Update googleurl to the latest version from Chromium

The version used is cc5912fc759fc64d7b8553cd9bb912f2a26c0cc7 from
Mon Oct 3 10:33:09 2022 +0000

Change-Id: I29d5289b4d383141f182640436c02f8c89f878fe
diff --git a/.bazelversion b/.bazelversion
index 831446c..03f488b 100644
--- a/.bazelversion
+++ b/.bazelversion
@@ -1 +1 @@
-5.1.0
+5.3.0
diff --git a/AUTHORS b/AUTHORS
index abd2e53..59ecce0 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -71,6 +71,7 @@
 Alexey Kuts <kruntuid@gmail.com>
 Alexey Kuzmin <alex.s.kuzmin@gmail.com>
 Alexey Kuznetsov <saturas2000@gmail.com>
+Alexey Terentiev <alexeyter@gmail.com>
 Alexis Brenon <brenon.alexis@gmail.com>
 Alexis La Goutte <alexis.lagoutte@gmail.com>
 Alexis Menard <alexis.menard@intel.com>
@@ -167,6 +168,7 @@
 Bhagirathi Satpathy <bhagirathi.s@samsung.com>
 Bhanukrushana Rout <b.rout@samsung.com>
 Biljith Jayan <billy.jayan@samsung.com>
+Bin Liao <bin.liao@intel.com>
 Boaz Sender <boaz@bocoup.com>
 Bobby Powers <bobbypowers@gmail.com>
 Branden Archer <bma4@zips.uakron.edu>
@@ -223,6 +225,7 @@
 Charles Vaughn <cvaughn@gmail.com>
 Cheng Zhao <zcbenz@gmail.com>
 Cheng Yu <yuzichengcode@gmail.com>
+Cheung Ho <uioptt24@gmail.com>
 Choongwoo Han <cwhan.tunz@gmail.com>
 Chris Greene <cwgreene@amazon.com>
 Chris Harrelson <chrishtr@gmail.com>
@@ -338,6 +341,7 @@
 Ehsan Akhgari <ehsan.akhgari@gmail.com>
 Ehsan Akhgari <ehsan@mightyapp.com>
 Elan Ruusamäe <elan.ruusamae@gmail.com>
+Emil Suleymanov <emil@esnx.xyz>
 Ergun Erdogmus <erdogmusergun@gmail.com>
 Eric Ahn <byungwook.ahn@gmail.com>
 Eric Huang <ele828@gmail.com>
@@ -363,6 +367,7 @@
 Felipe Erias Morandeira <felipeerias@gmail.com>
 Felix H. Dahlke <fhd@ubercode.de>
 Felix Weilbach <feweilbach@gmail.com>
+Feng Yu <f3n67u@gmail.com>
 Fengrong Fang <fr.fang@samsung.com>
 Fernando Jiménez Moreno <ferjmoreno@gmail.com>
 Finbar Crago <finbar.crago@gmail.com>
@@ -385,6 +390,7 @@
 Ganesh Borle <ganesh.borle@samsung.com>
 Gao Chun <chun.gao@intel.com>
 Gao Chun <gaochun.dev@gmail.com>
+Gao Sheng <gaosheng08@meituan.com>
 Gao Yu <wanggao@tencent.com>
 Gaurav Dhol <gaurav.dhol@einfochips.com>
 Gautham Banasandra <gautham.bangalore@gmail.com>
@@ -421,6 +427,7 @@
 Hans Hillen <hans.hillen@gmail.com>
 Hao Li <hao.x.li@intel.com>
 Haojian Wu <hokein.wu@gmail.com>
+Haoxuan Zhang <zhanghaoxuan.59@bytedance.com>
 Hari Singh <hari.singh1@samsung.com>
 Harpreet Singh Khurana <harpreet.sk@samsung.com>
 Harshikesh Kumar <harshikeshnobug@gmail.com>
@@ -431,6 +438,7 @@
 Henrique de Carvalho <decarv.henrique@gmail.com>
 Henrique Limas <henrique.ramos.limas@gmail.com>
 Himanshu Joshi <h.joshi@samsung.com>
+Hiroki Oshima <hiroki.oshima@gmail.com>
 Hiroyuki Matsuda <gsittyz@gmail.com>
 Hodol Han <bab6ting@gmail.com>
 Holger Kraus <kraush@amazon.com>
@@ -497,6 +505,7 @@
 Jakub Machacek <xtreit@gmail.com>
 James Burton <jb@0.me.uk>
 James Choi <jchoi42@pha.jhu.edu>
+James Raphael Tiovalen <jamestiotio@gmail.com>
 James Stanley <james@apphaus.co.uk>
 James Vega <vega.james@gmail.com>
 James Wei <james.wei@intel.com>
@@ -646,6 +655,7 @@
 Kaustubh Atrawalkar <kaustubh.ra@gmail.com>
 Ke He <ke.he@intel.com>
 Keeley Hammond <vertedinde@electronjs.org>
+Keeling <liqining.keeling@bytedance.com>
 Keene Pan <keenepan@linpus.com>
 Keiichiro Nagashima <n4ag3a2sh1i@gmail.com>
 Keita Suzuki <keitasuzuki.park@gmail.com>
@@ -715,6 +725,7 @@
 Lingqi Chi <someway.bit@gmail.com>
 Lingyun Cai <lingyun.cai@intel.com>
 Lionel Landwerlin <lionel.g.landwerlin@intel.com>
+Lisha Guo <lisha.guo@intel.com>
 Lizhi Fan <lizhi.fan@samsung.com>
 Loo Rong Jie <loorongjie@gmail.com>
 Lorenzo Stoakes <lstoakes@gmail.com>
@@ -796,6 +807,7 @@
 Md Abdullah Al Alamin <a.alamin.cse@gmail.com>
 Md. Hasanur Rashid <hasanur.r@samsung.com>
 Md Jobed Hossain <jobed.h@samsung.com>
+Md Raiyan bin Sayeed <mrbsayee@uwaterloo.ca>
 Md Sami Uddin <md.sami@samsung.com>
 Micha Hanselmann <micha.hanselmann@gmail.com>
 Michael Cirone <mikecirone@gmail.com>
@@ -927,6 +939,7 @@
 Peter Snyder <snyderp@gmail.com>
 Peter Varga <pvarga@inf.u-szeged.hu>
 Peter Wong <peter.wm.wong@gmail.com>
+Phan Quang Minh <phanquangminh217@gmail.com>
 Philip Hanson <philip.hanson@intel.com>
 Philipp Hancke <fippo@andyet.net>
 Philipp Hancke <philipp.hancke@googlemail.com>
@@ -1059,10 +1072,12 @@
 Sean DuBois <seaduboi@amazon.com>
 Sebastian Amend <sebastian.amend@googlemail.com>
 Sebastian Krzyszkowiak <dos@dosowisko.net>
+Sebastjan Raspor <sebastjan.raspor1@gmail.com>
 Seo Sanghyeon <sanxiyn@gmail.com>
 Seokju Kwon <seokju.kwon@gmail.com>
 Seokho Song <0xdevssh@gmail.com>
 SeongTae Jeong <ferendevelop.gl@gmail.com>
+Sergei Romanov <rsv.981@gmail.com>
 Sergey Kipet <sergey.kipet@gmail.com>
 Sergey Putilin <p.sergey@samsung.com>
 Sergey Shekyan <shekyan@gmail.com>
@@ -1307,11 +1322,13 @@
 Yong Ling <yongling@tencent.com>
 Yong Shin <sy3620@gmail.com>
 Yong Wang <ccyongwang@tencent.com>
+Yonggang Luo <luoyonggang@gmail.com>
 Yongha Lee <yongha78.lee@samsung.com>
 Yongseok Choi <yongseok.choi@navercorp.com>
 Yongsheng Zhu <yongsheng.zhu@intel.com>
 Yoonjae Cho <yoonjae.cho92@gmail.com>
 Yoshinori Sano <yoshinori.sano@gmail.com>
+Young Min Kim <y@ylem.kim>
 Youngho Seo <hazivoo@gmail.com>
 Youngjin Choi <cyjin9.yc@gmail.com>
 YoungKi Hong <simon.hong81@gmail.com>
@@ -1324,6 +1341,7 @@
 Yuki Tsuchiya <Yuki.Tsuchiya@sony.com>
 Yuma Takai <tara20070827@gmail.com>
 Yumikiyo Osanai <yumios.art@gmail.com>
+Yumin Su <yuminsu.hi@gmail.com>
 Yunchao He <yunchao.he@intel.com>
 Yupei Lin <yplam@yplam.com>
 Yupei Wang <perryuwang@tencent.com>
@@ -1337,6 +1355,7 @@
 Zachary Capalbo <zach.geek@gmail.com>
 Zeno Albisser <zeno.albisser@digia.com>
 Zeqin Chen <talonchen@tencent.com>
+Zhang Hao <zhanghao.m@bytedance.com>
 Zhang Hao <15686357310a@gmail.com>
 Zhaoze Zhou <zhaoze.zhou@partner.samsung.com>
 Zheda Chen <zheda.chen@intel.com>
@@ -1348,6 +1367,7 @@
 Zhibo Wang <zhibo1.wang@intel.com>
 Zhifei Fang <facetothefate@gmail.com>
 Zhiyuan Ye <zhiyuanye@tencent.com>
+Zhou Jun <zhoujun@uniontech.com>
 Zhuoyu Qian <zhuoyu.qian@samsung.com>
 Ziran Sun <ziran.sun@samsung.com>
 Zoltan Czirkos <czirkos.zoltan@gmail.com>
@@ -1429,12 +1449,14 @@
 The Chromium Authors <*@chromium.org>
 The MathWorks, Inc. <binod.pant@mathworks.com>
 THEO Technologies <*@theoplayer.com>
+Tien Hock Loh <tienhock.loh@starfivetech.com>
 Torchmobile Inc.
 Upwork <*@cloud.upwork.com>
 Venture 3 Systems LLC <*@venture3systems.com>
 Vewd Software AS <*@vewd.com>
 Vivaldi Technologies AS <*@vivaldi.com>
 Wacom <*@wacom.com>
+Whist Technologies <*@whist.com>
 Xperi Corporation <*@xperi.com>
 Yandex LLC <*@yandex-team.ru>
 Zuckjet <zuckjet@gmail.com>
diff --git a/LICENSE b/LICENSE
index a32e00c..2249a28 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// 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
@@ -10,7 +10,7 @@
 // copyright notice, this list of conditions and the following disclaimer
 // in the documentation and/or other materials provided with the
 // distribution.
-//    * Neither the name of Google Inc. nor the names of its
+//    * 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.
 //
diff --git a/base/BUILD b/base/BUILD
index 69dffea..60ca578 100644
--- a/base/BUILD
+++ b/base/BUILD
@@ -25,6 +25,7 @@
         "containers/span.h",
         "containers/util.h",
         "cxx17_backports.h",
+        "cxx20_is_constant_evaluated.h",
         "cxx20_to_address.h",
         "debug/crash_logging.h",
         "debug/leak_annotations.h",
@@ -34,8 +35,14 @@
         "memory/raw_ptr.h",
         "memory/raw_ptr_exclusion.h",
         "no_destructor.h",
+        "numerics/checked_math.h",
+        "numerics/checked_math_impl.h",
+        "numerics/clamped_math.h",
+        "numerics/clamped_math_impl.h",
         "numerics/safe_conversions.h",
         "numerics/safe_conversions_impl.h",
+        "numerics/safe_math_clang_gcc_impl.h",
+        "numerics/safe_math_shared_impl.h",
         "ranges/algorithm.h",
         "ranges/functional.h",
         "ranges/ranges.h",
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index 5719020..0174b6d 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -1,4 +1,4 @@
-// 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.
 
@@ -406,4 +406,17 @@
 #define GSL_POINTER
 #endif
 
+// Adds the "logically_const" tag to a symbol's mangled name. The "Mutable
+// Constants" check [1] detects instances of constants that aren't in .rodata,
+// e.g. due to a missing `const`. Using this tag suppresses the check for this
+// symbol, allowing it to live outside .rodata without a warning.
+//
+// [1]:
+// https://crsrc.org/c/docs/speed/binary_size/android_binary_size_trybot.md#Mutable-Constants
+#if defined(COMPILER_GCC) || defined(__clang__)
+#define LOGICALLY_CONST [[gnu::abi_tag("logically_const")]]
+#else
+#define LOGICALLY_CONST
+#endif
+
 #endif  // BASE_COMPILER_SPECIFIC_H_
diff --git a/base/containers/checked_iterators.h b/base/containers/checked_iterators.h
index c4e1e69..dc8d2ba 100644
--- a/base/containers/checked_iterators.h
+++ b/base/containers/checked_iterators.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/containers/contains.h b/base/containers/contains.h
index 559ff2c..430f79e 100644
--- a/base/containers/contains.h
+++ b/base/containers/contains.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/containers/contiguous_iterator.h b/base/containers/contiguous_iterator.h
index 6229efb..7f06432 100644
--- a/base/containers/contiguous_iterator.h
+++ b/base/containers/contiguous_iterator.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/containers/span.h b/base/containers/span.h
index 5bb30d1..40e325f 100644
--- a/base/containers/span.h
+++ b/base/containers/span.h
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2017 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -286,7 +286,10 @@
       typename End,
       typename = internal::EnableIfCompatibleContiguousIterator<It, T>,
       typename = std::enable_if_t<!std::is_convertible<End, size_t>::value>>
-  constexpr span(It begin, End end) noexcept : span(begin, end - begin) {
+  constexpr span(It begin, End end) noexcept
+      // Subtracting two iterators gives a ptrdiff_t, but the result should be
+      // non-negative: see GURL_CHECK below.
+      : span(begin, static_cast<size_t>(end - begin)) {
     // Note: GURL_CHECK_LE is not constexpr, hence regular GURL_CHECK must be used.
     GURL_CHECK(begin <= end);
   }
diff --git a/base/containers/util.h b/base/containers/util.h
index 7a65b6a..928263c 100644
--- a/base/containers/util.h
+++ b/base/containers/util.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/cxx17_backports.h b/base/cxx17_backports.h
index 86976d4..ce59af0 100644
--- a/base/cxx17_backports.h
+++ b/base/cxx17_backports.h
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,12 +6,8 @@
 #define BASE_CXX17_BACKPORTS_H_
 
 #include <functional>
-#include <tuple>
-#include <type_traits>
-#include <utility>
 
 #include "polyfills/base/check.h"
-#include "base/functional/invoke.h"
 
 namespace gurl_base {
 
@@ -31,26 +27,6 @@
   return gurl_base::clamp(v, lo, hi, std::less<T>{});
 }
 
-// C++14 implementation of C++17's std::apply():
-// https://en.cppreference.com/w/cpp/utility/apply
-namespace internal {
-template <class F, class Tuple, std::size_t... I>
-constexpr decltype(auto) apply_impl(F&& f,
-                                    Tuple&& t,
-                                    std::index_sequence<I...>) {
-  return gurl_base::invoke(std::forward<F>(f),
-                      std::get<I>(std::forward<Tuple>(t))...);
-}
-}  // namespace internal
-
-template <class F, class Tuple>
-constexpr decltype(auto) apply(F&& f, Tuple&& t) {
-  return internal::apply_impl(
-      std::forward<F>(f), std::forward<Tuple>(t),
-      std::make_index_sequence<
-          std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
-}
-
 }  // namespace base
 
 #endif  // BASE_CXX17_BACKPORTS_H_
diff --git a/base/cxx20_is_constant_evaluated.h b/base/cxx20_is_constant_evaluated.h
new file mode 100644
index 0000000..41fb247
--- /dev/null
+++ b/base/cxx20_is_constant_evaluated.h
@@ -0,0 +1,21 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_CXX20_IS_CONSTANT_EVALUATED_H_
+#define BASE_CXX20_IS_CONSTANT_EVALUATED_H_
+
+namespace gurl_base {
+
+// Implementation of C++20's std::is_constant_evaluated.
+//
+// References:
+// - https://en.cppreference.com/w/cpp/types/is_constant_evaluated
+// - https://wg21.link/meta.const.eval
+constexpr bool is_constant_evaluated() noexcept {
+  return __builtin_is_constant_evaluated();
+}
+
+}  // namespace base
+
+#endif  // BASE_CXX20_IS_CONSTANT_EVALUATED_H_
diff --git a/base/cxx20_to_address.h b/base/cxx20_to_address.h
index 56a87b7..ef67a9b 100644
--- a/base/cxx20_to_address.h
+++ b/base/cxx20_to_address.h
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,9 +9,10 @@
 
 namespace gurl_base {
 
-// Simplified C++14 implementation of C++20's std::to_address.
-// Note: This does not consider specializations of pointer_traits<>::to_address,
-// since that member function may only be present in C++20 and later.
+// Implementation of C++20's std::to_address.
+// Note: This does consider specializations of pointer_traits<>::to_address,
+// even though it's a C++20 member function, because CheckedContiguousIterator
+// specializes pointer_traits<> with a to_address() member.
 //
 // Reference: https://wg21.link/pointer.conversion#lib:to_address
 template <typename T>
@@ -22,8 +23,14 @@
 }
 
 template <typename Ptr>
-constexpr auto to_address(const Ptr& p) noexcept {
-  return to_address(p.operator->());
+constexpr auto to_address(const Ptr& p) noexcept
+    -> decltype(std::pointer_traits<Ptr>::to_address(p)) {
+  return std::pointer_traits<Ptr>::to_address(p);
+}
+
+template <typename Ptr, typename... None>
+constexpr auto to_address(const Ptr& p, None...) noexcept {
+  return gurl_base::to_address(p.operator->());
 }
 
 }  // namespace base
diff --git a/base/debug/crash_logging.cc b/base/debug/crash_logging.cc
index 124a31f..157a79f 100644
--- a/base/debug/crash_logging.cc
+++ b/base/debug/crash_logging.cc
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/base/debug/crash_logging.h b/base/debug/crash_logging.h
index 417d227..b4cf7bc 100644
--- a/base/debug/crash_logging.h
+++ b/base/debug/crash_logging.h
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/base/debug/leak_annotations.h b/base/debug/leak_annotations.h
index 89f47f4..506e1e0 100644
--- a/base/debug/leak_annotations.h
+++ b/base/debug/leak_annotations.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/functional/identity.h b/base/functional/identity.h
index 26af8e0..a0b66a6 100644
--- a/base/functional/identity.h
+++ b/base/functional/identity.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/functional/invoke.h b/base/functional/invoke.h
index 4399c6b..96dd088 100644
--- a/base/functional/invoke.h
+++ b/base/functional/invoke.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/functional/not_fn.h b/base/functional/not_fn.h
index 7457d03..4bf248f 100644
--- a/base/functional/not_fn.h
+++ b/base/functional/not_fn.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h
index c10a65d..d65ab44 100644
--- a/base/memory/raw_ptr.h
+++ b/base/memory/raw_ptr.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -24,7 +24,7 @@
 #include "build/buildflag.h"
 
 #if BUILDFLAG(USE_BACKUP_REF_PTR) || \
-    defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+    defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
 // USE_BACKUP_REF_PTR implies USE_PARTITION_ALLOC, needed for code under
 // allocator/partition_allocator/ to be built.
 #include "base/allocator/partition_allocator/address_pool_manager_bitmap.h"
@@ -32,13 +32,14 @@
 #include "base/allocator/partition_allocator/partition_alloc_constants.h"
 #include "polyfills/base/base_export.h"
 #endif  // BUILDFLAG(USE_BACKUP_REF_PTR) ||
-        // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+        // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
 
-#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
 #include "base/allocator/partition_allocator/partition_tag.h"
+#include "base/allocator/partition_allocator/partition_tag_types.h"
 #include "base/allocator/partition_allocator/tagging.h"
 #include "polyfills/base/check_op.h"
-#endif  // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+#endif  // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
 
 #if BUILDFLAG(IS_WIN)
 #include "base/win/win_handle_types.h"
@@ -59,6 +60,25 @@
 // NOTE: All methods should be `ALWAYS_INLINE`. raw_ptr is meant to be a
 // lightweight replacement of a raw pointer, hence performance is critical.
 
+// The following types are the different RawPtrType template option possible for
+// a `raw_ptr`:
+// - RawPtrMayDangle disables dangling pointers check when the object is
+//   released.
+// - RawPtrBanDanglingIfSupported may enable dangling pointers check on object
+//   destruction.
+//
+// We describe those types here so that they can be used outside of `raw_ptr` as
+// object markers, and their meaning might vary depending on where those markers
+// are being used. For instance, we are using those in `UnretainedWrapper` to
+// change behavior depending on RawPtrType.
+struct RawPtrMayDangle {};
+struct RawPtrBanDanglingIfSupported {};
+
+namespace raw_ptr_traits {
+template <typename T>
+struct RawPtrTypeToImpl;
+}
+
 namespace internal {
 // These classes/structures are part of the raw_ptr implementation.
 // DO NOT USE THESE CLASSES DIRECTLY YOURSELF.
@@ -121,6 +141,12 @@
     return wrapped_ptr + delta_elems;
   }
 
+  template <typename T>
+  static ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
+                                               T* wrapped_ptr2) {
+    return wrapped_ptr1 - wrapped_ptr2;
+  }
+
   // Returns a copy of a wrapped pointer, without making an assertion on whether
   // memory was freed or not.
   template <typename T>
@@ -134,7 +160,7 @@
   static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
 };
 
-#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
 
 constexpr int kValidAddressBits = 48;
 constexpr uintptr_t kAddressMask = (1ull << kValidAddressBits) - 1;
@@ -160,12 +186,7 @@
     // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this class
     // is responsible for handling the software MTE tag.
     auto addr = partition_alloc::UntagPtr(ptr);
-    // MTECheckedPtr algorithms work only when memory is
-    // allocated by PartitionAlloc, from normal buckets pool.
-    //
-    // TODO(crbug.com/1307514): Allow direct-map buckets.
-    return partition_alloc::IsManagedByPartitionAlloc(addr) &&
-           partition_alloc::internal::IsManagedByNormalBuckets(addr);
+    return partition_alloc::IsManagedByPartitionAlloc(addr);
   }
 
   // Returns pointer to the tag that protects are pointed by |addr|.
@@ -202,6 +223,7 @@
     static_assert(sizeof(partition_alloc::PartitionTag) * 8 <= kTagBits, "");
     uintptr_t tag = *(static_cast<volatile partition_alloc::PartitionTag*>(
         PartitionAllocSupport::TagPointer(addr)));
+    GURL_DCHECK(tag);
 
     tag <<= kValidAddressBits;
     addr |= tag;
@@ -277,6 +299,34 @@
     return wrapped_ptr + delta_elems;
   }
 
