Update googleurl to the version from Sat Nov 5 08:06:16 2022

This is corresponding to the Chromium commit 9880a0d69c8b70d4cd18f6705afcc4f73aba0b9b.

In this CL, I have also finally mocked out raw_ptr with a typedef, since
it keeps breaking every roll, and supporting it seems untenable.

Change-Id: Ia9b0c01d961a9586e1642df3dc27ce4573f6d484
diff --git a/AUTHORS b/AUTHORS
index 59ecce0..b32867a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -134,6 +134,7 @@
 Arnaud Renevier <a.renevier@samsung.com>
 Arpita Bahuguna <a.bah@samsung.com>
 Arthur Lussos <developer0420@gmail.com>
+Artur Akerberg <artur.aker@gmail.com>
 Arun Kulkarni <kulkarni.a@samsung.com>
 Arun Kumar <arun87.kumar@samsung.com>
 Arun Mankuzhi <arun.m@samsung.com>
@@ -514,6 +515,7 @@
 Jan Keitel <jan.keitel@gmail.com>
 Jan Rucka <ruckajan10@gmail.com>
 Jan Sauer <jan@jansauer.de>
+Jan-Michael Brummer <jan.brummer@tabos.org>
 Janusz Majnert <jmajnert@gmail.com>
 Janwar Dinata <j.dinata@gmail.com>
 Jared Shumway <jaredshumway94@gmail.com>
@@ -598,6 +600,7 @@
 Jongheon Kim <sapzape@gmail.com>
 JongKwon Lee <jongkwon.lee@navercorp.com>
 Jongmok Kim <jongmok.kim@navercorp.com>
+Jongmok Kim <johny.kimc@gmail.com>
 Jongsoo Lee <leejongsoo@gmail.com>
 Joone Hur <joone.hur@intel.com>
 Joonghun Park <pjh0718@gmail.com>
@@ -1319,6 +1322,7 @@
 Yizhou Jiang <yizhou.jiang@intel.com>
 Yoav Weiss <yoav@yoav.ws>
 Yoav Zilberberg <yoav.zilberberg@gmail.com>
+Yoichiro Hibara <hibarayoichiro871@gmail.com>
 Yong Ling <yongling@tencent.com>
 Yong Shin <sy3620@gmail.com>
 Yong Wang <ccyongwang@tencent.com>
@@ -1403,8 +1407,9 @@
 Endless Mobile, Inc. <*@endlessm.com>
 EngFlow, Inc. <*@engflow.com>
 Estimote, Inc. <*@estimote.com>
-Facebook, Inc. <*@fb.com>
-Facebook, Inc. <*@oculus.com>
+Meta Platforms, Inc. <*@fb.com>
+Meta Platforms, Inc. <*@meta.com>
+Meta Platforms, Inc. <*@oculus.com>
 Google Inc. <*@google.com>
 Grammarly, Inc. <*@grammarly.com>
 Hewlett-Packard Development Company, L.P. <*@hp.com>
@@ -1446,6 +1451,7 @@
 Tableau Software <*@tableau.com>
 Talon Cyber Security Ltd. <*@talon-sec.com>
 TeamSpeak Systems GmbH <*@teamspeak.com>
+The Browser Company <*@thebrowser.company>
 The Chromium Authors <*@chromium.org>
 The MathWorks, Inc. <binod.pant@mathworks.com>
 THEO Technologies <*@theoplayer.com>
diff --git a/README.md b/README.md
index 40fd7f1..5965c48 100644
--- a/README.md
+++ b/README.md
@@ -17,8 +17,8 @@
 the following commands in the root of the checkout:
 
 1. `copybara copy.bara.sky import <path-to-chrome>/src --folder-dir .`
-1. `bazel test --cxxopt="-std=c++14" //...`
-   (C++14 is replacible with later C++ versions)
+1. `bazel test --cxxopt="-std=c++17" //...`
+   (C++17 is replacible with later C++ versions)
 1. Fix all of the compilation errors, potentially modifying the BUILD files and
    the polyfill headers in `polyfill/` as appropriate.
 1. Check the new version into Git.
diff --git a/base/BUILD b/base/BUILD
index 32c3b9c..a1410fb 100644
--- a/base/BUILD
+++ b/base/BUILD
@@ -32,7 +32,6 @@
         "functional/identity.h",
         "functional/invoke.h",
         "functional/not_fn.h",
-        "memory/raw_ptr.h",
         "memory/raw_ptr_exclusion.h",
         "no_destructor.h",
         "numerics/checked_math.h",
@@ -53,6 +52,7 @@
         "strings/string_piece_forward.h",
         "strings/string_piece.h",
         "strings/string_util.h",
+        "strings/string_util_impl_helpers.h",
         "strings/string_util_internal.h",
         "strings/string_number_conversions.h",
         "strings/utf_string_conversions.h",
diff --git a/base/cxx20_to_address.h b/base/cxx20_to_address.h
index ef67a9b..04d0f71 100644
--- a/base/cxx20_to_address.h
+++ b/base/cxx20_to_address.h
@@ -5,10 +5,24 @@
 #ifndef BASE_CXX20_TO_ADDRESS_H_
 #define BASE_CXX20_TO_ADDRESS_H_
 
+#include <memory>
 #include <type_traits>
 
 namespace gurl_base {
 
+namespace {
+
+template <typename Ptr, typename = void>
+struct has_std_to_address : std::false_type {};
+
+template <typename Ptr>
+struct has_std_to_address<
+    Ptr,
+    std::void_t<decltype(std::pointer_traits<Ptr>::to_address(
+        std::declval<Ptr>()))>> : std::true_type {};
+
+}  // namespace
+
 // 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
@@ -23,14 +37,12 @@
 }
 
 template <typename Ptr>
-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->());
+constexpr auto to_address(const Ptr& p) noexcept {
+  if constexpr (has_std_to_address<Ptr>::value) {
+    return std::pointer_traits<Ptr>::to_address(p);
+  } else {
+    return gurl_base::to_address(p.operator->());
+  }
 }
 
 }  // namespace base
diff --git a/base/debug/crash_logging.cc b/base/debug/crash_logging.cc
index 157a79f..68d1c96 100644
--- a/base/debug/crash_logging.cc
+++ b/base/debug/crash_logging.cc
@@ -4,6 +4,8 @@
 
 #include "base/debug/crash_logging.h"
 
+#include <ostream>
+
 #include "base/strings/string_piece.h"
 #include "build/build_config.h"
 
diff --git a/base/debug/crash_logging.h b/base/debug/crash_logging.h
index b4cf7bc..ec1df77 100644
--- a/base/debug/crash_logging.h
+++ b/base/debug/crash_logging.h
@@ -12,7 +12,7 @@
 #include <type_traits>
 
 #include "polyfills/base/base_export.h"
-#include "base/memory/raw_ptr.h"
+#include "polyfills/base/memory/raw_ptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 
@@ -48,7 +48,7 @@
 //
 //   static auto* const crash_key = gurl_base::debug::AllocateCrashKeyString(
 //       "name", gurl_base::debug::CrashKeySize::Size32);
-//   gurl_base::debug::SetCrashKeyString(crash_key);
+//   gurl_base::debug::SetCrashKeyString(crash_key, "value");
 //
 //   // Do other work before calling `gurl_base::debug::DumpWithoutCrashing()` later.
 //
diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h
deleted file mode 100644
index d65ab44..0000000
--- a/base/memory/raw_ptr.h
+++ /dev/null
@@ -1,1510 +0,0 @@
-// 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.
-
-#ifndef BASE_MEMORY_RAW_PTR_H_
-#define BASE_MEMORY_RAW_PTR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <climits>
-#include <cstddef>
-#include <functional>
-#include <type_traits>
-#include <utility>
-
-#include "polyfills/base/allocator/buildflags.h"
-
-#include "polyfills/base/check.h"
-#include "base/compiler_specific.h"
-#include "polyfills/base/dcheck_is_on.h"
-#include "polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h"
-#include "build/build_config.h"
-#include "build/buildflag.h"
-
-#if BUILDFLAG(USE_BACKUP_REF_PTR) || \
-    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"
-#include "base/allocator/partition_allocator/partition_address_space.h"
-#include "base/allocator/partition_allocator/partition_alloc_constants.h"
-#include "polyfills/base/base_export.h"
-#endif  // BUILDFLAG(USE_BACKUP_REF_PTR) ||
-        // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_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_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-
-#if BUILDFLAG(IS_WIN)
-#include "base/win/win_handle_types.h"
-#endif
-
-namespace cc {
-class Scheduler;
-}
-namespace gurl_base::internal {
-class DelayTimerBase;
-}
-namespace content::responsiveness {
-class Calculator;
-}
-
-namespace gurl_base {
-
-// 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.
-
-// This type trait verifies a type can be used as a pointer offset.
-//
-// We support pointer offsets in signed (ptrdiff_t) or unsigned (size_t) values.
-// Smaller types are also allowed.
-template <typename Z>
-static constexpr bool offset_type =
-    std::is_integral_v<Z> && sizeof(Z) <= sizeof(ptrdiff_t);
-
-struct RawPtrNoOpImpl {
-  // Wraps a pointer.
-  template <typename T>
-  static ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
-    return ptr;
-  }
-
-  // Notifies the allocator when a wrapped pointer is being removed or replaced.
-  template <typename T>
-  static ALWAYS_INLINE void ReleaseWrappedPtr(T*) {}
-
-  // Unwraps the pointer, while asserting that memory hasn't been freed. The
-  // function is allowed to crash on nullptr.
-  template <typename T>
-  static ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer, while asserting that memory hasn't been freed. The
-  // function must handle nullptr gracefully.
-  template <typename T>
-  static ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer, without making an assertion on whether memory was
-  // freed or not.
-  template <typename T>
-  static ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // Upcasts the wrapped pointer.
-  template <typename To, typename From>
-  static ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) {
-    static_assert(std::is_convertible<From*, To*>::value,
-                  "From must be convertible to To.");
-    // Note, this cast may change the address if upcasting to base that lies in
-    // the middle of the derived object.
-    return wrapped_ptr;
-  }
-
-  // Advance the wrapped pointer by `delta_elems`.
-  template <typename T,
-            typename Z,
-            typename = std::enable_if_t<offset_type<Z>, void>>
-  static ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
-    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>
-  static ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // This is for accounting only, used by unit tests.
-  static ALWAYS_INLINE void IncrementSwapCountForTest() {}
-  static ALWAYS_INLINE void IncrementLessCountForTest() {}
-  static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
-};
-
-#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-
-constexpr int kValidAddressBits = 48;
-constexpr uintptr_t kAddressMask = (1ull << kValidAddressBits) - 1;
-constexpr int kTagBits = sizeof(uintptr_t) * 8 - kValidAddressBits;
-
-// MTECheckedPtr has no business with the topmost bits reserved for the
-// tag used by true ARM MTE, so we strip it out here.
-constexpr uintptr_t kTagMask =
-    ~kAddressMask & partition_alloc::internal::kPtrUntagMask;
-
-constexpr int kTopBitShift = 63;
-constexpr uintptr_t kTopBit = 1ull << kTopBitShift;
-static_assert(kTopBit << 1 == 0, "kTopBit should really be the top bit");
-static_assert((kTopBit & kTagMask) > 0,
-              "kTopBit bit must be inside the tag region");
-
-// This functionality is outside of MTECheckedPtrImpl, so that it can be
-// overridden by tests.
-struct MTECheckedPtrImplPartitionAllocSupport {
-  // Checks if the necessary support is enabled in PartitionAlloc for `ptr`.
-  template <typename T>
-  static ALWAYS_INLINE bool EnabledForPtr(T* ptr) {
-    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this class
-    // is responsible for handling the software MTE tag.
-    auto addr = partition_alloc::UntagPtr(ptr);
-    return partition_alloc::IsManagedByPartitionAlloc(addr);
-  }
-
-  // Returns pointer to the tag that protects are pointed by |addr|.
-  static ALWAYS_INLINE void* TagPointer(uintptr_t addr) {
-    return partition_alloc::PartitionTagPointer(addr);
-  }
-};
-
-template <typename PartitionAllocSupport>
-struct MTECheckedPtrImpl {
-  // This implementation assumes that pointers are 64 bits long and at least 16
-  // top bits are unused. The latter is harder to verify statically, but this is
-  // true for all currently supported 64-bit architectures (GURL_DCHECK when wrapping
-  // will verify that).
-  static_assert(sizeof(void*) >= 8, "Need 64-bit pointers");
-
-  // Wraps a pointer, and returns its uintptr_t representation.
-  template <typename T>
-  static ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
-    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
-    // function is responsible for adding the software MTE tag.
-    uintptr_t addr = partition_alloc::UntagPtr(ptr);
-    GURL_DCHECK_EQ(ExtractTag(addr), 0ull);
-
-    // Return a not-wrapped |addr|, if it's either nullptr or if the protection
-    // for this pointer is disabled.
-    if (!PartitionAllocSupport::EnabledForPtr(ptr)) {
-      return ptr;
-    }
-
-    // Read the tag and place it in the top bits of the address.
-    // Even if PartitionAlloc's tag has less than kTagBits, we'll read
-    // what's given and pad the rest with 0s.
-    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;
-    // See the disambiguation comment above.
-    // TODO(kdlee): Ensure that ptr's hardware MTE tag is preserved.
-    // TODO(kdlee): Ensure that hardware and software MTE tags don't conflict.
-    return static_cast<T*>(partition_alloc::internal::TagAddr(addr));
-  }
-
-  // Notifies the allocator when a wrapped pointer is being removed or replaced.
-  // No-op for MTECheckedPtrImpl.
-  template <typename T>
-  static ALWAYS_INLINE void ReleaseWrappedPtr(T*) {}
-
-  // Unwraps the pointer's uintptr_t representation, while asserting that memory
-  // hasn't been freed. The function is allowed to crash on nullptr.
-  template <typename T>
-  static ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
-    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
-    // function is responsible for removing the software MTE tag.
-    uintptr_t wrapped_addr = partition_alloc::UntagPtr(wrapped_ptr);
-    uintptr_t tag = ExtractTag(wrapped_addr);
-    if (tag > 0) {
-      // Read the tag provided by PartitionAlloc.
-      //
-      // Cast to volatile to ensure memory is read. E.g. in a tight loop, the
-      // compiler could cache the value in a register and thus could miss that
-      // another thread freed memory and changed tag.
-      uintptr_t read_tag =
-          *static_cast<volatile partition_alloc::PartitionTag*>(
-              PartitionAllocSupport::TagPointer(ExtractAddress(wrapped_addr)));
-      if (UNLIKELY(tag != read_tag))
-        IMMEDIATE_CRASH();
-      // See the disambiguation comment above.
-      // TODO(kdlee): Ensure that ptr's hardware MTE tag is preserved.
-      // TODO(kdlee): Ensure that hardware and software MTE tags don't conflict.
-      return static_cast<T*>(
-          partition_alloc::internal::TagAddr(ExtractAddress(wrapped_addr)));
-    }
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer's uintptr_t representation, while asserting that memory
-  // hasn't been freed. The function must handle nullptr gracefully.
-  template <typename T>
-  static ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
-    // SafelyUnwrapPtrForDereference handles nullptr case well.
-    return SafelyUnwrapPtrForDereference(wrapped_ptr);
-  }
-
-  // Unwraps the pointer's uintptr_t representation, without making an assertion
-  // on whether memory was freed or not.
-  template <typename T>
-  static ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
-    return ExtractPtr(wrapped_ptr);
-  }
-
-  // Upcasts the wrapped pointer.
-  template <typename To, typename From>
-  static ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) {
-    static_assert(std::is_convertible<From*, To*>::value,
-                  "From must be convertible to To.");
-
-    // The top-bit tag must not affect the result of upcast.
-    return static_cast<To*>(wrapped_ptr);
-  }
-
-  // Advance the wrapped pointer by `delta_elems`.
-  template <typename T,
-            typename Z,
-            typename = std::enable_if_t<offset_type<Z>, void>>
-  static ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
-    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>
-  static ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // This is for accounting only, used by unit tests.
-  static ALWAYS_INLINE void IncrementSwapCountForTest() {}
-  static ALWAYS_INLINE void IncrementLessCountForTest() {}
-  static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
-
- private:
-  static ALWAYS_INLINE uintptr_t ExtractAddress(uintptr_t wrapped_ptr) {
-    return wrapped_ptr & kAddressMask;
-  }
-
-  template <typename T>
-  static ALWAYS_INLINE T* ExtractPtr(T* wrapped_ptr) {
-    // Disambiguation: UntagPtr/TagAddr handle the hardware MTE tag, whereas
-    // this function is responsible for removing the software MTE tag.
-    // TODO(kdlee): Ensure that wrapped_ptr's hardware MTE tag is preserved.
-    // TODO(kdlee): Ensure that hardware and software MTE tags don't conflict.
-    return static_cast<T*>(partition_alloc::internal::TagAddr(
-        ExtractAddress(partition_alloc::UntagPtr(wrapped_ptr))));
-  }
-
-  static ALWAYS_INLINE uintptr_t ExtractTag(uintptr_t wrapped_ptr) {
-    return (wrapped_ptr & kTagMask) >> kValidAddressBits;
-  }
-};
-
-#endif  // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-
-#if BUILDFLAG(USE_BACKUP_REF_PTR)
-
-#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-BASE_EXPORT void CheckThatAddressIsntWithinFirstPartitionPage(
-    uintptr_t address);
-#endif
-
-template <bool AllowDangling = false>
-struct BackupRefPtrImpl {
-  // Note that `BackupRefPtrImpl` itself is not thread-safe. If multiple threads
-  // modify the same smart pointer object without synchronization, a data race
-  // will occur.
-
-  static ALWAYS_INLINE bool IsSupportedAndNotNull(uintptr_t address) {
-    // This covers the nullptr case, as address 0 is never in GigaCage.
-    bool is_in_brp_pool =
-        partition_alloc::IsManagedByPartitionAllocBRPPool(address);
-
-    // There are many situations where the compiler can prove that
-    // ReleaseWrappedPtr is called on a value that is always nullptr, but the
-    // way the check above is written, the compiler can't prove that nullptr is
-    // not managed by PartitionAlloc; and so the compiler has to emit a useless
-    // check and dead code.
-    // To avoid that without making the runtime check slower, explicitly promise
-    // to the compiler that is_in_brp_pool will always be false for nullptr.
-    //
-    // This condition would look nicer and might also theoretically be nicer for
-    // the optimizer if it was written as "if (!address) { ... }", but
-    // LLVM currently has issues with optimizing that away properly; see:
-    // https://bugs.llvm.org/show_bug.cgi?id=49403
-    // https://reviews.llvm.org/D97848
-    // https://chromium-review.googlesource.com/c/chromium/src/+/2727400/2/base/memory/checked_ptr.h#120
-#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-    GURL_CHECK(address || !is_in_brp_pool);
-#endif
-#if HAS_BUILTIN(__builtin_assume)
-    __builtin_assume(address || !is_in_brp_pool);
-#endif
-
-    // There may be pointers immediately after the allocation, e.g.
-    //   {
-    //     // Assume this allocation happens outside of PartitionAlloc.
-    //     raw_ptr<T> ptr = new T[20];
-    //     for (size_t i = 0; i < 20; i ++) { ptr++; }
-    //   }
-    //
-    // Such pointers are *not* at risk of accidentally falling into BRP pool,
-    // because:
-    // 1) On 64-bit systems, BRP pool is preceded by a forbidden region.
-    // 2) On 32-bit systems, the guard pages and metadata of super pages in BRP
-    //    pool aren't considered to be part of that pool.
-    //
-    // This allows us to make a stronger assertion that if
-    // IsManagedByPartitionAllocBRPPool returns true for a valid pointer,
-    // it must be at least partition page away from the beginning of a super
-    // page.
-#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-    if (is_in_brp_pool) {
-      CheckThatAddressIsntWithinFirstPartitionPage(address);
-    }
-#endif
-
-    return is_in_brp_pool;
-  }
-
-  // Wraps a pointer.
-  template <typename T>
-  static ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
-    uintptr_t address = partition_alloc::UntagPtr(ptr);
-    if (IsSupportedAndNotNull(address)) {
-#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-      GURL_CHECK(ptr != nullptr);
-#endif
-      AcquireInternal(address);
-    }
-#if !defined(PA_HAS_64_BITS_POINTERS)
-    else {
-      partition_alloc::internal::AddressPoolManagerBitmap::
-          BanSuperPageFromBRPPool(address);
-    }
-#endif
-
-    return ptr;
-  }
-
-  // Notifies the allocator when a wrapped pointer is being removed or replaced.
-  template <typename T>
-  static ALWAYS_INLINE void ReleaseWrappedPtr(T* wrapped_ptr) {
-    uintptr_t address = partition_alloc::UntagPtr(wrapped_ptr);
-    if (IsSupportedAndNotNull(address)) {
-#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-      GURL_CHECK(wrapped_ptr != nullptr);
-#endif
-      ReleaseInternal(address);
-    }
-    // We are unable to counteract BanSuperPageFromBRPPool(), called from
-    // WrapRawPtr(). We only use one bit per super-page and, thus can't tell if
-    // there's more than one associated raw_ptr<T> at a given time. The risk of
-    // exhausting the entire address space is minuscule, therefore, we couldn't
-    // resist the perf gain of a single relaxed store (in the above mentioned
-    // function) over much more expensive two CAS operations, which we'd have to
-    // use if we were to un-ban a super-page.
-  }
-
-  // Unwraps the pointer, while asserting that memory hasn't been freed. The
-  // function is allowed to crash on nullptr.
-  template <typename T>
-  static ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
-#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-    uintptr_t address = partition_alloc::UntagPtr(wrapped_ptr);
-    if (IsSupportedAndNotNull(address)) {
-      GURL_CHECK(wrapped_ptr != nullptr);
-      GURL_CHECK(IsPointeeAlive(address));
-    }
-#endif
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer, while asserting that memory hasn't been freed. The
-  // function must handle nullptr gracefully.
-  template <typename T>
-  static ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer, without making an assertion on whether memory was
-  // freed or not.
-  template <typename T>
-  static ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // Upcasts the wrapped pointer.
-  template <typename To, typename From>
-  static ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) {
-    static_assert(std::is_convertible<From*, To*>::value,
-                  "From must be convertible to To.");
-    // Note, this cast may change the address if upcasting to base that lies in
-    // the middle of the derived object.
-    return wrapped_ptr;
-  }
-
-  // Advance the wrapped pointer by `delta_elems`.
-  template <typename T,
-            typename Z,
-            typename = std::enable_if_t<offset_type<Z>, void>>
-  static ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
-#if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
-    // First check if the new address lands within the same allocation
-    // (end-of-allocation address is ok too). It has a non-trivial cost, but
-    // it's cheaper and more secure than the previous implementation that
-    // 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;
-#else
-    // In the "before allocation" mode, on 32-bit, we can run into a problem
-    // that the end-of-allocation address could fall out of "GigaCage", if this
-    // is the last slot of the super page, thus pointing to the guard page. This
-    // mean the ref-count won't be decreased when the pointer is released
-    // (leak).
-    //
-    // We could possibly solve it in a few different ways:
-    // - Add the trailing guard page to "GigaCage", but we'd have to think very
-    //   hard if this doesn't create another hole.
-    // - Add an address adjustment to "GigaCage" check, similar as the one in
-    //   PartitionAllocGetSlotStartInBRPPool(), but that seems fragile, not to
-    //   mention adding an extra instruction to an inlined hot path.
-    // - Let the leak happen, since it should a very rare condition.
-    // - Go back to the previous solution of rewrapping the pointer, but that
-    //   had an issue of losing protection in case the pointer ever gets shifter
-    //   before the end of allocation.
-    //
-    // We decided to cross that bridge once we get there... if we ever get
-    // there. Currently there are no plans to switch back to the "before
-    // allocation" mode.
-    //
-    // This problem doesn't exist in the "previous slot" mode, or any mode that
-    // involves putting extras after the allocation, because the
-    // end-of-allocation address belongs to the same slot.
-    static_assert(false);
-#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.
-  template <typename T>
-  static ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) {
-    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() {}
-  static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
-
- private:
-  // We've evaluated several strategies (inline nothing, various parts, or
-  // everything in |Wrap()| and |Release()|) using the Speedometer2 benchmark
-  // to measure performance. The best results were obtained when only the
-  // lightweight |IsManagedByPartitionAllocBRPPool()| check was inlined.
-  // Therefore, we've extracted the rest into the functions below and marked
-  // them as NOINLINE to prevent unintended LTO effects.
-  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>)
-      return IsValidSignedDelta(address, ptrdiff_t{delta_in_bytes});
-    else
-      return IsValidUnsignedDelta(address, size_t{delta_in_bytes});
-  }
-  static BASE_EXPORT NOINLINE bool IsValidSignedDelta(uintptr_t address,
-                                                      ptrdiff_t delta_in_bytes);
-  static BASE_EXPORT NOINLINE bool IsValidUnsignedDelta(uintptr_t address,
-                                                        size_t delta_in_bytes);
-};
-
-#endif  // BUILDFLAG(USE_BACKUP_REF_PTR)
-
-// Implementation that allows us to detect BackupRefPtr problems in ASan builds.
-struct AsanBackupRefPtrImpl {
-  // Wraps a pointer.
-  template <typename T>
-  static ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
-    AsanCheckIfValidInstantiation(ptr);
-    return ptr;
-  }
-
-  // Notifies the allocator when a wrapped pointer is being removed or replaced.
-  template <typename T>
-  static ALWAYS_INLINE void ReleaseWrappedPtr(T*) {}
-
-  // Unwraps the pointer, while asserting that memory hasn't been freed. The
-  // function is allowed to crash on nullptr.
-  template <typename T>
-  static ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
-    AsanCheckIfValidDereference(wrapped_ptr);
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer, while asserting that memory hasn't been freed. The
-  // function must handle nullptr gracefully.
-  template <typename T>
-  static ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
-    AsanCheckIfValidExtraction(wrapped_ptr);
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer, without making an assertion on whether memory was
-  // freed or not.
-  template <typename T>
-  static ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // Upcasts the wrapped pointer.
-  template <typename To, typename From>
-  static ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) {
-    static_assert(std::is_convertible<From*, To*>::value,
-                  "From must be convertible to To.");
-    // Note, this cast may change the address if upcasting to base that lies in
-    // the middle of the derived object.
-    return wrapped_ptr;
-  }
-
-  // Advance the wrapped pointer by `delta_elems`.
-  template <typename T,
-            typename Z,
-            typename = std::enable_if_t<offset_type<Z>, void>>
-  static ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
-    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>
-  static ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // This is for accounting only, used by unit tests.
-  static ALWAYS_INLINE void IncrementSwapCountForTest() {}
-  static ALWAYS_INLINE void IncrementLessCountForTest() {}
-  static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
-
- private:
-  static BASE_EXPORT NOINLINE void AsanCheckIfValidInstantiation(
-      void const volatile* ptr);
-  static BASE_EXPORT NOINLINE void AsanCheckIfValidDereference(
-      void const volatile* ptr);
-  static BASE_EXPORT NOINLINE void AsanCheckIfValidExtraction(
-      void const volatile* ptr);
-};
-
-template <class 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 SuperImpl::WrapRawPtr(ptr);
-  }
-
-  template <typename T>
-  static ALWAYS_INLINE void ReleaseWrappedPtr(T* ptr) {
-    ++release_wrapped_ptr_cnt;
-    SuperImpl::ReleaseWrappedPtr(ptr);
-  }
-
-  template <typename T>
-  static ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
-    ++get_for_dereference_cnt;
-    return SuperImpl::SafelyUnwrapPtrForDereference(wrapped_ptr);
-  }
-
-  template <typename T>
-  static ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
-    ++get_for_extraction_cnt;
-    return SuperImpl::SafelyUnwrapPtrForExtraction(wrapped_ptr);
-  }
-
-  template <typename T>
-  static ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
-    ++get_for_comparison_cnt;
-    return SuperImpl::UnsafelyUnwrapPtrForComparison(wrapped_ptr);
-  }
-
-  static ALWAYS_INLINE void IncrementSwapCountForTest() {
-    ++wrapped_ptr_swap_cnt;
-  }
-
-  static ALWAYS_INLINE void IncrementLessCountForTest() {
-    ++wrapped_ptr_less_cnt;
-  }
-
-  static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {
-    ++pointer_to_member_operator_cnt;
-  }
-
-  static void ClearCounters() {
-    wrap_raw_ptr_cnt = 0;
-    release_wrapped_ptr_cnt = 0;
-    get_for_dereference_cnt = 0;
-    get_for_extraction_cnt = 0;
-    get_for_comparison_cnt = 0;
-    wrapped_ptr_swap_cnt = 0;
-    wrapped_ptr_less_cnt = 0;
-    pointer_to_member_operator_cnt = 0;
-  }
-
-  static inline int wrap_raw_ptr_cnt = INT_MIN;
-  static inline int release_wrapped_ptr_cnt = INT_MIN;
-  static inline int get_for_dereference_cnt = INT_MIN;
-  static inline int get_for_extraction_cnt = INT_MIN;
-  static inline int get_for_comparison_cnt = INT_MIN;
-  static inline int wrapped_ptr_swap_cnt = INT_MIN;
-  static inline int wrapped_ptr_less_cnt = INT_MIN;
-  static inline int pointer_to_member_operator_cnt = INT_MIN;
-};
-
-}  // namespace internal
-
-namespace raw_ptr_traits {
-
-// IsSupportedType<T>::value answers whether raw_ptr<T> 1) compiles and 2) is
-// always safe at runtime.  Templates that may end up using `raw_ptr<T>` should
-// use IsSupportedType to ensure that raw_ptr is not used with unsupported
-// types.  As an example, see how gurl_base::internal::StorageTraits uses
-// IsSupportedType as a condition for using gurl_base::internal::UnretainedWrapper
-// (which has a `ptr_` field that will become `raw_ptr<T>` after the Big
-// Rewrite).
-template <typename T, typename SFINAE = void>
-struct IsSupportedType {
-  static constexpr bool value = true;
-};
-
-// raw_ptr<T> is not compatible with function pointer types. Also, they don't
-// even need the raw_ptr protection, because they don't point on heap.
-template <typename T>
-struct IsSupportedType<T, std::enable_if_t<std::is_function<T>::value>> {
-  static constexpr bool value = false;
-};
-
-// This section excludes some types from raw_ptr<T> to avoid them from being
-// used inside gurl_base::Unretained in performance sensitive places. These were
-// identified from sampling profiler data. See crbug.com/1287151 for more info.
-template <>
-struct IsSupportedType<cc::Scheduler> {
-  static constexpr bool value = false;
-};
-template <>
-struct IsSupportedType<gurl_base::internal::DelayTimerBase> {
-  static constexpr bool value = false;
-};
-template <>
-struct IsSupportedType<content::responsiveness::Calculator> {
-  static constexpr bool value = false;
-};
-
-// IsRawPtrCountingImpl<T>::value answers whether T is a specialization of
-// RawPtrCountingImplWrapperForTest, to know whether Impl is for testing
-// purposes.
-template <typename T>
-struct IsRawPtrCountingImpl : std::false_type {};
-
-template <typename T>
-struct IsRawPtrCountingImpl<internal::RawPtrCountingImplWrapperForTest<T>>
-    : std::true_type {};
-
-#if __OBJC__
-// raw_ptr<T> is not compatible with pointers to Objective-C classes for a
-// multitude of reasons. They may fail to compile in many cases, and wouldn't
-// work well with tagged pointers. Anyway, Objective-C objects have their own
-// way of tracking lifespan, hence don't need the raw_ptr protection as much.
-//
-// Such pointers are detected by checking if they're convertible to |id| type.
-template <typename T>
-struct IsSupportedType<T,
-                       std::enable_if_t<std::is_convertible<T*, id>::value>> {
-  static constexpr bool value = false;
-};
-#endif  // __OBJC__
-
-#if BUILDFLAG(IS_WIN)
-// raw_ptr<HWND__> is unsafe at runtime - if the handle happens to also
-// represent a valid pointer into a PartitionAlloc-managed region then it can
-// lead to manipulating random memory when treating it as BackupRefPtr
-// ref-count.  See also https://crbug.com/1262017.
-//
-// TODO(https://crbug.com/1262017): Cover other handle types like HANDLE,
-// HLOCAL, HINTERNET, or HDEVINFO.  Maybe we should avoid using raw_ptr<T> when
-// T=void (as is the case in these handle types).  OTOH, explicit,
-// non-template-based raw_ptr<void> should be allowed.  Maybe this can be solved
-// by having 2 traits: IsPointeeAlwaysSafe (to be used in templates) and
-// IsPointeeUsuallySafe (to be used in the static_assert in raw_ptr).  The
-// upside of this approach is that it will safely handle gurl_base::Bind closing over
-// HANDLE.  The downside of this approach is that gurl_base::Bind closing over a
-// void* pointer will not get UaF protection.
-#define CHROME_WINDOWS_HANDLE_TYPE(name)   \
-  template <>                              \
-  struct IsSupportedType<name##__, void> { \
-    static constexpr bool value = false;   \
-  };
-#include "base/win/win_handle_types_list.inc"
-#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
-// over raw pointers.  It behaves just like a raw pointer on platforms where
-// USE_BACKUP_REF_PTR is off, and almost like one when it's on (the main
-// difference is that it's zero-initialized and cleared on destruction and
-// move). Unlike `std::unique_ptr<T>`, `gurl_base::scoped_refptr<T>`, etc., it
-// doesn’t manage ownership or lifetime of an allocated object - you are still
-// responsible for freeing the object when no longer used, just as you would
-// with a raw C++ pointer.
-//
-// Compared to a raw C++ pointer, on platforms where USE_BACKUP_REF_PTR is on,
-// `raw_ptr<T>` incurs additional performance overhead for initialization,
-// destruction, and assignment (including `ptr++` and `ptr += ...`).  There is
-// no overhead when dereferencing a pointer.
-//
-// `raw_ptr<T>` is beneficial for security, because it can prevent a significant
-// percentage of Use-after-Free (UaF) bugs from being exploitable.  `raw_ptr<T>`
-// has limited impact on stability - dereferencing a dangling pointer remains
-// Undefined Behavior.  Note that the security protection is not yet enabled by
-// default.
-//
-// raw_ptr<T> is marked as [[gsl::Pointer]] which allows the compiler to catch
-// some bugs where the raw_ptr holds a dangling pointer to a temporary object.
-// However the [[gsl::Pointer]] analysis expects that such types do not have a
-// 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.
-
-using DefaultRawPtrType = RawPtrBanDanglingIfSupported;
-
-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>>,
-      raw_ptr<T, RawPtrMayDangle>>;
-
- public:
-  static_assert(raw_ptr_traits::IsSupportedType<T>::value,
-                "raw_ptr<T> doesn't work with this kind of pointee type T");
-
-#if BUILDFLAG(USE_BACKUP_REF_PTR)
-  // BackupRefPtr requires a non-trivial default constructor, destructor, etc.
-  constexpr ALWAYS_INLINE raw_ptr() noexcept : wrapped_ptr_(nullptr) {}
-
-  ALWAYS_INLINE raw_ptr(const raw_ptr& p) noexcept
-      : wrapped_ptr_(Impl::Duplicate(p.wrapped_ptr_)) {}
-
-  ALWAYS_INLINE raw_ptr(raw_ptr&& p) noexcept {
-    wrapped_ptr_ = p.wrapped_ptr_;
-    p.wrapped_ptr_ = nullptr;
-  }
-
-  ALWAYS_INLINE raw_ptr& operator=(const raw_ptr& p) noexcept {
-    // Duplicate before releasing, in case the pointer is assigned to itself.
-    //
-    // Unlike the move version of this operator, don't add |this != &p| branch,
-    // for performance reasons. Even though Duplicate() is not cheap, we
-    // practically never assign a raw_ptr<T> to itself. We suspect that a
-    // cumulative cost of a conditional branch, even if always correctly
-    // predicted, would exceed that.
-    T* new_ptr = Impl::Duplicate(p.wrapped_ptr_);
-    Impl::ReleaseWrappedPtr(wrapped_ptr_);
-    wrapped_ptr_ = new_ptr;
-    return *this;
-  }
-
-  ALWAYS_INLINE raw_ptr& operator=(raw_ptr&& p) noexcept {
-    // Unlike the the copy version of this operator, this branch is necessaty
-    // for correctness.
-    if (LIKELY(this != &p)) {
-      Impl::ReleaseWrappedPtr(wrapped_ptr_);
-      wrapped_ptr_ = p.wrapped_ptr_;
-      p.wrapped_ptr_ = nullptr;
-    }
-    return *this;
-  }
-
-  ALWAYS_INLINE ~raw_ptr() noexcept {
-    Impl::ReleaseWrappedPtr(wrapped_ptr_);
-    // Work around external issues where raw_ptr is used after destruction.
-    wrapped_ptr_ = nullptr;
-  }
-
-#else  // BUILDFLAG(USE_BACKUP_REF_PTR)
-
-  // raw_ptr can be trivially default constructed (leaving |wrapped_ptr_|
-  // uninitialized).  This is needed for compatibility with raw pointers.
-  //
-  // TODO(lukasza): Always initialize |wrapped_ptr_|.  Fix resulting build
-  // errors.  Analyze performance impact.
-  constexpr ALWAYS_INLINE raw_ptr() noexcept = default;
-
-  // In addition to nullptr_t ctor above, raw_ptr needs to have these
-  // as |=default| or |constexpr| to avoid hitting -Wglobal-constructors in
-  // cases like this:
-  //     struct SomeStruct { int int_field; raw_ptr<int> ptr_field; };
-  //     SomeStruct g_global_var = { 123, nullptr };
-  ALWAYS_INLINE raw_ptr(const raw_ptr&) noexcept = default;
-  ALWAYS_INLINE raw_ptr(raw_ptr&&) noexcept = default;
-  ALWAYS_INLINE raw_ptr& operator=(const raw_ptr&) noexcept = default;
-  ALWAYS_INLINE raw_ptr& operator=(raw_ptr&&) noexcept = default;
-
-  ALWAYS_INLINE ~raw_ptr() noexcept = default;
-
-#endif  // BUILDFLAG(USE_BACKUP_REF_PTR)
-
-  // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr.
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  constexpr ALWAYS_INLINE raw_ptr(std::nullptr_t) noexcept
-      : wrapped_ptr_(nullptr) {}
-
-  // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr.
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  ALWAYS_INLINE raw_ptr(T* p) noexcept : wrapped_ptr_(Impl::WrapRawPtr(p)) {}
-
-  // Deliberately implicit in order to support implicit upcast.
-  template <typename U,
-            typename Unused = std::enable_if_t<
-                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, RawPtrType>& ptr) noexcept
-      : wrapped_ptr_(
-            Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_))) {}
-  // Deliberately implicit in order to support implicit upcast.
-  template <typename U,
-            typename Unused = std::enable_if_t<
-                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, RawPtrType>&& ptr) noexcept
-      : wrapped_ptr_(Impl::template Upcast<T, U>(ptr.wrapped_ptr_)) {
-#if BUILDFLAG(USE_BACKUP_REF_PTR)
-    ptr.wrapped_ptr_ = nullptr;
-#endif
-  }
-
-  ALWAYS_INLINE raw_ptr& operator=(std::nullptr_t) noexcept {
-    Impl::ReleaseWrappedPtr(wrapped_ptr_);
-    wrapped_ptr_ = nullptr;
-    return *this;
-  }
-  ALWAYS_INLINE raw_ptr& operator=(T* p) noexcept {
-    Impl::ReleaseWrappedPtr(wrapped_ptr_);
-    wrapped_ptr_ = Impl::WrapRawPtr(p);
-    return *this;
-  }
-
-  // Upcast assignment
-  template <typename U,
-            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, 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)
-    GURL_CHECK(reinterpret_cast<uintptr_t>(this) !=
-          reinterpret_cast<uintptr_t>(&ptr));
-#endif
-    Impl::ReleaseWrappedPtr(wrapped_ptr_);
-    wrapped_ptr_ =
-        Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_));
-    return *this;
-  }
-  template <typename U,
-            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, 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)
-    GURL_CHECK(reinterpret_cast<uintptr_t>(this) !=
-          reinterpret_cast<uintptr_t>(&ptr));
-#endif
-    Impl::ReleaseWrappedPtr(wrapped_ptr_);
-    wrapped_ptr_ = Impl::template Upcast<T, U>(ptr.wrapped_ptr_);
-#if BUILDFLAG(USE_BACKUP_REF_PTR)
-    ptr.wrapped_ptr_ = nullptr;
-#endif
-    return *this;
-  }
-
-  // Avoid using. The goal of raw_ptr is to be as close to raw pointer as
-  // possible, so use it only if absolutely necessary (e.g. for const_cast).
-  ALWAYS_INLINE T* get() const { return GetForExtraction(); }
-
-  explicit ALWAYS_INLINE operator bool() const { return !!wrapped_ptr_; }
-
-  template <typename U = T,
-            typename Unused = std::enable_if_t<
-                !std::is_void<typename std::remove_cv<U>::type>::value>>
-  ALWAYS_INLINE U& operator*() const {
-    return *GetForDereference();
-  }
-  ALWAYS_INLINE T* operator->() const { return GetForDereference(); }
-
-  // Disables `(my_raw_ptr->*pmf)(...)` as a workaround for
-  // the ICE in GCC parsing the code, reported at
-  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103455
-  template <typename PMF>
-  void operator->*(PMF) const = delete;
-
-  // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr.
-  // NOLINTNEXTLINE(runtime/explicit)
-  ALWAYS_INLINE operator T*() const { return GetForExtraction(); }
-  template <typename U>
-  explicit ALWAYS_INLINE operator U*() const {
-    // This operator may be invoked from static_cast, meaning the types may not
-    // be implicitly convertible, hence the need for static_cast here.
-    return static_cast<U*>(GetForExtraction());
-  }
-
-  ALWAYS_INLINE raw_ptr& operator++() {
-    wrapped_ptr_ = Impl::Advance(wrapped_ptr_, 1);
-    return *this;
-  }
-  ALWAYS_INLINE raw_ptr& operator--() {
-    wrapped_ptr_ = Impl::Advance(wrapped_ptr_, -1);
-    return *this;
-  }
-  ALWAYS_INLINE raw_ptr operator++(int /* post_increment */) {
-    raw_ptr result = *this;
-    ++(*this);
-    return result;
-  }
-  ALWAYS_INLINE raw_ptr operator--(int /* post_decrement */) {
-    raw_ptr result = *this;
-    --(*this);
-    return result;
-  }
-  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>>>
-  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
-  // involves quarantine.
-  ALWAYS_INLINE void ClearAndDelete() noexcept {
-    delete GetForExtractionAndReset();
-  }
-  ALWAYS_INLINE void ClearAndDeleteArray() noexcept {
-    delete[] GetForExtractionAndReset();
-  }
-
-  // Clear the underlying pointer and return another raw_ptr instance
-  // that is allowed to dangle.
-  // This can be useful in cases such as:
-  // ```
-  //  ptr.ExtractAsDangling()->SelfDestroy();
-  // ```
-  // ```
-  //  c_style_api_do_something_and_destroy(ptr.ExtractAsDangling());
-  // ```
-  // 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,
-                      DanglingRawPtr>) {
-      DanglingRawPtr res(std::move(*this));
-      // Not all implementation clear the source pointer on move, so do it
-      // here just in case. Should be cheap.
-      operator=(nullptr);
-      return res;
-    } else {
-      T* ptr = GetForExtraction();
-      DanglingRawPtr res(ptr);
-      operator=(nullptr);
-      return res;
-    }
-  }
-
-  // Comparison operators between raw_ptr and raw_ptr<U>/U*/std::nullptr_t.
-  // Strictly speaking, it is not necessary to provide these: the compiler can
-  // use the conversion operator implicitly to allow comparisons to fall back to
-  // comparisons between raw pointers. However, `operator T*`/`operator U*` may
-  // perform safety checks with a higher runtime cost, so to avoid this, provide
-  // explicit comparison operators for all combinations of parameters.
-
-  // Comparisons between `raw_ptr`s. This unusual declaration and separate
-  // definition below is because `GetForComparison()` is a private method. The
-  // more conventional approach of defining a comparison operator between
-  // `raw_ptr` and `raw_ptr<U>` in the friend declaration itself does not work,
-  // because a comparison operator defined inline would not be allowed to call
-  // `raw_ptr<U>`'s private `GetForComparison()` method.
-  template <typename U, typename V, typename I>
-  friend ALWAYS_INLINE bool operator==(const raw_ptr<U, I>& lhs,
-                                       const raw_ptr<V, I>& rhs);
-  template <typename U>
-  friend ALWAYS_INLINE bool operator!=(const raw_ptr& lhs,
-                                       const raw_ptr<U, Impl>& rhs) {
-    return !(lhs == rhs);
-  }
-  template <typename U, typename V, typename I>
-  friend ALWAYS_INLINE bool operator<(const raw_ptr<U, I>& lhs,
-                                      const raw_ptr<V, I>& rhs);
-  template <typename U, typename V, typename I>
-  friend ALWAYS_INLINE bool operator>(const raw_ptr<U, I>& lhs,
-                                      const raw_ptr<V, I>& rhs);
-  template <typename U, typename V, typename I>
-  friend ALWAYS_INLINE bool operator<=(const raw_ptr<U, I>& lhs,
-                                       const raw_ptr<V, I>& rhs);
-  template <typename U, typename V, typename I>
-  friend ALWAYS_INLINE bool operator>=(const raw_ptr<U, I>& lhs,
-                                       const raw_ptr<V, I>& rhs);
-
-  // Comparisons with U*. These operators also handle the case where the RHS is
-  // T*.
-  template <typename U>
-  friend ALWAYS_INLINE bool operator==(const raw_ptr& lhs, U* rhs) {
-    return lhs.GetForComparison() == rhs;
-  }
-  template <typename U>
-  friend ALWAYS_INLINE bool operator!=(const raw_ptr& lhs, U* rhs) {
-    return !(lhs == rhs);
-  }
-  template <typename U>
-  friend ALWAYS_INLINE bool operator==(U* lhs, const raw_ptr& rhs) {
-    return rhs == lhs;  // Reverse order to call the operator above.
-  }
-  template <typename U>
-  friend ALWAYS_INLINE bool operator!=(U* lhs, const raw_ptr& rhs) {
-    return rhs != lhs;  // Reverse order to call the operator above.
-  }
-  template <typename U>
-  friend ALWAYS_INLINE bool operator<(const raw_ptr& lhs, U* rhs) {
-    return lhs.GetForComparison() < rhs;
-  }
-  template <typename U>
-  friend ALWAYS_INLINE bool operator<=(const raw_ptr& lhs, U* rhs) {
-    return lhs.GetForComparison() <= rhs;
-  }
-  template <typename U>
-  friend ALWAYS_INLINE bool operator>(const raw_ptr& lhs, U* rhs) {
-    return lhs.GetForComparison() > rhs;
-  }
-  template <typename U>
-  friend ALWAYS_INLINE bool operator>=(const raw_ptr& lhs, U* rhs) {
-    return lhs.GetForComparison() >= rhs;
-  }
-  template <typename U>
-  friend ALWAYS_INLINE bool operator<(U* lhs, const raw_ptr& rhs) {
-    return lhs < rhs.GetForComparison();
-  }
-  template <typename U>
-  friend ALWAYS_INLINE bool operator<=(U* lhs, const raw_ptr& rhs) {
-    return lhs <= rhs.GetForComparison();
-  }
-  template <typename U>
-  friend ALWAYS_INLINE bool operator>(U* lhs, const raw_ptr& rhs) {
-    return lhs > rhs.GetForComparison();
-  }
-  template <typename U>
-  friend ALWAYS_INLINE bool operator>=(U* lhs, const raw_ptr& rhs) {
-    return lhs >= rhs.GetForComparison();
-  }
-
-  // Comparisons with `std::nullptr_t`.
-  friend ALWAYS_INLINE bool operator==(const raw_ptr& lhs, std::nullptr_t) {
-    return !lhs;
-  }
-  friend ALWAYS_INLINE bool operator!=(const raw_ptr& lhs, std::nullptr_t) {
-    return !!lhs;  // Use !! otherwise the costly implicit cast will be used.
-  }
-  friend ALWAYS_INLINE bool operator==(std::nullptr_t, const raw_ptr& rhs) {
-    return !rhs;
-  }
-  friend ALWAYS_INLINE bool operator!=(std::nullptr_t, const raw_ptr& rhs) {
-    return !!rhs;  // Use !! otherwise the costly implicit cast will be used.
-  }
-
-  friend ALWAYS_INLINE void swap(raw_ptr& lhs, raw_ptr& rhs) noexcept {
-    Impl::IncrementSwapCountForTest();
-    std::swap(lhs.wrapped_ptr_, rhs.wrapped_ptr_);
-  }
-
-  // If T can be serialised into trace, its alias is also
-  // serialisable.
-  template <class U = T>
-  typename perfetto::check_traced_value_support<U>::type WriteIntoTrace(
-      perfetto::TracedValue&& context) const {
-    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),
-  // because it knows that the caller will crash on nullptr.
-  ALWAYS_INLINE T* GetForDereference() const {
-    return Impl::SafelyUnwrapPtrForDereference(wrapped_ptr_);
-  }
-  // This getter is meant for situations where the raw pointer is meant to be
-  // extracted outside of this class, but not necessarily with an intention to
-  // dereference. It mustn't crash on nullptr.
-  ALWAYS_INLINE T* GetForExtraction() const {
-    return Impl::SafelyUnwrapPtrForExtraction(wrapped_ptr_);
-  }
-  // This getter is meant *only* for situations where the pointer is meant to be
-  // compared (guaranteeing no dereference or extraction outside of this class).
-  // Any verifications can and should be skipped for performance reasons.
-  ALWAYS_INLINE T* GetForComparison() const {
-    return Impl::UnsafelyUnwrapPtrForComparison(wrapped_ptr_);
-  }
-
-  ALWAYS_INLINE T* GetForExtractionAndReset() {
-    T* ptr = GetForExtraction();
-    operator=(nullptr);
-    return ptr;
-  }
-
-  T* wrapped_ptr_;
-
-  template <typename U, typename V>
-  friend class raw_ptr;
-};
-
-template <typename U, typename V, typename I>
-ALWAYS_INLINE bool operator==(const raw_ptr<U, I>& lhs,
-                              const raw_ptr<V, I>& rhs) {
-  return lhs.GetForComparison() == rhs.GetForComparison();
-}
-
-template <typename U, typename V, typename I>
-ALWAYS_INLINE bool operator<(const raw_ptr<U, I>& lhs,
-                             const raw_ptr<V, I>& rhs) {
-  return lhs.GetForComparison() < rhs.GetForComparison();
-}
-
-template <typename U, typename V, typename I>
-ALWAYS_INLINE bool operator>(const raw_ptr<U, I>& lhs,
-                             const raw_ptr<V, I>& rhs) {
-  return lhs.GetForComparison() > rhs.GetForComparison();
-}
-
-template <typename U, typename V, typename I>
-ALWAYS_INLINE bool operator<=(const raw_ptr<U, I>& lhs,
-                              const raw_ptr<V, I>& rhs) {
-  return lhs.GetForComparison() <= rhs.GetForComparison();
-}
-
-template <typename U, typename V, typename I>
-ALWAYS_INLINE bool operator>=(const raw_ptr<U, I>& lhs,
-                              const raw_ptr<V, I>& rhs) {
-  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 {};
-
-template <typename T>
-struct IsPointer<T*> : std::true_type {};
-
-template <typename T, typename I>
-struct IsPointer<raw_ptr<T, I>> : std::true_type {};
-
-template <typename T>
-inline constexpr bool IsPointerV = IsPointer<T>::value;
-
-template <typename T>
-struct RemovePointer {
-  using type = T;
-};
-
-template <typename T>
-struct RemovePointer<T*> {
-  using type = T;
-};
-
-template <typename T, typename I>
-struct RemovePointer<raw_ptr<T, I>> {
-  using type = T;
-};
-
-template <typename T>
-using RemovePointerT = typename RemovePointer<T>::type;
-
-}  // namespace base
-
-using gurl_base::raw_ptr;
-
-// DisableDanglingPtrDetection option for raw_ptr annotates
-// "intentional-and-safe" dangling pointers. It is meant to be used at the
-// margin, only if there is no better way to re-architecture the code.
-//
-// Usage:
-// raw_ptr<T, DisableDanglingPtrDetection> dangling_ptr;
-//
-// When using it, please provide a justification about what guarantees it will
-// never be dereferenced after becoming dangling.
-using DisableDanglingPtrDetection = gurl_base::RawPtrMayDangle;
-
-// 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://crbug.com/1291138.
-using DanglingUntriaged = DisableDanglingPtrDetection;
-
-// The following template parameters are only meaningful when `raw_ptr`
-// is `MTECheckedPtr` (never the case unless a particular GN arg is set
-// true.) `raw_ptr` users need not worry about this and can refer solely
-// to `DisableDanglingPtrDetection` and `DanglingUntriaged` above.
-//
-// The `raw_ptr` definition allows users to specify an implementation.
-// 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_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-
-// Direct pass-through to no-op implementation.
-using DegradeToNoOpWhenMTE = gurl_base::internal::RawPtrNoOpImpl;
-
-// As above, but with the "untriaged dangling" annotation.
-using DanglingUntriagedDegradeToNoOpWhenMTE = gurl_base::internal::RawPtrNoOpImpl;
-
-// As above, but with the "explicitly disable protection" annotation.
-using DisableDanglingPtrDetectionDegradeToNoOpWhenMTE =
-    gurl_base::internal::RawPtrNoOpImpl;
-
-#else
-
-// Direct pass-through to default implementation specified by `raw_ptr`
-// template.
-using DegradeToNoOpWhenMTE = gurl_base::RawPtrBanDanglingIfSupported;
-
-// Direct pass-through to `DanglingUntriaged`.
-using DanglingUntriagedDegradeToNoOpWhenMTE = DanglingUntriaged;
-
-// Direct pass-through to `DisableDanglingPtrDetection`.
-using DisableDanglingPtrDetectionDegradeToNoOpWhenMTE =
-    DisableDanglingPtrDetection;
-
-#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 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, RawPtrType>& lhs,
-                  const raw_ptr<T, RawPtrType>& rhs) const {
-    Impl::IncrementLessCountForTest();
-    return lhs < rhs;
-  }
-
-  bool operator()(T* lhs, const raw_ptr<T, RawPtrType>& rhs) const {
-    Impl::IncrementLessCountForTest();
-    return lhs < rhs;
-  }
-
-  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 f881c04..2a30e26 100644
--- a/base/memory/raw_ptr_exclusion.h
+++ b/base/memory/raw_ptr_exclusion.h
@@ -6,8 +6,10 @@
 #define BASE_MEMORY_RAW_PTR_EXCLUSION_H_
 
 #include "polyfills/base/allocator/buildflags.h"
