Repository: cpplint/cpplint (language: python)

Issue:
False positive: Add #include <algorithm> for sort
Cpplint seems to assume that all standard algorithms come from the STL,
so, for example, if Boost algorithms are used,
the linter suggests to include `<algorithm>`.
Note that the function call is fully qualified as is required by the Google style:

``` cpp
#include <boost/range/algorithm.hpp>

void foo() {
  boost::sort(std::vector<int>{1, 2, 3, 4});
}
```

The solution strategy could be to take into account `std::` qualification for function calls.



Discussion / hints:
This repo is an "unofficial" fork of cpplint (still the one on pypi though), so you may want to report on https://github.com/google/styleguide.

@tkruse Good idea. Thanks!
I think I will just reference this to get more attention to this "unofficial" but awesome fork.


Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 40111297a..f740d1de9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,11 +1,21 @@
 name: Test
-on: [push, pull_request]
+on:
+  pull_request:
+    paths-ignore: "*.rst"
+  push:
+    paths-ignore: "*.rst"
+    branches: [master, develop]
+concurrency:
+  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+  cancel-in-progress: true
 jobs:
   build-test:
-    runs-on: ubuntu-latest
+    runs-on: ${{ matrix.os }}
     strategy:
       matrix:
-        python-version: ['3.9', 'pypy3.10']
+        # Python 3.7 is the lowest available for actions/setup-python
+        python-version: ['3.7', 'pypy3.10', '3.12']
+        os: [ubuntu-latest, windows-latest]
       fail-fast: false
 
     steps:
@@ -19,10 +29,11 @@ jobs:
           python-version: ${{ matrix.python-version }}
           architecture: x64
           cache: 'pip'
-          cache-dependency-path: '**/dev-requirements'
+          cache-dependency-path: '**/test-requirements'
       - name: Install dependencies
         run: |
           python -m pip install --upgrade pip
           python -m pip install -e .[dev]
+          python -m pip install 'tox-gh-actions<4.0.0'
       - name: Test with tox
         run: tox
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index fc095227d..e620bfc91 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -1,39 +1,25 @@
+******************
 Contributing guide
-==================
+******************
 
 Thanks for your interest in contributing to cpplint.
 
-Any kinds of contributions are welcome: Bug reports, Documentation, Patches.
+Any kinds of contributions are welcome: Bug reports, Documentation, Patches. However, here are some contributions you probably shouldn't make:
 
-However cpplint is a bit special as a project because it aims to closely follow what Google does in the upstream repository.
-That means Google remains the source of all major requirements and functionality of cpplint, where as this fork adds extensions to cpplint run on more environments and in more companies.
-The difference between this cpplint and Google should remain so small that anyone can at a glance see there is no added change that could be regarded as a security vulnerability.
-
-Here are some tips to make best use of your time:
-
-1. Feature suggestions should initially be opened at the `upstream repository <https://github.com/google/styleguide>`_, but feel free to open an issue here to and link to the upstream issue.
-
-2. Consider the goals and non-goals of this project:
-
-Goals:
-
-* Provides cpplint as a PyPI package for multiple python versions
-* Add a few features and fixes aimed at usages outside Google
-
-Non-Goals:
-
-* Become an independent fork adding major features
-* Fix python style issues in cpplint
+* Drastic reorganization
+  * Making the code conform to Google's Python style guidelines
+* Features that could be regarded as a security vulnerability
 
+If you need some ideas, you may check out some of the tasks in our `issue tracker <https://github.com/cpplint/cpplint/issues>`_.
 
 Development
------------
+===========
 
-For many tasks, it is okay to just develop using a single installed python version. But if you need to test/debug the project in multiple python versions, you need to install those versions::
+For many tasks, it is okay to just develop using a single installed python version. But if you need to test/debug the project in multiple python versions, you need to install those versions:
 
 1. (Optional) Install multiple python versions
 