+  template <typename T>
+  static ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
+                                               T* wrapped_ptr2) {
+    // Ensure that both pointers come from the same allocation.
+    //
+    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
+    // class is responsible for handling the software MTE tag.
+    //
+    // MTECheckedPtr doesn't use 0 as a valid tag; depending on which
+    // subtraction operator is called, we may be getting the actual
+    // untagged T* or the wrapped pointer (passed as a T*) in one or
+    // both args. We can only check slot cohabitation when both args
+    // come with tags.
+    const uintptr_t tag1 = ExtractTag(partition_alloc::UntagPtr(wrapped_ptr1));
+    const uintptr_t tag2 = ExtractTag(partition_alloc::UntagPtr(wrapped_ptr2));
+    if (tag1 && tag2) {
+      GURL_CHECK(tag1 == tag2);
+      return wrapped_ptr1 - wrapped_ptr2;
+    }
+
+    // If one or the other arg come untagged, we have to perform the
+    // subtraction entirely without tags.
+    return reinterpret_cast<T*>(
+               ExtractAddress(partition_alloc::UntagPtr(wrapped_ptr1))) -
+           reinterpret_cast<T*>(
+               ExtractAddress(partition_alloc::UntagPtr(wrapped_ptr2)));
+  }
+
   // Returns a copy of a wrapped pointer, without making an assertion
   // on whether memory was freed or not.
   template <typename T>
@@ -309,7 +359,7 @@
   }
 };
 
-#endif  // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+#endif  // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
 
 #if BUILDFLAG(USE_BACKUP_REF_PTR)
 
@@ -465,6 +515,7 @@
     // rewrapped the pointer (wrapped the new pointer and unwrapped the old
     // one).
     uintptr_t address = partition_alloc::UntagPtr(wrapped_ptr);
+    // TODO(bartekn): Consider adding support for non-BRP pool too.
     if (IsSupportedAndNotNull(address))
       GURL_CHECK(IsValidDelta(address, delta_elems * static_cast<Z>(sizeof(T))));
     return wrapped_ptr + delta_elems;
@@ -497,6 +548,22 @@
 #endif
   }
 
+  template <typename T>
+  static ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
+                                               T* wrapped_ptr2) {
+    uintptr_t address1 = partition_alloc::UntagPtr(wrapped_ptr1);
+    uintptr_t address2 = partition_alloc::UntagPtr(wrapped_ptr2);
+    // Ensure that both pointers are within the same slot, and pool!
+    // TODO(bartekn): Consider adding support for non-BRP pool too.
+    if (IsSupportedAndNotNull(address1)) {
+      GURL_CHECK(IsSupportedAndNotNull(address2));
+      GURL_CHECK(IsValidDelta(address2, address1 - address2));
+    } else {
+      GURL_CHECK(!IsSupportedAndNotNull(address2));
+    }
+    return wrapped_ptr1 - wrapped_ptr2;
+  }
+
   // Returns a copy of a wrapped pointer, without making an assertion on whether
   // memory was freed or not.
   // This method increments the reference count of the allocation slot.
@@ -505,6 +572,12 @@
     return WrapRawPtr(wrapped_ptr);
   }
 
+  // Report the current wrapped pointer if pointee isn't alive anymore.
+  template <typename T>
+  static ALWAYS_INLINE void ReportIfDangling(T* wrapped_ptr) {
+    ReportIfDanglingInternal(partition_alloc::UntagPtr(wrapped_ptr));
+  }
+
   // This is for accounting only, used by unit tests.
   static ALWAYS_INLINE void IncrementSwapCountForTest() {}
   static ALWAYS_INLINE void IncrementLessCountForTest() {}
@@ -520,6 +593,7 @@
   static BASE_EXPORT NOINLINE void AcquireInternal(uintptr_t address);
   static BASE_EXPORT NOINLINE void ReleaseInternal(uintptr_t address);
   static BASE_EXPORT NOINLINE bool IsPointeeAlive(uintptr_t address);
+  static BASE_EXPORT NOINLINE void ReportIfDanglingInternal(uintptr_t address);
   template <typename Z, typename = std::enable_if_t<offset_type<Z>, void>>
   static ALWAYS_INLINE bool IsValidDelta(uintptr_t address, Z delta_in_bytes) {
     if constexpr (std::is_signed_v<Z>)
@@ -589,6 +663,12 @@
     return wrapped_ptr + delta_elems;
   }
 
+  template <typename T>
+  static ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
+                                               T* wrapped_ptr2) {
+    return wrapped_ptr1 - wrapped_ptr2;
+  }
+
   // Returns a copy of a wrapped pointer, without making an assertion on whether
   // memory was freed or not.
   template <typename T>
@@ -611,35 +691,37 @@
 };
 
 template <class Super>
-struct RawPtrCountingImplWrapperForTest : public Super {
+struct RawPtrCountingImplWrapperForTest
+    : public raw_ptr_traits::RawPtrTypeToImpl<Super>::Impl {
+  using SuperImpl = typename raw_ptr_traits::RawPtrTypeToImpl<Super>::Impl;
   template <typename T>
   static ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
     ++wrap_raw_ptr_cnt;
-    return Super::WrapRawPtr(ptr);
+    return SuperImpl::WrapRawPtr(ptr);
   }
 
   template <typename T>
   static ALWAYS_INLINE void ReleaseWrappedPtr(T* ptr) {
     ++release_wrapped_ptr_cnt;
-    Super::ReleaseWrappedPtr(ptr);
+    SuperImpl::ReleaseWrappedPtr(ptr);
   }
 
   template <typename T>
   static ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
     ++get_for_dereference_cnt;
-    return Super::SafelyUnwrapPtrForDereference(wrapped_ptr);
+    return SuperImpl::SafelyUnwrapPtrForDereference(wrapped_ptr);
   }
 
   template <typename T>
   static ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
     ++get_for_extraction_cnt;
-    return Super::SafelyUnwrapPtrForExtraction(wrapped_ptr);
+    return SuperImpl::SafelyUnwrapPtrForExtraction(wrapped_ptr);
   }
 
   template <typename T>
   static ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
     ++get_for_comparison_cnt;
-    return Super::UnsafelyUnwrapPtrForComparison(wrapped_ptr);
+    return SuperImpl::UnsafelyUnwrapPtrForComparison(wrapped_ptr);
   }
 
   static ALWAYS_INLINE void IncrementSwapCountForTest() {
@@ -762,6 +844,42 @@
 #undef CHROME_WINDOWS_HANDLE_TYPE
 #endif
 
+template <typename T>
+struct RawPtrTypeToImpl {};
+
+template <typename T>
+struct RawPtrTypeToImpl<internal::RawPtrCountingImplWrapperForTest<T>> {
+  using Impl = internal::RawPtrCountingImplWrapperForTest<T>;
+};
+
+template <>
+struct RawPtrTypeToImpl<RawPtrMayDangle> {
+#if BUILDFLAG(USE_BACKUP_REF_PTR)
+  using Impl = internal::BackupRefPtrImpl</*AllowDangling=*/true>;
+#elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+  using Impl = internal::AsanBackupRefPtrImpl;
+#elif defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+  using Impl = internal::MTECheckedPtrImpl<
+      internal::MTECheckedPtrImplPartitionAllocSupport>;
+#else
+  using Impl = internal::RawPtrNoOpImpl;
+#endif
+};
+
+template <>
+struct RawPtrTypeToImpl<RawPtrBanDanglingIfSupported> {
+#if BUILDFLAG(USE_BACKUP_REF_PTR)
+  using Impl = internal::BackupRefPtrImpl</*AllowDangling=*/false>;
+#elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+  using Impl = internal::AsanBackupRefPtrImpl;
+#elif defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+  using Impl = internal::MTECheckedPtrImpl<
+      internal::MTECheckedPtrImplPartitionAllocSupport>;
+#else
+  using Impl = internal::RawPtrNoOpImpl;
+#endif
+};
+
 }  // namespace raw_ptr_traits
 
 // `raw_ptr<T>` is a non-owning smart pointer that has improved memory-safety
@@ -790,27 +908,12 @@
 // non-default move constructor/assignment. Thus, it's possible to get an error
 // where the pointer is not actually dangling, and have to work around the
 // compiler. We have not managed to construct such an example in Chromium yet.
-#if BUILDFLAG(USE_BACKUP_REF_PTR)
-using RawPtrMayDangle = internal::BackupRefPtrImpl</*AllowDangling=*/true>;
-using RawPtrBanDanglingIfSupported =
-    internal::BackupRefPtrImpl</*AllowDangling=*/false>;
-#elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
-using RawPtrMayDangle = internal::AsanBackupRefPtrImpl;
-using RawPtrBanDanglingIfSupported = internal::AsanBackupRefPtrImpl;
-#elif defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
-using RawPtrMayDangle = internal::MTECheckedPtrImpl<
-    internal::MTECheckedPtrImplPartitionAllocSupport>;
-using RawPtrBanDanglingIfSupported = internal::MTECheckedPtrImpl<
-    internal::MTECheckedPtrImplPartitionAllocSupport>;
-#else
-using RawPtrMayDangle = internal::RawPtrNoOpImpl;
-using RawPtrBanDanglingIfSupported = internal::RawPtrNoOpImpl;
-#endif
 
-using DefaultRawPtrImpl = RawPtrBanDanglingIfSupported;
+using DefaultRawPtrType = RawPtrBanDanglingIfSupported;
 
-template <typename T, typename Impl = DefaultRawPtrImpl>
+template <typename T, typename RawPtrType = DefaultRawPtrType>
 class TRIVIAL_ABI GSL_POINTER raw_ptr {
+  using Impl = typename raw_ptr_traits::RawPtrTypeToImpl<RawPtrType>::Impl;
   using DanglingRawPtr = std::conditional_t<
       raw_ptr_traits::IsRawPtrCountingImpl<Impl>::value,
       raw_ptr<T, internal::RawPtrCountingImplWrapperForTest<RawPtrMayDangle>>,
@@ -901,7 +1004,7 @@
                 std::is_convertible<U*, T*>::value &&
                 !std::is_void<typename std::remove_cv<T>::type>::value>>
   // NOLINTNEXTLINE(google-explicit-constructor)
-  ALWAYS_INLINE raw_ptr(const raw_ptr<U, Impl>& ptr) noexcept
+  ALWAYS_INLINE raw_ptr(const raw_ptr<U, RawPtrType>& ptr) noexcept
       : wrapped_ptr_(
             Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_))) {}
   // Deliberately implicit in order to support implicit upcast.
@@ -910,7 +1013,7 @@
                 std::is_convertible<U*, T*>::value &&
                 !std::is_void<typename std::remove_cv<T>::type>::value>>
   // NOLINTNEXTLINE(google-explicit-constructor)