+#include "base/compiler_specific.h"
 #include "build/build_config.h"
 
+#if HAS_ATTRIBUTE(annotate)
 #if defined(OFFICIAL_BUILD) && !BUILDFLAG(FORCE_ENABLE_RAW_PTR_EXCLUSION)
 // The annotation changed compiler output and increased binary size so disable
 // for official builds.
@@ -18,5 +20,8 @@
 // Example: RAW_PTR_EXCLUSION Foo* foo_;
 #define RAW_PTR_EXCLUSION __attribute__((annotate("raw_ptr_exclusion")))
 #endif
+#else
+#define RAW_PTR_EXCLUSION
+#endif
 
 #endif  // BASE_MEMORY_RAW_PTR_EXCLUSION_H_
diff --git a/base/no_destructor.h b/base/no_destructor.h
index b183e4f..d2bb766 100644
--- a/base/no_destructor.h
+++ b/base/no_destructor.h
@@ -10,28 +10,50 @@
 #include <utility>
 
 namespace gurl_base {
-// A tag type used for NoDestructor to allow it to be created for a type that
-// has a trivial destructor. Use for cases where the same class might have
-// different implementations that vary on destructor triviality or when the
-// LSan hiding properties of NoDestructor are needed.
-struct AllowForTriviallyDestructibleType;
 
-// A wrapper that makes it easy to create an object of type T with static
-// storage duration that:
-// - is only constructed on first access
-// - never invokes the destructor
-// in order to satisfy the styleguide ban on global constructors and
-// destructors.
+// Helper type to create a function-local static variable of type `T` when `T`
+// has a non-trivial destructor. Storing a `T` in a `gurl_base::NoDestructor<T>` will
+// prevent `~T()` from running, even when the variable goes out of scope.
 //
-// Runtime constant example:
-// const std::string& GetLineSeparator() {
-//  // Forwards to std::string(size_t, char, const Allocator&) constructor.
-//   static const gurl_base::NoDestructor<std::string> s(5, '-');
+// Useful when a variable has static storage duration but its type has a
+// non-trivial destructor. Chromium bans global constructors and destructors:
+// using a function-local static variable prevents the former, while using
+// `gurl_base::NoDestructor<T>` prevents the latter.
+//
+// ## Caveats
+//
+// - Must only be used as a function-local static variable. Declaring a global
+//   variable of type `gurl_base::NoDestructor<T>` will still generate a global
+//   constructor; declaring a local or member variable will lead to memory leaks
+//   or other surprising and undesirable behaviour.
+//
+// - If the data is rarely used, consider creating it on demand rather than
+//   caching it for the lifetime of the program. Though `gurl_base::NoDestructor<T>`
+//   does not heap allocate, the compiler still reserves space in bss for
+//   storing `T`, which costs memory at runtime.
+//
+// - If `T` is trivially destructible, do not use `gurl_base::NoDestructor<T>`:
+//
+//     const uint64_t GetUnstableSessionSeed() {
+//       // No need to use `gurl_base::NoDestructor<T>` as `uint64_t` is trivially
+//       // destructible and does not require a global destructor.
+//       static const uint64_t kSessionSeed = gurl_base::RandUint64();
+//       return kSessionSeed;
+//     }
+//
+// ## Example Usage
+//
+// const std::string& GetDefaultText() {
+//   // Required since `static const std::string` requires a global destructor.
+//   static const gurl_base::NoDestructor<std::string> s("Hello world!");
 //   return *s;
 // }
 //
-// More complex initialization with a lambda:
-// const std::string& GetSessionNonce() {
+// More complex initialization using a lambda:
+//
+// const std::string& GetRandomNonce() {
+//   // `nonce` is initialized with random data the first time this function is
+//   // called, but its value is fixed thereafter.
 //   static const gurl_base::NoDestructor<std::string> nonce([] {
 //     std::string s(16);
 //     crypto::RandString(s.data(), s.size());
@@ -40,29 +62,24 @@
 //   return *nonce;
 // }
 //
-// NoDestructor<T> stores the object inline, so it also avoids a pointer
-// indirection and a malloc. Also note that since C++11 static local variable
-// initialization is thread-safe and so is this pattern. Code should prefer to
-// use NoDestructor<T> over:
-// - A function scoped static T* or T& that is dynamically initialized.
-// - A global gurl_base::LazyInstance<T>.
+// ## Thread safety
 //
-// Note that since the destructor is never run, this *will* leak memory if used
-// as a stack or member variable. Furthermore, a NoDestructor<T> should never
-// have global scope as that may require a static initializer.
-template <typename T, typename O = std::nullptr_t>
+// Initialisation of function-local static variables is thread-safe since C++11.
+// The standard guarantees that:
+//
+// - function-local static variables will be initialised the first time
+//   execution passes through the declaration.
+//
+// - if another thread's execution concurrently passes through the declaration
+//   in the middle of initialisation, that thread will wait for the in-progress
+//   initialisation to complete.
+template <typename T>
 class NoDestructor {
  public:
   static_assert(
-      !std::is_trivially_destructible<T>::value ||
-          std::is_same<O, AllowForTriviallyDestructibleType>::value,
-      "gurl_base::NoDestructor is not needed because the templated class has a "
-      "trivial destructor");
-
-  static_assert(std::is_same<O, AllowForTriviallyDestructibleType>::value ||
-                    std::is_same<O, std::nullptr_t>::value,
-                "AllowForTriviallyDestructibleType is the only valid option "
-                "for the second template parameter of NoDestructor");
+      !std::is_trivially_destructible_v<T>,
+      "T is trivially destructible; please use a function-local static "
+      "of type T directly instead");
 
   // Not constexpr; just write static constexpr T x = ...; if the value should
   // be a constexpr.
diff --git a/base/stl_util.h b/base/stl_util.h
index 74ce611..2511412 100644
--- a/base/stl_util.h
+++ b/base/stl_util.h
@@ -26,17 +26,6 @@
 
 }  // namespace internal
 