-   1. (Optional) Install [pyenv](https://github.com/pyenv/pyenv-installer) to manage python versions
+   1. (Optional) Install `pyenv <https://github.com/pyenv/pyenv-installer>`_ to manage python versions
    2. (Optional) Using pyenv, install the python versions used in testing::
 
         pyenv install 2.7.16
@@ -41,39 +27,43 @@ For many tasks, it is okay to just develop using a single installed python versi
         # ...
         pyenv local 2.7.16 3.6.8 ...
 
-It may be okay to run and test python against locally installed libraries, but if you need to have a consistent build, it is recommended to manage your environment using virtualenv: [virtualenv](https://virtualenv.pypa.io/en/latest/ ), [virtualenvwrapper](https://pypi.org/project/virtualenvwrapper/ ):
-
-1. (Optional) Setup a local virtual environment with all necessary tools and libraries::
+It may be okay to run and test python against locally installed libraries, but if you need to have a consistent build, it is recommended to manage your environment using virtualenv: `virtualenv <https://virtualenv.pypa.io/en/latest/>`_, `virtualenvwrapper <https://pypi.org/project/virtualenvwrapper/>`_::
 
-      mkvirtualenv cpplint [-p /usr/bin/python3]
-      pip install .[dev]
+    mkvirtualenv cpplint [-p /usr/bin/python3]
+    pip install .[dev]
 
-Alternatively you can locally install patches like this::
+Alternatively, you can locally install patches like this::
 
     pip install -e .[dev]
     # for usage without virtualenv, add --user
 
-You can setup your local environment for developing patches for cpplint like this:
+.. _testing:
+
+Testing
+-------
+
+You can test your changes under your local python environment by running the tests and lints below:
 
 .. code-block:: bash
 
+    # install test requirements
+    pip install .[test]
     # run a single test
     pytest --no-cov cpplint_unittest.py -k testExclude
     # run a single CLI integration test
     pytest --no-cov cpplint_clitest.py -k testSillySample
-    # run all tests
-    ./setup.py test
-    ./setup.py lint
-    ./setup.py ci # all the above
-    ./flake8
-    tox    # all of the above in all python environments
+    # run all tests. you don't have to run the above tests separately
+    pytest
+    # lint the code
+    pylint cpplint.py
+    flake8
 
-Releasing
----------
+Alternatively, you can run `tox` to automatically run all tests and lints. Use `-e ` followed by the python runner and version (which you must have installed) to automatically generate the testing environment and run the above tests and lints in it. For example, `tox -e py39` does the steps in Python 3.9, `tox -e py312` does the steps in Python 3.12, and `tox -e pypy3` does the steps using the latest version of the pypy interpreter.
 
-The release process first prepares the documentation, then publishes to testpypi to verify, then releases to real pypi. Testpypi acts like real pypi, so broken releases cannot be deleted. For a typical bugfixing release, no special issue on testpypi is expected (but it's still good practice).
+Releasing
+=========
 
-To release a new version:
+The release process first prepares the documentation, then publishes to testpypi to verify, then releases to real pypi. Testpypi acts like real pypi, so broken releases cannot be deleted. For a typical bugfixing release, no special issue on testpypi is expected (but it's still good practice). The commands are documented below, and assume you've went through the testing steps above.
 
 .. code-block:: bash
 
@@ -82,11 +72,11 @@ To release a new version:
     vi changelog.rst # log changes
     git add cpplint.py changelog.rst
     git commit -m "Releasing x.y.z"
-    # test-release (on env by mkvirtualenv -p /usr/bin/python3)
-    pip install --upgrade setuptools wheel twine
+    # Build
+    pip install --upgrade build wheel twine
     rm -rf dist
+    python -m build --sdist --wheel
     # Test release, requires account on testpypi
-    python3 setup.py sdist bdist_wheel
     twine upload --repository testpypi dist/*
     # ... Check website and downloads from https://test.pypi.org/project/cpplint/
     # Actual release
@@ -94,12 +84,12 @@ To release a new version:
     git tag x.y.z
     git push --tags
 
-After releasing, it is be good practice to comment on github for closed tickets, to notify authors.
+After releasing, it is be good practice to comment on completed GitHub issues to notify authors.
 
 Catching up with Upstream
--------------------------
+=========================
 
-For maintainers, it is a regular duty to look at what cpplint changes were merged upstream, to include them in this fork (though these updates happen once per year and less).
+For maintainers, it is a regular duty to look at what cpplint changes were merged upstream and include them in this fork (though these updates happen rarely).
 
 Checkout here and upstream google:
 
diff --git a/README.rst b/README.rst
index 9ff67c0eb..2a7d7cd66 100644
--- a/README.rst
+++ b/README.rst
@@ -1,5 +1,6 @@
+#####################################
 cpplint - static code checker for C++
-=====================================
+#####################################
 
 .. image:: https://img.shields.io/pypi/v/cpplint.svg
     :target: https://pypi.python.org/pypi/cpplint
@@ -22,25 +23,28 @@ cpplint - static code checker for C++
 .. image:: https://img.shields.io/pypi/dm/cpplint.svg
     :target: https://pypi.python.org/pypi/cpplint
 
-Cpplint is a command-line tool to check C/C++ files for style issues following `Google's C++ style guide <http://google.github.io/styleguide/cppguide.html>`_.
-Cpplint is developed and maintained by Google Inc. at `google/styleguide <https://github.com/google/styleguide>`_, also see the `wikipedia entry <http://en.wikipedia.org/wiki/Cpplint>`_
+Cpplint is a command-line tool to check C/C++ files for style issues according to `Google's C++ style guide <http://google.github.io/styleguide/cppguide.html>`_.
 
-While Google maintains cpplint, Google is not (very) responsive to issues and pull requests, this fork aims to be (somewhat) more open to add fixes to cpplint to enable fixes, when those fixes make cpplint usable in wider contexts.
-Also see discussion here https://github.com/google/styleguide/pull/528.
+Cpplint used to be developed and maintained by Google Inc. at `google/styleguide <https://github.com/google/styleguide>`_. Nowadays, `Google is no longer maintaining the public version of cpplint <https://github.com/google/styleguide/pull/528#issuecomment-592315430>`_, and pretty much everything in their repo's PRs and issues about cpplint have gone unimplemented.
+
+This fork aims to update cpplint to modern specifications, and be (somewhat) more open to adding fixes and features to make cpplint usable in wider contexts.
 
 
 Installation
 ============
 
-
 To install cpplint from PyPI, run:
 
 .. code-block:: bash
 
     $ pip install cpplint
 
-Then run it with:
+Externally managed environments
+-------------------------------
+If you get the "This environment is externally managed" error, try to search and install cpplint with your system's package manager (e.g. apt, rpm, pacman...). If it doesn't exist, you can either package cpplint for your distribution or repeat the steps above with the :code:`--break-system-packages` flag.
 
+Usage
+-----
 .. code-block:: bash
 
     $ cpplint [OPTIONS] files
@@ -52,9 +56,7 @@ For full usage instructions, run:
     $ cpplint --help
 
 Changes
--------
-
-The modifications in this fork are minor fixes and cosmetic changes, such as:
+=======
 
 * python 3 compatibility
 * more default file extensions
@@ -65,15 +67,24 @@ The modifications in this fork are minor fixes and cosmetic changes, such as:
 * JUnit XML output format
 * Overriding repository root auto-detection via --repository
 * Support ``#pragma once`` as an alternative to header include guards
-* ... and a few more (most of which are open PRs on upstream)
-
+* ... and `quite a bit <https://github.com/cpplint/cpplint/blob/master/changelog.rst>`_ more
 
 Acknowledgements
-----------------
+================
 
 Thanks to Google Inc. for open-sourcing their in-house tool.
-Thanks to maintainers of the fork
 
-* `tkruse <https://github.com/tkruse>`_  
-* `mattyclarkson <https://github.com/mattyclarkson>`_
-* `theandrewdavis <https://github.com/theandrewdavis>`_
+Thanks to `our contributors <https://github.com/cpplint/cpplint/graphs/contributors>`_.
+
+Maintainers
+-----------
+
+* `@aaronliu0130 <https://github.com/aaronliu0130>`_
+* `@jayvdb <https://github.com/jayvdb>`_
+
+Former
+^^^^^^
+
+* `@tkruse <https://github.com/tkruse>`_
+* `@mattyclarkson <https://github.com/mattyclarkson>`_
+* `@theandrewdavis <https://github.com/theandrewdavis>`_
diff --git a/changelog.rst b/changelog.rst
index 372cf6754..9727ee6f5 100644
--- a/changelog.rst
+++ b/changelog.rst
@@ -1,71 +1,101 @@
+*********
 Changelog
-=========
+*********
+
+1.7 (Unreleased)
+==================
+
+A bunch of long-overdue modernizations of the codebase!
+
+* Python 2 is no longer supported. Python 3.7 and 3.12 support was added, courtesy of @jayvdb
+   * As a result of all this, setup.py's lint subcommand was removed. Please run the commands directly instead.
+* NOLINT and NOLINTNEXTLINE comments now support a comma-separated list of categories, courtesy of @n3world (https://github.com/cpplint/cpplint/pull/220)
+* The `--filter` option can now be only applied to a specific file or even a specific line through utilizing colons, e.g. `-filter=-whitespace:foo.h,+whitespace/braces:foo.h:418`. Courtesy of @PhilLab (https://github.com/cpplint/cpplint/pull/171)
+* NOLINT and NOLINTNEXTLINE will now ignore categories known to be from clang-tidy thanks to @xatier (https://github.com/cpplint/cpplint/pull/231)
+* Fix behavior with nested source repositories by @groegeorg (https://github.com/cpplint/cpplint/pull/78)
+* build/include-what-you-use no longer supports transitive headers from the header for the current module for parity with the style guide by @aaronliu0130 
+* build/include-what-you-use now supports a plethora of new functions, courtesy of @geoffviola (https://github.com/cpplint/cpplint/pull/94)
+* C++20 headers will no longer be flagged as C headers thanks to @miker2 (https://github.com/cpplint/cpplint/pull/216)
+   * Same goes for C++23 and C23 headers, thanks to @aaronliu0130 (https://github.com/cpplint/cpplint/pull/239)
+   * "complex.h" will be treated as the C99 header instead of the legacy C++ header by @tkruse (https://github.com/cpplint/cpplint/pull/219)
+   * Many features not blocked in Google's style guide will no longer be erred own thanks to @aaronliu0130
+      * As part of this, the build/c++14 and build/c++tr1 categories were removed.
+      * The filesystem header will now also be blocked, and the build/c++17 category has been added.
+* We will no longer bother you if you mark a no-arg constructor as explicit thanks to @markww (https://github.com/cpplint/cpplint/pull/227)
+   * In the same PR, @aaronliu0130 also decreased the verbosity of nagging to mark single-arg constructors as explicit to 4, as the styleguide includes a major exception to this rule that would be very hard to detect.
+* You can now specify the name of the CPPLINT.cfg file through `--config` as long as it is in the same directory, thanks to @gedankenexperimenter (https://github.com/cpplint/cpplint/pull/198)
+* The new `__VA_OPT__(,)` will now be recognized by the Whitespace linter as a function, courtesy of @elrinor (https://github.com/cpplint/cpplint/pull/237)
+* The check for including a source file's header file will now scan all files with the same base name. Thanks to @crogre for figuring out what code needed to be changed and @aaronliu0130 for fixing it (https://github.com/cpplint/cpplint/pull/104)
+* Usages of the deprecated sre_compile were refectored by @jspricke (https://github.com/cpplint/cpplint/pull/214)
+* Usages of deprecated unittest aliases were refactored by @tirkarthi (https://github.com/cpplint/cpplint/pull/182), @aaronliu0130 and @jayvdb
+* Typos in this changelog, comments and functions were fixed by @jayvdb (https://github.com/cpplint/cpplint/pull/245), @aaronliu0130 and @tkruse
+* %-strings were modernized into f-strings by @aaronliu0130
 
 1.6.1 (2022-08-20)
------
+==================
 
 * Fix #195 Fix post increment/decrement operator causing a false positive.
-* Fix #202 .hh files should not be considered sytem headers
+* Fix #202 .hh files should not be considered system headers
 * Fix #207 Python2 incompatibility for loading CPPLINT.cfg file
 * Fix #184 NOLINT(clang-analyzer) comments should not cause warnings
 
 1.6.0 (2022-02-19)
------
+==================
 
 * Fix #188: "Include the directory when naming header files" also for header files with other names like "*.hpp"
 
 1.5.5 (2021-05-20)
------
+==================
 
 * Fix #172: Added 'size_t' to typecasts detected by CheckCStyleCast
 * Fixed wrong CLI help text: Each filter needs + or -
 * Fix #164: add elif as an exception for CheckSpacingForFunctionCall()
-* Fix google#346: --root option not working on windows due to slashes in path
+* Fix google#346: --root option not working on Windows due to slashes in path
 
 1.5.4 (2020-08-18)
------
+==================
 
 * Fix google#166, Allow space before C++11 attributes
 
 1.5.3 (2020-07-20)
------
+==================
 
 * Fix #156: sed/gsed output parameter rejected
 * Fix #156: sed/gsed output without other stdout information
 * improvements to regression tests
 
 1.5.2 (2020-06-24)
------
+==================
 
 * Fix #83, output formats "sed" and "gsed" to auto-fix some issues
 * Fix #92, new category "build/namespaces_headers" for unnamed namespaces in header file
 * Sort list of files before processing
-* Fix #144 Falso positive for indent when using QT macros "signals" and "slots"
+* Fix #144 False positive for indent when using QT macros "signals" and "slots"
 * Fix #76 Parsing of class decorators that also use digits
 * Fix #139 Add message "Relative paths like . and .. are not allowed"
 
 1.5.1 (2020-06-05)
------
+==================
 
 * Revert #43 behavior change for include order from 1.5.0, and hide it behind command-line-flag `--includeorder=standardcfirst`.
   It turns out there is no easy objective way to tell c system headers from certain c++ library headers, and Google cpplint intentionally classifies some C++ header includes as C system header for simplicity.
-* Libraries considered as C system headers using --includeorder=standardcfirst now also includes linux-specifc headers (glibc-devel, glibc-kernheaders, linux-libc-dev).
+* Libraries considered as C system headers using --includeorder=standardcfirst now also includes linux-specific headers (glibc-devel, glibc-kernheaders, linux-libc-dev).
 
 
 1.5.0 (2020-05-31)
------
+==================
 
 * Fix #43 false positives in header include order by checking includes against a list of c headers.
   Since this interprets certain include lines different than before, output about header include order changes.
 
 1.4.6 (2020-05-31)
------
+==================
 
 * Fix #135: allow 'if constexpr' in readability/braces.
 * Fix runtime warning: Close files after reading contents
 
 1.4.5 (2020-01-13)
------
+==================
 
 * Avoid false positive for [build/include_what_you_use] in case of `foo.set<type>` and `foo->set<type>` usage.
 * Avoid false positive for [build/include_what_you_use] in case of `map` is user defined function
@@ -77,7 +107,7 @@ Changelog
 * fix #112, identifying of copy constructors should allow combinations of volatile and const
 
 1.4.4 (2019-02-25)
------
+==================
 
 Another cleanup release
 
@@ -86,118 +116,117 @@ Another cleanup release
 * add `--version` command (https://github.com/cpplint/cpplint/issues/27)
 
 1.4.3 (2019-02-18)
------
+==================
 
 * Revert "Fix the `build/endif_comment` check", same as reverted in upstream
 
 1.4.2 (2019-02-17)
------
+==================
 
 * Cleanup release, fixes further issues with tests and source distribution
 
 1.4.1 (2019-02-17)
------
+==================
 
 * Cleanup release, only adds test support files to source dist
 
 1.4.0 (2019-02-17)
------
+==================
 
 * Incorporate cpplint updates from google (e5d807c6a0d,  2018-05-03)
-  * Fix the `build/endif_comment` check (https://github.com/google/styleguide/pull/169)
-  * Teach the explicit constructor check about constexpr (#56)
-  * Changed vs7 output format (#57)
-  * Remove presubmit check for DISALLOW_* macros (#54)
-  * add `--quiet` flag as in upstream (https://github.com/google/styleguide/pull/293)
-  * support `--root` argument to run in different folder (https://github.com/google/styleguide/pull/291)
-  * Fix 16bit Unicode issue (https://github.com/google/styleguide/issues/337)
+   * Fix the `build/endif_comment` check (https://github.com/google/styleguide/pull/169)
+   * Teach the explicit constructor check about constexpr (#56)
+   * Changed vs7 output format (#57)
+   * Remove presubmit check for DISALLOW_* macros (#54)
+   * add `--quiet` flag as in upstream (https://github.com/google/styleguide/pull/293)
+   * support `--root` argument to run in different folder (https://github.com/google/styleguide/pull/291)
+   * Fix 16bit Unicode issue (https://github.com/google/styleguide/issues/337)
 
 1.3.0 (2016-07-12)
------
+==================
 
 * Incorporate cpplint updates from google (6d3a7d8a2, 2016-07-14)
 * Add --headers flag to choose which extensions are header files.
-* Add regression testsing.
+* Add regression testing.
 
 1.2.2 (2016-04-07)
------
+==================
 
 * Fixes bug causing RValue detection with namespaces to fail.
 
 1.2.1 (2016-03-19)
------
+==================
 
 * Fixes error in setup.py.
 
 1.2.0 (2016-03-19)
------
+==================
 
 * Adds `.cu` and `.cuh` as supported file extensions by default.
 * Moves the warning "Include the directory when naming .h files" from the `build/include` category to the `build/include_subdir` category.
 
 1.1.0 (2016-02-24)
------
+==================
 
 * Adds quiet option to suppress non error-related output.
 
 1.0.1 (2016-02-12)
------
+==================
 
 * Updates PyPi README.
 
 1.0.0 (2016-02-03)
------
+==================
 
 * Fixes a --repository flag bug.
 
 0.0.9 (2016-01-23)
------
+==================
 
 * Adds the --exclude flag to exclude files from being linted.
 
 0.0.8 (2016-01-18)
------
+==================
 
 * Adds the --repository flag to set the location of the project root for header guard calculations.
 * Adds support for ``#pragma once`` as an alternative to header include guards.
 
 0.0.7 (2016-01-07)
------
+==================
 
 * Fixes a Windows include guard bug.
 * Adds escaping and more detail to JUnit XML output.
 
 0.0.6 (2015-12-15)
------
+==================
 
 * Adds the --recursive flag.
 * Adds JUnit XML output.
 
 0.0.5 (2015-01-04)
------
+==================
 
 * Maintenance release, undoes earlier project folder structure changes to remain as true to upstream as possible.
 
 0.0.4 (2015-01-04)
------
+==================
 
 * Merged with upstream revision r141 (2014-12-04)
 * This includes many new checks, see commit messages for details
 * This also reverts some renaming of files, to stay close to the original project
 
-
 0.0.3 (2012-11-24)
------
+==================
 
 * python 3 compatibility
 
 0.0.2 (2012-11-06)
------
+==================
 
 * fixed and extended allowed extensions
 
 0.0.1 (2012-10-13)
------
+==================
 
 * import from googlecode, added setup.py
 * imported revision r83 (2012-05-11)
diff --git a/cpplint.py b/cpplint.py
old mode 100644
new mode 100755
index 78c9860bd..3a6436622
--- a/cpplint.py
+++ b/cpplint.py
@@ -58,7 +58,7 @@
 # if empty, use defaults
 _valid_extensions = set([])
 
-__VERSION__ = '1.7.0'
+__VERSION__ = '1.7'
 
 _USAGE = """
 Syntax: cpplint.py [--verbose=#] [--output=emacs|eclipse|vs7|junit|sed|gsed]
@@ -70,6 +70,7 @@
                    [--exclude=path]
                    [--extensions=hpp,cpp,...]
                    [--includeorder=default|standardcfirst]
+                   [--config=filename]
                    [--quiet]
                    [--version]
         <file> [file] ...
@@ -130,6 +131,14 @@
       To see a list of all the categories used in cpplint, pass no arg:
          --filter=
 
+      Filters can directly be limited to files and also line numbers. The
+      syntax is category:file:line , where line is optional. The filter limitation
+      works for both + and - and can be combined with ordinary filters:
+
+      Examples: --filter=-whitespace:foo.h,+whitespace/braces:foo.h
+                --filter=-whitespace,-runtime/printf:foo.h:14,+runtime/printf_format:foo.h
+                --filter=-,+build/include_what_you_use:foo.h:321
+
     counting=total|toplevel|detailed
       The total number of errors found is always printed. If
       'toplevel' is provided, then the count of errors in each of
@@ -217,6 +226,9 @@
       treat all others as separate group of "other system headers". The C headers
       included are those of the C-standard lib and closely related ones.
 
+    config=filename
+      Search for config files with the specified name instead of CPPLINT.cfg
+
     headers=x,y,...
       The header extensions that cpplint will treat as .h in checks. Values are
       automatically added to --extensions list.
@@ -278,8 +290,7 @@
 _ERROR_CATEGORIES = [
     'build/class',
     'build/c++11',
-    'build/c++14',
-    'build/c++tr1',
+    'build/c++17',
     'build/deprecated',
     'build/endif_comment',
     'build/explicit_make_pair',
@@ -364,7 +375,31 @@
 # These prefixes for categories should be ignored since they relate to other
 # tools which also use the NOLINT syntax, e.g. clang-tidy.
 _OTHER_NOLINT_CATEGORY_PREFIXES = [
-    'clang-analyzer',
+    'clang-analyzer-',
+    'abseil-',
+    'altera-',
+    'android-',
+    'boost-',
+    'bugprone-',
+    'cert-',
+    'concurrency-',
+    'cppcoreguidelines-',
+    'darwin-',
+    'fuchsia-',
+    'google-',
+    'hicpp-',
+    'linuxkernel-',
+    'llvm-',
+    'llvmlibc-',
+    'misc-',
+    'modernize-',
+    'mpi-',
+    'objc-',
+    'openmp-',
+    'performance-',
+    'portability-',
+    'readability-',
+    'zircon-',
     ]
 
 # The default state of the category filter. This is overridden by the --filter=
@@ -887,7 +922,7 @@
 # Files to exclude from linting. This is set by the --exclude flag.
 _excludes = None
 
-# Whether to supress all PrintInfo messages, UNRELATED to --quiet flag
+# Whether to suppress all PrintInfo messages, UNRELATED to --quiet flag
 _quiet = False
 
 # The allowed line length of files.
@@ -897,6 +932,9 @@
 # This allows to use different include order rule than default
 _include_order = "default"
 
+# This allows different config files to be used
+_config_filename = "CPPLINT.cfg"
+
 # Treat all headers starting with 'h' equally: .h, .hpp, .hxx etc.
 # This is set by --headers flag.
 _hpp_headers = set([])
@@ -983,8 +1021,11 @@ def ParseNolintSuppressions(filename, raw_line, linenum, error):
           error(filename, linenum, 'readability/nolint', 5,
                 f'Unknown NOLINT error category: {category}')
 
-
 def ProcessGlobalSuppresions(lines):
+  """Deprecated; use ProcessGlobalSuppressions."""
+  ProcessGlobalSuppressions(lines)
+
+def ProcessGlobalSuppressions(lines):
   """Updates the list of global error suppressions.
 
   Parses any lint directives in the file that have global effect.
@@ -1012,7 +1053,7 @@ def IsErrorSuppressedByNolint(category, linenum):
   """Returns true if the specified error category is suppressed on this line.
 
   Consults the global error_suppressions map populated by
-  ParseNolintSuppressions/ProcessGlobalSuppresions/ResetNolintSuppressions.
+  ParseNolintSuppressions/ProcessGlobalSuppressions/ResetNolintSuppressions.
 
   Args:
     category: str, the category of the error.
@@ -1615,7 +1656,7 @@ def IsSource(self):
     return _IsSourceExtension(self.Extension()[1:])
 
 
-def _ShouldPrintError(category, confidence, linenum):
+def _ShouldPrintError(category, confidence, filename, linenum):
   """If confidence >= verbose, category passes filter and is not suppressed."""
 
   # There are three ways we might decide not to print an error message:
@@ -1629,11 +1670,16 @@ def _ShouldPrintError(category, confidence, linenum):
 
   is_filtered = False
   for one_filter in _Filters():
+    filter_cat, filter_file, filter_line = _ParseFilterSelector(one_filter[1:])
+    category_match = category.startswith(filter_cat)
+    file_match = filter_file == "" or filter_file == filename
+    line_match = filter_line == linenum or filter_line == -1
+
     if one_filter.startswith('-'):
-      if category.startswith(one_filter[1:]):
+      if category_match and file_match and line_match:
         is_filtered = True
     elif one_filter.startswith('+'):
-      if category.startswith(one_filter[1:]):
+      if category_match and file_match and line_match:
         is_filtered = False
     else:
       assert False  # should have been checked for in SetFilter.
@@ -1665,7 +1711,7 @@ def Error(filename, linenum, category, confidence, message):
       and 1 meaning that it could be a legitimate construct.
     message: The error message.
   """
-  if _ShouldPrintError(category, confidence, linenum):
+  if _ShouldPrintError(category, confidence, filename, linenum):
     _cpplint_state.IncrementErrorCount(category)
     if _cpplint_state.output_format == 'vs7':
       _cpplint_state.PrintError(f'{filename}({linenum}): error cpplint:'
@@ -2458,13 +2504,13 @@ def CheckHeaderFileIncluded(filename, include_state, error):
   if re.search(_TEST_FILE_SUFFIX, fileinfo.BaseName()):
     return
 
+  first_include = message = None
+  basefilename = filename[0:len(filename) - len(fileinfo.Extension())]
   for ext in GetHeaderExtensions():
-    basefilename = filename[0:len(filename) - len(fileinfo.Extension())]
     headerfile = basefilename + '.' + ext
     if not os.path.exists(headerfile):
       continue
     headername = FileInfo(headerfile).RepositoryName()
-    first_include = None
     include_uses_unix_dir_aliases = False
     for section_list in include_state.include_list:
       for f in section_list:
@@ -2480,6 +2526,7 @@ def CheckHeaderFileIncluded(filename, include_state, error):
     if include_uses_unix_dir_aliases:
       message += ". Relative paths like . and .. are not allowed."
 
+  if message:
     error(filename, first_include, 'build/include', 5, message)
 
 
@@ -3404,16 +3451,12 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum,
         not initializer_list_constructor and
         not copy_constructor):
       if defaulted_args or variadic_args:
-        error(filename, linenum, 'runtime/explicit', 5,
+        error(filename, linenum, 'runtime/explicit', 4,
               'Constructors callable with one argument '
               'should be marked explicit.')
       else:
-        error(filename, linenum, 'runtime/explicit', 5,
+        error(filename, linenum, 'runtime/explicit', 4,
               'Single-parameter constructors should be marked explicit.')
-    elif is_marked_explicit and not onearg_constructor:
-      if noarg_constructor:
-        error(filename, linenum, 'runtime/explicit', 5,
-              'Zero-parameter constructors should not be marked explicit.')
 
 
 def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
@@ -3952,8 +3995,9 @@ def CheckCommaSpacing(filename, clean_lines, linenum, error):
   # verify that lines contain missing whitespaces, second pass on raw
   # lines to confirm that those missing whitespaces are not due to
   # elided comments.
-  if (re.search(r',[^,\s]', re.sub(r'\boperator\s*,\s*\(', 'F(', line)) and
-      re.search(r',[^,\s]', raw[linenum])):
+  match = re.search(r',[^,\s]', re.sub(r'\b__VA_OPT__\s*\(,\)', '',
+                                       re.sub(r'\boperator\s*,\s*\(', 'F(', line)))
+  if (match and re.search(r',[^,\s]', raw[linenum])):
     error(filename, linenum, 'whitespace/comma', 3,
           'Missing space after ,')
 
@@ -5914,7 +5958,26 @@ def ExpectingFunctionArgs(clean_lines, linenum):
     ('<utility>', ('forward', 'make_pair', 'move', 'swap')),
     )
 
-_RE_PATTERN_STRING = re.compile(r'\bstring\b')
+# Non templated types or global objects
+_HEADERS_TYPES_OR_OBJS = (
+    # String and others are special -- it is a non-templatized type in STL.
+    ('<string>', ('string',)),
+    ('<iostream>', ('cin', 'cout', 'cerr', 'clog', 'wcin', 'wcout',
+                    'wcerr', 'wclog')),
+    ('<cstdio>', ('FILE', 'fpos_t')))
+
+# Non templated functions
+_HEADERS_FUNCTIONS = (
+    ('<cstdio>', ('fopen', 'freopen',
+                  'fclose', 'fflush', 'setbuf', 'setvbuf', 'fread',
+                  'fwrite', 'fgetc', 'getc', 'fgets', 'fputc', 'putc',
+                  'fputs', 'getchar', 'gets', 'putchar', 'puts', 'ungetc',
+                  'scanf', 'fscanf', 'sscanf', 'vscanf', 'vfscanf',
+                  'vsscanf', 'printf', 'fprintf', 'sprintf', 'snprintf',
+                  'vprintf', 'vfprintf', 'vsprintf', 'vsnprintf',
+                  'ftell', 'fgetpos', 'fseek', 'fsetpos',
+                  'clearerr', 'feof', 'ferror', 'perror',
+                  'tmpfile', 'tmpnam'),),)
 
 _re_pattern_headers_maybe_templates = []
 for _header, _templates in _HEADERS_MAYBE_TEMPLATES:
@@ -5922,7 +5985,7 @@ def ExpectingFunctionArgs(clean_lines, linenum):
     # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or
     # 'type::max()'.
     _re_pattern_headers_maybe_templates.append(
-        (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
+        (re.compile(r'((\bstd::)|[^>.:])\b' + _template + r'(<.*?>)?\([^\)]'),
             _template,
             _header))
 # Match set<type>, but not foo->set<type>, foo.set<type>
@@ -5945,6 +6008,23 @@ def ExpectingFunctionArgs(clean_lines, linenum):
          _template + '<>',
          _header))
 
+_re_pattern_types_or_objs = []
+for _header, _types_or_objs in _HEADERS_TYPES_OR_OBJS:
+  for _type_or_obj in _types_or_objs:
+    _re_pattern_types_or_objs.append(
+        (re.compile(r'\b' + _type_or_obj + r'\b'),
+            _type_or_obj,
+            _header))
+
+_re_pattern_functions = []
+for _header, _functions in _HEADERS_FUNCTIONS:
+  for _function in _functions:
+    # Match printf(..., ...), but not foo->printf, foo.printf or
+    # 'type::printf()'.
+    _re_pattern_functions.append(
+        (re.compile(r'([^>.]|^)\b' + _function + r'\([^\)]'),
+            _function,
+            _header))
 
 def FilesBelongToSameModule(filename_cc, filename_h):
   """Check if these two filenames belong to the same module.
@@ -6004,34 +6084,6 @@ def FilesBelongToSameModule(filename_cc, filename_h):
   return files_belong_to_same_module, common_path
 
 
-def UpdateIncludeState(filename, include_dict, io=codecs):
-  """Fill up the include_dict with new includes found from the file.
-
-  Args:
-    filename: the name of the header to read.
-    include_dict: a dictionary in which the headers are inserted.
-    io: The io factory to use to read the file. Provided for testability.
-
-  Returns:
-    True if a header was successfully added. False otherwise.
-  """
-  headerfile = None
-  try:
-    with io.open(filename, 'r', 'utf8', 'replace') as headerfile:
-      linenum = 0
-      for line in headerfile:
-        linenum += 1
-        clean_line = CleanseComments(line)
-        match = _RE_PATTERN_INCLUDE.search(clean_line)
-        if match:
-          include = match.group(2)
-          include_dict.setdefault(include, linenum)
-    return True
-  except IOError:
-    return False
-
-
-
 def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
                               io=codecs):
   """Reports for missing stl includes.
@@ -6058,14 +6110,17 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
     if not line or line[0] == '#':
       continue
 
-    # String is special -- it is a non-templatized type in STL.
-    matched = _RE_PATTERN_STRING.search(line)
-    if matched:
-      # Don't warn about strings in non-STL namespaces:
-      # (We check only the first match per line; good enough.)
-      prefix = line[:matched.start()]
-      if prefix.endswith('std::') or not prefix.endswith('::'):
-        required['<string>'] = (linenum, 'string')
+    _re_patterns = []
+    _re_patterns.extend(_re_pattern_types_or_objs)
+    _re_patterns.extend(_re_pattern_functions)
+    for pattern, item, header in _re_patterns:
+      matched = pattern.search(line)
+      if matched:
+        # Don't warn about strings in non-STL namespaces:
+        # (We check only the first match per line; good enough.)
+        prefix = line[:matched.start()]
+        if prefix.endswith('std::') or not prefix.endswith('::'):
+          required[header] = (linenum, item)
 
     for pattern, template, header in _re_pattern_headers_maybe_templates:
       if pattern.search(line):
@@ -6084,46 +6139,10 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
         if prefix.endswith('std::') or not prefix.endswith('::'):
           required[header] = (linenum, template)
 
-  # The policy is that if you #include something in foo.h you don't need to
-  # include it again in foo.cc. Here, we will look at possible includes.
   # Let's flatten the include_state include_list and copy it into a dictionary.
   include_dict = dict([item for sublist in include_state.include_list
                        for item in sublist])
 
-  # Did we find the header for this file (if any) and successfully load it?
-  header_found = False
-
-  # Use the absolute path so that matching works properly.
-  abs_filename = FileInfo(filename).FullName()
-
-  # For Emacs's flymake.
-  # If cpplint is invoked from Emacs's flymake, a temporary file is generated
-  # by flymake and that file name might end with '_flymake.cc'. In that case,
-  # restore original file name here so that the corresponding header file can be
-  # found.
-  # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h'
-  # instead of 'foo_flymake.h'
-  abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename)
-
-  # include_dict is modified during iteration, so we iterate over a copy of
-  # the keys.
-  header_keys = list(include_dict.keys())
-  for header in header_keys:
-    (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
-    fullpath = common_path + header
-    if same_module and UpdateIncludeState(fullpath, include_dict, io):
-      header_found = True
-
-  # If we can't find the header file for a .cc, assume it's because we don't
-  # know where to look. In that case we'll give up as we're not sure they
-  # didn't include it in the .h file.
-  # TODO(unknown): Do a better job of finding .h files so we are confident that
-  # not having the .h file means there isn't one.
-  if not header_found:
-    for extension in GetNonHeaderExtensions():
-      if filename.endswith('.' + extension):
-        return
-
   # All the lines have been processed, report the errors found.
   for required_header_unstripped in sorted(required, key=required.__getitem__):
     template = required[required_header_unstripped][1]
@@ -6359,8 +6378,9 @@ def ProcessLine(filename, file_extension, clean_lines, line,
     for check_fn in extra_check_functions:
       check_fn(filename, clean_lines, line, error)
 
-def FlagCxx11Features(filename, clean_lines, linenum, error):
-  """Flag those c++11 features that we only allow in certain places.
+
+def FlagCxxHeaders(filename, clean_lines, linenum, error):
+  """Flag C++ headers that the styleguide restricts.
 
   Args:
     filename: The name of the current file.
@@ -6372,64 +6392,18 @@ def FlagCxx11Features(filename, clean_lines, linenum, error):
 
   include = re.match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
 
-  # Flag unapproved C++ TR1 headers.
-  if include and include.group(1).startswith('tr1/'):
-    error(filename, linenum, 'build/c++tr1', 5,
-          f"C++ TR1 headers such as <{include.group(1)}> are unapproved.")
-
-  # TODO: Figure out which of these headers are actually forbidden
-  # and add <filesystem> somewhere from C++17
   # Flag unapproved C++11 headers.
   if include and include.group(1) in ('cfenv',
-                                      'condition_variable',
                                       'fenv.h',
-                                      'future',
-                                      'mutex',
-                                      'thread',
-                                      'chrono',
                                       'ratio',
-                                      'regex',
-                                      'system_error',
                                      ):
     error(filename, linenum, 'build/c++11', 5,
           f"<{include.group(1)}> is an unapproved C++11 header.")
 
-  # The only place where we need to worry about C++11 keywords and library
-  # features in preprocessor directives is in macro definitions.
-  if re.match(r'\s*#', line) and not re.match(r'\s*#\s*define\b', line): return
-
-  # These are classes and free functions.  The classes are always
-  # mentioned as std::*, but we only catch the free functions if
-  # they're not found by ADL.  They're alphabetical by header.
-  for top_name in (
-      # type_traits
-      'alignment_of',
-      'aligned_union',
-      ):
-    if re.search(rf'\bstd::{top_name}\b', line):
-      error(filename, linenum, 'build/c++11', 5,
-            (f'std::{top_name} is an unapproved C++11 class or function.  '
-             'Send c-style an example of where it would'
-             ' make your code more readable, and they may let you use it.'))
-
-
-def FlagCxx14Features(filename, clean_lines, linenum, error):
-  """Flag those C++14 features that we restrict.
-
-  Args:
-    filename: The name of the current file.
-    clean_lines: A CleansedLines instance containing the file.
-    linenum: The number of the line to check.
-    error: The function to call with any errors found.
-  """
-  line = clean_lines.elided[linenum]
-
-  include = re.match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
-
-  # Flag unapproved C++14 headers.
-  if include and include.group(1) in ('scoped_allocator', 'shared_mutex'):
-    error(filename, linenum, 'build/c++14', 5,
-          f"<{include.group(1)}> is an unapproved C++14 header.")
+  # filesystem is the only unapproved C++17 header
+  if include and include.group(1) == 'filesystem':
+    error(filename, linenum, 'build/c++17', 5,
+          "<filesystem> is an unapproved C++17 header.")
 
 
 def ProcessFileData(filename, file_extension, lines, error,
@@ -6457,7 +6431,7 @@ def ProcessFileData(filename, file_extension, lines, error,
   ResetNolintSuppressions()
 
   CheckForCopyright(filename, lines, error)
-  ProcessGlobalSuppresions(lines)
+  ProcessGlobalSuppressions(lines)
   RemoveMultiLineComments(filename, lines, error)
   clean_lines = CleansedLines(lines)
 
@@ -6468,7 +6442,7 @@ def ProcessFileData(filename, file_extension, lines, error,
     ProcessLine(filename, file_extension, clean_lines, line,
                 include_state, function_state, nesting_state, error,
                 extra_check_functions)
-    FlagCxx11Features(filename, clean_lines, line, error)
+    FlagCxxHeaders(filename, clean_lines, line, error)
   nesting_state.CheckCompletedBlocks(filename, error)
 
   CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
@@ -6501,7 +6475,7 @@ def ProcessConfigOverrides(filename):
     if not base_name:
       break  # Reached the root directory.
 
-    cfg_file = os.path.join(abs_path, "CPPLINT.cfg")
+    cfg_file = os.path.join(abs_path, _config_filename)
     abs_filename = abs_path
     if not os.path.isfile(cfg_file):
       continue
@@ -6721,6 +6695,7 @@ def ParseArguments(args):
                                                  'recursive',
                                                  'headers=',
                                                  'includeorder=',
+                                                 'config=',
                                                  'quiet'])
   except getopt.GetoptError:
     PrintUsage('Invalid arguments.')
@@ -6779,6 +6754,11 @@ def ParseArguments(args):
       recursive = True
     elif opt == '--includeorder':
       ProcessIncludeOrderOption(val)
+    elif opt == '--config':
+      global _config_filename
+      _config_filename = val
+      if os.path.basename(_config_filename) != _config_filename:
+        PrintUsage('Config file name must not include directory components.')
 
   if not filenames:
     PrintUsage('No files were specified.')
@@ -6798,6 +6778,32 @@ def ParseArguments(args):
   filenames.sort()
   return filenames
 
+def _ParseFilterSelector(parameter):
+  """Parses the given command line parameter for file- and line-specific
+  exclusions.
+  readability/casting:file.cpp
+  readability/casting:file.cpp:43
+
+  Args:
+    parameter: The parameter value of --filter
+
+  Returns:
+    [category, filename, line].
+    Category is always given.
+    Filename is either a filename or empty if all files are meant.
+    Line is either a line in filename or -1 if all lines are meant.
+  """
+  colon_pos = parameter.find(":")
+  if colon_pos == -1:
+    return parameter, "", -1
+  category = parameter[:colon_pos]
+  second_colon_pos = parameter.find(":", colon_pos + 1)
+  if second_colon_pos == -1:
+    return category, parameter[colon_pos + 1:], -1
+  else:
+    return category, parameter[colon_pos + 1: second_colon_pos], \
+      int(parameter[second_colon_pos + 1:])
+
 def _ExpandDirectories(filenames):
   """Searches a list of filenames and replaces directories in the list with
   all files descending from those directories. Files with extensions not in
diff --git a/dev-requirements b/dev-requirements
index d5ab56a32..62a36ea5d 100644
--- a/dev-requirements
+++ b/dev-requirements
@@ -1,10 +1,5 @@
 # requirements to run development steps
 
-# also change in tox.ini, gitlab/ci.yml
 flake8>=4.0.1
-flake8-polyfill
 pylint>=2.11.0
-tox<5.0.0
-tox-gh-actions<4.0.0
-importlib-metadata>=0.12
-setuptools==58.2.0
+setuptools
diff --git a/samples/boost-sample/README.md b/samples/boost-sample/README.md
index 6266a4abf..dca6b56b3 100644
--- a/samples/boost-sample/README.md
+++ b/samples/boost-sample/README.md
@@ -1,3 +1,1 @@
-# VLC sample
-
-code taken for regression testing from https://github.com/boostorg
+Code under include/ and src/ taken from https://github.com/boostorg, licensed under the Boost license.
diff --git a/samples/cfg-file/simple.def b/samples/cfg-file/simple.def
index f3d9b1819..77f5bd614 100644
--- a/samples/cfg-file/simple.def
+++ b/samples/cfg-file/simple.def
@@ -8,9 +8,9 @@ src/sillycode.cpp:0:  No copyright message found.  You should have a line: "Copy
 src/sillycode.cpp:3:  Found C system header after C++ system header. Should be: sillycode.h, c system, c++ system, other.  [build/include_order] [4]
 src/sillycode.cpp:14:  Is this a non-const reference? If so, make const or use a pointer: vector<string>& v  [runtime/references] [2]
 src/sillycode.cpp:40:  If/else bodies with multiple statements require braces  [readability/braces] [4]
-src/sillycode.cpp:66:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
-src/sillycode.cpp:76:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
-src/sillycode.cpp:85:  Constructors callable with one argument should be marked explicit.  [runtime/explicit] [5]
+src/sillycode.cpp:66:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [4]
+src/sillycode.cpp:76:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [4]
+src/sillycode.cpp:85:  Constructors callable with one argument should be marked explicit.  [runtime/explicit] [4]
 src/sillycode.cpp:118:  Is this a non-const reference? If so, make const or use a pointer: N::X& a  [runtime/references] [2]
 src/sillycode.cpp:118:  Is this a non-const reference? If so, make const or use a pointer: N::X& b  [runtime/references] [2]
 src/sillycode.cpp:123:  Is this a non-const reference? If so, make const or use a pointer: N::X& a  [runtime/references] [2]
diff --git a/samples/chromium-sample/LICENSE b/samples/chromium-sample/LICENSE
new file mode 100644
index 000000000..2249a2865
--- /dev/null
+++ b/samples/chromium-sample/LICENSE
@@ -0,0 +1,27 @@
+// Copyright 2015 The Chromium Authors
+//
+// 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 LLC 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/samples/chromium-sample/README.md b/samples/chromium-sample/README.md
index f0c852d35..29e9a4423 100644
--- a/samples/chromium-sample/README.md
+++ b/samples/chromium-sample/README.md
@@ -1,3 +1,1 @@
-# VLC sample
-
-code taken for regression testing from https://github.com/chromium/chromium
+Code under src/ taken from https://github.com/chromium/chromium, licensed under the BSD 3-clause.
diff --git a/samples/chromium-sample/simple.def b/samples/chromium-sample/simple.def
index d1c4a6835..ba2ab4d9a 100644
--- a/samples/chromium-sample/simple.def
+++ b/samples/chromium-sample/simple.def
@@ -5,11 +5,11 @@ Done processing src/chrome_content_renderer_client.cc
 Done processing src/chrome_content_renderer_client.h
 Done processing src/io_thread.cc
 Done processing src/io_thread.h
-Total errors found: 13
+Total errors found: 17
 
-src/chrome_content_renderer_client.cc:113:  Include the directory when naming header files  [build/include_subdir] [4]
-src/chrome_content_renderer_client.cc:1156:  Use int16/int64/etc, rather than the C type long  [runtime/int] [4]
-src/chrome_content_renderer_client.cc:1161:  Use int16/int64/etc, rather than the C type long  [runtime/int] [4]
+src/chrome_content_renderer_client.cc:308:  Add #include <vector> for vector<>  [build/include_what_you_use] [4]
+src/chrome_content_renderer_client.cc:1540:  Add #include <set> for set<>  [build/include_what_you_use] [4]
+src/chrome_content_renderer_client.cc:1841:  Add #include <string> for string  [build/include_what_you_use] [4]
 src/chrome_content_renderer_client.cc:5:  samples/chromium-sample/src/chrome_content_renderer_client.cc should include its header file samples/chromium-sample/src/chrome_content_renderer_client.h  [build/include] [5]
 src/chrome_content_renderer_client.h:5:  #ifndef header guard has wrong style, please use: SAMPLES_CHROMIUM_SAMPLE_SRC_CHROME_CONTENT_RENDERER_CLIENT_H_  [build/header_guard] [5]
 src/chrome_content_renderer_client.h:225:  #endif line should be "#endif  // SAMPLES_CHROMIUM_SAMPLE_SRC_CHROME_CONTENT_RENDERER_CLIENT_H_"  [build/header_guard] [5]
@@ -17,6 +17,10 @@ src/chrome_content_renderer_client.h:115:  Use int16/int64/etc, rather than the
 src/chrome_content_renderer_client.h:117:  Use int16/int64/etc, rather than the C type long  [runtime/int] [4]
 src/io_thread.cc:1148:  Closing ) should be moved to the previous line  [whitespace/parens] [2]
 src/io_thread.cc:1547:  Missing space around colon in range-based for loop  [whitespace/forcolon] [2]
+src/io_thread.cc:651:  Add #include <map> for map<>  [build/include_what_you_use] [4]
+src/io_thread.cc:1546:  Add #include <unordered_set> for unordered_set<>  [build/include_what_you_use] [4]
+src/io_thread.cc:1609:  Add #include <string> for string  [build/include_what_you_use] [4]
+src/io_thread.cc:1731:  Add #include <memory> for unique_ptr<>  [build/include_what_you_use] [4]
 src/io_thread.cc:5:  samples/chromium-sample/src/io_thread.cc should include its header file samples/chromium-sample/src/io_thread.h  [build/include] [5]
 src/io_thread.h:5:  #ifndef header guard has wrong style, please use: SAMPLES_CHROMIUM_SAMPLE_SRC_IO_THREAD_H_  [build/header_guard] [5]
 src/io_thread.h:565:  #endif line should be "#endif  // SAMPLES_CHROMIUM_SAMPLE_SRC_IO_THREAD_H_"  [build/header_guard] [5]
diff --git a/samples/chromium-sample/src/chrome_content_renderer_client.cc b/samples/chromium-sample/src/chrome_content_renderer_client.cc
index ed78c480c..04a7dbd25 100644
--- a/samples/chromium-sample/src/chrome_content_renderer_client.cc
+++ b/samples/chromium-sample/src/chrome_content_renderer_client.cc
@@ -1,158 +1,263 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/renderer/chrome_content_renderer_client.h"
 
+#include <functional>
 #include <memory>
+#include <string_view>
 #include <utility>
 
+#include "base/check_op.h"
 #include "base/command_line.h"
 #include "base/debug/crash_logging.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/histogram.h"
+#include "base/functional/bind.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics_action.h"
+#include "base/no_destructor.h"
+#include "base/notreached.h"
+#include "base/process/current_process.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/single_thread_task_runner.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
+#include "chrome/common/buildflags.h"
 #include "chrome/common/channel_info.h"
+#include "chrome/common/chrome_content_client.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_isolated_world_ids.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/crash_keys.h"
+#include "chrome/common/pdf_util.h"
 #include "chrome/common/pepper_permission_util.h"
-#include "chrome/common/render_messages.h"
-#include "chrome/common/secure_origin_whitelist.h"
+#include "chrome/common/ppapi_utils.h"
+#include "chrome/common/profiler/thread_profiler.h"
+#include "chrome/common/profiler/unwind_util.h"
+#include "chrome/common/secure_origin_allowlist.h"
 #include "chrome/common/url_constants.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/grit/branded_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "chrome/grit/renderer_resources.h"
-#include "chrome/renderer/banners/app_banner_client.h"
 #include "chrome/renderer/benchmarking_extension.h"
+#include "chrome/renderer/browser_exposed_renderer_interfaces.h"
+#include "chrome/renderer/cart/commerce_hint_agent.h"
+#include "chrome/renderer/chrome_content_settings_agent_delegate.h"
 #include "chrome/renderer/chrome_render_frame_observer.h"
 #include "chrome/renderer/chrome_render_thread_observer.h"
-#include "chrome/renderer/chrome_render_view_observer.h"
-#include "chrome/renderer/content_settings_observer.h"
-#include "chrome/renderer/external_extension.h"
+#include "chrome/renderer/controlled_frame/controlled_frame_extensions_renderer_api_provider.h"
+#include "chrome/renderer/google_accounts_private_api_extension.h"
 #include "chrome/renderer/loadtimes_extension_bindings.h"
-#include "chrome/renderer/media/chrome_key_systems.h"
+#include "chrome/renderer/media/flash_embed_rewrite.h"
+#include "chrome/renderer/media/webrtc_logging_agent_impl.h"
 #include "chrome/renderer/net/net_error_helper.h"
 #include "chrome/renderer/net_benchmarking_extension.h"
-#include "chrome/renderer/page_load_histograms.h"
-#include "chrome/renderer/pepper/pepper_helper.h"
 #include "chrome/renderer/plugins/non_loadable_plugin_placeholder.h"
-#include "chrome/renderer/plugins/plugin_preroller.h"
+#include "chrome/renderer/plugins/pdf_plugin_placeholder.h"
 #include "chrome/renderer/plugins/plugin_uma.h"
-#include "chrome/renderer/prerender/prerender_dispatcher.h"
-#include "chrome/renderer/prerender/prerender_helper.h"
-#include "chrome/renderer/prerender/prerenderer_client.h"
-#include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h"
-#include "chrome/renderer/safe_browsing/threat_dom_details.h"
-#include "chrome/renderer/searchbox/search_bouncer.h"
-#include "chrome/renderer/searchbox/searchbox.h"
-#include "chrome/renderer/searchbox/searchbox_extension.h"
-#include "chrome/renderer/tts_dispatcher.h"
-#include "chrome/renderer/worker_content_settings_client_proxy.h"
+#include "chrome/renderer/trusted_vault_encryption_keys_extension.h"
+#include "chrome/renderer/url_loader_throttle_provider_impl.h"
+#include "chrome/renderer/v8_unwinder.h"
+#include "chrome/renderer/websocket_handshake_throttle_provider_impl.h"
+#include "chrome/renderer/worker_content_settings_client.h"
+#include "chrome/services/speech/buildflags/buildflags.h"
 #include "components/autofill/content/renderer/autofill_agent.h"
 #include "components/autofill/content/renderer/password_autofill_agent.h"
 #include "components/autofill/content/renderer/password_generation_agent.h"
+#include "components/autofill/core/common/autofill_features.h"
+#include "components/commerce/content/renderer/commerce_web_extractor.h"
+#include "components/commerce/core/commerce_feature_list.h"
+#include "components/content_capture/common/content_capture_features.h"
+#include "components/content_capture/renderer/content_capture_sender.h"
 #include "components/content_settings/core/common/content_settings_pattern.h"
-#include "components/contextual_search/renderer/overlay_js_render_frame_observer.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
+#include "components/continuous_search/renderer/search_result_extractor_impl.h"
 #include "components/dom_distiller/content/renderer/distillability_agent.h"
 #include "components/dom_distiller/content/renderer/distiller_js_render_frame_observer.h"
+#include "components/dom_distiller/core/dom_distiller_features.h"
+#include "components/dom_distiller/core/dom_distiller_switches.h"
 #include "components/dom_distiller/core/url_constants.h"
+#include "components/error_page/common/error.h"
 #include "components/error_page/common/localized_error.h"
-#include "components/network_hints/renderer/prescient_networking_dispatcher.h"
+#include "components/feed/buildflags.h"
+#include "components/grit/components_scaled_resources.h"
+#include "components/heap_profiling/in_process/heap_profiler_controller.h"
+#include "components/history_clusters/core/config.h"
+#include "components/metrics/call_stacks/call_stack_profile_builder.h"
+#include "components/network_hints/renderer/web_prescient_networking_impl.h"
+#include "components/no_state_prefetch/renderer/no_state_prefetch_client.h"
+#include "components/no_state_prefetch/renderer/no_state_prefetch_helper.h"
+#include "components/no_state_prefetch/renderer/no_state_prefetch_utils.h"
+#include "components/no_state_prefetch/renderer/prerender_render_frame_observer.h"
+#include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/page_load_metrics/renderer/metrics_render_frame_observer.h"
-#include "components/password_manager/content/renderer/credential_manager_client.h"
-#include "components/pdf/renderer/pepper_pdf_host.h"
-#include "components/plugins/renderer/mobile_youtube_plugin.h"
-#include "components/signin/core/common/profile_management_switches.h"
-#include "components/startup_metric_utils/common/startup_metric_messages.h"
+#include "components/paint_preview/buildflags/buildflags.h"
+#include "components/password_manager/core/common/password_manager_features.h"
+#include "components/pdf/common/constants.h"
+#include "components/permissions/features.h"
+#include "components/safe_browsing/buildflags.h"
+#include "components/safe_browsing/content/renderer/threat_dom_details.h"
+#include "components/spellcheck/spellcheck_buildflags.h"
+#include "components/subresource_filter/content/renderer/subresource_filter_agent.h"
+#include "components/subresource_filter/content/renderer/unverified_ruleset_dealer.h"
+#include "components/subresource_filter/core/common/common_features.h"
+#include "components/supervised_user/core/common/buildflags.h"
+#include "components/variations/net/variations_http_headers.h"
+#include "components/variations/variations_switches.h"
 #include "components/version_info/version_info.h"
-#include "components/visitedlink/renderer/visitedlink_slave.h"
+#include "components/visitedlink/renderer/visitedlink_reader.h"
 #include "components/web_cache/renderer/web_cache_impl.h"
+#include "components/webapps/renderer/web_page_metadata_agent.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/page_visibility_state.h"
 #include "content/public/common/url_constants.h"
-#include "content/public/renderer/plugin_instance_throttler.h"
+#include "content/public/common/webplugininfo.h"
 #include "content/public/renderer/render_frame.h"
-#include "content/public/renderer/render_thread.h"
-#include "content/public/renderer/render_view.h"
-#include "content/public/renderer/render_view_visitor.h"
-#include "extensions/common/constants.h"
+#include "content/public/renderer/render_frame_visitor.h"
+#include "extensions/buildflags/buildflags.h"
+#include "extensions/renderer/extensions_renderer_api_provider.h"
+#include "extensions/renderer/worker_script_context_set.h"
 #include "ipc/ipc_sync_channel.h"
+#include "media/base/media_switches.h"
+#include "media/media_buildflags.h"
+#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/net_errors.h"
-#include "ppapi/c/private/ppb_pdf.h"
-#include "ppapi/shared_impl/ppapi_switches.h"
-#include "third_party/WebKit/public/platform/URLConversion.h"
-#include "third_party/WebKit/public/platform/WebCachePolicy.h"
-#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/platform/WebURLError.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "third_party/WebKit/public/web/WebCache.h"
-#include "third_party/WebKit/public/web/WebDataSource.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebElement.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "third_party/WebKit/public/web/WebPluginParams.h"
-#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
+#include "pdf/buildflags.h"
+#include "ppapi/buildflags/buildflags.h"
+#include "printing/buildflags/buildflags.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
+#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.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_cache.h"
+#include "third_party/blink/public/platform/web_content_security_policy_struct.h"
+#include "third_party/blink/public/platform/web_runtime_features.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_request.h"
+#include "third_party/blink/public/platform/web_url_response.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_heap.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_origin_trials.h"
+#include "third_party/blink/public/web/web_plugin.h"
+#include "third_party/blink/public/web/web_plugin_container.h"
+#include "third_party/blink/public/web/web_plugin_params.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"
-#include "ui/base/layout.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/webui/jstemplate_builder.h"
-#include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
+#include "url/origin.h"
+#include "v8/include/v8-isolate.h"
+
+#if BUILDFLAG(IS_ANDROID)
+#include "chrome/renderer/sandbox_status_extension_android.h"
+#include "chrome/renderer/wallet/boarding_pass_extractor.h"
+#include "components/facilitated_payments/content/renderer/facilitated_payments_agent.h"
+#include "components/facilitated_payments/core/features/features.h"
+#else
+#include "chrome/renderer/searchbox/searchbox.h"
+#include "chrome/renderer/searchbox/searchbox_extension.h"
+#include "components/search/ntp_features.h"  // nogncheck
+#endif
+
+#if BUILDFLAG(ENABLE_SPEECH_SERVICE)
+#include "chrome/renderer/media/chrome_speech_recognition_client.h"
+#endif  // BUILDFLAG(ENABLE_SPEECH_SERVICE)
 
-#if !defined(DISABLE_NACL)
+#if BUILDFLAG(IS_WIN)
+#include "chrome/renderer/render_frame_font_family_accessor.h"
+#endif
+
+#if BUILDFLAG(ENABLE_FEED_V2)
+#include "components/feed/content/renderer/rss_link_reader.h"
+#include "components/feed/feed_feature_list.h"
+#endif
+
+#if BUILDFLAG(ENABLE_NACL)
 #include "components/nacl/common/nacl_constants.h"
 #include "components/nacl/renderer/nacl_helper.h"
 #endif
 
-#if defined(ENABLE_EXTENSIONS)
-#include "chrome/common/extensions/chrome_extensions_client.h"
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+#include "chrome/common/controlled_frame/controlled_frame.h"
+#include "chrome/common/initialize_extensions_client.h"
 #include "chrome/renderer/extensions/chrome_extensions_renderer_client.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/context_data.h"
 #include "extensions/common/extension_urls.h"
+#include "extensions/common/manifest_handlers/csp_info.h"
+#include "extensions/common/manifest_handlers/web_accessible_resources_info.h"
 #include "extensions/common/switches.h"
 #include "extensions/renderer/dispatcher.h"
+#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h"
 #include "extensions/renderer/renderer_extension_registry.h"
+#include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom.h"
+#include "third_party/blink/public/web/web_settings.h"
 #endif
 
-#if defined(ENABLE_IPC_FUZZER)
-#include "chrome/common/external_ipc_dumper.h"
-#endif
+#if BUILDFLAG(ENABLE_PDF)
+#include "chrome/renderer/pdf/chrome_pdf_internal_plugin_delegate.h"
+#include "components/pdf/renderer/internal_plugin_renderer_helpers.h"
+#endif  // BUILDFLAG(ENABLE_PDF)
 
-#if defined(ENABLE_PLUGINS)
+#if BUILDFLAG(ENABLE_PLUGINS)
 #include "chrome/renderer/plugins/chrome_plugin_placeholder.h"
-#include "chrome/renderer/plugins/power_saver_info.h"
+#endif  // BUILDFLAG(ENABLE_PLUGINS)
+
+#if BUILDFLAG(ENABLE_PPAPI)
+#include "chrome/renderer/pepper/pepper_helper.h"
+#include "ppapi/shared_impl/ppapi_switches.h"  // nogncheck crbug.com/1125897
 #endif
 
-#if defined(ENABLE_PRINTING)
-#include "chrome/common/chrome_content_client.h"
-#include "chrome/renderer/printing/chrome_print_web_view_helper_delegate.h"
-#include "components/printing/renderer/print_web_view_helper.h"
-#include "printing/print_settings.h"
+#if BUILDFLAG(ENABLE_PRINTING)
+#include "chrome/renderer/printing/chrome_print_render_frame_helper_delegate.h"
+#include "components/printing/renderer/print_render_frame_helper.h"  // nogncheck
+#include "printing/metafile_agent.h"  // nogncheck
 #endif
 
-#if defined(ENABLE_PRINT_PREVIEW)
-#include "chrome/renderer/pepper/chrome_pdf_print_client.h"
+#if BUILDFLAG(ENABLE_PAINT_PREVIEW)
+#include "components/paint_preview/renderer/paint_preview_recorder_impl.h"  // nogncheck
+#endif
+
+#if BUILDFLAG(ENABLE_SPELLCHECK)
+#include "components/spellcheck/renderer/spellcheck.h"
+#include "components/spellcheck/renderer/spellcheck_provider.h"
+
+#if BUILDFLAG(HAS_SPELLCHECK_PANEL)
+#include "components/spellcheck/renderer/spellcheck_panel.h"
+#endif  // BUILDFLAG(HAS_SPELLCHECK_PANEL)
+#endif  // BUILDFLAG(ENABLE_SPELLCHECK)
+
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+#include "chrome/renderer/supervised_user/supervised_user_error_page_controller_delegate_impl.h"
 #endif
 
-#if defined(ENABLE_SPELLCHECK)
-#include "chrome/renderer/spellchecker/spellcheck.h"
-#include "chrome/renderer/spellchecker/spellcheck_provider.h"
+#if BUILDFLAG(ENABLE_LIBRARY_CDMS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
+#include "chrome/renderer/media/chrome_key_systems.h"
 #endif
 
-#if defined(ENABLE_WEBRTC)
-#include "chrome/renderer/media/webrtc_logging_message_filter.h"
+#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
+#include "chrome/renderer/cco/multiline_detector.h"
 #endif
 
 using autofill::AutofillAgent;
@@ -161,9 +266,7 @@ using autofill::PasswordGenerationAgent;
 using base::ASCIIToUTF16;
 using base::UserMetricsAction;
 using blink::WebCache;
-using blink::WebCachePolicy;
 using blink::WebConsoleMessage;
-using blink::WebDataSource;
 using blink::WebDocument;
 using blink::WebFrame;
 using blink::WebLocalFrame;
@@ -177,37 +280,37 @@ using blink::WebURLError;
 using blink::WebURLRequest;
 using blink::WebURLResponse;
 using blink::WebVector;
-using content::PluginInstanceThrottler;
+using blink::mojom::FetchCacheMode;
 using content::RenderFrame;
 using content::RenderThread;
 using content::WebPluginInfo;
-using extensions::Extension;
+using content::WebPluginMimeType;
+using ExtractAllDatalists = autofill::AutofillAgent::ExtractAllDatalists;
+using FocusRequiresScroll = autofill::AutofillAgent::FocusRequiresScroll;
+using QueryPasswordSuggestions =
+    autofill::AutofillAgent::QueryPasswordSuggestions;
+using SecureContextRequired = autofill::AutofillAgent::SecureContextRequired;
+using UserGestureRequired = autofill::AutofillAgent::UserGestureRequired;
+using UsesKeyboardAccessoryForSuggestions =
+    autofill::AutofillAgent::UsesKeyboardAccessoryForSuggestions;
 
 namespace {
 
-// Whitelist PPAPI for Android Runtime for Chromium. (See crbug.com/383937)
-#if defined(ENABLE_PLUGINS)
+// Allow PPAPI for Android Runtime for Chromium. (See crbug.com/383937)
+#if BUILDFLAG(ENABLE_PLUGINS)
 const char* const kPredefinedAllowedCameraDeviceOrigins[] = {
-  "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F",
-  "4EB74897CB187C7633357C2FE832E0AD6A44883A"
-};
-
-const char* const kPredefinedAllowedCompositorOrigins[] = {
-  "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F",
-  "4EB74897CB187C7633357C2FE832E0AD6A44883A"
-};
-#endif
-
-#if defined(ENABLE_PLUGINS)
-void AppendParams(const std::vector<base::string16>& additional_names,
-                  const std::vector<base::string16>& additional_values,
-                  WebVector<WebString>* existing_names,
-                  WebVector<WebString>* existing_values) {
-  DCHECK(additional_names.size() == additional_values.size());
-  DCHECK(existing_names->size() == existing_values->size());
+    "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F",
+    "4EB74897CB187C7633357C2FE832E0AD6A44883A"};
+#endif
 
+#if BUILDFLAG(ENABLE_PLUGINS)
+void AppendParams(
+    const std::vector<WebPluginMimeType::Param>& additional_params,
+    WebVector<WebString>* existing_names,
+    WebVector<WebString>* existing_values) {
+  DCHECK(existing_names->size() == existing_values->size());
   size_t existing_size = existing_names->size();
-  size_t total_size = existing_size + additional_names.size();
+  size_t total_size = existing_size + additional_params.size();
 
   WebVector<WebString> names(total_size);
   WebVector<WebString> values(total_size);
@@ -217,348 +320,572 @@ void AppendParams(const std::vector<base::string16>& additional_names,
     values[i] = (*existing_values)[i];
   }
 
-  for (size_t i = 0; i < additional_names.size(); ++i) {
-    names[existing_size + i] = additional_names[i];
-    values[existing_size + i] = additional_values[i];
+  for (size_t i = 0; i < additional_params.size(); ++i) {
+    names[existing_size + i] = WebString::FromUTF16(additional_params[i].name);
+    values[existing_size + i] =
+        WebString::FromUTF16(additional_params[i].value);
   }
 
   existing_names->swap(names);
   existing_values->swap(values);
 }
+#endif  // BUILDFLAG(ENABLE_PLUGINS)
 
-// For certain sandboxed Pepper plugins, use the JavaScript Content Settings.
-bool ShouldUseJavaScriptSettingForPlugin(const WebPluginInfo& plugin) {
-  if (plugin.type != WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS &&
-      plugin.type != WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS) {
-    return false;
-  }
-
-#if !defined(DISABLE_NACL)
-  // Treat Native Client invocations like JavaScript.
-  if (plugin.name == ASCIIToUTF16(nacl::kNaClPluginName))
-    return true;
-#endif
-
-#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
-  // Treat CDM invocations like JavaScript.
-  if (plugin.name == ASCIIToUTF16(kWidevineCdmDisplayName)) {
-    DCHECK(plugin.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS);
-    return true;
-  }
-#endif  // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
-
+bool IsStandaloneContentExtensionProcess() {
+#if !BUILDFLAG(ENABLE_EXTENSIONS)
   return false;
+#else
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+      extensions::switches::kExtensionProcess);
+#endif
 }
-#endif  // defined(ENABLE_PLUGINS)
 
-#if defined(ENABLE_SPELLCHECK)
-class SpellCheckReplacer : public content::RenderViewVisitor {
- public:
-  explicit SpellCheckReplacer(SpellCheck* spellcheck)
-      : spellcheck_(spellcheck) {}
-  bool Visit(content::RenderView* render_view) override;
-
- private:
-  SpellCheck* spellcheck_;  // New shared spellcheck for all views. Weak Ptr.
-  DISALLOW_COPY_AND_ASSIGN(SpellCheckReplacer);
-};
-
-bool SpellCheckReplacer::Visit(content::RenderView* render_view) {
-  SpellCheckProvider* provider = SpellCheckProvider::Get(render_view);
-  DCHECK(provider);
-  provider->set_spellcheck(spellcheck_);
-  return true;
+std::unique_ptr<base::Unwinder> CreateV8Unwinder(v8::Isolate* isolate) {
+  return std::make_unique<V8Unwinder>(isolate);
 }
+
+// Web Share is conditionally enabled here in chrome/, to avoid it being
+// made available in other clients of content/ that do not have a Web Share
+// Mojo implementation (e.g. WebView).
+void MaybeEnableWebShare() {
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
+  if (base::FeatureList::IsEnabled(features::kWebShare))
+#endif
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || \
+    BUILDFLAG(IS_ANDROID)
+    blink::WebRuntimeFeatures::EnableWebShare(true);
 #endif
+}
 
-#if defined(ENABLE_EXTENSIONS)
-bool IsStandaloneExtensionProcess() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      extensions::switches::kExtensionProcess);
+#if BUILDFLAG(ENABLE_NACL) && BUILDFLAG(ENABLE_EXTENSIONS) && \
+    BUILDFLAG(IS_CHROMEOS_ASH)
+bool IsTerminalSystemWebAppNaClPage(GURL url) {
+  GURL::Replacements replacements;
+  replacements.ClearQuery();
+  replacements.ClearRef();
+  url = url.ReplaceComponents(replacements);
+  return url == "chrome-untrusted://terminal/html/terminal_ssh.html";
 }
 #endif
 
-// Defers media player loading in background pages until they're visible.
-// TODO(dalecurtis): Include an idle listener too.  http://crbug.com/509135
-class MediaLoadDeferrer : public content::RenderFrameObserver {
- public:
-  MediaLoadDeferrer(content::RenderFrame* render_frame,
-                    const base::Closure& continue_loading_cb)
-      : content::RenderFrameObserver(render_frame),
-        continue_loading_cb_(continue_loading_cb) {}
-  ~MediaLoadDeferrer() override {}
-
- private:
-  // content::RenderFrameObserver implementation:
-  void WasShown() override {
-    continue_loading_cb_.Run();
-    delete this;
-  }
-
-  const base::Closure continue_loading_cb_;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaLoadDeferrer);
-};
-
 }  // namespace
 
 ChromeContentRendererClient::ChromeContentRendererClient()
-    : main_entry_time_(base::TimeTicks::Now()) {
-#if defined(ENABLE_EXTENSIONS)
-  extensions::ExtensionsClient::Set(
-      extensions::ChromeExtensionsClient::GetInstance());
+    :
+#if BUILDFLAG(IS_WIN)
+      remote_module_watcher_(nullptr, base::OnTaskRunnerDeleter(nullptr)),
+#endif
+      main_thread_profiler_(
+#if BUILDFLAG(IS_CHROMEOS)
+          // The profiler can't start before the sandbox is initialized on
+          // ChromeOS due to ChromeOS's sandbox initialization code's use of
+          // AssertSingleThreaded().
+          nullptr
+#else
+          ThreadProfiler::CreateAndStartOnMainThread()
+#endif
+      ) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  EnsureExtensionsClientInitialized(
+      controlled_frame::CreateAvailabilityCheckMap());
   extensions::ExtensionsRendererClient::Set(
       ChromeExtensionsRendererClient::GetInstance());
 #endif
-#if defined(ENABLE_PLUGINS)
-  for (size_t i = 0; i < arraysize(kPredefinedAllowedCameraDeviceOrigins); ++i)
-    allowed_camera_device_origins_.insert(
-        kPredefinedAllowedCameraDeviceOrigins[i]);
-  for (size_t i = 0; i < arraysize(kPredefinedAllowedCompositorOrigins); ++i)
-    allowed_compositor_origins_.insert(kPredefinedAllowedCompositorOrigins[i]);
-#endif
-#if defined(ENABLE_PRINTING)
-  printing::SetAgent(GetUserAgent());
+#if BUILDFLAG(ENABLE_PLUGINS)
+  for (const char* origin : kPredefinedAllowedCameraDeviceOrigins)
+    allowed_camera_device_origins_.insert(origin);
 #endif
 }
 
-ChromeContentRendererClient::~ChromeContentRendererClient() {
-}
+ChromeContentRendererClient::~ChromeContentRendererClient() {}
 
 void ChromeContentRendererClient::RenderThreadStarted() {
   RenderThread* thread = RenderThread::Get();
 
-  thread->Send(new StartupMetricHostMsg_RecordRendererMainEntryTime(
-      main_entry_time_));
+  main_thread_profiler_->SetAuxUnwinderFactory(base::BindRepeating(
+      &CreateV8Unwinder, base::Unretained(v8::Isolate::GetCurrent())));
 
-  chrome_observer_.reset(new ChromeRenderThreadObserver());
-  web_cache_impl_.reset(new web_cache::WebCacheImpl());
+  // In the case of single process mode, the v8 unwinding will not work.
+  tracing::TracingSamplerProfiler::SetAuxUnwinderFactoryOnMainThread(
+      base::BindRepeating(&CreateV8Unwinder,
+                          base::Unretained(v8::Isolate::GetCurrent())));
 
-#if defined(ENABLE_EXTENSIONS)
-  ChromeExtensionsRendererClient::GetInstance()->RenderThreadStarted();
-#endif
+  const bool is_extension = IsStandaloneContentExtensionProcess();
+
+  thread->SetRendererProcessType(
+      is_extension
+          ? blink::scheduler::WebRendererProcessType::kExtensionRenderer
+          : blink::scheduler::WebRendererProcessType::kRenderer);
 
-  prescient_networking_dispatcher_.reset(
-      new network_hints::PrescientNetworkingDispatcher());
-#if defined(ENABLE_SPELLCHECK)
-  // ChromeRenderViewTest::SetUp() creates a Spellcheck and injects it using
-  // SetSpellcheck(). Don't overwrite it.
-  if (!spellcheck_) {
-    spellcheck_.reset(new SpellCheck());
-    thread->AddObserver(spellcheck_.get());
+  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);
   }
-#endif
-  visited_link_slave_.reset(new visitedlink::VisitedLinkSlave());
-#if defined(FULL_SAFE_BROWSING)
-  phishing_classifier_.reset(safe_browsing::PhishingClassifierFilter::Create());
-#endif
-  prerender_dispatcher_.reset(new prerender::PrerenderDispatcher());
-#if defined(ENABLE_WEBRTC)
-  webrtc_logging_message_filter_ = new WebRtcLoggingMessageFilter(
-      thread->GetIOMessageLoopProxy());
+
+#if BUILDFLAG(IS_WIN)
+  mojo::PendingRemote<mojom::ModuleEventSink> module_event_sink;
+  thread->BindHostReceiver(module_event_sink.InitWithNewPipeAndPassReceiver());
+  remote_module_watcher_ = RemoteModuleWatcher::Create(
+      thread->GetIOTaskRunner(), std::move(module_event_sink));
 #endif
 
-  thread->AddObserver(chrome_observer_.get());
-#if defined(FULL_SAFE_BROWSING)
-  thread->AddObserver(phishing_classifier_.get());
+  browser_interface_broker_ =
+      blink::Platform::Current()->GetBrowserInterfaceBroker();
+
+  chrome_observer_ = std::make_unique<ChromeRenderThreadObserver>();
+  web_cache_impl_ = std::make_unique<web_cache::WebCacheImpl>();
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  ChromeExtensionsRendererClient* chrome_extensions_renderer_client =
+      ChromeExtensionsRendererClient::GetInstance();
+  chrome_extensions_renderer_client->AddAPIProvider(
+      std::make_unique<
+          controlled_frame::ControlledFrameExtensionsRendererAPIProvider>());
+  chrome_extensions_renderer_client->RenderThreadStarted();
+  WebSecurityPolicy::RegisterURLSchemeAsExtension(
+      WebString::FromASCII(extensions::kExtensionScheme));
+  WebSecurityPolicy::RegisterURLSchemeAsCodeCacheWithHashing(
+      WebString::FromASCII(extensions::kExtensionScheme));
 #endif
-  thread->AddObserver(visited_link_slave_.get());
-  thread->AddObserver(prerender_dispatcher_.get());
-  thread->AddObserver(SearchBouncer::GetInstance());
 
-#if defined(ENABLE_WEBRTC)
-  thread->AddFilter(webrtc_logging_message_filter_.get());
+#if BUILDFLAG(ENABLE_SPELLCHECK)
+  if (!spellcheck_)
+    InitSpellCheck();
 #endif
 
-  thread->RegisterExtension(extensions_v8::ExternalExtension::Get());
-  thread->RegisterExtension(extensions_v8::LoadTimesExtension::Get());
+  subresource_filter_ruleset_dealer_ =
+      std::make_unique<subresource_filter::UnverifiedRulesetDealer>();
+
+  phishing_model_setter_ =
+      std::make_unique<safe_browsing::PhishingModelSetterImpl>();
+
+  thread->AddObserver(chrome_observer_.get());
+  thread->AddObserver(subresource_filter_ruleset_dealer_.get());
+  thread->AddObserver(phishing_model_setter_.get());
+
+  blink::WebScriptController::RegisterExtension(
+      extensions_v8::LoadTimesExtension::Get());
 
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kEnableBenchmarking))
-    thread->RegisterExtension(extensions_v8::BenchmarkingExtension::Get());
-  if (command_line->HasSwitch(switches::kEnableNetBenchmarking))
-    thread->RegisterExtension(extensions_v8::NetBenchmarkingExtension::Get());
-  if (command_line->HasSwitch(switches::kInstantProcess))
-    thread->RegisterExtension(extensions_v8::SearchBoxExtension::Get());
+  if (command_line->HasSwitch(variations::switches::kEnableBenchmarking)) {
+    blink::WebScriptController::RegisterExtension(
+        extensions_v8::BenchmarkingExtension::Get());
+  }
+
+  if (command_line->HasSwitch(switches::kEnableNetBenchmarking)) {
+    blink::WebScriptController::RegisterExtension(
+        extensions_v8::NetBenchmarkingExtension::Get());
+  }
+
+  // chrome: is also to be permitted to embeds https:// things and have them
+  // treated as first-party.
+  // See
+  // ChromeContentBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel
+  WebString chrome_scheme(WebString::FromASCII(content::kChromeUIScheme));
+  WebSecurityPolicy::RegisterURLSchemeAsFirstPartyWhenTopLevelEmbeddingSecure(
+      chrome_scheme);
+
+  // chrome-native: is a scheme used for placeholder navigations that allow
+  // UIs to be drawn with platform native widgets instead of HTML.  These pages
+  // should not be accessible.  No code should be runnable in these pages,
+  // so it should not need to access anything nor should it allow javascript
+  // URLs since it should never be visible to the user.
+  // See also ChromeContentClient::AddAdditionalSchemes that adds it as an
+  // empty document scheme.
+  WebString native_scheme(WebString::FromASCII(chrome::kChromeNativeScheme));
+  WebSecurityPolicy::RegisterURLSchemeAsDisplayIsolated(native_scheme);
+  WebSecurityPolicy::RegisterURLSchemeAsNotAllowingJavascriptURLs(
+      native_scheme);
 
   // chrome-search: and chrome-distiller: pages  should not be accessible by
   // normal content, and should also be unable to script anything but themselves
   // (to help limit the damage that a corrupt page could cause).
-  WebString chrome_search_scheme(ASCIIToUTF16(chrome::kChromeSearchScheme));
+  WebString chrome_search_scheme(
+      WebString::FromASCII(chrome::kChromeSearchScheme));
+
+  // IWAs can be enabled by either the feature flag or by enterprise
+  // policy. In either case the kEnableIsolatedWebAppsInRenderer flag is passed
+  // to the renderer process.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableIsolatedWebAppsInRenderer)) {
+    // isolated-app: is the scheme used for Isolated Web Apps, which are web
+    // applications packaged in Signed Web Bundles.
+    WebString isolated_app_scheme(
+        WebString::FromASCII(chrome::kIsolatedAppScheme));
+    // Resources contained in Isolated Web Apps are HTTP-like and safe to expose
+    // to the fetch API.
+    WebSecurityPolicy::RegisterURLSchemeAsSupportingFetchAPI(
+        isolated_app_scheme);
+    WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers(
+        isolated_app_scheme);
+    WebSecurityPolicy::RegisterURLSchemeAsAllowedForReferrer(
+        isolated_app_scheme);
+  }
 
   // The Instant process can only display the content but not read it.  Other
   // processes can't display it or read it.
   if (!command_line->HasSwitch(switches::kInstantProcess))
-    WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(chrome_search_scheme);
+    WebSecurityPolicy::RegisterURLSchemeAsDisplayIsolated(chrome_search_scheme);
 
   WebString dom_distiller_scheme(
-      ASCIIToUTF16(dom_distiller::kDomDistillerScheme));
+      WebString::FromASCII(dom_distiller::kDomDistillerScheme));
   // TODO(nyquist): Add test to ensure this happens when the flag is set.
-  WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(dom_distiller_scheme);
-
-#if defined(OS_CHROMEOS)
-  WebSecurityPolicy::registerURLSchemeAsLocal(
-      WebString::fromUTF8(content::kExternalFileScheme));
-#endif
-
-#if defined(OS_ANDROID)
-  WebSecurityPolicy::registerURLSchemeAsAllowedForReferrer(
-      WebString::fromUTF8(chrome::kAndroidAppScheme));
-#endif
+  WebSecurityPolicy::RegisterURLSchemeAsDisplayIsolated(dom_distiller_scheme);
 
-#if defined(ENABLE_IPC_FUZZER)
-  if (command_line->HasSwitch(switches::kIpcDumpDirectory)) {
-    base::FilePath dump_directory =
-        command_line->GetSwitchValuePath(switches::kIpcDumpDirectory);
-    IPC::ChannelProxy::OutgoingMessageFilter* filter =
-        LoadExternalIPCDumper(dump_directory);
-    thread->GetChannel()->set_outgoing_message_filter(filter);
-  }
+#if BUILDFLAG(IS_ANDROID)
+  WebSecurityPolicy::RegisterURLSchemeAsAllowedForReferrer(
+      WebString::FromUTF8(content::kAndroidAppScheme));
 #endif
 
   // chrome-search: pages should not be accessible by bookmarklets
   // or javascript: URLs typed in the omnibox.
-  WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs(
+  WebSecurityPolicy::RegisterURLSchemeAsNotAllowingJavascriptURLs(
       chrome_search_scheme);
 
-  // chrome-search: resources shouldn't trigger insecure content warnings. Note
-  // that chrome-extension: and chrome-extension-resource: schemes are taken
-  // care of in extensions::Dispatcher.
-  WebSecurityPolicy::registerURLSchemeAsSecure(chrome_search_scheme);
-
-#if defined(ENABLE_PRINT_PREVIEW)
-  pdf_print_client_.reset(new ChromePDFPrintClient());
-  pdf::PepperPDFHost::SetPrintClient(pdf_print_client_.get());
-#endif
-
-  std::set<GURL> origins;
-  GetSecureOriginWhitelist(&origins);
-  for (const GURL& origin : origins) {
-    WebSecurityPolicy::addOriginTrustworthyWhiteList(
-        WebSecurityOrigin::create(origin));
+  for (auto& scheme :
+       secure_origin_allowlist::GetSchemesBypassingSecureContextCheck()) {
+    WebSecurityPolicy::AddSchemeToSecureContextSafelist(
+        WebString::FromASCII(scheme));
   }
 
-  std::set<std::string> schemes;
-  GetSchemesBypassingSecureContextCheckWhitelist(&schemes);
-  for (const std::string& scheme : schemes) {
-    WebSecurityPolicy::addSchemeToBypassSecureContextWhitelist(
-        WebString::fromUTF8(scheme));
+  // This doesn't work in single-process mode.
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kSingleProcess)) {
+    using HeapProfilerController = heap_profiling::HeapProfilerController;
+    // The HeapProfilerController should have been created in
+    // ChromeMainDelegate::PostEarlyInitialization.
+    DCHECK_NE(HeapProfilerController::GetProfilingEnabled(),
+              HeapProfilerController::ProfilingEnabled::kNoController);
+    if (ThreadProfiler::ShouldCollectProfilesForChildProcess() ||
+        HeapProfilerController::GetProfilingEnabled() ==
+            HeapProfilerController::ProfilingEnabled::kEnabled) {
+      ThreadProfiler::SetMainThreadTaskRunner(
+          base::SingleThreadTaskRunner::GetCurrentDefault());
+      mojo::PendingRemote<metrics::mojom::CallStackProfileCollector> collector;
+      thread->BindHostReceiver(collector.InitWithNewPipeAndPassReceiver());
+      metrics::CallStackProfileBuilder::
+          SetParentProfileCollectorForChildProcess(std::move(collector));
+    }
   }
 }
 
+void ChromeContentRendererClient::ExposeInterfacesToBrowser(
+    mojo::BinderMap* binders) {
+  // NOTE: Do not add binders directly within this method. Instead, modify the
+  // definition of |ExposeChromeRendererInterfacesToBrowser()| to ensure
+  // security review coverage.
+  ExposeChromeRendererInterfacesToBrowser(this, binders);
+}
+
 void ChromeContentRendererClient::RenderFrameCreated(
     content::RenderFrame* render_frame) {
-  new ChromeRenderFrameObserver(render_frame);
+  ChromeRenderFrameObserver* render_frame_observer =
+      new ChromeRenderFrameObserver(render_frame, web_cache_impl_.get());
+  service_manager::BinderRegistry* registry = render_frame_observer->registry();
+
+  new prerender::PrerenderRenderFrameObserver(render_frame);
 
-  bool should_whitelist_for_content_settings =
+  bool should_allow_for_content_settings =
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kInstantProcess);
-  extensions::Dispatcher* ext_dispatcher = NULL;
-#if defined(ENABLE_EXTENSIONS)
-  ext_dispatcher =
-      ChromeExtensionsRendererClient::GetInstance()->extension_dispatcher();
+  auto content_settings_delegate =
+      std::make_unique<ChromeContentSettingsAgentDelegate>(render_frame);
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  content_settings_delegate->SetExtensionDispatcher(
+      ChromeExtensionsRendererClient::GetInstance()->extension_dispatcher());
 #endif
-  ContentSettingsObserver* content_settings = new ContentSettingsObserver(
-      render_frame, ext_dispatcher, should_whitelist_for_content_settings);
+  content_settings::ContentSettingsAgentImpl* content_settings =
+      new content_settings::ContentSettingsAgentImpl(
+          render_frame, should_allow_for_content_settings,
+          std::move(content_settings_delegate));
   if (chrome_observer_.get()) {
-    content_settings->SetContentSettingRules(
-        chrome_observer_->content_setting_rules());
+    if (chrome_observer_->content_settings_manager()) {
+      mojo::Remote<content_settings::mojom::ContentSettingsManager> manager;
+      chrome_observer_->content_settings_manager()->Clone(
+          manager.BindNewPipeAndPassReceiver());
+      content_settings->SetContentSettingsManager(std::move(manager));
+    }
   }
 
-#if defined(ENABLE_EXTENSIONS)
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   ChromeExtensionsRendererClient::GetInstance()->RenderFrameCreated(
-      render_frame);
+      render_frame, registry);
 #endif
 
-#if defined(ENABLE_PLUGINS)
+#if BUILDFLAG(ENABLE_PPAPI)
   new PepperHelper(render_frame);
 #endif
 
-#if !defined(DISABLE_NACL)
+#if BUILDFLAG(ENABLE_NACL)
   new nacl::NaClHelper(render_frame);
 #endif
 
-#if defined(FULL_SAFE_BROWSING)
-  safe_browsing::ThreatDOMDetails::Create(render_frame);
+#if BUILDFLAG(SAFE_BROWSING_DB_LOCAL) || BUILDFLAG(SAFE_BROWSING_DB_REMOTE)
+  safe_browsing::ThreatDOMDetails::Create(render_frame, registry);
+#endif
+
+#if BUILDFLAG(ENABLE_PRINTING)
+  new printing::PrintRenderFrameHelper(
+      render_frame, std::make_unique<ChromePrintRenderFrameHelperDelegate>());
+#endif
+
+#if BUILDFLAG(ENABLE_PAINT_PREVIEW)
+  new paint_preview::PaintPreviewRecorderImpl(render_frame);
 #endif
 
+#if BUILDFLAG(IS_ANDROID)
+  SandboxStatusExtension::Create(render_frame);
+#endif
+
+  TrustedVaultEncryptionKeysExtension::Create(render_frame);
+  GoogleAccountsPrivateApiExtension::Create(render_frame);
+
+  if (render_frame->IsMainFrame())
+    new webapps::WebPageMetadataAgent(render_frame);
+
+  const bool search_result_extractor_enabled =
+      render_frame->IsMainFrame() &&
+      optimization_guide::features::IsPageContentAnnotationEnabled();
+  if (search_result_extractor_enabled) {
+    continuous_search::SearchResultExtractorImpl::Create(render_frame);
+  }
+
   new NetErrorHelper(render_frame);
 
-  if (render_frame->IsMainFrame()) {
-    // Only attach MainRenderFrameObserver to the main frame, since
-    // we only want to log page load metrics for the main frame.
-    new page_load_metrics::MetricsRenderFrameObserver(render_frame);
-  } else {
-    // Avoid any race conditions from having the browser tell subframes that
-    // they're prerendering.
-    if (prerender::PrerenderHelper::IsPrerendering(
-            render_frame->GetRenderView()->GetMainRenderFrame())) {
-      new prerender::PrerenderHelper(render_frame);
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+  new SupervisedUserErrorPageControllerDelegateImpl(render_frame);
+#endif
+
+  if (!render_frame->IsMainFrame()) {
+    auto* main_frame_no_state_prefetch_helper =
+        prerender::NoStatePrefetchHelper::Get(
+            render_frame->GetMainRenderFrame());
+    if (main_frame_no_state_prefetch_helper) {
+      // Avoid any race conditions from having the browser tell subframes that
+      // they're no-state prefetching.
+      new prerender::NoStatePrefetchHelper(
+          render_frame,
+          main_frame_no_state_prefetch_helper->histogram_prefix());
     }
   }
 
-  // Set up a mojo service to test if this page is a distiller page.
+  // Set up a render frame observer to test if this page is a distiller page.
   new dom_distiller::DistillerJsRenderFrameObserver(
-      render_frame, chrome::ISOLATED_WORLD_ID_CHROME_INTERNAL);
+      render_frame, ISOLATED_WORLD_ID_CHROME_INTERNAL);
 
-  // Create DistillabilityAgent to send distillability updates to
-  // DistillabilityDriver in the browser process.
-  new dom_distiller::DistillabilityAgent(render_frame);
+  if (dom_distiller::ShouldStartDistillabilityService()) {
+    // Create DistillabilityAgent to send distillability updates to
+    // DistillabilityDriver in the browser process.
+    new dom_distiller::DistillabilityAgent(render_frame, DCHECK_IS_ON());
+  }
 
-  // Set up a mojo service to test if this page is a contextual search page.
-  new contextual_search::OverlayJsRenderFrameObserver(render_frame);
+  blink::AssociatedInterfaceRegistry* associated_interfaces =
+      render_frame_observer->associated_interfaces();
+
+  if (!render_frame->IsInFencedFrameTree() ||
+      base::FeatureList::IsEnabled(blink::features::kFencedFramesAPIChanges)) {
+    auto password_autofill_agent = std::make_unique<PasswordAutofillAgent>(
+        render_frame, associated_interfaces);
+    auto password_generation_agent = std::make_unique<PasswordGenerationAgent>(
+        render_frame, password_autofill_agent.get(), associated_interfaces);
+    new AutofillAgent(
+        render_frame,
+        {ExtractAllDatalists(false), FocusRequiresScroll(true),
+         QueryPasswordSuggestions(false), SecureContextRequired(false),
+         UserGestureRequired(true),
+         UsesKeyboardAccessoryForSuggestions(BUILDFLAG(IS_ANDROID))},
+        std::move(password_autofill_agent),
+        std::move(password_generation_agent), associated_interfaces);
+
+#if BUILDFLAG(IS_ANDROID)
+    if (render_frame->IsMainFrame() &&
+        base::FeatureList::IsEnabled(
+            payments::facilitated::kEnablePixDetection)) {
+      new payments::facilitated::FacilitatedPaymentsAgent(
+          render_frame, associated_interfaces);
+    }
+#endif
+  }
 
-  PasswordAutofillAgent* password_autofill_agent =
-      new PasswordAutofillAgent(render_frame);
-  PasswordGenerationAgent* password_generation_agent =
-      new PasswordGenerationAgent(render_frame, password_autofill_agent);
-  new AutofillAgent(render_frame, password_autofill_agent,
-                    password_generation_agent);
-}
+  if (content_capture::features::IsContentCaptureEnabled()) {
+    new content_capture::ContentCaptureSender(render_frame,
+                                              associated_interfaces);
+  }
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  associated_interfaces
+      ->AddInterface<extensions::mojom::MimeHandlerViewContainerManager>(
+          base::BindRepeating(
+              &extensions::MimeHandlerViewContainerManager::BindReceiver,
+              base::Unretained(render_frame)));
+#endif
+
+  // Owned by |render_frame|.
+  new page_load_metrics::MetricsRenderFrameObserver(render_frame);
+  // There is no render thread, thus no UnverifiedRulesetDealer in
+  // ChromeRenderViewTests.
+  if (subresource_filter_ruleset_dealer_) {
+    auto* subresource_filter_agent =
+        new subresource_filter::SubresourceFilterAgent(
+            render_frame, subresource_filter_ruleset_dealer_.get());
+    subresource_filter_agent->Initialize();
+  }
 
-void ChromeContentRendererClient::RenderViewCreated(
-    content::RenderView* render_view) {
-#if defined(ENABLE_EXTENSIONS)
-  ChromeExtensionsRendererClient::GetInstance()->RenderViewCreated(render_view);
+#if !BUILDFLAG(IS_ANDROID)
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kInstantProcess) &&
+      render_frame->IsMainFrame()) {
+    new SearchBox(render_frame);
+  }
 #endif
-  new PageLoadHistograms(render_view);
-#if defined(ENABLE_PRINTING)
-  new printing::PrintWebViewHelper(
-      render_view, std::unique_ptr<printing::PrintWebViewHelper::Delegate>(
-                       new ChromePrintWebViewHelperDelegate()));
+
+// We should create CommerceHintAgent only for a main frame except a fenced
+// frame that is the main frame as well, so we should check if |render_frame|
+// is the fenced frame.
+#if !BUILDFLAG(IS_ANDROID)
+  if (command_line->HasSwitch(commerce::switches::kEnableChromeCart) &&
+#else
+  if (base::FeatureList::IsEnabled(commerce::kCommerceHintAndroid) &&
+#endif  // !BUILDFLAG(IS_ANDROID)
+      render_frame->GetWebFrame()->IsOutermostMainFrame()) {
+    new cart::CommerceHintAgent(render_frame);
+  }
+
+#if BUILDFLAG(ENABLE_SPELLCHECK)
+  new SpellCheckProvider(render_frame, spellcheck_.get());
+
+#if BUILDFLAG(HAS_SPELLCHECK_PANEL)
+  new SpellCheckPanel(render_frame, registry, this);
+#endif  // BUILDFLAG(HAS_SPELLCHECK_PANEL)
 #endif
-#if defined(ENABLE_SPELLCHECK)
-  new SpellCheckProvider(render_view, spellcheck_.get());
+#if BUILDFLAG(ENABLE_FEED_V2)
+  if (render_frame->IsMainFrame() &&
+      base::FeatureList::IsEnabled(feed::kWebFeed)) {
+    new feed::RssLinkReader(render_frame, registry);
+  }
 #endif
-  new prerender::PrerendererClient(render_view);
 
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kInstantProcess))
-    new SearchBox(render_view);
+#if BUILDFLAG(IS_WIN)
+  if (render_frame->IsMainFrame()) {
+    associated_interfaces
+        ->AddInterface<chrome::mojom::RenderFrameFontFamilyAccessor>(
+            base::BindRepeating(&RenderFrameFontFamilyAccessor::Bind,
+                                render_frame));
+  }
+#endif
 
-  new ChromeRenderViewObserver(render_view, web_cache_impl_.get());
+#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
+  MultilineDetector::InstallIfNecessary(render_frame);
+#endif
+
+  if (render_frame->IsMainFrame()) {
+    new commerce::CommerceWebExtractor(render_frame, registry);
+  }
 
-  new password_manager::CredentialManagerClient(render_view);
+#if BUILDFLAG(IS_ANDROID)
+  if (base::FeatureList::IsEnabled(features::kBoardingPassDetector) &&
+      render_frame->IsMainFrame()) {
+    new wallet::BoardingPassExtractor(render_frame, registry);
+  }
+#endif
 }
 
+void ChromeContentRendererClient::WebViewCreated(
+    blink::WebView* web_view,
+    bool was_created_by_renderer,
+    const url::Origin* outermost_origin) {
+  new prerender::NoStatePrefetchClient(web_view);
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  ChromeExtensionsRendererClient::GetInstance()->WebViewCreated(
+      web_view, outermost_origin);
+#endif
+}
 
 SkBitmap* ChromeContentRendererClient::GetSadPluginBitmap() {
-  return const_cast<SkBitmap*>(ResourceBundle::GetSharedInstance().
-      GetImageNamed(IDR_SAD_PLUGIN).ToSkBitmap());
+  return const_cast<SkBitmap*>(ui::ResourceBundle::GetSharedInstance()
+                                   .GetImageNamed(IDR_SAD_PLUGIN)
+                                   .ToSkBitmap());
 }
 
 SkBitmap* ChromeContentRendererClient::GetSadWebViewBitmap() {
-  return const_cast<SkBitmap*>(ResourceBundle::GetSharedInstance().
-      GetImageNamed(IDR_SAD_WEBVIEW).ToSkBitmap());
+  return const_cast<SkBitmap*>(ui::ResourceBundle::GetSharedInstance()
+                                   .GetImageNamed(IDR_SAD_WEBVIEW)
+                                   .ToSkBitmap());
+}
+
+bool ChromeContentRendererClient::IsPluginHandledExternally(
+    content::RenderFrame* render_frame,
+    const blink::WebElement& plugin_element,
+    const GURL& original_url,
+    const std::string& mime_type) {
+#if BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS)
+  DCHECK(plugin_element.HasHTMLTagName("object") ||
+         plugin_element.HasHTMLTagName("embed"));
+
+  mojo::AssociatedRemote<chrome::mojom::PluginInfoHost> plugin_info_host;
+  render_frame->GetRemoteAssociatedInterfaces()->GetInterface(
+      &plugin_info_host);
+  // 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();
+  plugin_info_host->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 BUILDFLAG(ENABLE_PDF)
+  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;
+    }
+  }
+#endif  // BUILDFLAG(ENABLE_PDF)
+  return ChromeExtensionsRendererClient::MaybeCreateMimeHandlerView(
+      plugin_element, original_url, plugin_info->actual_mime_type,
+      plugin_info->plugin);
+#else   // !(BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS))
+  return false;
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS)
+}
+
+v8::Local<v8::Object> ChromeContentRendererClient::GetScriptableObject(
+    const blink::WebElement& plugin_element,
+    v8::Isolate* isolate) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  return ChromeExtensionsRendererClient::GetInstance()->GetScriptableObject(
+      plugin_element, isolate);
+#else
+  return v8::Local<v8::Object>();
+#endif
 }
 
 bool ChromeContentRendererClient::OverrideCreatePlugin(
     content::RenderFrame* render_frame,
-    WebLocalFrame* frame,
     const WebPluginParams& params,
     WebPlugin** plugin) {
-  std::string orig_mime_type = params.mimeType.utf8();
-#if defined(ENABLE_EXTENSIONS)
+  std::string orig_mime_type = params.mime_type.Utf8();
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   if (!ChromeExtensionsRendererClient::GetInstance()->OverrideCreatePlugin(
           render_frame, params)) {
     return false;
@@ -566,135 +893,136 @@ bool ChromeContentRendererClient::OverrideCreatePlugin(
 #endif
 
   GURL url(params.url);
-#if defined(ENABLE_PLUGINS)
-  ChromeViewHostMsg_GetPluginInfo_Output output;
-  WebString top_origin = frame->top()->getSecurityOrigin().toString();
-  render_frame->Send(new ChromeViewHostMsg_GetPluginInfo(
-      render_frame->GetRoutingID(), url, blink::WebStringToGURL(top_origin),
-      orig_mime_type, &output));
-  *plugin = CreatePlugin(render_frame, frame, params, output);
-#else  // !defined(ENABLE_PLUGINS)
-
-#if defined(OS_ANDROID)
-  if (plugins::MobileYouTubePlugin::IsYouTubeURL(url, orig_mime_type)) {
-    base::StringPiece template_html(
-        ResourceBundle::GetSharedInstance().GetRawDataResource(
-            IDR_MOBILE_YOUTUBE_PLUGIN_HTML));
-    *plugin = (new plugins::MobileYouTubePlugin(render_frame, frame, params,
-                                                template_html))->plugin();
+#if BUILDFLAG(ENABLE_PLUGINS)
+  mojo::AssociatedRemote<chrome::mojom::PluginInfoHost> plugin_info_host;
+  render_frame->GetRemoteAssociatedInterfaces()->GetInterface(
+      &plugin_info_host);
+
+  chrome::mojom::PluginInfoPtr plugin_info = chrome::mojom::PluginInfo::New();
+  plugin_info_host->GetPluginInfo(
+      url, render_frame->GetWebFrame()->Top()->GetSecurityOrigin(),
+      orig_mime_type, &plugin_info);
+  *plugin = CreatePlugin(render_frame, params, *plugin_info);
+#else  // !BUILDFLAG(ENABLE_PLUGINS)
+  PluginUMAReporter::GetInstance()->ReportPluginMissing(orig_mime_type, url);
+  if (orig_mime_type == pdf::kPDFMimeType) {
+    ReportPDFLoadStatus(
+        PDFLoadStatus::kShowedDisabledPluginPlaceholderForEmbeddedPdf);
+
+    PDFPluginPlaceholder* placeholder =
+        PDFPluginPlaceholder::CreatePDFPlaceholder(render_frame, params);
+    *plugin = placeholder->plugin();
     return true;
   }
-#endif  // defined(OS_ANDROID)
-
-  PluginUMAReporter::GetInstance()->ReportPluginMissing(orig_mime_type, url);
-  *plugin = NonLoadablePluginPlaceholder::CreateNotSupportedPlugin(
-                render_frame, frame, params)->plugin();
+  auto* placeholder = NonLoadablePluginPlaceholder::CreateNotSupportedPlugin(
+      render_frame, params);
+  *plugin = placeholder->plugin();
 
-#endif  // defined(ENABLE_PLUGINS)
+#endif  // BUILDFLAG(ENABLE_PLUGINS)
   return true;
 }
 
+#if BUILDFLAG(ENABLE_PLUGINS)
 WebPlugin* ChromeContentRendererClient::CreatePluginReplacement(
     content::RenderFrame* render_frame,
     const base::FilePath& plugin_path) {
-  return NonLoadablePluginPlaceholder::CreateErrorPlugin(render_frame,
-                                                         plugin_path)->plugin();
+  auto* placeholder = NonLoadablePluginPlaceholder::CreateErrorPlugin(
+      render_frame, plugin_path);
+  return placeholder->plugin();
 }
+#endif  // BUILDFLAG(ENABLE_PLUGINS)
 
-void ChromeContentRendererClient::DeferMediaLoad(
+bool ChromeContentRendererClient::DeferMediaLoad(
     content::RenderFrame* render_frame,
     bool has_played_media_before,
-    const base::Closure& closure) {
-  // Don't allow autoplay/autoload of media resources in a RenderFrame that is
-  // hidden and has never played any media before.  We want to allow future
-  // loads even when hidden to allow playlist-like functionality.
-  //
-  // NOTE: This is also used to defer media loading for prerender.
-  // NOTE: Switch can be used to allow autoplay, unless frame is prerendered.
-  //
-  // TODO(dalecurtis): Include an idle check too.  http://crbug.com/509135
-  if ((render_frame->IsHidden() && !has_played_media_before &&
-       !base::CommandLine::ForCurrentProcess()->HasSwitch(
-           switches::kDisableGestureRequirementForMediaPlayback)) ||
-      prerender::PrerenderHelper::IsPrerendering(render_frame)) {
-    new MediaLoadDeferrer(render_frame, closure);
-    return;
-  }
-
-  closure.Run();
+    base::OnceClosure closure) {
+  return prerender::DeferMediaLoad(render_frame, has_played_media_before,
+                                   std::move(closure));
 }
 
-#if defined(ENABLE_PLUGINS)
+#if BUILDFLAG(ENABLE_PLUGINS)
+
+// static
 WebPlugin* ChromeContentRendererClient::CreatePlugin(
     content::RenderFrame* render_frame,
-    WebLocalFrame* frame,
     const WebPluginParams& original_params,
-    const ChromeViewHostMsg_GetPluginInfo_Output& output) {
-  const WebPluginInfo& info = output.plugin;
-  const std::string& actual_mime_type = output.actual_mime_type;
-  const base::string16& group_name = output.group_name;
-  const std::string& identifier = output.group_identifier;
-  ChromeViewHostMsg_GetPluginInfo_Status status = output.status;
+    const chrome::mojom::PluginInfo& plugin_info) {
+  const WebPluginInfo& info = plugin_info.plugin;
+  const std::string& actual_mime_type = plugin_info.actual_mime_type;
+  const std::u16string& group_name = plugin_info.group_name;
+  const std::string& identifier = plugin_info.group_identifier;
+  chrome::mojom::PluginStatus status = plugin_info.status;
   GURL url(original_params.url);
-  std::string orig_mime_type = original_params.mimeType.utf8();
-  ChromePluginPlaceholder* placeholder = NULL;
+  std::string orig_mime_type = original_params.mime_type.Utf8();
+  ChromePluginPlaceholder* placeholder = nullptr;
 
   // If the browser plugin is to be enabled, this should be handled by the
   // renderer, so the code won't reach here due to the early exit in
   // OverrideCreatePlugin.
-  if (status == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound ||
+  if (status == chrome::mojom::PluginStatus::kNotFound ||
       orig_mime_type == content::kBrowserPluginMimeType) {
-    PluginUMAReporter::GetInstance()->ReportPluginMissing(orig_mime_type, url);
-    placeholder = ChromePluginPlaceholder::CreateLoadableMissingPlugin(
-        render_frame, frame, original_params);
+    // Flash has been thoroughly removed in M88+, so we need to have a special
+    // case here to display a deprecated message instead of a generic
+    // plugin-missing message.
+    if (orig_mime_type == "application/x-shockwave-flash" ||
+        orig_mime_type == "application/futuresplash") {
+      return NonLoadablePluginPlaceholder::CreateFlashDeprecatedPlaceholder(
+                 render_frame, original_params)
+          ->plugin();
+    } else {
+      PluginUMAReporter::GetInstance()->ReportPluginMissing(orig_mime_type,
+                                                            url);
+      placeholder = ChromePluginPlaceholder::CreateLoadableMissingPlugin(
+          render_frame, original_params);
+    }
   } else {
     // TODO(bauerb): This should be in content/.
     WebPluginParams params(original_params);
-    for (size_t i = 0; i < info.mime_types.size(); ++i) {
-      if (info.mime_types[i].mime_type == actual_mime_type) {
-        AppendParams(info.mime_types[i].additional_param_names,
-                     info.mime_types[i].additional_param_values,
-                     &params.attributeNames, &params.attributeValues);
+    for (const auto& mime_type : info.mime_types) {
+      if (mime_type.mime_type == actual_mime_type) {
+        AppendParams(mime_type.additional_params, &params.attribute_names,
+                     &params.attribute_values);
         break;
       }
     }
-    if (params.mimeType.isNull() && (actual_mime_type.size() > 0)) {
+    if (params.mime_type.IsNull() && (actual_mime_type.size() > 0)) {
       // Webkit might say that mime type is null while we already know the
       // actual mime type via ChromeViewHostMsg_GetPluginInfo. In that case
       // we should use what we know since WebpluginDelegateProxy does some
       // specific initializations based on this information.
-      params.mimeType = WebString::fromUTF8(actual_mime_type.c_str());
+      params.mime_type = WebString::FromUTF8(actual_mime_type);
     }
 
-    ContentSettingsObserver* observer =
-        ContentSettingsObserver::Get(render_frame);
+    auto* content_settings_agent =
+        content_settings::ContentSettingsAgentImpl::Get(render_frame);
+    auto* content_settings_agent_delegate =
+        ChromeContentSettingsAgentDelegate::Get(render_frame);
 
-    const ContentSettingsType content_type =
-        ShouldUseJavaScriptSettingForPlugin(info)
-            ? CONTENT_SETTINGS_TYPE_JAVASCRIPT
-            : CONTENT_SETTINGS_TYPE_PLUGINS;
+    const ContentSettingsType content_type = ContentSettingsType::JAVASCRIPT;
 
-    if ((status == ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized ||
-         status == ChromeViewHostMsg_GetPluginInfo_Status::kBlocked) &&
-        observer->IsPluginTemporarilyAllowed(identifier)) {
-      status = ChromeViewHostMsg_GetPluginInfo_Status::kAllowed;
+    if ((status == chrome::mojom::PluginStatus::kUnauthorized ||
+         status == chrome::mojom::PluginStatus::kBlocked) &&
+        content_settings_agent_delegate->IsPluginTemporarilyAllowed(
+            identifier)) {
+      status = chrome::mojom::PluginStatus::kAllowed;
     }
 
-    auto create_blocked_plugin = [&render_frame, &frame, &params, &info,
-                                  &identifier, &group_name](
-        int template_id, const base::string16& message) {
+    auto create_blocked_plugin = [&render_frame, &params, &info, &identifier,
+                                  &group_name](int template_id,
+                                               const std::u16string& message) {
       return ChromePluginPlaceholder::CreateBlockedPlugin(
-          render_frame, frame, params, info, identifier, group_name,
-          template_id, message, PowerSaverInfo());
+          render_frame, params, info, identifier, group_name, template_id,
+          message);
     };
     switch (status) {
-      case ChromeViewHostMsg_GetPluginInfo_Status::kNotFound: {
+      case chrome::mojom::PluginStatus::kNotFound: {
         NOTREACHED();
         break;
       }
-      case ChromeViewHostMsg_GetPluginInfo_Status::kAllowed:
-      case ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent: {
-#if !defined(DISABLE_NACL) && defined(ENABLE_EXTENSIONS)
+      case chrome::mojom::PluginStatus::kAllowed:
+      case chrome::mojom::PluginStatus::kPlayImportantContent: {
+#if BUILDFLAG(ENABLE_NACL) && BUILDFLAG(ENABLE_EXTENSIONS)
+        WebLocalFrame* frame = render_frame->GetWebFrame();
         const bool is_nacl_plugin =
             info.name == ASCIIToUTF16(nacl::kNaClPluginName);
         const bool is_nacl_mime_type =
@@ -702,154 +1030,160 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
         const bool is_pnacl_mime_type =
             actual_mime_type == nacl::kPnaclPluginMimeType;
         if (is_nacl_plugin || is_nacl_mime_type || is_pnacl_mime_type) {
-          bool is_nacl_unrestricted = false;
-          if (is_nacl_mime_type) {
-            is_nacl_unrestricted =
-                base::CommandLine::ForCurrentProcess()->HasSwitch(
-                    switches::kEnableNaCl);
-          } else if (is_pnacl_mime_type) {
-            is_nacl_unrestricted = true;
-          }
+          bool has_enable_nacl_switch =
+              base::CommandLine::ForCurrentProcess()->HasSwitch(
+                  switches::kEnableNaCl);
+          bool is_nacl_unrestricted =
+              has_enable_nacl_switch || is_pnacl_mime_type;
           GURL manifest_url;
           GURL app_url;
           if (is_nacl_mime_type || is_pnacl_mime_type) {
             // Normal NaCl/PNaCl embed. The app URL is the page URL.
             manifest_url = url;
-            app_url = frame->top()->document().url();
+            app_url = frame->GetDocument().Url();
           } else {
             // NaCl is being invoked as a content handler. Look up the NaCl
             // module using the MIME type. The app URL is the manifest URL.
             manifest_url = GetNaClContentHandlerURL(actual_mime_type, info);
             app_url = manifest_url;
           }
-          const Extension* extension =
+          bool is_module_allowed = false;
+          const extensions::Extension* extension =
               extensions::RendererExtensionRegistry::Get()
                   ->GetExtensionOrAppByURL(manifest_url);
-          if (!IsNaClAllowed(manifest_url,
-                             app_url,
-                             is_nacl_unrestricted,
-                             extension,
-                             &params)) {
+          if (IsNaclAllowed()) {
+            if (extension) {
+              is_module_allowed =
+                  IsNativeNaClAllowed(app_url, is_nacl_unrestricted, extension);
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+              // Allow Terminal System App to load the SSH extension NaCl
+              // module.
+            } else if (IsTerminalSystemWebAppNaClPage(app_url)) {
+              is_module_allowed = true;
+#endif
+            } else {
+              WebDocument document = frame->GetDocument();
+              is_module_allowed =
+                  has_enable_nacl_switch ||
+                  (is_pnacl_mime_type &&
+                   blink::WebOriginTrials::isTrialEnabled(&document, "PNaCl"));
+            }
+          }
+          if (!is_module_allowed) {
             WebString error_message;
-            if (is_nacl_mime_type) {
+            if (!IsNaclAllowed()) {
+              error_message = "NaCl is disabled.";
+            } else if (is_nacl_mime_type) {
               error_message =
                   "Only unpacked extensions and apps installed from the Chrome "
                   "Web Store can load NaCl modules without enabling Native "
                   "Client in about:flags.";
             } else if (is_pnacl_mime_type) {
               error_message =
-                  "Portable Native Client must not be disabled in about:flags.";
+                  "PNaCl modules can only be used on the open web (non-app/"
+                  "extension) when the PNaCl Origin Trial is enabled";
             }
-            frame->addMessageToConsole(
-                WebConsoleMessage(WebConsoleMessage::LevelError,
-                                  error_message));
+            frame->AddMessageToConsole(WebConsoleMessage(
+                blink::mojom::ConsoleMessageLevel::kError, error_message));
             placeholder = create_blocked_plugin(
                 IDR_BLOCKED_PLUGIN_HTML,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
                 l10n_util::GetStringUTF16(IDS_NACL_PLUGIN_BLOCKED));
 #else
                 l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name));
 #endif
             break;
           }
+          ReportNaClAppType(is_pnacl_mime_type, extension);
+        }
+#endif  // BUILDFLAG(ENABLE_NACL) && BUILDFLAG(ENABLE_EXTENSIONS)
+
+        if (info.path.value() == ChromeContentClient::kPDFExtensionPluginPath) {
+          // Report PDF load metrics. Since the PDF plugin is comprised of an
+          // extension that loads a second plugin, avoid double counting by
+          // ignoring the creation of the second plugin.
+          bool is_main_frame_plugin_document =
+              render_frame->IsMainFrame() &&
+              render_frame->GetWebFrame()->GetDocument().IsPluginDocument();
+          ReportPDFLoadStatus(
+              is_main_frame_plugin_document
+                  ? PDFLoadStatus::kLoadedFullPagePdfWithPdfium
+                  : PDFLoadStatus::kLoadedEmbeddedPdfWithPdfium);
         }
-#endif  // !defined(DISABLE_NACL) && defined(ENABLE_EXTENSIONS)
 
-        // Delay loading plugins if prerendering.
-        // TODO(mmenke):  In the case of prerendering, feed into
+        // Delay loading plugins if no-state prefetching.
+        // TODO(mmenke):  In the case of NoStatePrefetch, feed into
         //                ChromeContentRendererClient::CreatePlugin instead, to
         //                reduce the chance of future regressions.
-        bool is_prerendering =
-            prerender::PrerenderHelper::IsPrerendering(render_frame);
-
-        bool power_saver_setting_on =
-            status ==
-            ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent;
-        PowerSaverInfo power_saver_info =
-            PowerSaverInfo::Get(render_frame, power_saver_setting_on, params,
-                                info, frame->document().url());
-        if (power_saver_info.blocked_for_background_tab || is_prerendering ||
-            !power_saver_info.poster_attribute.empty()) {
+        bool is_no_state_prefetching =
+            prerender::NoStatePrefetchHelper::IsPrefetching(render_frame);
+
+        if (is_no_state_prefetching) {
           placeholder = ChromePluginPlaceholder::CreateBlockedPlugin(
-              render_frame, frame, params, info, identifier, group_name,
-              power_saver_info.poster_attribute.empty()
-                  ? IDR_BLOCKED_PLUGIN_HTML
-                  : IDR_PLUGIN_POSTER_HTML,
-              l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name),
-              power_saver_info);
-          placeholder->set_blocked_for_prerendering(is_prerendering);
+              render_frame, params, info, identifier, group_name,
+              IDR_BLOCKED_PLUGIN_HTML,
+              l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name));
+          placeholder->set_blocked_for_prerendering(is_no_state_prefetching);
           placeholder->AllowLoading();
           break;
         }
 
-        std::unique_ptr<content::PluginInstanceThrottler> throttler;
-        if (power_saver_info.power_saver_enabled) {
-          throttler = PluginInstanceThrottler::Create();
-          // PluginPreroller manages its own lifetime.
-          new PluginPreroller(
-              render_frame, frame, params, info, identifier, group_name,
-              l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name),
-              throttler.get());
+#if BUILDFLAG(ENABLE_PDF)
+        if (info.path.value() == ChromeContentClient::kPDFInternalPluginPath) {
+          return pdf::CreateInternalPlugin(
+              std::move(params), render_frame,
+              std::make_unique<ChromePdfInternalPluginDelegate>());
         }
+#endif  // BUILDFLAG(ENABLE_PDF)
 
-        return render_frame->CreatePlugin(frame, info, params,
-                                          std::move(throttler));
+        return render_frame->CreatePlugin(info, params);
       }
-      case ChromeViewHostMsg_GetPluginInfo_Status::kDisabled: {
+      case chrome::mojom::PluginStatus::kDisabled: {
         PluginUMAReporter::GetInstance()->ReportPluginDisabled(orig_mime_type,
                                                                url);
+        if (info.path.value() == ChromeContentClient::kPDFExtensionPluginPath) {
+          ReportPDFLoadStatus(
+              PDFLoadStatus::kShowedDisabledPluginPlaceholderForEmbeddedPdf);
+
+          return PDFPluginPlaceholder::CreatePDFPlaceholder(render_frame,
+                                                            params)
+              ->plugin();
+        }
+
         placeholder = create_blocked_plugin(
             IDR_DISABLED_PLUGIN_HTML,
             l10n_util::GetStringFUTF16(IDS_PLUGIN_DISABLED, group_name));
         break;
       }
-      case ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked: {
-#if defined(ENABLE_PLUGIN_INSTALLATION)
-        placeholder = create_blocked_plugin(
-            IDR_BLOCKED_PLUGIN_HTML,
-            l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED, group_name));
-        placeholder->AllowLoading();
-        render_frame->Send(new ChromeViewHostMsg_BlockedOutdatedPlugin(
-            render_frame->GetRoutingID(), placeholder->CreateRoutingId(),
-            identifier));
-#else
-        NOTREACHED();
-#endif
-        break;
-      }
-      case ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedDisallowed: {
-        placeholder = create_blocked_plugin(
-            IDR_BLOCKED_PLUGIN_HTML,
-            l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED, group_name));
-        break;
-      }
-      case ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized: {
+      case chrome::mojom::PluginStatus::kUnauthorized: {
         placeholder = create_blocked_plugin(
             IDR_BLOCKED_PLUGIN_HTML,
             l10n_util::GetStringFUTF16(IDS_PLUGIN_NOT_AUTHORIZED, group_name));
         placeholder->AllowLoading();
-        render_frame->Send(new ChromeViewHostMsg_BlockedUnauthorizedPlugin(
-            render_frame->GetRoutingID(), group_name, identifier));
-        observer->DidBlockContentType(content_type, group_name);
+        mojo::AssociatedRemote<chrome::mojom::PluginAuthHost> plugin_auth_host;
+        render_frame->GetRemoteAssociatedInterfaces()->GetInterface(
+            plugin_auth_host.BindNewEndpointAndPassReceiver());
+        plugin_auth_host->BlockedUnauthorizedPlugin(group_name, identifier);
+        content_settings_agent->DidBlockContentType(content_type);
         break;
       }
-      case ChromeViewHostMsg_GetPluginInfo_Status::kBlocked: {
+      case chrome::mojom::PluginStatus::kBlocked: {
         placeholder = create_blocked_plugin(
             IDR_BLOCKED_PLUGIN_HTML,
             l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name));
         placeholder->AllowLoading();
         RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Blocked"));
-        observer->DidBlockContentType(content_type, group_name);
+        content_settings_agent->DidBlockContentType(content_type);
         break;
       }
-      case ChromeViewHostMsg_GetPluginInfo_Status::kBlockedByPolicy: {
+      case chrome::mojom::PluginStatus::kBlockedByPolicy: {
         placeholder = create_blocked_plugin(
             IDR_BLOCKED_PLUGIN_HTML,
             l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED_BY_POLICY,
                                        group_name));
         RenderThread::Get()->RecordAction(
             UserMetricsAction("Plugin_BlockedByPolicy"));
-        observer->DidBlockContentType(content_type, group_name);
+        content_settings_agent->DidBlockContentType(content_type);
         break;
       }
     }
@@ -857,7 +1191,7 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
   placeholder->SetStatus(status);
   return placeholder->plugin();
 }
-#endif  // defined(ENABLE_PLUGINS)
+#endif  // BUILDFLAG(ENABLE_PLUGINS)
 
 // For NaCl content handling plugins, the NaCl manifest is stored in an
 // additonal 'nacl' param associated with the MIME type.
@@ -866,14 +1200,11 @@ GURL ChromeContentRendererClient::GetNaClContentHandlerURL(
     const std::string& actual_mime_type,
     const content::WebPluginInfo& plugin) {
   // Look for the manifest URL among the MIME type's additonal parameters.
-  const char kNaClPluginManifestAttribute[] = "nacl";
-  base::string16 nacl_attr = ASCIIToUTF16(kNaClPluginManifestAttribute);
-  for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
-    if (plugin.mime_types[i].mime_type == actual_mime_type) {
-      const content::WebPluginMimeType& content_type = plugin.mime_types[i];
-      for (size_t i = 0; i < content_type.additional_param_names.size(); ++i) {
-        if (content_type.additional_param_names[i] == nacl_attr)
-          return GURL(content_type.additional_param_values[i]);
+  for (const auto& mime_type : plugin.mime_types) {
+    if (mime_type.mime_type == actual_mime_type) {
+      for (const auto& p : mime_type.additional_params) {
+        if (p.name == u"nacl")
+          return GURL(p.value);
       }
       break;
     }
@@ -881,314 +1212,295 @@ GURL ChromeContentRendererClient::GetNaClContentHandlerURL(
   return GURL();
 }
 
-#if !defined(DISABLE_NACL)
+void ChromeContentRendererClient::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 eliminting the "chrome" and
+  // "chrome_renderer" services. Spellcheck is (and should remain) the only
+  // consumer of this implementation.
+  RenderThread::Get()->BindHostReceiver(
+      mojo::GenericPendingReceiver(interface_name, std::move(interface_pipe)));
+}
+
+#if BUILDFLAG(ENABLE_NACL)
 //  static
-bool ChromeContentRendererClient::IsNaClAllowed(
-    const GURL& manifest_url,
+bool ChromeContentRendererClient::IsNativeNaClAllowed(
     const GURL& app_url,
     bool is_nacl_unrestricted,
-    const Extension* extension,
-    WebPluginParams* params) {
-  // Temporarily allow these whitelisted apps and WebUIs to use NaCl.
-  std::string app_url_host = app_url.host();
-  std::string manifest_url_path = manifest_url.path();
-
-  bool is_whitelisted_web_ui =
-      app_url.spec() == chrome::kChromeUIAppListStartPageURL;
-
-  bool is_photo_app =
-      // Whitelisted apps must be served over https.
-      app_url.SchemeIsCryptographic() && manifest_url.SchemeIsCryptographic() &&
-      (base::EndsWith(app_url_host, "plus.google.com",
-                      base::CompareCase::INSENSITIVE_ASCII) ||
-       base::EndsWith(app_url_host, "plus.sandbox.google.com",
-                      base::CompareCase::INSENSITIVE_ASCII)) &&
-      manifest_url.DomainIs("ssl.gstatic.com") &&
-      (manifest_url_path.find("s2/oz/nacl/") == 1 ||
-       manifest_url_path.find("photos/nacl/") == 1);
-
-  std::string manifest_fs_host;
-  if (manifest_url.SchemeIsFileSystem() && manifest_url.inner_url()) {
-    manifest_fs_host = manifest_url.inner_url()->host();
-  }
-  bool is_hangouts_app =
-      // Whitelisted apps must be served over secure scheme.
-      app_url.SchemeIsCryptographic() && manifest_url.SchemeIsFileSystem() &&
-      manifest_url.inner_url()->SchemeIsCryptographic() &&
-      (base::EndsWith(app_url_host, "talkgadget.google.com",
-                      base::CompareCase::INSENSITIVE_ASCII) ||
-       base::EndsWith(app_url_host, "plus.google.com",
-                      base::CompareCase::INSENSITIVE_ASCII) ||
-       base::EndsWith(app_url_host, "plus.sandbox.google.com",
-                      base::CompareCase::INSENSITIVE_ASCII) ||
-       base::EndsWith(app_url_host, "hangouts.google.com",
-                      base::CompareCase::INSENSITIVE_ASCII)) &&
-      // The manifest must be loaded from the host's FileSystem.
-      (manifest_fs_host == app_url_host);
-
-  bool is_whitelisted_app = is_photo_app || is_hangouts_app;
-
+    const extensions::Extension* extension) {
   bool is_invoked_by_webstore_installed_extension = false;
   bool is_extension_unrestricted = false;
   bool is_extension_force_installed = false;
-#if defined(ENABLE_EXTENSIONS)
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   bool is_extension_from_webstore = extension && extension->from_webstore();
 
-  bool is_invoked_by_extension = app_url.SchemeIs("chrome-extension");
-  bool is_invoked_by_hosted_app = extension &&
-      extension->is_hosted_app() &&
-      extension->web_extent().MatchesURL(app_url);
+  bool is_invoked_by_extension = app_url.SchemeIs(extensions::kExtensionScheme);
+  bool is_invoked_by_hosted_app = extension && extension->is_hosted_app() &&
+                                  extension->web_extent().MatchesURL(app_url);
 
-  is_invoked_by_webstore_installed_extension = is_extension_from_webstore &&
+  is_invoked_by_webstore_installed_extension =
+      is_extension_from_webstore &&
       (is_invoked_by_extension || is_invoked_by_hosted_app);
 
   // Allow built-in extensions and developer mode extensions.
-  is_extension_unrestricted = extension &&
-       (extensions::Manifest::IsUnpackedLocation(extension->location()) ||
-        extensions::Manifest::IsComponentLocation(extension->location()));
+  is_extension_unrestricted =
+      extension &&
+      (extensions::Manifest::IsUnpackedLocation(extension->location()) ||
+       extensions::Manifest::IsComponentLocation(extension->location()));
   // Allow extensions force installed by admin policy.
-  is_extension_force_installed = extension &&
-       extensions::Manifest::IsPolicyLocation(extension->location());
-#endif  // defined(ENABLE_EXTENSIONS)
+  is_extension_force_installed =
+      extension &&
+      extensions::Manifest::IsPolicyLocation(extension->location());
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
   // Allow NaCl under any of the following circumstances:
-  //  1) An app or URL is explictly whitelisted above.
-  //  2) An extension is loaded unpacked or built-in (component) to Chrome.
-  //  3) An extension is force installed by policy.
-  //  4) An extension is installed from the webstore, and invoked in that
+  //  1) An extension is loaded unpacked or built-in (component) to Chrome.
+  //  2) An extension is force installed by policy.
+  //  3) An extension is installed from the webstore, and invoked in that
   //     context (hosted app URL or chrome-extension:// scheme).
-  //  5) --enable-nacl is set.
-  bool is_nacl_allowed_by_location =
-      is_whitelisted_web_ui ||
-      is_whitelisted_app ||
-      is_extension_unrestricted ||
-      is_extension_force_installed ||
-      is_invoked_by_webstore_installed_extension;
+  //  4) --enable-nacl is set.
+  bool is_nacl_allowed_by_location = is_extension_unrestricted ||
+                                     is_extension_force_installed ||
+                                     is_invoked_by_webstore_installed_extension;
   bool is_nacl_allowed = is_nacl_allowed_by_location || is_nacl_unrestricted;
-  if (is_nacl_allowed) {
-    // Make sure that PPAPI 'dev' interfaces are only available for unpacked
-    // and component extensions.  Also allow dev interfaces when --enable-nacl
-    // is set, but do not allow --enable-nacl to provide dev interfaces to
-    // webstore installed and other normally allowed URLs.
-    WebString dev_attribute = WebString::fromUTF8("@dev");
-    if (is_extension_unrestricted ||
-        (is_nacl_unrestricted && !is_nacl_allowed_by_location)) {
-      // Add the special '@dev' attribute.
-      std::vector<base::string16> param_names;
-      std::vector<base::string16> param_values;
-      param_names.push_back(dev_attribute);
-      param_values.push_back(WebString());
-      AppendParams(
-          param_names,
-          param_values,
-          &params->attributeNames,
-          &params->attributeValues);
-    } else {
-      // If the params somehow contain '@dev', remove it.
-      size_t attribute_count = params->attributeNames.size();
-      for (size_t i = 0; i < attribute_count; ++i) {
-        if (params->attributeNames[i].equals(dev_attribute))
-          params->attributeNames[i] = WebString();
-      }
-    }
-  }
   return is_nacl_allowed;
 }
-#endif  // defined(DISABLE_NACL)
 
-bool ChromeContentRendererClient::HasErrorPage(int http_status_code,
-                                               std::string* error_domain) {
-  // Use an internal error page, if we have one for the status code.
-  if (!error_page::LocalizedError::HasStrings(
-          error_page::LocalizedError::kHttpErrorDomain, http_status_code)) {
-    return false;
+// static
+void ChromeContentRendererClient::ReportNaClAppType(
+    bool is_pnacl,
+    const extensions::Extension* extension) {
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused.
+  enum class NaClAppType {
+    kPNaClOpenWeb = 0,
+    kPNaClHostedApp = 1,
+    kPNaClPlatformApp = 2,
+    kPNaClLegacyPackagedApp = 3,
+    kPNaClMv2Extension = 4,
+    kPNaClMv3Extension = 5,
+    kPNaClLoginScreenMv2Extension = 6,
+    kPNaClLoginScreenMv3Extension = 7,
+    kNaClOpenWeb = 8,
+    kNaClHostedApp = 9,
+    kNaClPlatformApp = 10,
+    kNaClLegacyPackagedApp = 11,
+    kNaClMv2Extension = 12,
+    kNaClMv3Extension = 13,
+    kNaClLoginScreenMv2Extension = 14,
+    kNaClLoginScreenMv3Extension = 15,
+    kMaxValue = kNaClLoginScreenMv3Extension
+  };
+
+  // Not all combinations are allowed by default (e.g. kNaClOpenWeb), but they
+  // can be used with the --enable-nacl flag.
+  NaClAppType app_type =
+      is_pnacl ? NaClAppType::kPNaClOpenWeb : NaClAppType::kNaClOpenWeb;
+  if (extension) {
+    if (extension->is_extension()) {
+      if (extension->manifest_version() >= 3) {
+        app_type = is_pnacl ? NaClAppType::kPNaClMv3Extension
+                            : NaClAppType::kNaClMv3Extension;
+      } else {
+        app_type = is_pnacl ? NaClAppType::kPNaClMv2Extension
+                            : NaClAppType::kNaClMv2Extension;
+      }
+    } else if (extension->is_hosted_app()) {
+      app_type =
+          is_pnacl ? NaClAppType::kPNaClHostedApp : NaClAppType::kNaClHostedApp;
+    } else if (extension->is_legacy_packaged_app()) {
+      app_type = is_pnacl ? NaClAppType::kPNaClLegacyPackagedApp
+                          : NaClAppType::kNaClLegacyPackagedApp;
+    } else if (extension->is_platform_app()) {
+      app_type = is_pnacl ? NaClAppType::kPNaClPlatformApp
+                          : NaClAppType::kNaClPlatformApp;
+    } else if (extension->is_login_screen_extension()) {
+      if (extension->manifest_version() >= 3) {
+        app_type = is_pnacl ? NaClAppType::kPNaClLoginScreenMv3Extension
+                            : NaClAppType::kNaClLoginScreenMv3Extension;
+      } else {
+        app_type = is_pnacl ? NaClAppType::kPNaClLoginScreenMv2Extension
+                            : NaClAppType::kNaClLoginScreenMv2Extension;
+      }
+    } else {
+      // We found an extension that is not covered by any metric
+      NOTREACHED() << "Invalid NaCl usage in extension. Extension name: "
+                   << extension->name() << ", type: " << extension->GetType();
+    }
   }
 
-  *error_domain = error_page::LocalizedError::kHttpErrorDomain;
-  return true;
+  base::UmaHistogramEnumeration("NaCl.EmbedderType", app_type);
 }
+#endif  // BUILDFLAG(ENABLE_NACL)
 
-bool ChromeContentRendererClient::ShouldSuppressErrorPage(
+void ChromeContentRendererClient::PrepareErrorPage(
     content::RenderFrame* render_frame,
-    const GURL& url) {
-  // Unit tests for ChromeContentRendererClient pass a NULL RenderFrame here.
-  // Unfortunately it's very difficult to construct a mock RenderView, so skip
-  // this functionality in this case.
-  if (render_frame &&
-      NetErrorHelper::Get(render_frame)->ShouldSuppressErrorPage(url)) {
-    return true;
-  }
-  // Do not flash an error page if the Instant new tab page fails to load.
-  return SearchBouncer::GetInstance()->IsNewTabPage(url);
+    const blink::WebURLError& web_error,
+    const std::string& http_method,
+    content::mojom::AlternativeErrorPageOverrideInfoPtr
+        alternative_error_page_info,
+    std::string* error_html) {
+  NetErrorHelper::Get(render_frame)
+      ->PrepareErrorPage(
+          error_page::Error::NetError(
+              web_error.url(), web_error.reason(), web_error.extended_reason(),
+              web_error.resolve_error_info(), web_error.has_copy_in_cache()),
+          http_method == "POST", std::move(alternative_error_page_info),
+          error_html);
+
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+  SupervisedUserErrorPageControllerDelegateImpl::Get(render_frame)
+      ->PrepareForErrorPage();
+#endif
 }
 
-void ChromeContentRendererClient::GetNavigationErrorStrings(
+void ChromeContentRendererClient::PrepareErrorPageForHttpStatusError(
     content::RenderFrame* render_frame,
-    const WebURLRequest& failed_request,
-    const WebURLError& error,
-    std::string* error_html,
-    base::string16* error_description) {
-  const GURL failed_url = error.unreachableURL;
-
-  bool is_post = base::EqualsASCII(
-      base::StringPiece16(failed_request.httpMethod()), "POST");
-  bool is_ignoring_cache =
-      failed_request.getCachePolicy() == WebCachePolicy::BypassingCache;
-  if (error_html) {
-    NetErrorHelper::Get(render_frame)
-        ->GetErrorHTML(error, is_post, is_ignoring_cache, error_html);
-  }
+    const blink::WebURLError& error,
+    const std::string& http_method,
+    int http_status,
+    content::mojom::AlternativeErrorPageOverrideInfoPtr
+        alternative_error_page_info,
+    std::string* error_html) {
+  NetErrorHelper::Get(render_frame)
+      ->PrepareErrorPage(error_page::Error::HttpError(error.url(), http_status),
+                         http_method == "POST",
+                         std::move(alternative_error_page_info), error_html);
+}
 
-  if (error_description) {
-    *error_description = error_page::LocalizedError::GetErrorDetails(
-        error.domain.utf8(), error.reason, is_post);
-  }
+void ChromeContentRendererClient::PostSandboxInitialized() {
+#if BUILDFLAG(IS_CHROMEOS)
+  DCHECK(!main_thread_profiler_);
+  main_thread_profiler_ = ThreadProfiler::CreateAndStartOnMainThread();
+#endif  // BUILDFLAG(IS_CHROMEOS)
 }
 
-bool ChromeContentRendererClient::RunIdleHandlerWhenWidgetsHidden() {
-#if defined(ENABLE_EXTENSIONS)
-  return !IsStandaloneExtensionProcess();
-#else
-  return true;
-#endif
+void ChromeContentRendererClient::PostIOThreadCreated(
+    base::SingleThreadTaskRunner* io_thread_task_runner) {
+  io_thread_task_runner->PostTask(
+      FROM_HERE, base::BindOnce(&ThreadProfiler::StartOnChildThread,
+                                metrics::CallStackProfileParams::Thread::kIo));
 }
 
-bool ChromeContentRendererClient::
-    AllowTimerSuspensionWhenProcessBackgrounded() {
-#if defined(OS_ANDROID)
-  return true;
+void ChromeContentRendererClient::PostCompositorThreadCreated(
+    base::SingleThreadTaskRunner* compositor_thread_task_runner) {
+  compositor_thread_task_runner->PostTask(
+      FROM_HERE,
+      base::BindOnce(&ThreadProfiler::StartOnChildThread,
+                     metrics::CallStackProfileParams::Thread::kCompositor));
+  // Enable stack sampling for tracing.
+  // We pass in CreateCoreUnwindersFactory here since it lives in the chrome/
+  // layer while TracingSamplerProfiler is outside of chrome/.
+  compositor_thread_task_runner->PostTask(
+      FROM_HERE,
+      base::BindOnce(&tracing::TracingSamplerProfiler::
+                         CreateOnChildThreadWithCustomUnwinders,
+#if BUILDFLAG(IS_ANDROID)
+                     base::BindRepeating(&CreateCoreUnwindersFactory, false)));
 #else
-  return false;
-#endif
+                     base::BindRepeating(&CreateCoreUnwindersFactory)));
+#endif  // BUILDFLAG(IS_ANDROID)
+}
+
+bool ChromeContentRendererClient::RunIdleHandlerWhenWidgetsHidden() {
+  return !IsStandaloneContentExtensionProcess();
 }
 
 bool ChromeContentRendererClient::AllowPopup() {
-#if defined(ENABLE_EXTENSIONS)
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   return ChromeExtensionsRendererClient::GetInstance()->AllowPopup();
 #else
   return false;
 #endif
 }
 
-bool ChromeContentRendererClient::ShouldFork(WebLocalFrame* frame,
-                                             const GURL& url,
-                                             const std::string& http_method,
-                                             bool is_initial_navigation,
-                                             bool is_server_redirect,
-                                             bool* send_referrer) {
-  DCHECK(!frame->parent());
-
-  // If this is the Instant process, fork all navigations originating from the
-  // renderer.  The destination page will then be bucketed back to this Instant
-  // process if it is an Instant url, or to another process if not.  Conversely,
-  // fork if this is a non-Instant process navigating to an Instant url, so that
-  // such navigations can also be bucketed into an Instant renderer.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kInstantProcess) ||
-      SearchBouncer::GetInstance()->ShouldFork(url)) {
-    *send_referrer = true;
-    return true;
-  }
-
-  // For now, we skip the rest for POST submissions.  This is because
-  // http://crbug.com/101395 is more likely to cause compatibility issues
-  // with hosted apps and extensions than WebUI pages.  We will remove this
-  // check when cross-process POST submissions are supported.
-  if (http_method != "GET")
-    return false;
+bool ChromeContentRendererClient::ShouldNotifyServiceWorkerOnWebSocketActivity(
+    v8::Local<v8::Context> context) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  extensions::ScriptContext* script_context =
+      ChromeExtensionsRendererClient::GetInstance()
+          ->extension_dispatcher()
+          ->GetWorkerScriptContextSet()
+          ->GetContextByV8Context(context);
+  // Only notify on web socket activity if the service worker is the background
+  // service worker for an extension.
+  return script_context &&
+         ChromeExtensionsRendererClient::GetInstance()
+             ->ExtensionAPIEnabledForServiceWorkerScript(
+                 script_context->service_worker_scope(), script_context->url());
+#else
+  return false;
+#endif
+}
 
-  // If |url| matches one of the prerendered URLs, stop this navigation and try
-  // to swap in the prerendered page on the browser process. If the prerendered
-  // page no longer exists by the time the OpenURL IPC is handled, a normal
-  // navigation is attempted.
-  if (prerender_dispatcher_.get() &&
-      prerender_dispatcher_->IsPrerenderURL(url)) {
-    *send_referrer = true;
-    return true;
+blink::ProtocolHandlerSecurityLevel
+ChromeContentRendererClient::GetProtocolHandlerSecurityLevel(
+    const url::Origin& origin) {
+  if (origin.scheme() == chrome::kIsolatedAppScheme) {
+    return blink::ProtocolHandlerSecurityLevel::kSameOrigin;
   }
-
-#if defined(ENABLE_EXTENSIONS)
-  bool should_fork = ChromeExtensionsRendererClient::ShouldFork(
-      frame, url, is_initial_navigation, is_server_redirect, send_referrer);
-  if (should_fork)
-    return true;
-#endif  // defined(ENABLE_EXTENSIONS)
-
-  return false;
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  return ChromeExtensionsRendererClient::GetInstance()
+      ->GetProtocolHandlerSecurityLevel();
+#else
+  return blink::ProtocolHandlerSecurityLevel::kStrict;
+#endif
 }
 
-bool ChromeContentRendererClient::WillSendRequest(
-    WebFrame* frame,
+void ChromeContentRendererClient::WillSendRequest(
+    WebLocalFrame* frame,
     ui::PageTransition transition_type,
-    const GURL& url,
-    const GURL& first_party_for_cookies,
+    const blink::WebURL& url,
+    const net::SiteForCookies& site_for_cookies,
+    const url::Origin* initiator_origin,
     GURL* new_url) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   // 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 defined(ENABLE_EXTENSIONS)
-  if (ChromeExtensionsRendererClient::GetInstance()->WillSendRequest(
-          frame, transition_type, url, new_url)) {
-    return true;
-  }
+  ChromeExtensionsRendererClient::GetInstance()->WillSendRequest(
+      frame, transition_type, url, site_for_cookies, initiator_origin, new_url);
+  if (!new_url->is_empty())
+    return;
 #endif
 
-  const content::RenderView* render_view =
-      content::RenderView::FromWebView(frame->view());
-  SearchBox* search_box = SearchBox::Get(render_view);
-  if (search_box && url.SchemeIs(chrome::kChromeSearchScheme)) {
-    SearchBox::ImageSourceType type = SearchBox::NONE;
-    if (url.host() == chrome::kChromeUIFaviconHost)
-      type = SearchBox::FAVICON;
-    else if (url.host() == chrome::kChromeUILargeIconHost)
-      type = SearchBox::LARGE_ICON;
-    else if (url.host() == chrome::kChromeUIFallbackIconHost)
-      type = SearchBox::FALLBACK_ICON;
-    else if (url.host() == chrome::kChromeUIThumbnailHost)
-      type = SearchBox::THUMB;
-
-    if (type != SearchBox::NONE)
-      return search_box->GenerateImageURLFromTransientURL(url, type, new_url);
-  }
-
-  return false;
-}
+  if (!url.ProtocolIs(chrome::kChromeSearchScheme))
+    return;
 
-unsigned long long ChromeContentRendererClient::VisitedLinkHash(
-    const char* canonical_url, size_t length) {
-  return visited_link_slave_->ComputeURLFingerprint(canonical_url, length);
+#if !BUILDFLAG(IS_ANDROID)
+  SearchBox* search_box =
+      SearchBox::Get(content::RenderFrame::FromWebFrame(frame->LocalRoot()));
+  if (search_box) {
+    // Note: this GURL copy could be avoided if host() were added to WebURL.
+    GURL gurl(url);
+    if (gurl.host_piece() == chrome::kChromeUIFaviconHost)
+      search_box->GenerateImageURLFromTransientURL(url, new_url);
+  }
+#endif  // !BUILDFLAG(IS_ANDROID)
 }
 
-bool ChromeContentRendererClient::IsLinkVisited(unsigned long long link_hash) {
-  return visited_link_slave_->IsVisited(link_hash);
+bool ChromeContentRendererClient::IsPrefetchOnly(
+    content::RenderFrame* render_frame) {
+  return prerender::NoStatePrefetchHelper::IsPrefetching(render_frame);
 }
 
-blink::WebPrescientNetworking*
-ChromeContentRendererClient::GetPrescientNetworking() {
-  return prescient_networking_dispatcher_.get();
+uint64_t ChromeContentRendererClient::VisitedLinkHash(
+    std::string_view canonical_url) {
+  return chrome_observer_->visited_link_reader()->ComputeURLFingerprint(
+      canonical_url);
 }
 
-bool ChromeContentRendererClient::ShouldOverridePageVisibilityState(
-    const content::RenderFrame* render_frame,
-    blink::WebPageVisibilityState* override_state) {
-  if (!prerender::PrerenderHelper::IsPrerendering(render_frame))
-    return false;
-
-  *override_state = blink::WebPageVisibilityStatePrerender;
-  return true;
+bool ChromeContentRendererClient::IsLinkVisited(uint64_t link_hash) {
+  return chrome_observer_->visited_link_reader()->IsVisited(link_hash);
 }
 
-#if defined(ENABLE_SPELLCHECK)
-void ChromeContentRendererClient::SetSpellcheck(SpellCheck* spellcheck) {
-  RenderThread* thread = RenderThread::Get();
-  if (spellcheck_.get() && thread)
-    thread->RemoveObserver(spellcheck_.get());
-  spellcheck_.reset(spellcheck);
-  SpellCheckReplacer replacer(spellcheck_.get());
-  content::RenderView::ForEach(&replacer);
-  if (thread)
-    thread->AddObserver(spellcheck_.get());
+std::unique_ptr<blink::WebPrescientNetworking>
+ChromeContentRendererClient::CreatePrescientNetworking(
+    content::RenderFrame* render_frame) {
+  return std::make_unique<network_hints::WebPrescientNetworkingImpl>(
+      render_frame);
 }
-#endif
 
 bool ChromeContentRendererClient::IsExternalPepperPlugin(
     const std::string& module_name) {
@@ -1198,211 +1510,250 @@ bool ChromeContentRendererClient::IsExternalPepperPlugin(
   return module_name == "Native Client";
 }
 
-#if defined(ENABLE_PLUGINS) && defined(ENABLE_EXTENSIONS)
-bool ChromeContentRendererClient::IsExtensionOrSharedModuleWhitelisted(
-    const GURL& url, const std::set<std::string>& whitelist) {
+bool ChromeContentRendererClient::IsOriginIsolatedPepperPlugin(
+    const base::FilePath& plugin_path) {
+  // Hosting plugins in-process is inherently incompatible with attempting to
+  // process-isolate plugins from different origins.
+  auto* cmdline = base::CommandLine::ForCurrentProcess();
+  if (cmdline->HasSwitch(switches::kPpapiInProcess)) {
+    // The kPpapiInProcess switch should only be used by tests.  In particular,
+    // we expect that the PDF plugin should always be isolated in the product
+    // (and that the switch won't interfere with PDF isolation).
+    CHECK_NE(ChromeContentClient::kPDFInternalPluginPath, plugin_path.value());
+
+    return false;
+  }
+
+#if BUILDFLAG(ENABLE_NACL)
+  // Don't isolate the NaCl plugin (preserving legacy behavior).
+  if (plugin_path.value() == nacl::kInternalNaClPluginFileName)
+    return false;
+#endif
+
+  // Isolate all the other plugins (including the PDF plugin + test plugins).
+  return true;
+}
+
+#if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_EXTENSIONS)
+bool ChromeContentRendererClient::IsExtensionOrSharedModuleAllowed(
+    const GURL& url,
+    const std::set<std::string>& allowlist) {
   const extensions::ExtensionSet* extension_set =
       extensions::RendererExtensionRegistry::Get()->GetMainThreadExtensionSet();
-  return chrome::IsExtensionOrSharedModuleWhitelisted(url, extension_set,
-      whitelist);
+  return ::IsExtensionOrSharedModuleAllowed(url, extension_set, allowlist);
 }
 #endif
 
-blink::WebSpeechSynthesizer*
-ChromeContentRendererClient::OverrideSpeechSynthesizer(
-    blink::WebSpeechSynthesizerClient* client) {
-  return new TtsDispatcher(client);
+#if BUILDFLAG(ENABLE_SPELLCHECK)
+void ChromeContentRendererClient::InitSpellCheck() {
+  spellcheck_ = std::make_unique<SpellCheck>(this);
 }
+#endif
 
-bool ChromeContentRendererClient::AllowPepperMediaStreamAPI(
-    const GURL& url) {
-#if !defined(OS_ANDROID)
-  // Allow only the Hangouts app to use the MediaStream APIs. It's OK to check
-  // the whitelist in the renderer, since we're only preventing access until
-  // these APIs are public and stable.
-  std::string url_host = url.host();
-  if (url.SchemeIs("https") &&
-      (base::EndsWith(url_host, "talkgadget.google.com",
-                      base::CompareCase::INSENSITIVE_ASCII) ||
-       base::EndsWith(url_host, "plus.google.com",
-                      base::CompareCase::INSENSITIVE_ASCII) ||
-       base::EndsWith(url_host, "plus.sandbox.google.com",
-                      base::CompareCase::INSENSITIVE_ASCII)) &&
-      base::StartsWith(url.path(), "/hangouts/",
-                       base::CompareCase::INSENSITIVE_ASCII)) {
-    return true;
-  }
-  // Allow access for tests.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnablePepperTesting)) {
-    return true;
+ChromeRenderThreadObserver* ChromeContentRendererClient::GetChromeObserver()
+    const {
+  return chrome_observer_.get();
+}
+
+web_cache::WebCacheImpl* ChromeContentRendererClient::GetWebCache() {
+  return web_cache_impl_.get();
+}
+
+chrome::WebRtcLoggingAgentImpl*
+ChromeContentRendererClient::GetWebRtcLoggingAgent() {
+  if (!webrtc_logging_agent_impl_) {
+    webrtc_logging_agent_impl_ =
+        std::make_unique<chrome::WebRtcLoggingAgentImpl>();
   }
-#endif  // !defined(OS_ANDROID)
-  return false;
+  return webrtc_logging_agent_impl_.get();
 }
 
-void ChromeContentRendererClient::AddSupportedKeySystems(
-    std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems) {
-  AddChromeKeySystems(key_systems);
+#if BUILDFLAG(ENABLE_SPELLCHECK)
+SpellCheck* ChromeContentRendererClient::GetSpellCheck() {
+  return spellcheck_.get();
 }
+#endif  // BUILDFLAG(ENABLE_SPELLCHECK)
 
-bool ChromeContentRendererClient::ShouldReportDetailedMessageForSource(
-    const base::string16& source) const {
-#if defined(ENABLE_EXTENSIONS)
-  return extensions::IsSourceFromAnExtension(source);
+std::unique_ptr<blink::WebSocketHandshakeThrottleProvider>
+ChromeContentRendererClient::CreateWebSocketHandshakeThrottleProvider() {
+  return std::make_unique<WebSocketHandshakeThrottleProviderImpl>(
+      browser_interface_broker_.get());
+}
+
+void ChromeContentRendererClient::GetSupportedKeySystems(
+    media::GetSupportedKeySystemsCB cb) {
+#if BUILDFLAG(ENABLE_LIBRARY_CDMS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
+  GetChromeKeySystems(std::move(cb));
 #else
-  return false;
+  std::move(cb).Run({});
 #endif
 }
 
-bool ChromeContentRendererClient::ShouldGatherSiteIsolationStats() const {
-  // Site isolation stats are gathered currently for non-extension renderer
-  // processes running a normal web page from the Internet.
-  // TODO(nick): https://crbug.com/268640 Gather stats for extension processes
-  // too; we would need to check the extension's manifest to know which sites
-  // it's allowed to access.
-#if defined(ENABLE_EXTENSIONS)
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  return !command_line->HasSwitch(extensions::switches::kExtensionProcess);
+bool ChromeContentRendererClient::ShouldReportDetailedMessageForSource(
+    const std::u16string& source) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  return extensions::IsSourceFromAnExtension(source);
 #else
-  return true;
+  return false;
 #endif
 }
 
-blink::WebWorkerContentSettingsClientProxy*
-ChromeContentRendererClient::CreateWorkerContentSettingsClientProxy(
-    content::RenderFrame* render_frame,
-    WebFrame* frame) {
-  return new WorkerContentSettingsClientProxy(render_frame, frame);
+std::unique_ptr<blink::WebContentSettingsClient>
+ChromeContentRendererClient::CreateWorkerContentSettingsClient(
+    content::RenderFrame* render_frame) {
+  return std::make_unique<WorkerContentSettingsClient>(render_frame);
 }
 
-bool ChromeContentRendererClient::IsPluginAllowedToUseDevChannelAPIs() {
-#if defined(ENABLE_PLUGINS)
-  // Allow access for tests.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnablePepperTesting)) {
-    return true;
-  }
-
-  version_info::Channel channel = chrome::GetChannel();
-  // Allow dev channel APIs to be used on "Canary", "Dev", and "Unknown"
-  // releases of Chrome. Permitting "Unknown" allows these APIs to be used on
-  // Chromium builds as well.
-  return channel <= version_info::Channel::DEV;
-#else
-  return false;
-#endif
+#if BUILDFLAG(ENABLE_SPEECH_SERVICE)
+std::unique_ptr<media::SpeechRecognitionClient>
+ChromeContentRendererClient::CreateSpeechRecognitionClient(
+    content::RenderFrame* render_frame) {
+  return std::make_unique<ChromeSpeechRecognitionClient>(render_frame);
 }
+#endif  // BUILDFLAG(ENABLE_SPEECH_SERVICE)
 
 bool ChromeContentRendererClient::IsPluginAllowedToUseCameraDeviceAPI(
     const GURL& url) {
-#if defined(ENABLE_PLUGINS) && defined(ENABLE_EXTENSIONS)
+#if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_EXTENSIONS)
+#if BUILDFLAG(ENABLE_PPAPI)
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnablePepperTesting))
     return true;
+#endif  // BUILDFLAG(ENABLE_PPAPI)
 
-  if (IsExtensionOrSharedModuleWhitelisted(url, allowed_camera_device_origins_))
+  if (IsExtensionOrSharedModuleAllowed(url, allowed_camera_device_origins_))
     return true;
 #endif
 
   return false;
 }
 
-bool ChromeContentRendererClient::IsPluginAllowedToUseCompositorAPI(
-    const GURL& url) {
-#if defined(ENABLE_PLUGINS) && defined(ENABLE_EXTENSIONS)
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnablePepperTesting))
-    return true;
-  if (IsExtensionOrSharedModuleWhitelisted(url, allowed_compositor_origins_))
-    return true;
+void ChromeContentRendererClient::RunScriptsAtDocumentStart(
+    content::RenderFrame* render_frame) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentStart(
+      render_frame);
+  // |render_frame| might be dead by now.
+#endif
+}
 
-  version_info::Channel channel = chrome::GetChannel();
-  return channel <= version_info::Channel::DEV;
-#else
-  return false;
+void ChromeContentRendererClient::RunScriptsAtDocumentEnd(
+    content::RenderFrame* render_frame) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentEnd(
+      render_frame);
+  // |render_frame| might be dead by now.
 #endif
 }
 
-content::BrowserPluginDelegate*
-ChromeContentRendererClient::CreateBrowserPluginDelegate(
-    content::RenderFrame* render_frame,
-    const std::string& mime_type,
-    const GURL& original_url) {
-#if defined(ENABLE_EXTENSIONS)
-  return ChromeExtensionsRendererClient::CreateBrowserPluginDelegate(
-    render_frame, mime_type, original_url);
-#else
-  return nullptr;
+void ChromeContentRendererClient::RunScriptsAtDocumentIdle(
+    content::RenderFrame* render_frame) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentIdle(
+      render_frame);
+  // |render_frame| might be dead by now.
 #endif
 }
 
-void ChromeContentRendererClient::RecordRappor(const std::string& metric,
-                                               const std::string& sample) {
-  RenderThread::Get()->Send(new ChromeViewHostMsg_RecordRappor(metric, sample));
+void ChromeContentRendererClient::
+    SetRuntimeFeaturesDefaultsBeforeBlinkInitialization() {
+  // The performance manager service interfaces are provided by the chrome
+  // embedder only.
+  blink::WebRuntimeFeatures::EnablePerformanceManagerInstrumentation(true);
+
+  MaybeEnableWebShare();
+
+  if (base::FeatureList::IsEnabled(
+          autofill::features::kAutofillSharedAutofill)) {
+    blink::WebRuntimeFeatures::EnableSharedAutofill(true);
+  }
+
+  if (base::FeatureList::IsEnabled(subresource_filter::kAdTagging))
+    blink::WebRuntimeFeatures::EnableAdTagging(true);
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  // WebHID and WebUSB on service workers is only available in extensions.
+  if (IsStandaloneContentExtensionProcess()) {
+    if (base::FeatureList::IsEnabled(
+            features::kEnableWebUsbOnExtensionServiceWorker)) {
+      blink::WebRuntimeFeatures::EnableWebUSBOnServiceWorkers(true);
+    }
+#if !BUILDFLAG(IS_ANDROID)
+    if (base::FeatureList::IsEnabled(
+            features::kEnableWebHidOnExtensionServiceWorker)) {
+      blink::WebRuntimeFeatures::EnableWebHIDOnServiceWorkers(true);
+    }
+#endif  // !BUILDFLAG(IS_ANDROID)
+  }
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 }
 
-void ChromeContentRendererClient::RecordRapporURL(const std::string& metric,
-                                                  const GURL& url) {
-  RenderThread::Get()->Send(new ChromeViewHostMsg_RecordRapporURL(metric, url));
+bool ChromeContentRendererClient::AllowScriptExtensionForServiceWorker(
+    const url::Origin& script_origin) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  return script_origin.scheme() == extensions::kExtensionScheme;
+#else
+  return false;
+#endif
 }
 
-std::unique_ptr<blink::WebAppBannerClient>
-ChromeContentRendererClient::CreateAppBannerClient(
-    content::RenderFrame* render_frame) {
-  return std::unique_ptr<blink::WebAppBannerClient>(
-      new AppBannerClient(render_frame));
-}
-
-void ChromeContentRendererClient::AddImageContextMenuProperties(
-    const WebURLResponse& response,
-    std::map<std::string, std::string>* properties) {
-  DCHECK(properties);
-  WebString header_key(ASCIIToUTF16(
-      data_reduction_proxy::chrome_proxy_header()));
-  if (!response.httpHeaderField(header_key).isNull() &&
-      response.httpHeaderField(header_key).utf8().find(
-          data_reduction_proxy::chrome_proxy_lo_fi_directive()) !=
-              std::string::npos) {
-    (*properties)[data_reduction_proxy::chrome_proxy_header()] =
-        data_reduction_proxy::chrome_proxy_lo_fi_directive();
-  }
+void ChromeContentRendererClient::
+    WillInitializeServiceWorkerContextOnWorkerThread() {
+  // This is called on the service worker thread.
+  ThreadProfiler::StartOnChildThread(
+      metrics::CallStackProfileParams::Thread::kServiceWorker);
 }
 
-void ChromeContentRendererClient::RunScriptsAtDocumentStart(
-    content::RenderFrame* render_frame) {
-#if defined(ENABLE_EXTENSIONS)
-  ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentStart(
-      render_frame);
-  // |render_frame| might be dead by now.
+void ChromeContentRendererClient::
+    DidInitializeServiceWorkerContextOnWorkerThread(
+        blink::WebServiceWorkerContextProxy* context_proxy,
+        const GURL& service_worker_scope,
+        const GURL& script_url) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  ChromeExtensionsRendererClient::GetInstance()
+      ->extension_dispatcher()
+      ->DidInitializeServiceWorkerContextOnWorkerThread(
+          context_proxy, service_worker_scope, script_url);
 #endif
 }
 
-void ChromeContentRendererClient::RunScriptsAtDocumentEnd(
-    content::RenderFrame* render_frame) {
-#if defined(ENABLE_EXTENSIONS)
-  ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentEnd(
-      render_frame);
-  // |render_frame| might be dead by now.
+void ChromeContentRendererClient::WillEvaluateServiceWorkerOnWorkerThread(
+    blink::WebServiceWorkerContextProxy* context_proxy,
+    v8::Local<v8::Context> v8_context,
+    int64_t service_worker_version_id,
+    const GURL& service_worker_scope,
+    const GURL& script_url) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  ChromeExtensionsRendererClient::GetInstance()
+      ->extension_dispatcher()
+      ->WillEvaluateServiceWorkerOnWorkerThread(
+          context_proxy, v8_context, service_worker_version_id,
+          service_worker_scope, script_url);
 #endif
 }
 
-void
-ChromeContentRendererClient::DidInitializeServiceWorkerContextOnWorkerThread(
-    v8::Local<v8::Context> context,
-    const GURL& url) {
-#if defined(ENABLE_EXTENSIONS)
-  extensions::Dispatcher::DidInitializeServiceWorkerContextOnWorkerThread(
-      context, url);
+void ChromeContentRendererClient::DidStartServiceWorkerContextOnWorkerThread(
+    int64_t service_worker_version_id,
+    const GURL& service_worker_scope,
+    const GURL& script_url) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  ChromeExtensionsRendererClient::GetInstance()
+      ->extension_dispatcher()
+      ->DidStartServiceWorkerContextOnWorkerThread(
+          service_worker_version_id, service_worker_scope, script_url);
 #endif
 }
 
 void ChromeContentRendererClient::WillDestroyServiceWorkerContextOnWorkerThread(
     v8::Local<v8::Context> context,
-    const GURL& url) {
-#if defined(ENABLE_EXTENSIONS)
-  extensions::Dispatcher::WillDestroyServiceWorkerContextOnWorkerThread(context,
-                                                                        url);
+    int64_t service_worker_version_id,
+    const GURL& service_worker_scope,
+    const GURL& script_url) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  ChromeExtensionsRendererClient::GetInstance()
+      ->extension_dispatcher()
+      ->WillDestroyServiceWorkerContextOnWorkerThread(
+          context, service_worker_version_id, service_worker_scope, script_url);
 #endif
 }
 
@@ -1411,9 +1762,89 @@ void ChromeContentRendererClient::WillDestroyServiceWorkerContextOnWorkerThread(
 // information. Also, the enforcement of sending and binding UDP is already done
 // by chrome extension permission model.
 bool ChromeContentRendererClient::ShouldEnforceWebRTCRoutingPreferences() {
-#if defined(ENABLE_EXTENSIONS)
-  return !IsStandaloneExtensionProcess();
+  return !IsStandaloneContentExtensionProcess();
+}
+
+GURL ChromeContentRendererClient::OverrideFlashEmbedWithHTML(const GURL& url) {
+  if (!url.is_valid())
+    return GURL();
+
+  return FlashEmbedRewrite::RewriteFlashEmbedURL(url);
+}
+
+std::unique_ptr<blink::URLLoaderThrottleProvider>
+ChromeContentRendererClient::CreateURLLoaderThrottleProvider(
+    blink::URLLoaderThrottleProviderType provider_type) {
+  return URLLoaderThrottleProviderImpl::Create(provider_type, this,
+                                               browser_interface_broker_.get());
+}
+
+blink::WebFrame* ChromeContentRendererClient::FindFrame(
+    blink::WebLocalFrame* relative_to_frame,
+    const std::string& name) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  return ChromeExtensionsRendererClient::FindFrame(relative_to_frame, name);
 #else
+  return nullptr;
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+}
+
+bool ChromeContentRendererClient::IsSafeRedirectTarget(const GURL& from_url,
+                                                       const GURL& to_url) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  if (to_url.SchemeIs(extensions::kExtensionScheme)) {
+    const extensions::Extension* extension =
+        extensions::RendererExtensionRegistry::Get()->GetByID(to_url.host());
+    if (!extension)
+      return false;
+    // TODO(solomonkinard): Use initiator_origin and add tests.
+    if (extensions::WebAccessibleResourcesInfo::IsResourceWebAccessible(
+            extension, to_url.path(), nullptr)) {
+      return true;
+    }
+    return extension->guid() == from_url.host();
+  }
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
   return true;
+}
+
+void ChromeContentRendererClient::DidSetUserAgent(
+    const std::string& user_agent) {
+#if BUILDFLAG(ENABLE_PRINTING)
+  printing::SetAgent(user_agent);
+#endif
+}
+
+void ChromeContentRendererClient::AppendContentSecurityPolicy(
+    const blink::WebURL& url,
+    blink::WebVector<blink::WebContentSecurityPolicyHeader>* csp) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+#if BUILDFLAG(ENABLE_PDF)
+  // 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;
+#endif  // BUILDFLAG(ENABLE_PDF)
+
+  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});
 #endif
 }
diff --git a/samples/codelite-sample/README.md b/samples/codelite-sample/README.md
index 5cd1b36cc..7c1e4b946 100644
--- a/samples/codelite-sample/README.md
+++ b/samples/codelite-sample/README.md
@@ -1,2 +1,1 @@
-Canary sample taken from codelite https://github.com/eranif/codelite
-License applies as per LICENSE file in this folder
+Code under src/ taken from https://github.com/eranif/codelite, licensed under the GPL2.
diff --git a/samples/codelite-sample/simple.def b/samples/codelite-sample/simple.def
index 4e45c6b41..88c9bf035 100644
--- a/samples/codelite-sample/simple.def
+++ b/samples/codelite-sample/simple.def
@@ -3,7 +3,7 @@ src/*
 4
 Done processing src/pptable.cpp
 Done processing src/pptable.h
-Total errors found: 681
+Total errors found: 685
 
 src/pptable.cpp:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
 src/pptable.cpp:1:  Include the directory when naming header files  [build/include_subdir] [4]
@@ -605,6 +605,10 @@ src/pptable.cpp:660:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/pptable.cpp:661:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/pptable.cpp:662:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/pptable.cpp:663:  Tab found; better to use spaces  [whitespace/tab] [1]
+src/pptable.cpp:526:  Add #include <map> for map<>  [build/include_what_you_use] [4]
+src/pptable.cpp:592:  Add #include <vector> for vector<>  [build/include_what_you_use] [4]
+src/pptable.cpp:602:  Add #include <cstdio> for sprintf  [build/include_what_you_use] [4]
+src/pptable.cpp:648:  Add #include <string> for string  [build/include_what_you_use] [4]
 src/pptable.h:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
 src/pptable.h:1:  #ifndef header guard has wrong style, please use: SAMPLES_CODELITE_SAMPLE_SRC_PPTABLE_H_  [build/header_guard] [5]
 src/pptable.h:131:  #endif line should be "#endif  // SAMPLES_CODELITE_SAMPLE_SRC_PPTABLE_H_"  [build/header_guard] [5]
diff --git a/samples/protobuf-sample/README.md b/samples/protobuf-sample/README.md
index 9e5b33528..7e8e74605 100644
--- a/samples/protobuf-sample/README.md
+++ b/samples/protobuf-sample/README.md
@@ -1,3 +1,1 @@
-# VLC sample
-
-code taken for regression testing from https://github.com/protocolbuffers/protobuf
+Code under src/ taken from https://github.com/protocolbuffers/protobuf, licensed under the BSD 3-clause.
diff --git a/samples/protobuf-sample/simple.def b/samples/protobuf-sample/simple.def
index 6135da698..c9aa90f83 100644
--- a/samples/protobuf-sample/simple.def
+++ b/samples/protobuf-sample/simple.def
@@ -4,7 +4,7 @@ src/*
 Done processing src/descriptor.pb.cc
 Done processing src/descriptor.pb.h
 Done processing src/descriptor_unittest.cc
-Total errors found: 2643
+Total errors found: 2646
 
 src/descriptor.pb.cc:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
 src/descriptor.pb.cc:9:  Found C system header after C++ system header. Should be: descriptor.pb.h, c system, c++ system, other.  [build/include_order] [4]
@@ -1626,6 +1626,8 @@ src/descriptor.pb.cc:15142:  Lines should be <= 80 characters long  [whitespace/
 src/descriptor.pb.cc:15146:  Lines should be <= 80 characters long  [whitespace/line_length] [2]
 src/descriptor.pb.cc:15150:  Lines should be <= 80 characters long  [whitespace/line_length] [2]
 src/descriptor.pb.cc:15155:  Lines should be <= 80 characters long  [whitespace/line_length] [2]
+src/descriptor.pb.cc:14981:  Add #include <utility> for swap  [build/include_what_you_use] [4]
+src/descriptor.pb.cc:15069:  Add #include <string> for string  [build/include_what_you_use] [4]
 src/descriptor.pb.cc:5:  samples/protobuf-sample/src/descriptor.pb.cc should include its header file samples/protobuf-sample/src/descriptor.pb.h  [build/include] [5]
 src/descriptor.pb.h:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
 src/descriptor.pb.h:4:  #ifndef header guard has wrong style, please use: SAMPLES_PROTOBUF_SAMPLE_SRC_DESCRIPTOR_PB_H_  [build/header_guard] [5]
@@ -2646,7 +2648,8 @@ src/descriptor_unittest.cc:4548:  Closing ) should be moved to the previous line
 src/descriptor_unittest.cc:4984:  Lines should be <= 80 characters long  [whitespace/line_length] [2]
 src/descriptor_unittest.cc:4990:  Lines should be <= 80 characters long  [whitespace/line_length] [2]
 src/descriptor_unittest.cc:5125:  Closing ) should be moved to the previous line  [whitespace/parens] [2]
-src/descriptor_unittest.cc:5929:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
-src/descriptor_unittest.cc:5968:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
+src/descriptor_unittest.cc:5929:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [4]
+src/descriptor_unittest.cc:5968:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [4]
 src/descriptor_unittest.cc:6486:  Redundant blank line at the end of a code block should be deleted.  [whitespace/blank_line] [3]
+src/descriptor_unittest.cc:6437:  Add #include <string> for string  [build/include_what_you_use] [4]
 
diff --git a/samples/silly-sample/filters.def b/samples/silly-sample/filters.def
index e420e1527..43029f1d3 100644
--- a/samples/silly-sample/filters.def
+++ b/samples/silly-sample/filters.def
@@ -12,9 +12,9 @@ src/sillycode.cpp:0:  No copyright message found.  You should have a line: "Copy
 src/sillycode.cpp:3:  Found C system header after C++ system header. Should be: sillycode.h, c system, c++ system, other.  [build/include_order] [4]
 src/sillycode.cpp:14:  Is this a non-const reference? If so, make const or use a pointer: vector<string>& v  [runtime/references] [2]
 src/sillycode.cpp:40:  If/else bodies with multiple statements require braces  [readability/braces] [4]
-src/sillycode.cpp:66:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
-src/sillycode.cpp:76:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
-src/sillycode.cpp:85:  Constructors callable with one argument should be marked explicit.  [runtime/explicit] [5]
+src/sillycode.cpp:66:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [4]
+src/sillycode.cpp:76:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [4]
+src/sillycode.cpp:85:  Constructors callable with one argument should be marked explicit.  [runtime/explicit] [4]
 src/sillycode.cpp:118:  Is this a non-const reference? If so, make const or use a pointer: N::X& a  [runtime/references] [2]
 src/sillycode.cpp:118:  Is this a non-const reference? If so, make const or use a pointer: N::X& b  [runtime/references] [2]
 src/sillycode.cpp:123:  Is this a non-const reference? If so, make const or use a pointer: N::X& a  [runtime/references] [2]
diff --git a/samples/silly-sample/includeorder_cfirst.def b/samples/silly-sample/includeorder_cfirst.def
index 05e8e664c..b7ea51de5 100644
--- a/samples/silly-sample/includeorder_cfirst.def
+++ b/samples/silly-sample/includeorder_cfirst.def
@@ -2,7 +2,7 @@
 1
 3
 Done processing src/sillycode.cpp
-Total errors found: 106
+Total errors found: 111
 
 src/sillycode.cpp:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
 src/sillycode.cpp:8:  public: should be indented +1 space inside class Date  [whitespace/indent] [3]
@@ -20,15 +20,15 @@ src/sillycode.cpp:64:  public: should be indented +1 space inside class X  [whit
 src/sillycode.cpp:65:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/sillycode.cpp:65:  At least two spaces is best between code and comments  [whitespace/comments] [2]
 src/sillycode.cpp:66:  Tab found; better to use spaces  [whitespace/tab] [1]
-src/sillycode.cpp:66:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
+src/sillycode.cpp:66:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [4]
 src/sillycode.cpp:74:  public: should be indented +1 space inside class X2  [whitespace/indent] [3]
 src/sillycode.cpp:75:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/sillycode.cpp:76:  Tab found; better to use spaces  [whitespace/tab] [1]
-src/sillycode.cpp:76:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
+src/sillycode.cpp:76:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [4]
 src/sillycode.cpp:80:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/sillycode.cpp:80:  At least two spaces is best between code and comments  [whitespace/comments] [2]
 src/sillycode.cpp:84:  public: should be indented +1 space inside class X3  [whitespace/indent] [3]
-src/sillycode.cpp:85:  Constructors callable with one argument should be marked explicit.  [runtime/explicit] [5]
+src/sillycode.cpp:85:  Constructors callable with one argument should be marked explicit.  [runtime/explicit] [4]
 src/sillycode.cpp:86:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/sillycode.cpp:86:  Lines should be <= 80 characters long  [whitespace/line_length] [2]
 src/sillycode.cpp:94:  public: should be indented +1 space inside class Foo  [whitespace/indent] [3]
@@ -110,4 +110,9 @@ src/sillycode.cpp:257:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/sillycode.cpp:257:  At least two spaces is best between code and comments  [whitespace/comments] [2]
 src/sillycode.cpp:260:  Empty loop bodies should use {} or continue  [whitespace/empty_loop_body] [5]
 src/sillycode.cpp:260:  At least two spaces is best between code and comments  [whitespace/comments] [2]
+src/sillycode.cpp:126:  Add #include <utility> for swap  [build/include_what_you_use] [4]
+src/sillycode.cpp:168:  Add #include <memory> for unique_ptr<>  [build/include_what_you_use] [4]
+src/sillycode.cpp:224:  Add #include <limits> for numeric_limits<>  [build/include_what_you_use] [4]
+src/sillycode.cpp:237:  Add #include <string> for string  [build/include_what_you_use] [4]
+src/sillycode.cpp:244:  Add #include <iostream> for cout  [build/include_what_you_use] [4]
 
diff --git a/samples/silly-sample/sed.def b/samples/silly-sample/sed.def
index 7a0ff19fb..a9e70262b 100644
--- a/samples/silly-sample/sed.def
+++ b/samples/silly-sample/sed.def
@@ -23,15 +23,15 @@ sed -i '208s/\([^ ]\){/\1 {/' src/sillycode.cpp # Missing space before {  [white
 # src/sillycode.cpp:65:  "Tab found; better to use spaces"  [whitespace/tab] [1]
 # src/sillycode.cpp:65:  "At least two spaces is best between code and comments"  [whitespace/comments] [2]
 # src/sillycode.cpp:66:  "Tab found; better to use spaces"  [whitespace/tab] [1]
-# src/sillycode.cpp:66:  "Single-parameter constructors should be marked explicit."  [runtime/explicit] [5]
+# src/sillycode.cpp:66:  "Single-parameter constructors should be marked explicit."  [runtime/explicit] [4]
 # src/sillycode.cpp:74:  "public: should be indented +1 space inside class X2"  [whitespace/indent] [3]
 # src/sillycode.cpp:75:  "Tab found; better to use spaces"  [whitespace/tab] [1]
 # src/sillycode.cpp:76:  "Tab found; better to use spaces"  [whitespace/tab] [1]
-# src/sillycode.cpp:76:  "Single-parameter constructors should be marked explicit."  [runtime/explicit] [5]
+# src/sillycode.cpp:76:  "Single-parameter constructors should be marked explicit."  [runtime/explicit] [4]
 # src/sillycode.cpp:80:  "Tab found; better to use spaces"  [whitespace/tab] [1]
 # src/sillycode.cpp:80:  "At least two spaces is best between code and comments"  [whitespace/comments] [2]
 # src/sillycode.cpp:84:  "public: should be indented +1 space inside class X3"  [whitespace/indent] [3]
-# src/sillycode.cpp:85:  "Constructors callable with one argument should be marked explicit."  [runtime/explicit] [5]
+# src/sillycode.cpp:85:  "Constructors callable with one argument should be marked explicit."  [runtime/explicit] [4]
 # src/sillycode.cpp:86:  "Tab found; better to use spaces"  [whitespace/tab] [1]
 # src/sillycode.cpp:86:  "Lines should be <= 80 characters long"  [whitespace/line_length] [2]
 # src/sillycode.cpp:94:  "public: should be indented +1 space inside class Foo"  [whitespace/indent] [3]
@@ -109,4 +109,9 @@ sed -i '208s/\([^ ]\){/\1 {/' src/sillycode.cpp # Missing space before {  [white
 # src/sillycode.cpp:257:  "At least two spaces is best between code and comments"  [whitespace/comments] [2]
 # src/sillycode.cpp:260:  "Empty loop bodies should use {} or continue"  [whitespace/empty_loop_body] [5]
 # src/sillycode.cpp:260:  "At least two spaces is best between code and comments"  [whitespace/comments] [2]
+# src/sillycode.cpp:126:  "Add #include <utility> for swap"  [build/include_what_you_use] [4]
+# src/sillycode.cpp:168:  "Add #include <memory> for unique_ptr<>"  [build/include_what_you_use] [4]
+# src/sillycode.cpp:224:  "Add #include <limits> for numeric_limits<>"  [build/include_what_you_use] [4]
+# src/sillycode.cpp:237:  "Add #include <string> for string"  [build/include_what_you_use] [4]
+# src/sillycode.cpp:244:  "Add #include <iostream> for cout"  [build/include_what_you_use] [4]
 
diff --git a/samples/silly-sample/simple.def b/samples/silly-sample/simple.def
index 5b1147860..adcd44ef7 100644
--- a/samples/silly-sample/simple.def
+++ b/samples/silly-sample/simple.def
@@ -2,7 +2,7 @@ src/*.cpp
 1
 3
 Done processing src/sillycode.cpp
-Total errors found: 107
+Total errors found: 112
 
 src/sillycode.cpp:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
 src/sillycode.cpp:3:  Found C system header after C++ system header. Should be: sillycode.h, c system, c++ system, other.  [build/include_order] [4]
@@ -21,15 +21,15 @@ src/sillycode.cpp:64:  public: should be indented +1 space inside class X  [whit
 src/sillycode.cpp:65:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/sillycode.cpp:65:  At least two spaces is best between code and comments  [whitespace/comments] [2]
 src/sillycode.cpp:66:  Tab found; better to use spaces  [whitespace/tab] [1]
-src/sillycode.cpp:66:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
+src/sillycode.cpp:66:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [4]
 src/sillycode.cpp:74:  public: should be indented +1 space inside class X2  [whitespace/indent] [3]
 src/sillycode.cpp:75:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/sillycode.cpp:76:  Tab found; better to use spaces  [whitespace/tab] [1]
-src/sillycode.cpp:76:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
+src/sillycode.cpp:76:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [4]
 src/sillycode.cpp:80:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/sillycode.cpp:80:  At least two spaces is best between code and comments  [whitespace/comments] [2]
 src/sillycode.cpp:84:  public: should be indented +1 space inside class X3  [whitespace/indent] [3]
-src/sillycode.cpp:85:  Constructors callable with one argument should be marked explicit.  [runtime/explicit] [5]
+src/sillycode.cpp:85:  Constructors callable with one argument should be marked explicit.  [runtime/explicit] [4]
 src/sillycode.cpp:86:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/sillycode.cpp:86:  Lines should be <= 80 characters long  [whitespace/line_length] [2]
 src/sillycode.cpp:94:  public: should be indented +1 space inside class Foo  [whitespace/indent] [3]
@@ -111,4 +111,9 @@ src/sillycode.cpp:257:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/sillycode.cpp:257:  At least two spaces is best between code and comments  [whitespace/comments] [2]
 src/sillycode.cpp:260:  Empty loop bodies should use {} or continue  [whitespace/empty_loop_body] [5]
 src/sillycode.cpp:260:  At least two spaces is best between code and comments  [whitespace/comments] [2]
+src/sillycode.cpp:126:  Add #include <utility> for swap  [build/include_what_you_use] [4]
+src/sillycode.cpp:168:  Add #include <memory> for unique_ptr<>  [build/include_what_you_use] [4]
+src/sillycode.cpp:224:  Add #include <limits> for numeric_limits<>  [build/include_what_you_use] [4]
+src/sillycode.cpp:237:  Add #include <string> for string  [build/include_what_you_use] [4]
+src/sillycode.cpp:244:  Add #include <iostream> for cout  [build/include_what_you_use] [4]
 
diff --git a/samples/v8-sample/LICENSE b/samples/v8-sample/LICENSE
index 4d04acd2c..bbad26627 100644
--- a/samples/v8-sample/LICENSE
+++ b/samples/v8-sample/LICENSE
@@ -1,4 +1,4 @@
-Copyright 2006-2011, the V8 project authors. All rights reserved.
+Copyright 2014, 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:
@@ -24,4 +24,3 @@ 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/samples/v8-sample/README.md b/samples/v8-sample/README.md
index 7cf07c7b6..640fe4482 100644
--- a/samples/v8-sample/README.md
+++ b/samples/v8-sample/README.md
@@ -1,3 +1,1 @@
-# V8 sample
-
-code taken for regression testing from https://github.com/v8/v8
+Code under src/ taken from https://github.com/v8/v8, licensed under the BSD 3-clause.
diff --git a/samples/vlc-sample/README.md b/samples/vlc-sample/README.md
index f9177bcab..d36093e13 100644
--- a/samples/vlc-sample/README.md
+++ b/samples/vlc-sample/README.md
@@ -1,3 +1,1 @@
-# VLC sample
-
-code taken for regression testing from https://github.com/videolan/vlc
+Code under src/ taken from https://github.com/videolan/vlc, licensed under the GPL2.
diff --git a/samples/vlc-sample/simple.def b/samples/vlc-sample/simple.def
index 174819ed7..19c956337 100644
--- a/samples/vlc-sample/simple.def
+++ b/samples/vlc-sample/simple.def
@@ -4,7 +4,7 @@ src/*
 Done processing src/libvlc.c
 Done processing src/libvlc.h
 Done processing src/missing.c
-Total errors found: 601
+Total errors found: 602
 
 src/libvlc.c:41:  Found C system header after other header. Should be: libvlc.h, c system, c++ system, other.  [build/include_order] [4]
 src/libvlc.c:47:  Found C system header after other header. Should be: libvlc.h, c system, c++ system, other.  [build/include_order] [4]
@@ -367,6 +367,7 @@ src/libvlc.c:627:  Missing space before ( in if(  [whitespace/parens] [5]
 src/libvlc.c:629:  Extra space after ( in function call  [whitespace/parens] [4]
 src/libvlc.c:629:  Extra space before )  [whitespace/parens] [2]
 src/libvlc.c:640:  { should almost always be at the end of the previous line  [whitespace/braces] [4]
+src/libvlc.c:223:  Add #include <cstdio> for fclose  [build/include_what_you_use] [4]
 src/libvlc.h:0:  No #ifndef header guard found, suggested CPP variable is: SAMPLES_VLC_SAMPLE_SRC_LIBVLC_H_  [build/header_guard] [5]
 src/libvlc.h:34:  Extra space before ( in function call  [whitespace/parens] [4]
 src/libvlc.h:35:  Extra space before ( in function call  [whitespace/parens] [4]
diff --git a/setup.cfg b/setup.cfg
index 636753943..dbe6220dd 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -4,7 +4,7 @@ test = pytest
 [tool:pytest]
 python_files = *test.py
 testpaths = .
+required_plugins = pytest-cov pytest-timeout
+timeout = 64
 # running with tox reports only 75%
-addopts = --cov-fail-under=75 --cov=cpplint
-filterwarnings =
-    ignore:.*:DeprecationWarning
+addopts = --color=yes --cov-fail-under=75 --cov=cpplint
diff --git a/setup.py b/setup.py
index 0297e7467..a567f0231 100755
--- a/setup.py
+++ b/setup.py
@@ -1,41 +1,8 @@
 #! /usr/bin/env python
+from setuptools import setup
+import cpplint
 
-from setuptools import setup, Command
-from subprocess import check_call
-from distutils.spawn import find_executable
-import cpplint as cpplint
-
-class Cmd(Command):
-    '''
-    Superclass for other commands to run via setup.py, declared in setup.cfg.
-    These commands will auto-install setup_requires in a temporary folder.
-    '''
-    user_options = [
-      ('executable', 'e', 'The executable to use for the command')
-    ]
-
-    def initialize_options(self):
-        self.executable = find_executable(self.executable)
-
-    def finalize_options(self):
-        pass
-
-    def execute(self, *k):
-        check_call((self.executable,) + k)
-
-
-class Lint(Cmd):
-    '''run with python setup.py lint'''
-    description = 'Run linting of the code'
-    user_options = Cmd.user_options + [
-      ('jobs', 'j', 'Use multiple processes to speed up the linting')
-    ]
-    executable = 'pylint'
-
-    def run(self):
-        self.execute('cpplint.py')
-
-# some pip versions bark on comments (e.g. on travis)
+# some pip versions bark on comments
 def read_without_comments(filename):
     with open(filename) as f:
         return [line for line in f.read().splitlines() if not len(line) == 0 and not line.startswith('#')]
@@ -57,32 +24,27 @@ def read_without_comments(filename):
       keywords=['lint', 'python', 'c++'],
       maintainer='cpplint Developers',
       maintainer_email='see_github@nospam.com',
-      classifiers=['Programming Language :: Python',
-                   'Programming Language :: Python :: 2',
-                   'Programming Language :: Python :: 2.7',
-                   'Programming Language :: Python :: 3',
-                   'Programming Language :: Python :: 3.6',
+      classifiers=['Development Status :: 5 - Production/Stable',
+                   'Environment :: Console',
+                   'Intended Audience :: End Users/Desktop',
+                   'License :: Freely Distributable',
+                   'License :: OSI Approved :: BSD License',
+                   'Natural Language :: English',
+                   'Programming Language :: Python :: 3 :: Only',
                    'Programming Language :: Python :: 3.7',
                    'Programming Language :: Python :: 3.8',
                    'Programming Language :: Python :: 3.9',
                    'Programming Language :: Python :: 3.10',
+                   'Programming Language :: Python :: 3.11',
+                   'Programming Language :: Python :: 3.12',
                    'Programming Language :: C++',
-                   'Development Status :: 5 - Production/Stable',
-                   'Environment :: Console',
-                   'Topic :: Software Development :: Quality Assurance',
-                   'License :: Freely Distributable'],
+                   'Topic :: Software Development :: Quality Assurance'],
       description='Automated checker to ensure C++ files follow Google\'s style guide',
       long_description=open('README.rst').read(),
       license='BSD-3-Clause',
-      setup_requires=[
-          "pytest-runner==5.2"
-      ],
       tests_require=test_required,
       # extras_require allow pip install .[dev]
       extras_require={
           'test': test_required,
           'dev': read_without_comments('dev-requirements') + test_required
-      },
-      cmdclass={
-          'lint': Lint
       })
diff --git a/tox.ini b/tox.ini
index 400f52895..5994a66b1 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,24 +1,20 @@
-# also see gitlab ci.yml
 [tox]
-envlist = py39, py310, py312, pypy3
+envlist = py37, py38, py39, py311, py312, pypy3
+skip_missing_interpreters = true
 
 [gh-actions]
 python =
+    3.7: py37
+    3.8: py38
     3.9: py39
     3.10: py310
     3.12: py312
     pypy3.10: pypy3
 
 [testenv]
-deps =
-  flake8>=4.0.1
-  radon>=2.4.0
-  pylint>=2.11.0
-  flake8-polyfill
-  pytest
-  setuptools==58.2.0
+extras = dev
 
 commands =
-  {envpython} setup.py test
-  {envpython} setup.py lint
-  {envpython} -m flake8
\ No newline at end of file
+  {envpython} -m pytest {posargs:}
+  {envpython} -m pylint cpplint.py
+  {envpython} -m flake8 cpplint.py


Test patch:
diff --git a/cpplint_clitest.py b/cpplint_clitest.py
index 850aea402..efcf7d270 100755
--- a/cpplint_clitest.py
+++ b/cpplint_clitest.py
@@ -31,17 +31,19 @@
 
 """Command Line interface integration test for cpplint.py."""
 
+import glob
 import os
 import sys
 import subprocess
 import unittest
 import shutil
 import tempfile
+from pytest import mark
 from testfixtures import compare
 
 BASE_CMD = sys.executable + ' ' + os.path.abspath('./cpplint.py ')
 
-def RunShellCommand(cmd, cwd='.'):
+def RunShellCommand(cmd: str, args: str, cwd='.'):
     """
     executes a command
     :param cmd: A string to execute.
@@ -51,7 +53,7 @@ def RunShellCommand(cmd, cwd='.'):
     stdout_target = subprocess.PIPE
     stderr_target = subprocess.PIPE
 
-    proc = subprocess.Popen(cmd,
+    proc = subprocess.Popen(cmd + ' ' + args,
                             shell=True,
                             cwd=cwd,
                             stdout=stdout_target,
@@ -60,7 +62,10 @@ def RunShellCommand(cmd, cwd='.'):
 
     # Make output system-agnostic, aka support Windows
     if os.sep == '\\':
-        out, err = out.replace(b'\\', b'/'), err.replace(b'\\', b'/')
+        # TODO: Support scenario with multiple folder inputs
+        win_path = (os.path.dirname(args.split(' ')[-1]) + '\\').encode()
+        good_path = win_path.replace(b'\\', b'/')
+        out, err = out.replace(win_path, good_path), err.replace(win_path, good_path)
     if os.linesep == '\r\n':
         out, err = out.replace(b'\r\n', b'\n'), err.replace(b'\r\n', b'\n')
 
@@ -71,7 +76,7 @@ def RunShellCommand(cmd, cwd='.'):
 class UsageTest(unittest.TestCase):
 
     def testHelp(self):
-        (status, out, err) = RunShellCommand(BASE_CMD + ' --help')
+        (status, out, err) = RunShellCommand(BASE_CMD, '--help')
         self.assertEqual(0, status)
         self.assertEqual(b'', out)
         self.assertTrue(err.startswith(b'\nSyntax: cpplint'))
@@ -132,8 +137,17 @@ def _checkDef(self, path):
         with open(path, 'rb') as filehandle:
             datalines = filehandle.readlines()
             stdoutLines = int(datalines[2])
+            filenames = datalines[0].decode('utf8').strip()
+            args, _, filenames = filenames.rpartition(" ")
+            if '*' in filenames:
+                rel_cwd = os.path.dirname(path)
+                filenames = ' '.join(
+                    filename[len(rel_cwd)+1:]
+                    for filename in glob.glob(rel_cwd + '/' + filenames)
+                )
+            args += ' ' + filenames
             self._runAndCheck(path,
-                              datalines[0].decode('utf8').strip(),
+                              args,
                               int(datalines[1]),
                               [line.decode('utf8').strip() for line in datalines[3:3 + stdoutLines]],
                               [line.decode('utf8').strip() for line in datalines[3 + stdoutLines:]])
@@ -147,11 +161,11 @@ def _runAndCheck(
             expected_err
     ):
         rel_cwd = os.path.dirname(definition_file)
-        cmd = BASE_CMD + self.get_extra_command_args(rel_cwd) + args
+        cmd = BASE_CMD + self.get_extra_command_args(rel_cwd)
         cwd = os.path.join(self._root, rel_cwd)
         # command to reproduce, do not forget first two lines have special meaning
-        print("\ncd " + cwd + " && " + cmd + " 2> <filename>")
-        (status, out, err) = RunShellCommand(cmd, cwd)
+        print("\ncd " + cwd + " && " + cmd + ' '  + args + " 2> <filename>")
+        (status, out, err) = RunShellCommand(cmd, args, cwd)
         self.assertEqual(expected_status, status, 'bad command status %s' % status)
         prefix = 'Failed check in %s comparing to %s for command: %s' % (cwd, definition_file, cmd)
         compare('\n'.join(expected_err), err.decode('utf8'), prefix=prefix, show_whitespace=True)
@@ -179,6 +193,7 @@ def testCfgFileSample(self):
     def testBoostSample(self):
         self.checkAllInFolder('./samples/boost-sample', 4)
 
+    @mark.timeout(180)
     def testProtobufSample(self):
         self.checkAllInFolder('./samples/protobuf-sample', 1)
 
diff --git a/cpplint_unittest.py b/cpplint_unittest.py
index fc96e6123..b8a9c1724 100755
--- a/cpplint_unittest.py
+++ b/cpplint_unittest.py
@@ -35,6 +35,7 @@
 
 import codecs
 import os
+import platform
 import random
 import re
 import shutil
@@ -42,6 +43,7 @@
 import sys
 import tempfile
 import unittest
+
 import pytest
 
 import cpplint
@@ -66,13 +68,13 @@ def __init__(self, assert_fn):
     self._errors = []
     cpplint.ResetNolintSuppressions()
 
-  def __call__(self, unused_filename, linenum,
+  def __call__(self, filename, linenum,
                category, confidence, message):
     self._assert_fn(category in self._ERROR_CATEGORIES,
                     'Message "%s" has category "%s",'
                     ' which is not in _ERROR_CATEGORIES' % (message, category))
     self._SEEN_ERROR_CATEGORIES[category] = 1
-    if cpplint._ShouldPrintError(category, confidence, linenum):
+    if cpplint._ShouldPrintError(category, confidence, filename, linenum):
       self._errors.append('%s  [%s] [%d]' % (message, category, confidence))
 
   def Results(self):
@@ -128,8 +130,6 @@ class CpplintTestBase(unittest.TestCase):
   def setUp(self):
     # Allow subclasses to cheat os.path.abspath called in FileInfo class.
     self.os_path_abspath_orig = os.path.abspath
-    self.assertEqual = self.assertEqual
-    self.assertTrue = self.assertTrue
 
   def tearDown(self):
     os.path.abspath = self.os_path_abspath_orig
@@ -571,6 +571,7 @@ def testErrorSuppression(self):
     error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('test.cc', 'cc',
                             ['// Copyright 2014 Your Company.',
+                             '#include <iostream>',
                              'for (int i = 0; i != 100; ++i) {',
                              '  std::cout << i << std::endl;',
                              '};  // NOLINT',
@@ -932,13 +933,11 @@ def testTypedefForPointerToFunction(self):
 
   def testIncludeWhatYouUseNoImplementationFiles(self):
     code = 'std::vector<int> foo;'
-    for extension in ['h', 'hpp', 'hxx', 'h++', 'cuh']:
+    for extension in ['h', 'hpp', 'hxx', 'h++', 'cuh',
+                      'c', 'cc', 'cpp', 'cxx', 'c++', 'cu']:
       self.assertEqual('Add #include <vector> for vector<>'
                        '  [build/include_what_you_use] [4]',
                        self.PerformIncludeWhatYouUse(code, 'foo.' + extension))
-    for extension in ['c', 'cc', 'cpp', 'cxx', 'c++', 'cu']:
-      self.assertEqual('',
-                       self.PerformIncludeWhatYouUse(code, 'foo.' + extension))
 
   def testIncludeWhatYouUse(self):
     self.TestIncludeWhatYouUse(
@@ -1025,6 +1024,12 @@ def testIncludeWhatYouUse(self):
            bool foobar = min<int>(0,1);
         """,
         'Add #include <algorithm> for min  [build/include_what_you_use] [4]')
+    self.TestIncludeWhatYouUse(
+        'cout << "hello world" << endl;',
+        'Add #include <iostream> for cout  [build/include_what_you_use] [4]')
+    self.TestIncludeWhatYouUse(
+        'printf("hello world");',
+        'Add #include <cstdio> for printf  [build/include_what_you_use] [4]')
     self.TestIncludeWhatYouUse(
         'void a(const string &foobar);',
         'Add #include <string> for string  [build/include_what_you_use] [4]')
@@ -1047,7 +1052,12 @@ def testIncludeWhatYouUse(self):
         '[build/include_what_you_use] [4]')
     self.TestIncludeWhatYouUse(
         """#include "base/foobar.h"
-           bool foobar = min_element(a.begin(), a.end());
+           boost::range::transform(input, std::back_inserter(output), square);
+        """,
+        '') # Avoid false positives on transform in other namespaces.
+    self.TestIncludeWhatYouUse(
+        """#include "base/foobar.h"
+           bool foobar = std::min_element(a.begin(), a.end());
         """,
         'Add #include <algorithm> for min_element  '
         '[build/include_what_you_use] [4]')
@@ -1152,50 +1162,6 @@ def testIncludeWhatYouUse(self):
         """,
         '')
 
-    # Test the UpdateIncludeState code path.
-    mock_header_contents = ['#include "blah/foo.h"', '#include "blah/bar.h"']
-    message = self.PerformIncludeWhatYouUse(
-        '#include "blah/a.h"',
-        filename='blah/a.cc',
-        io=MockIo(mock_header_contents))
-    self.assertEqual(message, '')
-
-    mock_header_contents = ['#include <set>']
-    message = self.PerformIncludeWhatYouUse(
-        """#include "blah/a.h"
-           std::set<int> foo;""",
-        filename='blah/a.cc',
-        io=MockIo(mock_header_contents))
-    self.assertEqual(message, '')
-
-    # Make sure we can find the correct header file if the cc file seems to be
-    # a temporary file generated by Emacs's flymake.
-    mock_header_contents = ['']
-    message = self.PerformIncludeWhatYouUse(
-        """#include "blah/a.h"
-           std::set<int> foo;""",
-        filename='blah/a_flymake.cc',
-        io=MockIo(mock_header_contents))
-    self.assertEqual(message, 'Add #include <set> for set<>  '
-                      '[build/include_what_you_use] [4]')
-
-    # If there's just a cc and the header can't be found then it's ok.
-    message = self.PerformIncludeWhatYouUse(
-        """#include "blah/a.h"
-           std::set<int> foo;""",
-        filename='blah/a.cc')
-    self.assertEqual(message, '')
-
-    # Make sure we find the headers with relative paths.
-    mock_header_contents = ['']
-    message = self.PerformIncludeWhatYouUse(
-        """#include "%s/a.h"
-           std::set<int> foo;""" % os.path.basename(os.getcwd()),
-        filename='a.cc',
-        io=MockIo(mock_header_contents))
-    self.assertEqual(message, 'Add #include <set> for set<>  '
-                      '[build/include_what_you_use] [4]')
-
   def testFilesBelongToSameModule(self):
     f = cpplint.FilesBelongToSameModule
     self.assertEqual((True, ''), f('a.cc', 'a.h'))
@@ -1387,7 +1353,7 @@ class Foo {
             Foo(int f);
           };""",
           'Single-parameter constructors should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # missing explicit is bad, even with whitespace
       self.TestMultiLineLint(
           """
@@ -1396,7 +1362,7 @@ class Foo {
           };""",
           ['Extra space before ( in function call  [whitespace/parens] [4]',
            'Single-parameter constructors should be marked explicit.'
-           '  [runtime/explicit] [5]'])
+           '  [runtime/explicit] [4]'])
       # missing explicit, with distracting comment, is still bad
       self.TestMultiLineLint(
           """
@@ -1404,7 +1370,7 @@ class Foo {
             Foo(int f);  // simpler than Foo(blargh, blarg)
           };""",
           'Single-parameter constructors should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # missing explicit, with qualified classname
       self.TestMultiLineLint(
           """
@@ -1412,7 +1378,7 @@ class Qualifier::AnotherOne::Foo {
             Foo(int f);
           };""",
           'Single-parameter constructors should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # missing explicit for inline constructors is bad as well
       self.TestMultiLineLint(
           """
@@ -1420,7 +1386,7 @@ class Foo {
             inline Foo(int f);
           };""",
           'Single-parameter constructors should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # missing explicit for constexpr constructors is bad as well
       self.TestMultiLineLint(
           """
@@ -1428,7 +1394,7 @@ class Foo {
             constexpr Foo(int f);
           };""",
           'Single-parameter constructors should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # missing explicit for constexpr+inline constructors is bad as well
       self.TestMultiLineLint(
           """
@@ -1436,14 +1402,14 @@ class Foo {
             constexpr inline Foo(int f);
           };""",
           'Single-parameter constructors should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       self.TestMultiLineLint(
           """
           class Foo {
             inline constexpr Foo(int f);
           };""",
           'Single-parameter constructors should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # explicit with inline is accepted
       self.TestMultiLineLint(
           """
@@ -1502,7 +1468,7 @@ class Foo {
             Foo(int f);
           };""",
           'Single-parameter constructors should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # Templatized classes are caught as well.
       self.TestMultiLineLint(
           """
@@ -1510,7 +1476,7 @@ class Foo {
             Foo(int f);
           };""",
           'Single-parameter constructors should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # inline case for templatized classes.
       self.TestMultiLineLint(
           """
@@ -1518,7 +1484,7 @@ class Foo {
             inline Foo(int f);
           };""",
           'Single-parameter constructors should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # constructors with a default argument should still be marked explicit
       self.TestMultiLineLint(
           """
@@ -1526,7 +1492,7 @@ class Foo {
             Foo(int f = 0);
           };""",
           'Constructors callable with one argument should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # multi-argument constructors with all but one default argument should be
       # marked explicit
       self.TestMultiLineLint(
@@ -1535,7 +1501,7 @@ class Foo {
             Foo(int f, int g = 0);
           };""",
           'Constructors callable with one argument should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # multi-argument constructors with all default arguments should be marked
       # explicit
       self.TestMultiLineLint(
@@ -1544,23 +1510,21 @@ class Foo {
             Foo(int f = 0, int g = 0);
           };""",
           'Constructors callable with one argument should be marked explicit.'
-          '  [runtime/explicit] [5]')
-      # explicit no-argument constructors are bad
+          '  [runtime/explicit] [4]')
+      # explicit no-argument constructors are just fine
       self.TestMultiLineLint(
           """
           class Foo {
             explicit Foo();
           };""",
-          'Zero-parameter constructors should not be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '')
       # void constructors are considered no-argument
       self.TestMultiLineLint(
           """
           class Foo {
             explicit Foo(void);
           };""",
-          'Zero-parameter constructors should not be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '')
       # No warning for multi-parameter constructors
       self.TestMultiLineLint(
           """
@@ -1582,7 +1546,7 @@ class Foo {
             Foo(void (*f)(int f, int g));
           };""",
           'Single-parameter constructors should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # single-argument constructors that take a single template argument with
       # multiple parameters should be explicit
       self.TestMultiLineLint(
@@ -1592,7 +1556,7 @@ class Foo {
             Foo(Bar<T, S> b);
           };""",
           'Single-parameter constructors should be marked explicit.'
-          '  [runtime/explicit] [5]')
+          '  [runtime/explicit] [4]')
       # but copy constructors that take multiple template parameters are OK
       self.TestMultiLineLint(
           """
@@ -1745,7 +1709,7 @@ class Foo {
           error_collector)
       self.assertEqual(1, error_collector.ResultList().count(
         'Constructors callable with one argument should be marked explicit.'
-        '  [runtime/explicit] [5]'))
+        '  [runtime/explicit] [4]'))
       error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData('foo.cc', 'cc',
           ['class Foo {',
@@ -1755,7 +1719,7 @@ class Foo {
           error_collector)
       self.assertEqual(1, error_collector.ResultList().count(
         'Constructors callable with one argument should be marked explicit.'
-        '  [runtime/explicit] [5]'))
+        '  [runtime/explicit] [4]'))
       # Anything goes inside an assembly block
       error_collector = ErrorCollector(self.assertTrue)
       cpplint.ProcessFileData('foo.cc', 'cc',
@@ -2452,6 +2416,8 @@ def testNonConstReference(self):
     cpplint.ProcessFileData(
         'foo.cc', 'cc',
         ['// Copyright 2014 Your Company. All Rights Reserved.',
+         '#include <string>',
+         '#include <utility>',
          'void swap(int &x,',
          '          int &y) {',
          '}',
@@ -3084,6 +3050,7 @@ def testStaticOrGlobalSTLStrings(self):
     error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('foo.cc', 'cc',
                             ['// Copyright 2014 Your Company.',
+                             '#include <string>',
                              'string Class',
                              '::MemberFunction1();',
                              'string Class::',
@@ -3294,7 +3261,7 @@ def DoTest(self, raw_bytes, has_invalid_utf8):
   def testBadCharacters(self):
     # Test for NUL bytes only
     error_collector = ErrorCollector(self.assertTrue)
-    cpplint.ProcessFileData('nul.cc', 'cc',
+    cpplint.ProcessFileData('nul_input.cc', 'cc',
                             ['// Copyright 2014 Your Company.',
                              '\0', ''], error_collector)
     self.assertEqual(
@@ -3671,6 +3638,9 @@ def testComma(self):
     self.TestLint('operator,()', '')
     self.TestLint('operator,(a,b)',
                   'Missing space after ,  [whitespace/comma] [3]')
+    self.TestLint('__VA_OPT__(,)', '')
+    self.TestLint('__VA_OPT__ (,)',
+                  'Extra space before ( in function call  [whitespace/parens] [4]')
 
   def testEqualsOperatorSpacing(self):
     self.TestLint('int tmp= a;',
@@ -4395,6 +4365,55 @@ def testDefaultFilter(self):
       cpplint._cpplint_state.filters = old_filters
       cpplint._DEFAULT_FILTERS = default_filters
 
+  def testFileSpecificFilter(self):
+    old_filters = cpplint._cpplint_state.filters
+    try:
+      test_code = """
+                  class Foo {
+                    Foo(int f)
+                    {
+                    }
+                  };"""
+      cpplint._cpplint_state.SetFilters('')
+      self.TestMultiLineLint(
+          test_code,
+          ['Single-parameter constructors should be marked explicit.'
+          '  [runtime/explicit] [4]',
+          '{ should almost always be at the end of the previous line'
+          '  [whitespace/braces] [4]']
+          )
+
+      cpplint._cpplint_state.SetFilters('-runtime/explicit:foo.h')
+      self.TestMultiLineLint(
+          test_code,
+          '{ should almost always be at the end of the previous line'
+          '  [whitespace/braces] [4]'
+          )
+
+      cpplint._cpplint_state.SetFilters('-runtime/explicit:foo.h:2')
+      self.TestMultiLineLint(
+          test_code,
+          '{ should almost always be at the end of the previous line'
+          '  [whitespace/braces] [4]'
+          )
+
+      cpplint._cpplint_state.SetFilters('-runtime/explicit:foo.h:14,-whitespace/braces:otherfile.h:3')
+      self.TestMultiLineLint(
+          test_code,
+          ['Single-parameter constructors should be marked explicit.'
+          '  [runtime/explicit] [4]',
+          '{ should almost always be at the end of the previous line'
+          '  [whitespace/braces] [4]']
+          )
+
+      cpplint._cpplint_state.SetFilters('-runtime/explicit:foo.h:2,-whitespace/braces:foo.h:3')
+      self.TestMultiLineLint(
+          test_code,
+          ''
+          )
+    finally:
+      cpplint._cpplint_state.filters = old_filters
+
   def testDuplicateHeader(self):
     error_collector = ErrorCollector(self.assertTrue)
     cpplint.ProcessFileData('path/self.cc', 'cc',
@@ -4857,6 +4876,9 @@ def testIncludeItsHeader(self):
         'test/foo.cc', 'cc',
         [''],
         error_collector)
+
+      if platform.system() == 'Windows':
+        test_directory = test_directory.replace('\\', '/')
       expected = "{dir}/{fn}.cc should include its header file {dir}/{fn}.h  [build/include] [5]".format(
           fn="foo",
           dir=test_directory)
@@ -4919,6 +4941,18 @@ def testIncludeItsHeader(self):
         0,
         error_collector.Results().count(expected))
 
+      # Test edge case in which multiple files have the same base name
+      open(os.path.join(test_directory, 'foo.hpp'), 'a').close()
+      cpplint.ProcessFileData(
+        'test/foo.cc', 'cc',
+        [r'#include "foo.hpp"',
+         ''
+         ],
+        error_collector)
+      self.assertEqual(
+        0,
+        error_collector.Results().count(expected))
+
     finally:
       # Restore previous CWD.
       os.chdir(cur_dir)
@@ -4943,7 +4977,15 @@ def testPathSplitToList(self):
   def testBuildHeaderGuardWithRepository(self):
     temp_directory = os.path.realpath(tempfile.mkdtemp())
     temp_directory2 = os.path.realpath(tempfile.mkdtemp())
+
+    # On Windows, os.path.relpath fails when the input is on
+    # a different drive than the current drive.
+    # In GitHub Actions CI, TEMP is set to C: drive, while the
+    # repository clone is on D: drive.
+    current_directory = os.getcwd()
     try:
+      os.chdir(temp_directory)
+
       os.makedirs(os.path.join(temp_directory, ".svn"))
       trunk_dir = os.path.join(temp_directory, "trunk")
       os.makedirs(trunk_dir)
@@ -4981,6 +5023,7 @@ def testBuildHeaderGuardWithRepository(self):
                         cpplint.GetHeaderGuardCPPVariable(file_path))
 
     finally:
+      os.chdir(current_directory)
       shutil.rmtree(temp_directory)
       shutil.rmtree(temp_directory2)
       cpplint._repository = None
@@ -5025,6 +5068,7 @@ def testBuildPrintfFormat(self):
     cpplint.ProcessFileData(
         'foo.cc', 'cc',
         ['// Copyright 2014 Your Company.',
+         '#include <cstdio>',
          r'printf("\\%%%d", value);',
          r'printf(R"(\[)");',
          r'printf(R"(\[%s)", R"(\])");',
@@ -5181,7 +5225,7 @@ def testSnprintfSize(self):
     self.TestLint('snprintf(fisk, 1, format)',
                   'If you can, use sizeof(fisk) instead of 1 as the 2nd arg '
                   'to snprintf.  [runtime/printf] [3]')
-class Cxx11Test(CpplintTestBase):
+class CxxTest(CpplintTestBase):
 
   def Helper(self, package, extension, lines, count):
     filename = package + '/foo.' + extension
@@ -5203,46 +5247,24 @@ def Helper(self, package, extension, lines, count):
     error_list = collector.ResultList()
     self.assertEqual(count, len(error_list), error_list)
 
-  def TestCxx11Feature(self, code, expected_error):
+  def TestCxxFeature(self, code, expected_error):
     lines = code.split('\n')
     collector = ErrorCollector(self.assertTrue)
     cpplint.RemoveMultiLineComments('foo.h', lines, collector)
     clean_lines = cpplint.CleansedLines(lines)
-    cpplint.FlagCxx11Features('foo.cc', clean_lines, 0, collector)
+    cpplint.FlagCxxHeaders('foo.cc', clean_lines, 0, collector)
     self.assertEqual(expected_error, collector.Results())
 
   def testBlockedHeaders(self):
-    self.TestCxx11Feature('#include <tr1/regex>',
-                          'C++ TR1 headers such as <tr1/regex> are '
-                          'unapproved.  [build/c++tr1] [5]')
-    self.TestCxx11Feature('#include <mutex>',
-                          '<mutex> is an unapproved C++11 header.'
+    self.TestCxxFeature('#include <ratio>',
+                          '<ratio> is an unapproved C++11 header.'
                           '  [build/c++11] [5]')
-
-  def testBlockedClasses(self):
-    self.TestCxx11Feature('std::alignment_of<T>',
-                          'std::alignment_of is an unapproved '
-                          'C++11 class or function.  Send c-style an example '
-                          'of where it would make your code more readable, '
-                          'and they may let you use it.'
+    self.TestCxxFeature('#include <fenv.h>',
+                          '<fenv.h> is an unapproved C++11 header.'
                           '  [build/c++11] [5]')
-    self.TestCxx11Feature('std::alignment_offer', '')
-    self.TestCxx11Feature('mystd::alignment_of', '')
-    self.TestCxx11Feature('std::binomial_distribution', '')
-
-  def testBlockedFunctions(self):
-    self.TestCxx11Feature('std::alignment_of<int>',
-                          'std::alignment_of is an unapproved '
-                          'C++11 class or function.  Send c-style an example '
-                          'of where it would make your code more readable, '
-                          'and they may let you use it.'
-                          '  [build/c++11] [5]')
-    # Missed because of the lack of "std::".  Compiles because ADL
-    # looks in the namespace of my_shared_ptr, which (presumably) is
-    # std::.  But there will be a lint error somewhere in this file
-    # since my_shared_ptr had to be defined.
-    self.TestCxx11Feature('static_pointer_cast<Base>(my_shared_ptr)', '')
-    self.TestCxx11Feature('std::declval<T>()', '')
+    self.TestCxxFeature('#include <filesystem>',
+                          '<filesystem> is an unapproved C++17 header.'
+                          '  [build/c++17] [5]')
 
   def testExplicitMakePair(self):
     self.TestLint('make_pair', '')
@@ -5259,30 +5281,9 @@ def testExplicitMakePair(self):
                   '  [build/explicit_make_pair] [4]')
     self.TestLint('my_make_pair<int, int>', '')
 
-class Cxx14Test(CpplintTestBase):
-
-  def TestCxx14Feature(self, code, expected_error):
-    lines = code.split('\n')
-    collector = ErrorCollector(self.assertTrue)
-    cpplint.RemoveMultiLineComments('foo.h', lines, collector)
-    clean_lines = cpplint.CleansedLines(lines)
-    cpplint.FlagCxx14Features('foo.cc', clean_lines, 0, collector)
-    self.assertEqual(expected_error, collector.Results())
-
-  def testBlockedHeaders(self):
-    self.TestCxx14Feature('#include <scoped_allocator>',
-                          '<scoped_allocator> is an unapproved C++14 header.'
-                           '  [build/c++14] [5]')
-    self.TestCxx14Feature('#include <shared_mutex>',
-                          '<shared_mutex> is an unapproved C++14 header.'
-                          '  [build/c++14] [5]')
-
 
 class CleansedLinesTest(unittest.TestCase):
 
-  def setUp(self):
-    self.assertEqual = self.assertEqual
-
   def testInit(self):
     lines = ['Line 1',
              'Line 2',
@@ -6019,7 +6020,6 @@ def CountLeadingWhitespace(s):
 class CloseExpressionTest(unittest.TestCase):
 
   def setUp(self):
-    self.assertEqual = self.assertEqual
     self.lines = cpplint.CleansedLines(
         #           1         2         3         4         5
         # 0123456789012345678901234567890123456789012345678901234567890
@@ -6092,7 +6092,6 @@ class NestingStateTest(unittest.TestCase):
   def setUp(self):
     self.nesting_state = cpplint.NestingState()
     self.error_collector = ErrorCollector(self.assertTrue)
-    self.assertEqual = self.assertEqual
 
   def UpdateWithLines(self, lines):
     clean_lines = cpplint.CleansedLines(lines)
@@ -6475,7 +6474,6 @@ def setUp(self):
     self.python_executable = sys.executable or 'python'
     self.cpplint_test_h = os.path.join(self.this_dir_path,
                                        'cpplint_test_header.h')
-    self.assertEqual = self.assertEqual
     open(self.cpplint_test_h, 'w').close()
 
   def tearDown(self):
diff --git a/test-requirements b/test-requirements
index 50f6fb3be..e048cd721 100644
--- a/test-requirements
+++ b/test-requirements
@@ -1,6 +1,7 @@
-# minimal requirements to run python setup.py test
-# 5.x requires python 3.5
+# requirements for testing steps
+tox<5.0.0
+
 pytest
 pytest-cov
-# freeze versions breaking python 2.7 on travis
+pytest-timeout
 testfixtures