-  ALWAYS_INLINE raw_ptr(raw_ptr<U, Impl>&& ptr) noexcept
+  ALWAYS_INLINE raw_ptr(raw_ptr<U, RawPtrType>&& ptr) noexcept
       : wrapped_ptr_(Impl::template Upcast<T, U>(ptr.wrapped_ptr_)) {
 #if BUILDFLAG(USE_BACKUP_REF_PTR)
     ptr.wrapped_ptr_ = nullptr;
@@ -933,7 +1036,7 @@
             typename Unused = std::enable_if_t<
                 std::is_convertible<U*, T*>::value &&
                 !std::is_void<typename std::remove_cv<T>::type>::value>>
-  ALWAYS_INLINE raw_ptr& operator=(const raw_ptr<U, Impl>& ptr) noexcept {
+  ALWAYS_INLINE raw_ptr& operator=(const raw_ptr<U, RawPtrType>& ptr) noexcept {
     // Make sure that pointer isn't assigned to itself (look at pointer address,
     // not its value).
 #if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
@@ -949,7 +1052,7 @@
             typename Unused = std::enable_if_t<
                 std::is_convertible<U*, T*>::value &&
                 !std::is_void<typename std::remove_cv<T>::type>::value>>
-  ALWAYS_INLINE raw_ptr& operator=(raw_ptr<U, Impl>&& ptr) noexcept {
+  ALWAYS_INLINE raw_ptr& operator=(raw_ptr<U, RawPtrType>&& ptr) noexcept {
     // Make sure that pointer isn't assigned to itself (look at pointer address,
     // not its value).
 #if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
@@ -1012,18 +1115,37 @@
     --(*this);
     return result;
   }
-  template <typename Z,
-            typename = std::enable_if_t<internal::offset_type<Z>, void>>
+  template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
   ALWAYS_INLINE raw_ptr& operator+=(Z delta_elems) {
     wrapped_ptr_ = Impl::Advance(wrapped_ptr_, delta_elems);
     return *this;
   }
-  template <typename Z,
-            typename = std::enable_if_t<internal::offset_type<Z>, void>>
+  template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
   ALWAYS_INLINE raw_ptr& operator-=(Z delta_elems) {
     return *this += -delta_elems;
   }
 
+  template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
+  friend ALWAYS_INLINE raw_ptr operator+(const raw_ptr& p, Z delta_elems) {
+    raw_ptr result = p;
+    return result += delta_elems;
+  }
+  template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
+  friend ALWAYS_INLINE raw_ptr operator-(const raw_ptr& p, Z delta_elems) {
+    raw_ptr result = p;
+    return result -= delta_elems;
+  }
+  friend ALWAYS_INLINE ptrdiff_t operator-(const raw_ptr& p1,
+                                           const raw_ptr& p2) {
+    return Impl::GetDeltaElems(p1.wrapped_ptr_, p2.wrapped_ptr_);
+  }
+  friend ALWAYS_INLINE ptrdiff_t operator-(T* p1, const raw_ptr& p2) {
+    return Impl::GetDeltaElems(p1, p2.wrapped_ptr_);
+  }
+  friend ALWAYS_INLINE ptrdiff_t operator-(const raw_ptr& p1, T* p2) {
+    return Impl::GetDeltaElems(p1.wrapped_ptr_, p2);
+  }
+
   // Stop referencing the underlying pointer and free its memory. Compared to
   // raw delete calls, this avoids the raw_ptr to be temporarily dangling
   // during the free operation, which will lead to taking the slower path that
@@ -1047,6 +1169,10 @@
   // NOTE, avoid using this method as it indicates an error-prone memory
   // ownership pattern. If possible, use smart pointers like std::unique_ptr<>
   // instead of raw_ptr<>.
+  // If you have to use it, avoid saving the return value in a long-lived
+  // variable (or worse, a field)! It's meant to be used as a temporary, to be
+  // passed into a cleanup & freeing function, and destructed at the end of the
+  // statement.
   ALWAYS_INLINE DanglingRawPtr ExtractAsDangling() noexcept {
     if constexpr (std::is_same_v<
                       typename std::remove_reference<decltype(*this)>::type,
@@ -1176,6 +1302,12 @@
     perfetto::WriteIntoTracedValue(std::move(context), get());
   }
 
+  ALWAYS_INLINE void ReportIfDangling() const noexcept {
+#if BUILDFLAG(USE_BACKUP_REF_PTR)
+    Impl::ReportIfDangling(wrapped_ptr_);
+#endif
+  }
+
  private:
   // This getter is meant for situations where the pointer is meant to be
   // dereferenced. It is allowed to crash on nullptr (it may or may not),
@@ -1238,6 +1370,15 @@
   return lhs.GetForComparison() >= rhs.GetForComparison();
 }
 
+template <typename T>
+struct IsRawPtr : std::false_type {};
+
+template <typename T, typename I>
+struct IsRawPtr<raw_ptr<T, I>> : std::true_type {};
+
+template <typename T>
+inline constexpr bool IsRawPtrV = IsRawPtr<T>::value;
+
 // Template helpers for working with T* or raw_ptr<T>.
 template <typename T>
 struct IsPointer : std::false_type {};
@@ -1286,7 +1427,7 @@
 
 // See `docs/dangling_ptr.md`
 // Annotates known dangling raw_ptr. Those haven't been triaged yet. All the
-// occurrences are meant to be removed. See https://cbug.com/1291138.
+// occurrences are meant to be removed. See https://crbug.com/1291138.
 using DanglingUntriaged = DisableDanglingPtrDetection;
 
 // The following template parameters are only meaningful when `raw_ptr`
@@ -1298,7 +1439,7 @@
 // When `MTECheckedPtr` is in play, we need to augment this
 // implementation setting with another layer that allows the `raw_ptr`
 // to degrade into the no-op version.
-#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
 
 // Direct pass-through to no-op implementation.
 using DegradeToNoOpWhenMTE = gurl_base::internal::RawPtrNoOpImpl;
@@ -1323,33 +1464,47 @@
 using DisableDanglingPtrDetectionDegradeToNoOpWhenMTE =
     DisableDanglingPtrDetection;
 
-#endif  // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+#endif  // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
 
 namespace std {
 
 // Override so set/map lookups do not create extra raw_ptr. This also allows
 // dangling pointers to be used for lookup.
-template <typename T, typename Impl>
-struct less<raw_ptr<T, Impl>> {
+template <typename T, typename RawPtrType>
+struct less<raw_ptr<T, RawPtrType>> {
+  using Impl =
+      typename gurl_base::raw_ptr_traits::RawPtrTypeToImpl<RawPtrType>::Impl;
   using is_transparent = void;
 
-  bool operator()(const raw_ptr<T, Impl>& lhs,
-                  const raw_ptr<T, Impl>& rhs) const {
+  bool operator()(const raw_ptr<T, RawPtrType>& lhs,
+                  const raw_ptr<T, RawPtrType>& rhs) const {
     Impl::IncrementLessCountForTest();
     return lhs < rhs;
   }
 
-  bool operator()(T* lhs, const raw_ptr<T, Impl>& rhs) const {
+  bool operator()(T* lhs, const raw_ptr<T, RawPtrType>& rhs) const {
     Impl::IncrementLessCountForTest();
     return lhs < rhs;
   }
 
-  bool operator()(const raw_ptr<T, Impl>& lhs, T* rhs) const {
+  bool operator()(const raw_ptr<T, RawPtrType>& lhs, T* rhs) const {
     Impl::IncrementLessCountForTest();
     return lhs < rhs;
   }
 };
 
+// Define for cases where raw_ptr<T> holds a pointer to an array of type T.
+// This is consistent with definition of std::iterator_traits<T*>.
+// Algorithms like std::binary_search need that.
+template <typename T, typename Impl>
+struct iterator_traits<raw_ptr<T, Impl>> {
+  using difference_type = ptrdiff_t;
+  using value_type = std::remove_cv_t<T>;
+  using pointer = T*;
+  using reference = T&;
+  using iterator_category = std::random_access_iterator_tag;
+};
+
 }  // namespace std
 
 #endif  // BASE_MEMORY_RAW_PTR_H_
diff --git a/base/memory/raw_ptr_exclusion.h b/base/memory/raw_ptr_exclusion.h
index 37e9eac..f881c04 100644
--- a/base/memory/raw_ptr_exclusion.h
+++ b/base/memory/raw_ptr_exclusion.h
@@ -1,13 +1,14 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #ifndef BASE_MEMORY_RAW_PTR_EXCLUSION_H_
 #define BASE_MEMORY_RAW_PTR_EXCLUSION_H_
 
+#include "polyfills/base/allocator/buildflags.h"
 #include "build/build_config.h"
 
-#if defined(OFFICIAL_BUILD)
+#if defined(OFFICIAL_BUILD) && !BUILDFLAG(FORCE_ENABLE_RAW_PTR_EXCLUSION)
 // The annotation changed compiler output and increased binary size so disable
 // for official builds.
 // TODO(crbug.com/1320670): Remove when issue is resolved.
diff --git a/base/no_destructor.h b/base/no_destructor.h
index 2f3c549..b183e4f 100644
--- a/base/no_destructor.h
+++ b/base/no_destructor.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/numerics/checked_math.h b/base/numerics/checked_math.h
new file mode 100644
index 0000000..4973f09
--- /dev/null
+++ b/base/numerics/checked_math.h
@@ -0,0 +1,381 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_CHECKED_MATH_H_
+#define BASE_NUMERICS_CHECKED_MATH_H_
+
+#include <stddef.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/checked_math_impl.h"
+
+namespace gurl_base {
+namespace internal {
+
+template <typename T>
+class CheckedNumeric {
+  static_assert(std::is_arithmetic<T>::value,
+                "CheckedNumeric<T>: T must be a numeric type.");
+
+ public:
+  template <typename Src>
+  friend class CheckedNumeric;
+
+  using type = T;
+
+  constexpr CheckedNumeric() = default;
+
+  // Copy constructor.
+  template <typename Src>
+  constexpr CheckedNumeric(const CheckedNumeric<Src>& rhs)
+      : state_(rhs.state_.value(), rhs.IsValid()) {}
+
+  // Strictly speaking, this is not necessary, but declaring this allows class
+  // template argument deduction to be used so that it is possible to simply
+  // write `CheckedNumeric(777)` instead of `CheckedNumeric<int>(777)`.
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  constexpr CheckedNumeric(T value) : state_(value) {}
+
+  // This is not an explicit constructor because we implicitly upgrade regular
+  // numerics to CheckedNumerics to make them easier to use.
+  template <typename Src>
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  constexpr CheckedNumeric(Src value) : state_(value) {
+    static_assert(UnderlyingType<Src>::is_numeric, "Argument must be numeric.");
+  }
+
+  // This is not an explicit constructor because we want a seamless conversion
+  // from StrictNumeric types.
+  template <typename Src>
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  constexpr CheckedNumeric(StrictNumeric<Src> value)
+      : state_(static_cast<Src>(value)) {}
+
+  // IsValid() - The public API to test if a CheckedNumeric is currently valid.
+  // A range checked destination type can be supplied using the Dst template
+  // parameter.
+  template <typename Dst = T>
+  constexpr bool IsValid() const {
+    return state_.is_valid() &&
+           IsValueInRangeForNumericType<Dst>(state_.value());
+  }
+
+  // AssignIfValid(Dst) - Assigns the underlying value if it is currently valid
+  // and is within the range supported by the destination type. Returns true if
+  // successful and false otherwise.
+  template <typename Dst>
+#if defined(__clang__) || defined(__GNUC__)
+  __attribute__((warn_unused_result))
+#elif defined(_MSC_VER)
+  _Check_return_
+#endif
+  constexpr bool
+  AssignIfValid(Dst* result) const {
+    return BASE_NUMERICS_LIKELY(IsValid<Dst>())
+               ? ((*result = static_cast<Dst>(state_.value())), true)
+               : false;
+  }
+
+  // ValueOrDie() - The primary accessor for the underlying value. If the
+  // current state is not valid it will GURL_CHECK and crash.
+  // A range checked destination type can be supplied using the Dst template
+  // parameter, which will trigger a GURL_CHECK if the value is not in bounds for
+  // the destination.
+  // The GURL_CHECK behavior can be overridden by supplying a handler as a
+  // template parameter, for test code, etc. However, the handler cannot access
+  // the underlying value, and it is not available through other means.
+  template <typename Dst = T, class CheckHandler = CheckOnFailure>
+  constexpr StrictNumeric<Dst> ValueOrDie() const {
+    return BASE_NUMERICS_LIKELY(IsValid<Dst>())
+               ? static_cast<Dst>(state_.value())
+               : CheckHandler::template HandleFailure<Dst>();
+  }
+
+  // ValueOrDefault(T default_value) - A convenience method that returns the
+  // current value if the state is valid, and the supplied default_value for
+  // any other state.
+  // A range checked destination type can be supplied using the Dst template
+  // parameter. WARNING: This function may fail to compile or GURL_CHECK at runtime
+  // if the supplied default_value is not within range of the destination type.
+  template <typename Dst = T, typename Src>
+  constexpr StrictNumeric<Dst> ValueOrDefault(const Src default_value) const {
+    return BASE_NUMERICS_LIKELY(IsValid<Dst>())
+               ? static_cast<Dst>(state_.value())
+               : checked_cast<Dst>(default_value);
+  }
+
+  // Returns a checked numeric of the specified type, cast from the current
+  // CheckedNumeric. If the current state is invalid or the destination cannot
+  // represent the result then the returned CheckedNumeric will be invalid.
+  template <typename Dst>
+  constexpr CheckedNumeric<typename UnderlyingType<Dst>::type> Cast() const {
+    return *this;
+  }
+
+  // This friend method is available solely for providing more detailed logging
+  // in the tests. Do not implement it in production code, because the
+  // underlying values may change at any time.
+  template <typename U>
+  friend U GetNumericValueForTest(const CheckedNumeric<U>& src);
+
+  // Prototypes for the supported arithmetic operator overloads.
+  template <typename Src>
+  constexpr CheckedNumeric& operator+=(const Src rhs);
+  template <typename Src>
+  constexpr CheckedNumeric& operator-=(const Src rhs);
+  template <typename Src>
+  constexpr CheckedNumeric& operator*=(const Src rhs);
+  template <typename Src>
+  constexpr CheckedNumeric& operator/=(const Src rhs);
+  template <typename Src>
+  constexpr CheckedNumeric& operator%=(const Src rhs);
+  template <typename Src>
+  constexpr CheckedNumeric& operator<<=(const Src rhs);
+  template <typename Src>
+  constexpr CheckedNumeric& operator>>=(const Src rhs);
+  template <typename Src>
+  constexpr CheckedNumeric& operator&=(const Src rhs);
+  template <typename Src>
+  constexpr CheckedNumeric& operator|=(const Src rhs);
+  template <typename Src>
+  constexpr CheckedNumeric& operator^=(const Src rhs);
+
+  constexpr CheckedNumeric operator-() const {
+    // Use an optimized code path for a known run-time variable.
+    if (!IsConstantEvaluated() && std::is_signed<T>::value &&
+        std::is_floating_point<T>::value) {
+      return FastRuntimeNegate();
+    }
+    // The negation of two's complement int min is int min.
+    const bool is_valid =
+        IsValid() &&
+        (!std::is_signed<T>::value || std::is_floating_point<T>::value ||
+         NegateWrapper(state_.value()) != std::numeric_limits<T>::lowest());
+    return CheckedNumeric<T>(NegateWrapper(state_.value()), is_valid);
+  }
+
+  constexpr CheckedNumeric operator~() const {
+    return CheckedNumeric<decltype(InvertWrapper(T()))>(
+        InvertWrapper(state_.value()), IsValid());
+  }
+
+  constexpr CheckedNumeric Abs() const {
+    return !IsValueNegative(state_.value()) ? *this : -*this;
+  }
+
+  template <typename U>
+  constexpr CheckedNumeric<typename MathWrapper<CheckedMaxOp, T, U>::type> Max(
+      const U rhs) const {
+    return CheckMax(*this, rhs);
+  }
+
+  template <typename U>
+  constexpr CheckedNumeric<typename MathWrapper<CheckedMinOp, T, U>::type> Min(
+      const U rhs) const {
+    return CheckMin(*this, rhs);
+  }
+
+  // This function is available only for integral types. It returns an unsigned
+  // integer of the same width as the source type, containing the absolute value
+  // of the source, and properly handling signed min.
+  constexpr CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>
+  UnsignedAbs() const {
+    return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>(
+        SafeUnsignedAbs(state_.value()), state_.is_valid());
+  }
+
+  constexpr CheckedNumeric& operator++() {
+    *this += 1;
+    return *this;
+  }
+
+  constexpr CheckedNumeric operator++(int) {
+    CheckedNumeric value = *this;
+    *this += 1;
+    return value;
+  }
+
+  constexpr CheckedNumeric& operator--() {
+    *this -= 1;
+    return *this;
+  }
+
+  constexpr CheckedNumeric operator--(int) {
+    // TODO(pkasting): Consider std::exchange() once it's constexpr in C++20.
+    const CheckedNumeric value = *this;
+    *this -= 1;
+    return value;
+  }
+
+  // These perform the actual math operations on the CheckedNumerics.
+  // Binary arithmetic operations.
+  template <template <typename, typename, typename> class M,
+            typename L,
+            typename R>
+  static constexpr CheckedNumeric MathOp(const L lhs, const R rhs) {
+    using Math = typename MathWrapper<M, L, R>::math;
+    T result = 0;
+    const bool is_valid =
+        Wrapper<L>::is_valid(lhs) && Wrapper<R>::is_valid(rhs) &&
+        Math::Do(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs), &result);
+    return CheckedNumeric<T>(result, is_valid);
+  }
+
+  // Assignment arithmetic operations.
+  template <template <typename, typename, typename> class M, typename R>
+  constexpr CheckedNumeric& MathOp(const R rhs) {
+    using Math = typename MathWrapper<M, T, R>::math;
+    T result = 0;  // Using T as the destination saves a range check.
+    const bool is_valid =
+        state_.is_valid() && Wrapper<R>::is_valid(rhs) &&
+        Math::Do(state_.value(), Wrapper<R>::value(rhs), &result);
+    *this = CheckedNumeric<T>(result, is_valid);
+    return *this;
+  }
+
+ private:
+  CheckedNumericState<T> state_;
+
+  CheckedNumeric FastRuntimeNegate() const {
+    T result;
+    const bool success = CheckedSubOp<T, T>::Do(T(0), state_.value(), &result);
+    return CheckedNumeric<T>(result, IsValid() && success);
+  }
+
+  template <typename Src>
+  constexpr CheckedNumeric(Src value, bool is_valid)
+      : state_(value, is_valid) {}
+
+  // These wrappers allow us to handle state the same way for both
+  // CheckedNumeric and POD arithmetic types.
+  template <typename Src>
+  struct Wrapper {
+    static constexpr bool is_valid(Src) { return true; }
+    static constexpr Src value(Src value) { return value; }
+  };
+
+  template <typename Src>
+  struct Wrapper<CheckedNumeric<Src>> {
+    static constexpr bool is_valid(const CheckedNumeric<Src> v) {
+      return v.IsValid();
+    }
+    static constexpr Src value(const CheckedNumeric<Src> v) {
+      return v.state_.value();
+    }
+  };
+
+  template <typename Src>
+  struct Wrapper<StrictNumeric<Src>> {
+    static constexpr bool is_valid(const StrictNumeric<Src>) { return true; }
+    static constexpr Src value(const StrictNumeric<Src> v) {
+      return static_cast<Src>(v);
+    }
+  };
+};
+
+// Convenience functions to avoid the ugly template disambiguator syntax.
+template <typename Dst, typename Src>
+constexpr bool IsValidForType(const CheckedNumeric<Src> value) {
+  return value.template IsValid<Dst>();
+}
+
+template <typename Dst, typename Src>
+constexpr StrictNumeric<Dst> ValueOrDieForType(
+    const CheckedNumeric<Src> value) {
+  return value.template ValueOrDie<Dst>();
+}
+
+template <typename Dst, typename Src, typename Default>
+constexpr StrictNumeric<Dst> ValueOrDefaultForType(
+    const CheckedNumeric<Src> value,
+    const Default default_value) {
+  return value.template ValueOrDefault<Dst>(default_value);
+}
+
+// Convenience wrapper to return a new CheckedNumeric from the provided
+// arithmetic or CheckedNumericType.
+template <typename T>
+constexpr CheckedNumeric<typename UnderlyingType<T>::type> MakeCheckedNum(
+    const T value) {
+  return value;
+}
+
+// These implement the variadic wrapper for the math operations.
+template <template <typename, typename, typename> class M,
+          typename L,
+          typename R>
+constexpr CheckedNumeric<typename MathWrapper<M, L, R>::type> CheckMathOp(
+    const L lhs,
+    const R rhs) {
+  using Math = typename MathWrapper<M, L, R>::math;
+  return CheckedNumeric<typename Math::result_type>::template MathOp<M>(lhs,
+                                                                        rhs);
+}
+
+// General purpose wrapper template for arithmetic operations.
+template <template <typename, typename, typename> class M,
+          typename L,
+          typename R,
+          typename... Args>
+constexpr auto CheckMathOp(const L lhs, const R rhs, const Args... args) {
+  return CheckMathOp<M>(CheckMathOp<M>(lhs, rhs), args...);
+}
+
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Add, +, +=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Sub, -, -=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mul, *, *=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Div, /, /=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mod, %, %=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Lsh, <<, <<=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Rsh, >>, >>=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, And, &, &=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Or, |, |=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Xor, ^, ^=)
+BASE_NUMERIC_ARITHMETIC_VARIADIC(Checked, Check, Max)
+BASE_NUMERIC_ARITHMETIC_VARIADIC(Checked, Check, Min)
+
+// These are some extra StrictNumeric operators to support simple pointer
+// arithmetic with our result types. Since wrapping on a pointer is always
+// bad, we trigger the GURL_CHECK condition here.
+template <typename L, typename R>
+L* operator+(L* lhs, const StrictNumeric<R> rhs) {
+  const uintptr_t result = CheckAdd(reinterpret_cast<uintptr_t>(lhs),
+                                    CheckMul(sizeof(L), static_cast<R>(rhs)))
+                               .template ValueOrDie<uintptr_t>();
+  return reinterpret_cast<L*>(result);
+}
+
+template <typename L, typename R>
+L* operator-(L* lhs, const StrictNumeric<R> rhs) {
+  const uintptr_t result = CheckSub(reinterpret_cast<uintptr_t>(lhs),
+                                    CheckMul(sizeof(L), static_cast<R>(rhs)))
+                               .template ValueOrDie<uintptr_t>();
+  return reinterpret_cast<L*>(result);
+}
+
+}  // namespace internal
+
+using internal::CheckAdd;
+using internal::CheckAnd;
+using internal::CheckDiv;
+using internal::CheckedNumeric;
+using internal::CheckLsh;
+using internal::CheckMax;
+using internal::CheckMin;
+using internal::CheckMod;
+using internal::CheckMul;
+using internal::CheckOr;
+using internal::CheckRsh;
+using internal::CheckSub;
+using internal::CheckXor;
+using internal::IsValidForType;
+using internal::MakeCheckedNum;
+using internal::ValueOrDefaultForType;
+using internal::ValueOrDieForType;
+
+}  // namespace base
+
+#endif  // BASE_NUMERICS_CHECKED_MATH_H_
diff --git a/base/numerics/checked_math_impl.h b/base/numerics/checked_math_impl.h
new file mode 100644
index 0000000..30dd8e1
--- /dev/null
+++ b/base/numerics/checked_math_impl.h
@@ -0,0 +1,593 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_CHECKED_MATH_IMPL_H_
+#define BASE_NUMERICS_CHECKED_MATH_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/safe_conversions.h"
+#include "base/numerics/safe_math_shared_impl.h"
+
+namespace gurl_base {
+namespace internal {
+
+template <typename T>
+constexpr bool CheckedAddImpl(T x, T y, T* result) {
+  static_assert(std::is_integral<T>::value, "Type must be integral");
+  // Since the value of x+y is undefined if we have a signed type, we compute
+  // it using the unsigned type of the same size.
+  using UnsignedDst = typename std::make_unsigned<T>::type;
+  using SignedDst = typename std::make_signed<T>::type;
+  const UnsignedDst ux = static_cast<UnsignedDst>(x);
+  const UnsignedDst uy = static_cast<UnsignedDst>(y);
+  const UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy);
+  // Addition is valid if the sign of (x + y) is equal to either that of x or
+  // that of y.
+  if (std::is_signed<T>::value
+          ? static_cast<SignedDst>((uresult ^ ux) & (uresult ^ uy)) < 0
+          : uresult < uy)  // Unsigned is either valid or underflow.
+    return false;
+  *result = static_cast<T>(uresult);
+  return true;
+}
+
+template <typename T, typename U, class Enable = void>
+struct CheckedAddOp {};
+
+template <typename T, typename U>
+struct CheckedAddOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename MaxExponentPromotion<T, U>::type;
+  template <typename V>
+  static constexpr bool Do(T x, U y, V* result) {
+    if constexpr (CheckedAddFastOp<T, U>::is_supported)
+      return CheckedAddFastOp<T, U>::Do(x, y, result);
+
+    // Double the underlying type up to a full machine word.
+    using FastPromotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+    using Promotion =
+        typename std::conditional<(IntegerBitsPlusSign<FastPromotion>::value >
+                                   IntegerBitsPlusSign<intptr_t>::value),
+                                  typename BigEnoughPromotion<T, U>::type,
+                                  FastPromotion>::type;
+    // Fail if either operand is out of range for the promoted type.
+    // TODO(jschuh): This could be made to work for a broader range of values.
+    if (BASE_NUMERICS_UNLIKELY(!IsValueInRangeForNumericType<Promotion>(x) ||
+                               !IsValueInRangeForNumericType<Promotion>(y))) {
+      return false;
+    }
+
+    Promotion presult = {};
+    bool is_valid = true;
+    if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
+      presult = static_cast<Promotion>(x) + static_cast<Promotion>(y);
+    } else {
+      is_valid = CheckedAddImpl(static_cast<Promotion>(x),
+                                static_cast<Promotion>(y), &presult);
+    }
+    if (!is_valid || !IsValueInRangeForNumericType<V>(presult))
+      return false;
+    *result = static_cast<V>(presult);
+    return true;
+  }
+};
+
+template <typename T>
+constexpr bool CheckedSubImpl(T x, T y, T* result) {
+  static_assert(std::is_integral<T>::value, "Type must be integral");
+  // Since the value of x+y is undefined if we have a signed type, we compute
+  // it using the unsigned type of the same size.
+  using UnsignedDst = typename std::make_unsigned<T>::type;
+  using SignedDst = typename std::make_signed<T>::type;
+  const UnsignedDst ux = static_cast<UnsignedDst>(x);
+  const UnsignedDst uy = static_cast<UnsignedDst>(y);
+  const UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy);
+  // Subtraction is valid if either x and y have same sign, or (x-y) and x have
+  // the same sign.
+  if (std::is_signed<T>::value
+          ? static_cast<SignedDst>((uresult ^ ux) & (ux ^ uy)) < 0
+          : x < y)
+    return false;
+  *result = static_cast<T>(uresult);
+  return true;
+}
+
+template <typename T, typename U, class Enable = void>
+struct CheckedSubOp {};
+
+template <typename T, typename U>
+struct CheckedSubOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename MaxExponentPromotion<T, U>::type;
+  template <typename V>
+  static constexpr bool Do(T x, U y, V* result) {
+    if constexpr (CheckedSubFastOp<T, U>::is_supported)
+      return CheckedSubFastOp<T, U>::Do(x, y, result);
+
+    // Double the underlying type up to a full machine word.
+    using FastPromotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+    using Promotion =
+        typename std::conditional<(IntegerBitsPlusSign<FastPromotion>::value >
+                                   IntegerBitsPlusSign<intptr_t>::value),
+                                  typename BigEnoughPromotion<T, U>::type,
+                                  FastPromotion>::type;
+    // Fail if either operand is out of range for the promoted type.
+    // TODO(jschuh): This could be made to work for a broader range of values.
+    if (BASE_NUMERICS_UNLIKELY(!IsValueInRangeForNumericType<Promotion>(x) ||
+                               !IsValueInRangeForNumericType<Promotion>(y))) {
+      return false;
+    }
+
+    Promotion presult = {};
+    bool is_valid = true;
+    if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
+      presult = static_cast<Promotion>(x) - static_cast<Promotion>(y);
+    } else {
+      is_valid = CheckedSubImpl(static_cast<Promotion>(x),
+                                static_cast<Promotion>(y), &presult);
+    }
+    if (!is_valid || !IsValueInRangeForNumericType<V>(presult))
+      return false;
+    *result = static_cast<V>(presult);
+    return true;
+  }
+};
+
+template <typename T>
+constexpr bool CheckedMulImpl(T x, T y, T* result) {
+  static_assert(std::is_integral<T>::value, "Type must be integral");
+  // Since the value of x*y is potentially undefined if we have a signed type,
+  // we compute it using the unsigned type of the same size.
+  using UnsignedDst = typename std::make_unsigned<T>::type;
+  using SignedDst = typename std::make_signed<T>::type;
+  const UnsignedDst ux = SafeUnsignedAbs(x);
+  const UnsignedDst uy = SafeUnsignedAbs(y);
+  const UnsignedDst uresult = static_cast<UnsignedDst>(ux * uy);
+  const bool is_negative =
+      std::is_signed<T>::value && static_cast<SignedDst>(x ^ y) < 0;
+  // We have a fast out for unsigned identity or zero on the second operand.
+  // After that it's an unsigned overflow check on the absolute value, with
+  // a +1 bound for a negative result.
+  if (uy > UnsignedDst(!std::is_signed<T>::value || is_negative) &&
+      ux > (std::numeric_limits<T>::max() + UnsignedDst(is_negative)) / uy)
+    return false;
+  *result = static_cast<T>(is_negative ? 0 - uresult : uresult);
+  return true;
+}
+
+template <typename T, typename U, class Enable = void>
+struct CheckedMulOp {};
+
+template <typename T, typename U>
+struct CheckedMulOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename MaxExponentPromotion<T, U>::type;
+  template <typename V>
+  static constexpr bool Do(T x, U y, V* result) {
+    if constexpr (CheckedMulFastOp<T, U>::is_supported)
+      return CheckedMulFastOp<T, U>::Do(x, y, result);
+
+    using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+    // Verify the destination type can hold the result (always true for 0).
+    if (BASE_NUMERICS_UNLIKELY((!IsValueInRangeForNumericType<Promotion>(x) ||
+                                !IsValueInRangeForNumericType<Promotion>(y)) &&
+                               x && y)) {
+      return false;
+    }
+
+    Promotion presult = {};
+    bool is_valid = true;
+    if (CheckedMulFastOp<Promotion, Promotion>::is_supported) {
+      // The fast op may be available with the promoted type.
+      // The casts here are safe because of the "value in range" conditional
+      // above.
+      is_valid = CheckedMulFastOp<Promotion, Promotion>::Do(
+          static_cast<Promotion>(x), static_cast<Promotion>(y), &presult);
+    } else if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
+      presult = static_cast<Promotion>(x) * static_cast<Promotion>(y);
+    } else {
+      is_valid = CheckedMulImpl(static_cast<Promotion>(x),
+                                static_cast<Promotion>(y), &presult);
+    }
+    if (!is_valid || !IsValueInRangeForNumericType<V>(presult))
+      return false;
+    *result = static_cast<V>(presult);
+    return true;
+  }
+};
+
+// Division just requires a check for a zero denominator or an invalid negation
+// on signed min/-1.
+template <typename T, typename U, class Enable = void>
+struct CheckedDivOp {};
+
+template <typename T, typename U>
+struct CheckedDivOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename MaxExponentPromotion<T, U>::type;
+  template <typename V>
+  static constexpr bool Do(T x, U y, V* result) {
+    if (BASE_NUMERICS_UNLIKELY(!y))
+      return false;
+
+    // The overflow check can be compiled away if we don't have the exact
+    // combination of types needed to trigger this case.
+    using Promotion = typename BigEnoughPromotion<T, U>::type;
+    if (BASE_NUMERICS_UNLIKELY(
+            (std::is_signed<T>::value && std::is_signed<U>::value &&
+             IsTypeInRangeForNumericType<T, Promotion>::value &&
+             static_cast<Promotion>(x) ==
+                 std::numeric_limits<Promotion>::lowest() &&
+             y == static_cast<U>(-1)))) {
+      return false;
+    }
+
+    // This branch always compiles away if the above branch wasn't removed.
+    if (BASE_NUMERICS_UNLIKELY((!IsValueInRangeForNumericType<Promotion>(x) ||
+                                !IsValueInRangeForNumericType<Promotion>(y)) &&
+                               x)) {
+      return false;
+    }
+
+    const Promotion presult = Promotion(x) / Promotion(y);
+    if (!IsValueInRangeForNumericType<V>(presult))
+      return false;
+    *result = static_cast<V>(presult);
+    return true;
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct CheckedModOp {};
+
+template <typename T, typename U>
+struct CheckedModOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename MaxExponentPromotion<T, U>::type;
+  template <typename V>
+  static constexpr bool Do(T x, U y, V* result) {
+    if (BASE_NUMERICS_UNLIKELY(!y))
+      return false;
+
+    using Promotion = typename BigEnoughPromotion<T, U>::type;
+    if (BASE_NUMERICS_UNLIKELY(
+            (std::is_signed<T>::value && std::is_signed<U>::value &&
+             IsTypeInRangeForNumericType<T, Promotion>::value &&
+             static_cast<Promotion>(x) ==
+                 std::numeric_limits<Promotion>::lowest() &&
+             y == static_cast<U>(-1)))) {
+      *result = 0;
+      return true;
+    }
+
+    const Promotion presult =
+        static_cast<Promotion>(x) % static_cast<Promotion>(y);
+    if (!IsValueInRangeForNumericType<V>(presult))
+      return false;
+    *result = static_cast<Promotion>(presult);
+    return true;
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct CheckedLshOp {};
+
+// Left shift. Shifts less than 0 or greater than or equal to the number
+// of bits in the promoted type are undefined. Shifts of negative values
+// are undefined. Otherwise it is defined when the result fits.
+template <typename T, typename U>
+struct CheckedLshOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = T;
+  template <typename V>
+  static constexpr bool Do(T x, U shift, V* result) {
+    // Disallow negative numbers and verify the shift is in bounds.
+    if (BASE_NUMERICS_LIKELY(!IsValueNegative(x) &&
+                             as_unsigned(shift) <
+                                 as_unsigned(std::numeric_limits<T>::digits))) {
+      // Shift as unsigned to avoid undefined behavior.
+      *result = static_cast<V>(as_unsigned(x) << shift);
+      // If the shift can be reversed, we know it was valid.
+      return *result >> shift == x;
+    }
+
+    // Handle the legal corner-case of a full-width signed shift of zero.
+    if (!std::is_signed<T>::value || x ||
+        as_unsigned(shift) != as_unsigned(std::numeric_limits<T>::digits))
+      return false;
+    *result = 0;
+    return true;
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct CheckedRshOp {};
+
+// Right shift. Shifts less than 0 or greater than or equal to the number
+// of bits in the promoted type are undefined. Otherwise, it is always defined,
+// but a right shift of a negative value is implementation-dependent.
+template <typename T, typename U>
+struct CheckedRshOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = T;
+  template <typename V>
+  static constexpr bool Do(T x, U shift, V* result) {
+    // Use sign conversion to push negative values out of range.
+    if (BASE_NUMERICS_UNLIKELY(as_unsigned(shift) >=
+                               IntegerBitsPlusSign<T>::value)) {
+      return false;
+    }
+
+    const T tmp = x >> shift;
+    if (!IsValueInRangeForNumericType<V>(tmp))
+      return false;
+    *result = static_cast<V>(tmp);
+    return true;
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct CheckedAndOp {};
+
+// For simplicity we support only unsigned integer results.
+template <typename T, typename U>
+struct CheckedAndOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename std::make_unsigned<
+      typename MaxExponentPromotion<T, U>::type>::type;
+  template <typename V>
+  static constexpr bool Do(T x, U y, V* result) {
+    const result_type tmp =
+        static_cast<result_type>(x) & static_cast<result_type>(y);
+    if (!IsValueInRangeForNumericType<V>(tmp))
+      return false;
+    *result = static_cast<V>(tmp);
+    return true;
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct CheckedOrOp {};
+
+// For simplicity we support only unsigned integers.
+template <typename T, typename U>
+struct CheckedOrOp<T,
+                   U,
+                   typename std::enable_if<std::is_integral<T>::value &&
+                                           std::is_integral<U>::value>::type> {
+  using result_type = typename std::make_unsigned<
+      typename MaxExponentPromotion<T, U>::type>::type;
+  template <typename V>
+  static constexpr bool Do(T x, U y, V* result) {
+    const result_type tmp =
+        static_cast<result_type>(x) | static_cast<result_type>(y);
+    if (!IsValueInRangeForNumericType<V>(tmp))
+      return false;
+    *result = static_cast<V>(tmp);
+    return true;
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct CheckedXorOp {};
+
+// For simplicity we support only unsigned integers.
+template <typename T, typename U>
+struct CheckedXorOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename std::make_unsigned<
+      typename MaxExponentPromotion<T, U>::type>::type;
+  template <typename V>
+  static constexpr bool Do(T x, U y, V* result) {
+    const result_type tmp =
+        static_cast<result_type>(x) ^ static_cast<result_type>(y);
+    if (!IsValueInRangeForNumericType<V>(tmp))
+      return false;
+    *result = static_cast<V>(tmp);
+    return true;
+  }
+};
+
+// Max doesn't really need to be implemented this way because it can't fail,
+// but it makes the code much cleaner to use the MathOp wrappers.
+template <typename T, typename U, class Enable = void>
+struct CheckedMaxOp {};
+
+template <typename T, typename U>
+struct CheckedMaxOp<
+    T,
+    U,
+    typename std::enable_if<std::is_arithmetic<T>::value &&
+                            std::is_arithmetic<U>::value>::type> {
+  using result_type = typename MaxExponentPromotion<T, U>::type;
+  template <typename V>
+  static constexpr bool Do(T x, U y, V* result) {
+    const result_type tmp = IsGreater<T, U>::Test(x, y)
+                                ? static_cast<result_type>(x)
+                                : static_cast<result_type>(y);
+    if (!IsValueInRangeForNumericType<V>(tmp))
+      return false;
+    *result = static_cast<V>(tmp);
+    return true;
+  }
+};
+
+// Min doesn't really need to be implemented this way because it can't fail,
+// but it makes the code much cleaner to use the MathOp wrappers.
+template <typename T, typename U, class Enable = void>
+struct CheckedMinOp {};
+
+template <typename T, typename U>
+struct CheckedMinOp<
+    T,
+    U,
+    typename std::enable_if<std::is_arithmetic<T>::value &&
+                            std::is_arithmetic<U>::value>::type> {
+  using result_type = typename LowestValuePromotion<T, U>::type;
+  template <typename V>
+  static constexpr bool Do(T x, U y, V* result) {
+    const result_type tmp = IsLess<T, U>::Test(x, y)
+                                ? static_cast<result_type>(x)
+                                : static_cast<result_type>(y);
+    if (!IsValueInRangeForNumericType<V>(tmp))
+      return false;
+    *result = static_cast<V>(tmp);
+    return true;
+  }
+};
+
+// This is just boilerplate that wraps the standard floating point arithmetic.
+// A macro isn't the nicest solution, but it beats rewriting these repeatedly.
+#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP)                              \
+  template <typename T, typename U>                                      \
+  struct Checked##NAME##Op<                                              \
+      T, U,                                                              \
+      typename std::enable_if<std::is_floating_point<T>::value ||        \
+                              std::is_floating_point<U>::value>::type> { \
+    using result_type = typename MaxExponentPromotion<T, U>::type;       \
+    template <typename V>                                                \
+    static constexpr bool Do(T x, U y, V* result) {                      \
+      using Promotion = typename MaxExponentPromotion<T, U>::type;       \
+      const Promotion presult = x OP y;                                  \
+      if (!IsValueInRangeForNumericType<V>(presult))                     \
+        return false;                                                    \
+      *result = static_cast<V>(presult);                                 \
+      return true;                                                       \
+    }                                                                    \
+  };
+
+BASE_FLOAT_ARITHMETIC_OPS(Add, +)
+BASE_FLOAT_ARITHMETIC_OPS(Sub, -)
+BASE_FLOAT_ARITHMETIC_OPS(Mul, *)
+BASE_FLOAT_ARITHMETIC_OPS(Div, /)
+
+#undef BASE_FLOAT_ARITHMETIC_OPS
+
+// Floats carry around their validity state with them, but integers do not. So,
+// we wrap the underlying value in a specialization in order to hide that detail
+// and expose an interface via accessors.
+enum NumericRepresentation {
+  NUMERIC_INTEGER,
+  NUMERIC_FLOATING,
+  NUMERIC_UNKNOWN
+};
+
+template <typename NumericType>
+struct GetNumericRepresentation {
+  static const NumericRepresentation value =
+      std::is_integral<NumericType>::value
+          ? NUMERIC_INTEGER
+          : (std::is_floating_point<NumericType>::value ? NUMERIC_FLOATING
+                                                        : NUMERIC_UNKNOWN);
+};
+
+template <typename T,
+          NumericRepresentation type = GetNumericRepresentation<T>::value>
+class CheckedNumericState {};
+
+// Integrals require quite a bit of additional housekeeping to manage state.
+template <typename T>
+class CheckedNumericState<T, NUMERIC_INTEGER> {
+ public:
+  template <typename Src = int>
+  constexpr explicit CheckedNumericState(Src value = 0, bool is_valid = true)
+      : is_valid_(is_valid && IsValueInRangeForNumericType<T>(value)),
+        value_(WellDefinedConversionOrZero(value, is_valid_)) {
+    static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric.");
+  }
+
+  template <typename Src>
+  constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs)
+      : CheckedNumericState(rhs.value(), rhs.is_valid()) {}
+
+  constexpr bool is_valid() const { return is_valid_; }
+
+  constexpr T value() const { return value_; }
+
+ private:
+  // Ensures that a type conversion does not trigger undefined behavior.
+  template <typename Src>
+  static constexpr T WellDefinedConversionOrZero(Src value, bool is_valid) {
+    using SrcType = typename internal::UnderlyingType<Src>::type;
+    return (std::is_integral<SrcType>::value || is_valid)
+               ? static_cast<T>(value)
+               : 0;
+  }
+
+  // is_valid_ precedes value_ because member initializers in the constructors
+  // are evaluated in field order, and is_valid_ must be read when initializing
+  // value_.
+  bool is_valid_;
+  T value_;
+};
+
+// Floating points maintain their own validity, but need translation wrappers.
+template <typename T>
+class CheckedNumericState<T, NUMERIC_FLOATING> {
+ public:
+  template <typename Src = double>
+  constexpr explicit CheckedNumericState(Src value = 0.0, bool is_valid = true)
+      : value_(WellDefinedConversionOrNaN(
+            value,
+            is_valid && IsValueInRangeForNumericType<T>(value))) {}
+
+  template <typename Src>
+  constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs)
+      : CheckedNumericState(rhs.value(), rhs.is_valid()) {}
+
+  constexpr bool is_valid() const {
+    // Written this way because std::isfinite is not reliably constexpr.
+    return IsConstantEvaluated()
+               ? value_ <= std::numeric_limits<T>::max() &&
+                     value_ >= std::numeric_limits<T>::lowest()
+               : std::isfinite(value_);
+  }
+
+  constexpr T value() const { return value_; }
+
+ private:
+  // Ensures that a type conversion does not trigger undefined behavior.
+  template <typename Src>
+  static constexpr T WellDefinedConversionOrNaN(Src value, bool is_valid) {
+    using SrcType = typename internal::UnderlyingType<Src>::type;
+    return (StaticDstRangeRelationToSrcRange<T, SrcType>::value ==
+                NUMERIC_RANGE_CONTAINED ||
+            is_valid)
+               ? static_cast<T>(value)
+               : std::numeric_limits<T>::quiet_NaN();
+  }
+
+  T value_;
+};
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_NUMERICS_CHECKED_MATH_IMPL_H_
diff --git a/base/numerics/clamped_math.h b/base/numerics/clamped_math.h
new file mode 100644
index 0000000..fe6b0fe
--- /dev/null
+++ b/base/numerics/clamped_math.h
@@ -0,0 +1,260 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_CLAMPED_MATH_H_
+#define BASE_NUMERICS_CLAMPED_MATH_H_
+
+#include <stddef.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/clamped_math_impl.h"
+
+namespace gurl_base {
+namespace internal {
+
+template <typename T>
+class ClampedNumeric {
+  static_assert(std::is_arithmetic<T>::value,
+                "ClampedNumeric<T>: T must be a numeric type.");
+
+ public:
+  using type = T;
+
+  constexpr ClampedNumeric() : value_(0) {}
+
+  // Copy constructor.
+  template <typename Src>
+  constexpr ClampedNumeric(const ClampedNumeric<Src>& rhs)
+      : value_(saturated_cast<T>(rhs.value_)) {}
+
+  template <typename Src>
+  friend class ClampedNumeric;
+
+  // Strictly speaking, this is not necessary, but declaring this allows class
+  // template argument deduction to be used so that it is possible to simply
+  // write `ClampedNumeric(777)` instead of `ClampedNumeric<int>(777)`.
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  constexpr ClampedNumeric(T value) : value_(value) {}
+
+  // This is not an explicit constructor because we implicitly upgrade regular
+  // numerics to ClampedNumerics to make them easier to use.
+  template <typename Src>
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  constexpr ClampedNumeric(Src value) : value_(saturated_cast<T>(value)) {
+    static_assert(UnderlyingType<Src>::is_numeric, "Argument must be numeric.");
+  }
+
+  // This is not an explicit constructor because we want a seamless conversion
+  // from StrictNumeric types.
+  template <typename Src>
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  constexpr ClampedNumeric(StrictNumeric<Src> value)
+      : value_(saturated_cast<T>(static_cast<Src>(value))) {}
+
+  // Returns a ClampedNumeric of the specified type, cast from the current
+  // ClampedNumeric, and saturated to the destination type.
+  template <typename Dst>
+  constexpr ClampedNumeric<typename UnderlyingType<Dst>::type> Cast() const {
+    return *this;
+  }
+
+  // Prototypes for the supported arithmetic operator overloads.
+  template <typename Src>
+  constexpr ClampedNumeric& operator+=(const Src rhs);
+  template <typename Src>
+  constexpr ClampedNumeric& operator-=(const Src rhs);
+  template <typename Src>
+  constexpr ClampedNumeric& operator*=(const Src rhs);
+  template <typename Src>
+  constexpr ClampedNumeric& operator/=(const Src rhs);
+  template <typename Src>
+  constexpr ClampedNumeric& operator%=(const Src rhs);
+  template <typename Src>
+  constexpr ClampedNumeric& operator<<=(const Src rhs);
+  template <typename Src>
+  constexpr ClampedNumeric& operator>>=(const Src rhs);
+  template <typename Src>
+  constexpr ClampedNumeric& operator&=(const Src rhs);
+  template <typename Src>
+  constexpr ClampedNumeric& operator|=(const Src rhs);
+  template <typename Src>
+  constexpr ClampedNumeric& operator^=(const Src rhs);
+
+  constexpr ClampedNumeric operator-() const {
+    // The negation of two's complement int min is int min, so that's the
+    // only overflow case where we will saturate.
+    return ClampedNumeric<T>(SaturatedNegWrapper(value_));
+  }
+
+  constexpr ClampedNumeric operator~() const {
+    return ClampedNumeric<decltype(InvertWrapper(T()))>(InvertWrapper(value_));
+  }
+
+  constexpr ClampedNumeric Abs() const {
+    // The negation of two's complement int min is int min, so that's the
+    // only overflow case where we will saturate.
+    return ClampedNumeric<T>(SaturatedAbsWrapper(value_));
+  }
+
+  template <typename U>
+  constexpr ClampedNumeric<typename MathWrapper<ClampedMaxOp, T, U>::type> Max(
+      const U rhs) const {
+    using result_type = typename MathWrapper<ClampedMaxOp, T, U>::type;
+    return ClampedNumeric<result_type>(
+        ClampedMaxOp<T, U>::Do(value_, Wrapper<U>::value(rhs)));
+  }
+
+  template <typename U>
+  constexpr ClampedNumeric<typename MathWrapper<ClampedMinOp, T, U>::type> Min(
+      const U rhs) const {
+    using result_type = typename MathWrapper<ClampedMinOp, T, U>::type;
+    return ClampedNumeric<result_type>(
+        ClampedMinOp<T, U>::Do(value_, Wrapper<U>::value(rhs)));
+  }
+
+  // This function is available only for integral types. It returns an unsigned
+  // integer of the same width as the source type, containing the absolute value
+  // of the source, and properly handling signed min.
+  constexpr ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>
+  UnsignedAbs() const {
+    return ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>(
+        SafeUnsignedAbs(value_));
+  }
+
+  constexpr ClampedNumeric& operator++() {
+    *this += 1;
+    return *this;
+  }
+
+  constexpr ClampedNumeric operator++(int) {
+    ClampedNumeric value = *this;
+    *this += 1;
+    return value;
+  }
+
+  constexpr ClampedNumeric& operator--() {
+    *this -= 1;
+    return *this;
+  }
+
+  constexpr ClampedNumeric operator--(int) {
+    ClampedNumeric value = *this;
+    *this -= 1;
+    return value;
+  }
+
+  // These perform the actual math operations on the ClampedNumerics.
+  // Binary arithmetic operations.
+  template <template <typename, typename, typename> class M,
+            typename L,
+            typename R>
+  static constexpr ClampedNumeric MathOp(const L lhs, const R rhs) {
+    using Math = typename MathWrapper<M, L, R>::math;
+    return ClampedNumeric<T>(
+        Math::template Do<T>(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs)));
+  }
+
+  // Assignment arithmetic operations.
+  template <template <typename, typename, typename> class M, typename R>
+  constexpr ClampedNumeric& MathOp(const R rhs) {
+    using Math = typename MathWrapper<M, T, R>::math;
+    *this =
+        ClampedNumeric<T>(Math::template Do<T>(value_, Wrapper<R>::value(rhs)));
+    return *this;
+  }
+
+  template <typename Dst>
+  constexpr operator Dst() const {
+    return saturated_cast<typename ArithmeticOrUnderlyingEnum<Dst>::type>(
+        value_);
+  }
+
+  // This method extracts the raw integer value without saturating it to the
+  // destination type as the conversion operator does. This is useful when
+  // e.g. assigning to an auto type or passing as a deduced template parameter.
+  constexpr T RawValue() const { return value_; }
+
+ private:
+  T value_;
+
+  // These wrappers allow us to handle state the same way for both
+  // ClampedNumeric and POD arithmetic types.
+  template <typename Src>
+  struct Wrapper {
+    static constexpr typename UnderlyingType<Src>::type value(Src value) {
+      return value;
+    }
+  };
+};
+
+// Convenience wrapper to return a new ClampedNumeric from the provided
+// arithmetic or ClampedNumericType.
+template <typename T>
+constexpr ClampedNumeric<typename UnderlyingType<T>::type> MakeClampedNum(
+    const T value) {
+  return value;
+}
+
+// These implement the variadic wrapper for the math operations.
+template <template <typename, typename, typename> class M,
+          typename L,
+          typename R>
+constexpr ClampedNumeric<typename MathWrapper<M, L, R>::type> ClampMathOp(
+    const L lhs,
+    const R rhs) {
+  using Math = typename MathWrapper<M, L, R>::math;
+  return ClampedNumeric<typename Math::result_type>::template MathOp<M>(lhs,
+                                                                        rhs);
+}
+
+// General purpose wrapper template for arithmetic operations.
+template <template <typename, typename, typename> class M,
+          typename L,
+          typename R,
+          typename... Args>
+constexpr auto ClampMathOp(const L lhs, const R rhs, const Args... args) {
+  return ClampMathOp<M>(ClampMathOp<M>(lhs, rhs), args...);
+}
+
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Add, +, +=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Sub, -, -=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mul, *, *=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Div, /, /=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mod, %, %=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Lsh, <<, <<=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Rsh, >>, >>=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, And, &, &=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Or, |, |=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Xor, ^, ^=)
+BASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Max)
+BASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Min)
+BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLess, <)
+BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLessOrEqual, <=)
+BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreater, >)
+BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreaterOrEqual, >=)
+BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsEqual, ==)
+BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsNotEqual, !=)
+
+}  // namespace internal
+
+using internal::ClampAdd;
+using internal::ClampAnd;
+using internal::ClampDiv;
+using internal::ClampedNumeric;
+using internal::ClampLsh;
+using internal::ClampMax;
+using internal::ClampMin;
+using internal::ClampMod;
+using internal::ClampMul;
+using internal::ClampOr;
+using internal::ClampRsh;
+using internal::ClampSub;
+using internal::ClampXor;
+using internal::MakeClampedNum;
+
+}  // namespace base
+
+#endif  // BASE_NUMERICS_CLAMPED_MATH_H_
diff --git a/base/numerics/clamped_math_impl.h b/base/numerics/clamped_math_impl.h
new file mode 100644
index 0000000..10023f0
--- /dev/null
+++ b/base/numerics/clamped_math_impl.h
@@ -0,0 +1,340 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_CLAMPED_MATH_IMPL_H_
+#define BASE_NUMERICS_CLAMPED_MATH_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/checked_math.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/numerics/safe_math_shared_impl.h"
+
+namespace gurl_base {
+namespace internal {
+
+template <typename T,
+          typename std::enable_if<std::is_integral<T>::value &&
+                                  std::is_signed<T>::value>::type* = nullptr>
+constexpr T SaturatedNegWrapper(T value) {
+  return IsConstantEvaluated() || !ClampedNegFastOp<T>::is_supported
+             ? (NegateWrapper(value) != std::numeric_limits<T>::lowest()
+                    ? NegateWrapper(value)
+                    : std::numeric_limits<T>::max())
+             : ClampedNegFastOp<T>::Do(value);
+}
+
+template <typename T,
+          typename std::enable_if<std::is_integral<T>::value &&
+                                  !std::is_signed<T>::value>::type* = nullptr>
+constexpr T SaturatedNegWrapper(T value) {
+  return T(0);
+}
+
+template <
+    typename T,
+    typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
+constexpr T SaturatedNegWrapper(T value) {
+  return -value;
+}
+
+template <typename T,
+          typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
+constexpr T SaturatedAbsWrapper(T value) {
+  // The calculation below is a static identity for unsigned types, but for
+  // signed integer types it provides a non-branching, saturated absolute value.
+  // This works because SafeUnsignedAbs() returns an unsigned type, which can
+  // represent the absolute value of all negative numbers of an equal-width
+  // integer type. The call to IsValueNegative() then detects overflow in the
+  // special case of numeric_limits<T>::min(), by evaluating the bit pattern as
+  // a signed integer value. If it is the overflow case, we end up subtracting
+  // one from the unsigned result, thus saturating to numeric_limits<T>::max().
+  return static_cast<T>(
+      SafeUnsignedAbs(value) -
+      IsValueNegative<T>(static_cast<T>(SafeUnsignedAbs(value))));
+}
+
+template <
+    typename T,
+    typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
+constexpr T SaturatedAbsWrapper(T value) {
+  return value < 0 ? -value : value;
+}
+
+template <typename T, typename U, class Enable = void>
+struct ClampedAddOp {};
+
+template <typename T, typename U>
+struct ClampedAddOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename MaxExponentPromotion<T, U>::type;
+  template <typename V = result_type>
+  static constexpr V Do(T x, U y) {
+    if (!IsConstantEvaluated() && ClampedAddFastOp<T, U>::is_supported)
+      return ClampedAddFastOp<T, U>::template Do<V>(x, y);
+
+    static_assert(std::is_same<V, result_type>::value ||
+                      IsTypeInRangeForNumericType<U, V>::value,
+                  "The saturation result cannot be determined from the "
+                  "provided types.");
+    const V saturated = CommonMaxOrMin<V>(IsValueNegative(y));
+    V result = {};
+    return BASE_NUMERICS_LIKELY((CheckedAddOp<T, U>::Do(x, y, &result)))
+               ? result
+               : saturated;
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedSubOp {};
+
+template <typename T, typename U>
+struct ClampedSubOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename MaxExponentPromotion<T, U>::type;
+  template <typename V = result_type>
+  static constexpr V Do(T x, U y) {
+    if (!IsConstantEvaluated() && ClampedSubFastOp<T, U>::is_supported)
+      return ClampedSubFastOp<T, U>::template Do<V>(x, y);
+
+    static_assert(std::is_same<V, result_type>::value ||
+                      IsTypeInRangeForNumericType<U, V>::value,
+                  "The saturation result cannot be determined from the "
+                  "provided types.");
+    const V saturated = CommonMaxOrMin<V>(!IsValueNegative(y));
+    V result = {};
+    return BASE_NUMERICS_LIKELY((CheckedSubOp<T, U>::Do(x, y, &result)))
+               ? result
+               : saturated;
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedMulOp {};
+
+template <typename T, typename U>
+struct ClampedMulOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename MaxExponentPromotion<T, U>::type;
+  template <typename V = result_type>
+  static constexpr V Do(T x, U y) {
+    if (!IsConstantEvaluated() && ClampedMulFastOp<T, U>::is_supported)
+      return ClampedMulFastOp<T, U>::template Do<V>(x, y);
+
+    V result = {};
+    const V saturated =
+        CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y));
+    return BASE_NUMERICS_LIKELY((CheckedMulOp<T, U>::Do(x, y, &result)))
+               ? result
+               : saturated;
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedDivOp {};
+
+template <typename T, typename U>
+struct ClampedDivOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename MaxExponentPromotion<T, U>::type;
+  template <typename V = result_type>
+  static constexpr V Do(T x, U y) {
+    V result = {};
+    if (BASE_NUMERICS_LIKELY((CheckedDivOp<T, U>::Do(x, y, &result))))
+      return result;
+    // Saturation goes to max, min, or NaN (if x is zero).
+    return x ? CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y))
+             : SaturationDefaultLimits<V>::NaN();
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedModOp {};
+
+template <typename T, typename U>
+struct ClampedModOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename MaxExponentPromotion<T, U>::type;
+  template <typename V = result_type>
+  static constexpr V Do(T x, U y) {
+    V result = {};
+    return BASE_NUMERICS_LIKELY((CheckedModOp<T, U>::Do(x, y, &result)))
+               ? result
+               : x;
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedLshOp {};
+
+// Left shift. Non-zero values saturate in the direction of the sign. A zero
+// shifted by any value always results in zero.
+template <typename T, typename U>
+struct ClampedLshOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = T;
+  template <typename V = result_type>
+  static constexpr V Do(T x, U shift) {
+    static_assert(!std::is_signed<U>::value, "Shift value must be unsigned.");
+    if (BASE_NUMERICS_LIKELY(shift < std::numeric_limits<T>::digits)) {
+      // Shift as unsigned to avoid undefined behavior.
+      V result = static_cast<V>(as_unsigned(x) << shift);
+      // If the shift can be reversed, we know it was valid.
+      if (BASE_NUMERICS_LIKELY(result >> shift == x))
+        return result;
+    }
+    return x ? CommonMaxOrMin<V>(IsValueNegative(x)) : 0;
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedRshOp {};
+
+// Right shift. Negative values saturate to -1. Positive or 0 saturates to 0.
+template <typename T, typename U>
+struct ClampedRshOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = T;
+  template <typename V = result_type>
+  static constexpr V Do(T x, U shift) {
+    static_assert(!std::is_signed<U>::value, "Shift value must be unsigned.");
+    // Signed right shift is odd, because it saturates to -1 or 0.
+    const V saturated = as_unsigned(V(0)) - IsValueNegative(x);
+    return BASE_NUMERICS_LIKELY(shift < IntegerBitsPlusSign<T>::value)
+               ? saturated_cast<V>(x >> shift)
+               : saturated;
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedAndOp {};
+
+template <typename T, typename U>
+struct ClampedAndOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename std::make_unsigned<
+      typename MaxExponentPromotion<T, U>::type>::type;
+  template <typename V>
+  static constexpr V Do(T x, U y) {
+    return static_cast<result_type>(x) & static_cast<result_type>(y);
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedOrOp {};
+
+// For simplicity we promote to unsigned integers.
+template <typename T, typename U>
+struct ClampedOrOp<T,
+                   U,
+                   typename std::enable_if<std::is_integral<T>::value &&
+                                           std::is_integral<U>::value>::type> {
+  using result_type = typename std::make_unsigned<
+      typename MaxExponentPromotion<T, U>::type>::type;
+  template <typename V>
+  static constexpr V Do(T x, U y) {
+    return static_cast<result_type>(x) | static_cast<result_type>(y);
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedXorOp {};
+
+// For simplicity we support only unsigned integers.
+template <typename T, typename U>
+struct ClampedXorOp<T,
+                    U,
+                    typename std::enable_if<std::is_integral<T>::value &&
+                                            std::is_integral<U>::value>::type> {
+  using result_type = typename std::make_unsigned<
+      typename MaxExponentPromotion<T, U>::type>::type;
+  template <typename V>
+  static constexpr V Do(T x, U y) {
+    return static_cast<result_type>(x) ^ static_cast<result_type>(y);
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedMaxOp {};
+
+template <typename T, typename U>
+struct ClampedMaxOp<
+    T,
+    U,
+    typename std::enable_if<std::is_arithmetic<T>::value &&
+                            std::is_arithmetic<U>::value>::type> {
+  using result_type = typename MaxExponentPromotion<T, U>::type;
+  template <typename V = result_type>
+  static constexpr V Do(T x, U y) {
+    return IsGreater<T, U>::Test(x, y) ? saturated_cast<V>(x)
+                                       : saturated_cast<V>(y);
+  }
+};
+
+template <typename T, typename U, class Enable = void>
+struct ClampedMinOp {};
+
+template <typename T, typename U>
+struct ClampedMinOp<
+    T,
+    U,
+    typename std::enable_if<std::is_arithmetic<T>::value &&
+                            std::is_arithmetic<U>::value>::type> {
+  using result_type = typename LowestValuePromotion<T, U>::type;
+  template <typename V = result_type>
+  static constexpr V Do(T x, U y) {
+    return IsLess<T, U>::Test(x, y) ? saturated_cast<V>(x)
+                                    : saturated_cast<V>(y);
+  }
+};
+
+// This is just boilerplate that wraps the standard floating point arithmetic.
+// A macro isn't the nicest solution, but it beats rewriting these repeatedly.
+#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP)                              \
+  template <typename T, typename U>                                      \
+  struct Clamped##NAME##Op<                                              \
+      T, U,                                                              \
+      typename std::enable_if<std::is_floating_point<T>::value ||        \
+                              std::is_floating_point<U>::value>::type> { \
+    using result_type = typename MaxExponentPromotion<T, U>::type;       \
+    template <typename V = result_type>                                  \
+    static constexpr V Do(T x, U y) {                                    \
+      return saturated_cast<V>(x OP y);                                  \
+    }                                                                    \
+  };
+
+BASE_FLOAT_ARITHMETIC_OPS(Add, +)
+BASE_FLOAT_ARITHMETIC_OPS(Sub, -)
+BASE_FLOAT_ARITHMETIC_OPS(Mul, *)
+BASE_FLOAT_ARITHMETIC_OPS(Div, /)
+
+#undef BASE_FLOAT_ARITHMETIC_OPS
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_NUMERICS_CLAMPED_MATH_IMPL_H_
diff --git a/base/numerics/math_constants.h b/base/numerics/math_constants.h
new file mode 100644
index 0000000..c406ab9
--- /dev/null
+++ b/base/numerics/math_constants.h
@@ -0,0 +1,19 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_MATH_CONSTANTS_H_
+#define BASE_NUMERICS_MATH_CONSTANTS_H_
+
+namespace gurl_base {
+
+constexpr double kPiDouble = 3.14159265358979323846;
+constexpr float kPiFloat = 3.14159265358979323846f;
+
+// The mean acceleration due to gravity on Earth in m/s^2.
+constexpr double kMeanGravityDouble = 9.80665;
+constexpr float kMeanGravityFloat = 9.80665f;
+
+}  // namespace base
+
+#endif  // BASE_NUMERICS_MATH_CONSTANTS_H_
diff --git a/base/numerics/ostream_operators.h b/base/numerics/ostream_operators.h
new file mode 100644
index 0000000..100c37f
--- /dev/null
+++ b/base/numerics/ostream_operators.h
@@ -0,0 +1,35 @@
+// Copyright 2021 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_OSTREAM_OPERATORS_H_
+#define BASE_NUMERICS_OSTREAM_OPERATORS_H_
+
+#include <ostream>
+
+namespace gurl_base {
+namespace internal {
+
+template <typename T>
+class ClampedNumeric;
+template <typename T>
+class StrictNumeric;
+
+// Overload the ostream output operator to make logging work nicely.
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const StrictNumeric<T>& value) {
+  os << static_cast<T>(value);
+  return os;
+}
+
+// Overload the ostream output operator to make logging work nicely.
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const ClampedNumeric<T>& value) {
+  os << static_cast<T>(value);
+  return os;
+}
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_NUMERICS_OSTREAM_OPERATORS_H_
diff --git a/base/numerics/ranges.h b/base/numerics/ranges.h
new file mode 100644
index 0000000..98085eb
--- /dev/null
+++ b/base/numerics/ranges.h
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_RANGES_H_
+#define BASE_NUMERICS_RANGES_H_
+
+#include <cmath>
+#include <type_traits>
+
+namespace gurl_base {
+
+template <typename T>
+constexpr bool IsApproximatelyEqual(T lhs, T rhs, T tolerance) {
+  static_assert(std::is_arithmetic<T>::value, "Argument must be arithmetic");
+  return std::abs(rhs - lhs) <= tolerance;
+}
+
+}  // namespace base
+
+#endif  // BASE_NUMERICS_RANGES_H_
diff --git a/base/numerics/safe_conversions.h b/base/numerics/safe_conversions.h
index df84c7e..4a9494e 100644
--- a/base/numerics/safe_conversions.h
+++ b/base/numerics/safe_conversions.h
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -284,11 +284,17 @@
   constexpr StrictNumeric(const StrictNumeric<Src>& rhs)
       : value_(strict_cast<T>(rhs.value_)) {}
 
+  // Strictly speaking, this is not necessary, but declaring this allows class
+  // template argument deduction to be used so that it is possible to simply
+  // write `StrictNumeric(777)` instead of `StrictNumeric<int>(777)`.
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  constexpr StrictNumeric(T value) : value_(value) {}
+
   // This is not an explicit constructor because we implicitly upgrade regular
   // numerics to StrictNumerics to make them easier to use.
   template <typename Src>
-  constexpr StrictNumeric(Src value)  // NOLINT(runtime/explicit)
-      : value_(strict_cast<T>(value)) {}
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  constexpr StrictNumeric(Src value) : value_(strict_cast<T>(value)) {}
 
   // If you got here from a compiler error, it's because you tried to assign
   // from a source type to a destination type that has insufficient range.
diff --git a/base/numerics/safe_conversions_arm_impl.h b/base/numerics/safe_conversions_arm_impl.h
new file mode 100644
index 0000000..176af95
--- /dev/null
+++ b/base/numerics/safe_conversions_arm_impl.h
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_ARM_IMPL_H_
+#define BASE_NUMERICS_SAFE_CONVERSIONS_ARM_IMPL_H_
+
+#include <cassert>
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/safe_conversions_impl.h"
+
+namespace gurl_base {
+namespace internal {
+
+// Fast saturation to a destination type.
+template <typename Dst, typename Src>
+struct SaturateFastAsmOp {
+  static constexpr bool is_supported =
+      kEnableAsmCode && std::is_signed<Src>::value &&
+      std::is_integral<Dst>::value && std::is_integral<Src>::value &&
+      IntegerBitsPlusSign<Src>::value <= IntegerBitsPlusSign<int32_t>::value &&
+      IntegerBitsPlusSign<Dst>::value <= IntegerBitsPlusSign<int32_t>::value &&
+      !IsTypeInRangeForNumericType<Dst, Src>::value;
+
+  __attribute__((always_inline)) static Dst Do(Src value) {
+    int32_t src = value;
+    typename std::conditional<std::is_signed<Dst>::value, int32_t,
+                              uint32_t>::type result;
+    if (std::is_signed<Dst>::value) {
+      asm("ssat %[dst], %[shift], %[src]"
+          : [dst] "=r"(result)
+          : [src] "r"(src), [shift] "n"(IntegerBitsPlusSign<Dst>::value <= 32
+                                            ? IntegerBitsPlusSign<Dst>::value
+                                            : 32));
+    } else {
+      asm("usat %[dst], %[shift], %[src]"
+          : [dst] "=r"(result)
+          : [src] "r"(src), [shift] "n"(IntegerBitsPlusSign<Dst>::value < 32
+                                            ? IntegerBitsPlusSign<Dst>::value
+                                            : 31));
+    }
+    return static_cast<Dst>(result);
+  }
+};
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_NUMERICS_SAFE_CONVERSIONS_ARM_IMPL_H_
diff --git a/base/numerics/safe_conversions_impl.h b/base/numerics/safe_conversions_impl.h
index 07a927e..abe1706 100644
--- a/base/numerics/safe_conversions_impl.h
+++ b/base/numerics/safe_conversions_impl.h
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/numerics/safe_math.h b/base/numerics/safe_math.h
new file mode 100644
index 0000000..25d10f6
--- /dev/null
+++ b/base/numerics/safe_math.h
@@ -0,0 +1,12 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_MATH_H_
+#define BASE_NUMERICS_SAFE_MATH_H_
+
+#include "base/numerics/checked_math.h"
+#include "base/numerics/clamped_math.h"
+#include "base/numerics/safe_conversions.h"
+
+#endif  // BASE_NUMERICS_SAFE_MATH_H_
diff --git a/base/numerics/safe_math_arm_impl.h b/base/numerics/safe_math_arm_impl.h
new file mode 100644
index 0000000..f419773
--- /dev/null
+++ b/base/numerics/safe_math_arm_impl.h
@@ -0,0 +1,125 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
+#define BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
+
+#include <cassert>
+#include <type_traits>
+
+#include "base/numerics/safe_conversions.h"
+
+namespace gurl_base {
+namespace internal {
+
+template <typename T, typename U>
+struct CheckedMulFastAsmOp {
+  static const bool is_supported =
+      kEnableAsmCode && FastIntegerArithmeticPromotion<T, U>::is_contained;
+
+  // The following is not an assembler routine and is thus constexpr safe, it
+  // just emits much more efficient code than the Clang and GCC builtins for
+  // performing overflow-checked multiplication when a twice wider type is
+  // available. The below compiles down to 2-3 instructions, depending on the
+  // width of the types in use.
+  // As an example, an int32_t multiply compiles to:
+  //    smull   r0, r1, r0, r1
+  //    cmp     r1, r1, asr #31
+  // And an int16_t multiply compiles to:
+  //    smulbb  r1, r1, r0
+  //    asr     r2, r1, #16
+  //    cmp     r2, r1, asr #15
+  template <typename V>
+  static constexpr bool Do(T x, U y, V* result) {
+    using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+    Promotion presult;
+
+    presult = static_cast<Promotion>(x) * static_cast<Promotion>(y);
+    if (!IsValueInRangeForNumericType<V>(presult))
+      return false;
+    *result = static_cast<V>(presult);
+    return true;
+  }
+};
+
+template <typename T, typename U>
+struct ClampedAddFastAsmOp {
+  static const bool is_supported =
+      kEnableAsmCode && BigEnoughPromotion<T, U>::is_contained &&
+      IsTypeInRangeForNumericType<
+          int32_t,
+          typename BigEnoughPromotion<T, U>::type>::value;
+
+  template <typename V>
+  __attribute__((always_inline)) static V Do(T x, U y) {
+    // This will get promoted to an int, so let the compiler do whatever is
+    // clever and rely on the saturated cast to bounds check.
+    if (IsIntegerArithmeticSafe<int, T, U>::value)
+      return saturated_cast<V>(static_cast<int>(x) + static_cast<int>(y));
+
+    int32_t result;
+    int32_t x_i32 = checked_cast<int32_t>(x);
+    int32_t y_i32 = checked_cast<int32_t>(y);
+
+    asm("qadd %[result], %[first], %[second]"
+        : [result] "=r"(result)
+        : [first] "r"(x_i32), [second] "r"(y_i32));
+    return saturated_cast<V>(result);
+  }
+};
+
+template <typename T, typename U>
+struct ClampedSubFastAsmOp {
+  static const bool is_supported =
+      kEnableAsmCode && BigEnoughPromotion<T, U>::is_contained &&
+      IsTypeInRangeForNumericType<
+          int32_t,
+          typename BigEnoughPromotion<T, U>::type>::value;
+
+  template <typename V>
+  __attribute__((always_inline)) static V Do(T x, U y) {
+    // This will get promoted to an int, so let the compiler do whatever is
+    // clever and rely on the saturated cast to bounds check.
+    if (IsIntegerArithmeticSafe<int, T, U>::value)
+      return saturated_cast<V>(static_cast<int>(x) - static_cast<int>(y));
+
+    int32_t result;
+    int32_t x_i32 = checked_cast<int32_t>(x);
+    int32_t y_i32 = checked_cast<int32_t>(y);
+
+    asm("qsub %[result], %[first], %[second]"
+        : [result] "=r"(result)
+        : [first] "r"(x_i32), [second] "r"(y_i32));
+    return saturated_cast<V>(result);
+  }
+};
+
+template <typename T, typename U>
+struct ClampedMulFastAsmOp {
+  static const bool is_supported =
+      kEnableAsmCode && CheckedMulFastAsmOp<T, U>::is_supported;
+
+  template <typename V>
+  __attribute__((always_inline)) static V Do(T x, U y) {
+    // Use the CheckedMulFastAsmOp for full-width 32-bit values, because
+    // it's fewer instructions than promoting and then saturating.
+    if (!IsIntegerArithmeticSafe<int32_t, T, U>::value &&
+        !IsIntegerArithmeticSafe<uint32_t, T, U>::value) {
+      V result;
+      return CheckedMulFastAsmOp<T, U>::Do(x, y, &result)
+                 ? result
+                 : CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y));
+    }
+
+    assert((FastIntegerArithmeticPromotion<T, U>::is_contained));
+    using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+    return saturated_cast<V>(static_cast<Promotion>(x) *
+                             static_cast<Promotion>(y));
+  }
+};
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
diff --git a/base/numerics/safe_math_clang_gcc_impl.h b/base/numerics/safe_math_clang_gcc_impl.h
new file mode 100644
index 0000000..a11ab06
--- /dev/null
+++ b/base/numerics/safe_math_clang_gcc_impl.h
@@ -0,0 +1,157 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
+#define BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
+
+#include <cassert>
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/safe_conversions.h"
+
+#if !defined(__native_client__) && (defined(__ARMEL__) || defined(__arch64__))
+#include "base/numerics/safe_math_arm_impl.h"
+#define BASE_HAS_ASSEMBLER_SAFE_MATH (1)
+#else
+#define BASE_HAS_ASSEMBLER_SAFE_MATH (0)
+#endif
+
+namespace gurl_base {
+namespace internal {
+
+// These are the non-functioning boilerplate implementations of the optimized
+// safe math routines.
+#if !BASE_HAS_ASSEMBLER_SAFE_MATH
+template <typename T, typename U>
+struct CheckedMulFastAsmOp {
+  static const bool is_supported = false;
+  template <typename V>
+  static constexpr bool Do(T, U, V*) {
+    // Force a compile failure if instantiated.
+    return CheckOnFailure::template HandleFailure<bool>();
+  }
+};
+
+template <typename T, typename U>
+struct ClampedAddFastAsmOp {
+  static const bool is_supported = false;
+  template <typename V>
+  static constexpr V Do(T, U) {
+    // Force a compile failure if instantiated.
+    return CheckOnFailure::template HandleFailure<V>();
+  }
+};
+
+template <typename T, typename U>
+struct ClampedSubFastAsmOp {
+  static const bool is_supported = false;
+  template <typename V>
+  static constexpr V Do(T, U) {
+    // Force a compile failure if instantiated.
+    return CheckOnFailure::template HandleFailure<V>();
+  }
+};
+
+template <typename T, typename U>
+struct ClampedMulFastAsmOp {
+  static const bool is_supported = false;
+  template <typename V>
+  static constexpr V Do(T, U) {
+    // Force a compile failure if instantiated.
+    return CheckOnFailure::template HandleFailure<V>();
+  }
+};
+#endif  // BASE_HAS_ASSEMBLER_SAFE_MATH
+#undef BASE_HAS_ASSEMBLER_SAFE_MATH
+
+template <typename T, typename U>
+struct CheckedAddFastOp {
+  static const bool is_supported = true;
+  template <typename V>
+  __attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
+    return !__builtin_add_overflow(x, y, result);
+  }
+};
+
+template <typename T, typename U>
+struct CheckedSubFastOp {
+  static const bool is_supported = true;
+  template <typename V>
+  __attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
+    return !__builtin_sub_overflow(x, y, result);
+  }
+};
+
+template <typename T, typename U>
+struct CheckedMulFastOp {
+#if defined(__clang__)
+  // TODO(jschuh): Get the Clang runtime library issues sorted out so we can
+  // support full-width, mixed-sign multiply builtins.
+  // https://crbug.com/613003
+  // We can support intptr_t, uintptr_t, or a smaller common type.
+  static const bool is_supported =
+      (IsTypeInRangeForNumericType<intptr_t, T>::value &&
+       IsTypeInRangeForNumericType<intptr_t, U>::value) ||
+      (IsTypeInRangeForNumericType<uintptr_t, T>::value &&
+       IsTypeInRangeForNumericType<uintptr_t, U>::value);
+#else
+  static const bool is_supported = true;
+#endif
+  template <typename V>
+  __attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
+    return CheckedMulFastAsmOp<T, U>::is_supported
+               ? CheckedMulFastAsmOp<T, U>::Do(x, y, result)
+               : !__builtin_mul_overflow(x, y, result);
+  }
+};
+
+template <typename T, typename U>
+struct ClampedAddFastOp {
+  static const bool is_supported = ClampedAddFastAsmOp<T, U>::is_supported;
+  template <typename V>
+  __attribute__((always_inline)) static V Do(T x, U y) {
+    return ClampedAddFastAsmOp<T, U>::template Do<V>(x, y);
+  }
+};
+
+template <typename T, typename U>
+struct ClampedSubFastOp {
+  static const bool is_supported = ClampedSubFastAsmOp<T, U>::is_supported;
+  template <typename V>
+  __attribute__((always_inline)) static V Do(T x, U y) {
+    return ClampedSubFastAsmOp<T, U>::template Do<V>(x, y);
+  }
+};
+
+template <typename T, typename U>
+struct ClampedMulFastOp {
+  static const bool is_supported = ClampedMulFastAsmOp<T, U>::is_supported;
+  template <typename V>
+  __attribute__((always_inline)) static V Do(T x, U y) {
+    return ClampedMulFastAsmOp<T, U>::template Do<V>(x, y);
+  }
+};
+
+template <typename T>
+struct ClampedNegFastOp {
+  static const bool is_supported = std::is_signed<T>::value;
+  __attribute__((always_inline)) static T Do(T value) {
+    // Use this when there is no assembler path available.
+    if (!ClampedSubFastAsmOp<T, T>::is_supported) {
+      T result;
+      return !__builtin_sub_overflow(T(0), value, &result)
+                 ? result
+                 : std::numeric_limits<T>::max();
+    }
+
+    // Fallback to the normal subtraction path.
+    return ClampedSubFastOp<T, T>::template Do<T>(T(0), value);
+  }
+};
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
diff --git a/base/numerics/safe_math_shared_impl.h b/base/numerics/safe_math_shared_impl.h
new file mode 100644
index 0000000..d0030fc
--- /dev/null
+++ b/base/numerics/safe_math_shared_impl.h
@@ -0,0 +1,216 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_
+#define BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <cassert>
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/safe_conversions.h"
+#include "build/build_config.h"
+
+#if BUILDFLAG(IS_ASMJS)
+// Optimized safe math instructions are incompatible with asmjs.
+#define BASE_HAS_OPTIMIZED_SAFE_MATH (0)
+// Where available use builtin math overflow support on Clang and GCC.
+#elif !defined(__native_client__) &&                       \
+    ((defined(__clang__) &&                                \
+      ((__clang_major__ > 3) ||                            \
+       (__clang_major__ == 3 && __clang_minor__ >= 4))) || \
+     (defined(__GNUC__) && __GNUC__ >= 5))
+#include "base/numerics/safe_math_clang_gcc_impl.h"
+#define BASE_HAS_OPTIMIZED_SAFE_MATH (1)
+#else
+#define BASE_HAS_OPTIMIZED_SAFE_MATH (0)
+#endif
+
+namespace gurl_base {
+namespace internal {
+
+// These are the non-functioning boilerplate implementations of the optimized
+// safe math routines.
+#if !BASE_HAS_OPTIMIZED_SAFE_MATH
+template <typename T, typename U>
+struct CheckedAddFastOp {
+  static const bool is_supported = false;
+  template <typename V>
+  static constexpr bool Do(T, U, V*) {
+    // Force a compile failure if instantiated.
+    return CheckOnFailure::template HandleFailure<bool>();
+  }
+};
+
+template <typename T, typename U>
+struct CheckedSubFastOp {
+  static const bool is_supported = false;
+  template <typename V>
+  static constexpr bool Do(T, U, V*) {
+    // Force a compile failure if instantiated.
+    return CheckOnFailure::template HandleFailure<bool>();
+  }
+};
+
+template <typename T, typename U>
+struct CheckedMulFastOp {
+  static const bool is_supported = false;
+  template <typename V>
+  static constexpr bool Do(T, U, V*) {
+    // Force a compile failure if instantiated.
+    return CheckOnFailure::template HandleFailure<bool>();
+  }
+};
+
+template <typename T, typename U>
+struct ClampedAddFastOp {
+  static const bool is_supported = false;
+  template <typename V>
+  static constexpr V Do(T, U) {
+    // Force a compile failure if instantiated.
+    return CheckOnFailure::template HandleFailure<V>();
+  }
+};
+
+template <typename T, typename U>
+struct ClampedSubFastOp {
+  static const bool is_supported = false;
+  template <typename V>
+  static constexpr V Do(T, U) {
+    // Force a compile failure if instantiated.
+    return CheckOnFailure::template HandleFailure<V>();
+  }
+};
+
+template <typename T, typename U>
+struct ClampedMulFastOp {
+  static const bool is_supported = false;
+  template <typename V>
+  static constexpr V Do(T, U) {
+    // Force a compile failure if instantiated.
+    return CheckOnFailure::template HandleFailure<V>();
+  }
+};
+
+template <typename T>
+struct ClampedNegFastOp {
+  static const bool is_supported = false;
+  static constexpr T Do(T) {
+    // Force a compile failure if instantiated.
+    return CheckOnFailure::template HandleFailure<T>();
+  }
+};
+#endif  // BASE_HAS_OPTIMIZED_SAFE_MATH
+#undef BASE_HAS_OPTIMIZED_SAFE_MATH
+
+// This is used for UnsignedAbs, where we need to support floating-point
+// template instantiations even though we don't actually support the operations.
+// However, there is no corresponding implementation of e.g. SafeUnsignedAbs,
+// so the float versions will not compile.
+template <typename Numeric,
+          bool IsInteger = std::is_integral<Numeric>::value,
+          bool IsFloat = std::is_floating_point<Numeric>::value>
+struct UnsignedOrFloatForSize;
+
+template <typename Numeric>
+struct UnsignedOrFloatForSize<Numeric, true, false> {
+  using type = typename std::make_unsigned<Numeric>::type;
+};
+
+template <typename Numeric>
+struct UnsignedOrFloatForSize<Numeric, false, true> {
+  using type = Numeric;
+};
+
+// Wrap the unary operations to allow SFINAE when instantiating integrals versus
+// floating points. These don't perform any overflow checking. Rather, they
+// exhibit well-defined overflow semantics and rely on the caller to detect
+// if an overflow occurred.
+
+template <typename T,
+          typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
+constexpr T NegateWrapper(T value) {
+  using UnsignedT = typename std::make_unsigned<T>::type;
+  // This will compile to a NEG on Intel, and is normal negation on ARM.
+  return static_cast<T>(UnsignedT(0) - static_cast<UnsignedT>(value));
+}
+
+template <
+    typename T,
+    typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
+constexpr T NegateWrapper(T value) {
+  return -value;
+}
+
+template <typename T,
+          typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
+constexpr typename std::make_unsigned<T>::type InvertWrapper(T value) {
+  return ~value;
+}
+
+template <typename T,
+          typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
+constexpr T AbsWrapper(T value) {
+  return static_cast<T>(SafeUnsignedAbs(value));
+}
+
+template <
+    typename T,
+    typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
+constexpr T AbsWrapper(T value) {
+  return value < 0 ? -value : value;
+}
+
+template <template <typename, typename, typename> class M,
+          typename L,
+          typename R>
+struct MathWrapper {
+  using math = M<typename UnderlyingType<L>::type,
+                 typename UnderlyingType<R>::type,
+                 void>;
+  using type = typename math::result_type;
+};
+
+// The following macros are just boilerplate for the standard arithmetic
+// operator overloads and variadic function templates. A macro isn't the nicest
+// solution, but it beats rewriting these over and over again.
+#define BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME)       \
+  template <typename L, typename R, typename... Args>                   \
+  constexpr auto CL_ABBR##OP_NAME(const L lhs, const R rhs,             \
+                                  const Args... args) {                 \
+    return CL_ABBR##MathOp<CLASS##OP_NAME##Op, L, R, Args...>(lhs, rhs, \
+                                                              args...); \
+  }
+
+#define BASE_NUMERIC_ARITHMETIC_OPERATORS(CLASS, CL_ABBR, OP_NAME, OP, CMP_OP) \
+  /* Binary arithmetic operator for all CLASS##Numeric operations. */          \
+  template <typename L, typename R,                                            \
+            typename std::enable_if<Is##CLASS##Op<L, R>::value>::type* =       \
+                nullptr>                                                       \
+  constexpr CLASS##Numeric<                                                    \
+      typename MathWrapper<CLASS##OP_NAME##Op, L, R>::type>                    \
+  operator OP(const L lhs, const R rhs) {                                      \
+    return decltype(lhs OP rhs)::template MathOp<CLASS##OP_NAME##Op>(lhs,      \
+                                                                     rhs);     \
+  }                                                                            \
+  /* Assignment arithmetic operator implementation from CLASS##Numeric. */     \
+  template <typename L>                                                        \
+  template <typename R>                                                        \
+  constexpr CLASS##Numeric<L>& CLASS##Numeric<L>::operator CMP_OP(             \
+      const R rhs) {                                                           \
+    return MathOp<CLASS##OP_NAME##Op>(rhs);                                    \
+  }                                                                            \
+  /* Variadic arithmetic functions that return CLASS##Numeric. */              \
+  BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME)
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_
diff --git a/base/ranges/algorithm.h b/base/ranges/algorithm.h
index f7a23c4..70932a8 100644
--- a/base/ranges/algorithm.h
+++ b/base/ranges/algorithm.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,11 +13,11 @@
 
 #include "polyfills/base/check.h"
 #include "base/compiler_specific.h"
+#include "base/cxx20_is_constant_evaluated.h"
 #include "base/functional/identity.h"
 #include "base/functional/invoke.h"
 #include "base/ranges/functional.h"
 #include "base/ranges/ranges.h"
-#include "base/template_util.h"
 
 namespace gurl_base {
 
diff --git a/base/ranges/functional.h b/base/ranges/functional.h
index e71abab..6557a19 100644
--- a/base/ranges/functional.h
+++ b/base/ranges/functional.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/ranges/ranges.h b/base/ranges/ranges.h
index 7eef2d6..f591c6c 100644
--- a/base/ranges/ranges.h
+++ b/base/ranges/ranges.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/stl_util.h b/base/stl_util.h
index a9c627d..74ce611 100644
--- a/base/stl_util.h
+++ b/base/stl_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,7 +14,6 @@
 
 #include "polyfills/base/check.h"
 #include "base/ranges/algorithm.h"
-#include "absl/types/optional.h"
 
 namespace gurl_base {
 
@@ -175,25 +174,6 @@
   const typename Collection::const_iterator end_;
 };
 
-// Helper for returning the optional value's address, or nullptr.
-template <class T>
-T* OptionalOrNullptr(absl::optional<T>& optional) {
-  return optional.has_value() ? &optional.value() : nullptr;
-}
-
-template <class T>
-const T* OptionalOrNullptr(const absl::optional<T>& optional) {
-  return optional.has_value() ? &optional.value() : nullptr;
-}
-
-// Helper for creating an optional<T> from a potentially nullptr T*.
-template <class T>
-absl::optional<T> OptionalFromPtr(const T* value) {
-  if (value)
-    return absl::optional<T>(*value);
-  return absl::nullopt;
-}
-
 }  // namespace base
 
 #endif  // BASE_STL_UTIL_H_
diff --git a/base/strings/abseil_string_conversions.cc b/base/strings/abseil_string_conversions.cc
index 5915b53..6a12c0c 100644
--- a/base/strings/abseil_string_conversions.cc
+++ b/base/strings/abseil_string_conversions.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/abseil_string_conversions.h b/base/strings/abseil_string_conversions.h
index 1cee63d..ffb0688 100644
--- a/base/strings/abseil_string_conversions.h
+++ b/base/strings/abseil_string_conversions.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/abseil_string_conversions_unittest.cc b/base/strings/abseil_string_conversions_unittest.cc
index 6c8816d..3744035 100644
--- a/base/strings/abseil_string_conversions_unittest.cc
+++ b/base/strings/abseil_string_conversions_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/abseil_string_number_conversions.cc b/base/strings/abseil_string_number_conversions.cc
index aab4905..cce321f 100644
--- a/base/strings/abseil_string_number_conversions.cc
+++ b/base/strings/abseil_string_number_conversions.cc
@@ -1,4 +1,4 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/abseil_string_number_conversions.h b/base/strings/abseil_string_number_conversions.h
index c709d34..2c26752 100644
--- a/base/strings/abseil_string_number_conversions.h
+++ b/base/strings/abseil_string_number_conversions.h
@@ -1,4 +1,4 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/abseil_string_number_conversions_unittest.cc b/base/strings/abseil_string_number_conversions_unittest.cc
index 5873e79..77a06b1 100644
--- a/base/strings/abseil_string_number_conversions_unittest.cc
+++ b/base/strings/abseil_string_number_conversions_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/escape.cc b/base/strings/escape.cc
index 5cd770d..96657a3 100644
--- a/base/strings/escape.cc
+++ b/base/strings/escape.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/escape.h b/base/strings/escape.h
index 02203be..5ae4555 100644
--- a/base/strings/escape.h
+++ b/base/strings/escape.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/escape_unittest.cc b/base/strings/escape_unittest.cc
index 182e83f..ec37ed1 100644
--- a/base/strings/escape_unittest.cc
+++ b/base/strings/escape_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/latin1_string_conversions.cc b/base/strings/latin1_string_conversions.cc
index e4b4020..43f0dc0 100644
--- a/base/strings/latin1_string_conversions.cc
+++ b/base/strings/latin1_string_conversions.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/latin1_string_conversions.h b/base/strings/latin1_string_conversions.h
index 7b67073..83f8ef2 100644
--- a/base/strings/latin1_string_conversions.h
+++ b/base/strings/latin1_string_conversions.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/no_trigraphs_unittest.cc b/base/strings/no_trigraphs_unittest.cc
index 91fbda5..6641989 100644
--- a/base/strings/no_trigraphs_unittest.cc
+++ b/base/strings/no_trigraphs_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/pattern.cc b/base/strings/pattern.cc
index 607d6d5..23644e3 100644
--- a/base/strings/pattern.cc
+++ b/base/strings/pattern.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/pattern.h b/base/strings/pattern.h
index 3d280d0..52e25a2 100644
--- a/base/strings/pattern.h
+++ b/base/strings/pattern.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/pattern_unittest.cc b/base/strings/pattern_unittest.cc
index 20383e8..4797de6 100644
--- a/base/strings/pattern_unittest.cc
+++ b/base/strings/pattern_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/safe_sprintf.cc b/base/strings/safe_sprintf.cc
index 26a7715..5071377 100644
--- a/base/strings/safe_sprintf.cc
+++ b/base/strings/safe_sprintf.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/safe_sprintf.h b/base/strings/safe_sprintf.h
index a5b242b..de4f06a 100644
--- a/base/strings/safe_sprintf.h
+++ b/base/strings/safe_sprintf.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/safe_sprintf_unittest.cc b/base/strings/safe_sprintf_unittest.cc
index ad1cca2..bdcc2ff 100644
--- a/base/strings/safe_sprintf_unittest.cc
+++ b/base/strings/safe_sprintf_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/strcat.cc b/base/strings/strcat.cc
index c6b8faf..24b7e8d 100644
--- a/base/strings/strcat.cc
+++ b/base/strings/strcat.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2017 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/strcat.h b/base/strings/strcat.h
index 1cdd708..386d542 100644
--- a/base/strings/strcat.h
+++ b/base/strings/strcat.h
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2017 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/strcat_internal.h b/base/strings/strcat_internal.h
index 8011946..894aac9 100644
--- a/base/strings/strcat_internal.h
+++ b/base/strings/strcat_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/strcat_unittest.cc b/base/strings/strcat_unittest.cc
index d6a68d3..0c433c9 100644
--- a/base/strings/strcat_unittest.cc
+++ b/base/strings/strcat_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2017 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/strcat_win.cc b/base/strings/strcat_win.cc
index affc99e..93cb2c8 100644
--- a/base/strings/strcat_win.cc
+++ b/base/strings/strcat_win.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/strcat_win.h b/base/strings/strcat_win.h
index e32a7e5..d9c00e9 100644
--- a/base/strings/strcat_win.h
+++ b/base/strings/strcat_win.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_number_conversions.cc b/base/strings/string_number_conversions.cc
index 929b650..e7c692e 100644
--- a/base/strings/string_number_conversions.cc
+++ b/base/strings/string_number_conversions.cc
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/base/strings/string_number_conversions.h b/base/strings/string_number_conversions.h
index 7d1b0b5..71d324e 100644
--- a/base/strings/string_number_conversions.h
+++ b/base/strings/string_number_conversions.h
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/base/strings/string_number_conversions_fuzzer.cc b/base/strings/string_number_conversions_fuzzer.cc
index e6e5c6f..cea3d3c 100644
--- a/base/strings/string_number_conversions_fuzzer.cc
+++ b/base/strings/string_number_conversions_fuzzer.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_number_conversions_internal.h b/base/strings/string_number_conversions_internal.h
index 7c1804c..e505a81 100644
--- a/base/strings/string_number_conversions_internal.h
+++ b/base/strings/string_number_conversions_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -275,7 +275,7 @@
   //  - If the first character is a space, there was leading whitespace
   return !input.empty() && output != HUGE_VAL && output != -HUGE_VAL &&
          static_cast<size_t>(processed_characters_count) == input.size() &&
-         !IsUnicodeWhitespace(input[0]);
+         !IsWhitespace(input[0]);
 }
 
 template <typename Char, typename OutIter>
diff --git a/base/strings/string_number_conversions_unittest.cc b/base/strings/string_number_conversions_unittest.cc
index 34f811e..349e2e4 100644
--- a/base/strings/string_number_conversions_unittest.cc
+++ b/base/strings/string_number_conversions_unittest.cc
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/base/strings/string_number_conversions_win.cc b/base/strings/string_number_conversions_win.cc
index da67ca2..6e81b2f 100644
--- a/base/strings/string_number_conversions_win.cc
+++ b/base/strings/string_number_conversions_win.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_number_conversions_win.h b/base/strings/string_number_conversions_win.h
index d63d2d7..1d7e7a6 100644
--- a/base/strings/string_number_conversions_win.h
+++ b/base/strings/string_number_conversions_win.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_piece.cc b/base/strings/string_piece.cc
index e76e6ad..e67aa17 100644
--- a/base/strings/string_piece.cc
+++ b/base/strings/string_piece.cc
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/base/strings/string_piece.h b/base/strings/string_piece.h
index 68d6205..a1db548 100644
--- a/base/strings/string_piece.h
+++ b/base/strings/string_piece.h
@@ -1,4 +1,4 @@
-// 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.
 //
@@ -33,7 +33,8 @@
 #include "polyfills/base/check.h"
 #include "polyfills/base/check_op.h"
 #include "base/compiler_specific.h"
-#include "base/strings/string_piece_forward.h"
+#include "base/cxx20_is_constant_evaluated.h"
+#include "base/strings/string_piece_forward.h"  // IWYU pragma: export
 #include "build/build_config.h"
 
 namespace gurl_base {
diff --git a/base/strings/string_piece_forward.h b/base/strings/string_piece_forward.h
index e257528..6c391b1 100644
--- a/base/strings/string_piece_forward.h
+++ b/base/strings/string_piece_forward.h
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2017 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
diff --git a/base/strings/string_piece_rust.h b/base/strings/string_piece_rust.h
index 1542c17..0d89aa4 100644
--- a/base/strings/string_piece_rust.h
+++ b/base/strings/string_piece_rust.h
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_piece_rust_unittest.cc b/base/strings/string_piece_rust_unittest.cc
index bf860fb..38d50d4 100644
--- a/base/strings/string_piece_rust_unittest.cc
+++ b/base/strings/string_piece_rust_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_piece_unittest.cc b/base/strings/string_piece_unittest.cc
index c6b1f29..fb1be66 100644
--- a/base/strings/string_piece_unittest.cc
+++ b/base/strings/string_piece_unittest.cc
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/base/strings/string_split.cc b/base/strings/string_split.cc
index 24b4a21..05d4101 100644
--- a/base/strings/string_split.cc
+++ b/base/strings/string_split.cc
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/base/strings/string_split.h b/base/strings/string_split.h
index b464f08..ca16457 100644
--- a/base/strings/string_split.h
+++ b/base/strings/string_split.h
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/base/strings/string_split_internal.h b/base/strings/string_split_internal.h
index 4430381..8228bd6 100644
--- a/base/strings/string_split_internal.h
+++ b/base/strings/string_split_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_split_unittest.cc b/base/strings/string_split_unittest.cc
index 5bafec5..dc2bc3a 100644
--- a/base/strings/string_split_unittest.cc
+++ b/base/strings/string_split_unittest.cc
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/base/strings/string_split_win.cc b/base/strings/string_split_win.cc
index 1327769..05c0541 100644
--- a/base/strings/string_split_win.cc
+++ b/base/strings/string_split_win.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_split_win.h b/base/strings/string_split_win.h
index 74efb5d..08b52b2 100644
--- a/base/strings/string_split_win.h
+++ b/base/strings/string_split_win.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_tokenizer.h b/base/strings/string_tokenizer.h
index e85bf45..62acf43 100644
--- a/base/strings/string_tokenizer.h
+++ b/base/strings/string_tokenizer.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_tokenizer_fuzzer.cc b/base/strings/string_tokenizer_fuzzer.cc
index b3b046b..a0c0788 100644
--- a/base/strings/string_tokenizer_fuzzer.cc
+++ b/base/strings/string_tokenizer_fuzzer.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_tokenizer_unittest.cc b/base/strings/string_tokenizer_unittest.cc
index 9cca0c1..9a5e88e 100644
--- a/base/strings/string_tokenizer_unittest.cc
+++ b/base/strings/string_tokenizer_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright 2006-2008 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc
index 8623096..482bb6e 100644
--- a/base/strings/string_util.cc
+++ b/base/strings/string_util.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_util.h b/base/strings/string_util.h
index 282d4a8..56cf483 100644
--- a/base/strings/string_util.h
+++ b/base/strings/string_util.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -14,6 +14,7 @@
 
 #include <algorithm>
 #include <initializer_list>
+#include <sstream>
 #include <string>
 #include <type_traits>
 #include <vector>
@@ -110,6 +111,14 @@
   return MakeBasicStringPiece<wchar_t>(begin, end);
 }
 
+// Convert a type with defined `operator<<` into a string.
+template <typename... Streamable>
+std::string StreamableToString(const Streamable&... values) {
+  std::ostringstream ss;
+  (ss << ... << values);
+  return ss.str();
+}
+
 // ASCII-specific tolower.  The standard library's tolower is locale sensitive,
 // so we don't want to use it here.
 template <typename CharT,
@@ -376,7 +385,12 @@
 // library versions will change based on locale).
 template <typename Char>
 inline bool IsAsciiWhitespace(Char c) {
-  return c == ' ' || c == '\r' || c == '\n' || c == '\t' || c == '\f';
+  // kWhitespaceASCII is a null-terminated string.
+  for (const char* cur = kWhitespaceASCII; *cur; ++cur) {
+    if (*cur == c)
+      return true;
+  }
+  return false;
 }
 template <typename Char>
 inline bool IsAsciiAlpha(Char c) {
@@ -421,17 +435,33 @@
   return HexDigitToInt(static_cast<char>(c));
 }
 
-// Returns true if it's a Unicode whitespace character.
-template <typename Char>
+// Returns whether `c` is a Unicode whitespace character.
+// This cannot be used on eight-bit characters, since if they are ASCII you
+// should call IsAsciiWhitespace(), and if they are from a UTF-8 string they may
+// be individual units of a multi-unit code point.  Convert to 16- or 32-bit
+// values known to hold the full code point before calling this.
+template <typename Char, typename = std::enable_if_t<(sizeof(Char) > 1)>>
 inline bool IsUnicodeWhitespace(Char c) {
-  // kWhitespaceWide is a NUL-terminated string
+  // kWhitespaceWide is a null-terminated string.
   for (const auto* cur = kWhitespaceWide; *cur; ++cur) {
     if (static_cast<typename std::make_unsigned_t<wchar_t>>(*cur) ==
         static_cast<typename std::make_unsigned_t<Char>>(c))
       return true;
   }
   return false;
-};
+}
+
+// DANGEROUS: Assumes ASCII or not base on the size of `Char`.  You should
+// probably be explicitly calling IsUnicodeWhitespace() or IsAsciiWhitespace()
+// instead!
+template <typename Char>
+inline bool IsWhitespace(Char c) {
+  if constexpr (sizeof(Char) > 1) {
+    return IsUnicodeWhitespace(c);
+  } else {
+    return IsAsciiWhitespace(c);
+  }
+}
 
 // Return a byte string in human-readable format with a unit suffix. Not
 // appropriate for use in any UI; use of FormatBytes and friends in ui/base is
diff --git a/base/strings/string_util_constants.cc b/base/strings/string_util_constants.cc
index 198cd53..fece0af 100644
--- a/base/strings/string_util_constants.cc
+++ b/base/strings/string_util_constants.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_util_internal.h b/base/strings/string_util_internal.h
index cc92e0d..1d6a41e 100644
--- a/base/strings/string_util_internal.h
+++ b/base/strings/string_util_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -149,7 +149,7 @@
 
   size_t chars_written = 0;
   for (auto c : text) {
-    if (IsUnicodeWhitespace(c)) {
+    if (IsWhitespace(c)) {
       if (!in_whitespace) {
         // Reduce all whitespace sequences to a single space.
         in_whitespace = true;
diff --git a/base/strings/string_util_perftest.cc b/base/strings/string_util_perftest.cc
index 8a5d540..879c74f 100644
--- a/base/strings/string_util_perftest.cc
+++ b/base/strings/string_util_perftest.cc
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_util_posix.h b/base/strings/string_util_posix.h
index 91cf7a6..49351f9 100644
--- a/base/strings/string_util_posix.h
+++ b/base/strings/string_util_posix.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc
index 4d2ac71..d4326c7 100644
--- a/base/strings/string_util_unittest.cc
+++ b/base/strings/string_util_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -479,23 +479,26 @@
   const bool trim;
   const char* output;
 } collapse_cases_ascii[] = {
-  {" Google Video ", false, "Google Video"},
-  {"Google Video", false, "Google Video"},
-  {"", false, ""},
-  {"  ", false, ""},
-  {"\t\rTest String\n", false, "Test String"},
-  {"    Test     \n  \t String    ", false, "Test String"},
-  {"   Test String", false, "Test String"},
-  {"Test String    ", false, "Test String"},
-  {"Test String", false, "Test String"},
-  {"", true, ""},
-  {"\n", true, ""},
-  {"  \r  ", true, ""},
-  {"\nFoo", true, "Foo"},
-  {"\r  Foo  ", true, "Foo"},
-  {" Foo bar ", true, "Foo bar"},
-  {"  \tFoo  bar  \n", true, "Foo bar"},
-  {" a \r b\n c \r\n d \t\re \t f \n ", true, "abcde f"},
+    {" Google Video ", false, "Google Video"},
+    {"Google Video", false, "Google Video"},
+    {"", false, ""},
+    {"  ", false, ""},
+    {"\t\rTest String\n", false, "Test String"},
+    {"    Test     \n  \t String    ", false, "Test String"},
+    {"   Test String", false, "Test String"},
+    {"Test String    ", false, "Test String"},
+    {"Test String", false, "Test String"},
+    {"", true, ""},
+    {"\n", true, ""},
+    {"  \r  ", true, ""},
+    {"\nFoo", true, "Foo"},
+    {"\r  Foo  ", true, "Foo"},
+    {" Foo bar ", true, "Foo bar"},
+    // \u00A0 is whitespace, but not _ASCII_ whitespace, so it should not be
+    // collapsed by CollapseWhitespaceASCII().
+    {"Foo\u00A0bar", true, "Foo\u00A0bar"},
+    {"  \tFoo  bar  \n", true, "Foo bar"},
+    {" a \r b\n c \r\n d \t\re \t f \n ", true, "abcde f"},
 };
 
 TEST(StringUtilTest, CollapseWhitespaceASCII) {
@@ -1324,6 +1327,28 @@
   EXPECT_TRUE(MakeWStringPiece(baz.end(), baz.end()).empty());
 }
 
+enum class StreamableTestEnum { kGreeting, kLocation };
+
+std::ostream& operator<<(std::ostream& os, const StreamableTestEnum& value) {
+  switch (value) {
+    case StreamableTestEnum::kGreeting:
+      return os << "hello";
+    case StreamableTestEnum::kLocation:
+      return os << "world";
+  }
+}
+
+TEST(StringUtilTest, StreamableToString) {
+  EXPECT_EQ(StreamableToString("foo"), "foo");
+  EXPECT_EQ(StreamableToString(123), "123");
+  EXPECT_EQ(StreamableToString(StreamableTestEnum::kGreeting), "hello");
+  EXPECT_EQ(StreamableToString(StreamableTestEnum::kGreeting, " ",
+                               StreamableTestEnum::kLocation),
+            "hello world");
+  EXPECT_EQ(StreamableToString("42 in hex is ", std::hex, 42),
+            "42 in hex is 2a");
+}
+
 TEST(StringUtilTest, RemoveChars) {
   const char kRemoveChars[] = "-/+*";
   std::string input = "A-+bc/d!*";
diff --git a/base/strings/string_util_win.cc b/base/strings/string_util_win.cc
index 7ab9061..f8d0243 100644
--- a/base/strings/string_util_win.cc
+++ b/base/strings/string_util_win.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/string_util_win.h b/base/strings/string_util_win.h
index 6b5fba3..14f08fe 100644
--- a/base/strings/string_util_win.h
+++ b/base/strings/string_util_win.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/stringize_macros.h b/base/strings/stringize_macros.h
index d4e2707..355aee3 100644
--- a/base/strings/stringize_macros.h
+++ b/base/strings/stringize_macros.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright 2010 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
diff --git a/base/strings/stringize_macros_unittest.cc b/base/strings/stringize_macros_unittest.cc
index d7f9e56..c3c3479 100644
--- a/base/strings/stringize_macros_unittest.cc
+++ b/base/strings/stringize_macros_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright 2010 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/stringprintf.cc b/base/strings/stringprintf.cc
index 8de48f3..9509aff 100644
--- a/base/strings/stringprintf.cc
+++ b/base/strings/stringprintf.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/stringprintf.h b/base/strings/stringprintf.h
index b0d473b..b393c93 100644
--- a/base/strings/stringprintf.h
+++ b/base/strings/stringprintf.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/stringprintf_unittest.cc b/base/strings/stringprintf_unittest.cc
index 334d0ba..c137095 100644
--- a/base/strings/stringprintf_unittest.cc
+++ b/base/strings/stringprintf_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/sys_string_conversions.h b/base/strings/sys_string_conversions.h
index d80b178..37f5455 100644
--- a/base/strings/sys_string_conversions.h
+++ b/base/strings/sys_string_conversions.h
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/base/strings/sys_string_conversions_posix.cc b/base/strings/sys_string_conversions_posix.cc
index 02535ed..3aab336 100644
--- a/base/strings/sys_string_conversions_posix.cc
+++ b/base/strings/sys_string_conversions_posix.cc
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/base/strings/sys_string_conversions_unittest.cc b/base/strings/sys_string_conversions_unittest.cc
index 01bceb0..0e3dfa1 100644
--- a/base/strings/sys_string_conversions_unittest.cc
+++ b/base/strings/sys_string_conversions_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/sys_string_conversions_win.cc b/base/strings/sys_string_conversions_win.cc
index c0b4829..da19245 100644
--- a/base/strings/sys_string_conversions_win.cc
+++ b/base/strings/sys_string_conversions_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright 2006-2008 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/utf_offset_string_conversions.cc b/base/strings/utf_offset_string_conversions.cc
index b67b6a7..f893b89 100644
--- a/base/strings/utf_offset_string_conversions.cc
+++ b/base/strings/utf_offset_string_conversions.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/utf_offset_string_conversions.h b/base/strings/utf_offset_string_conversions.h
index 3b2904d..03b2e7a 100644
--- a/base/strings/utf_offset_string_conversions.h
+++ b/base/strings/utf_offset_string_conversions.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/utf_offset_string_conversions_unittest.cc b/base/strings/utf_offset_string_conversions_unittest.cc
index 83bbc35..1f3e6db 100644
--- a/base/strings/utf_offset_string_conversions_unittest.cc
+++ b/base/strings/utf_offset_string_conversions_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/utf_string_conversion_utils.cc b/base/strings/utf_string_conversion_utils.cc
index ffeeb6c..162fa36 100644
--- a/base/strings/utf_string_conversion_utils.cc
+++ b/base/strings/utf_string_conversion_utils.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright 2009 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/utf_string_conversion_utils.h b/base/strings/utf_string_conversion_utils.h
index 8c209a2..f5ae5b1 100644
--- a/base/strings/utf_string_conversion_utils.h
+++ b/base/strings/utf_string_conversion_utils.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/utf_string_conversions.cc b/base/strings/utf_string_conversions.cc
index 683b339..383f1a3 100644
--- a/base/strings/utf_string_conversions.cc
+++ b/base/strings/utf_string_conversions.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/utf_string_conversions.h b/base/strings/utf_string_conversions.h
index 77dc194..975d29d 100644
--- a/base/strings/utf_string_conversions.h
+++ b/base/strings/utf_string_conversions.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/utf_string_conversions_fuzzer.cc b/base/strings/utf_string_conversions_fuzzer.cc
index 7bae707..3cc4521 100644
--- a/base/strings/utf_string_conversions_fuzzer.cc
+++ b/base/strings/utf_string_conversions_fuzzer.cc
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/strings/utf_string_conversions_unittest.cc b/base/strings/utf_string_conversions_unittest.cc
index f738da4..cc35a12 100644
--- a/base/strings/utf_string_conversions_unittest.cc
+++ b/base/strings/utf_string_conversions_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright 2010 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/template_util.h b/base/template_util.h
index 17db620..1179a99 100644
--- a/base/template_util.h
+++ b/base/template_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2011 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -93,19 +93,6 @@
 template <typename T>
 using remove_cvref_t = typename remove_cvref<T>::type;
 
-// Implementation of C++20's std::is_constant_evaluated.
-//
-// References:
-// - https://en.cppreference.com/w/cpp/types/is_constant_evaluated
-// - https://wg21.link/meta.const.eval
-constexpr bool is_constant_evaluated() noexcept {
-#if HAS_BUILTIN(__builtin_is_constant_evaluated)
-  return __builtin_is_constant_evaluated();
-#else
-  return false;
-#endif
-}
-
 // Simplified implementation of C++20's std::iter_value_t.
 // As opposed to std::iter_value_t, this implementation does not restrict
 // the type of `Iter` and does not consider specializations of
diff --git a/base/win/win_handle_types.h b/base/win/win_handle_types.h
index d71702c..503bf6f 100644
--- a/base/win/win_handle_types.h
+++ b/base/win/win_handle_types.h
@@ -1,4 +1,4 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/win/win_handle_types_list.inc b/base/win/win_handle_types_list.inc
index b1dbef6..2241211 100644
--- a/base/win/win_handle_types_list.inc
+++ b/base/win/win_handle_types_list.inc
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/build/build_config.h b/build/build_config.h
index 1914750..8f90f47 100644
--- a/build/build_config.h
+++ b/build/build_config.h
@@ -1,4 +1,4 @@
-// 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.
 
diff --git a/build/buildflag.h b/build/buildflag.h
index 5776a75..6346979 100644
--- a/build/buildflag.h
+++ b/build/buildflag.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/copy.bara.sky b/copy.bara.sky
index 7ecc7c8..f9d1a2a 100644
--- a/copy.bara.sky
+++ b/copy.bara.sky
@@ -20,6 +20,7 @@
         "base/containers/util.h",
         "base/cxx17_backports.h",
         "base/cxx20_to_address.h",
+	"base/cxx20_is_constant_evaluated.h",
         "base/debug/crash_logging.cc",
         "base/debug/crash_logging.h",
         "base/debug/leak_annotations.h",
@@ -27,8 +28,7 @@
         "base/i18n/uchar.h",
         "base/memory/raw_ptr.h",
         "base/memory/raw_ptr_exclusion.h",
-        "base/numerics/safe_conversions.h",
-        "base/numerics/safe_conversions_impl.h",
+        "base/numerics/*.h",
         "base/no_destructor.h",
         "base/ranges/*.h",
         "base/stl_util.h",
diff --git a/polyfills/base/allocator/buildflags.h b/polyfills/base/allocator/buildflags.h
index 54e240c..c5e46c4 100644
--- a/polyfills/base/allocator/buildflags.h
+++ b/polyfills/base/allocator/buildflags.h
@@ -14,5 +14,6 @@
 #define BUILDFLAG_INTERNAL_NEVER_REMOVE_FROM_BRP_POOL_BLOCKLIST() (0)
 #define BUILDFLAG_INTERNAL_USE_FAKE_BINARY_EXPERIMENT() (0)
 #define BUILDFLAG_INTERNAL_RECORD_ALLOC_INFO() (0)
+#define BUILDFLAG_INTERNAL_FORCE_ENABLE_RAW_PTR_EXCLUSION() (0)
 
 #endif  // POLYFILLS_BASE_ALLOCATOR_BUILDFLAGS_H_
diff --git a/url/gurl.cc b/url/gurl.cc
index 1337666..6c0429e 100644
--- a/url/gurl.cc
+++ b/url/gurl.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/gurl.h b/url/gurl.h
index 97a60ab..919ae5c 100644
--- a/url/gurl.h
+++ b/url/gurl.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/gurl_abstract_tests.h b/url/gurl_abstract_tests.h
index ffe9942..d787d3e 100644
--- a/url/gurl_abstract_tests.h
+++ b/url/gurl_abstract_tests.h
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/gurl_fuzzer.cc b/url/gurl_fuzzer.cc
index 0c3c101..170de8a 100644
--- a/url/gurl_fuzzer.cc
+++ b/url/gurl_fuzzer.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/gurl_unittest.cc b/url/gurl_unittest.cc
index 24e8f94..16e3a8e 100644
--- a/url/gurl_unittest.cc
+++ b/url/gurl_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/origin.cc b/url/origin.cc
index b17591d..1b416a9 100644
--- a/url/origin.cc
+++ b/url/origin.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -331,9 +331,8 @@
     pickle.WriteUInt64(0);
   }
 
-  gurl_base::span<const uint8_t> data(
-      static_cast<const uint8_t*>(pickle.data()),
-      static_cast<const uint8_t*>(pickle.data()) + pickle.size());
+  gurl_base::span<const uint8_t> data(static_cast<const uint8_t*>(pickle.data()),
+                                 pickle.size());
   // Base64 encode the data to make it nicer to play with.
   return gurl_base::Base64Encode(data);
 }
diff --git a/url/origin.h b/url/origin.h
index 6769535..0d04628 100644
--- a/url/origin.h
+++ b/url/origin.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/origin_abstract_tests.cc b/url/origin_abstract_tests.cc
index 1619eae..d48a9f5 100644
--- a/url/origin_abstract_tests.cc
+++ b/url/origin_abstract_tests.cc
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/origin_abstract_tests.h b/url/origin_abstract_tests.h
index 4aaf495..b89f63f 100644
--- a/url/origin_abstract_tests.h
+++ b/url/origin_abstract_tests.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/origin_unittest.cc b/url/origin_unittest.cc
index bd9ee7e..61500a6 100644
--- a/url/origin_unittest.cc
+++ b/url/origin_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/run_all_perftests.cc b/url/run_all_perftests.cc
index be7a746..47aeae2 100644
--- a/url/run_all_perftests.cc
+++ b/url/run_all_perftests.cc
@@ -1,4 +1,4 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/run_all_unittests.cc b/url/run_all_unittests.cc
index cf408d4..0e339bd 100644
--- a/url/run_all_unittests.cc
+++ b/url/run_all_unittests.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/scheme_host_port.cc b/url/scheme_host_port.cc
index 854c6f6..db23d39 100644
--- a/url/scheme_host_port.cc
+++ b/url/scheme_host_port.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/scheme_host_port.h b/url/scheme_host_port.h
index 70df243..88013dd 100644
--- a/url/scheme_host_port.h
+++ b/url/scheme_host_port.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/scheme_host_port_unittest.cc b/url/scheme_host_port_unittest.cc
index f49bd59..49bcf25 100644
--- a/url/scheme_host_port_unittest.cc
+++ b/url/scheme_host_port_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/third_party/mozilla/url_parse.h b/url/third_party/mozilla/url_parse.h
index c3535ba..2246d53 100644
--- a/url/third_party/mozilla/url_parse.h
+++ b/url/third_party/mozilla/url_parse.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon.cc b/url/url_canon.cc
index dce7847..003165b 100644
--- a/url/url_canon.cc
+++ b/url/url_canon.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2017 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon.h b/url/url_canon.h
index cab7d29..abeea84 100644
--- a/url/url_canon.h
+++ b/url/url_canon.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,6 +11,7 @@
 #include "polyfills/base/component_export.h"
 #include "polyfills/base/export_template.h"
 #include "base/memory/raw_ptr_exclusion.h"
+#include "base/numerics/clamped_math.h"
 #include "url/third_party/mozilla/url_parse.h"
 
 namespace url {
@@ -28,42 +29,33 @@
 template<typename T>
 class CanonOutputT {
  public:
-  CanonOutputT() : buffer_(nullptr), buffer_len_(0), cur_len_(0) {}
-  virtual ~CanonOutputT() {
-  }
+  CanonOutputT() = default;
+  virtual ~CanonOutputT() = default;
 
   // Implemented to resize the buffer. This function should update the buffer
   // pointer to point to the new buffer, and any old data up to |cur_len_| in
   // the buffer must be copied over.
   //
   // The new size |sz| must be larger than buffer_len_.
-  virtual void Resize(int sz) = 0;
+  virtual void Resize(size_t sz) = 0;
 
   // Accessor for returning a character at a given position. The input offset
   // must be in the valid range.
-  inline T at(int offset) const {
-    return buffer_[offset];
-  }
+  inline T at(size_t offset) const { return buffer_[offset]; }
 
   // Sets the character at the given position. The given position MUST be less
   // than the length().
-  inline void set(int offset, T ch) {
-    buffer_[offset] = ch;
-  }
+  inline void set(size_t offset, T ch) { buffer_[offset] = ch; }
 
   // Returns the number of characters currently in the buffer.
-  inline int length() const {
-    return cur_len_;
-  }
+  inline size_t length() const { return cur_len_; }
 
   // Returns the current capacity of the buffer. The length() is the number of
   // characters that have been declared to be written, but the capacity() is
   // the number that can be written without reallocation. If the caller must
   // write many characters at once, it can make sure there is enough capacity,
   // write the data, then use set_size() to declare the new length().
-  int capacity() const {
-    return buffer_len_;
-  }
+  size_t capacity() const { return buffer_len_; }
 
   // Called by the user of this class to get the output. The output will NOT
   // be NULL-terminated. Call length() to get the
@@ -81,9 +73,7 @@
   // to declare the new length.
   //
   // This MUST NOT be used to expand the size of the buffer beyond capacity().
-  void set_length(int new_len) {
-    cur_len_ = new_len;
-  }
+  void set_length(size_t new_len) { cur_len_ = new_len; }
 
   // This is the most performance critical function, since it is called for
   // every character.
@@ -107,28 +97,28 @@
   }
 
   // Appends the given string to the output.
-  void Append(const T* str, int str_len) {
-    if (cur_len_ + str_len > buffer_len_) {
-      if (!Grow(cur_len_ + str_len - buffer_len_))
+  void Append(const T* str, size_t str_len) {
+    if (str_len > buffer_len_ - cur_len_) {
+      if (!Grow(str_len - (buffer_len_ - cur_len_)))
         return;
     }
-    for (int i = 0; i < str_len; i++)
+    for (size_t i = 0; i < str_len; i++)
       buffer_[cur_len_ + i] = str[i];
     cur_len_ += str_len;
   }
 
-  void ReserveSizeIfNeeded(int estimated_size) {
+  void ReserveSizeIfNeeded(size_t estimated_size) {
     // Reserve a bit extra to account for escaped chars.
     if (estimated_size > buffer_len_)
-      Resize(estimated_size + 8);
+      Resize((gurl_base::ClampedNumeric<size_t>(estimated_size) + 8).RawValue());
   }
 
  protected:
   // Grows the given buffer so that it can fit at least |min_additional|
   // characters. Returns true if the buffer could be resized, false on OOM.
-  bool Grow(int min_additional) {
-    static const int kMinBufferLen = 16;
-    int new_len = (buffer_len_ == 0) ? kMinBufferLen : buffer_len_;
+  bool Grow(size_t min_additional) {
+    static const size_t kMinBufferLen = 16;
+    size_t new_len = (buffer_len_ == 0) ? kMinBufferLen : buffer_len_;
     do {
       if (new_len >= (1 << 30))  // Prevent overflow below.
         return false;
@@ -140,11 +130,11 @@
 
   // `buffer_` is not a raw_ptr<...> for performance reasons (based on analysis
   // of sampling profiler data).
-  RAW_PTR_EXCLUSION T* buffer_;
-  int buffer_len_;
+  RAW_PTR_EXCLUSION T* buffer_ = nullptr;
+  size_t buffer_len_ = 0;
 
   // Used characters in the buffer.
-  int cur_len_;
+  size_t cur_len_ = 0;
 };
 
 // Simple implementation of the CanonOutput using new[]. This class
@@ -162,7 +152,7 @@
       delete[] this->buffer_;
   }
 
-  void Resize(int sz) override {
+  void Resize(size_t sz) override {
     T* new_buf = new T[sz];
     memcpy(new_buf, this->buffer_,
            sizeof(T) * (this->cur_len_ < sz ? this->cur_len_ : sz));
diff --git a/url/url_canon_etc.cc b/url/url_canon_etc.cc
index c3ebddd..e54b843 100644
--- a/url/url_canon_etc.cc
+++ b/url/url_canon_etc.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_filesystemurl.cc b/url/url_canon_filesystemurl.cc
index b36198a..0472484 100644
--- a/url/url_canon_filesystemurl.cc
+++ b/url/url_canon_filesystemurl.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_fileurl.cc b/url/url_canon_fileurl.cc
index b0740a2..dae5c4c 100644
--- a/url/url_canon_fileurl.cc
+++ b/url/url_canon_fileurl.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_host.cc b/url/url_canon_host.cc
index edc9d67..d29f7ab 100644
--- a/url/url_canon_host.cc
+++ b/url/url_canon_host.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -69,7 +69,7 @@
     'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',kEsc,kEsc,kEsc,  0 ,  0 };
 
 // RFC1034 maximum FQDN length.
-constexpr int kMaxHostLength = 253;
+constexpr size_t kMaxHostLength = 253;
 
 // Generous padding to account for the fact that UTS#46 normalization can cause
 // a long string to actually shrink and fit within the 253 character RFC1034
@@ -77,11 +77,11 @@
 // cases: An arbitrary number of characters (e.g. U+00AD SOFT HYPHEN) can be
 // removed from the input by UTS#46 processing. However, this should be
 // sufficient for all normally-encountered, non-abusive hostname strings.
-constexpr int kMaxHostBufferLength = kMaxHostLength*5;
+constexpr size_t kMaxHostBufferLength = kMaxHostLength * 5;
 
-const int kTempHostBufferLen = 1024;
-typedef RawCanonOutputT<char, kTempHostBufferLen> StackBuffer;
-typedef RawCanonOutputT<char16_t, kTempHostBufferLen> StackBufferW;
+constexpr size_t kTempHostBufferLen = 1024;
+using StackBuffer = RawCanonOutputT<char, kTempHostBufferLen>;
+using StackBufferW = RawCanonOutputT<char16_t, kTempHostBufferLen>;
 
 // Scans a host name and fills in the output flags according to what we find.
 // |has_non_ascii| will be true if there are any non-7-bit characters, and
@@ -201,8 +201,7 @@
   // Now we check the ASCII output like a normal host. It will also handle
   // unescaping. Although we unescaped everything before this function call, if
   // somebody does %00 as fullwidth, ICU will convert this to ASCII.
-  bool success = DoSimpleHost(wide_output.data(),
-                              static_cast<size_t>(wide_output.length()), output,
+  bool success = DoSimpleHost(wide_output.data(), wide_output.length(), output,
                               &has_non_ascii);
   if (has_non_ascii) {
     // ICU generated something that DoSimpleHost didn't think looked like
@@ -220,8 +219,7 @@
     // ASCII isn't strictly necessary, but DoSimpleHost handles this case
     // anyway so we handle it/
     output->set_length(original_output_len);
-    AppendInvalidNarrowString(wide_output.data(), 0,
-                              static_cast<size_t>(wide_output.length()),
+    AppendInvalidNarrowString(wide_output.data(), 0, wide_output.length(),
                               output);
     return false;
   }
@@ -238,7 +236,7 @@
                    CanonOutput* output) {
   // Save the current position in the output. We may write stuff and rewind it
   // below, so we need to know where to rewind to.
-  int begin_length = output->length();
+  size_t begin_length = output->length();
 
   // Points to the UTF-8 data we want to convert. This will either be the
   // input or the unescaped version written to |*output| if necessary.
@@ -268,7 +266,7 @@
     // Save the pointer into the data was just converted (it may be appended to
     // other data in the output buffer).
     utf8_source = &output->data()[begin_length];
-    utf8_source_len = static_cast<size_t>(output->length() - begin_length);
+    utf8_source_len = output->length() - begin_length;
   } else {
     // We don't need to unescape, use input for IDNization later. (We know the
     // input has non-ASCII, or the simple version would have been called
@@ -287,15 +285,14 @@
     for (size_t i = 0; i < utf8_source_len; i++)
       utf8.push_back(utf8_source[i]);
     output->set_length(begin_length);
-    AppendInvalidNarrowString(utf8.data(), 0,
-                              static_cast<size_t>(utf8.length()), output);
+    AppendInvalidNarrowString(utf8.data(), 0, utf8.length(), output);
     return false;
   }
   output->set_length(begin_length);
 
   // This will call DoSimpleHost which will do normal ASCII canonicalization
   // and also check for IP addresses in the outpt.
-  return DoIDNHost(utf16.data(), static_cast<size_t>(utf16.length()), output) &&
+  return DoIDNHost(utf16.data(), utf16.length(), output) &&
          are_all_escaped_valid;
 }
 
@@ -324,8 +321,8 @@
 
     // Once we convert to UTF-8, we can use the 8-bit version of the complex
     // host handling code above.
-    return DoComplexHost(utf8.data(), static_cast<size_t>(utf8.length()),
-                         has_non_ascii, has_escaped, output);
+    return DoComplexHost(utf8.data(), utf8.length(), has_non_ascii, has_escaped,
+                         output);
   }
 
   // No unescaping necessary, we can safely pass the input to ICU. This
diff --git a/url/url_canon_icu.cc b/url/url_canon_icu.cc
index 3a6b9be..20c31a8 100644
--- a/url/url_canon_icu.cc
+++ b/url/url_canon_icu.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_icu.h b/url/url_canon_icu.h
index b861f7a..9a35df1 100644
--- a/url/url_canon_icu.h
+++ b/url/url_canon_icu.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_icu_unittest.cc b/url/url_canon_icu_unittest.cc
index cb74f64..0ac0fcb 100644
--- a/url/url_canon_icu_unittest.cc
+++ b/url/url_canon_icu_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -92,7 +92,7 @@
     RawCanonOutput<static_size> output;
     converter.ConvertFromUTF16(input.c_str(), static_cast<int>(input.length()),
                                &output);
-    EXPECT_EQ(input.length(), static_cast<size_t>(output.length()));
+    EXPECT_EQ(input.length(), output.length());
   }
 }
 
diff --git a/url/url_canon_internal.cc b/url/url_canon_internal.cc
index f6b4b03..eb24cee 100644
--- a/url/url_canon_internal.cc
+++ b/url/url_canon_internal.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_internal.h b/url/url_canon_internal.h
index a41a771..58ae144 100644
--- a/url/url_canon_internal.h
+++ b/url/url_canon_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -101,7 +101,7 @@
 extern const char kCharToHexLookup[8];
 
 // Assumes the input is a valid hex digit! Call IsHexChar before using this.
-inline unsigned char HexCharToValue(unsigned char c) {
+inline int HexCharToValue(unsigned char c) {
   return c - kCharToHexLookup[c / 0x20];
 }
 
@@ -136,8 +136,8 @@
 inline void AppendEscapedChar(UINCHAR ch,
                               CanonOutputT<OUTCHAR>* output) {
   output->push_back('%');
-  output->push_back(kHexCharLookup[(ch >> 4) & 0xf]);
-  output->push_back(kHexCharLookup[ch & 0xf]);
+  output->push_back(static_cast<OUTCHAR>(kHexCharLookup[(ch >> 4) & 0xf]));
+  output->push_back(static_cast<OUTCHAR>(kHexCharLookup[ch & 0xf]));
 }
 
 // The character we'll substitute for undecodable or invalid characters.
@@ -331,7 +331,8 @@
   }
 
   // Valid escape sequence.
-  *unescaped_value = (HexCharToValue(first) << 4) + HexCharToValue(second);
+  *unescaped_value = static_cast<unsigned char>((HexCharToValue(first) << 4) +
+                                                HexCharToValue(second));
   *begin += 2;
   return true;
 }
@@ -418,11 +419,11 @@
 // resolver as well, so we declare them here.
 bool CanonicalizePartialPathInternal(const char* spec,
                                      const Component& path,
-                                     int path_begin_in_output,
+                                     size_t path_begin_in_output,
                                      CanonOutput* output);
 bool CanonicalizePartialPathInternal(const char16_t* spec,
                                      const Component& path,
-                                     int path_begin_in_output,
+                                     size_t path_begin_in_output,
                                      CanonOutput* output);
 
 // Find the position of a bona fide Windows drive letter in the given path. If
diff --git a/url/url_canon_internal_file.h b/url/url_canon_internal_file.h
index 3b0a81e..c5b40a1 100644
--- a/url/url_canon_internal_file.h
+++ b/url/url_canon_internal_file.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_ip.cc b/url/url_canon_ip.cc
index f0552b5..fde31f1 100644
--- a/url/url_canon_ip.cc
+++ b/url/url_canon_ip.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_ip.h b/url/url_canon_ip.h
index 4e85466..953be0a 100644
--- a/url/url_canon_ip.h
+++ b/url/url_canon_ip.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_mailtourl.cc b/url/url_canon_mailtourl.cc
index ff62bea..e48b642 100644
--- a/url/url_canon_mailtourl.cc
+++ b/url/url_canon_mailtourl.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_path.cc b/url/url_canon_path.cc
index 32cb5f3..3480517 100644
--- a/url/url_canon_path.cc
+++ b/url/url_canon_path.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,7 @@
 
 #include "polyfills/base/check.h"
 #include "polyfills/base/check_op.h"
+#include "absl/types/optional.h"
 #include "url/url_canon.h"
 #include "url/url_canon_internal.h"
 #include "url/url_parse_internal.h"
@@ -150,19 +151,19 @@
 // because it is run only on the canonical output.
 //
 // The output is guaranteed to end in a slash when this function completes.
-void BackUpToPreviousSlash(int path_begin_in_output,
-                           CanonOutput* output) {
-  GURL_DCHECK(output->length() > 0);
+void BackUpToPreviousSlash(size_t path_begin_in_output, CanonOutput* output) {
+  GURL_CHECK(output->length() > 0);
+  GURL_CHECK(path_begin_in_output < output->length());
 
-  int i = output->length() - 1;
+  size_t i = output->length() - 1;
   GURL_DCHECK(output->at(i) == '/');
   if (i == path_begin_in_output)
     return;  // We're at the first slash, nothing to do.
 
   // Now back up (skipping the trailing slash) until we find another slash.
-  i--;
-  while (output->at(i) != '/' && i > path_begin_in_output)
-    i--;
+  do {
+    --i;
+  } while (output->at(i) != '/' && i > path_begin_in_output);
 
   // Now shrink the output to just include that last slash we found.
   output->set_length(i + 1);
@@ -199,9 +200,9 @@
 void CheckForNestedEscapes(const CHAR* spec,
                            size_t next_input_index,
                            size_t input_len,
-                           int last_invalid_percent_index,
+                           size_t last_invalid_percent_index,
                            CanonOutput* output) {
-  const int length = output->length();
+  const size_t length = output->length();
   const char last_unescaped_char = output->at(length - 1);
 
   // If |output| currently looks like "%c", we need to try appending the next
@@ -220,10 +221,9 @@
   }
 
   // Now output ends like "%cc".  Try to unescape this.
-  size_t begin = static_cast<size_t>(last_invalid_percent_index);
+  size_t begin = last_invalid_percent_index;
   unsigned char temp;
-  if (DecodeEscaped(output->data(), &begin,
-                    static_cast<size_t>(output->length()), &temp)) {
+  if (DecodeEscaped(output->data(), &begin, output->length(), &temp)) {
     // New escape sequence found.  Overwrite the characters following the '%'
     // with "25", and push_back() the one or two characters that were following
     // the '%' when we were called.
@@ -253,7 +253,7 @@
 template <typename CHAR, typename UCHAR>
 bool DoPartialPathInternal(const CHAR* spec,
                            const Component& path,
-                           int path_begin_in_output,
+                           size_t path_begin_in_output,
                            CanonOutput* output) {
   if (!path.is_nonempty())
     return true;
@@ -263,11 +263,10 @@
   // We use this variable to minimize the amount of work done when unescaping --
   // we'll only call CheckForNestedEscapes() when this points at one of the last
   // couple of characters in |output|.
-  int last_invalid_percent_index = INT_MIN;
+  absl::optional<size_t> last_invalid_percent_index;
 
   bool success = true;
   for (size_t i = static_cast<size_t>(path.begin); i < end; i++) {
-    GURL_DCHECK_LT(last_invalid_percent_index, output->length());
     UCHAR uch = static_cast<UCHAR>(spec[i]);
     if (sizeof(CHAR) > 1 && uch >= 0x80) {
       // We only need to test wide input for having non-ASCII characters. For
@@ -307,7 +306,7 @@
               case DIRECTORY_UP:
                 BackUpToPreviousSlash(path_begin_in_output, output);
                 if (last_invalid_percent_index >= output->length()) {
-                  last_invalid_percent_index = INT_MIN;
+                  last_invalid_percent_index = absl::nullopt;
                 }
                 i += dotlen + consumed_len - 1;
                 break;
@@ -339,9 +338,12 @@
               // '%' from a previously-detected invalid escape sequence, we
               // might have an input string with problematic nested escape
               // sequences; detect and fix them.
-              if (last_invalid_percent_index >= (output->length() - 3)) {
+              if (last_invalid_percent_index.has_value() &&
+                  ((last_invalid_percent_index.value() + 3) >=
+                   output->length())) {
                 CheckForNestedEscapes(spec, i + 1, end,
-                                      last_invalid_percent_index, output);
+                                      last_invalid_percent_index.value(),
+                                      output);
               }
             } else {
               // Either this is an invalid escaped character, or it's a valid
@@ -455,7 +457,7 @@
 
 bool CanonicalizePartialPathInternal(const char* spec,
                                      const Component& path,
-                                     int path_begin_in_output,
+                                     size_t path_begin_in_output,
                                      CanonOutput* output) {
   return DoPartialPathInternal<char, unsigned char>(
       spec, path, path_begin_in_output, output);
@@ -463,7 +465,7 @@
 
 bool CanonicalizePartialPathInternal(const char16_t* spec,
                                      const Component& path,
-                                     int path_begin_in_output,
+                                     size_t path_begin_in_output,
                                      CanonOutput* output) {
   return DoPartialPathInternal<char16_t, char16_t>(
       spec, path, path_begin_in_output, output);
diff --git a/url/url_canon_pathurl.cc b/url/url_canon_pathurl.cc
index d8d65f3..85983a8 100644
--- a/url/url_canon_pathurl.cc
+++ b/url/url_canon_pathurl.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_query.cc b/url/url_canon_query.cc
index 53699c5..4beac7a 100644
--- a/url/url_canon_query.cc
+++ b/url/url_canon_query.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_relative.cc b/url/url_canon_relative.cc
index 309f596..80588fe 100644
--- a/url/url_canon_relative.cc
+++ b/url/url_canon_relative.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -355,7 +355,7 @@
       // Relative path, replace the query, and reference. We take the
       // original path with the file part stripped, and append the new path.
       // The canonicalizer will take care of resolving ".." and "."
-      int path_begin = output->length();
+      size_t path_begin = output->length();
       CopyToLastSlash(base_url, base_path_begin, base_parsed.path.end(),
                       output);
       success &= CanonicalizePartialPathInternal(relative_url, path, path_begin,
diff --git a/url/url_canon_stdstring.cc b/url/url_canon_stdstring.cc
index c81a0a9..60e2a26 100644
--- a/url/url_canon_stdstring.cc
+++ b/url/url_canon_stdstring.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,11 +6,10 @@
 
 namespace url {
 
-StdStringCanonOutput::StdStringCanonOutput(std::string* str)
-    : CanonOutput(), str_(str) {
-  cur_len_ = static_cast<int>(str_->size());  // Append to existing data.
-  buffer_ = str_->empty() ? NULL : &(*str_)[0];
-  buffer_len_ = static_cast<int>(str_->size());
+StdStringCanonOutput::StdStringCanonOutput(std::string* str) : str_(str) {
+  cur_len_ = str_->size();  // Append to existing data.
+  buffer_ = str_->empty() ? nullptr : &(*str_)[0];
+  buffer_len_ = str_->size();
 }
 
 StdStringCanonOutput::~StdStringCanonOutput() {
@@ -22,9 +21,9 @@
   buffer_len_ = cur_len_;
 }
 
-void StdStringCanonOutput::Resize(int sz) {
+void StdStringCanonOutput::Resize(size_t sz) {
   str_->resize(sz);
-  buffer_ = str_->empty() ? NULL : &(*str_)[0];
+  buffer_ = str_->empty() ? nullptr : &(*str_)[0];
   buffer_len_ = sz;
 }
 
diff --git a/url/url_canon_stdstring.h b/url/url_canon_stdstring.h
index d8b94ec..c9e2a1b 100644
--- a/url/url_canon_stdstring.h
+++ b/url/url_canon_stdstring.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -46,7 +46,7 @@
   // Must be called after writing has completed but before the string is used.
   void Complete();
 
-  void Resize(int sz) override;
+  void Resize(size_t sz) override;
 
  protected:
   // `str_` is not a raw_ptr<...> for performance reasons (based on analysis of
diff --git a/url/url_canon_stdurl.cc b/url/url_canon_stdurl.cc
index d7e4197..da18d42 100644
--- a/url/url_canon_stdurl.cc
+++ b/url/url_canon_stdurl.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_canon_unittest.cc b/url/url_canon_unittest.cc
index 4fa31ec..62a5c36 100644
--- a/url/url_canon_unittest.cc
+++ b/url/url_canon_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_constants.cc b/url/url_constants.cc
index ee21a27..aa8978b 100644
--- a/url/url_constants.cc
+++ b/url/url_constants.cc
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_constants.h b/url/url_constants.h
index 9c72569..bbcdd40 100644
--- a/url/url_constants.h
+++ b/url/url_constants.h
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_file.h b/url/url_file.h
index c15c8f5..114c46f 100644
--- a/url/url_file.h
+++ b/url/url_file.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,6 +17,9 @@
 inline bool IsWindowsDriveSeparator(char16_t ch) {
   return ch == ':' || ch == '|';
 }
+inline bool IsWindowsDriveSeparator(char ch) {
+  return IsWindowsDriveSeparator(static_cast<char16_t>(ch));
+}
 
 // Returns the index of the next slash in the input after the given index, or
 // spec_len if the end of the input is reached.
diff --git a/url/url_idna_ascii_only.cc b/url/url_idna_ascii_only.cc
index 55e8459..2a4f0d3 100644
--- a/url/url_idna_ascii_only.cc
+++ b/url/url_idna_ascii_only.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_idna_icu.cc b/url/url_idna_icu.cc
index 381d74e..356a1cd 100644
--- a/url/url_idna_icu.cc
+++ b/url/url_idna_icu.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_parse_file.cc b/url/url_parse_file.cc
index 77a622f..582f5d3 100644
--- a/url/url_parse_file.cc
+++ b/url/url_parse_file.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_parse_internal.h b/url/url_parse_internal.h
index 4e2527a..a73f13b 100644
--- a/url/url_parse_internal.h
+++ b/url/url_parse_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,12 +15,18 @@
 inline bool IsURLSlash(char16_t ch) {
   return ch == '/' || ch == '\\';
 }
+inline bool IsURLSlash(char ch) {
+  return IsURLSlash(static_cast<char16_t>(ch));
+}
 
 // Returns true if we should trim this character from the URL because it is a
 // space or a control character.
 inline bool ShouldTrimFromURL(char16_t ch) {
   return ch <= ' ';
 }
+inline bool ShouldTrimFromURL(char ch) {
+  return ShouldTrimFromURL(static_cast<char16_t>(ch));
+}
 
 // Given an already-initialized begin index and length, this shrinks the range
 // to eliminate "should-be-trimmed" characters. Note that the length does *not*
diff --git a/url/url_parse_perftest.cc b/url/url_parse_perftest.cc
index 82c7693..b9b85d9 100644
--- a/url/url_parse_perftest.cc
+++ b/url/url_parse_perftest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright 2006-2008 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_parse_unittest.cc b/url/url_parse_unittest.cc
index 9a8bb57..f67a445 100644
--- a/url/url_parse_unittest.cc
+++ b/url/url_parse_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_test_utils.h b/url/url_test_utils.h
index bb75c74..e1be7fc 100644
--- a/url/url_test_utils.h
+++ b/url/url_test_utils.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_util.cc b/url/url_util.cc
index ac6ffd7..872e469 100644
--- a/url/url_util.cc
+++ b/url/url_util.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,6 +12,7 @@
 
 #include "polyfills/base/check_op.h"
 #include "base/compiler_specific.h"
+#include "base/containers/contains.h"
 #include "base/no_destructor.h"
 #include "base/strings/string_util.h"
 #include "url/url_canon_internal.h"
@@ -522,10 +523,7 @@
   GURL_DCHECK(strlen(new_scheme) > 0);
   GURL_DCHECK(strlen(handler) > 0);
   GURL_DCHECK_EQ(gurl_base::ToLowerASCII(new_scheme), new_scheme);
-  GURL_DCHECK(std::find_if(schemes->begin(), schemes->end(),
-                      [&new_scheme](const SchemeWithHandler& scheme) {
-                        return scheme.scheme == new_scheme;
-                      }) == schemes->end());
+  GURL_DCHECK(!gurl_base::Contains(*schemes, new_scheme, &SchemeWithHandler::scheme));
   schemes->push_back({new_scheme, handler});
 }
 
@@ -534,8 +532,7 @@
   GURL_DCHECK(schemes);
   GURL_DCHECK(strlen(new_scheme) > 0);
   GURL_DCHECK_EQ(gurl_base::ToLowerASCII(new_scheme), new_scheme);
-  GURL_DCHECK(std::find(schemes->begin(), schemes->end(), new_scheme) ==
-         schemes->end());
+  GURL_DCHECK(!gurl_base::Contains(*schemes, new_scheme));
   schemes->push_back(new_scheme);
 }
 
@@ -546,10 +543,7 @@
   GURL_DCHECK(schemes);
   GURL_DCHECK(strlen(new_scheme) > 0);
   GURL_DCHECK_EQ(gurl_base::ToLowerASCII(new_scheme), new_scheme);
-  GURL_DCHECK(std::find_if(schemes->begin(), schemes->end(),
-                      [&new_scheme](const SchemeWithType& scheme) {
-                        return scheme.scheme == new_scheme;
-                      }) == schemes->end());
+  GURL_DCHECK(!gurl_base::Contains(*schemes, new_scheme, &SchemeWithType::scheme));
   schemes->push_back({new_scheme, type});
 }
 
@@ -878,10 +872,9 @@
   int output_initial_length = output->length();
   // Convert that 8-bit to UTF-16. It's not clear IE does this at all to
   // JavaScript URLs, but Firefox and Safari do.
-  size_t unescaped_length = static_cast<size_t>(unescaped_chars.length());
+  size_t unescaped_length = unescaped_chars.length();
   for (size_t i = 0; i < unescaped_length; i++) {
-    unsigned char uch =
-        static_cast<unsigned char>(unescaped_chars.at(static_cast<int>(i)));
+    unsigned char uch = static_cast<unsigned char>(unescaped_chars.at(i));
     if (uch < 0x80) {
       // Non-UTF-8, just append directly
       output->push_back(uch);
@@ -905,7 +898,7 @@
         // copy all characters from the beginning to the end of the
         // identified sequence.
         output->set_length(output_initial_length);
-        for (int j = 0; j < unescaped_chars.length(); ++j)
+        for (size_t j = 0; j < unescaped_chars.length(); ++j)
           output->push_back(static_cast<unsigned char>(unescaped_chars.at(j)));
         break;
       }
diff --git a/url/url_util.h b/url/url_util.h
index e622130..b489362 100644
--- a/url/url_util.h
+++ b/url/url_util.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_util_internal.h b/url/url_util_internal.h
index b2730b6..fe2a4d9 100644
--- a/url/url_util_internal.h
+++ b/url/url_util_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/url/url_util_unittest.cc b/url/url_util_unittest.cc
index 53aab7d..098dc7c 100644
--- a/url/url_util_unittest.cc
+++ b/url/url_util_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.