-// Implementation of C++23's std::to_underlying.
-//
-// Note: This has an additional `std::is_enum<EnumT>` requirement to be SFINAE
-// friendly prior to C++20.
-//
-// Reference: https://en.cppreference.com/w/cpp/utility/to_underlying
-template <typename EnumT, typename = std::enable_if_t<std::is_enum<EnumT>{}>>
-constexpr std::underlying_type_t<EnumT> to_underlying(EnumT e) noexcept {
-  return static_cast<std::underlying_type_t<EnumT>>(e);
-}
-
 // Returns a const reference to the underlying container of a container adapter.
 // Works for std::priority_queue, std::queue, and std::stack.
 template <class A>
@@ -59,14 +48,6 @@
   obj->reserve(0);
 }
 
-// Counts the number of instances of val in a container.
-template <typename Container, typename T>
-typename std::iterator_traits<
-    typename Container::const_iterator>::difference_type
-STLCount(const Container& container, const T& val) {
-  return std::count(container.begin(), container.end(), val);
-}
-
 // O(1) implementation of const casting an iterator for any sequence,
 // associative or unordered associative container in the STL.
 //
diff --git a/base/strings/escape.cc b/base/strings/escape.cc
index 96657a3..d855c1c 100644
--- a/base/strings/escape.cc
+++ b/base/strings/escape.cc
@@ -49,7 +49,7 @@
                    bool keep_escaped = false) {
   std::string escaped;
   escaped.reserve(text.length() * 3);
-  for (unsigned int i = 0; i < text.length(); ++i) {
+  for (size_t i = 0; i < text.length(); ++i) {
     unsigned char c = static_cast<unsigned char>(text[i]);
     if (use_plus && ' ' == c) {
       escaped.push_back('+');
diff --git a/base/strings/safe_sprintf.cc b/base/strings/safe_sprintf.cc
index 5071377..0b53dff 100644
--- a/base/strings/safe_sprintf.cc
+++ b/base/strings/safe_sprintf.cc
@@ -10,7 +10,7 @@
 #include <algorithm>
 #include <limits>
 
-#include "base/memory/raw_ptr.h"
+#include "polyfills/base/memory/raw_ptr.h"
 #include "build/build_config.h"
 
 #if !defined(NDEBUG)
diff --git a/base/strings/safe_sprintf_unittest.cc b/base/strings/safe_sprintf_unittest.cc
index bdcc2ff..76d72b2 100644
--- a/base/strings/safe_sprintf_unittest.cc
+++ b/base/strings/safe_sprintf_unittest.cc
@@ -12,6 +12,7 @@
 #include <limits>
 #include <memory>
 
+
 #include "polyfills/base/check_op.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -482,7 +483,14 @@
 
 }  // anonymous namespace
 
-TEST(SafeSPrintfTest, Truncation) {
+// TODO(crbug.com/1369007): Fails when OOB protection is turned on.
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \
+    BUILDFLAG(ENABLE_MTE_CHECKED_PTR_SUPPORT)
+#define MAYBE_Truncation DISABLED_Truncation
+#else
+#define MAYBE_Truncation Truncation
+#endif
+TEST(SafeSPrintfTest, MAYBE_Truncation) {
   // We use PrintLongString() to print a complex long string and then
   // truncate to all possible lengths. This ends up exercising a lot of
   // different code paths in SafeSPrintf() and IToASCII(), as truncation can
diff --git a/base/strings/string_number_conversions_fuzzer.cc b/base/strings/string_number_conversions_fuzzer.cc
deleted file mode 100644
index cea3d3c..0000000
--- a/base/strings/string_number_conversions_fuzzer.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// 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.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/strings/string_number_conversions.h"
-
-template <class NumberType, class StringPieceType, class StringType>
-void CheckRoundtripsT(const uint8_t* data,
-                      const size_t size,
-                      StringType (*num_to_string)(NumberType),
-                      bool (*string_to_num)(StringPieceType, NumberType*)) {
-  // Ensure we can read a NumberType from |data|
-  if (size < sizeof(NumberType))
-    return;
-  const NumberType v1 = *reinterpret_cast<const NumberType*>(data);
-
-  // Because we started with an arbitrary NumberType value, not an arbitrary
-  // string, we expect that the function |string_to_num| (e.g. StringToInt) will
-  // return true, indicating a perfect conversion.
-  NumberType v2;
-  GURL_CHECK(string_to_num(num_to_string(v1), &v2));
-
-  // Given that this was a perfect conversion, we expect the original NumberType
-  // value to equal the newly parsed one.
-  GURL_CHECK_EQ(v1, v2);
-}
-
-template <class NumberType>
-void CheckRoundtrips(const uint8_t* data,
-                     const size_t size,
-                     bool (*string_to_num)(gurl_base::StringPiece, NumberType*)) {
-  return CheckRoundtripsT<NumberType, gurl_base::StringPiece, std::string>(
-      data, size, &gurl_base::NumberToString, string_to_num);
-}
-
-template <class NumberType>
-void CheckRoundtrips16(const uint8_t* data,
-                       const size_t size,
-                       bool (*string_to_num)(gurl_base::StringPiece16,
-                                             NumberType*)) {
-  return CheckRoundtripsT<NumberType, gurl_base::StringPiece16, std::u16string>(
-      data, size, &gurl_base::NumberToString16, string_to_num);
-}
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  // For each instantiation of NumberToString f and its corresponding StringTo*
-  // function g, check that f(g(x)) = x holds for fuzzer-determined values of x.
-  CheckRoundtrips<int>(data, size, &gurl_base::StringToInt);
-  CheckRoundtrips16<int>(data, size, &gurl_base::StringToInt);
-  CheckRoundtrips<unsigned int>(data, size, &gurl_base::StringToUint);
-  CheckRoundtrips16<unsigned int>(data, size, &gurl_base::StringToUint);
-  CheckRoundtrips<int64_t>(data, size, &gurl_base::StringToInt64);
-  CheckRoundtrips16<int64_t>(data, size, &gurl_base::StringToInt64);
-  CheckRoundtrips<uint64_t>(data, size, &gurl_base::StringToUint64);
-  CheckRoundtrips16<uint64_t>(data, size, &gurl_base::StringToUint64);
-  CheckRoundtrips<size_t>(data, size, &gurl_base::StringToSizeT);
-  CheckRoundtrips16<size_t>(data, size, &gurl_base::StringToSizeT);
-
-  gurl_base::StringPiece string_piece_input(reinterpret_cast<const char*>(data),
-                                       size);
-  std::string string_input(reinterpret_cast<const char*>(data), size);
-
-  int out_int;
-  gurl_base::StringToInt(string_piece_input, &out_int);
-  unsigned out_uint;
-  gurl_base::StringToUint(string_piece_input, &out_uint);
-  int64_t out_int64;
-  gurl_base::StringToInt64(string_piece_input, &out_int64);
-  uint64_t out_uint64;
-  gurl_base::StringToUint64(string_piece_input, &out_uint64);
-  size_t out_size;
-  gurl_base::StringToSizeT(string_piece_input, &out_size);
-
-  // Test for StringPiece16 if size is even.
-  if (size % 2 == 0) {
-    gurl_base::StringPiece16 string_piece_input16(
-        reinterpret_cast<const char16_t*>(data), size / 2);
-
-    gurl_base::StringToInt(string_piece_input16, &out_int);
-    gurl_base::StringToUint(string_piece_input16, &out_uint);
-    gurl_base::StringToInt64(string_piece_input16, &out_int64);
-    gurl_base::StringToUint64(string_piece_input16, &out_uint64);
-    gurl_base::StringToSizeT(string_piece_input16, &out_size);
-  }
-
-  double out_double;
-  gurl_base::StringToDouble(string_input, &out_double);
-
-  gurl_base::HexStringToInt(string_piece_input, &out_int);
-  gurl_base::HexStringToUInt(string_piece_input, &out_uint);
-  gurl_base::HexStringToInt64(string_piece_input, &out_int64);
-  gurl_base::HexStringToUInt64(string_piece_input, &out_uint64);
-  std::vector<uint8_t> out_bytes;
-  gurl_base::HexStringToBytes(string_piece_input, &out_bytes);
-
-  gurl_base::HexEncode(data, size);
-
-  // Convert the numbers back to strings.
-  gurl_base::NumberToString(out_int);
-  gurl_base::NumberToString16(out_int);
-  gurl_base::NumberToString(out_uint);
-  gurl_base::NumberToString16(out_uint);
-  gurl_base::NumberToString(out_int64);
-  gurl_base::NumberToString16(out_int64);
-  gurl_base::NumberToString(out_uint64);
-  gurl_base::NumberToString16(out_uint64);
-  gurl_base::NumberToString(out_double);
-  gurl_base::NumberToString16(out_double);
-
-  return 0;
-}
diff --git a/base/strings/string_tokenizer_fuzzer.cc b/base/strings/string_tokenizer_fuzzer.cc
deleted file mode 100644
index a0c0788..0000000
--- a/base/strings/string_tokenizer_fuzzer.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-#include <tuple>
-
-#include "base/strings/string_tokenizer.h"
-
-void GetAllTokens(gurl_base::StringTokenizer& t) {
-  while (t.GetNext()) {
-    std::ignore = t.token();
-  }
-}
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  uint8_t size_t_bytes = sizeof(size_t);
-  if (size < size_t_bytes + 1) {
-    return 0;
-  }
-
-  // Calculate pattern size based on remaining bytes, otherwise fuzzing is
-  // inefficient with bailouts in most cases.
-  size_t pattern_size =
-      *reinterpret_cast<const size_t*>(data) % (size - size_t_bytes);
-
-  std::string pattern(reinterpret_cast<const char*>(data + size_t_bytes),
-                      pattern_size);
-  std::string input(
-      reinterpret_cast<const char*>(data + size_t_bytes + pattern_size),
-      size - pattern_size - size_t_bytes);
-
-  // Allow quote_chars and options to be set. Otherwise full coverage
-  // won't be possible since IsQuote, FullGetNext and other functions
-  // won't be called.
-  for (bool return_delims : {false, true}) {
-    for (bool return_empty_strings : {false, true}) {
-      int options = 0;
-      if (return_delims)
-        options |= gurl_base::StringTokenizer::RETURN_DELIMS;
-      if (return_empty_strings)
-        options |= gurl_base::StringTokenizer::RETURN_EMPTY_TOKENS;
-
-      gurl_base::StringTokenizer t(input, pattern);
-      t.set_options(options);
-      GetAllTokens(t);
-
-      gurl_base::StringTokenizer t_quote(input, pattern);
-      t_quote.set_quote_chars("\"");
-      t_quote.set_options(options);
-      GetAllTokens(t_quote);
-    }
-  }
-
-  return 0;
-}
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc
index 482bb6e..f92029f 100644
--- a/base/strings/string_util.cc
+++ b/base/strings/string_util.cc
@@ -16,13 +16,14 @@
 #include <wchar.h>
 #include <wctype.h>
 
-#include <algorithm>
 #include <limits>
 #include <type_traits>
 #include <vector>
 
 #include "polyfills/base/check_op.h"
 #include "base/no_destructor.h"
+#include "base/ranges/algorithm.h"
+#include "base/strings/string_util_impl_helpers.h"
 #include "base/strings/string_util_internal.h"
 #include "base/strings/utf_string_conversion_utils.h"
 #include "base/strings/utf_string_conversions.h"
@@ -82,14 +83,6 @@
   return internal::ToUpperASCIIImpl(str);
 }
 
-int CompareCaseInsensitiveASCII(StringPiece a, StringPiece b) {
-  return internal::CompareCaseInsensitiveASCIIT(a, b);
-}
-
-int CompareCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b) {
-  return internal::CompareCaseInsensitiveASCIIT(a, b);
-}
-
 const std::string& EmptyString() {
   static const gurl_base::NoDestructor<std::string> s;
   return *s;
@@ -256,7 +249,7 @@
 }
 
 bool EqualsASCII(StringPiece16 str, StringPiece ascii) {
-  return std::equal(ascii.begin(), ascii.end(), str.begin(), str.end());
+  return ranges::equal(ascii, str);
 }
 
 bool StartsWith(StringPiece str,
diff --git a/base/strings/string_util.h b/base/strings/string_util.h
index 56cf483..b7bee67 100644
--- a/base/strings/string_util.h
+++ b/base/strings/string_util.h
@@ -12,7 +12,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include <algorithm>
 #include <initializer_list>
 #include <sstream>
 #include <string>
@@ -25,6 +24,7 @@
 #include "base/containers/span.h"
 #include "base/cxx20_to_address.h"
 #include "base/strings/string_piece.h"  // For implicit conversions.
+#include "base/strings/string_util_internal.h"
 #include "build/build_config.h"
 
 namespace gurl_base {
@@ -123,8 +123,8 @@
 // so we don't want to use it here.
 template <typename CharT,
           typename = std::enable_if_t<std::is_integral<CharT>::value>>
-CharT ToLowerASCII(CharT c) {
-  return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
+constexpr CharT ToLowerASCII(CharT c) {
+  return internal::ToLowerASCII(c);
 }
 
 // ASCII-specific toupper.  The standard library's toupper is locale sensitive,
@@ -165,19 +165,14 @@
 // (unlike strcasecmp which can return values greater or less than 1/-1). For
 // full Unicode support, use gurl_base::i18n::ToLower or gurl_base::i18n::FoldCase
 // and then just call the normal string operators on the result.
-BASE_EXPORT int CompareCaseInsensitiveASCII(StringPiece a, StringPiece b);
-BASE_EXPORT int CompareCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b);
-
-namespace internal {
-template <typename CharT, typename CharU>
-inline bool EqualsCaseInsensitiveASCIIT(BasicStringPiece<CharT> a,
-                                        BasicStringPiece<CharU> b) {
-  return std::equal(a.begin(), a.end(), b.begin(), b.end(),
-                    [](auto lhs, auto rhs) {
-                      return ToLowerASCII(lhs) == ToLowerASCII(rhs);
-                    });
+BASE_EXPORT constexpr int CompareCaseInsensitiveASCII(StringPiece a,
+                                                      StringPiece b) {
+  return internal::CompareCaseInsensitiveASCIIT(a, b);
 }
-}  // namespace internal
+BASE_EXPORT constexpr int CompareCaseInsensitiveASCII(StringPiece16 a,
+                                                      StringPiece16 b) {
+  return internal::CompareCaseInsensitiveASCIIT(a, b);
+}
 
 // Equality for ASCII case-insensitive comparisons. For full Unicode support,
 // use gurl_base::i18n::ToLower or gurl_base::i18n::FoldCase and then compare with either
diff --git a/base/strings/string_util_impl_helpers.h b/base/strings/string_util_impl_helpers.h
new file mode 100644
index 0000000..970a912
--- /dev/null
+++ b/base/strings/string_util_impl_helpers.h
@@ -0,0 +1,582 @@
+// 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.
+
+#ifndef BASE_STRINGS_STRING_UTIL_IMPL_HELPERS_H_
+#define BASE_STRINGS_STRING_UTIL_IMPL_HELPERS_H_
+
+#include <algorithm>
+
+#include "polyfills/base/check.h"
+#include "polyfills/base/check_op.h"
+#include "polyfills/base/logging.h"
+#include "polyfills/base/notreached.h"
+#include "base/ranges/algorithm.h"
+#include "base/strings/string_piece.h"
+#include "base/third_party/icu/icu_utf.h"
+
+namespace gurl_base::internal {
+
+// Used by ReplaceStringPlaceholders to track the position in the string of
+// replaced parameters.
+struct ReplacementOffset {
+  ReplacementOffset(uintptr_t parameter, size_t offset)
+      : parameter(parameter), offset(offset) {}
+
+  // Index of the parameter.
+  size_t parameter;
+
+  // Starting position in the string.
+  size_t offset;
+};
+
+static bool CompareParameter(const ReplacementOffset& elem1,
+                             const ReplacementOffset& elem2) {
+  return elem1.parameter < elem2.parameter;
+}
+
+// Assuming that a pointer is the size of a "machine word", then
+// uintptr_t is an integer type that is also a machine word.
+using MachineWord = uintptr_t;
+
+inline bool IsMachineWordAligned(const void* pointer) {
+  return !(reinterpret_cast<MachineWord>(pointer) & (sizeof(MachineWord) - 1));
+}
+
+template <typename T, typename CharT = typename T::value_type>
+std::basic_string<CharT> ToLowerASCIIImpl(T str) {
+  std::basic_string<CharT> ret;
+  ret.reserve(str.size());
+  for (size_t i = 0; i < str.size(); i++)
+    ret.push_back(ToLowerASCII(str[i]));
+  return ret;
+}
+
+template <typename T, typename CharT = typename T::value_type>
+std::basic_string<CharT> ToUpperASCIIImpl(T str) {
+  std::basic_string<CharT> ret;
+  ret.reserve(str.size());
+  for (size_t i = 0; i < str.size(); i++)
+    ret.push_back(ToUpperASCII(str[i]));
+  return ret;
+}
+
+template <typename T, typename CharT = typename T::value_type>
+TrimPositions TrimStringT(T input,
+                          T trim_chars,
+                          TrimPositions positions,
+                          std::basic_string<CharT>* output) {
+  // Find the edges of leading/trailing whitespace as desired. Need to use
+  // a StringPiece version of input to be able to call find* on it with the
+  // StringPiece version of trim_chars (normally the trim_chars will be a
+  // constant so avoid making a copy).
+  const size_t last_char = input.length() - 1;
+  const size_t first_good_char =
+      (positions & TRIM_LEADING) ? input.find_first_not_of(trim_chars) : 0;
+  const size_t last_good_char = (positions & TRIM_TRAILING)
+                                    ? input.find_last_not_of(trim_chars)
+                                    : last_char;
+
+  // When the string was all trimmed, report that we stripped off characters
+  // from whichever position the caller was interested in. For empty input, we
+  // stripped no characters, but we still need to clear |output|.
+  if (input.empty() || first_good_char == std::basic_string<CharT>::npos ||
+      last_good_char == std::basic_string<CharT>::npos) {
+    bool input_was_empty = input.empty();  // in case output == &input
+    output->clear();
+    return input_was_empty ? TRIM_NONE : positions;
+  }
+
+  // Trim.
+  output->assign(input.data() + first_good_char,
+                 last_good_char - first_good_char + 1);
+
+  // Return where we trimmed from.
+  return static_cast<TrimPositions>(
+      (first_good_char == 0 ? TRIM_NONE : TRIM_LEADING) |
+      (last_good_char == last_char ? TRIM_NONE : TRIM_TRAILING));
+}
+
+template <typename T, typename CharT = typename T::value_type>
+T TrimStringPieceT(T input, T trim_chars, TrimPositions positions) {
+  size_t begin =
+      (positions & TRIM_LEADING) ? input.find_first_not_of(trim_chars) : 0;
+  size_t end = (positions & TRIM_TRAILING)
+                   ? input.find_last_not_of(trim_chars) + 1
+                   : input.size();
+  return input.substr(std::min(begin, input.size()), end - begin);
+}
+
+template <typename T, typename CharT = typename T::value_type>
+std::basic_string<CharT> CollapseWhitespaceT(
+    T text,
+    bool trim_sequences_with_line_breaks) {
+  std::basic_string<CharT> result;
+  result.resize(text.size());
+
+  // Set flags to pretend we're already in a trimmed whitespace sequence, so we
+  // will trim any leading whitespace.
+  bool in_whitespace = true;
+  bool already_trimmed = true;
+
+  size_t chars_written = 0;
+  for (auto c : text) {
+    if (IsWhitespace(c)) {
+      if (!in_whitespace) {
+        // Reduce all whitespace sequences to a single space.
+        in_whitespace = true;
+        result[chars_written++] = L' ';
+      }
+      if (trim_sequences_with_line_breaks && !already_trimmed &&
+          ((c == '\n') || (c == '\r'))) {
+        // Whitespace sequences containing CR or LF are eliminated entirely.
+        already_trimmed = true;
+        --chars_written;
+      }
+    } else {
+      // Non-whitespace characters are copied straight across.
+      in_whitespace = false;
+      already_trimmed = false;
+      result[chars_written++] = c;
+    }
+  }
+
+  if (in_whitespace && !already_trimmed) {
+    // Any trailing whitespace is eliminated.
+    --chars_written;
+  }
+
+  result.resize(chars_written);
+  return result;
+}
+
+template <class Char>
+bool DoIsStringASCII(const Char* characters, size_t length) {
+  // Bitmasks to detect non ASCII characters for character sizes of 8, 16 and 32
+  // bits.
+  constexpr MachineWord NonASCIIMasks[] = {
+      0, MachineWord(0x8080808080808080ULL), MachineWord(0xFF80FF80FF80FF80ULL),
+      0, MachineWord(0xFFFFFF80FFFFFF80ULL),
+  };
+
+  if (!length)
+    return true;
+  constexpr MachineWord non_ascii_bit_mask = NonASCIIMasks[sizeof(Char)];
+  static_assert(non_ascii_bit_mask, "Error: Invalid Mask");
+  MachineWord all_char_bits = 0;
+  const Char* end = characters + length;
+
+  // Prologue: align the input.
+  while (!IsMachineWordAligned(characters) && characters < end)
+    all_char_bits |= static_cast<MachineWord>(*characters++);
+  if (all_char_bits & non_ascii_bit_mask)
+    return false;
+
+  // Compare the values of CPU word size.
+  constexpr size_t chars_per_word = sizeof(MachineWord) / sizeof(Char);
+  constexpr int batch_count = 16;
+  while (characters <= end - batch_count * chars_per_word) {
+    all_char_bits = 0;
+    for (int i = 0; i < batch_count; ++i) {
+      all_char_bits |= *(reinterpret_cast<const MachineWord*>(characters));
+      characters += chars_per_word;
+    }
+    if (all_char_bits & non_ascii_bit_mask)
+      return false;
+  }
+
+  // Process the remaining words.
+  all_char_bits = 0;
+  while (characters <= end - chars_per_word) {
+    all_char_bits |= *(reinterpret_cast<const MachineWord*>(characters));
+    characters += chars_per_word;
+  }
+
+  // Process the remaining bytes.
+  while (characters < end)
+    all_char_bits |= static_cast<MachineWord>(*characters++);
+
+  return !(all_char_bits & non_ascii_bit_mask);
+}
+
+template <bool (*Validator)(base_icu::UChar32)>
+inline bool DoIsStringUTF8(StringPiece str) {
+  const uint8_t* src = reinterpret_cast<const uint8_t*>(str.data());
+  size_t src_len = str.length();
+  size_t char_index = 0;
+
+  while (char_index < src_len) {
+    base_icu::UChar32 code_point;
+    CBU8_NEXT(src, char_index, src_len, code_point);
+    if (!Validator(code_point))
+      return false;
+  }
+  return true;
+}
+
+template <typename T, typename CharT = typename T::value_type>
+bool StartsWithT(T str, T search_for, CompareCase case_sensitivity) {
+  if (search_for.size() > str.size())
+    return false;
+
+  BasicStringPiece<CharT> source = str.substr(0, search_for.size());
+
+  switch (case_sensitivity) {
+    case CompareCase::SENSITIVE:
+      return source == search_for;
+
+    case CompareCase::INSENSITIVE_ASCII:
+      return std::equal(search_for.begin(), search_for.end(), source.begin(),
+                        CaseInsensitiveCompareASCII<CharT>());
+
+    default:
+      GURL_NOTREACHED();
+      return false;
+  }
+}
+
+template <typename T, typename CharT = typename T::value_type>
+bool EndsWithT(T str, T search_for, CompareCase case_sensitivity) {
+  if (search_for.size() > str.size())
+    return false;
+
+  BasicStringPiece<CharT> source =
+      str.substr(str.size() - search_for.size(), search_for.size());
+
+  switch (case_sensitivity) {
+    case CompareCase::SENSITIVE:
+      return source == search_for;
+
+    case CompareCase::INSENSITIVE_ASCII:
+      return std::equal(source.begin(), source.end(), search_for.begin(),
+                        CaseInsensitiveCompareASCII<CharT>());
+
+    default:
+      GURL_NOTREACHED();
+      return false;
+  }
+}
+
+// A Matcher for DoReplaceMatchesAfterOffset() that matches substrings.
+template <class CharT>
+struct SubstringMatcher {
+  BasicStringPiece<CharT> find_this;
+
+  size_t Find(const std::basic_string<CharT>& input, size_t pos) {
+    return input.find(find_this.data(), pos, find_this.length());
+  }
+  size_t MatchSize() { return find_this.length(); }
+};
+
+// Type deduction helper for SubstringMatcher.
+template <typename T, typename CharT = typename T::value_type>
+auto MakeSubstringMatcher(T find_this) {
+  return SubstringMatcher<CharT>{find_this};
+}
+
+// A Matcher for DoReplaceMatchesAfterOffset() that matches single characters.
+template <class CharT>
+struct CharacterMatcher {
+  BasicStringPiece<CharT> find_any_of_these;
+
+  size_t Find(const std::basic_string<CharT>& input, size_t pos) {
+    return input.find_first_of(find_any_of_these.data(), pos,
+                               find_any_of_these.length());
+  }
+  constexpr size_t MatchSize() { return 1; }
+};
+
+// Type deduction helper for CharacterMatcher.
+template <typename T, typename CharT = typename T::value_type>
+auto MakeCharacterMatcher(T find_any_of_these) {
+  return CharacterMatcher<CharT>{find_any_of_these};
+}
+
+enum class ReplaceType { REPLACE_ALL, REPLACE_FIRST };
+
+// Runs in O(n) time in the length of |str|, and transforms the string without
+// reallocating when possible. Returns |true| if any matches were found.
+//
+// This is parameterized on a |Matcher| traits type, so that it can be the
+// implementation for both ReplaceChars() and ReplaceSubstringsAfterOffset().
+template <typename Matcher, typename T, typename CharT = typename T::value_type>
+bool DoReplaceMatchesAfterOffset(std::basic_string<CharT>* str,
+                                 size_t initial_offset,
+                                 Matcher matcher,
+                                 T replace_with,
+                                 ReplaceType replace_type) {
+  using CharTraits = std::char_traits<CharT>;
+
+  const size_t find_length = matcher.MatchSize();
+  if (!find_length)
+    return false;
+
+  // If the find string doesn't appear, there's nothing to do.
+  size_t first_match = matcher.Find(*str, initial_offset);
+  if (first_match == std::basic_string<CharT>::npos)
+    return false;
+
+  // If we're only replacing one instance, there's no need to do anything
+  // complicated.
+  const size_t replace_length = replace_with.length();
+  if (replace_type == ReplaceType::REPLACE_FIRST) {
+    str->replace(first_match, find_length, replace_with.data(), replace_length);
+    return true;
+  }
+
+  // If the find and replace strings are the same length, we can simply use
+  // replace() on each instance, and finish the entire operation in O(n) time.
+  if (find_length == replace_length) {
+    auto* buffer = &((*str)[0]);
+    for (size_t offset = first_match; offset != std::basic_string<CharT>::npos;
+         offset = matcher.Find(*str, offset + replace_length)) {
+      CharTraits::copy(buffer + offset, replace_with.data(), replace_length);
+    }
+    return true;
+  }
+
+  // Since the find and replace strings aren't the same length, a loop like the
+  // one above would be O(n^2) in the worst case, as replace() will shift the
+  // entire remaining string each time. We need to be more clever to keep things
+  // O(n).
+  //
+  // When the string is being shortened, it's possible to just shift the matches
+  // down in one pass while finding, and truncate the length at the end of the
+  // search.
+  //
+  // If the string is being lengthened, more work is required. The strategy used
+  // here is to make two find() passes through the string. The first pass counts
+  // the number of matches to determine the new size. The second pass will
+  // either construct the new string into a new buffer (if the existing buffer
+  // lacked capacity), or else -- if there is room -- create a region of scratch
+  // space after |first_match| by shifting the tail of the string to a higher
+  // index, and doing in-place moves from the tail to lower indices thereafter.
+  size_t str_length = str->length();
+  size_t expansion = 0;
+  if (replace_length > find_length) {
+    // This operation lengthens the string; determine the new length by counting
+    // matches.
+    const size_t expansion_per_match = (replace_length - find_length);
+    size_t num_matches = 0;
+    for (size_t match = first_match; match != std::basic_string<CharT>::npos;
+         match = matcher.Find(*str, match + find_length)) {
+      expansion += expansion_per_match;
+      ++num_matches;
+    }
+    const size_t final_length = str_length + expansion;
+
+    if (str->capacity() < final_length) {
+      // If we'd have to allocate a new buffer to grow the string, build the
+      // result directly into the new allocation via append().
+      std::basic_string<CharT> src(str->get_allocator());
+      str->swap(src);
+      str->reserve(final_length);
+
+      size_t pos = 0;
+      for (size_t match = first_match;; match = matcher.Find(src, pos)) {
+        str->append(src, pos, match - pos);
+        str->append(replace_with.data(), replace_length);
+        pos = match + find_length;
+
+        // A mid-loop test/break enables skipping the final Find() call; the
+        // number of matches is known, so don't search past the last one.
+        if (!--num_matches)
+          break;
+      }
+
+      // Handle substring after the final match.
+      str->append(src, pos, str_length - pos);
+      return true;
+    }
+
+    // Prepare for the copy/move loop below -- expand the string to its final
+    // size by shifting the data after the first match to the end of the resized
+    // string.
+    size_t shift_src = first_match + find_length;
+    size_t shift_dst = shift_src + expansion;
+
+    // Big |expansion| factors (relative to |str_length|) require padding up to
+    // |shift_dst|.
+    if (shift_dst > str_length)
+      str->resize(shift_dst);
+
+    str->replace(shift_dst, str_length - shift_src, *str, shift_src,
+                 str_length - shift_src);
+    str_length = final_length;
+  }
+
+  // We can alternate replacement and move operations. This won't overwrite the
+  // unsearched region of the string so long as |write_offset| <= |read_offset|;
+  // that condition is always satisfied because:
+  //
+  //   (a) If the string is being shortened, |expansion| is zero and
+  //       |write_offset| grows slower than |read_offset|.
+  //
+  //   (b) If the string is being lengthened, |write_offset| grows faster than
+  //       |read_offset|, but |expansion| is big enough so that |write_offset|
+  //       will only catch up to |read_offset| at the point of the last match.
+  auto* buffer = &((*str)[0]);
+  size_t write_offset = first_match;
+  size_t read_offset = first_match + expansion;
+  do {
+    if (replace_length) {
+      CharTraits::copy(buffer + write_offset, replace_with.data(),
+                       replace_length);
+      write_offset += replace_length;
+    }
+    read_offset += find_length;
+
+    // min() clamps std::basic_string<CharT>::npos (the largest unsigned value)
+    // to str_length.
+    size_t match = std::min(matcher.Find(*str, read_offset), str_length);
+
+    size_t length = match - read_offset;
+    if (length) {
+      CharTraits::move(buffer + write_offset, buffer + read_offset, length);
+      write_offset += length;
+      read_offset += length;
+    }
+  } while (read_offset < str_length);
+
+  // If we're shortening the string, truncate it now.
+  str->resize(write_offset);
+  return true;
+}
+
+template <typename T, typename CharT = typename T::value_type>
+bool ReplaceCharsT(T input,
+                   T find_any_of_these,
+                   T replace_with,
+                   std::basic_string<CharT>* output) {
+  // Commonly, this is called with output and input being the same string; in
+  // that case, skip the copy.
+  if (input.data() != output->data() || input.size() != output->size())
+    output->assign(input.data(), input.size());
+
+  return DoReplaceMatchesAfterOffset(output, 0,
+                                     MakeCharacterMatcher(find_any_of_these),
+                                     replace_with, ReplaceType::REPLACE_ALL);
+}
+
+template <class string_type>
+inline typename string_type::value_type* WriteIntoT(string_type* str,
+                                                    size_t length_with_null) {
+  GURL_DCHECK_GE(length_with_null, 1u);
+  str->reserve(length_with_null);
+  str->resize(length_with_null - 1);
+  return &((*str)[0]);
+}
+
+// Generic version for all JoinString overloads. |list_type| must be a sequence
+// (gurl_base::span or std::initializer_list) of strings/StringPieces (std::string,
+// std::u16string, StringPiece or StringPiece16). |CharT| is either char or
+// char16_t.
+template <typename list_type,
+          typename T,
+          typename CharT = typename T::value_type>
+static std::basic_string<CharT> JoinStringT(list_type parts, T sep) {
+  if (std::empty(parts))
+    return std::basic_string<CharT>();
+
+  // Pre-allocate the eventual size of the string. Start with the size of all of
+  // the separators (note that this *assumes* parts.size() > 0).
+  size_t total_size = (parts.size() - 1) * sep.size();
+  for (const auto& part : parts)
+    total_size += part.size();
+  std::basic_string<CharT> result;
+  result.reserve(total_size);
+
+  auto iter = parts.begin();
+  GURL_DCHECK(iter != parts.end());
+  result.append(iter->data(), iter->size());
+  ++iter;
+
+  for (; iter != parts.end(); ++iter) {
+    result.append(sep.data(), sep.size());
+    result.append(iter->data(), iter->size());
+  }
+
+  // Sanity-check that we pre-allocated correctly.
+  GURL_DCHECK_EQ(total_size, result.size());
+
+  return result;
+}
+
+template <typename T, typename CharT = typename T::value_type>
+std::basic_string<CharT> DoReplaceStringPlaceholders(
+    T format_string,
+    const std::vector<std::basic_string<CharT>>& subst,
+    std::vector<size_t>* offsets) {
+  size_t substitutions = subst.size();
+  GURL_DCHECK_LT(substitutions, 11U);
+
+  size_t sub_length = 0;
+  for (const auto& cur : subst)
+    sub_length += cur.length();
+
+  std::basic_string<CharT> formatted;
+  formatted.reserve(format_string.length() + sub_length);
+
+  std::vector<ReplacementOffset> r_offsets;
+  for (auto i = format_string.begin(); i != format_string.end(); ++i) {
+    if ('$' == *i) {
+      if (i + 1 != format_string.end()) {
+        ++i;
+        if ('$' == *i) {
+          while (i != format_string.end() && '$' == *i) {
+            formatted.push_back('$');
+            ++i;
+          }
+          --i;
+        } else {
+          if (*i < '1' || *i > '9') {
+            GURL_DLOG(ERROR) << "Invalid placeholder: $"
+                        << std::basic_string<CharT>(1, *i);
+            continue;
+          }
+          size_t index = static_cast<size_t>(*i - '1');
+          if (offsets) {
+            ReplacementOffset r_offset(index, formatted.size());
+            r_offsets.insert(
+                ranges::upper_bound(r_offsets, r_offset, &CompareParameter),
+                r_offset);
+          }
+          if (index < substitutions)
+            formatted.append(subst.at(index));
+        }
+      }
+    } else {
+      formatted.push_back(*i);
+    }
+  }
+  if (offsets) {
+    for (const auto& cur : r_offsets)
+      offsets->push_back(cur.offset);
+  }
+  return formatted;
+}
+
+// The following code is compatible with the OpenBSD lcpy interface.  See:
+//   http://www.gratisoft.us/todd/papers/strlcpy.html
+//   ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c
+
+template <typename CHAR>
+size_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) {
+  for (size_t i = 0; i < dst_size; ++i) {
+    if ((dst[i] = src[i]) == 0)  // We hit and copied the terminating NULL.
+      return i;
+  }
+
+  // We were left off at dst_size.  We over copied 1 byte.  Null terminate.
+  if (dst_size != 0)
+    dst[dst_size - 1] = 0;
+
+  // Count the rest of the |src|, and return it's length in characters.
+  while (src[dst_size])
+    ++dst_size;
+  return dst_size;
+}
+
+}  // namespace gurl_base::internal
+
+#endif  // BASE_STRINGS_STRING_UTIL_IMPL_HELPERS_H_
diff --git a/base/strings/string_util_internal.h b/base/strings/string_util_internal.h
index 1d6a41e..3a493dd 100644
--- a/base/strings/string_util_internal.h
+++ b/base/strings/string_util_internal.h
@@ -5,66 +5,21 @@
 #ifndef BASE_STRINGS_STRING_UTIL_INTERNAL_H_
 #define BASE_STRINGS_STRING_UTIL_INTERNAL_H_
 
-#include <algorithm>
-
-#include "polyfills/base/check.h"
-#include "polyfills/base/check_op.h"
-#include "polyfills/base/logging.h"
-#include "polyfills/base/notreached.h"
 #include "base/ranges/algorithm.h"
 #include "base/strings/string_piece.h"
-#include "base/third_party/icu/icu_utf.h"
 
-namespace gurl_base {
+namespace gurl_base::internal {
 
-namespace internal {
-
-// Used by ReplaceStringPlaceholders to track the position in the string of
-// replaced parameters.
-struct ReplacementOffset {
-  ReplacementOffset(uintptr_t parameter, size_t offset)
-      : parameter(parameter), offset(offset) {}
-
-  // Index of the parameter.
-  size_t parameter;
-
-  // Starting position in the string.
-  size_t offset;
-};
-
-static bool CompareParameter(const ReplacementOffset& elem1,
-                             const ReplacementOffset& elem2) {
-  return elem1.parameter < elem2.parameter;
-}
-
-// Assuming that a pointer is the size of a "machine word", then
-// uintptr_t is an integer type that is also a machine word.
-using MachineWord = uintptr_t;
-
-inline bool IsMachineWordAligned(const void* pointer) {
-  return !(reinterpret_cast<MachineWord>(pointer) & (sizeof(MachineWord) - 1));
+// ASCII-specific tolower.  The standard library's tolower is locale sensitive,
+// so we don't want to use it here.
+template <typename CharT,
+          typename = std::enable_if_t<std::is_integral<CharT>::value>>
+constexpr CharT ToLowerASCII(CharT c) {
+  return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
 }
 
 template <typename T, typename CharT = typename T::value_type>
-std::basic_string<CharT> ToLowerASCIIImpl(T str) {
-  std::basic_string<CharT> ret;
-  ret.reserve(str.size());
-  for (size_t i = 0; i < str.size(); i++)
-    ret.push_back(ToLowerASCII(str[i]));
-  return ret;
-}
-
-template <typename T, typename CharT = typename T::value_type>
-std::basic_string<CharT> ToUpperASCIIImpl(T str) {
-  std::basic_string<CharT> ret;
-  ret.reserve(str.size());
-  for (size_t i = 0; i < str.size(); i++)
-    ret.push_back(ToUpperASCII(str[i]));
-  return ret;
-}
-
-template <typename T, typename CharT = typename T::value_type>
-int CompareCaseInsensitiveASCIIT(T a, T b) {
+constexpr int CompareCaseInsensitiveASCIIT(T a, T b) {
   // Find the first characters that aren't equal and compare them.  If the end
   // of one of the strings is found before a nonequal character, the lengths
   // of the strings are compared.
@@ -89,524 +44,14 @@
   return 1;
 }
 
-template <typename T, typename CharT = typename T::value_type>
-TrimPositions TrimStringT(T input,
-                          T trim_chars,
-                          TrimPositions positions,
-                          std::basic_string<CharT>* output) {
-  // Find the edges of leading/trailing whitespace as desired. Need to use
-  // a StringPiece version of input to be able to call find* on it with the
-  // StringPiece version of trim_chars (normally the trim_chars will be a
-  // constant so avoid making a copy).
-  const size_t last_char = input.length() - 1;
-  const size_t first_good_char =
-      (positions & TRIM_LEADING) ? input.find_first_not_of(trim_chars) : 0;
-  const size_t last_good_char = (positions & TRIM_TRAILING)
-                                    ? input.find_last_not_of(trim_chars)
-                                    : last_char;
-
-  // When the string was all trimmed, report that we stripped off characters
-  // from whichever position the caller was interested in. For empty input, we
-  // stripped no characters, but we still need to clear |output|.
-  if (input.empty() || first_good_char == std::basic_string<CharT>::npos ||
-      last_good_char == std::basic_string<CharT>::npos) {
-    bool input_was_empty = input.empty();  // in case output == &input
-    output->clear();
-    return input_was_empty ? TRIM_NONE : positions;
-  }
-
-  // Trim.
-  output->assign(input.data() + first_good_char,
-                 last_good_char - first_good_char + 1);
-
-  // Return where we trimmed from.
-  return static_cast<TrimPositions>(
-      (first_good_char == 0 ? TRIM_NONE : TRIM_LEADING) |
-      (last_good_char == last_char ? TRIM_NONE : TRIM_TRAILING));
+template <typename CharT, typename CharU>
+inline bool EqualsCaseInsensitiveASCIIT(BasicStringPiece<CharT> a,
+                                        BasicStringPiece<CharU> b) {
+  return ranges::equal(a, b, [](auto lhs, auto rhs) {
+    return ToLowerASCII(lhs) == ToLowerASCII(rhs);
+  });
 }
 
-template <typename T, typename CharT = typename T::value_type>
-T TrimStringPieceT(T input, T trim_chars, TrimPositions positions) {
-  size_t begin =
-      (positions & TRIM_LEADING) ? input.find_first_not_of(trim_chars) : 0;
-  size_t end = (positions & TRIM_TRAILING)
-                   ? input.find_last_not_of(trim_chars) + 1
-                   : input.size();
-  return input.substr(std::min(begin, input.size()), end - begin);
-}
-
-template <typename T, typename CharT = typename T::value_type>
-std::basic_string<CharT> CollapseWhitespaceT(
-    T text,
-    bool trim_sequences_with_line_breaks) {
-  std::basic_string<CharT> result;
-  result.resize(text.size());
-
-  // Set flags to pretend we're already in a trimmed whitespace sequence, so we
-  // will trim any leading whitespace.
-  bool in_whitespace = true;
-  bool already_trimmed = true;
-
-  size_t chars_written = 0;
-  for (auto c : text) {
-    if (IsWhitespace(c)) {
-      if (!in_whitespace) {
-        // Reduce all whitespace sequences to a single space.
-        in_whitespace = true;
-        result[chars_written++] = L' ';
-      }
-      if (trim_sequences_with_line_breaks && !already_trimmed &&
-          ((c == '\n') || (c == '\r'))) {
-        // Whitespace sequences containing CR or LF are eliminated entirely.
-        already_trimmed = true;
-        --chars_written;
-      }
-    } else {
-      // Non-whitespace characters are copied straight across.
-      in_whitespace = false;
-      already_trimmed = false;
-      result[chars_written++] = c;
-    }
-  }
-
-  if (in_whitespace && !already_trimmed) {
-    // Any trailing whitespace is eliminated.
-    --chars_written;
-  }
-
-  result.resize(chars_written);
-  return result;
-}
-
-template <class Char>
-bool DoIsStringASCII(const Char* characters, size_t length) {
-  // Bitmasks to detect non ASCII characters for character sizes of 8, 16 and 32
-  // bits.
-  constexpr MachineWord NonASCIIMasks[] = {
-      0, MachineWord(0x8080808080808080ULL), MachineWord(0xFF80FF80FF80FF80ULL),
-      0, MachineWord(0xFFFFFF80FFFFFF80ULL),
-  };
-
-  if (!length)
-    return true;
-  constexpr MachineWord non_ascii_bit_mask = NonASCIIMasks[sizeof(Char)];
-  static_assert(non_ascii_bit_mask, "Error: Invalid Mask");
-  MachineWord all_char_bits = 0;
-  const Char* end = characters + length;
-
-  // Prologue: align the input.
-  while (!IsMachineWordAligned(characters) && characters < end)
-    all_char_bits |= static_cast<MachineWord>(*characters++);
-  if (all_char_bits & non_ascii_bit_mask)
-    return false;
-
-  // Compare the values of CPU word size.
-  constexpr size_t chars_per_word = sizeof(MachineWord) / sizeof(Char);
-  constexpr int batch_count = 16;
-  while (characters <= end - batch_count * chars_per_word) {
-    all_char_bits = 0;
-    for (int i = 0; i < batch_count; ++i) {
-      all_char_bits |= *(reinterpret_cast<const MachineWord*>(characters));
-      characters += chars_per_word;
-    }
-    if (all_char_bits & non_ascii_bit_mask)
-      return false;
-  }
-
-  // Process the remaining words.
-  all_char_bits = 0;
-  while (characters <= end - chars_per_word) {
-    all_char_bits |= *(reinterpret_cast<const MachineWord*>(characters));
-    characters += chars_per_word;
-  }
-
-  // Process the remaining bytes.
-  while (characters < end)
-    all_char_bits |= static_cast<MachineWord>(*characters++);
-
-  return !(all_char_bits & non_ascii_bit_mask);
-}
-
-template <bool (*Validator)(base_icu::UChar32)>
-inline bool DoIsStringUTF8(StringPiece str) {
-  const uint8_t* src = reinterpret_cast<const uint8_t*>(str.data());
-  size_t src_len = str.length();
-  size_t char_index = 0;
-
-  while (char_index < src_len) {
-    base_icu::UChar32 code_point;
-    CBU8_NEXT(src, char_index, src_len, code_point);
-    if (!Validator(code_point))
-      return false;
-  }
-  return true;
-}
-
-template <typename T, typename CharT = typename T::value_type>
-bool StartsWithT(T str, T search_for, CompareCase case_sensitivity) {
-  if (search_for.size() > str.size())
-    return false;
-
-  BasicStringPiece<CharT> source = str.substr(0, search_for.size());
-
-  switch (case_sensitivity) {
-    case CompareCase::SENSITIVE:
-      return source == search_for;
-
-    case CompareCase::INSENSITIVE_ASCII:
-      return std::equal(search_for.begin(), search_for.end(), source.begin(),
-                        CaseInsensitiveCompareASCII<CharT>());
-
-    default:
-      GURL_NOTREACHED();
-      return false;
-  }
-}
-
-template <typename T, typename CharT = typename T::value_type>
-bool EndsWithT(T str, T search_for, CompareCase case_sensitivity) {
-  if (search_for.size() > str.size())
-    return false;
-
-  BasicStringPiece<CharT> source =
-      str.substr(str.size() - search_for.size(), search_for.size());
-
-  switch (case_sensitivity) {
-    case CompareCase::SENSITIVE:
-      return source == search_for;
-
-    case CompareCase::INSENSITIVE_ASCII:
-      return std::equal(source.begin(), source.end(), search_for.begin(),
-                        CaseInsensitiveCompareASCII<CharT>());
-
-    default:
-      GURL_NOTREACHED();
-      return false;
-  }
-}
-
-// A Matcher for DoReplaceMatchesAfterOffset() that matches substrings.
-template <class CharT>
-struct SubstringMatcher {
-  BasicStringPiece<CharT> find_this;
-
-  size_t Find(const std::basic_string<CharT>& input, size_t pos) {
-    return input.find(find_this.data(), pos, find_this.length());
-  }
-  size_t MatchSize() { return find_this.length(); }
-};
-
-// Type deduction helper for SubstringMatcher.
-template <typename T, typename CharT = typename T::value_type>
-auto MakeSubstringMatcher(T find_this) {
-  return SubstringMatcher<CharT>{find_this};
-}
-
-// A Matcher for DoReplaceMatchesAfterOffset() that matches single characters.
-template <class CharT>
-struct CharacterMatcher {
-  BasicStringPiece<CharT> find_any_of_these;
-
-  size_t Find(const std::basic_string<CharT>& input, size_t pos) {
-    return input.find_first_of(find_any_of_these.data(), pos,
-                               find_any_of_these.length());
-  }
-  constexpr size_t MatchSize() { return 1; }
-};
-
-// Type deduction helper for CharacterMatcher.
-template <typename T, typename CharT = typename T::value_type>
-auto MakeCharacterMatcher(T find_any_of_these) {
-  return CharacterMatcher<CharT>{find_any_of_these};
-}
-
-enum class ReplaceType { REPLACE_ALL, REPLACE_FIRST };
-
-// Runs in O(n) time in the length of |str|, and transforms the string without
-// reallocating when possible. Returns |true| if any matches were found.
-//
-// This is parameterized on a |Matcher| traits type, so that it can be the
-// implementation for both ReplaceChars() and ReplaceSubstringsAfterOffset().
-template <typename Matcher, typename T, typename CharT = typename T::value_type>
-bool DoReplaceMatchesAfterOffset(std::basic_string<CharT>* str,
-                                 size_t initial_offset,
-                                 Matcher matcher,
-                                 T replace_with,
-                                 ReplaceType replace_type) {
-  using CharTraits = std::char_traits<CharT>;
-
-  const size_t find_length = matcher.MatchSize();
-  if (!find_length)
-    return false;
-
-  // If the find string doesn't appear, there's nothing to do.
-  size_t first_match = matcher.Find(*str, initial_offset);
-  if (first_match == std::basic_string<CharT>::npos)
-    return false;
-
-  // If we're only replacing one instance, there's no need to do anything
-  // complicated.
-  const size_t replace_length = replace_with.length();
-  if (replace_type == ReplaceType::REPLACE_FIRST) {
-    str->replace(first_match, find_length, replace_with.data(), replace_length);
-    return true;
-  }
-
-  // If the find and replace strings are the same length, we can simply use
-  // replace() on each instance, and finish the entire operation in O(n) time.
-  if (find_length == replace_length) {
-    auto* buffer = &((*str)[0]);
-    for (size_t offset = first_match; offset != std::basic_string<CharT>::npos;
-         offset = matcher.Find(*str, offset + replace_length)) {
-      CharTraits::copy(buffer + offset, replace_with.data(), replace_length);
-    }
-    return true;
-  }
-
-  // Since the find and replace strings aren't the same length, a loop like the
-  // one above would be O(n^2) in the worst case, as replace() will shift the
-  // entire remaining string each time. We need to be more clever to keep things
-  // O(n).
-  //
-  // When the string is being shortened, it's possible to just shift the matches
-  // down in one pass while finding, and truncate the length at the end of the
-  // search.
-  //
-  // If the string is being lengthened, more work is required. The strategy used
-  // here is to make two find() passes through the string. The first pass counts
-  // the number of matches to determine the new size. The second pass will
-  // either construct the new string into a new buffer (if the existing buffer
-  // lacked capacity), or else -- if there is room -- create a region of scratch
-  // space after |first_match| by shifting the tail of the string to a higher
-  // index, and doing in-place moves from the tail to lower indices thereafter.
-  size_t str_length = str->length();
-  size_t expansion = 0;
-  if (replace_length > find_length) {
-    // This operation lengthens the string; determine the new length by counting
-    // matches.
-    const size_t expansion_per_match = (replace_length - find_length);
-    size_t num_matches = 0;
-    for (size_t match = first_match; match != std::basic_string<CharT>::npos;
-         match = matcher.Find(*str, match + find_length)) {
-      expansion += expansion_per_match;
-      ++num_matches;
-    }
-    const size_t final_length = str_length + expansion;
-
-    if (str->capacity() < final_length) {
-      // If we'd have to allocate a new buffer to grow the string, build the
-      // result directly into the new allocation via append().
-      std::basic_string<CharT> src(str->get_allocator());
-      str->swap(src);
-      str->reserve(final_length);
-
-      size_t pos = 0;
-      for (size_t match = first_match;; match = matcher.Find(src, pos)) {
-        str->append(src, pos, match - pos);
-        str->append(replace_with.data(), replace_length);
-        pos = match + find_length;
-
-        // A mid-loop test/break enables skipping the final Find() call; the
-        // number of matches is known, so don't search past the last one.
-        if (!--num_matches)
-          break;
-      }
-
-      // Handle substring after the final match.
-      str->append(src, pos, str_length - pos);
-      return true;
-    }
-
-    // Prepare for the copy/move loop below -- expand the string to its final
-    // size by shifting the data after the first match to the end of the resized
-    // string.
-    size_t shift_src = first_match + find_length;
-    size_t shift_dst = shift_src + expansion;
-
-    // Big |expansion| factors (relative to |str_length|) require padding up to
-    // |shift_dst|.
-    if (shift_dst > str_length)
-      str->resize(shift_dst);
-
-    str->replace(shift_dst, str_length - shift_src, *str, shift_src,
-                 str_length - shift_src);
-    str_length = final_length;
-  }
-
-  // We can alternate replacement and move operations. This won't overwrite the
-  // unsearched region of the string so long as |write_offset| <= |read_offset|;
-  // that condition is always satisfied because:
-  //
-  //   (a) If the string is being shortened, |expansion| is zero and
-  //       |write_offset| grows slower than |read_offset|.
-  //
-  //   (b) If the string is being lengthened, |write_offset| grows faster than
-  //       |read_offset|, but |expansion| is big enough so that |write_offset|
-  //       will only catch up to |read_offset| at the point of the last match.
-  auto* buffer = &((*str)[0]);
-  size_t write_offset = first_match;
-  size_t read_offset = first_match + expansion;
-  do {
-    if (replace_length) {
-      CharTraits::copy(buffer + write_offset, replace_with.data(),
-                       replace_length);
-      write_offset += replace_length;
-    }
-    read_offset += find_length;
-
-    // min() clamps std::basic_string<CharT>::npos (the largest unsigned value)
-    // to str_length.
-    size_t match = std::min(matcher.Find(*str, read_offset), str_length);
-
-    size_t length = match - read_offset;
-    if (length) {
-      CharTraits::move(buffer + write_offset, buffer + read_offset, length);
-      write_offset += length;
-      read_offset += length;
-    }
-  } while (read_offset < str_length);
-
-  // If we're shortening the string, truncate it now.
-  str->resize(write_offset);
-  return true;
-}
-
-template <typename T, typename CharT = typename T::value_type>
-bool ReplaceCharsT(T input,
-                   T find_any_of_these,
-                   T replace_with,
-                   std::basic_string<CharT>* output) {
-  // Commonly, this is called with output and input being the same string; in
-  // that case, skip the copy.
-  if (input.data() != output->data() || input.size() != output->size())
-    output->assign(input.data(), input.size());
-
-  return DoReplaceMatchesAfterOffset(output, 0,
-                                     MakeCharacterMatcher(find_any_of_these),
-                                     replace_with, ReplaceType::REPLACE_ALL);
-}
-
-template <class string_type>
-inline typename string_type::value_type* WriteIntoT(string_type* str,
-                                                    size_t length_with_null) {
-  GURL_DCHECK_GE(length_with_null, 1u);
-  str->reserve(length_with_null);
-  str->resize(length_with_null - 1);
-  return &((*str)[0]);
-}
-
-// Generic version for all JoinString overloads. |list_type| must be a sequence
-// (gurl_base::span or std::initializer_list) of strings/StringPieces (std::string,
-// std::u16string, StringPiece or StringPiece16). |CharT| is either char or
-// char16_t.
-template <typename list_type,
-          typename T,
-          typename CharT = typename T::value_type>
-static std::basic_string<CharT> JoinStringT(list_type parts, T sep) {
-  if (std::empty(parts))
-    return std::basic_string<CharT>();
-
-  // Pre-allocate the eventual size of the string. Start with the size of all of
-  // the separators (note that this *assumes* parts.size() > 0).
-  size_t total_size = (parts.size() - 1) * sep.size();
-  for (const auto& part : parts)
-    total_size += part.size();
-  std::basic_string<CharT> result;
-  result.reserve(total_size);
-
-  auto iter = parts.begin();
-  GURL_DCHECK(iter != parts.end());
-  result.append(iter->data(), iter->size());
-  ++iter;
-
-  for (; iter != parts.end(); ++iter) {
-    result.append(sep.data(), sep.size());
-    result.append(iter->data(), iter->size());
-  }
-
-  // Sanity-check that we pre-allocated correctly.
-  GURL_DCHECK_EQ(total_size, result.size());
-
-  return result;
-}
-
-template <typename T, typename CharT = typename T::value_type>
-std::basic_string<CharT> DoReplaceStringPlaceholders(
-    T format_string,
-    const std::vector<std::basic_string<CharT>>& subst,
-    std::vector<size_t>* offsets) {
-  size_t substitutions = subst.size();
-  GURL_DCHECK_LT(substitutions, 11U);
-
-  size_t sub_length = 0;
-  for (const auto& cur : subst)
-    sub_length += cur.length();
-
-  std::basic_string<CharT> formatted;
-  formatted.reserve(format_string.length() + sub_length);
-
-  std::vector<ReplacementOffset> r_offsets;
-  for (auto i = format_string.begin(); i != format_string.end(); ++i) {
-    if ('$' == *i) {
-      if (i + 1 != format_string.end()) {
-        ++i;
-        if ('$' == *i) {
-          while (i != format_string.end() && '$' == *i) {
-            formatted.push_back('$');
-            ++i;
-          }
-          --i;
-        } else {
-          if (*i < '1' || *i > '9') {
-            GURL_DLOG(ERROR) << "Invalid placeholder: $"
-                        << std::basic_string<CharT>(1, *i);
-            continue;
-          }
-          size_t index = static_cast<size_t>(*i - '1');
-          if (offsets) {
-            ReplacementOffset r_offset(index, formatted.size());
-            r_offsets.insert(
-                ranges::upper_bound(r_offsets, r_offset, &CompareParameter),
-                r_offset);
-          }
-          if (index < substitutions)
-            formatted.append(subst.at(index));
-        }
-      }
-    } else {
-      formatted.push_back(*i);
-    }
-  }
-  if (offsets) {
-    for (const auto& cur : r_offsets)
-      offsets->push_back(cur.offset);
-  }
-  return formatted;
-}
-
-// The following code is compatible with the OpenBSD lcpy interface.  See:
-//   http://www.gratisoft.us/todd/papers/strlcpy.html
-//   ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c
-
-template <typename CHAR>
-size_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) {
-  for (size_t i = 0; i < dst_size; ++i) {
-    if ((dst[i] = src[i]) == 0)  // We hit and copied the terminating NULL.
-      return i;
-  }
-
-  // We were left off at dst_size.  We over copied 1 byte.  Null terminate.
-  if (dst_size != 0)
-    dst[dst_size - 1] = 0;
-
-  // Count the rest of the |src|, and return it's length in characters.
-  while (src[dst_size])
-    ++dst_size;
-  return dst_size;
-}
-
-}  // namespace internal
-
-}  // namespace base
+}  // namespace gurl_base::internal
 
 #endif  // BASE_STRINGS_STRING_UTIL_INTERNAL_H_
diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc
index d4326c7..4109f8e 100644
--- a/base/strings/string_util_unittest.cc
+++ b/base/strings/string_util_unittest.cc
@@ -1474,6 +1474,14 @@
   // Differing values.
   EXPECT_EQ(-1, CompareCaseInsensitiveASCII("AsdfA", "aSDfb"));
   EXPECT_EQ(1, CompareCaseInsensitiveASCII("Asdfb", "aSDfA"));
+
+  // For constexpr.
+  static_assert(CompareCaseInsensitiveASCII("", "") == 0);
+  static_assert(CompareCaseInsensitiveASCII("Asdf", "aSDf") == 0);
+  static_assert(CompareCaseInsensitiveASCII("Asdf", "aSDfA") == -1);
+  static_assert(CompareCaseInsensitiveASCII("AsdfA", "aSDf") == 1);
+  static_assert(CompareCaseInsensitiveASCII("AsdfA", "aSDfb") == -1);
+  static_assert(CompareCaseInsensitiveASCII("Asdfb", "aSDfA") == 1);
 }
 
 TEST(StringUtilTest, EqualsCaseInsensitiveASCII) {
diff --git a/base/strings/string_util_win.cc b/base/strings/string_util_win.cc
index f8d0243..c3569b3 100644
--- a/base/strings/string_util_win.cc
+++ b/base/strings/string_util_win.cc
@@ -4,7 +4,8 @@
 
 #include "base/strings/string_util_win.h"
 
-#include "base/strings/string_util_internal.h"
+#include "base/ranges/algorithm.h"
+#include "base/strings/string_util_impl_helpers.h"
 
 namespace gurl_base {
 
@@ -72,7 +73,7 @@
 }
 
 bool EqualsASCII(WStringPiece str, StringPiece ascii) {
-  return std::equal(ascii.begin(), ascii.end(), str.begin(), str.end());
+  return ranges::equal(ascii, str);
 }
 
 bool StartsWith(WStringPiece str,
diff --git a/base/strings/utf_string_conversions_fuzzer.cc b/base/strings/utf_string_conversions_fuzzer.cc
deleted file mode 100644
index 3cc4521..0000000
--- a/base/strings/utf_string_conversions_fuzzer.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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.
-
-#include <tuple>
-
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-
-std::string output_std_string;
-std::wstring output_std_wstring;
-std::u16string output_string16;
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  gurl_base::StringPiece string_piece_input(reinterpret_cast<const char*>(data),
-                                       size);
-
-  std::ignore = gurl_base::UTF8ToWide(string_piece_input);
-  gurl_base::UTF8ToWide(reinterpret_cast<const char*>(data), size,
-                   &output_std_wstring);
-  std::ignore = gurl_base::UTF8ToUTF16(string_piece_input);
-  gurl_base::UTF8ToUTF16(reinterpret_cast<const char*>(data), size,
-                    &output_string16);
-
-  // Test for char16_t.
-  if (size % 2 == 0) {
-    gurl_base::StringPiece16 string_piece_input16(
-        reinterpret_cast<const char16_t*>(data), size / 2);
-    std::ignore = gurl_base::UTF16ToWide(output_string16);
-    gurl_base::UTF16ToWide(reinterpret_cast<const char16_t*>(data), size / 2,
-                      &output_std_wstring);
-    std::ignore = gurl_base::UTF16ToUTF8(string_piece_input16);
-    gurl_base::UTF16ToUTF8(reinterpret_cast<const char16_t*>(data), size / 2,
-                      &output_std_string);
-  }
-
-  // Test for wchar_t.
-  size_t wchar_t_size = sizeof(wchar_t);
-  if (size % wchar_t_size == 0) {
-    std::ignore = gurl_base::WideToUTF8(output_std_wstring);
-    gurl_base::WideToUTF8(reinterpret_cast<const wchar_t*>(data),
-                     size / wchar_t_size, &output_std_string);
-    std::ignore = gurl_base::WideToUTF16(output_std_wstring);
-    gurl_base::WideToUTF16(reinterpret_cast<const wchar_t*>(data),
-                      size / wchar_t_size, &output_string16);
-  }
-
-  // Test for ASCII. This condition is needed to avoid hitting instant GURL_CHECK
-  // failures.
-  if (gurl_base::IsStringASCII(string_piece_input)) {
-    output_string16 = gurl_base::ASCIIToUTF16(string_piece_input);
-    gurl_base::StringPiece16 string_piece_input16(output_string16);
-    std::ignore = gurl_base::UTF16ToASCII(string_piece_input16);
-  }
-
-  return 0;
-}
diff --git a/build/build_config.h b/build/build_config.h
index 8f90f47..6811872 100644
--- a/build/build_config.h
+++ b/build/build_config.h
@@ -245,6 +245,12 @@
 #define BUILDFLAG_INTERNAL_IS_WIN() (0)
 #endif
 
+#if defined(USE_OZONE)
+#define BUILDFLAG_INTERNAL_IS_OZONE() (1)
+#else
+#define BUILDFLAG_INTERNAL_IS_OZONE() (0)
+#endif
+
 // Compiler detection. Note: clang masquerades as GCC on POSIX and as MSVC on
 // Windows.
 #if defined(__GNUC__)
diff --git a/copy.bara.sky b/copy.bara.sky
index f9d1a2a..89f70ce 100644
--- a/copy.bara.sky
+++ b/copy.bara.sky
@@ -24,9 +24,10 @@
         "base/debug/crash_logging.cc",
         "base/debug/crash_logging.h",
         "base/debug/leak_annotations.h",
-        "base/functional/*.h",
+        "base/functional/identity.h",
+        "base/functional/invoke.h",
+        "base/functional/not_fn.h",
         "base/i18n/uchar.h",
-        "base/memory/raw_ptr.h",
         "base/memory/raw_ptr_exclusion.h",
         "base/numerics/*.h",
         "base/no_destructor.h",
@@ -47,6 +48,7 @@
     ],
     exclude = [
         "url/url_idna_icu_alternatives_android.cc",
+        "**/*_fuzzer.cc",
     ],
 )
 
@@ -72,10 +74,11 @@
     "base/check_op.h",
     "base/component_export.h",
     "base/cpu_reduction_experiment.h",
-    "base/dcheck_is_on.h",
+    #"base/dcheck_is_on.h",
     "base/debug/alias.h",
     "base/export_template.h",
     "base/logging.h",
+    "base/memory/raw_ptr.h",
     "base/notreached.h",
     "base/trace_event/memory_usage_estimator.h",
     "third_party/perfetto/include/perfetto/tracing/traced_value.h",
@@ -107,7 +110,6 @@
 
     core.replace("#include \"base/strings/string_number_conversions_win.h\"", ""),
     core.replace("#include \"base/allocator/partition_allocator/partition_alloc_config.h\"", ""),
-    core.replace("base/trace_event/base_tracing_forward.h", "polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h"),
 
     # Use system ICU.
     core.replace(
diff --git a/polyfills/BUILD b/polyfills/BUILD
index 6a58eec..ea1b73e 100644
--- a/polyfills/BUILD
+++ b/polyfills/BUILD
@@ -16,6 +16,7 @@
         "base/debug/alias.h",
         "base/export_template.h",
         "base/logging.h",
+        "base/memory/raw_ptr.h",
         "base/metrics/histogram_macros.h",
         "base/notreached.h",
         "base/trace_event/memory_usage_estimator.h",
diff --git a/polyfills/base/memory/raw_ptr.h b/polyfills/base/memory/raw_ptr.h
new file mode 100644
index 0000000..ec0e526
--- /dev/null
+++ b/polyfills/base/memory/raw_ptr.h
@@ -0,0 +1,17 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef POLYFILLS_BASE_MEMORY_RAW_PTR_H_
+#define POLYFILLS_BASE_MEMORY_RAW_PTR_H_
+
+namespace gurl_base {
+
+template<typename T>
+using raw_ptr = T*;
+
+}  // namespace gurl_base
+
+using gurl_base::raw_ptr;
+
+#endif  // POLYFILLS_BASE_MEMORY_RAW_PTR_H_
diff --git a/url/gurl_fuzzer.cc b/url/gurl_fuzzer.cc
deleted file mode 100644
index 170de8a..0000000
--- a/url/gurl_fuzzer.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// 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.
-
-#include "base/at_exit.h"
-#include "polyfills/base/check_op.h"
-#include "base/i18n/icu_util.h"
-#include "base/no_destructor.h"
-#include "url/gurl.h"
-
-struct TestCase {
-  TestCase() { GURL_CHECK(gurl_base::i18n::InitializeICU()); }
-
-  // used by ICU integration.
-  gurl_base::AtExitManager at_exit_manager;
-};
-
-TestCase* test_case = new TestCase();
-
-// Checks that GURL's canonicalization is idempotent. This can help discover
-// issues like https://crbug.com/1128999.
-void CheckIdempotency(const GURL& url) {
-  if (!url.is_valid())
-    return;
-  const std::string& spec = url.spec();
-  GURL recanonicalized(spec);
-  GURL_CHECK(recanonicalized.is_valid());
-  GURL_CHECK_EQ(spec, recanonicalized.spec());
-}
-
-// Checks that |url.spec()| is preserved across a call to ReplaceComponents with
-// zero replacements, which is effectively a copy. This can help discover issues
-// like https://crbug.com/1075515.
-void CheckReplaceComponentsPreservesSpec(const GURL& url) {
-  static const gurl_base::NoDestructor<GURL::Replacements> no_op;
-  GURL copy = url.ReplaceComponents(*no_op);
-  GURL_CHECK_EQ(url.is_valid(), copy.is_valid());
-  if (url.is_valid()) {
-    GURL_CHECK_EQ(url.spec(), copy.spec());
-  }
-}
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  if (size < 1)
-    return 0;
-  {
-    gurl_base::StringPiece string_piece_input(reinterpret_cast<const char*>(data),
-                                         size);
-    const GURL url_from_string_piece(string_piece_input);
-    CheckIdempotency(url_from_string_piece);
-    CheckReplaceComponentsPreservesSpec(url_from_string_piece);
-  }
-  // Test for StringPiece16 if size is even.
-  if (size % sizeof(char16_t) == 0) {
-    gurl_base::StringPiece16 string_piece_input16(
-        reinterpret_cast<const char16_t*>(data), size / sizeof(char16_t));
-    const GURL url_from_string_piece16(string_piece_input16);
-    CheckIdempotency(url_from_string_piece16);
-    CheckReplaceComponentsPreservesSpec(url_from_string_piece16);
-  }
-  // Resolve relative url tests.
-  {
-    size_t size_t_bytes = sizeof(size_t);
-    if (size < size_t_bytes + 1) {
-      return 0;
-    }
-    size_t relative_size =
-        *reinterpret_cast<const size_t*>(data) % (size - size_t_bytes);
-    std::string relative_string(
-        reinterpret_cast<const char*>(data + size_t_bytes), relative_size);
-    gurl_base::StringPiece string_piece_part_input(
-        reinterpret_cast<const char*>(data + size_t_bytes + relative_size),
-        size - relative_size - size_t_bytes);
-    const GURL url_from_string_piece_part(string_piece_part_input);
-    CheckIdempotency(url_from_string_piece_part);
-    CheckReplaceComponentsPreservesSpec(url_from_string_piece_part);
-
-    url_from_string_piece_part.Resolve(relative_string);
-
-    if (relative_size % sizeof(char16_t) == 0) {
-      std::u16string relative_string16(
-          reinterpret_cast<const char16_t*>(data + size_t_bytes),
-          relative_size / sizeof(char16_t));
-      url_from_string_piece_part.Resolve(relative_string16);
-    }
-  }
-  return 0;
-}
diff --git a/url/origin.h b/url/origin.h
index 0d04628..2b8caa5 100644
--- a/url/origin.h
+++ b/url/origin.h
@@ -311,6 +311,13 @@
   gurl_base::android::ScopedJavaLocalRef<jobject> CreateJavaObject() const;
   static Origin FromJavaObject(
       const gurl_base::android::JavaRef<jobject>& java_origin);
+  static jlong CreateNative(JNIEnv* env,
+                            const gurl_base::android::JavaRef<jstring>& java_scheme,
+                            const gurl_base::android::JavaRef<jstring>& java_host,
+                            uint16_t port,
+                            bool is_opaque,
+                            uint64_t tokenHighBits,
+                            uint64_t tokenLowBits);
 #endif  // BUILDFLAG(IS_ANDROID)
 
   void WriteIntoTrace(perfetto::TracedValue context) const;
diff --git a/url/origin_unittest.cc b/url/origin_unittest.cc
index 61500a6..5f28acc 100644
--- a/url/origin_unittest.cc
+++ b/url/origin_unittest.cc
@@ -5,7 +5,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "base/memory/raw_ptr.h"
+#include "polyfills/base/memory/raw_ptr.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
diff --git a/url/url_canon_icu.cc b/url/url_canon_icu.cc
index 20c31a8..088235b 100644
--- a/url/url_canon_icu.cc
+++ b/url/url_canon_icu.cc
@@ -9,7 +9,7 @@
 #include <string.h>
 
 #include "polyfills/base/check.h"
-#include "base/memory/raw_ptr.h"
+#include "polyfills/base/memory/raw_ptr.h"
 #include <unicode/ucnv.h>
 #include <unicode/ucnv_cb.h>
 #include <unicode/utypes.h>
diff --git a/url/url_canon_icu.h b/url/url_canon_icu.h
index 9a35df1..9b64722 100644
--- a/url/url_canon_icu.h
+++ b/url/url_canon_icu.h
@@ -9,7 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "polyfills/base/component_export.h"
-#include "base/memory/raw_ptr.h"
+#include "polyfills/base/memory/raw_ptr.h"
 #include "url/url_canon.h"
 
 typedef struct UConverter UConverter;
diff --git a/url/url_canon_icu_unittest.cc b/url/url_canon_icu_unittest.cc
index 0ac0fcb..fc3fb67 100644
--- a/url/url_canon_icu_unittest.cc
+++ b/url/url_canon_icu_unittest.cc
@@ -7,7 +7,7 @@
 #include <stddef.h>
 
 #include "polyfills/base/logging.h"
-#include "base/memory/raw_ptr.h"
+#include "polyfills/base/memory/raw_ptr.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include <unicode/ucnv.h>
 #include "url/url_canon.h"
diff --git a/url/url_canon_query.cc b/url/url_canon_query.cc
index 4beac7a..d326ce8 100644
--- a/url/url_canon_query.cc
+++ b/url/url_canon_query.cc
@@ -39,18 +39,6 @@
 
 namespace {
 
-// Returns true if the characters starting at |begin| and going until |end|
-// (non-inclusive) are all representable in 7-bits.
-template<typename CHAR, typename UCHAR>
-bool IsAllASCII(const CHAR* spec, const Component& query) {
-  int end = query.end();
-  for (int i = query.begin; i < end; i++) {
-    if (static_cast<UCHAR>(spec[i]) >= 0x80)
-      return false;
-  }
-  return true;
-}
-
 // Appends the given string to the output, escaping characters that do not
 // match the given |type| in SharedCharTypes. This version will accept 8 or 16
 // bit characters, but assumes that they have only 7-bit values. It also assumes
@@ -93,29 +81,22 @@
                               static_cast<size_t>(query.len), output);
 }
 
-template<typename CHAR, typename UCHAR>
+template <typename CHAR, typename UCHAR>
 void DoConvertToQueryEncoding(const CHAR* spec,
                               const Component& query,
                               CharsetConverter* converter,
                               CanonOutput* output) {
-  if (IsAllASCII<CHAR, UCHAR>(spec, query)) {
-    // Easy: the input can just appended with no character set conversions.
-    AppendRaw8BitQueryString(&spec[query.begin], query.len, output);
+  if (converter) {
+    // Run the converter to get an 8-bit string, then append it, escaping
+    // necessary values.
+    RawCanonOutput<1024> eight_bit;
+    RunConverter(spec, query, converter, &eight_bit);
+    AppendRaw8BitQueryString(eight_bit.data(), eight_bit.length(), output);
 
   } else {
-    // Harder: convert to the proper encoding first.
-    if (converter) {
-      // Run the converter to get an 8-bit string, then append it, escaping
-      // necessary values.
-      RawCanonOutput<1024> eight_bit;
-      RunConverter(spec, query, converter, &eight_bit);
-      AppendRaw8BitQueryString(eight_bit.data(), eight_bit.length(), output);
-
-    } else {
-      // No converter, do our own UTF-8 conversion.
-      AppendStringOfType(&spec[query.begin], static_cast<size_t>(query.len),
-                         CHAR_QUERY, output);
-    }
+    // No converter, do our own UTF-8 conversion.
+    AppendStringOfType(&spec[query.begin], static_cast<size_t>(query.len),
+                       CHAR_QUERY, output);
   }
 }