diff --git a/DEPS b/DEPS
index 9c146def..321c174 100644
--- a/DEPS
+++ b/DEPS
@@ -305,7 +305,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'src_internal_revision': '5a392040dbeaedc5f2cfabe8ac08793c446f8d6c',
+  'src_internal_revision': '8c572c92ad2038d9a0488d55599a138ab24941eb',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
@@ -336,7 +336,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:16.20231109.2.1',
+  'fuchsia_version': 'version:16.20231110.0.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -384,7 +384,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling chromium_variations
   # and whatever else without interference from each other.
-  'chromium_variations_revision': 'fa82e3ff298620455f9e159f8571a89bee79de72',
+  'chromium_variations_revision': 'eb760559fcf0a51cdfaf7e67f219a28d979ad2ef',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling CrossBench
   # and whatever else without interference from each other.
@@ -400,7 +400,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': 'cef1d4d47c8c59859778863f2ab83b7b9db68aa3',
+  'devtools_frontend_revision': 'c3e6c9af4f1260fce7879783b5fb8bbcf0b273bd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -424,7 +424,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'd3e897d992221ddddce7a9a7893fa66db8559c52',
+  'dawn_revision': 'c36093e932c33b6269204461ebbf864bd7e717de',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -468,7 +468,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'cros_components_revision': 'ccadd234bf9dfa004a69560ed58874a857541e19',
+  'cros_components_revision': 'e7649321f6608d790eb2421a8bada54d2d559ac4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -824,7 +824,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    'dcf0a93ec1e24456a5d335b278c99775a58dc7c6',
+    '12e84541a2d44aa5535caf8b1a073fa64376c0c6',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -986,7 +986,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'gO1gwDNP8NCu6fb6BPpX_uX5XEdw02892N08vXrJgh0C',
+          'version': 'VhiGCU24L3DYdm5QY-9RX9d2FneEUMrhgxAtcZU6T4AC',
       },
     ],
     'condition': 'checkout_android',
@@ -1218,13 +1218,13 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'dbd29671bd11c2d59fa898722bdbbcb7d48b8f8b',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ea9bf7f343d3510746a51313a20fb596cd7a6d58',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '34951c1d294f6e511c2ce3ecb17973a3a37cc1af',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'b32c6af7c0da8b57e81dd7217f1a519e3b8805e0',
     'condition': 'checkout_src_internal',
   },
 
@@ -1689,7 +1689,7 @@
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '8dc60d8a5484638134420511e0f54415853621c9',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '9c4d5090f6a29c785d4e2a1a1f577bcc17eeb648',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1871,7 +1871,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'f4bf599a8b575df685c31d9c4729a70a04e377ed',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '8eee61b66c5987e48fed3fc362910a52f91eb1ca',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '4e27db8161aec185923afa024f62870ef5a6442c',
 
   'src/third_party/webrtc':
     Var('webrtc_git') + '/src.git' + '@' + '283a5fd7ec64d231b1369843ac24d18222ecfde7',
@@ -2041,7 +2041,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': '9IVS0-UDErr5itZ_HHL6r0tAP8KhYGPz8OUr6qv-GLcC',
+        'version': 'rF05bDXQOiKycyinOyTdnpvoCMCtwASt4vSCI5O3Bd4C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -3858,7 +3858,7 @@
 
   'src/chrome/browser/resources/chromeos/quickoffice': {
       'url': Var('chrome_git') + '/quickoffice/crx.git' + '@' +
-        '23bde3495989fbc0112213613d2498030be51417',
+        '79e797d69d4675a2f0ef916dbb65457fe9485fc9',
       'condition': '(checkout_chromeos or checkout_linux) and checkout_src_internal',
   },
 
@@ -4031,7 +4031,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        'c1c113a56121778292a433076521a87eb30a441d',
+        '6fedcb89fabbeccebd8c87753620098b0037fcfe',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 77b2939..ef596091 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -7160,7 +7160,7 @@
     # `win-presubmit` are particularly sensitive to reading the files. Adding
     # this check caused the bot to run 2x longer. See https://crbug.com/1486612.
     if input_api.no_diffs:
-      return []
+        return []
 
     def FilterFile(file):
         return input_api.FilterSourceFile(
@@ -7171,8 +7171,8 @@
 
     count = 0
     for f in input_api.AffectedSourceFiles(FilterFile):
-        count -= f.OldContents().count("DanglingUntriaged")
-        count += f.NewContents().count("DanglingUntriaged")
+        count -= sum([l.count("DanglingUntriaged") for l in f.OldContents()])
+        count += sum([l.count("DanglingUntriaged") for l in f.NewContents()])
 
     # Most likely, nothing changed:
     if count == 0:
@@ -7180,10 +7180,7 @@
 
     # Congrats developers for improving it:
     if count < 0:
-        message = (
-            f"DanglingUntriaged pointers removed: {-count}",
-            f"Thank you!",
-        )
+        message = f"DanglingUntriaged pointers removed: {-count}\nThank you!"
         return [output_api.PresubmitNotifyResult(message)]
 
     # Check for 'DanglingUntriaged-notes' in the description:
@@ -7199,18 +7196,18 @@
         return []
 
     message = (
-        "Unexpected new occurrences of `DanglingUntriaged` detected. Please",
-        "avoid adding new ones",
-        "",
-        "See documentation:",
-        "https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr.md",
-        "",
-        "See also the guide to fix dangling pointers:",
-        "https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr_guide.md",
-        "",
-        "To disable this warning, please add in the commit description:",
-        "DanglingUntriaged-notes: <rational for new untriaged dangling "
-        "pointers>",
+        "Unexpected new occurrences of `DanglingUntriaged` detected. Please\n" +
+        "avoid adding new ones\n" +
+        "\n" +
+        "See documentation:\n" +
+        "https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr.md\n" +
+        "\n" +
+        "See also the guide to fix dangling pointers:\n" +
+        "https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr_guide.md\n" +
+        "\n" +
+        "To disable this warning, please add in the commit description:\n" +
+        "DanglingUntriaged-notes: <rational for new untriaged dangling " +
+        "pointers>"
     )
     return [output_api.PresubmitPromptWarning(message)]
 
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py
index fb6ab873..30175c3e 100755
--- a/PRESUBMIT_test.py
+++ b/PRESUBMIT_test.py
@@ -5106,8 +5106,8 @@
     mock_input_api.files = [
       MockAffectedFile(
         local_path="foo/foo.cc",
-        old_contents="raw_ptr<T>",
-        new_contents="raw_ptr<T, DanglingUntriaged>",
+        old_contents=["raw_ptr<T>"],
+        new_contents=["raw_ptr<T, DanglingUntriaged>"],
       )
     ]
     msgs = PRESUBMIT.CheckDanglingUntriaged(mock_input_api, mock_output_api)
@@ -5128,18 +5128,15 @@
     mock_input_api.files = [
       MockAffectedFile(
         local_path="foo/foo.cc",
-        old_contents="raw_ptr<T>",
-        new_contents="raw_ptr<T, DanglingUntriaged>",
+        old_contents=["raw_ptr<T>"],
+        new_contents=["raw_ptr<T, DanglingUntriaged>"],
       )
     ]
     msgs = PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
                         mock_output_api)
     self.assertEqual(len(msgs), 1)
-    self.assertEqual(len(msgs[0].message), 11)
-    self.assertEqual(
-      msgs[0].message[0],
-      "Unexpected new occurrences of `DanglingUntriaged` detected. Please",
-    )
+    self.assertTrue(("Unexpected new occurrences of `DanglingUntriaged` detected"
+                    in msgs[0].message))
 
   def testNonCppFile(self):
     """Test patch adding dangling pointers are not reported in non C++ files"""
@@ -5150,8 +5147,8 @@
     mock_input_api.files = [
       MockAffectedFile(
         local_path="foo/README.md",
-        old_contents="",
-        new_contents="The DanglingUntriaged annotation means",
+        old_contents=[""],
+        new_contents=["The DanglingUntriaged annotation means"],
       )
     ]
     msgs = PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
@@ -5167,8 +5164,8 @@
     mock_input_api.files = [
       MockAffectedFile(
         local_path="foo/foo.cc",
-        old_contents="raw_ptr<T>",
-        new_contents="raw_ptr<T, DanglingUntriaged>",
+        old_contents=["raw_ptr<T>"],
+        new_contents=["raw_ptr<T, DanglingUntriaged>"],
       )
     ]
     mock_input_api.change.DescriptionText = lambda: (
@@ -5186,8 +5183,8 @@
     mock_input_api.files = [
       MockAffectedFile(
         local_path="foo/foo.cc",
-        old_contents="raw_ptr<T>",
-        new_contents="raw_ptr<T, DanglingUntriaged>",
+        old_contents=["raw_ptr<T>"],
+        new_contents=["raw_ptr<T, DanglingUntriaged>"],
       )
     ]
     mock_input_api.change.DescriptionText = lambda: "description"
@@ -5204,8 +5201,8 @@
     mock_input_api.files = [
       MockAffectedFile(
         local_path="foo/foo.cc",
-        old_contents="raw_ptr<T, DanglingUntriaged>",
-        new_contents="raw_ptr<T>",
+        old_contents=["raw_ptr<T, DanglingUntriaged>"],
+        new_contents=["raw_ptr<T>"],
       )
     ]
     mock_input_api.change.DescriptionText = lambda: (
@@ -5225,14 +5222,14 @@
     mock_input_api.files = [
       MockAffectedFile(
         local_path="foo/foo.cc",
-        old_contents="raw_ptr<T, DanglingUntriaged>",
-        new_contents="",
+        old_contents=["raw_ptr<T, DanglingUntriaged>"],
+        new_contents=[""],
         action="D",
       ),
       MockAffectedFile(
         local_path="foo/foo.cc",
-        old_contents="",
-        new_contents="raw_ptr<T, DanglingUntriaged>",
+        old_contents=[""],
+        new_contents=["raw_ptr<T, DanglingUntriaged>"],
         action="A",
       ),
     ]
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index 658a6bd..38fd3e3 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -1119,6 +1119,7 @@
     "enable_printing=$enable_printing",
     "safe_browsing_mode=$safe_browsing_mode",
     "enable_supervised_users=$enable_supervised_users",
+    "use_blink=$use_blink",
   ]
 
   # See :generate_webui_resources for an explanation of the allowlist
diff --git a/android_webview/browser/aw_client_hints_controller_delegate.cc b/android_webview/browser/aw_client_hints_controller_delegate.cc
index a3cba10a..a3b196f 100644
--- a/android_webview/browser/aw_client_hints_controller_delegate.cc
+++ b/android_webview/browser/aw_client_hints_controller_delegate.cc
@@ -58,14 +58,14 @@
   // Regenerate the brand version lists with Android WebView product name.
   metadata.brand_version_list = embedder_support::GenerateBrandVersionList(
       major_version_number, kAndroidWebViewProductName, major_version,
-      absl::nullopt, absl::nullopt, enable_updated_grease_by_policy,
+      std::nullopt, std::nullopt, enable_updated_grease_by_policy,
       blink::UserAgentBrandVersionType::kMajorVersion);
 
   if (!only_low_entropy_ch) {
     metadata.brand_full_version_list =
         embedder_support::GenerateBrandVersionList(
             major_version_number, kAndroidWebViewProductName,
-            metadata.full_version, absl::nullopt, absl::nullopt,
+            metadata.full_version, std::nullopt, std::nullopt,
             enable_updated_grease_by_policy,
             blink::UserAgentBrandVersionType::kFullVersion);
   }
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 013ac5e6..3e0360f 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -499,12 +499,12 @@
   return std::string();
 }
 
-absl::optional<base::FilePath>
+std::optional<base::FilePath>
 AwContentBrowserClient::GetLocalTracesDirectory() {
   base::FilePath user_data_dir;
   if (!base::PathService::Get(android_webview::DIR_LOCAL_TRACES,
                               &user_data_dir)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   DCHECK(!user_data_dir.empty());
   return user_data_dir;
@@ -843,7 +843,7 @@
     network::mojom::WebSandboxFlags /*sandbox_flags*/,
     ui::PageTransition page_transition,
     bool has_user_gesture,
-    const absl::optional<url::Origin>& initiating_origin,
+    const std::optional<url::Origin>& initiating_origin,
     content::RenderFrameHost* initiator_document,
     mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
   // Sandbox flags
@@ -871,7 +871,7 @@
     // Manages its own lifetime.
     new android_webview::AwProxyingURLLoaderFactory(
         frame_tree_node_id, std::move(receiver), mojo::NullRemote(),
-        true /* intercept_only */, absl::nullopt /* security_options */,
+        true /* intercept_only */, std::nullopt /* security_options */,
         nullptr /* xrw_allowlist_matcher */, std::move(browser_context_handle));
   } else {
     content::GetIOThreadTaskRunner({})->PostTask(
@@ -885,7 +885,7 @@
               new android_webview::AwProxyingURLLoaderFactory(
                   frame_tree_node_id, std::move(receiver), mojo::NullRemote(),
                   true /* intercept_only */,
-                  absl::nullopt /* security_options */,
+                  std::nullopt /* security_options */,
                   nullptr /* xrw_allowlist_matcher */,
                   std::move(browser_context_handle));
             },
@@ -898,7 +898,7 @@
 void AwContentBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
     int render_process_id,
     int render_frame_id,
-    const absl::optional<url::Origin>& request_initiator_origin,
+    const std::optional<url::Origin>& request_initiator_origin,
     NonNetworkURLLoaderFactoryMap* factories) {
   WebContents* web_contents = content::WebContents::FromRenderFrameHost(
       content::RenderFrameHost::FromID(render_process_id, render_frame_id));
@@ -975,7 +975,7 @@
     int render_process_id,
     URLLoaderFactoryType type,
     const url::Origin& request_initiator,
-    absl::optional<int64_t> navigation_id,
+    std::optional<int64_t> navigation_id,
     ukm::SourceIdObj ukm_source_id,
     mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
     mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
@@ -1013,7 +1013,7 @@
           static_cast<AwBrowserContext*>(browser_context));
   if (frame) {
     auto security_options =
-        absl::make_optional<AwProxyingURLLoaderFactory::SecurityOptions>();
+        std::make_optional<AwProxyingURLLoaderFactory::SecurityOptions>();
     security_options->disable_web_security =
         base::CommandLine::ForCurrentProcess()->HasSwitch(
             switches::kDisableWebSecurity);
@@ -1057,7 +1057,7 @@
             &AwProxyingURLLoaderFactory::CreateProxy,
             content::RenderFrameHost::kNoFrameTreeNodeId,
             std::move(proxied_receiver), std::move(target_factory_remote),
-            absl::nullopt /* security_options */,
+            std::nullopt /* security_options */,
             aw_browser_context->service_worker_xrw_allowlist_matcher(),
             std::move(browser_context_handle)));
   }
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index 6e26be2..e093590 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -120,7 +120,7 @@
                        bool* no_javascript_access) override;
   base::FilePath GetDefaultDownloadDirectory() override;
   std::string GetDefaultDownloadName() override;
-  absl::optional<base::FilePath> GetLocalTracesDirectory() override;
+  std::optional<base::FilePath> GetLocalTracesDirectory() override;
   void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override;
   bool AllowPepperSocketAPI(
       content::BrowserContext* browser_context,
@@ -196,14 +196,14 @@
       network::mojom::WebSandboxFlags sandbox_flags,
       ui::PageTransition page_transition,
       bool has_user_gesture,
-      const absl::optional<url::Origin>& initiating_origin,
+      const std::optional<url::Origin>& initiating_origin,
       content::RenderFrameHost* initiator_document,
       mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory)
       override;
   void RegisterNonNetworkSubresourceURLLoaderFactories(
       int render_process_id,
       int render_frame_id,
-      const absl::optional<url::Origin>& request_initiator_origin,
+      const std::optional<url::Origin>& request_initiator_origin,
       NonNetworkURLLoaderFactoryMap* factories) override;
   bool ShouldAllowNoLongerUsedProcessToExit() override;
   bool ShouldIsolateErrorPage(bool in_main_frame) override;
@@ -219,7 +219,7 @@
       int render_process_id,
       URLLoaderFactoryType type,
       const url::Origin& request_initiator,
-      absl::optional<int64_t> navigation_id,
+      std::optional<int64_t> navigation_id,
       ukm::SourceIdObj ukm_source_id,
       mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
       mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
diff --git a/android_webview/browser/aw_contents_io_thread_client.cc b/android_webview/browser/aw_contents_io_thread_client.cc
index d2613cfc..cb45f04 100644
--- a/android_webview/browser/aw_contents_io_thread_client.cc
+++ b/android_webview/browser/aw_contents_io_thread_client.cc
@@ -8,6 +8,7 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "android_webview/browser/aw_settings.h"
 #include "android_webview/browser/network_service/aw_web_resource_intercept_response.h"
 #include "android_webview/browser/network_service/aw_web_resource_request.h"
@@ -35,7 +36,6 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "net/base/data_url.h"
 #include "services/network/public/cpp/resource_request.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 using base::LazyInstance;
 using base::android::AttachCurrentThread;
@@ -74,10 +74,10 @@
   static RfhToIoThreadClientMap* GetInstance();
   void Set(const content::GlobalRenderFrameHostToken& rfh_token,
            const JavaObjectWeakGlobalRef& client);
-  absl::optional<JavaObjectWeakGlobalRef> Get(
+  std::optional<JavaObjectWeakGlobalRef> Get(
       const content::GlobalRenderFrameHostToken& rfh_token);
 
-  absl::optional<JavaObjectWeakGlobalRef> Get(int frame_tree_node_id);
+  std::optional<JavaObjectWeakGlobalRef> Get(int frame_tree_node_id);
 
   // Prefer to call these when RenderFrameHost* is available, because they
   // update both maps at the same time.
@@ -109,25 +109,25 @@
   rfh_to_weak_global_ref_[rfh_token] = client;
 }
 
-absl::optional<JavaObjectWeakGlobalRef> RfhToIoThreadClientMap::Get(
+std::optional<JavaObjectWeakGlobalRef> RfhToIoThreadClientMap::Get(
     const content::GlobalRenderFrameHostToken& rfh_token) {
   base::AutoLock lock(map_lock_);
   RenderFrameHostToWeakGlobalRefType::iterator iterator =
       rfh_to_weak_global_ref_.find(rfh_token);
   if (iterator == rfh_to_weak_global_ref_.end()) {
-    return absl::nullopt;
+    return std::nullopt;
   } else {
     return iterator->second;
   }
 }
 
-absl::optional<JavaObjectWeakGlobalRef> RfhToIoThreadClientMap::Get(
+std::optional<JavaObjectWeakGlobalRef> RfhToIoThreadClientMap::Get(
     int frame_tree_node_id) {
   base::AutoLock lock(map_lock_);
   FrameTreeNodeToWeakGlobalRefType::iterator iterator =
       frame_tree_node_to_weak_global_ref_.find(frame_tree_node_id);
   if (iterator == frame_tree_node_to_weak_global_ref_.end()) {
-    return absl::nullopt;
+    return std::nullopt;
   } else {
     return iterator->second.second;
   }
@@ -222,7 +222,7 @@
 // a scoped local reference. This will return |nullptr| if either the optional
 // is empty or the weak reference has already expired.
 std::unique_ptr<AwContentsIoThreadClient> WrapOptionalWeakRef(
-    absl::optional<JavaObjectWeakGlobalRef> opt_delegate_weak_ref) {
+    std::optional<JavaObjectWeakGlobalRef> opt_delegate_weak_ref) {
   if (opt_delegate_weak_ref) {
     JNIEnv* env = AttachCurrentThread();
     ScopedJavaLocalRef<jobject> java_delegate = opt_delegate_weak_ref->get(env);
@@ -252,7 +252,7 @@
     const blink::LocalFrameToken& parent_frame_token,
     const blink::LocalFrameToken& child_frame_token) {
   RfhToIoThreadClientMap* map = RfhToIoThreadClientMap::GetInstance();
-  absl::optional<JavaObjectWeakGlobalRef> opt_delegate_weak_ref = map->Get(
+  std::optional<JavaObjectWeakGlobalRef> opt_delegate_weak_ref = map->Get(
       content::GlobalRenderFrameHostToken(child_id, parent_frame_token));
   if (opt_delegate_weak_ref) {
     map->Set(content::GlobalRenderFrameHostToken(child_id, child_frame_token),
diff --git a/android_webview/browser/aw_dark_mode.cc b/android_webview/browser/aw_dark_mode.cc
index 09d8c0ff..01ccbf8 100644
--- a/android_webview/browser/aw_dark_mode.cc
+++ b/android_webview/browser/aw_dark_mode.cc
@@ -175,7 +175,7 @@
 }
 
 void AwDarkMode::InferredColorSchemeUpdated(
-    absl::optional<blink::mojom::PreferredColorScheme> color_scheme) {
+    std::optional<blink::mojom::PreferredColorScheme> color_scheme) {
   if (prefers_dark_from_theme_ && color_scheme.has_value()) {
     UMA_HISTOGRAM_BOOLEAN(
         "Android.WebView.DarkMode.PageDarkenedAccordingToAppTheme",
diff --git a/android_webview/browser/aw_dark_mode.h b/android_webview/browser/aw_dark_mode.h
index 071c9ecd..d6036e2 100644
--- a/android_webview/browser/aw_dark_mode.h
+++ b/android_webview/browser/aw_dark_mode.h
@@ -38,7 +38,7 @@
   void NavigationEntryCommitted(
       const content::LoadCommittedDetails& load_details) override;
   void InferredColorSchemeUpdated(
-      absl::optional<blink::mojom::PreferredColorScheme> color_scheme) override;
+      std::optional<blink::mojom::PreferredColorScheme> color_scheme) override;
 
   void PopulateWebPreferencesForPreT(blink::web_pref::WebPreferences* web_prefs,
                                      int force_dark_mode,
diff --git a/android_webview/browser/aw_feature_map.cc b/android_webview/browser/aw_feature_map.cc
index cc92c7f..27dc4bdb 100644
--- a/android_webview/browser/aw_feature_map.cc
+++ b/android_webview/browser/aw_feature_map.cc
@@ -43,6 +43,7 @@
     &features::kWebViewSupervisedUserSiteBlock,
     &base::features::kCollectAndroidFrameTimelineMetrics,
     &features::kWebViewInjectPlatformJsApis,
+    &features::kWebViewMediaIntegrityApi,
 };
 
 // static
diff --git a/android_webview/browser/aw_http_auth_handler.cc b/android_webview/browser/aw_http_auth_handler.cc
index 00e237c6..663bcc90 100644
--- a/android_webview/browser/aw_http_auth_handler.cc
+++ b/android_webview/browser/aw_http_auth_handler.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include <optional>
 #include "android_webview/browser/aw_contents.h"
 #include "android_webview/browser_jni_headers/AwHttpAuthHandler_jni.h"
 #include "base/android/jni_android.h"
@@ -15,7 +16,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "net/base/auth.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 using base::android::ConvertJavaStringToUTF16;
 using base::android::JavaParamRef;
@@ -62,7 +62,7 @@
 void AwHttpAuthHandler::Cancel(JNIEnv* env, const JavaParamRef<jobject>& obj) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (callback_) {
-    std::move(callback_).Run(absl::nullopt);
+    std::move(callback_).Run(std::nullopt);
   }
 }
 
@@ -71,14 +71,14 @@
 
   // The WebContents may have been destroyed during the PostTask.
   if (!web_contents_) {
-    std::move(callback_).Run(absl::nullopt);
+    std::move(callback_).Run(std::nullopt);
     return;
   }
 
   AwContents* aw_contents = AwContents::FromWebContents(web_contents_.get());
   if (!aw_contents->OnReceivedHttpAuthRequest(http_auth_handler_, host_,
                                               realm_)) {
-    std::move(callback_).Run(absl::nullopt);
+    std::move(callback_).Run(std::nullopt);
   }
 }
 
diff --git a/android_webview/browser/aw_user_agent_metadata_unittest.cc b/android_webview/browser/aw_user_agent_metadata_unittest.cc
index 5c08aab..6512ba4 100644
--- a/android_webview/browser/aw_user_agent_metadata_unittest.cc
+++ b/android_webview/browser/aw_user_agent_metadata_unittest.cc
@@ -24,9 +24,9 @@
 
   void verifyUaMetadata(blink::UserAgentMetadata expect,
                         blink::UserAgentMetadata actual) {
-    absl::optional<std::string> expect_str =
+    std::optional<std::string> expect_str =
         blink::UserAgentMetadata::Marshal(expect);
-    absl::optional<std::string> actual_str =
+    std::optional<std::string> actual_str =
         blink::UserAgentMetadata::Marshal(actual);
     EXPECT_TRUE(expect_str.has_value() == actual_str.has_value());
     if (expect_str.has_value()) {
diff --git a/android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy.cc b/android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy.cc
index de62978..45ba404 100644
--- a/android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy.cc
+++ b/android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy.cc
@@ -13,6 +13,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "android_webview/browser/metrics/aw_metrics_service_client.h"
 #include "android_webview/common/aw_features.h"
 #include "android_webview/common/aw_switches.h"
@@ -34,7 +35,6 @@
 #include "base/version.h"
 #include "components/component_updater/android/component_loader_policy.h"
 #include "components/optimization_guide/core/bloom_filter.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace android_webview {
 
@@ -54,7 +54,7 @@
 
 struct AllowListLookupResult {
   AllowlistPraseStatus parse_status;
-  absl::optional<AppPackageNameLoggingRule> record_rule;
+  std::optional<AppPackageNameLoggingRule> record_rule;
 };
 
 void RecordAndReportResult(AllowListLookupCallback lookup_callback,
@@ -118,7 +118,7 @@
 }
 
 void SetAppPackageNameLoggingRule(
-    absl::optional<AppPackageNameLoggingRule> record) {
+    std::optional<AppPackageNameLoggingRule> record) {
   auto* metrics_service_client = AwMetricsServiceClient::GetInstance();
   DCHECK(metrics_service_client);
   metrics_service_client->SetAppPackageNameLoggingRule(record);
@@ -142,7 +142,7 @@
 
 bool ShouldThrottleAppPackageNamesAllowlistComponent(
     base::Time last_update,
-    absl::optional<AppPackageNameLoggingRule> cached_record) {
+    std::optional<AppPackageNameLoggingRule> cached_record) {
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kWebViewDisablePackageAllowlistThrottling) ||
       last_update.is_null()) {
@@ -166,7 +166,7 @@
 AwAppsPackageNamesAllowlistComponentLoaderPolicy::
     AwAppsPackageNamesAllowlistComponentLoaderPolicy(
         std::string app_package_name,
-        absl::optional<AppPackageNameLoggingRule> cached_record,
+        std::optional<AppPackageNameLoggingRule> cached_record,
         AllowListLookupCallback lookup_callback)
     : app_package_name_(std::move(app_package_name)),
       cached_record_(cached_record),
@@ -204,11 +204,11 @@
 
   // Have to use double because base::DictionaryValue doesn't support int64
   // values.
-  absl::optional<double> expiry_date_ms =
+  std::optional<double> expiry_date_ms =
       manifest.FindDoubleByDottedPath(kExpiryDateKey);
-  absl::optional<int> num_hash =
+  std::optional<int> num_hash =
       manifest.FindIntByDottedPath(kBloomFilterNumHashKey);
-  absl::optional<int> num_bits =
+  std::optional<int> num_bits =
       manifest.FindIntByDottedPath(kBloomFilterNumBitsKey);
   // Being conservative and consider the allowlist expired when a valid expiry
   // date is absent.
@@ -255,7 +255,7 @@
   DCHECK(lookup_callback_);
   // TODO(crbug.com/1216200): Record the error in a histogram in the
   // ComponentLoader for each component.
-  std::move(lookup_callback_).Run(absl::optional<AppPackageNameLoggingRule>());
+  std::move(lookup_callback_).Run(std::optional<AppPackageNameLoggingRule>());
 }
 
 void AwAppsPackageNamesAllowlistComponentLoaderPolicy::GetHash(
@@ -279,7 +279,7 @@
               kWebViewAppsPackageNamesServerSideAllowlist)) {
     return;
   }
-  absl::optional<AppPackageNameLoggingRule> cached_record =
+  std::optional<AppPackageNameLoggingRule> cached_record =
       metrics_service_client->GetCachedAppPackageNameLoggingRule();
   base::Time last_update =
       metrics_service_client->GetAppPackageNameLoggingRuleLastUpdateTime();
diff --git a/android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy.h b/android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy.h
index 8458065..72e67699 100644
--- a/android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy.h
+++ b/android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy.h
@@ -9,13 +9,13 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "android_webview/common/metrics/app_package_name_logging_rule.h"
 #include "base/containers/flat_map.h"
 #include "base/files/scoped_file.h"
 #include "base/functional/callback.h"
 #include "base/values.h"
 #include "components/component_updater/android/component_loader_policy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class Time;
@@ -45,7 +45,7 @@
 // A callback for the result of loading and looking up the allowlist. If the
 // allowlist loading fails, it will be called with a null record.
 using AllowListLookupCallback =
-    base::OnceCallback<void(absl::optional<AppPackageNameLoggingRule>)>;
+    base::OnceCallback<void(std::optional<AppPackageNameLoggingRule>)>;
 
 // Defines a loader responsible for receiving the allowlist for apps package
 // names that can be included in UMA records and lookup the embedding app's name
@@ -73,7 +73,7 @@
   //                    `app_package_name` in the packages names allowlist.
   AwAppsPackageNamesAllowlistComponentLoaderPolicy(
       std::string app_package_name,
-      absl::optional<AppPackageNameLoggingRule> cached_record,
+      std::optional<AppPackageNameLoggingRule> cached_record,
       AllowListLookupCallback lookup_callback);
   ~AwAppsPackageNamesAllowlistComponentLoaderPolicy() override;
 
@@ -93,7 +93,7 @@
 
  private:
   std::string app_package_name_;
-  absl::optional<AppPackageNameLoggingRule> cached_record_;
+  std::optional<AppPackageNameLoggingRule> cached_record_;
 
   AllowListLookupCallback lookup_callback_;
 };
diff --git a/android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy_unittest.cc b/android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy_unittest.cc
index f84c180..1895967c 100644
--- a/android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy_unittest.cc
+++ b/android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy_unittest.cc
@@ -93,7 +93,7 @@
   }
 
   void LookupConfirmationCallback(
-      absl::optional<AppPackageNameLoggingRule> record) {
+      std::optional<AppPackageNameLoggingRule> record) {
     EXPECT_TRUE(checker_.CalledOnValidSequence());
     allowlist_lookup_result_ = record;
     lookup_run_loop_.Quit();
@@ -106,7 +106,7 @@
   base::RunLoop lookup_run_loop_;
   base::HistogramTester histogram_tester_;
 
-  absl::optional<AppPackageNameLoggingRule> allowlist_lookup_result_;
+  std::optional<AppPackageNameLoggingRule> allowlist_lookup_result_;
 
  private:
   base::FilePath allowlist_path_;
@@ -179,7 +179,7 @@
 
   auto policy =
       std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
-          "non.existent.app", absl::optional<AppPackageNameLoggingRule>(),
+          "non.existent.app", std::optional<AppPackageNameLoggingRule>(),
           base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
                              LookupConfirmationCallback,
                          base::Unretained(this)));
@@ -203,7 +203,7 @@
 
   auto policy =
       std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
-          kTestAllowlist[1], absl::optional<AppPackageNameLoggingRule>(),
+          kTestAllowlist[1], std::optional<AppPackageNameLoggingRule>(),
           base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
                              LookupConfirmationCallback,
                          base::Unretained(this)));
@@ -228,7 +228,7 @@
 
   auto policy =
       std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
-          kTestAllowlist[1], absl::optional<AppPackageNameLoggingRule>(),
+          kTestAllowlist[1], std::optional<AppPackageNameLoggingRule>(),
           base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
                              LookupConfirmationCallback,
                          base::Unretained(this)));
@@ -252,7 +252,7 @@
 
   auto policy =
       std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
-          kTestAllowlist[1], absl::optional<AppPackageNameLoggingRule>(),
+          kTestAllowlist[1], std::optional<AppPackageNameLoggingRule>(),
           base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
                              LookupConfirmationCallback,
                          base::Unretained(this)));
@@ -277,7 +277,7 @@
 
   auto policy =
       std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
-          kTestAllowlist[1], absl::optional<AppPackageNameLoggingRule>(),
+          kTestAllowlist[1], std::optional<AppPackageNameLoggingRule>(),
           base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
                              LookupConfirmationCallback,
                          base::Unretained(this)));
@@ -306,7 +306,7 @@
 
   auto policy =
       std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
-          kTestAllowlist[1], absl::optional<AppPackageNameLoggingRule>(),
+          kTestAllowlist[1], std::optional<AppPackageNameLoggingRule>(),
           base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
                              LookupConfirmationCallback,
                          base::Unretained(this)));
@@ -346,7 +346,7 @@
   EXPECT_EQ(policies.size(), expect_throttling ? 0 : 1u);
 }
 
-void TestThrottlingAllowlist(absl::optional<AppPackageNameLoggingRule> rule,
+void TestThrottlingAllowlist(std::optional<AppPackageNameLoggingRule> rule,
                              bool expect_throttling) {
   TestingPrefServiceSimple prefs;
   AwMetricsServiceClient::RegisterMetricsPrefs(prefs.registry());
@@ -390,7 +390,7 @@
       android_webview::features::kWebViewAppsPackageNamesServerSideAllowlist);
   base::SetRecordActionTaskRunner(env_.GetMainThreadTaskRunner());
 
-  TestThrottlingAllowlist(absl::optional<AppPackageNameLoggingRule>(),
+  TestThrottlingAllowlist(std::optional<AppPackageNameLoggingRule>(),
                           /*expect_throttling=*/false);
 }
 
diff --git a/android_webview/browser/cookie_manager.cc b/android_webview/browser/cookie_manager.cc
index 1a771d4..825fb40 100644
--- a/android_webview/browser/cookie_manager.cc
+++ b/android_webview/browser/cookie_manager.cc
@@ -10,6 +10,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "android_webview/browser/aw_browser_context.h"
 #include "android_webview/browser/aw_browser_context_store.h"
 #include "android_webview/browser/aw_client_hints_controller_delegate.h"
@@ -54,7 +55,6 @@
 #include "services/network/cookie_access_delegate_impl.h"
 #include "services/network/network_service.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/url_constants.h"
 
 using base::WaitableEvent;
@@ -488,7 +488,7 @@
       host, value, workaround_http_secure_cookies_, &should_allow_cookie);
 
   std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create(
-      new_host, value, base::Time::Now(), absl::nullopt /* server_time */,
+      new_host, value, base::Time::Now(), std::nullopt /* server_time */,
       net::CookiePartitionKey::FromWire(net::SchemefulSite(new_host))));
 
   if (!cc || !should_allow_cookie) {
diff --git a/android_webview/browser/enterprise_authentication_app_link_policy_handler_unittest.cc b/android_webview/browser/enterprise_authentication_app_link_policy_handler_unittest.cc
index fee7f6c..22dbbac 100644
--- a/android_webview/browser/enterprise_authentication_app_link_policy_handler_unittest.cc
+++ b/android_webview/browser/enterprise_authentication_app_link_policy_handler_unittest.cc
@@ -40,7 +40,7 @@
              nullptr);
   this->UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  absl::optional<base::Value> expected = base::JSONReader::Read(R"(
+  std::optional<base::Value> expected = base::JSONReader::Read(R"(
     [
      "https://www.testserver1.com/login",
      "https://www.testserver2.com/login"
diff --git a/android_webview/browser/gfx/aw_draw_fn_impl.h b/android_webview/browser/gfx/aw_draw_fn_impl.h
index 75498cec..41df418 100644
--- a/android_webview/browser/gfx/aw_draw_fn_impl.h
+++ b/android_webview/browser/gfx/aw_draw_fn_impl.h
@@ -5,6 +5,7 @@
 #ifndef ANDROID_WEBVIEW_BROWSER_GFX_AW_DRAW_FN_IMPL_H_
 #define ANDROID_WEBVIEW_BROWSER_GFX_AW_DRAW_FN_IMPL_H_
 
+#include <optional>
 #include "android_webview/browser/gfx/aw_vulkan_context_provider.h"
 #include "android_webview/browser/gfx/compositor_frame_consumer.h"
 #include "android_webview/browser/gfx/render_thread_manager.h"
@@ -12,7 +13,6 @@
 #include "android_webview/public/browser/draw_fn.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/threading/platform_thread.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
 
 namespace android_webview {
@@ -68,13 +68,13 @@
   // Vulkan context provider for Vk rendering.
   scoped_refptr<AwVulkanContextProvider> vulkan_context_provider_;
 
-  absl::optional<AwVulkanContextProvider::ScopedSecondaryCBDraw>
+  std::optional<AwVulkanContextProvider::ScopedSecondaryCBDraw>
       scoped_secondary_cb_draw_;
 
-  absl::optional<VulkanGLInterop> interop_;
+  std::optional<VulkanGLInterop> interop_;
 
   // Latched on first DrawGL / InitVk call.
-  absl::optional<base::PlatformThreadId> render_thread_id_;
+  std::optional<base::PlatformThreadId> render_thread_id_;
 
   bool skip_next_post_draw_vk_ = false;
 };
diff --git a/android_webview/browser/gfx/aw_vulkan_context_provider.cc b/android_webview/browser/gfx/aw_vulkan_context_provider.cc
index 17e8dd93..7fd74c6 100644
--- a/android_webview/browser/gfx/aw_vulkan_context_provider.cc
+++ b/android_webview/browser/gfx/aw_vulkan_context_provider.cc
@@ -212,9 +212,8 @@
   post_submit_tasks_.push_back(std::move(closure));
 }
 
-absl::optional<uint32_t> AwVulkanContextProvider::GetSyncCpuMemoryLimit()
-    const {
-  return absl::optional<uint32_t>();
+std::optional<uint32_t> AwVulkanContextProvider::GetSyncCpuMemoryLimit() const {
+  return std::optional<uint32_t>();
 }
 
 bool AwVulkanContextProvider::Initialize(AwDrawFn_InitVkParams* params) {
diff --git a/android_webview/browser/gfx/aw_vulkan_context_provider.h b/android_webview/browser/gfx/aw_vulkan_context_provider.h
index 26aec03..14c9db5 100644
--- a/android_webview/browser/gfx/aw_vulkan_context_provider.h
+++ b/android_webview/browser/gfx/aw_vulkan_context_provider.h
@@ -7,10 +7,10 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/memory/raw_ptr_exclusion.h"
 #include "components/viz/common/gpu/vulkan_context_provider.h"
 #include "gpu/vulkan/vulkan_device_queue.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/gpu/GrBackendSemaphore.h"
 #include "third_party/skia/include/private/chromium/GrVkSecondaryCBDrawContext.h"
@@ -63,7 +63,7 @@
   void EnqueueSecondaryCBSemaphores(
       std::vector<VkSemaphore> semaphores) override;
   void EnqueueSecondaryCBPostSubmitTask(base::OnceClosure closure) override;
-  absl::optional<uint32_t> GetSyncCpuMemoryLimit() const override;
+  std::optional<uint32_t> GetSyncCpuMemoryLimit() const override;
 
   VkDevice device() { return globals_->device_queue->GetVulkanDevice(); }
   VkQueue queue() { return globals_->device_queue->GetVulkanQueue(); }
diff --git a/android_webview/browser/gfx/browser_view_renderer.h b/android_webview/browser/gfx/browser_view_renderer.h
index 3f5116d6..7e7a4aaf 100644
--- a/android_webview/browser/gfx/browser_view_renderer.h
+++ b/android_webview/browser/gfx/browser_view_renderer.h
@@ -10,6 +10,7 @@
 #include <map>
 #include <set>
 
+#include <optional>
 #include "android_webview/browser/gfx/begin_frame_source_webview.h"
 #include "android_webview/browser/gfx/child_frame.h"
 #include "android_webview/browser/gfx/compositor_frame_producer.h"
@@ -24,7 +25,6 @@
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "content/public/browser/android/synchronous_compositor.h"
 #include "content/public/browser/android/synchronous_compositor_client.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
 #include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/geometry/rect.h"
@@ -282,7 +282,7 @@
   gfx::Vector2dF overscroll_rounding_error_;
 
   // The scroll to apply after the next scroll state update.
-  absl::optional<gfx::Point> scroll_on_scroll_state_update_;
+  std::optional<gfx::Point> scroll_on_scroll_state_update_;
 
   ParentCompositorDrawConstraints external_draw_constraints_;
 
diff --git a/android_webview/browser/gfx/child_frame.h b/android_webview/browser/gfx/child_frame.h
index f71be02..4177b76 100644
--- a/android_webview/browser/gfx/child_frame.h
+++ b/android_webview/browser/gfx/child_frame.h
@@ -8,12 +8,12 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/containers/circular_deque.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "components/viz/common/surfaces/surface_id.h"
 #include "content/public/browser/android/synchronous_compositor.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/geometry/transform.h"
 
@@ -55,7 +55,7 @@
   scoped_refptr<content::SynchronousCompositor::FrameFuture> frame_future;
   uint32_t layer_tree_frame_sink_id = 0u;
   std::unique_ptr<viz::CompositorFrame> frame;
-  absl::optional<viz::HitTestRegionList> hit_test_region_list;
+  std::optional<viz::HitTestRegionList> hit_test_region_list;
   // The id of the compositor this |frame| comes from.
   const viz::FrameSinkId frame_sink_id;
   // Local surface id of the frame. Invalid if |frame| is null.
diff --git a/android_webview/browser/gfx/hardware_renderer.cc b/android_webview/browser/gfx/hardware_renderer.cc
index 99fd14d0..d2987ba 100644
--- a/android_webview/browser/gfx/hardware_renderer.cc
+++ b/android_webview/browser/gfx/hardware_renderer.cc
@@ -338,7 +338,7 @@
       render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
   surface_quad->SetNew(quad_state, gfx::Rect(quad_state->quad_layer_rect),
                        gfx::Rect(quad_state->quad_layer_rect),
-                       viz::SurfaceRange(absl::nullopt, child_id),
+                       viz::SurfaceRange(std::nullopt, child_id),
                        SkColors::kWhite,
                        /*stretch_content_to_fill_bounds=*/false);
 
@@ -697,7 +697,7 @@
         ->PessimisticallyResetGrContext();
   }
 
-  absl::optional<OverlayProcessorWebView::ScopedSurfaceControlAvailable>
+  std::optional<OverlayProcessorWebView::ScopedSurfaceControlAvailable>
       allow_surface_control;
 
   auto* overlay_processor = on_viz_->overlay_processor();
diff --git a/android_webview/browser/gfx/overlay_processor_webview.cc b/android_webview/browser/gfx/overlay_processor_webview.cc
index b7301a7..b5c8b8e 100644
--- a/android_webview/browser/gfx/overlay_processor_webview.cc
+++ b/android_webview/browser/gfx/overlay_processor_webview.cc
@@ -393,10 +393,10 @@
     }
   }
 
-  absl::optional<gfx::SurfaceControl::Transaction> TakeHWUITransaction() {
+  std::optional<gfx::SurfaceControl::Transaction> TakeHWUITransaction() {
     DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
 
-    absl::optional<gfx::SurfaceControl::Transaction> result;
+    std::optional<gfx::SurfaceControl::Transaction> result;
     if (hwui_transaction_) {
       DCHECK(gpu_task_runner_);
       if (!pending_resource_update_.empty() || !pending_removals_.empty()) {
@@ -657,7 +657,7 @@
   base::flat_set<uint64_t> pending_removals_;
 
   scoped_refptr<gfx::SurfaceControl::Surface> parent_surface_;
-  absl::optional<gfx::SurfaceControl::Transaction> hwui_transaction_;
+  std::optional<gfx::SurfaceControl::Transaction> hwui_transaction_;
 
   GetSurfaceControlFn get_surface_control_ = nullptr;
 
@@ -721,7 +721,7 @@
   overlays_.clear();
 }
 
-absl::optional<gfx::SurfaceControl::Transaction>
+std::optional<gfx::SurfaceControl::Transaction>
 OverlayProcessorWebView::TakeSurfaceTransactionOnRT() {
   DCHECK(manager_);
   return manager_->TakeHWUITransaction();
diff --git a/android_webview/browser/gfx/overlay_processor_webview.h b/android_webview/browser/gfx/overlay_processor_webview.h
index 5c8b2fa..e27ec41 100644
--- a/android_webview/browser/gfx/overlay_processor_webview.h
+++ b/android_webview/browser/gfx/overlay_processor_webview.h
@@ -54,7 +54,7 @@
                              const viz::ResolvedFrameData* frame_data);
   void SetOverlaysEnabledByHWUI(bool enabled);
   void RemoveOverlays();
-  absl::optional<gfx::SurfaceControl::Transaction> TakeSurfaceTransactionOnRT();
+  std::optional<gfx::SurfaceControl::Transaction> TakeSurfaceTransactionOnRT();
   viz::SurfaceId GetOverlaySurfaceId(const viz::FrameSinkId& frame_sink_id);
 
   // viz::OverlayProcessorSurfaceControl overrides:
@@ -62,8 +62,9 @@
       viz::OverlayCandidateList* candidate_list) override;
   void ScheduleOverlays(
       viz::DisplayResourceProvider* resource_provider) override;
-  void AdjustOutputSurfaceOverlay(absl::optional<OutputSurfaceOverlayPlane>*
-                                      output_surface_plane) override {}
+  void AdjustOutputSurfaceOverlay(
+      std::optional<OutputSurfaceOverlayPlane>* output_surface_plane) override {
+  }
   void CheckOverlaySupportImpl(
       const viz::OverlayProcessorInterface::OutputSurfaceOverlayPlane*
           primary_plane,
diff --git a/android_webview/browser/gfx/render_thread_manager.cc b/android_webview/browser/gfx/render_thread_manager.cc
index 930298b..3680341 100644
--- a/android_webview/browser/gfx/render_thread_manager.cc
+++ b/android_webview/browser/gfx/render_thread_manager.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "android_webview/browser/gfx/compositor_frame_producer.h"
 #include "android_webview/browser/gfx/gpu_service_webview.h"
 #include "android_webview/browser/gfx/hardware_renderer.h"
@@ -23,7 +24,6 @@
 #include "base/trace_event/traced_value.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/quads/compositor_frame.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace android_webview {
 
@@ -194,7 +194,7 @@
   // Force GL binding init if it's not yet initialized.
   GpuServiceWebView::GetInstance();
 
-  absl::optional<ScopedAppGLStateRestore> state_restore;
+  std::optional<ScopedAppGLStateRestore> state_restore;
   if (!vulkan_context_provider_) {
     state_restore.emplace(ScopedAppGLStateRestore::MODE_DRAW, save_restore);
     if (state_restore->skip_draw()) {
@@ -229,7 +229,7 @@
                                                       bool abandon_context) {
   GpuServiceWebView::GetInstance();
 
-  absl::optional<ScopedAppGLStateRestore> state_restore;
+  std::optional<ScopedAppGLStateRestore> state_restore;
   if (!vulkan_context_provider_ && !abandon_context) {
     state_restore.emplace(ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT,
                           save_restore);
diff --git a/android_webview/browser/gfx/root_frame_sink.cc b/android_webview/browser/gfx/root_frame_sink.cc
index acb376cc..6532848 100644
--- a/android_webview/browser/gfx/root_frame_sink.cc
+++ b/android_webview/browser/gfx/root_frame_sink.cc
@@ -77,7 +77,7 @@
   void SubmitCompositorFrame(
       const viz::LocalSurfaceId& local_surface_id,
       viz::CompositorFrame frame,
-      absl::optional<viz::HitTestRegionList> hit_test_region_list) {
+      std::optional<viz::HitTestRegionList> hit_test_region_list) {
     size_ = frame.size_in_pixels();
     support()->SubmitCompositorFrame(local_surface_id, std::move(frame),
                                      std::move(hit_test_region_list));
diff --git a/android_webview/browser/gfx/test/invalidate_test.cc b/android_webview/browser/gfx/test/invalidate_test.cc
index f0f5b49..849a5447 100644
--- a/android_webview/browser/gfx/test/invalidate_test.cc
+++ b/android_webview/browser/gfx/test/invalidate_test.cc
@@ -49,7 +49,7 @@
       render_pass.CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
   surface_quad->SetNew(quad_state, gfx::Rect(quad_state->quad_layer_rect),
                        gfx::Rect(quad_state->quad_layer_rect),
-                       viz::SurfaceRange(absl::nullopt, child_id),
+                       viz::SurfaceRange(std::nullopt, child_id),
                        SkColors::kWhite,
                        /*stretch_content_to_fill_bounds=*/false);
 }
@@ -233,7 +233,7 @@
     frame.metadata.frame_token = frames_submitted_;
     support_->SubmitCompositorFrame(
         local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
-        std::move(frame), absl::nullopt);
+        std::move(frame), std::nullopt);
   }
 
   void DidNotProduceFrame(const viz::BeginFrameAck& ack) {
diff --git a/android_webview/browser/metrics/aw_component_metrics_provider_delegate.cc b/android_webview/browser/metrics/aw_component_metrics_provider_delegate.cc
index 3c59dca..8629bc86 100644
--- a/android_webview/browser/metrics/aw_component_metrics_provider_delegate.cc
+++ b/android_webview/browser/metrics/aw_component_metrics_provider_delegate.cc
@@ -43,7 +43,7 @@
                               kWebViewAppsPackageNamesAllowlistComponentId;
                      }),
       components.end());
-  absl::optional<AppPackageNameLoggingRule> record =
+  std::optional<AppPackageNameLoggingRule> record =
       client_->GetCachedAppPackageNameLoggingRule();
   if (record.has_value()) {
     components.emplace_back(kWebViewAppsPackageNamesAllowlistComponentId, "",
diff --git a/android_webview/browser/metrics/aw_metrics_service_client.cc b/android_webview/browser/metrics/aw_metrics_service_client.cc
index 8eab70e..d7d6378 100644
--- a/android_webview/browser/metrics/aw_metrics_service_client.cc
+++ b/android_webview/browser/metrics/aw_metrics_service_client.cc
@@ -170,8 +170,8 @@
 }
 
 void AwMetricsServiceClient::SetAppPackageNameLoggingRule(
-    absl::optional<AppPackageNameLoggingRule> record) {
-  absl::optional<AppPackageNameLoggingRule> cached_record =
+    std::optional<AppPackageNameLoggingRule> record) {
+  std::optional<AppPackageNameLoggingRule> cached_record =
       GetCachedAppPackageNameLoggingRule();
   if (!record.has_value()) {
     package_name_record_status_ =
@@ -201,7 +201,7 @@
       base::Time::Now() - time_created_);
 }
 
-absl::optional<AppPackageNameLoggingRule>
+std::optional<AppPackageNameLoggingRule>
 AwMetricsServiceClient::GetCachedAppPackageNameLoggingRule() {
   if (cached_package_name_record_.has_value()) {
     return cached_package_name_record_;
diff --git a/android_webview/browser/metrics/aw_metrics_service_client.h b/android_webview/browser/metrics/aw_metrics_service_client.h
index 787b650..74a14f2 100644
--- a/android_webview/browser/metrics/aw_metrics_service_client.h
+++ b/android_webview/browser/metrics/aw_metrics_service_client.h
@@ -195,12 +195,11 @@
   // `record` If it has a null value, then it will be ignored and the cached
   //          record will be used if any.
   void SetAppPackageNameLoggingRule(
-      absl::optional<AppPackageNameLoggingRule> record);
+      std::optional<AppPackageNameLoggingRule> record);
 
   // Get the cached record of the app package names allowlist set by
   // `SetAppPackageNameLoggingRule` if any.
-  absl::optional<AppPackageNameLoggingRule>
-  GetCachedAppPackageNameLoggingRule();
+  std::optional<AppPackageNameLoggingRule> GetCachedAppPackageNameLoggingRule();
 
   // The last time the apps package name allowlist was queried from the
   // component update service, regardless if it was successful or not.
@@ -225,7 +224,7 @@
   base::Time time_created_;
   std::unique_ptr<Delegate> delegate_;
 
-  absl::optional<AppPackageNameLoggingRule> cached_package_name_record_;
+  std::optional<AppPackageNameLoggingRule> cached_package_name_record_;
   AppPackageNameLoggingRuleStatus package_name_record_status_ =
       AppPackageNameLoggingRuleStatus::kNotLoadedNoCache;
 };
diff --git a/android_webview/browser/metrics/aw_metrics_service_client_unittest.cc b/android_webview/browser/metrics/aw_metrics_service_client_unittest.cc
index 97cbe8d..82e26c5 100644
--- a/android_webview/browser/metrics/aw_metrics_service_client_unittest.cc
+++ b/android_webview/browser/metrics/aw_metrics_service_client_unittest.cc
@@ -141,7 +141,7 @@
   prefs->SetDict(prefs::kMetricsAppPackageNameLoggingRule,
                  expected_record.ToDictionary());
 
-  absl::optional<AppPackageNameLoggingRule> cached_record =
+  std::optional<AppPackageNameLoggingRule> cached_record =
       client->GetCachedAppPackageNameLoggingRule();
   EXPECT_TRUE(client->ShouldRecordPackageName());
   ASSERT_TRUE(cached_record.has_value());
@@ -173,7 +173,7 @@
   AppPackageNameLoggingRule expected_record(
       base::Version(kTestAllowlistVersion), base::Time::Min());
   client->SetAppPackageNameLoggingRule(expected_record);
-  absl::optional<AppPackageNameLoggingRule> cached_record =
+  std::optional<AppPackageNameLoggingRule> cached_record =
       client->GetCachedAppPackageNameLoggingRule();
 
   EXPECT_FALSE(client->ShouldRecordPackageName());
@@ -204,7 +204,7 @@
   AppPackageNameLoggingRule expected_record(
       base::Version(kTestAllowlistVersion), base::Time::Now() + expiry_time);
   client->SetAppPackageNameLoggingRule(expected_record);
-  absl::optional<AppPackageNameLoggingRule> cached_record =
+  std::optional<AppPackageNameLoggingRule> cached_record =
       client->GetCachedAppPackageNameLoggingRule();
 
   EXPECT_TRUE(client->ShouldRecordPackageName());
@@ -247,8 +247,8 @@
       base::Version(kTestAllowlistVersion), base::Time::Now() + expiry_time);
   client->SetAppPackageNameLoggingRule(expected_record);
   client->SetAppPackageNameLoggingRule(
-      absl::optional<AppPackageNameLoggingRule>());
-  absl::optional<AppPackageNameLoggingRule> cached_record =
+      std::optional<AppPackageNameLoggingRule>());
+  std::optional<AppPackageNameLoggingRule> cached_record =
       client->GetCachedAppPackageNameLoggingRule();
 
   EXPECT_TRUE(client->ShouldRecordPackageName());
@@ -277,7 +277,7 @@
 
   AwMetricsServiceClient* client = GetClient();
   client->SetAppPackageNameLoggingRule(
-      absl::optional<AppPackageNameLoggingRule>());
+      std::optional<AppPackageNameLoggingRule>());
 
   EXPECT_FALSE(client->ShouldRecordPackageName());
 
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
index d724f1f..331b949 100644
--- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
+++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
@@ -9,6 +9,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "android_webview/browser/android_protocol_handler.h"
 #include "android_webview/browser/aw_browser_context.h"
 #include "android_webview/browser/aw_contents_client_bridge.h"
@@ -46,7 +47,6 @@
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/mojom/early_hints.mojom.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
 #include "third_party/blink/public/mojom/origin_trial_feature/origin_trial_feature.mojom-shared.h"
 #include "url/gurl.h"
@@ -84,7 +84,7 @@
       mojo::PendingRemote<network::mojom::URLLoaderClient> client,
       mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory,
       bool intercept_only,
-      absl::optional<AwProxyingURLLoaderFactory::SecurityOptions>
+      std::optional<AwProxyingURLLoaderFactory::SecurityOptions>
           security_options,
       scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher,
       scoped_refptr<AwBrowserContextIoThreadHandle> browser_context_handle);
@@ -101,7 +101,7 @@
   void OnReceiveResponse(
       network::mojom::URLResponseHeadPtr head,
       mojo::ScopedDataPipeConsumerHandle body,
-      absl::optional<mojo_base::BigBuffer> cached_metadata) override;
+      std::optional<mojo_base::BigBuffer> cached_metadata) override;
   void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
                          network::mojom::URLResponseHeadPtr head) override;
   void OnUploadProgress(int64_t current_position,
@@ -115,7 +115,7 @@
       const std::vector<std::string>& removed_headers,
       const net::HttpRequestHeaders& modified_headers,
       const net::HttpRequestHeaders& modified_cors_exempt_headers,
-      const absl::optional<GURL>& new_url) override;
+      const std::optional<GURL>& new_url) override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
@@ -180,7 +180,7 @@
 
   AwSettings::RequestedWithHeaderMode requested_with_header_mode;
 
-  absl::optional<AwProxyingURLLoaderFactory::SecurityOptions> security_options_;
+  std::optional<AwProxyingURLLoaderFactory::SecurityOptions> security_options_;
 
   // If the |target_loader_| called OnComplete with an error this stores it.
   // That way the destructor can send it to OnReceivedError if safe browsing
@@ -293,8 +293,7 @@
     mojo::PendingRemote<network::mojom::URLLoaderClient> client,
     mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory,
     bool intercept_only,
-    absl::optional<AwProxyingURLLoaderFactory::SecurityOptions>
-        security_options,
+    std::optional<AwProxyingURLLoaderFactory::SecurityOptions> security_options,
     scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher,
     scoped_refptr<AwBrowserContextIoThreadHandle> browser_context_handle)
     : frame_tree_node_id_(frame_tree_node_id),
@@ -624,7 +623,7 @@
           traffic_annotation_,
           std::make_unique<InterceptResponseDelegate>(
               std::move(response), weak_factory_.GetWeakPtr()),
-          absl::nullopt);
+          std::nullopt);
   loader->Start();
 }
 
@@ -687,7 +686,7 @@
 void InterceptedRequest::OnReceiveResponse(
     network::mojom::URLResponseHeadPtr head,
     mojo::ScopedDataPipeConsumerHandle body,
-    absl::optional<mojo_base::BigBuffer> cached_metadata) {
+    std::optional<mojo_base::BigBuffer> cached_metadata) {
   // intercept response headers here
   // pause/resume |proxied_client_receiver_| if necessary
 
@@ -765,7 +764,7 @@
     const std::vector<std::string>& removed_headers,
     const net::HttpRequestHeaders& modified_headers,
     const net::HttpRequestHeaders& modified_cors_exempt_headers,
-    const absl::optional<GURL>& new_url) {
+    const std::optional<GURL>& new_url) {
   if (target_loader_) {
     target_loader_->FollowRedirect(removed_headers, modified_headers,
                                    modified_cors_exempt_headers, new_url);
@@ -906,7 +905,7 @@
     mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver,
     mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote,
     bool intercept_only,
-    absl::optional<SecurityOptions> security_options,
+    std::optional<SecurityOptions> security_options,
     scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher,
     scoped_refptr<AwBrowserContextIoThreadHandle> browser_context_handle)
     : frame_tree_node_id_(frame_tree_node_id),
@@ -935,7 +934,7 @@
     int frame_tree_node_id,
     mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver,
     mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote,
-    absl::optional<SecurityOptions> security_options,
+    std::optional<SecurityOptions> security_options,
     scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher,
     scoped_refptr<AwBrowserContextIoThreadHandle> browser_context_handle) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.h b/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
index 5bea2cd..33708dd0 100644
--- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
+++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
@@ -5,6 +5,7 @@
 #ifndef ANDROID_WEBVIEW_BROWSER_NETWORK_SERVICE_AW_PROXYING_URL_LOADER_FACTORY_H_
 #define ANDROID_WEBVIEW_BROWSER_NETWORK_SERVICE_AW_PROXYING_URL_LOADER_FACTORY_H_
 
+#include <optional>
 #include "android_webview/browser/network_service/aw_browser_context_io_thread_handle.h"
 #include "base/memory/weak_ptr.h"
 #include "components/embedder_support/android/util/android_stream_reader_url_loader.h"
@@ -15,7 +16,6 @@
 #include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/origin.h"
 
 namespace net {
@@ -72,7 +72,7 @@
       mojo::PendingRemote<network::mojom::URLLoaderFactory>
           target_factory_remote,
       bool intercept_only,
-      absl::optional<SecurityOptions> security_options,
+      std::optional<SecurityOptions> security_options,
       scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher,
       scoped_refptr<AwBrowserContextIoThreadHandle> browser_context_handle);
 
@@ -88,7 +88,7 @@
       mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader,
       mojo::PendingRemote<network::mojom::URLLoaderFactory>
           target_factory_remote,
-      absl::optional<SecurityOptions> security_options,
+      std::optional<SecurityOptions> security_options,
       scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher,
       scoped_refptr<AwBrowserContextIoThreadHandle> browser_context_handle);
 
@@ -117,7 +117,7 @@
   // a response, the loader will abort loading.
   bool intercept_only_;
 
-  absl::optional<SecurityOptions> security_options_;
+  std::optional<SecurityOptions> security_options_;
 
   scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher_;
 
diff --git a/android_webview/browser/network_service/aw_web_resource_request.h b/android_webview/browser/network_service/aw_web_resource_request.h
index f336ffc..69f4a51 100644
--- a/android_webview/browser/network_service/aw_web_resource_request.h
+++ b/android_webview/browser/network_service/aw_web_resource_request.h
@@ -8,8 +8,8 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/android/scoped_java_ref.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace net {
 class HttpRequestHeaders;
@@ -62,7 +62,7 @@
   bool has_user_gesture;
   std::vector<std::string> header_names;
   std::vector<std::string> header_values;
-  absl::optional<bool> is_renderer_initiated;
+  std::optional<bool> is_renderer_initiated;
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/tracing/aw_background_tracing_metrics_provider.h b/android_webview/browser/tracing/aw_background_tracing_metrics_provider.h
index 935860a..7052fd8 100644
--- a/android_webview/browser/tracing/aw_background_tracing_metrics_provider.h
+++ b/android_webview/browser/tracing/aw_background_tracing_metrics_provider.h
@@ -7,8 +7,8 @@
 
 #include "components/tracing/common/background_tracing_metrics_provider.h"
 
+#include <optional>
 #include "base/memory/weak_ptr.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace tracing {
 
diff --git a/android_webview/browser/tracing/aw_tracing_delegate.cc b/android_webview/browser/tracing/aw_tracing_delegate.cc
index f071f474..60792a6b 100644
--- a/android_webview/browser/tracing/aw_tracing_delegate.cc
+++ b/android_webview/browser/tracing/aw_tracing_delegate.cc
@@ -88,7 +88,7 @@
   return true;
 }
 
-absl::optional<base::Value::Dict> AwTracingDelegate::GenerateMetadataDict() {
+std::optional<base::Value::Dict> AwTracingDelegate::GenerateMetadataDict() {
   base::Value::Dict metadata_dict;
   metadata_dict.Set("revision", version_info::GetLastChange());
   return metadata_dict;
diff --git a/android_webview/browser/tracing/aw_tracing_delegate.h b/android_webview/browser/tracing/aw_tracing_delegate.h
index 8b37ebb..aa63baf 100644
--- a/android_webview/browser/tracing/aw_tracing_delegate.h
+++ b/android_webview/browser/tracing/aw_tracing_delegate.h
@@ -5,8 +5,8 @@
 #ifndef ANDROID_WEBVIEW_BROWSER_TRACING_AW_TRACING_DELEGATE_H_
 #define ANDROID_WEBVIEW_BROWSER_TRACING_AW_TRACING_DELEGATE_H_
 
+#include <optional>
 #include "content/public/browser/tracing_delegate.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class PrefRegistrySimple;
 
@@ -26,7 +26,7 @@
   // content::TracingDelegate implementation:
   bool OnBackgroundTracingActive(bool requires_anonymized_data) override;
   bool OnBackgroundTracingIdle(bool requires_anonymized_data) override;
-  absl::optional<base::Value::Dict> GenerateMetadataDict() override;
+  std::optional<base::Value::Dict> GenerateMetadataDict() override;
 
  private:
   bool IsAllowedToStartScenario() const;
diff --git a/android_webview/common/aw_features.cc b/android_webview/common/aw_features.cc
index 6a5e11d..a08f4f5 100644
--- a/android_webview/common/aw_features.cc
+++ b/android_webview/common/aw_features.cc
@@ -77,6 +77,12 @@
              "WebViewEmptyComponentLoaderPolicy",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Enable the WebView Media Integrity API.
+// This feature requires `kWebViewInjectPlatformJsApis` to be enabled as well.
+BASE_FEATURE(kWebViewMediaIntegrityApi,
+             "WebViewMediaIntegrityApi",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // When enabled, passive mixed content (Audio/Video/Image subresources loaded
 // over HTTP on HTTPS sites) will be autoupgraded to HTTPS, and the load will be
 // blocked if the resource fails to load over HTTPS. This only affects apps that
diff --git a/android_webview/common/aw_features.h b/android_webview/common/aw_features.h
index bf731be..d2f29d91 100644
--- a/android_webview/common/aw_features.h
+++ b/android_webview/common/aw_features.h
@@ -32,6 +32,7 @@
 BASE_DECLARE_FEATURE(kWebViewImageDrag);
 BASE_DECLARE_FEATURE(kWebViewInjectPlatformJsApis);
 BASE_DECLARE_FEATURE(kWebViewJavaJsBridgeMojo);
+BASE_DECLARE_FEATURE(kWebViewMediaIntegrityApi);
 BASE_DECLARE_FEATURE(kWebViewMetricsFiltering);
 BASE_DECLARE_FEATURE(kWebViewMixedContentAutoupgrades);
 BASE_DECLARE_FEATURE(kWebViewOriginTrials);
diff --git a/android_webview/common/metrics/app_package_name_logging_rule.cc b/android_webview/common/metrics/app_package_name_logging_rule.cc
index c4f2c1b1..db4ae5b 100644
--- a/android_webview/common/metrics/app_package_name_logging_rule.cc
+++ b/android_webview/common/metrics/app_package_name_logging_rule.cc
@@ -4,11 +4,11 @@
 
 #include "android_webview/common/metrics/app_package_name_logging_rule.h"
 
+#include <optional>
 #include "base/json/values_util.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "base/version.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace android_webview {
 
@@ -47,23 +47,22 @@
 }
 
 // static
-absl::optional<AppPackageNameLoggingRule>
+std::optional<AppPackageNameLoggingRule>
 AppPackageNameLoggingRule::FromDictionary(const base::Value::Dict& dict) {
   const std::string* version_string = dict.FindString(kVersionKey);
   if (!version_string) {
-    return absl::optional<AppPackageNameLoggingRule>();
+    return std::optional<AppPackageNameLoggingRule>();
   }
   base::Version version(*version_string);
   if (!version.IsValid()) {
-    return absl::optional<AppPackageNameLoggingRule>();
+    return std::optional<AppPackageNameLoggingRule>();
   }
 
   const base::Value* expiry_date_value = dict.Find(kExpiryDateKey);
   if (!expiry_date_value) {
     return AppPackageNameLoggingRule(version, base::Time::Min());
   }
-  absl::optional<base::Time> expiry_date =
-      base::ValueToTime(*expiry_date_value);
+  std::optional<base::Time> expiry_date = base::ValueToTime(*expiry_date_value);
   if (!expiry_date.has_value()) {
     return AppPackageNameLoggingRule(version, base::Time::Min());
   }
diff --git a/android_webview/common/metrics/app_package_name_logging_rule.h b/android_webview/common/metrics/app_package_name_logging_rule.h
index 900e7fe..8a2875e1 100644
--- a/android_webview/common/metrics/app_package_name_logging_rule.h
+++ b/android_webview/common/metrics/app_package_name_logging_rule.h
@@ -5,10 +5,10 @@
 #ifndef ANDROID_WEBVIEW_COMMON_METRICS_APP_PACKAGE_NAME_LOGGING_RULE_H_
 #define ANDROID_WEBVIEW_COMMON_METRICS_APP_PACKAGE_NAME_LOGGING_RULE_H_
 
+#include <optional>
 #include "base/time/time.h"
 #include "base/values.h"
 #include "base/version.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace android_webview {
 
@@ -41,7 +41,7 @@
 
   // Creates a valid AppPackageNameLoggingRule from a dictionary, or null if
   // the dictionary have invalid values.
-  static absl::optional<AppPackageNameLoggingRule> FromDictionary(
+  static std::optional<AppPackageNameLoggingRule> FromDictionary(
       const base::Value::Dict& dict);
 
  private:
diff --git a/android_webview/common/metrics/app_package_name_logging_rule_unittests.cc b/android_webview/common/metrics/app_package_name_logging_rule_unittests.cc
index 7886dbf..72207c0 100644
--- a/android_webview/common/metrics/app_package_name_logging_rule_unittests.cc
+++ b/android_webview/common/metrics/app_package_name_logging_rule_unittests.cc
@@ -4,10 +4,10 @@
 
 #include "android_webview/common/metrics/app_package_name_logging_rule.h"
 
+#include <optional>
 #include "base/time/time.h"
 #include "base/version.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace android_webview {
 
@@ -32,7 +32,7 @@
   base::Time one_day_from_now = base::Time::Now() + base::Days(1);
   {
     AppPackageNameLoggingRule expected_record(version, one_day_from_now);
-    absl::optional<AppPackageNameLoggingRule> record =
+    std::optional<AppPackageNameLoggingRule> record =
         AppPackageNameLoggingRule::FromDictionary(
             expected_record.ToDictionary());
     ASSERT_TRUE(record.has_value());
@@ -41,7 +41,7 @@
 
   {
     AppPackageNameLoggingRule expected_record(version, base::Time::Min());
-    absl::optional<AppPackageNameLoggingRule> record =
+    std::optional<AppPackageNameLoggingRule> record =
         AppPackageNameLoggingRule::FromDictionary(
             expected_record.ToDictionary());
     ASSERT_TRUE(record.has_value());
@@ -49,7 +49,7 @@
   }
 
   {
-    absl::optional<AppPackageNameLoggingRule> record =
+    std::optional<AppPackageNameLoggingRule> record =
         AppPackageNameLoggingRule::FromDictionary(base::Value::Dict());
     EXPECT_FALSE(record.has_value());
   }
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
index 06e0ebc..85319a42 100644
--- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -770,7 +770,11 @@
         Flag.baseFeature("V8MinorMS"),
         Flag.baseFeature(
                 AwFeatures.WEBVIEW_INJECT_PLATFORM_JS_APIS,
-                "Inject platform-specific Javascript APIs."),
+                "Inject platform-specific JavaScript APIs."),
+        Flag.baseFeature(
+                AwFeatures.WEBVIEW_MEDIA_INTEGRITY_API,
+                "Enable the WebView Media Integrity API. Requires injection of platform-specific"
+                        + " JavaScript APIs to be enabled."),
         Flag.baseFeature(
                 "PMProcessPriorityPolicy",
                 "Controls whether the priority of renderers is controlled by the performance "
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc
index 2bad87c..5d1e8bf 100644
--- a/android_webview/lib/aw_main_delegate.cc
+++ b/android_webview/lib/aw_main_delegate.cc
@@ -88,7 +88,7 @@
 
 AwMainDelegate::~AwMainDelegate() = default;
 
-absl::optional<int> AwMainDelegate::BasicStartupComplete() {
+std::optional<int> AwMainDelegate::BasicStartupComplete() {
   TRACE_EVENT0("startup", "AwMainDelegate::BasicStartupComplete");
   base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
 
@@ -313,7 +313,7 @@
   // renderer processes. See also: switches::kInProcessGPU above.
   content::ForceInProcessNetworkService();
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 void AwMainDelegate::PreSandboxStartup() {
@@ -394,7 +394,7 @@
       variations::VariationsIdsProvider::Mode::kDontSendSignedInVariations);
 }
 
-absl::optional<int> AwMainDelegate::PostEarlyInitialization(
+std::optional<int> AwMainDelegate::PostEarlyInitialization(
     InvokedIn invoked_in) {
   const bool is_browser_process =
       absl::holds_alternative<InvokedInBrowserProcess>(invoked_in);
@@ -406,7 +406,7 @@
 
   InitializeMemorySystem(is_browser_process);
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 content::ContentClient* AwMainDelegate::CreateContentClient() {
diff --git a/android_webview/lib/aw_main_delegate.h b/android_webview/lib/aw_main_delegate.h
index b2a41d7e1..693558cb 100644
--- a/android_webview/lib/aw_main_delegate.h
+++ b/android_webview/lib/aw_main_delegate.h
@@ -39,7 +39,7 @@
 
  private:
   // content::ContentMainDelegate implementation:
-  absl::optional<int> BasicStartupComplete() override;
+  std::optional<int> BasicStartupComplete() override;
   void PreSandboxStartup() override;
   absl::variant<int, content::MainFunctionParams> RunProcess(
       const std::string& process_type,
@@ -48,7 +48,7 @@
   bool ShouldCreateFeatureList(InvokedIn invoked_in) override;
   bool ShouldInitializeMojo(InvokedIn invoked_in) override;
   variations::VariationsIdsProvider* CreateVariationsIdsProvider() override;
-  absl::optional<int> PostEarlyInitialization(InvokedIn invoked_in) override;
+  std::optional<int> PostEarlyInitialization(InvokedIn invoked_in) override;
   content::ContentClient* CreateContentClient() override;
   content::ContentBrowserClient* CreateContentBrowserClient() override;
   content::ContentGpuClient* CreateContentGpuClient() override;
diff --git a/android_webview/nonembedded/component_updater/aw_component_update_service.cc b/android_webview/nonembedded/component_updater/aw_component_update_service.cc
index 3a764c5b..76889e9 100644
--- a/android_webview/nonembedded/component_updater/aw_component_update_service.cc
+++ b/android_webview/nonembedded/component_updater/aw_component_update_service.cc
@@ -191,7 +191,7 @@
   return crx;
 }
 
-absl::optional<component_updater::ComponentRegistration>
+std::optional<component_updater::ComponentRegistration>
 AwComponentUpdateService::GetComponent(const std::string& id) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return component_updater::GetComponent(components_, id);
@@ -200,16 +200,15 @@
 void AwComponentUpdateService::GetCrxComponents(
     const std::vector<std::string>& ids,
     base::OnceCallback<
-        void(const std::vector<absl::optional<update_client::CrxComponent>>&)>
+        void(const std::vector<std::optional<update_client::CrxComponent>>&)>
         callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  std::vector<absl::optional<update_client::CrxComponent>> crxs;
-  for (absl::optional<component_updater::ComponentRegistration> item :
+  std::vector<std::optional<update_client::CrxComponent>> crxs;
+  for (std::optional<component_updater::ComponentRegistration> item :
        component_updater::GetCrxComponents(components_, ids)) {
     crxs.push_back(
-        item
-            ? absl::optional<update_client::CrxComponent>{ToCrxComponent(*item)}
-            : absl::nullopt);
+        item ? std::optional<update_client::CrxComponent>{ToCrxComponent(*item)}
+             : std::nullopt);
   }
   std::move(callback).Run(crxs);
 }
diff --git a/android_webview/nonembedded/component_updater/aw_component_update_service.h b/android_webview/nonembedded/component_updater/aw_component_update_service.h
index babef45e..93aa24e 100644
--- a/android_webview/nonembedded/component_updater/aw_component_update_service.h
+++ b/android_webview/nonembedded/component_updater/aw_component_update_service.h
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/android/scoped_java_ref.h"
 #include "base/containers/flat_map.h"
 #include "base/functional/callback_forward.h"
@@ -19,7 +20,6 @@
 #include "base/sequence_checker.h"
 #include "components/update_client/update_client.h"
 #include "components/update_client/update_client_errors.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class TimeTicks;
@@ -75,12 +75,12 @@
                         update_client::Error error);
   update_client::CrxComponent ToCrxComponent(
       const component_updater::ComponentRegistration& component) const;
-  absl::optional<component_updater::ComponentRegistration> GetComponent(
+  std::optional<component_updater::ComponentRegistration> GetComponent(
       const std::string& id) const;
   void GetCrxComponents(
       const std::vector<std::string>& ids,
       base::OnceCallback<
-          void(const std::vector<absl::optional<update_client::CrxComponent>>&)>
+          void(const std::vector<std::optional<update_client::CrxComponent>>&)>
           callback);
   void ScheduleUpdatesOfRegisteredComponents(UpdateCallback on_finished_updates,
                                              bool on_demand_update);
diff --git a/android_webview/nonembedded/component_updater/aw_component_update_service_test.cc b/android_webview/nonembedded/component_updater/aw_component_update_service_test.cc
index bcfdca91..e3fa53c 100644
--- a/android_webview/nonembedded/component_updater/aw_component_update_service_test.cc
+++ b/android_webview/nonembedded/component_updater/aw_component_update_service_test.cc
@@ -10,6 +10,7 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "android_webview/common/aw_paths.h"
 #include "android_webview/nonembedded/component_updater/aw_component_updater_configurator.h"
 #include "base/android/path_utils.h"
@@ -32,7 +33,6 @@
 #include "components/update_client/network.h"
 #include "components/update_client/update_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace android_webview {
@@ -313,7 +313,7 @@
   base::Version GetVersion() const { return version_; }
 
  private:
-  absl::optional<base::Value::Dict> manifest_;
+  std::optional<base::Value::Dict> manifest_;
   base::FilePath install_dir_;
   base::Version version_;
 };
diff --git a/android_webview/nonembedded/component_updater/aw_component_updater_configurator.cc b/android_webview/nonembedded/component_updater/aw_component_updater_configurator.cc
index 9131e43f..48d54e5 100644
--- a/android_webview/nonembedded/component_updater/aw_component_updater_configurator.cc
+++ b/android_webview/nonembedded/component_updater/aw_component_updater_configurator.cc
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "android_webview/nonembedded/net/network_impl.h"
 #include "base/android/path_utils.h"
 #include "base/files/file_path.h"
@@ -29,7 +30,6 @@
 #include "components/version_info/android/channel_getter.h"
 #include "components/version_info/version_info.h"
 #include "components/version_info/version_info_values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace android_webview {
 
@@ -184,9 +184,9 @@
   return configurator_impl_.GetProtocolHandlerFactory();
 }
 
-absl::optional<bool>
-AwComponentUpdaterConfigurator::IsMachineExternallyManaged() const {
-  return absl::nullopt;
+std::optional<bool> AwComponentUpdaterConfigurator::IsMachineExternallyManaged()
+    const {
+  return std::nullopt;
 }
 
 update_client::UpdaterStateProvider
@@ -201,13 +201,13 @@
                                                               pref_service);
 }
 
-absl::optional<base::FilePath> AwComponentUpdaterConfigurator::GetCrxCachePath()
+std::optional<base::FilePath> AwComponentUpdaterConfigurator::GetCrxCachePath()
     const {
   base::FilePath path;
   return base::android::GetCacheDirectory(&path)
-             ? absl::optional<base::FilePath>(
+             ? std::optional<base::FilePath>(
                    path.AppendASCII(("webview_crx_cache")))
-             : absl::nullopt;
+             : std::nullopt;
 }
 
 }  // namespace android_webview
diff --git a/android_webview/nonembedded/component_updater/aw_component_updater_configurator.h b/android_webview/nonembedded/component_updater/aw_component_updater_configurator.h
index 6b96c89..8a7e3d8 100644
--- a/android_webview/nonembedded/component_updater/aw_component_updater_configurator.h
+++ b/android_webview/nonembedded/component_updater/aw_component_updater_configurator.h
@@ -5,6 +5,7 @@
 #ifndef ANDROID_WEBVIEW_NONEMBEDDED_COMPONENT_UPDATER_AW_COMPONENT_UPDATER_CONFIGURATOR_H_
 #define ANDROID_WEBVIEW_NONEMBEDDED_COMPONENT_UPDATER_AW_COMPONENT_UPDATER_CONFIGURATOR_H_
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
@@ -19,7 +20,6 @@
 #include "components/update_client/patcher.h"
 #include "components/update_client/protocol_handler.h"
 #include "components/update_client/unzipper.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class PrefService;
 
@@ -62,9 +62,9 @@
   bool IsPerUserInstall() const override;
   std::unique_ptr<update_client::ProtocolHandlerFactory>
   GetProtocolHandlerFactory() const override;
-  absl::optional<bool> IsMachineExternallyManaged() const override;
+  std::optional<bool> IsMachineExternallyManaged() const override;
   update_client::UpdaterStateProvider GetUpdaterStateProvider() const override;
-  absl::optional<base::FilePath> GetCrxCachePath() const override;
+  std::optional<base::FilePath> GetCrxCachePath() const override;
 
  protected:
   friend class base::RefCountedThreadSafe<AwComponentUpdaterConfigurator>;
diff --git a/android_webview/tools/cts_archive/3pp/install.sh b/android_webview/tools/cts_archive/3pp/install.sh
index f7a9b518..9a2ce775 100755
--- a/android_webview/tools/cts_archive/3pp/install.sh
+++ b/android_webview/tools/cts_archive/3pp/install.sh
@@ -279,6 +279,11 @@
 unzip -j "$IN_ZIPFILE" "android-cts/testcases/CtsMockInputMethod/arm64/CtsMockInputMethod.apk" -d "$UNZIP_DEST"
 unzip -j "$IN_ZIPFILE" "android-cts/testcases/CtsAutoFillServiceTestCases/arm64/CtsAutoFillServiceTestCases.apk" -d "$UNZIP_DEST"
 unzip -j "$IN_ZIPFILE" "android-cts/testcases/CtsTextTestCases/arm64/CtsTextTestCases.apk" -d "$UNZIP_DEST"
+# host-driven CTS separator for readability
+# TODO: b/267730567 - Unzip "android-cts/tools/*" after r6 release.
+unzip "$IN_ZIPFILE" "android-cts/testcases/CtsHostsideWebViewTests/*"
+unzip -j "$IN_ZIPFILE" "android-cts/testcases/CtsSecurityTestCases/CtsDeviceInfo.apk" -d "$UNZIP_DEST"
+unzip -j "$IN_ZIPFILE" "android-cts/testcases/CtsPreconditions/arm64/CtsPreconditions.apk" -d "$UNZIP_DEST"
 
 zip -rm "$TARGET_DIR/$OUT_ZIPFILE" android-cts
 
@@ -299,5 +304,10 @@
 unzip -j "$IN_ZIPFILE" "android-cts/testcases/CtsMockInputMethod/x86_64/CtsMockInputMethod.apk" -d "$UNZIP_DEST"
 unzip -j "$IN_ZIPFILE" "android-cts/testcases/CtsAutoFillServiceTestCases/x86_64/CtsAutoFillServiceTestCases.apk" -d "$UNZIP_DEST"
 unzip -j "$IN_ZIPFILE" "android-cts/testcases/CtsTextTestCases/x86_64/CtsTextTestCases.apk" -d "$UNZIP_DEST"
+# host-driven CTS separator for readability
+# TODO: b/267730567 - Unzip "android-cts/tools/*" after r6 release.
+unzip "$IN_ZIPFILE" "android-cts/testcases/CtsHostsideWebViewTests/*"
+unzip -j "$IN_ZIPFILE" "android-cts/testcases/CtsSecurityTestCases/CtsDeviceInfo.apk" -d "$UNZIP_DEST"
+unzip -j "$IN_ZIPFILE" "android-cts/testcases/CtsPreconditions/x86_64/CtsPreconditions.apk" -d "$UNZIP_DEST"
 
 zip -rm "$TARGET_DIR/$OUT_ZIPFILE" android-cts
diff --git a/apps/launcher.cc b/apps/launcher.cc
index d8b18e5..2701ae3 100644
--- a/apps/launcher.cc
+++ b/apps/launcher.cc
@@ -127,7 +127,7 @@
   PlatformAppPathLauncher(const PlatformAppPathLauncher&) = delete;
   PlatformAppPathLauncher& operator=(const PlatformAppPathLauncher&) = delete;
 
-  void set_action_data(absl::optional<app_runtime::ActionData> action_data) {
+  void set_action_data(std::optional<app_runtime::ActionData> action_data) {
     action_data_ = std::move(action_data);
   }
 
@@ -217,7 +217,7 @@
 
     // TODO(crbug.com/1354063): This conditional block is being added here
     // temporarily, and should be removed once the underlying type of
-    // |launch_data.action_data| is wrapped with absl::optional<T>.
+    // |launch_data.action_data| is wrapped with std::optional<T>.
     if (action_data_) {
       launch_data.action_data = std::move(*action_data_);
       action_data_.reset();
@@ -352,7 +352,7 @@
   const std::string extension_id;
   extensions::AppLaunchSource launch_source_ =
       extensions::AppLaunchSource::kSourceFileHandler;
-  absl::optional<app_runtime::ActionData> action_data_;
+  std::optional<app_runtime::ActionData> action_data_;
   // A list of files and directories to be passed through to the app.
   std::vector<base::FilePath> entry_paths_;
   // A corresponding list with EntryInfo for every base::FilePath in
@@ -505,7 +505,7 @@
   if (listening_to_launch && had_windows) {
     AppRuntimeEventRouter::DispatchOnLaunchedEvent(
         context, app, extensions::AppLaunchSource::kSourceRestart,
-        absl::nullopt);
+        std::nullopt);
   }
 }
 
diff --git a/apps/saved_files_service.cc b/apps/saved_files_service.cc
index 10fc8c4..5e535ba 100644
--- a/apps/saved_files_service.cc
+++ b/apps/saved_files_service.cc
@@ -12,6 +12,7 @@
 #include <unordered_map>
 #include <utility>
 
+#include <optional>
 #include "apps/saved_files_service_factory.h"
 #include "base/json/values_util.h"
 #include "base/memory/raw_ptr.h"
@@ -25,7 +26,6 @@
 #include "extensions/common/permissions/api_permission.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "extensions/common/permissions/permissions_data.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace apps {
 
@@ -105,7 +105,7 @@
 // Clears all SavedFileEntry for the app from ExtensionPrefs.
 void ClearSavedFileEntries(ExtensionPrefs* prefs,
                            const std::string& extension_id) {
-  prefs->UpdateExtensionPref(extension_id, kFileEntries, absl::nullopt);
+  prefs->UpdateExtensionPref(extension_id, kFileEntries, std::nullopt);
 }
 
 // Returns all SavedFileEntries for the app.
@@ -127,13 +127,13 @@
     const base::Value* path_value = file_entry->Find(kFileEntryPath);
     if (!path_value)
       continue;
-    absl::optional<base::FilePath> file_path =
+    std::optional<base::FilePath> file_path =
         base::ValueToFilePath(*path_value);
     if (!file_path)
       continue;
     bool is_directory =
         file_entry->FindBool(kFileEntryIsDirectory).value_or(false);
-    const absl::optional<int> sequence_number =
+    const std::optional<int> sequence_number =
         file_entry->FindInt(kFileEntrySequenceNumber);
     if (!sequence_number || sequence_number.value() == 0)
       continue;
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index c2dea6c8..4d75ec2 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -2257,7 +2257,7 @@
              base::FEATURE_ENABLED_BY_DEFAULT);
 
 // Controls whether to show promise icons during app installations.
-BASE_FEATURE(kPromiseIcons, "PromiseIcons", base::FEATURE_ENABLED_BY_DEFAULT);
+BASE_FEATURE(kPromiseIcons, "PromiseIcons", base::FEATURE_DISABLED_BY_DEFAULT);
 
 // Controls whether to show promise icons during web app installations.
 BASE_FEATURE(kPromiseIconsForWebApps,
diff --git a/ash/fast_ink/fast_ink_host_frame_utils_unittest.cc b/ash/fast_ink/fast_ink_host_frame_utils_unittest.cc
index b454e686..dc413be9 100644
--- a/ash/fast_ink/fast_ink_host_frame_utils_unittest.cc
+++ b/ash/fast_ink/fast_ink_host_frame_utils_unittest.cc
@@ -15,10 +15,13 @@
 #include "ash/test/ash_test_helper.h"
 #include "base/memory/raw_ptr.h"
 #include "cc/base/math_util.h"
+#include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/resources/resource_id.h"
 #include "components/viz/common/resources/shared_image_format_utils.h"
+#include "gpu/command_buffer/client/shared_image_interface.h"
+#include "gpu/command_buffer/common/shared_image_usage.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
@@ -36,7 +39,9 @@
 constexpr auto kTestContentRectInDIP = gfx::Rect(0, 0, 200, 100);
 constexpr auto kTestTotalDamageRectInDIP = gfx::Rect(0, 0, 50, 25);
 
-class FastInkHostCreateFrameUtilTest : public AshTestBase {
+class FastInkHostCreateFrameUtilTest
+    : public AshTestBase,
+      public ::testing::WithParamInterface<bool> {
  public:
   FastInkHostCreateFrameUtilTest() = default;
 
@@ -62,48 +67,72 @@
     // `host_window` is owned by the root_window and it will be deleted as
     // window hierarchy is deleted during Shell deletion.
     host_window_ = host_window.release();
-    gpu_memory_buffer_ = CreateGpuBufferForHostWindow(host_window_.get());
+    buffer_size_ = BufferSizeForHostWindow(host_window_.get());
+
+    bool mappable_si_enabled = GetParam();
+    if (mappable_si_enabled) {
+      mailbox_ = fast_ink_internal::CreateMappableSharedImage(
+          buffer_size_,
+          gpu::SHARED_IMAGE_USAGE_DISPLAY_READ |
+              gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE |
+              gpu::SHARED_IMAGE_USAGE_SCANOUT,
+          gfx::BufferUsage::SCANOUT_CPU_READ_WRITE);
+      ASSERT_FALSE(mailbox_.IsZero());
+    } else {
+      gpu_memory_buffer_ = CreateGpuBufferForHostWindow(host_window_.get());
+    }
   }
 
   // AshTestBase:
   void TearDown() override {
+    if (!mailbox_.IsZero()) {
+      shared_image_interface()->DestroySharedImage(gpu::SyncToken(), mailbox_);
+    }
     resource_manager_.ClearAvailableResources();
     resource_manager_.LostExportedResources();
     AshTestBase::TearDown();
   }
 
  protected:
+  const gfx::Size BufferSizeForHostWindow(aura::Window* host_window) {
+    const gfx::Transform& window_to_buffer_transform =
+        host_window->GetHost()->GetRootTransform();
+    gfx::Rect bounds(host_window->GetBoundsInScreen().size());
+
+    return cc::MathUtil::MapEnclosingClippedRect(window_to_buffer_transform,
+                                                 bounds)
+        .size();
+  }
+
   // Creates a GPU buffer that is the same size as the `host_window`. The root
   // transform is applied as the buffer size is calculated. Please see
   // `FastInkHost::InitializeFastInkBuffer()` for more details.
   std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuBufferForHostWindow(
       aura::Window* host_window) {
-    const gfx::Transform& window_to_buffer_transform =
-        host_window->GetHost()->GetRootTransform();
-    gfx::Rect bounds(host_window->GetBoundsInScreen().size());
-
-    const gfx::Size buffer_size = cc::MathUtil::MapEnclosingClippedRect(
-                                      window_to_buffer_transform, bounds)
-                                      .size();
-
     return fast_ink_internal::CreateGpuBuffer(
-        buffer_size, gfx::BufferUsageAndFormat(
-                         gfx::BufferUsage::SCANOUT_CPU_READ_WRITE,
-                         viz::SinglePlaneSharedImageFormatToBufferFormat(
-                             fast_ink_internal::kFastInkSharedImageFormat)));
+        buffer_size_, gfx::BufferUsageAndFormat(
+                          gfx::BufferUsage::SCANOUT_CPU_READ_WRITE,
+                          viz::SinglePlaneSharedImageFormatToBufferFormat(
+                              fast_ink_internal::kFastInkSharedImageFormat)));
+  }
+
+  gpu::SharedImageInterface* shared_image_interface() {
+    return fast_ink_internal::GetContextProvider()->SharedImageInterface();
   }
 
   UiResourceManager resource_manager_;
   raw_ptr<aura::Window, DanglingUntriaged> host_window_;
   std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_;
+  gpu::Mailbox mailbox_;
+  gfx::Size buffer_size_;
 };
 
-TEST_F(FastInkHostCreateFrameUtilTest, HasValidSourceId) {
+TEST_P(FastInkHostCreateFrameUtilTest, HasValidSourceId) {
   auto frame = fast_ink_internal::CreateCompositorFrame(
       viz::BeginFrameAck::CreateManualAckWithDamage(), kTestContentRectInDIP,
       kTestTotalDamageRectInDIP, /*auto_update=*/true, *host_window_,
-      gpu_memory_buffer_->GetSize(), gpu_memory_buffer_.get(),
-      &resource_manager_, gpu::Mailbox(), gpu::SyncToken());
+      buffer_size_, gpu_memory_buffer_.get(), &resource_manager_, mailbox_,
+      gpu::SyncToken());
 
   ASSERT_EQ(frame->resource_list.size(), 1u);
   viz::ResourceId resource_id = frame->resource_list.back().id;
@@ -112,12 +141,31 @@
             kInvalidUiSourceId);
 }
 
-TEST_F(FastInkHostCreateFrameUtilTest, CompositorFrameHasCorrectStructure) {
+TEST_P(FastInkHostCreateFrameUtilTest,
+       ResourceUsesMailboxIfNonZeroAndCreatesMailboxOtherwise) {
   auto frame = fast_ink_internal::CreateCompositorFrame(
       viz::BeginFrameAck::CreateManualAckWithDamage(), kTestContentRectInDIP,
       kTestTotalDamageRectInDIP, /*auto_update=*/true, *host_window_,
-      gpu_memory_buffer_->GetSize(), gpu_memory_buffer_.get(),
-      &resource_manager_, gpu::Mailbox(), gpu::SyncToken());
+      buffer_size_, gpu_memory_buffer_.get(), &resource_manager_, mailbox_,
+      gpu::SyncToken());
+
+  ASSERT_EQ(frame->resource_list.size(), 1u);
+  viz::ResourceId resource_id = frame->resource_list.back().id;
+
+  auto* resource = resource_manager_.PeekExportedResource(resource_id);
+  EXPECT_NE(resource->ui_source_id, kInvalidUiSourceId);
+  EXPECT_FALSE(resource->mailbox().IsZero());
+  if (!mailbox_.IsZero()) {
+    EXPECT_EQ(resource->mailbox(), mailbox_);
+  }
+}
+
+TEST_P(FastInkHostCreateFrameUtilTest, CompositorFrameHasCorrectStructure) {
+  auto frame = fast_ink_internal::CreateCompositorFrame(
+      viz::BeginFrameAck::CreateManualAckWithDamage(), kTestContentRectInDIP,
+      kTestTotalDamageRectInDIP, /*auto_update=*/true, *host_window_,
+      buffer_size_, gpu_memory_buffer_.get(), &resource_manager_, mailbox_,
+      gpu::SyncToken());
 
   auto primary_display = display::Screen::GetScreen()->GetPrimaryDisplay();
 
@@ -140,12 +188,12 @@
             primary_display.device_scale_factor());
 }
 
-TEST_F(FastInkHostCreateFrameUtilTest, FrameDamage_AutoModeOff) {
+TEST_P(FastInkHostCreateFrameUtilTest, FrameDamage_AutoModeOff) {
   auto frame = fast_ink_internal::CreateCompositorFrame(
       viz::BeginFrameAck::CreateManualAckWithDamage(), kTestContentRectInDIP,
       kTestTotalDamageRectInDIP, /*auto_update=*/false, *host_window_,
-      gpu_memory_buffer_->GetSize(), gpu_memory_buffer_.get(),
-      &resource_manager_, gpu::Mailbox(), gpu::SyncToken());
+      buffer_size_, gpu_memory_buffer_.get(), &resource_manager_, mailbox_,
+      gpu::SyncToken());
 
   EXPECT_EQ(frame->render_pass_list.front()->damage_rect,
             gfx::Rect(0, 0, 100, 50));
@@ -155,19 +203,19 @@
   frame = fast_ink_internal::CreateCompositorFrame(
       viz::BeginFrameAck::CreateManualAckWithDamage(), kTestContentRectInDIP,
       gfx::Rect(0, 0, 501, 100), /*auto_update=*/false, *host_window_,
-      gpu_memory_buffer_->GetSize(), gpu_memory_buffer_.get(),
-      &resource_manager_, gpu::Mailbox(), gpu::SyncToken());
+      buffer_size_, gpu_memory_buffer_.get(), &resource_manager_, mailbox_,
+      gpu::SyncToken());
 
   EXPECT_EQ(frame->render_pass_list.front()->damage_rect,
             gfx::Rect(0, 0, 1000, 200));
 }
 
-TEST_F(FastInkHostCreateFrameUtilTest, FrameDamage_AutoModeOn) {
+TEST_P(FastInkHostCreateFrameUtilTest, FrameDamage_AutoModeOn) {
   auto frame = fast_ink_internal::CreateCompositorFrame(
       viz::BeginFrameAck::CreateManualAckWithDamage(), kTestContentRectInDIP,
       kTestTotalDamageRectInDIP, /*auto_update=*/true, *host_window_,
-      gpu_memory_buffer_->GetSize(), gpu_memory_buffer_.get(),
-      &resource_manager_, gpu::Mailbox(), gpu::SyncToken());
+      buffer_size_, gpu_memory_buffer_.get(), &resource_manager_, mailbox_,
+      gpu::SyncToken());
 
   // In auto update mode, we damage the full output rect, regardless of the
   // specified total_damage_rect.
@@ -175,15 +223,15 @@
             gfx::Rect(frame->size_in_pixels()));
 }
 
-TEST_F(FastInkHostCreateFrameUtilTest, OnlyCreateNewResourcesWhenNecessary) {
+TEST_P(FastInkHostCreateFrameUtilTest, OnlyCreateNewResourcesWhenNecessary) {
   // Populate resources in the resource manager.
   constexpr gfx::Size kResourceSizes[4] = {
       {1000, 404}, {1000, 404}, {250, 150}, {50, 25}};
   for (const auto& size : kResourceSizes) {
     resource_manager_.OfferResource(fast_ink_internal::CreateUiResource(
         size, fast_ink_internal::kFastInkUiSourceId,
-        /*is_overlay_candidate=*/false, gpu_memory_buffer_.get(),
-        gpu::Mailbox(), gpu::SyncToken()));
+        /*is_overlay_candidate=*/false, gpu_memory_buffer_.get(), mailbox_,
+        gpu::SyncToken()));
   }
 
   EXPECT_EQ(resource_manager_.available_resources_count(), 4u);
@@ -191,8 +239,8 @@
   auto frame = fast_ink_internal::CreateCompositorFrame(
       viz::BeginFrameAck::CreateManualAckWithDamage(), kTestContentRectInDIP,
       kTestTotalDamageRectInDIP, /*auto_update=*/true, *host_window_,
-      gpu_memory_buffer_->GetSize(), gpu_memory_buffer_.get(),
-      &resource_manager_, gpu::Mailbox(), gpu::SyncToken());
+      buffer_size_, gpu_memory_buffer_.get(), &resource_manager_, mailbox_,
+      gpu::SyncToken());
 
   // We reuse one of the matching available resources.
   EXPECT_EQ(resource_manager_.available_resources_count(), 3u);
@@ -201,8 +249,8 @@
   frame = fast_ink_internal::CreateCompositorFrame(
       viz::BeginFrameAck::CreateManualAckWithDamage(), kTestContentRectInDIP,
       kTestTotalDamageRectInDIP, /*auto_update=*/true, *host_window_,
-      gpu_memory_buffer_->GetSize(), gpu_memory_buffer_.get(),
-      &resource_manager_, gpu::Mailbox(), gpu::SyncToken());
+      buffer_size_, gpu_memory_buffer_.get(), &resource_manager_, mailbox_,
+      gpu::SyncToken());
 
   // We again reuse one of the matching available resources.
   EXPECT_EQ(resource_manager_.available_resources_count(), 2u);
@@ -211,8 +259,8 @@
   frame = fast_ink_internal::CreateCompositorFrame(
       viz::BeginFrameAck::CreateManualAckWithDamage(), kTestContentRectInDIP,
       kTestTotalDamageRectInDIP, /*auto_update=*/true, *host_window_,
-      gpu_memory_buffer_->GetSize(), gpu_memory_buffer_.get(),
-      &resource_manager_, gpu::Mailbox(), gpu::SyncToken());
+      buffer_size_, gpu_memory_buffer_.get(), &resource_manager_, mailbox_,
+      gpu::SyncToken());
 
   // Now the factory create a new resource since any available resource does not
   // match our requirements. The total number of resources in the manager has
@@ -221,5 +269,8 @@
   EXPECT_EQ(resource_manager_.exported_resources_count(), 3u);
 }
 
+INSTANTIATE_TEST_SUITE_P(MappableSIEnabled,
+                         FastInkHostCreateFrameUtilTest,
+                         testing::Bool());
 }  // namespace
 }  // namespace ash
diff --git a/ash/public/cpp/scale_utility.cc b/ash/public/cpp/scale_utility.cc
index e55a0f4..d1672f3 100644
--- a/ash/public/cpp/scale_utility.cc
+++ b/ash/public/cpp/scale_utility.cc
@@ -10,8 +10,9 @@
 namespace ash {
 
 float GetScaleFactorForTransform(const gfx::Transform& transform) {
-  if (absl::optional<gfx::DecomposedTransform> decomp = transform.Decompose())
+  if (std::optional<gfx::DecomposedTransform> decomp = transform.Decompose()) {
     return decomp->scale[0];
+  }
   return 1.0f;
 }
 
diff --git a/ash/public/cpp/system_notification_builder.h b/ash/public/cpp/system_notification_builder.h
index 0ddb7357..b3df262 100644
--- a/ash/public/cpp/system_notification_builder.h
+++ b/ash/public/cpp/system_notification_builder.h
@@ -6,6 +6,7 @@
 #define ASH_PUBLIC_CPP_SYSTEM_NOTIFICATION_BUILDER_H_
 
 #include <memory>
+#include <optional>
 #include <string>
 
 #include "ash/constants/notifier_catalogs.h"
@@ -262,7 +263,7 @@
   std::unique_ptr<message_center::Notification> BuildPtr(bool keep_timestamp);
 
   // Get a NotifierId by combining `catalog_name_` and `id_` if `notifier_id_`
-  // is `absl::nullopt`, otherwise returns the value of `notifier_id_`.
+  // is `std::nullopt`, otherwise returns the value of `notifier_id_`.
   // The `notifier_id_` should never be read directly but only through this
   // method.
   message_center::NotifierId GetNotifierId() const;
@@ -275,7 +276,7 @@
   std::u16string message_;
   std::u16string display_source_;
   GURL origin_url_;
-  absl::optional<message_center::NotifierId> notifier_id_;
+  std::optional<message_center::NotifierId> notifier_id_;
   NotificationCatalogName catalog_name_ = NotificationCatalogName::kNone;
   scoped_refptr<message_center::NotificationDelegate> delegate_ = nullptr;
   raw_ptr<const gfx::VectorIcon, ExperimentalAsh> small_image_ =
diff --git a/ash/shell.cc b/ash/shell.cc
index 954008e4..7b7e5bb 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -1298,7 +1298,7 @@
   // `ScheduledFeature` ctor will access `geolocation_controller_` from
   // `Shell`.
   geolocation_controller_ = std::make_unique<GeolocationController>(
-      shell_delegate_->GetGeolocationUrlLoaderFactory());
+      SimpleGeolocationProvider::GetInstance());
 
   // Night Light depends on the display manager, the display color manager,
   // aura::Env, and geolocation controller, so initialize it after all have
diff --git a/ash/system/geolocation/geolocation_controller.cc b/ash/system/geolocation/geolocation_controller.cc
index 7fb2c46..7192efa0 100644
--- a/ash/system/geolocation/geolocation_controller.cc
+++ b/ash/system/geolocation/geolocation_controller.cc
@@ -11,6 +11,7 @@
 #include "ash/shell.h"
 #include "ash/system/privacy_hub/privacy_hub_controller.h"
 #include "ash/system/time/time_of_day.h"
+#include "base/check_is_test.h"
 #include "base/functional/bind.h"
 #include "base/logging.h"
 #include "base/time/clock.h"
@@ -45,14 +46,14 @@
 }  // namespace
 
 GeolocationController::GeolocationController(
-    scoped_refptr<network::SharedURLLoaderFactory> factory)
-    : simple_geolocation_provider_(std::make_unique<SimpleGeolocationProvider>(
-          this,
-          std::move(factory),
-          SimpleGeolocationProvider::DefaultGeolocationProviderURL())),
+    SimpleGeolocationProvider* const geolocation_provider)
+    : geolocation_provider_(geolocation_provider),
       backoff_delay_(kMinimumDelayAfterFailure),
       timer_(std::make_unique<base::OneShotTimer>()),
       scoped_session_observer_(this) {
+  // Subscribe to geolocation changes.
+  geolocation_provider_->AddObserver(this);
+
   auto* timezone_settings = system::TimezoneSettings::GetInstance();
   current_timezone_id_ = timezone_settings->GetCurrentTimezoneID();
   timezone_settings->AddObserver(this);
@@ -62,6 +63,8 @@
 GeolocationController::~GeolocationController() {
   system::TimezoneSettings::GetInstance()->RemoveObserver(this);
   chromeos::PowerManagerClient::Get()->RemoveObserver(this);
+  geolocation_provider_->RemoveObserver(this);
+  geolocation_provider_ = nullptr;
 }
 
 // static
@@ -81,7 +84,7 @@
 void GeolocationController::AddObserver(Observer* observer) {
   const bool is_first_observer = observers_.empty();
   observers_.AddObserver(observer);
-  if (is_first_observer && IsSystemGeolocationAllowed()) {
+  if (is_first_observer && geolocation_provider_->IsGeolocationUsageAllowed()) {
     ScheduleNextRequest(base::Seconds(0));
   }
 }
@@ -93,6 +96,20 @@
   }
 }
 
+void GeolocationController::OnGeolocationPermissionChanged(bool enabled) {
+  // Drop all pending requests when system geolocation access is denied.
+  if (!enabled) {
+    timer_->Stop();
+    return;
+  }
+
+  // System geolocation access was granted, only resume scheduling when clients
+  // are present. Post an immediate geolocation request.
+  if (!observers_.empty()) {
+    ScheduleNextRequest(base::Seconds(0));
+  }
+}
+
 void GeolocationController::TimezoneChanged(const icu::TimeZone& timezone) {
   const std::u16string timezone_id =
       system::TimezoneSettings::GetTimezoneID(timezone);
@@ -104,35 +121,18 @@
 
   // On timezone changes, request an immediate geoposition if the system
   // geolocation allows.
-  if (IsSystemGeolocationAllowed()) {
+  if (geolocation_provider_->IsGeolocationUsageAllowed()) {
     ScheduleNextRequest(base::Seconds(0));
   }
 }
 
 void GeolocationController::SuspendDone(base::TimeDelta sleep_duration) {
-  if (sleep_duration >= kNextRequestDelayAfterSuccess) {
+  if (sleep_duration >= kNextRequestDelayAfterSuccess &&
+      geolocation_provider_->IsGeolocationUsageAllowed()) {
     ScheduleNextRequest(base::Seconds(0));
   }
 }
 
-bool GeolocationController::IsSystemGeolocationAllowed() const {
-  // TODO(b/276715041): Refactor the `SimpleGeolocationProvider` class to
-  // eliminate the `Shell`-dependency of this class.
-  Shell* const shell = Shell::Get();
-  const PrefService* primary_user_prefs =
-      shell->session_controller()->GetPrimaryUserPrefService();
-
-  // Follow device preference on log-in screen.
-  if (!primary_user_prefs) {
-    return shell->local_state()->GetInteger(
-               ash::prefs::kDeviceGeolocationAllowed) ==
-           static_cast<int>(PrivacyHubController::AccessLevel::kAllowed);
-  }
-
-  // Inside user session check geolocation user preference.
-  return primary_user_prefs->GetBoolean(ash::prefs::kUserGeolocationAllowed);
-}
-
 void GeolocationController::OnActiveUserPrefServiceChanged(
     PrefService* pref_service) {
   if (pref_service == active_user_pref_service_.get()) {
@@ -143,67 +143,49 @@
   LoadCachedGeopositionIfNeeded();
 }
 
-void GeolocationController::OnSystemGeolocationPermissionChanged(bool enabled) {
-  // Drop all pending requests when system geolocation is toggled OFF.
-  if (!enabled) {
-    timer_->Stop();
-    return;
-  }
-
-  // System geolocation toggled ON, post an immediate new geolocation request to
-  // resume continuous scheduling.
-  ScheduleNextRequest(base::Seconds(0));
-}
-
 // static
 base::TimeDelta
 GeolocationController::GetNextRequestDelayAfterSuccessForTesting() {
-  return kNextRequestDelayAfterSuccess;  // IN-TEST
-}
-
-network::SharedURLLoaderFactory*
-GeolocationController::GetSharedURLLoaderFactoryForTesting() {
-  return simple_geolocation_provider_
-      ->GetSharedURLLoaderFactoryForTesting();  // IN-TEST
+  CHECK_IS_TEST();
+  return kNextRequestDelayAfterSuccess;
 }
 
 void GeolocationController::SetTimerForTesting(
     std::unique_ptr<base::OneShotTimer> timer) {
-  timer_ = std::move(timer);  // IN-TEST
+  CHECK_IS_TEST();
+  timer_ = std::move(timer);
 }
 
 void GeolocationController::SetClockForTesting(base::Clock* clock) {
-  clock_ = clock;  // IN-TEST
+  CHECK_IS_TEST();
+  clock_ = clock;
 }
 
 void GeolocationController::SetLocalTimeConverterForTesting(
     const LocalTimeConverter* local_time_converter) {
-  local_time_converter_ = local_time_converter;  // IN-TEST
-}
-
-void GeolocationController::SetGeolocationProviderForTesting(
-    std::unique_ptr<SimpleGeolocationProvider> simple_geolocation_provider) {
-  simple_geolocation_provider_ = std::move(simple_geolocation_provider);
-  // Immediately schedule a new request to receive a geoposition event.
-  RequestImmediateGeopositionForTesting();  // IN-TEST
+  CHECK_IS_TEST();
+  local_time_converter_ = local_time_converter;
 }
 
 void GeolocationController::SetCurrentTimezoneIdForTesting(
     const std::u16string& timezone_id) {
-  current_timezone_id_ = timezone_id;  // IN-TEST
+  CHECK_IS_TEST();
+  current_timezone_id_ = timezone_id;
 }
 
 void GeolocationController::RequestImmediateGeopositionForTesting() {
-  ScheduleNextRequest(base::Seconds(0));  // IN-TEST
+  CHECK_IS_TEST();
+  ScheduleNextRequest(base::Seconds(0));
 }
 
 void GeolocationController::OnGeoposition(const Geoposition& position,
                                           bool server_error,
                                           const base::TimeDelta elapsed) {
-  if (!IsSystemGeolocationAllowed() || observers_.empty()) {
+  if (!geolocation_provider_->IsGeolocationUsageAllowed() ||
+      observers_.empty()) {
     // The request might come after the user disabled the system geolocation
     // access or if all observers unsubscribed, in which case we should stop
-    // processing the geolocation responses.
+    // processing the geolocation responses and stop scheduling new requests.
     return;
   }
 
@@ -268,13 +250,7 @@
 }
 
 void GeolocationController::ScheduleNextRequest(base::TimeDelta delay) {
-  // Drop all pending geolocation requests while system permission is
-  // denied. Toggling system geolocation ON will trigger a fresh geolocation
-  // request.
-  if (!IsSystemGeolocationAllowed()) {
-    return;
-  }
-
+  CHECK(geolocation_provider_->IsGeolocationUsageAllowed());
   timer_->Start(FROM_HERE, delay, this,
                 &GeolocationController::RequestGeoposition);
 }
@@ -288,11 +264,11 @@
 
 void GeolocationController::RequestGeoposition() {
   VLOG(1) << "Requesting a new geoposition";
-  simple_geolocation_provider_->RequestGeolocation(
+  geolocation_provider_->RequestGeolocation(
       kGeolocationRequestTimeout, /*send_wifi_access_points=*/false,
       /*send_cell_towers=*/false,
       base::BindOnce(&GeolocationController::OnGeoposition,
-                     base::Unretained(this)));
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 base::expected<base::Time, GeolocationController::SunRiseSetError>
diff --git a/ash/system/geolocation/geolocation_controller.h b/ash/system/geolocation/geolocation_controller.h
index d25176ba..a248016f 100644
--- a/ash/system/geolocation/geolocation_controller.h
+++ b/ash/system/geolocation/geolocation_controller.h
@@ -11,6 +11,7 @@
 #include "ash/ash_export.h"
 #include "ash/public/cpp/session/session_observer.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
 #include "base/time/time.h"
@@ -19,7 +20,6 @@
 #include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
 #include "chromeos/ash/components/settings/timezone_settings.h"
 #include "chromeos/dbus/power/power_manager_client.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 class PrefChangeRegistrar;
 class PrefRegistrySimple;
@@ -55,10 +55,10 @@
 // TODO(crbug.com/1272178): `GeolocationController` should observe the sleep
 // and update next request time.
 class ASH_EXPORT GeolocationController
-    : public system::TimezoneSettings::Observer,
+    : public SimpleGeolocationProvider::Observer,
+      public system::TimezoneSettings::Observer,
       public chromeos::PowerManagerClient::Observer,
-      public SessionObserver,
-      public SimpleGeolocationProvider::Delegate {
+      public SessionObserver {
  public:
   // Possible errors for `GetSunsetTime()` and `GetSunriseTime()`.
   enum class SunRiseSetError {
@@ -87,8 +87,7 @@
     ~Observer() override = default;
   };
 
-  explicit GeolocationController(
-      scoped_refptr<network::SharedURLLoaderFactory> factory);
+  explicit GeolocationController(SimpleGeolocationProvider* const provider);
   GeolocationController(const GeolocationController&) = delete;
   GeolocationController& operator=(const GeolocationController&) = delete;
   ~GeolocationController() override;
@@ -96,12 +95,6 @@
   static GeolocationController* Get();
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
 
-  // This class should respect the system geolocation permission. When the
-  // permission is disabled, no requests should be dispatched and no responses
-  // processed.
-  // Called from `ash::Preferences::ApplyPreferences()`.
-  void OnSystemGeolocationPermissionChanged(bool enabled);
-
   const base::OneShotTimer& timer() const { return *timer_; }
 
   const std::u16string& current_timezone_id() const {
@@ -111,15 +104,15 @@
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
 
+  // SimpleGeolocationProvider::Observer:
+  void OnGeolocationPermissionChanged(bool enabled) override;
+
   // system::TimezoneSettings::Observer:
   void TimezoneChanged(const icu::TimeZone& timezone) override;
 
   // chromeos::PowerManagerClient::Observer:
   void SuspendDone(base::TimeDelta sleep_duration) override;
 
-  // SimpleGeolocationProvider::Delegate:
-  bool IsSystemGeolocationAllowed() const override;
-
   // SessionObserver:
   void OnActiveUserPrefServiceChanged(PrefService* pref_service) override;
 
@@ -135,8 +128,6 @@
 
   static base::TimeDelta GetNextRequestDelayAfterSuccessForTesting();
 
-  network::SharedURLLoaderFactory* GetSharedURLLoaderFactoryForTesting();
-
   base::OneShotTimer* GetTimerForTesting() { return timer_.get(); }
 
   bool HasObserver(const Observer* obs) const {
@@ -148,8 +139,6 @@
   void SetClockForTesting(base::Clock* clock);
   void SetLocalTimeConverterForTesting(
       const LocalTimeConverter* local_time_converter);
-  void SetGeolocationProviderForTesting(
-      std::unique_ptr<SimpleGeolocationProvider> geolocation_provider);
   void SetCurrentTimezoneIdForTesting(const std::u16string& timezone_id);
   // Resets the running `timer_` and issues an immediate geoposition request.
   // Any responses on the fly will be processed first, but will be overridden
@@ -194,13 +183,14 @@
   // being able to retrieve a valid geoposition.
   void StoreCachedGeoposition() const;
 
+  // Points to the `SimpleGeolocationProvider::GetInstance()` throughout the
+  // object lifecycle. Overridden in unit tests.
+  raw_ptr<SimpleGeolocationProvider> geolocation_provider_ = nullptr;
+
   // May be null if a user has not logged in yet.
   raw_ptr<PrefService> active_user_pref_service_ = nullptr;
   std::unique_ptr<PrefChangeRegistrar> registrar_;
 
-  // The IP-based geolocation provider.
-  std::unique_ptr<SimpleGeolocationProvider> simple_geolocation_provider_;
-
   // Delay after which a new request is retried after a failed one.
   base::TimeDelta backoff_delay_;
 
@@ -229,6 +219,8 @@
   std::unique_ptr<SimpleGeoposition> geoposition_;
 
   ScopedSessionObserver scoped_session_observer_;
+
+  base::WeakPtrFactory<GeolocationController> weak_ptr_factory_{this};
 };
 
 }  // namespace ash
diff --git a/ash/system/geolocation/geolocation_controller_unittest.cc b/ash/system/geolocation/geolocation_controller_unittest.cc
index c23fcf8d..c2aad3927 100644
--- a/ash/system/geolocation/geolocation_controller_unittest.cc
+++ b/ash/system/geolocation/geolocation_controller_unittest.cc
@@ -22,6 +22,7 @@
 #include "base/time/clock.h"
 #include "base/time/time.h"
 #include "base/timer/mock_timer.h"
+#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/prefs/pref_service.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -85,8 +86,8 @@
 class FakeGeolocationController : public GeolocationController {
  public:
   explicit FakeGeolocationController(
-      scoped_refptr<network::SharedURLLoaderFactory> factory)
-      : GeolocationController(factory) {}
+      SimpleGeolocationProvider* geolocation_provider)
+      : GeolocationController(geolocation_provider) {}
 
   // Proxy method to call the `OnGeoposition()` callback directly, without
   // waiting for the server response. Need this to test scheduler behavior.
@@ -120,9 +121,9 @@
   void SetUp() override {
     AshTestBase::SetUp();
     CreateTestUserSessions();
+    // `SimpleGeolocationProvider` is initialized by `AshTestHelper`.
     controller_ = std::make_unique<FakeGeolocationController>(
-        static_cast<scoped_refptr<network::SharedURLLoaderFactory>>(
-            base::MakeRefCounted<TestGeolocationUrlLoaderFactory>()));
+        SimpleGeolocationProvider::GetInstance());
 
     test_clock_.SetNow(base::Time::Now());
     controller_->SetClockForTesting(&test_clock_);
@@ -188,15 +189,18 @@
   void SetServerPosition(const Geoposition& position) {
     position_ = position;
     auto* factory = static_cast<TestGeolocationUrlLoaderFactory*>(
-        controller_->GetSharedURLLoaderFactoryForTesting());
+        SimpleGeolocationProvider::GetInstance()
+            ->GetSharedURLLoaderFactoryForTesting());
     factory->ClearResponses();
     factory->set_position(position_);
   }
 
   void UpdateUserGeolocationPermission(bool enabled) {
-    PrefService* pref_service =
-        Shell::Get()->session_controller()->GetPrimaryUserPrefService();
-    pref_service->SetBoolean(ash::prefs::kUserGeolocationAllowed, enabled);
+    if (enabled) {
+      SimpleGeolocationProvider::GetInstance()->AllowGeolocationUsage();
+    } else {
+      SimpleGeolocationProvider::GetInstance()->DisallowGeolocationUsage();
+    }
   }
 
  private:
@@ -330,11 +334,11 @@
   EXPECT_TRUE(timer_ptr()->IsRunning());
 
   // Disable system geo permission. Scheduling should stop.
-  controller()->OnSystemGeolocationPermissionChanged(false);
+  UpdateUserGeolocationPermission(false);
   EXPECT_FALSE(timer_ptr()->IsRunning());
 
   // Re-enabling the system geo permission, should resume scheduling.
-  controller()->OnSystemGeolocationPermissionChanged(true);
+  UpdateUserGeolocationPermission(true);
   EXPECT_TRUE(timer_ptr()->IsRunning());
 }
 
@@ -351,18 +355,18 @@
 
   // Disable user geolocation permission, this should stop scheduling.
   UpdateUserGeolocationPermission(false);
-  controller()->OnSystemGeolocationPermissionChanged(false);
   EXPECT_FALSE(timer_ptr()->IsRunning());
 
-  // Simulate server response and check it didn't trigger scheduling to
-  // continue.
+  // Simulate server response and check it didn't resume scheduling.
   controller()->ImitateGeopositionReceived();
   EXPECT_FALSE(timer_ptr()->IsRunning());
 
   // Re-enable user geolocation permission, this should resume scheduling.
   UpdateUserGeolocationPermission(true);
-  controller()->OnSystemGeolocationPermissionChanged(true);
   EXPECT_TRUE(timer_ptr()->IsRunning());
+
+  // Unsubscribe the observer before being destroyed.
+  controller()->RemoveObserver(&observer);
 }
 
 TEST_F(GeolocationControllerTest, StopSchedulingWhenObserverListIsEmpty) {
@@ -385,6 +389,9 @@
   // Add the observer back, scheduling should resume.
   controller()->AddObserver(&observer);
   EXPECT_TRUE(timer_ptr()->IsRunning());
+
+  // Unsubscribe the observer before being destroyed.
+  controller()->RemoveObserver(&observer);
 }
 
 // Tests obtaining sunset/sunrise time when there is no valid geoposition, for
diff --git a/ash/system/night_light/night_light_controller_unittest.cc b/ash/system/night_light/night_light_controller_unittest.cc
index 04ad427..116b54e 100644
--- a/ash/system/night_light/night_light_controller_unittest.cc
+++ b/ash/system/night_light/night_light_controller_unittest.cc
@@ -219,10 +219,10 @@
     // Start with ambient color pref disabled.
     SetAmbientColorPrefEnabled(false);
 
-    geolocation_controller()->SetGeolocationProviderForTesting(
-        std::make_unique<SimpleGeolocationProvider>(
-            geolocation_controller(), geolocation_url_loader_factory_,
-            SimpleGeolocationProvider::DefaultGeolocationProviderURL()));
+    // `GeolocationController` uses `SimpleGeolocationProvider` singleton
+    // instance, which is initialized by `AshTestHelper`.
+    SimpleGeolocationProvider::GetInstance()
+        ->SetSharedUrlLoaderFactoryForTesting(geolocation_url_loader_factory_);
   }
 
   void CreateTestUserSessions() {
diff --git a/ash/system/scheduled_feature/scheduled_feature_unittest.cc b/ash/system/scheduled_feature/scheduled_feature_unittest.cc
index 0a5ff452..adacf39 100644
--- a/ash/system/scheduled_feature/scheduled_feature_unittest.cc
+++ b/ash/system/scheduled_feature/scheduled_feature_unittest.cc
@@ -225,8 +225,10 @@
   const base::OneShotTimer* timer_ptr() const { return timer_ptr_; }
 
   TestGeolocationUrlLoaderFactory* factory() const {
+    CHECK(SimpleGeolocationProvider::GetInstance());
     return static_cast<TestGeolocationUrlLoaderFactory*>(
-        geolocation_controller_->GetSharedURLLoaderFactoryForTesting());
+        SimpleGeolocationProvider::GetInstance()
+            ->GetSharedURLLoaderFactoryForTesting());
   }
 
   // AshTestBase:
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index da9c7444..2b01c60 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -27,6 +27,7 @@
 #include "ash/shell.h"
 #include "ash/shell_init_params.h"
 #include "ash/style/dark_light_mode_controller_impl.h"
+#include "ash/system/geolocation/test_geolocation_url_loader_factory.h"
 #include "ash/system/message_center/session_state_notification_blocker.h"
 #include "ash/system/model/system_tray_model.h"
 #include "ash/system/screen_layout_observer.h"
@@ -143,6 +144,11 @@
   // Clears the saved state so that test doesn't use on the wrong
   // default state.
   shell::ToplevelWindow::ClearSavedStateForTest();
+
+  // SimpleGeolocationProvider has to be initialized before
+  // GeolocationController, which is constructed during Shell::Init().
+  SimpleGeolocationProvider::Initialize(
+      base::MakeRefCounted<TestGeolocationUrlLoaderFactory>());
 }
 
 AshTestHelper::~AshTestHelper() {
@@ -150,6 +156,8 @@
     TearDown();
   }
 
+  SimpleGeolocationProvider::DestroyForTesting();
+
   // Ensure the next test starts with a null display::Screen.  This must be done
   // here instead of in TearDown() since some tests test access to the Screen
   // after the shell shuts down (which they use TearDown() to trigger).
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index edb5641..cd2c248 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -975,16 +975,16 @@
     task_environment_start_time_ = task_environment()->GetMockClock()->Now();
     SetSimulatedStartTime(GetTestDateMidnight());
 
+    // Set fixed geoposition for testing.
     scoped_refptr<TestGeolocationUrlLoaderFactory>
         geolocation_url_loader_factory =
             base::MakeRefCounted<TestGeolocationUrlLoaderFactory>();
     geolocation_url_loader_factory->SetValidPosition(
         kSanJoseGeoposition.latitude, kSanJoseGeoposition.longitude, Now());
-    Shell::Get()->geolocation_controller()->SetGeolocationProviderForTesting(
-        std::make_unique<SimpleGeolocationProvider>(
-            Shell::Get()->geolocation_controller(),
-            std::move(geolocation_url_loader_factory),
-            SimpleGeolocationProvider::DefaultGeolocationProviderURL()));
+    SimpleGeolocationProvider::GetInstance()
+        ->SetSharedUrlLoaderFactoryForTesting(
+            std::move(geolocation_url_loader_factory));
+
     GeopositionResponsesWaiter waiter(Shell::Get()->geolocation_controller());
     waiter.Wait();
   }
diff --git a/ash/webui/camera_app_ui/resources/css/mode/scan.css b/ash/webui/camera_app_ui/resources/css/mode/scan.css
index 8954510..ab10218 100644
--- a/ash/webui/camera_app_ui/resources/css/mode/scan.css
+++ b/ash/webui/camera_app_ui/resources/css/mode/scan.css
@@ -174,6 +174,7 @@
 .expanded #barcode-chip-text-content {
   /* TODO(b/172879638): Make this responsive */
   max-height: calc(var(--text-line-height) * 10);
+  overflow-wrap: break-word;
   white-space: normal;
   /* Keep the same width as before to avoid text jumping. */
   width: var(--chip-max-width);
diff --git a/chrome/browser/app_controller_mac_browsertest.mm b/chrome/browser/app_controller_mac_browsertest.mm
index 8ae98b9c..56d36c8 100644
--- a/chrome/browser/app_controller_mac_browsertest.mm
+++ b/chrome/browser/app_controller_mac_browsertest.mm
@@ -1223,62 +1223,6 @@
   EXPECT_EQ(profile, new_browser->profile());
 }
 
-// Test switching from Regular to OTR profiles updates the history menu.
-IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest,
-                       SwitchToIncognitoRemovesHistoryItems) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  AppController* app_controller = AppController.sharedController;
-
-  GURL simple(embedded_test_server()->GetURL("/simple.html"));
-  SendOpenUrlToAppController(simple);
-
-  Profile* profile = browser()->profile();
-  EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
-  Browser* regular_browser = chrome::GetLastActiveBrowser();
-
-  // Load profile's History Service backend so it will be assigned to the
-  // HistoryMenuBridge, or else this test will fail flaky.
-  ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
-      profile, ServiceAccessType::EXPLICIT_ACCESS));
-
-  // Verify that history bridge service is available for regular profiles.
-  EXPECT_TRUE([app_controller historyMenuBridge]->service());
-
-  // Open a URL in Incognito window.
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(), simple, WindowOpenDisposition::OFF_THE_RECORD,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
-
-  // Check that there are exactly 2 browsers (regular and incognito).
-  BrowserList* active_browser_list = BrowserList::GetInstance();
-  EXPECT_EQ(2u, active_browser_list->size());
-
-  Browser* inc_browser = chrome::GetLastActiveBrowser();
-  EXPECT_TRUE(inc_browser->profile()->IsIncognitoProfile());
-
-  // Assure that `windowDidBecomeMain` is called even if this browser window
-  // losts focus because of other browser processes in other tests are taking
-  // focus. It prevents flakiness.
-  [[NSNotificationCenter defaultCenter]
-      postNotificationName:NSWindowDidBecomeMainNotification
-                    object:inc_browser->window()
-                               ->GetNativeWindow()
-                               .GetNativeNSWindow()];
-
-  // Verify that history bridge service is not available in Incognito.
-  EXPECT_FALSE([app_controller historyMenuBridge]->service());
-
-  // Switch the focus back to the regular profile window.
-  [[NSNotificationCenter defaultCenter]
-      postNotificationName:NSWindowDidBecomeMainNotification
-                    object:regular_browser->window()
-                               ->GetNativeWindow()
-                               .GetNativeNSWindow()];
-
-  // Verify that history bridge service is available again.
-  EXPECT_TRUE([app_controller historyMenuBridge]->service());
-}
-
 class AppControllerIncognitoSwitchTest : public InProcessBrowserTest {
  public:
   void SetUpCommandLine(base::CommandLine* command_line) override {
diff --git a/chrome/browser/app_controller_mac_interactive_uitest.mm b/chrome/browser/app_controller_mac_interactive_uitest.mm
new file mode 100644
index 0000000..65804cd
--- /dev/null
+++ b/chrome/browser/app_controller_mac_interactive_uitest.mm
@@ -0,0 +1,78 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include <string>
+
+#import "chrome/browser/app_controller_mac.h"
+#include "chrome/browser/history/history_service_factory.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/cocoa/history_menu_bridge.h"
+#include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/test/browser_test.h"
+#include "extensions/browser/app_window/app_window_registry.h"
+#include "net/base/mac/url_conversions.h"
+
+namespace {
+
+// Instructs the NSApp's delegate to open |url|.
+void SendOpenUrlToAppController(const GURL& url) {
+  [NSApp.delegate application:NSApp openURLs:@[ net::NSURLWithGURL(url) ]];
+}
+
+class AppControllerMainMenuInteractiveUITest : public InProcessBrowserTest {
+ protected:
+  AppControllerMainMenuInteractiveUITest() = default;
+};
+
+// Note: This test interacts with SharedController which requires the browser's
+// focus. In browser_tests other tests that are running in parallel cause
+// flakiness to test test. See: https://crbug.com/1469960
+// Test switching from Regular to OTR profiles updates the history menu.
+IN_PROC_BROWSER_TEST_F(AppControllerMainMenuInteractiveUITest,
+                       SwitchToIncognitoRemovesHistoryItems) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  AppController* app_controller = AppController.sharedController;
+
+  GURL simple(embedded_test_server()->GetURL("/simple.html"));
+  SendOpenUrlToAppController(simple);
+
+  Profile* profile = browser()->profile();
+  EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
+
+  // Load profile's History Service backend so it will be assigned to the
+  // HistoryMenuBridge, or else this test will fail flaky.
+  ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
+      profile, ServiceAccessType::EXPLICIT_ACCESS));
+
+  // Verify that history bridge service is available for regular profiles.
+  EXPECT_TRUE([app_controller historyMenuBridge]->service());
+  Browser* regular_browser = chrome::GetLastActiveBrowser();
+
+  // Open a URL in Incognito window.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), simple, WindowOpenDisposition::OFF_THE_RECORD,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
+
+  // Check that there are exactly 2 browsers (regular and incognito).
+  BrowserList* active_browser_list = BrowserList::GetInstance();
+  EXPECT_EQ(2u, active_browser_list->size());
+
+  Browser* inc_browser = chrome::GetLastActiveBrowser();
+  EXPECT_TRUE(inc_browser->profile()->IsIncognitoProfile());
+
+  // Verify that history bridge service is not available in Incognito.
+  EXPECT_FALSE([app_controller historyMenuBridge]->service());
+
+  regular_browser->window()->Show();
+  // Verify that history bridge service is available again.
+  EXPECT_TRUE([app_controller historyMenuBridge]->service());
+}
+
+}  // namespace
diff --git a/chrome/browser/ash/chrome_browser_main_parts_ash.cc b/chrome/browser/ash/chrome_browser_main_parts_ash.cc
index c2c8d7b..e77b57b4 100644
--- a/chrome/browser/ash/chrome_browser_main_parts_ash.cc
+++ b/chrome/browser/ash/chrome_browser_main_parts_ash.cc
@@ -215,6 +215,7 @@
 #include "chromeos/ash/components/disks/disk_mount_manager.h"
 #include "chromeos/ash/components/drivefs/fake_drivefs_launcher_client.h"
 #include "chromeos/ash/components/fwupd/firmware_update_manager.h"
+#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
 #include "chromeos/ash/components/install_attributes/install_attributes.h"
 #include "chromeos/ash/components/local_search_service/public/cpp/local_search_service_proxy_factory.h"
 #include "chromeos/ash/components/login/auth/auth_events_recorder.h"
@@ -1000,6 +1001,10 @@
     WizardController::SetZeroDelays();
   }
 
+  // Initialize `SimpleGeolocationProvider` for the system parts.
+  SimpleGeolocationProvider::Initialize(
+      g_browser_process->shared_url_loader_factory());
+
   // On Chrome OS, Chrome does not exit when all browser windows are closed.
   // UnregisterKeepAlive is called from chrome::HandleAppExitingForPlatform.
   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/chrome/browser/ash/crosapi/print_job_info_idl_conversions.cc b/chrome/browser/ash/crosapi/print_job_info_idl_conversions.cc
index 02f5c02..dc9dbd6e 100644
--- a/chrome/browser/ash/crosapi/print_job_info_idl_conversions.cc
+++ b/chrome/browser/ash/crosapi/print_job_info_idl_conversions.cc
@@ -72,6 +72,8 @@
       return idl::PrintJobSource::kAndroidApp;
     case proto::PrintJobInfo_PrintJobSource_EXTENSION:
       return idl::PrintJobSource::kExtension;
+    case proto::PrintJobInfo_PrintJobSource_ISOLATED_WEB_APP:
+      return idl::PrintJobSource::kIsolatedWebApp;
     default:
       NOTREACHED();
   }
diff --git a/chrome/browser/ash/login/session/user_session_manager.cc b/chrome/browser/ash/login/session/user_session_manager.cc
index bf294fe..2d699745 100644
--- a/chrome/browser/ash/login/session/user_session_manager.cc
+++ b/chrome/browser/ash/login/session/user_session_manager.cc
@@ -148,7 +148,7 @@
 #include "components/flags_ui/pref_service_flags_storage.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/prefs/pref_member.h"
 #include "components/prefs/pref_registry_simple.h"
diff --git a/chrome/browser/ash/login/ui/login_display_host_mojo.cc b/chrome/browser/ash/login/ui/login_display_host_mojo.cc
index c88f9254..c38c979 100644
--- a/chrome/browser/ash/login/ui/login_display_host_mojo.cc
+++ b/chrome/browser/ash/login/ui/login_display_host_mojo.cc
@@ -561,6 +561,28 @@
 }
 
 void LoginDisplayHostMojo::ShowGaiaDialog(const AccountId& prefilled_account) {
+  GetWizardContext()->knowledge_factor_setup =
+      WizardContext::KnowledgeFactorSetup();
+
+  GetWizardContext()->knowledge_factor_setup.auth_setup_flow =
+      WizardContext::AuthChangeFlow::kInitialSetup;
+
+  ShowGaiaDialogImpl(prefilled_account);
+}
+
+void LoginDisplayHostMojo::StartUserRecovery(
+    const AccountId& account_to_recover) {
+  GetWizardContext()->knowledge_factor_setup =
+      WizardContext::KnowledgeFactorSetup();
+
+  GetWizardContext()->knowledge_factor_setup.auth_setup_flow =
+      WizardContext::AuthChangeFlow::kRecovery;
+
+  ShowGaiaDialogImpl(account_to_recover);
+}
+
+void LoginDisplayHostMojo::ShowGaiaDialogImpl(
+    const AccountId& prefilled_account) {
   EnsureOobeDialogLoaded();
   DCHECK(GetOobeUI());
 
@@ -577,11 +599,6 @@
   UpdateWallpaper(prefilled_account);
 }
 
-void LoginDisplayHostMojo::StartUserRecovery(
-    const AccountId& account_to_recover) {
-  ShowGaiaDialog(account_to_recover);
-}
-
 void LoginDisplayHostMojo::ShowOsInstallScreen() {
   StartWizard(OsInstallScreenView::kScreenId);
   ShowDialog();
diff --git a/chrome/browser/ash/login/ui/login_display_host_mojo.h b/chrome/browser/ash/login/ui/login_display_host_mojo.h
index a95c74d..96d5ed8 100644
--- a/chrome/browser/ash/login/ui/login_display_host_mojo.h
+++ b/chrome/browser/ash/login/ui/login_display_host_mojo.h
@@ -173,6 +173,9 @@
   void ShowFullScreen();
   void HideDialog();
 
+  // Common part for ShowGaiaDialog/StartUserRecovery.
+  void ShowGaiaDialogImpl(const AccountId& prefilled_account);
+
   // Adds this as a `OobeUI::Observer` if it has not already been added as one.
   void ObserveOobeUI();
 
diff --git a/chrome/browser/ash/login/ui/login_ui_pref_controller.cc b/chrome/browser/ash/login/ui/login_ui_pref_controller.cc
index 50bc4b31..eead9e8c6 100644
--- a/chrome/browser/ash/login/ui/login_ui_pref_controller.cc
+++ b/chrome/browser/ash/login/ui/login_ui_pref_controller.cc
@@ -5,12 +5,14 @@
 #include "chrome/browser/ash/login/ui/login_ui_pref_controller.h"
 
 #include "ash/constants/ash_pref_names.h"
+#include "ash/system/privacy_hub/privacy_hub_controller.h"
 #include "base/functional/bind.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/system/input_device_settings.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
 
@@ -32,6 +34,11 @@
       prefs::kOwnerTapToClickEnabled,
       base::BindRepeating(&LoginUIPrefController::UpdateTapToClickEnabled,
                           weak_factory_.GetWeakPtr()));
+  pref_change_registrar_.Add(
+      ash::prefs::kDeviceGeolocationAllowed,
+      base::BindRepeating(&LoginUIPrefController::UpdateGeolocationUsageAllowed,
+                          weak_factory_.GetWeakPtr()));
+
   if (prefs->GetAllPrefStoresInitializationStatus() ==
       PrefService::INITIALIZATION_STATUS_WAITING) {
     prefs->AddPrefInitObserver(
@@ -63,6 +70,20 @@
           prefs::kOwnerTapToClickEnabled));
 }
 
+void LoginUIPrefController::UpdateGeolocationUsageAllowed() {
+  auto access_level = static_cast<PrivacyHubController::AccessLevel>(
+      g_browser_process->local_state()->GetInteger(
+          ash::prefs::kDeviceGeolocationAllowed));
+  switch (access_level) {
+    case PrivacyHubController::AccessLevel::kAllowed:
+      SimpleGeolocationProvider::GetInstance()->AllowGeolocationUsage();
+      break;
+    case PrivacyHubController::AccessLevel::kDisallowed:
+    default:
+      SimpleGeolocationProvider::GetInstance()->DisallowGeolocationUsage();
+  }
+}
+
 void LoginUIPrefController::InitOwnerPreferences(bool success) {
   if (!success) {
     LOG(ERROR) << "InitOwnerPreferences failed.";
@@ -71,6 +92,7 @@
   UpdatePrimaryMouseButtonRight();
   UpdatePrimaryPointingStickButtonRight();
   UpdateTapToClickEnabled();
+  UpdateGeolocationUsageAllowed();
 }
 
 }  // namespace ash
diff --git a/chrome/browser/ash/login/ui/login_ui_pref_controller.h b/chrome/browser/ash/login/ui/login_ui_pref_controller.h
index 402d2d74..d82aa22 100644
--- a/chrome/browser/ash/login/ui/login_ui_pref_controller.h
+++ b/chrome/browser/ash/login/ui/login_ui_pref_controller.h
@@ -32,6 +32,9 @@
   // Apply "owner.touchpad.enable_tap_to_click" preference on the login screen.
   void UpdateTapToClickEnabled();
 
+  // Apply "ash.device.geolocation_allowed" preference on the login screen.
+  void UpdateGeolocationUsageAllowed();
+
   PrefChangeRegistrar pref_change_registrar_;
 
   base::WeakPtrFactory<LoginUIPrefController> weak_factory_{this};
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc
index bb9480b..4736373 100644
--- a/chrome/browser/ash/login/wizard_controller.cc
+++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -2532,11 +2532,7 @@
     return;
   }
 
-  geolocation_provider_ = std::make_unique<SimpleGeolocationProvider>(
-      g_browser_process->platform_part()->GetTimezoneResolverManager(),
-      shared_url_loader_factory_,
-      SimpleGeolocationProvider::DefaultGeolocationProviderURL());
-  geolocation_provider_->RequestGeolocation(
+  SimpleGeolocationProvider::GetInstance()->RequestGeolocation(
       base::Seconds(kResolveTimeZoneTimeoutSeconds),
       false /* send_wifi_geolocation_data */,
       false /* send_cellular_geolocation_data */,
diff --git a/chrome/browser/ash/login/wizard_controller.h b/chrome/browser/ash/login/wizard_controller.h
index f8e0578..78c70a5 100644
--- a/chrome/browser/ash/login/wizard_controller.h
+++ b/chrome/browser/ash/login/wizard_controller.h
@@ -600,7 +600,6 @@
 
   base::CallbackListSubscription accessibility_subscription_;
 
-  std::unique_ptr<SimpleGeolocationProvider> geolocation_provider_;
   std::unique_ptr<TimeZoneProvider> timezone_provider_;
 
   // Controller of the demo mode setup. It has the lifetime of the single demo
diff --git a/chrome/browser/ash/login/wizard_controller_browsertest.cc b/chrome/browser/ash/login/wizard_controller_browsertest.cc
index 4affc8d..e95ed77 100644
--- a/chrome/browser/ash/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/ash/login/wizard_controller_browsertest.cc
@@ -620,6 +620,10 @@
     wizard_controller->SetSharedURLLoaderFactoryForTesting(
         base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
             &test_url_loader_factory_));
+    SimpleGeolocationProvider::GetInstance()
+        ->SetSharedUrlLoaderFactoryForTesting(
+            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+                &test_url_loader_factory_));
 
     // Set up the mocks for all screens.
     mock_welcome_screen_ =
@@ -763,10 +767,6 @@
         NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204);
   }
 
-  SimpleGeolocationProvider* GetGeolocationProvider() {
-    return WizardController::default_controller()->geolocation_provider_.get();
-  }
-
   void WaitUntilTimezoneResolved() {
     base::RunLoop loop;
     if (!WizardController::default_controller()
@@ -817,7 +817,7 @@
     EXPECT_CALL(*mock_update_screen_, ShowImpl()).Times(1);
     mock_network_screen_->ExitScreen(NetworkScreen::Result::CONNECTED);
 
-    EXPECT_TRUE(GetGeolocationProvider());
+    EXPECT_NE(SimpleGeolocationProvider::GetInstance(), nullptr);
 
     // Let update screen smooth time process (time = 0ms).
     content::RunAllPendingInMessageLoop();
diff --git a/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller.cc b/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller.cc
index 7bf285d..f06e185c 100644
--- a/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller.cc
+++ b/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller.cc
@@ -205,9 +205,7 @@
   auto result = remoting::mojom::SupportSessionParams::New();
   result->user_name = parameters.user_name;
   result->authorized_helper = parameters.admin_email;
-  // Note the oauth token must be prefixed with 'oauth2:', or it will be
-  // rejected by the CRD host.
-  result->oauth_access_token = "oauth2:" + parameters.oauth_token;
+  result->oauth_access_token = parameters.oauth_token;
 
   return result;
 }
diff --git a/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller_unittest.cc b/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller_unittest.cc
index d47fe89..9873ea78 100644
--- a/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller_unittest.cc
+++ b/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller_unittest.cc
@@ -383,7 +383,7 @@
                                     session_finished_callback());
 
   ASSERT_FALSE(actual_parameters.is_null());
-  EXPECT_EQ(actual_parameters->oauth_access_token, "oauth2:<the-oauth-token>");
+  EXPECT_EQ(actual_parameters->oauth_access_token, "<the-oauth-token>");
 }
 
 TEST_F(CrdAdminSessionControllerTest, ShouldPassUserNameToRemotingService) {
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job.cc b/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job.cc
index ab673ca0..4477fa13 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job.cc
@@ -101,12 +101,6 @@
       .LogSessionLaunchResult(result_code);
 }
 
-void SendSessionTypeToUma(
-    DeviceCommandStartCrdSessionJob::UmaSessionType session_type) {
-  base::UmaHistogramEnumeration(
-      "Enterprise.DeviceRemoteCommand.Crd.SessionType", session_type);
-}
-
 std::string CreateSuccessPayload(const std::string& access_code) {
   return base::WriteJson(
              base::Value::Dict()
@@ -393,7 +387,6 @@
 
   SendResultCodeToUma(GetCrdSessionType(), GetCurrentUserSessionType(),
                       ExtendedStartCrdSessionResultCode::kSuccess);
-  SendSessionTypeToUma(GetUmaSessionType());
   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
       FROM_HERE,
       base::BindOnce(std::move(result_callback_), ResultType::kSuccess,
@@ -452,28 +445,6 @@
   return CrdSessionType::REMOTE_SUPPORT_SESSION;
 }
 
-DeviceCommandStartCrdSessionJob::UmaSessionType
-DeviceCommandStartCrdSessionJob::GetUmaSessionType() const {
-  switch (GetCurrentUserSessionType()) {
-    case UserSessionType::AUTO_LAUNCHED_KIOSK_SESSION:
-      return UmaSessionType::kAutoLaunchedKiosk;
-    case UserSessionType::AFFILIATED_USER_SESSION:
-      return UmaSessionType::kAffiliatedUser;
-    case UserSessionType::MANAGED_GUEST_SESSION:
-      return UmaSessionType::kManagedGuestSession;
-    case UserSessionType::MANUALLY_LAUNCHED_KIOSK_SESSION:
-      return UmaSessionType::kManuallyLaunchedKiosk;
-    case UserSessionType::NO_SESSION:
-      // TODO(b/236689277): Introduce UmaSessionType::kNoLocalUser.
-      return UmaSessionType::kMaxValue;
-    case UserSessionType::UNAFFILIATED_USER_SESSION:
-    case UserSessionType::GUEST_SESSION:
-    case UserSessionType::USER_SESSION_TYPE_UNKNOWN:
-      NOTREACHED();
-      return UmaSessionType::kMaxValue;
-  }
-}
-
 bool DeviceCommandStartCrdSessionJob::IsDeviceIdle() const {
   return GetDeviceIdleTime() >= idleness_cutoff_;
 }
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job.h b/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job.h
index 2f2b869..ce2fae57 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job.h
+++ b/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job.h
@@ -42,16 +42,6 @@
   // fetch an oauth token.
   void SetOAuthTokenForTest(const std::string& token);
 
-  // This enum can't be renumbered because it is logged to UMA.
-  // TODO(b/261425261): Remove this enum when the Uma histogram is removed.
-  enum class UmaSessionType {
-    kAutoLaunchedKiosk = 0,
-    kAffiliatedUser = 1,
-    kManagedGuestSession = 2,
-    kManuallyLaunchedKiosk = 3,
-    kMaxValue = kManuallyLaunchedKiosk
-  };
-
  protected:
   // RemoteCommandJob:
   bool ParseCommandPayload(const std::string& command_payload) override;
@@ -71,7 +61,6 @@
   void FinishWithNotIdleError();
 
   bool UserTypeSupportsCrd() const;
-  UmaSessionType GetUmaSessionType() const;
   CrdSessionType GetCrdSessionType() const;
   bool IsDeviceIdle() const;
 
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job_unittest.cc
index 99ad2cca..ee83464 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job_unittest.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job_unittest.cc
@@ -50,7 +50,6 @@
 using base::test::IsJson;
 using base::test::TestFuture;
 using test::TestSessionType;
-using UmaSessionType = DeviceCommandStartCrdSessionJob::UmaSessionType;
 using chromeos::network_config::mojom::NetworkType;
 using chromeos::network_config::mojom::OncSource;
 using remoting::features::kEnableCrdAdminRemoteAccess;
@@ -737,59 +736,6 @@
 }
 
 TEST_P(DeviceCommandStartCrdSessionJobTestParameterized,
-       ShouldSendSuccessUmaLogsForRemoteSupport) {
-  TestSessionType user_session_type = GetParam();
-  SCOPED_TRACE(base::StringPrintf("Testing session type %s",
-                                  SessionTypeToString(user_session_type)));
-
-  if (!SupportsRemoteSupport(user_session_type)) {
-    return;
-  }
-
-  base::HistogramTester histogram_tester;
-
-  StartSessionOfType(user_session_type);
-  RunJobAndWaitForResult();
-
-  UmaSessionType expected_session_type = [&]() {
-    switch (user_session_type) {
-      case TestSessionType::kManuallyLaunchedArcKioskSession:
-      case TestSessionType::kManuallyLaunchedWebKioskSession:
-      case TestSessionType::kManuallyLaunchedKioskSession:
-        return UmaSessionType::kManuallyLaunchedKiosk;
-      case TestSessionType::kAutoLaunchedArcKioskSession:
-      case TestSessionType::kAutoLaunchedWebKioskSession:
-      case TestSessionType::kAutoLaunchedKioskSession:
-        return UmaSessionType::kAutoLaunchedKiosk;
-
-      case TestSessionType::kManagedGuestSession:
-        return UmaSessionType::kManagedGuestSession;
-
-      case TestSessionType::kAffiliatedUserSession:
-        return UmaSessionType::kAffiliatedUser;
-
-      case TestSessionType::kGuestSession:
-      case TestSessionType::kUnaffiliatedUserSession:
-      case TestSessionType::kNoSession:
-        // Unsupported session types
-        NOTREACHED();
-        return UmaSessionType::kMaxValue;
-    }
-  }();
-
-  histogram_tester.ExpectUniqueSample(
-      "Enterprise.DeviceRemoteCommand.Crd.Result",
-      ExtendedStartCrdSessionResultCode::kSuccess, 1);
-  histogram_tester.ExpectUniqueSample(
-      "Enterprise.DeviceRemoteCommand.Crd.SessionType", expected_session_type,
-      1);
-  histogram_tester.ExpectUniqueSample(
-      base::StringPrintf(kHistogramResultTemplate, "RemoteSupport",
-                         SessionTypeToUmaString(user_session_type)),
-      ExtendedStartCrdSessionResultCode::kSuccess, /*expected_bucket_count=*/1);
-}
-
-TEST_P(DeviceCommandStartCrdSessionJobTestParameterized,
        ShouldSendSessionDurationLogForRemoteSupport) {
   TestSessionType user_session_type = GetParam();
   SCOPED_TRACE(base::StringPrintf("Testing session type %s",
diff --git a/chrome/browser/ash/preferences.cc b/chrome/browser/ash/preferences.cc
index 9dd1c6a0a2..8c16dddd 100644
--- a/chrome/browser/ash/preferences.cc
+++ b/chrome/browser/ash/preferences.cc
@@ -15,6 +15,7 @@
 #include "ash/public/cpp/ash_prefs.h"
 #include "ash/shell.h"
 #include "ash/system/geolocation/geolocation_controller.h"
+#include "ash/system/privacy_hub/privacy_hub_controller.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/functional/bind.h"
@@ -54,6 +55,7 @@
 #include "chromeos/ash/components/dbus/pciguard/pciguard_client.h"
 #include "chromeos/ash/components/dbus/update_engine/update_engine.pb.h"
 #include "chromeos/ash/components/dbus/update_engine/update_engine_client.h"
+#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
 #include "chromeos/ash/components/peripheral_notification/peripheral_notification_manager.h"
 #include "chromeos/ash/components/settings/cros_settings_names.h"
 #include "chromeos/ash/components/standalone_browser/lacros_availability.h"
@@ -685,7 +687,6 @@
   consumer_auto_update_toggle_pref_.Init(::prefs::kConsumerAutoUpdateToggle,
                                          g_browser_process->local_state(),
                                          callback);
-  // TODO(zauri): change to BooleanPrefMember
   pref_change_registrar_.Init(prefs);
   pref_change_registrar_.Add(ash::prefs::kUserGeolocationAllowed, callback);
   pref_change_registrar_.Add(::prefs::kUserTimezone, callback);
@@ -1143,30 +1144,27 @@
   if (reason == REASON_INITIALIZATION ||
       (pref_name == ash::prefs::kUserGeolocationAllowed &&
        reason == REASON_PREF_CHANGED)) {
-    const bool system_geolocation_permission_enabled =
+    const bool user_geolocation_permission_enabled =
         prefs_->GetBoolean(ash::prefs::kUserGeolocationAllowed);
 
-    const bool automatic_timezone_selected = prefs_->GetBoolean(
-        ::prefs::kResolveTimezoneByGeolocationMigratedToMethod);
-
-    // Fall back to static timezone when system geolocation access is disabled.
-    if (!system_geolocation_permission_enabled && automatic_timezone_selected) {
-      prefs_->SetBoolean(::prefs::kResolveTimezoneByGeolocationMigratedToMethod,
-                         false);
-      prefs_->SetInteger(::prefs::kResolveTimezoneByGeolocationMethod,
-                         static_cast<int>(system::TimeZoneResolverManager::
-                                              TimeZoneResolveMethod::DISABLED));
+    if (user_geolocation_permission_enabled) {
+      SimpleGeolocationProvider::GetInstance()->AllowGeolocationUsage();
+    } else {
+      SimpleGeolocationProvider::GetInstance()->DisallowGeolocationUsage();
     }
 
-    ash::system::TimeZoneResolverManager* timezone_resolver_manager =
-        g_browser_process->platform_part()->GetTimezoneResolverManager();
-    GeolocationController* geolocation_controller =
-        ash::Shell::Get()->geolocation_controller();
-
-    timezone_resolver_manager->OnSystemGeolocationPermissionChanged(
-        system_geolocation_permission_enabled);
-    geolocation_controller->OnSystemGeolocationPermissionChanged(
-        system_geolocation_permission_enabled);
+    // Log-in screen follows the owner's geolocation setting.
+    if (user_is_owner) {
+      PrivacyHubController::AccessLevel access_level;
+      if (user_geolocation_permission_enabled) {
+        access_level = PrivacyHubController::AccessLevel::kAllowed;
+      } else {
+        access_level = PrivacyHubController::AccessLevel::kDisallowed;
+      }
+      g_browser_process->local_state()->SetInteger(
+          ash::prefs::kDeviceGeolocationAllowed,
+          static_cast<int>(access_level));
+    }
   }
 
   if (pref_name == ::prefs::kUserTimezone &&
diff --git a/chrome/browser/ash/printing/history/print_job_info.proto b/chrome/browser/ash/printing/history/print_job_info.proto
index 2f91f37..fbf8662 100644
--- a/chrome/browser/ash/printing/history/print_job_info.proto
+++ b/chrome/browser/ash/printing/history/print_job_info.proto
@@ -83,6 +83,7 @@
     ARC = 1;
     EXTENSION = 2;
     PRINT_PREVIEW_INCOGNITO = 3;
+    ISOLATED_WEB_APP = 4;
   }
 
   enum PrintJobStatus {
diff --git a/chrome/browser/ash/printing/history/print_job_info_proto_conversions.cc b/chrome/browser/ash/printing/history/print_job_info_proto_conversions.cc
index 3cac4ac..ca0f55b10 100644
--- a/chrome/browser/ash/printing/history/print_job_info_proto_conversions.cc
+++ b/chrome/browser/ash/printing/history/print_job_info_proto_conversions.cc
@@ -60,6 +60,8 @@
       return proto::PrintJobInfo_PrintJobSource_EXTENSION;
     case ::printing::PrintJob::Source::kPrintPreviewIncognito:
       return proto::PrintJobInfo_PrintJobSource_PRINT_PREVIEW_INCOGNITO;
+    case ::printing::PrintJob::Source::kIsolatedWebApp:
+      return proto::PrintJobInfo_PrintJobSource_ISOLATED_WEB_APP;
     default:
       NOTREACHED();
   }
diff --git a/chrome/browser/ash/system/timezone_resolver_manager.cc b/chrome/browser/ash/system/timezone_resolver_manager.cc
index a9e72db..ebd0448 100644
--- a/chrome/browser/ash/system/timezone_resolver_manager.cc
+++ b/chrome/browser/ash/system/timezone_resolver_manager.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
 #include "chromeos/ash/components/install_attributes/install_attributes.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/prefs/pref_change_registrar.h"
@@ -135,10 +136,17 @@
 
 }  // anonymous namespace.
 
-TimeZoneResolverManager::TimeZoneResolverManager() {
-  local_state_initialized_ =
-      g_browser_process->local_state()->GetInitializationStatus() ==
-      PrefService::INITIALIZATION_STATUS_SUCCESS;
+TimeZoneResolverManager::TimeZoneResolverManager(
+    SimpleGeolocationProvider* const geolocation_provider)
+    : geolocation_provider_(geolocation_provider) {
+  switch (g_browser_process->local_state()->GetInitializationStatus()) {
+    case PrefService::INITIALIZATION_STATUS_SUCCESS:
+    case PrefService::INITIALIZATION_STATUS_CREATED_NEW_PREF_STORE:
+      local_state_initialized_ = true;
+      break;
+    default:
+      local_state_initialized_ = false;
+  }
   g_browser_process->local_state()->AddPrefInitObserver(
       base::BindOnce(&TimeZoneResolverManager::OnLocalStateInitialized,
                      weak_factory_.GetWeakPtr()));
@@ -148,9 +156,14 @@
       ::prefs::kSystemTimezoneAutomaticDetectionPolicy,
       base::BindRepeating(&TimeZoneResolverManager::UpdateTimezoneResolver,
                           base::Unretained(this)));
+
+  geolocation_provider_->AddObserver(this);
 }
 
-TimeZoneResolverManager::~TimeZoneResolverManager() {}
+TimeZoneResolverManager::~TimeZoneResolverManager() {
+  geolocation_provider_->RemoveObserver(this);
+  geolocation_provider_ = nullptr;
+}
 
 void TimeZoneResolverManager::SetPrimaryUserPrefs(PrefService* pref_service) {
   primary_user_prefs_ = pref_service;
@@ -232,18 +245,6 @@
          TimeZoneResolveMethod::SEND_ALL_LOCATION_INFO;
 }
 
-bool TimeZoneResolverManager::IsSystemGeolocationAllowed() const {
-  // Follow device preference on log-in screen.
-  if (!primary_user_prefs_) {
-    return g_browser_process->local_state()->GetInteger(
-               ash::prefs::kDeviceGeolocationAllowed) ==
-           static_cast<int>(PrivacyHubController::AccessLevel::kAllowed);
-  }
-
-  // Inside user session check geolocation user preference.
-  return primary_user_prefs_->GetBoolean(ash::prefs::kUserGeolocationAllowed);
-}
-
 // static
 int TimeZoneResolverManager::GetEffectiveAutomaticTimezoneManagementSetting() {
   // Regular users choose automatic time zone method themselves.
@@ -285,8 +286,8 @@
     observer.OnTimeZoneResolverUpdated();
 }
 
-void TimeZoneResolverManager::OnSystemGeolocationPermissionChanged(
-    bool enabled) {
+void TimeZoneResolverManager::OnGeolocationPermissionChanged(bool enabled) {
+  // New permission state will be retrieved from `geolocation_provider_`.
   UpdateTimezoneResolver();
 }
 
@@ -305,7 +306,7 @@
 bool TimeZoneResolverManager::TimeZoneResolverShouldBeRunning() {
   // System geolocation permission is required for automatic timezone
   // resolution.
-  if (!IsSystemGeolocationAllowed()) {
+  if (!geolocation_provider_->IsGeolocationUsageAllowed()) {
     return false;
   }
 
diff --git a/chrome/browser/ash/system/timezone_resolver_manager.h b/chrome/browser/ash/system/timezone_resolver_manager.h
index 8869711..2407380 100644
--- a/chrome/browser/ash/system/timezone_resolver_manager.h
+++ b/chrome/browser/ash/system/timezone_resolver_manager.h
@@ -9,6 +9,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
 #include "chromeos/ash/components/timezone/timezone_resolver.h"
 #include "components/prefs/pref_change_registrar.h"
 
@@ -17,7 +18,9 @@
 namespace ash {
 namespace system {
 
-class TimeZoneResolverManager : public TimeZoneResolver::Delegate {
+class TimeZoneResolverManager
+    : public TimeZoneResolver::Delegate,
+      public ash::SimpleGeolocationProvider::Observer {
  public:
   class Observer {
    public:
@@ -38,7 +41,8 @@
     METHODS_NUMBER = 4
   };
 
-  TimeZoneResolverManager();
+  explicit TimeZoneResolverManager(
+      SimpleGeolocationProvider* const geolocation_provider);
 
   TimeZoneResolverManager(const TimeZoneResolverManager&) = delete;
   TimeZoneResolverManager& operator=(const TimeZoneResolverManager&) = delete;
@@ -51,7 +55,6 @@
   // TimeZoneResolver::Delegate:
   bool ShouldSendWiFiGeolocationData() const override;
   bool ShouldSendCellularGeolocationData() const override;
-  bool IsSystemGeolocationAllowed() const override;
 
   // Starts or stops TimezoneResolver according to current settings.
   void UpdateTimezoneResolver();
@@ -59,8 +62,7 @@
   // This class should respect the system geolocation permission. When the
   // permission is disabled, no requests should be dispatched and no responses
   // processed.
-  // Called from `ash::Preferences::ApplyPreferences()`.
-  void OnSystemGeolocationPermissionChanged(bool enabled);
+  void OnGeolocationPermissionChanged(bool enabled) override;
 
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
@@ -106,6 +108,10 @@
 
   base::ObserverList<Observer>::Unchecked observers_;
 
+  // Points to the `SimpleGeolocationProvider::GetInstance()` throughout the
+  // object lifecycle. Overridden in unit tests.
+  raw_ptr<SimpleGeolocationProvider> geolocation_provider_ = nullptr;
+
   // This is non-null only after user logs in.
   raw_ptr<PrefService, DanglingUntriaged | ExperimentalAsh>
       primary_user_prefs_ = nullptr;
diff --git a/chrome/browser/ash/system/timezone_resolver_manager_browsertest.cc b/chrome/browser/ash/system/timezone_resolver_manager_browsertest.cc
index 94a04a6..3f8cc110 100644
--- a/chrome/browser/ash/system/timezone_resolver_manager_browsertest.cc
+++ b/chrome/browser/ash/system/timezone_resolver_manager_browsertest.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/ash/components/settings/cros_settings_names.h"
 #include "components/account_id/account_id.h"
@@ -400,6 +401,7 @@
 
   ash::system::TimeZoneResolverManager* tz_resolver_manager =
       g_browser_process->platform_part()->GetTimezoneResolverManager();
+
   TimeZoneResolver* tz_resolver =
       g_browser_process->platform_part()->GetTimezoneResolver();
   ASSERT_NE(tz_resolver_manager, nullptr);
@@ -411,12 +413,13 @@
 
   // Log in a user.
   LoginUser(regular_primary_user_id_);
-  base::RunLoop().RunUntilIdle();
+
   PrefService* pref_service =
       g_browser_process->profile_manager()->GetActiveUserProfile()->GetPrefs();
 
   // Check the default configuration: TZResolver should be running.
-  EXPECT_TRUE(tz_resolver_manager->IsSystemGeolocationAllowed());
+  EXPECT_TRUE(
+      SimpleGeolocationProvider::GetInstance()->IsGeolocationUsageAllowed());
   EXPECT_TRUE(tz_resolver_manager->TimeZoneResolverShouldBeRunning());
   EXPECT_EQ(
       system::TimeZoneResolverManager::GetEffectiveUserTimeZoneResolveMethod(
@@ -426,22 +429,20 @@
 
   UpdateUserGeolocationPermission(pref_service, false);
   // Change of `kUserGeolocationPermission` will trigger the
-  // `OnSystemGeolocationPermissionChanged()`, stopping the scheduler.
-  EXPECT_FALSE(tz_resolver_manager->IsSystemGeolocationAllowed());
+  // `OnGeolocationPermissionChanged()`, stopping the scheduler.
+  EXPECT_FALSE(
+      SimpleGeolocationProvider::GetInstance()->IsGeolocationUsageAllowed());
   EXPECT_FALSE(tz_resolver_manager->TimeZoneResolverShouldBeRunning());
   EXPECT_FALSE(tz_resolver->IsRunning());
 
-  // Disabling geolocation permission is silently rolling back timezone setting
-  // to the static timezone.
-  EXPECT_TRUE(IsStaticTimezoneSelected(pref_service));
-
   // Re-enable geolocation permission and select automatic timezone again.
-  // Ccheck that the resolver is working again.
+  // Check that the resolver is working again.
   UpdateUserGeolocationPermission(pref_service, true);
   SetUserTimeZoneResolveMethod(
       pref_service, system::TimeZoneResolverManager::TimeZoneResolveMethod::
                         SEND_ALL_LOCATION_INFO);
-  EXPECT_TRUE(tz_resolver_manager->IsSystemGeolocationAllowed());
+  EXPECT_TRUE(
+      SimpleGeolocationProvider::GetInstance()->IsGeolocationUsageAllowed());
   EXPECT_TRUE(tz_resolver_manager->TimeZoneResolverShouldBeRunning());
   EXPECT_TRUE(tz_resolver->IsRunning());
 }
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_time_of_day_browsertest.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_time_of_day_browsertest.cc
index 197db893..31991235 100644
--- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_time_of_day_browsertest.cc
+++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_time_of_day_browsertest.cc
@@ -165,15 +165,16 @@
     auto* geolocation_controller = GeolocationController::Get();
     geolocation_controller->SetClockForTesting(this);
 
+    // Override SharedUrlLoaderFactory to return fixed geoposition.
     scoped_refptr<TestGeolocationUrlLoaderFactory>
         geolocation_url_loader_factory =
             base::MakeRefCounted<TestGeolocationUrlLoaderFactory>();
-    test_geolocation_url_loader_factory_ = geolocation_url_loader_factory.get();
-    test_geolocation_url_loader_factory_->set_position(GetGeoposition());
-    geolocation_controller->SetGeolocationProviderForTesting(
-        std::make_unique<SimpleGeolocationProvider>(
-            geolocation_controller, std::move(geolocation_url_loader_factory),
-            SimpleGeolocationProvider::DefaultGeolocationProviderURL()));
+    geolocation_url_loader_factory->set_position(GetGeoposition());
+    SimpleGeolocationProvider::GetInstance()
+        ->SetSharedUrlLoaderFactoryForTesting(geolocation_url_loader_factory);
+    // Request immediate geoposition to fetch and broadcast the fixed
+    // geoposition set by TestSharedUrlLoaderFactory above.
+    GeolocationController::Get()->RequestImmediateGeopositionForTesting();
 
     WaitForTestSystemAppInstall();
   }
@@ -181,7 +182,6 @@
   void TearDownOnMainThread() override {
     SystemWebAppBrowserTestBase::TearDownOnMainThread();
 
-    test_geolocation_url_loader_factory_ = nullptr;
     time_of_day_scheduler_ = nullptr;
   }
 
@@ -249,7 +249,6 @@
   const std::vector<base::Time> times_to_test_ = GenerateTimesToTest();
   base::SimpleTestClock clock_;
   base::SimpleTestTickClock tick_clock_;
-  raw_ptr<TestGeolocationUrlLoaderFactory> test_geolocation_url_loader_factory_;
   raw_ptr<WallpaperTimeOfDayScheduler> time_of_day_scheduler_;
   TestChromeWebUIControllerFactory test_chrome_webui_controller_factory_;
   TestPersonalizationAppWebUIProvider test_webui_provider_;
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.cc b/chrome/browser/autofill/android/personal_data_manager_android.cc
index 07ee58b..3074b63 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.cc
+++ b/chrome/browser/autofill/android/personal_data_manager_android.cc
@@ -260,8 +260,7 @@
   AutofillProfile profile = AutofillProfile::CreateFromJavaObject(
       jprofile, target_profile, g_browser_process->GetApplicationLocale());
 
-  if (target_profile != nullptr &&
-      target_profile->record_type() == AutofillProfile::LOCAL_PROFILE) {
+  if (target_profile != nullptr) {
     personal_data_manager_->UpdateProfile(profile);
   } else {
     personal_data_manager_->AddProfile(profile);
diff --git a/chrome/browser/autofill/autofill_browsertest.cc b/chrome/browser/autofill/autofill_browsertest.cc
index d0cc713..1f6b09104 100644
--- a/chrome/browser/autofill/autofill_browsertest.cc
+++ b/chrome/browser/autofill/autofill_browsertest.cc
@@ -77,44 +77,6 @@
     "  document.getElementById('testform').submit();"
     "};";
 
-// TODO(bondd): PdmChangeWaiter in autofill_uitest_util.cc is a replacement for
-// this class. Remove this class and use helper functions in that file instead.
-class WindowedPersonalDataManagerObserver : public PersonalDataManagerObserver {
- public:
-  explicit WindowedPersonalDataManagerObserver(Browser* browser)
-      : alerted_(false), has_run_message_loop_(false), browser_(browser) {
-    PersonalDataManagerFactory::GetForProfile(browser_->profile())->
-        AddObserver(this);
-  }
-
-  ~WindowedPersonalDataManagerObserver() override {}
-
-  void Wait() {
-    if (!alerted_) {
-      has_run_message_loop_ = true;
-      content::RunMessageLoop();
-    }
-    PersonalDataManagerFactory::GetForProfile(browser_->profile())->
-        RemoveObserver(this);
-  }
-
-  // PersonalDataManagerObserver:
-  void OnPersonalDataChanged() override {
-    if (has_run_message_loop_) {
-      base::RunLoop::QuitCurrentWhenIdleDeprecated();
-      has_run_message_loop_ = false;
-    }
-    alerted_ = true;
-  }
-
-  void OnInsufficientFormData() override { OnPersonalDataChanged(); }
-
- private:
-  bool alerted_;
-  bool has_run_message_loop_;
-  raw_ptr<Browser> browser_;
-};
-
 class AutofillTest : public InProcessBrowserTest {
  protected:
   class TestAutofillManager : public BrowserAutofillManager {
@@ -204,7 +166,7 @@
         autofill_manager_injector_[web_contents()]->WaitForFormsSeen(1));
     // Shortcut explicit save prompts and automatically accept.
     personal_data_manager()->set_auto_accept_address_imports_for_testing(true);
-    WindowedPersonalDataManagerObserver observer(browser());
+    PdmChangeWaiter observer(browser()->profile());
     ASSERT_TRUE(
         content::ExecJs(web_contents(), GetJSToFillForm(data) + submit_js));
     if (simulate_click) {
diff --git a/chrome/browser/autofill/autofill_server_browsertest.cc b/chrome/browser/autofill/autofill_server_browsertest.cc
index 787b8b1..4882907 100644
--- a/chrome/browser/autofill/autofill_server_browsertest.cc
+++ b/chrome/browser/autofill/autofill_server_browsertest.cc
@@ -43,31 +43,6 @@
 namespace autofill {
 namespace {
 
-// TODO(bondd): PdmChangeWaiter in autofill_uitest_util.cc is a replacement for
-// this class. Remove this class and use helper functions in that file instead.
-class WindowedPersonalDataManagerObserver : public PersonalDataManagerObserver {
- public:
-  explicit WindowedPersonalDataManagerObserver(Profile* profile)
-      : profile_(profile),
-        message_loop_runner_(new content::MessageLoopRunner) {
-    PersonalDataManagerFactory::GetForProfile(profile_)->AddObserver(this);
-  }
-  ~WindowedPersonalDataManagerObserver() override {}
-
-  // Waits for the PersonalDataManager's list of profiles to be updated.
-  void Wait() {
-    message_loop_runner_->Run();
-    PersonalDataManagerFactory::GetForProfile(profile_)->RemoveObserver(this);
-  }
-
-  // PersonalDataManagerObserver:
-  void OnPersonalDataChanged() override { message_loop_runner_->Quit(); }
-
- private:
-  raw_ptr<Profile> profile_;
-  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
-};
-
 class WindowedNetworkObserver {
  public:
   explicit WindowedNetworkObserver(Matcher<std::string> expected_upload_data)
@@ -81,7 +56,7 @@
   WindowedNetworkObserver(const WindowedNetworkObserver&) = delete;
   WindowedNetworkObserver& operator=(const WindowedNetworkObserver&) = delete;
 
-  ~WindowedNetworkObserver() {}
+  ~WindowedNetworkObserver() = default;
 
   // Waits for a network request with the |expected_upload_data_|.
   void Wait() {
@@ -205,8 +180,7 @@
                        QueryAndUploadBothIncludeFieldsWithAutocompleteOff) {
   // Seed some test Autofill profile data, as upload requests are only made when
   // there is local data available to use as a baseline.
-  WindowedPersonalDataManagerObserver personal_data_observer(
-      browser()->profile());
+  PdmChangeWaiter personal_data_observer(browser()->profile());
   PersonalDataManagerFactory::GetForProfile(browser()->profile())
       ->AddProfile(test::GetFullProfile());
   personal_data_observer.Wait();
diff --git a/chrome/browser/autofill/autofill_uitest_util.cc b/chrome/browser/autofill/autofill_uitest_util.cc
index add194e..7e7d91f 100644
--- a/chrome/browser/autofill/autofill_uitest_util.cc
+++ b/chrome/browser/autofill/autofill_uitest_util.cc
@@ -23,52 +23,35 @@
 
 namespace autofill {
 
-// This class is used to wait for asynchronous updates to PersonalDataManager
-// to complete.
-class PdmChangeWaiter : public PersonalDataManagerObserver {
- public:
-  explicit PdmChangeWaiter(Profile* base_profile)
-      : alerted_(false),
-        has_run_message_loop_(false),
-        base_profile_(base_profile) {
-    PersonalDataManagerFactory::GetForProfile(base_profile_)->AddObserver(this);
-  }
-
-  PdmChangeWaiter(const PdmChangeWaiter&) = delete;
-  PdmChangeWaiter& operator=(const PdmChangeWaiter&) = delete;
-
-  ~PdmChangeWaiter() override {}
-
-  // PersonalDataManagerObserver:
-  void OnPersonalDataChanged() override {
-    if (has_run_message_loop_) {
-      base::RunLoop::QuitCurrentWhenIdleDeprecated();
-      has_run_message_loop_ = false;
-    }
-    alerted_ = true;
-  }
-
-  void OnInsufficientFormData() override { OnPersonalDataChanged(); }
-
-  void Wait() {
-    if (!alerted_) {
-      has_run_message_loop_ = true;
-      content::RunMessageLoop();
-    }
-    PersonalDataManagerFactory::GetForProfile(base_profile_)
-        ->RemoveObserver(this);
-  }
-
- private:
-  bool alerted_;
-  bool has_run_message_loop_;
-  raw_ptr<Profile> base_profile_;
-};
-
 static PersonalDataManager* GetPersonalDataManager(Profile* profile) {
   return PersonalDataManagerFactory::GetForProfile(profile);
 }
 
+PdmChangeWaiter::PdmChangeWaiter(Profile* base_profile)
+    : base_profile_(base_profile) {
+  obs_.Observe(GetPersonalDataManager(base_profile_));
+}
+
+PdmChangeWaiter::~PdmChangeWaiter() = default;
+
+void PdmChangeWaiter::OnPersonalDataChanged() {
+  if (run_loop_.running()) {
+    run_loop_.Quit();
+  }
+  alerted_ = true;
+}
+
+void PdmChangeWaiter::OnInsufficientFormData() {
+  OnPersonalDataChanged();
+}
+
+void PdmChangeWaiter::Wait() {
+  if (!alerted_) {
+    run_loop_.Run();
+  }
+  obs_.Reset();
+}
+
 void AddTestProfile(Profile* base_profile, const AutofillProfile& profile) {
   PdmChangeWaiter observer(base_profile);
   GetPersonalDataManager(base_profile)->AddProfile(profile);
diff --git a/chrome/browser/autofill/autofill_uitest_util.h b/chrome/browser/autofill/autofill_uitest_util.h
index fdb345bb..e09466d3 100644
--- a/chrome/browser/autofill/autofill_uitest_util.h
+++ b/chrome/browser/autofill/autofill_uitest_util.h
@@ -5,7 +5,9 @@
 #ifndef CHROME_BROWSER_AUTOFILL_AUTOFILL_UITEST_UTIL_H_
 #define CHROME_BROWSER_AUTOFILL_AUTOFILL_UITEST_UTIL_H_
 
+#include "base/run_loop.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
+#include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "ui/gfx/geometry/rect_f.h"
 
 class Profile;
@@ -15,6 +17,30 @@
 class AutofillProfile;
 class CreditCard;
 
+// This class is used to wait for asynchronous updates to PersonalDataManager
+// to complete.
+class PdmChangeWaiter : public PersonalDataManagerObserver {
+ public:
+  explicit PdmChangeWaiter(Profile* base_profile);
+
+  PdmChangeWaiter(const PdmChangeWaiter&) = delete;
+  PdmChangeWaiter& operator=(const PdmChangeWaiter&) = delete;
+
+  ~PdmChangeWaiter() override;
+
+  // PersonalDataManagerObserver:
+  void OnPersonalDataChanged() override;
+  void OnInsufficientFormData() override;
+
+  void Wait();
+
+ private:
+  bool alerted_ = false;
+  base::RunLoop run_loop_{base::RunLoop::Type::kNestableTasksAllowed};
+  raw_ptr<Profile> base_profile_ = nullptr;
+  base::ScopedObservation<PersonalDataManager, PdmChangeWaiter> obs_{this};
+};
+
 void AddTestProfile(Profile* base_profile, const AutofillProfile& profile);
 void AddTestCreditCard(Profile* base_profile, const CreditCard& card);
 void AddTestServerCreditCard(Profile* base_profile, const CreditCard& card);
diff --git a/chrome/browser/browser_process_platform_part_ash.cc b/chrome/browser/browser_process_platform_part_ash.cc
index 8cfb796..0549a8d 100644
--- a/chrome/browser/browser_process_platform_part_ash.cc
+++ b/chrome/browser/browser_process_platform_part_ash.cc
@@ -253,7 +253,8 @@
 BrowserProcessPlatformPart::GetTimezoneResolverManager() {
   if (!timezone_resolver_manager_.get()) {
     timezone_resolver_manager_ =
-        std::make_unique<ash::system::TimeZoneResolverManager>();
+        std::make_unique<ash::system::TimeZoneResolverManager>(
+            ash::SimpleGeolocationProvider::GetInstance());
   }
   return timezone_resolver_manager_.get();
 }
@@ -262,8 +263,8 @@
   if (!timezone_resolver_.get()) {
     timezone_resolver_ = std::make_unique<ash::TimeZoneResolver>(
         GetTimezoneResolverManager(),
+        ash::SimpleGeolocationProvider::GetInstance(),
         g_browser_process->shared_url_loader_factory(),
-        ash::SimpleGeolocationProvider::DefaultGeolocationProviderURL(),
         base::BindRepeating(&ash::system::ApplyTimeZone),
         base::BindRepeating(&ash::DelayNetworkCall),
         g_browser_process->local_state());
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
index f88e23df..4dbe4af5 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -109,8 +109,8 @@
 #include "components/open_from_clipboard/clipboard_recent_content.h"
 #include "components/password_manager/core/browser/features/password_features.h"
 #include "components/password_manager/core/browser/features/password_manager_features_util.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_store/smart_bubble_stats_store.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
 #include "components/payments/content/payment_manifest_web_data_service.h"
 #include "components/permissions/permission_actions_history.h"
 #include "components/permissions/permission_decision_auto_blocker.h"
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index 98d149de..01b18f8 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -125,8 +125,8 @@
 #include "components/password_manager/core/browser/mock_password_store_interface.h"
 #include "components/password_manager/core/browser/mock_smart_bubble_stats_store.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/payments/content/mock_payment_manifest_web_data_service.h"
 #include "components/permissions/features.h"
 #include "components/permissions/permission_actions_history.h"
diff --git a/chrome/browser/browsing_data/counters/browsing_data_counter_factory.cc b/chrome/browser/browsing_data/counters/browsing_data_counter_factory.cc
index d1987f3..f3ede720 100644
--- a/chrome/browser/browsing_data/counters/browsing_data_counter_factory.cc
+++ b/chrome/browser/browsing_data/counters/browsing_data_counter_factory.cc
@@ -30,7 +30,7 @@
 #include "components/browsing_data/core/counters/passwords_counter.h"
 #include "components/browsing_data/core/pref_names.h"
 #include "components/history/core/browser/web_history_service.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/sync/service/sync_service.h"
 #include "extensions/buildflags/buildflags.h"
 
diff --git a/chrome/browser/browsing_data/counters/passwords_counter_browsertest.cc b/chrome/browser/browsing_data/counters/passwords_counter_browsertest.cc
index d8195bc..dba81047 100644
--- a/chrome/browser/browsing_data/counters/passwords_counter_browsertest.cc
+++ b/chrome/browser/browsing_data/counters/passwords_counter_browsertest.cc
@@ -19,7 +19,7 @@
 #include "components/browsing_data/core/counters/passwords_counter.h"
 #include "components/browsing_data/core/pref_names.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/browsing_data/counters/signin_data_counter.cc b/chrome/browser/browsing_data/counters/signin_data_counter.cc
index 81b4960..da3aef82 100644
--- a/chrome/browser/browsing_data/counters/signin_data_counter.cc
+++ b/chrome/browser/browsing_data/counters/signin_data_counter.cc
@@ -6,7 +6,8 @@
 
 #include <string>
 #include <utility>
-#include "components/password_manager/core/browser/password_store_interface.h"
+
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 namespace browsing_data {
 
diff --git a/chrome/browser/browsing_data/counters/sync_aware_counter_browsertest.cc b/chrome/browser/browsing_data/counters/sync_aware_counter_browsertest.cc
index 1780e61..3b24b7f 100644
--- a/chrome/browser/browsing_data/counters/sync_aware_counter_browsertest.cc
+++ b/chrome/browser/browsing_data/counters/sync_aware_counter_browsertest.cc
@@ -26,7 +26,7 @@
 #include "components/browsing_data/core/pref_names.h"
 #include "components/history/core/browser/web_history_service.h"
 #include "components/history/core/test/fake_web_history_service.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/prefs/pref_service.h"
 #include "components/sync/service/sync_service_impl.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chrome_content_browser_client_unittest.cc b/chrome/browser/chrome_content_browser_client_unittest.cc
index b116e96..c7673a6 100644
--- a/chrome/browser/chrome_content_browser_client_unittest.cc
+++ b/chrome/browser/chrome_content_browser_client_unittest.cc
@@ -10,6 +10,8 @@
 
 #include "ash/webui/camera_app_ui/url_constants.h"
 #include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_file.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/memory/raw_ptr.h"
@@ -18,11 +20,13 @@
 #include "base/run_loop.h"
 #include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/gmock_callback_support.h"
 #include "base/test/gtest_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_command_line.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/test/test_future.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -44,6 +48,8 @@
 #include "components/browsing_data/content/browsing_data_helper.h"
 #include "components/captive_portal/core/buildflags.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/file_access/scoped_file_access.h"
+#include "components/file_access/test/mock_scoped_file_access_delegate.h"
 #include "components/network_session_configurator/common/network_switches.h"
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/privacy_sandbox/privacy_sandbox_features.h"
@@ -77,7 +83,6 @@
 #include "url/origin.h"
 
 #if !BUILDFLAG(IS_ANDROID)
-#include "base/test/test_future.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -1201,6 +1206,36 @@
 }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+#if BUILDFLAG(IS_CHROMEOS)
+TEST_F(ChromeContentBrowserClientTest, RequestFileAccessAllow) {
+  file_access::MockScopedFileAccessDelegate scoped_file_access;
+  base::test::TestFuture<file_access::ScopedFileAccess> continuation_callback;
+  base::FilePath path = base::FilePath(FILE_PATH_LITERAL("/path/to/file"));
+  EXPECT_CALL(scoped_file_access,
+              RequestFilesAccess(testing::ElementsAre(path), GURL(), _))
+      .WillOnce(base::test::RunOnceCallback<2>(
+          file_access::ScopedFileAccess::Allowed()));
+  ChromeContentBrowserClient client;
+  client.RequestFilesAccess({path}, GURL(),
+                            continuation_callback.GetCallback());
+  EXPECT_TRUE(continuation_callback.Take().is_allowed());
+}
+
+TEST_F(ChromeContentBrowserClientTest, RequestFileAccessDeny) {
+  file_access::MockScopedFileAccessDelegate scoped_file_access;
+  base::test::TestFuture<file_access::ScopedFileAccess> continuation_callback;
+  base::FilePath path = base::FilePath(FILE_PATH_LITERAL("/path/to/file"));
+  EXPECT_CALL(scoped_file_access,
+              RequestFilesAccess(testing::ElementsAre(path), GURL(), _))
+      .WillOnce(base::test::RunOnceCallback<2>(
+          file_access::ScopedFileAccess::Denied()));
+  ChromeContentBrowserClient client;
+  client.RequestFilesAccess({path}, GURL(),
+                            continuation_callback.GetCallback());
+  EXPECT_FALSE(continuation_callback.Take().is_allowed());
+}
+#endif  // BUILDFLAG(IS_CHROMEOS)
+
 class ChromeContentBrowserClientSwitchTest
     : public ChromeRenderViewHostTestHarness {
  public:
diff --git a/chrome/browser/chrome_for_testing/chrome_for_testing_info_bar_browsertest.cc b/chrome/browser/chrome_for_testing/chrome_for_testing_info_bar_browsertest.cc
index 60e78fd..92fc9f2 100644
--- a/chrome/browser/chrome_for_testing/chrome_for_testing_info_bar_browsertest.cc
+++ b/chrome/browser/chrome_for_testing/chrome_for_testing_info_bar_browsertest.cc
@@ -12,6 +12,7 @@
 #include "components/infobars/content/content_infobar_manager.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/infobars/core/infobar.h"
+#include "components/infobars/core/infobars_switches.h"
 #include "content/public/test/browser_test.h"
 
 namespace {
@@ -72,3 +73,36 @@
               test_infobar->GetIdentifier());
   }
 }
+
+// Subclass for tests that require infobars to be disabled.
+class ChromeForTestingInfoBarDisabledTest : public ChromeForTestingInfoBarTest {
+ public:
+  ChromeForTestingInfoBarDisabledTest() = default;
+
+  ChromeForTestingInfoBarDisabledTest(
+      const ChromeForTestingInfoBarDisabledTest&) = delete;
+  ChromeForTestingInfoBarDisabledTest& operator=(
+      const ChromeForTestingInfoBarDisabledTest&) = delete;
+
+  ~ChromeForTestingInfoBarDisabledTest() override = default;
+
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(infobars::switches::kDisableInfoBars);
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(ChromeForTestingInfoBarDisabledTest,
+                       NoInfoBarAppearsInitially) {
+  ASSERT_EQ(0u, GetInfoBarManagerFromTabIndex(0)->infobars().size());
+}
+
+IN_PROC_BROWSER_TEST_F(ChromeForTestingInfoBarDisabledTest,
+                       NoInfoBarAppearsInNewTabs) {
+  ASSERT_EQ(0u, GetInfoBarManagerFromTabIndex(0)->infobars().size());
+
+  // Open a second tab in the same window.
+  chrome::AddTabAt(browser(), GURL("about:blank"), -1, true);
+
+  ASSERT_EQ(0u, GetInfoBarManagerFromTabIndex(1)->infobars().size());
+}
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_confidential_file_unittest.cc b/chrome/browser/chromeos/policy/dlp/dlp_confidential_file_unittest.cc
index e5380ef..d2acd08 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_confidential_file_unittest.cc
+++ b/chrome/browser/chromeos/policy/dlp/dlp_confidential_file_unittest.cc
@@ -28,6 +28,10 @@
   DlpConfidentialFile file2 = DlpConfidentialFile(base::FilePath(kFilePath2));
 
   EXPECT_TRUE(file1 != file2);
+  EXPECT_TRUE(file1 < file2);
+  EXPECT_TRUE(file1 <= file2);
+  EXPECT_FALSE(file1 > file2);
+  EXPECT_FALSE(file1 >= file2);
 }
 
 TEST_F(DlpConfidentialFileTest, ComparisonWithSamePaths) {
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.cc
index 089fdb8b..729124be 100644
--- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.cc
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h"
 
 #include <memory>
+#include <optional>
 
 #include "base/check.h"
 #include "base/check_op.h"
@@ -26,7 +27,7 @@
   crypto::SignatureVerifier::SignatureAlgorithm Algorithm() const override;
   std::vector<uint8_t> GetSubjectPublicKeyInfo() const override;
   std::vector<uint8_t> GetWrappedKey() const override;
-  absl::optional<std::vector<uint8_t>> SignSlowly(
+  std::optional<std::vector<uint8_t>> SignSlowly(
       base::span<const uint8_t> data) override;
 
  private:
@@ -63,7 +64,7 @@
   return wrapped;
 }
 
-absl::optional<std::vector<uint8_t>> ECSigningKey::SignSlowly(
+std::optional<std::vector<uint8_t>> ECSigningKey::SignSlowly(
     base::span<const uint8_t> data) {
   std::vector<uint8_t> signature;
   auto signer = crypto::ECSignatureCreator::Create(key_.get());
@@ -78,7 +79,7 @@
 ECSigningKeyProvider::ECSigningKeyProvider() = default;
 ECSigningKeyProvider::~ECSigningKeyProvider() = default;
 
-absl::optional<crypto::SignatureVerifier::SignatureAlgorithm>
+std::optional<crypto::SignatureVerifier::SignatureAlgorithm>
 ECSigningKeyProvider::SelectAlgorithm(
     base::span<const crypto::SignatureVerifier::SignatureAlgorithm>
         acceptable_algorithms) {
@@ -87,7 +88,7 @@
       return crypto::SignatureVerifier::ECDSA_SHA256;
   }
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 std::unique_ptr<crypto::UnexportableSigningKey>
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h
index c2ddc155..66329d0 100644
--- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h
@@ -21,7 +21,7 @@
   ~ECSigningKeyProvider() override;
 
   // crypto::UnexportableKeyProvider:
-  absl::optional<crypto::SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
+  std::optional<crypto::SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
       base::span<const crypto::SignatureVerifier::SignatureAlgorithm>
           acceptable_algorithms) override;
   std::unique_ptr<crypto::UnexportableSigningKey> GenerateSigningKeySlowly(
diff --git a/chrome/browser/extensions/api/enterprise_kiosk_input/OWNERS b/chrome/browser/extensions/api/enterprise_kiosk_input/OWNERS
index aa95e1d..471d601 100644
--- a/chrome/browser/extensions/api/enterprise_kiosk_input/OWNERS
+++ b/chrome/browser/extensions/api/enterprise_kiosk_input/OWNERS
@@ -1,2 +1 @@
-eariassoto@google.com
 file://chrome/browser/ash/app_mode/OWNERS
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index a3d023a..e2da15b 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -659,9 +659,9 @@
 
     std::set<std::string> result_ids;
     for (const base::Value& item : results) {
-      std::unique_ptr<api::identity::AccountInfo> info =
-          api::identity::AccountInfo::FromValueDeprecated(item);
-      if (info.get()) {
+      absl::optional<api::identity::AccountInfo> info =
+          api::identity::AccountInfo::FromValue(item);
+      if (info) {
         result_ids.insert(info->id);
       } else {
         return GenerateFailureResult(gaia_ids, &results);
@@ -688,12 +688,13 @@
       msg << "NULL";
     } else {
       for (const auto& result : *results) {
-        std::unique_ptr<api::identity::AccountInfo> info =
-            api::identity::AccountInfo::FromValueDeprecated(result);
-        if (info.get())
+        absl::optional<api::identity::AccountInfo> info =
+            api::identity::AccountInfo::FromValue(result);
+        if (info) {
           msg << info->id << " ";
-        else
+        } else {
           msg << result << "<-" << result.type() << " ";
+        }
       }
     }
 
@@ -740,24 +741,24 @@
 
 class IdentityGetProfileUserInfoFunctionTest : public IdentityTestWithSignin {
  protected:
-  std::unique_ptr<api::identity::ProfileUserInfo> RunGetProfileUserInfo() {
+  absl::optional<api::identity::ProfileUserInfo> RunGetProfileUserInfo() {
     scoped_refptr<IdentityGetProfileUserInfoFunction> func(
         new IdentityGetProfileUserInfoFunction);
     func->set_extension(
         ExtensionBuilder("Test").SetID(kExtensionId).Build().get());
     absl::optional<base::Value> value = utils::RunFunctionAndReturnSingleResult(
         func.get(), "[]", browser()->profile());
-    return api::identity::ProfileUserInfo::FromValueDeprecated(*value);
+    return api::identity::ProfileUserInfo::FromValue(*value);
   }
 
-  std::unique_ptr<api::identity::ProfileUserInfo>
+  absl::optional<api::identity::ProfileUserInfo>
   RunGetProfileUserInfoWithEmail() {
     scoped_refptr<IdentityGetProfileUserInfoFunction> func(
         new IdentityGetProfileUserInfoFunction);
     func->set_extension(CreateExtensionWithEmailPermission());
     absl::optional<base::Value> value = utils::RunFunctionAndReturnSingleResult(
         func.get(), "[]", browser()->profile());
-    return api::identity::ProfileUserInfo::FromValueDeprecated(*value);
+    return api::identity::ProfileUserInfo::FromValue(*value);
   }
 
   scoped_refptr<const Extension> CreateExtensionWithEmailPermission() {
@@ -766,7 +767,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest, NotSignedIn) {
-  std::unique_ptr<api::identity::ProfileUserInfo> info =
+  absl::optional<api::identity::ProfileUserInfo> info =
       RunGetProfileUserInfoWithEmail();
   EXPECT_TRUE(info->email.empty());
   EXPECT_TRUE(info->id.empty());
@@ -774,7 +775,7 @@
 
 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest, SignedIn) {
   SignIn("president@example.com");
-  std::unique_ptr<api::identity::ProfileUserInfo> info =
+  absl::optional<api::identity::ProfileUserInfo> info =
       RunGetProfileUserInfoWithEmail();
   EXPECT_EQ("president@example.com", info->email);
   EXPECT_EQ("gaia_id_for_president_example.com", info->id);
@@ -784,7 +785,7 @@
                        SignedInUnconsented) {
   identity_test_env()->MakePrimaryAccountAvailable(
       "test@example.com", signin::ConsentLevel::kSignin);
-  std::unique_ptr<api::identity::ProfileUserInfo> info =
+  absl::optional<api::identity::ProfileUserInfo> info =
       RunGetProfileUserInfoWithEmail();
   EXPECT_TRUE(info->email.empty());
   EXPECT_TRUE(info->id.empty());
@@ -792,8 +793,7 @@
 
 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,
                        NotSignedInNoEmail) {
-  std::unique_ptr<api::identity::ProfileUserInfo> info =
-      RunGetProfileUserInfo();
+  absl::optional<api::identity::ProfileUserInfo> info = RunGetProfileUserInfo();
   EXPECT_TRUE(info->email.empty());
   EXPECT_TRUE(info->id.empty());
 }
@@ -801,8 +801,7 @@
 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,
                        SignedInNoEmail) {
   SignIn("president@example.com");
-  std::unique_ptr<api::identity::ProfileUserInfo> info =
-      RunGetProfileUserInfo();
+  absl::optional<api::identity::ProfileUserInfo> info = RunGetProfileUserInfo();
   EXPECT_TRUE(info->email.empty());
   EXPECT_TRUE(info->id.empty());
 }
@@ -811,7 +810,7 @@
     : public IdentityGetProfileUserInfoFunctionTest,
       public ::testing::WithParamInterface<std::string> {
  protected:
-  std::unique_ptr<api::identity::ProfileUserInfo>
+  absl::optional<api::identity::ProfileUserInfo>
   RunGetProfileUserInfoWithAccountStatus() {
     scoped_refptr<IdentityGetProfileUserInfoFunction> func(
         new IdentityGetProfileUserInfoFunction);
@@ -820,7 +819,7 @@
                                           account_status().c_str());
     absl::optional<base::Value> value = utils::RunFunctionAndReturnSingleResult(
         func.get(), args, browser()->profile());
-    return api::identity::ProfileUserInfo::FromValueDeprecated(*value);
+    return api::identity::ProfileUserInfo::FromValue(*value);
   }
 
   std::string account_status() { return GetParam(); }
@@ -834,7 +833,7 @@
 IN_PROC_BROWSER_TEST_P(
     IdentityGetProfileUserInfoFunctionTestWithAccountStatusParam,
     NotSignedIn) {
-  std::unique_ptr<api::identity::ProfileUserInfo> info =
+  absl::optional<api::identity::ProfileUserInfo> info =
       RunGetProfileUserInfoWithAccountStatus();
   EXPECT_TRUE(info->email.empty());
   EXPECT_TRUE(info->id.empty());
@@ -844,7 +843,7 @@
     IdentityGetProfileUserInfoFunctionTestWithAccountStatusParam,
     SignedIn) {
   SignIn("test@example.com");
-  std::unique_ptr<api::identity::ProfileUserInfo> info =
+  absl::optional<api::identity::ProfileUserInfo> info =
       RunGetProfileUserInfoWithAccountStatus();
   EXPECT_EQ("test@example.com", info->email);
   EXPECT_EQ("gaia_id_for_test_example.com", info->id);
@@ -855,7 +854,7 @@
     SignedInUnconsented) {
   identity_test_env()->MakePrimaryAccountAvailable(
       "test@example.com", signin::ConsentLevel::kSignin);
-  std::unique_ptr<api::identity::ProfileUserInfo> info =
+  absl::optional<api::identity::ProfileUserInfo> info =
       RunGetProfileUserInfoWithAccountStatus();
   // The unconsented (Sync off) primary account is returned conditionally,
   // depending on the accountStatus parameter.
@@ -1009,8 +1008,8 @@
         utils::RunFunctionAndReturnSingleResult(function, args,
                                                 browser->profile());
     ASSERT_TRUE(result_value);
-    std::unique_ptr<api::identity::GetAuthTokenResult> result =
-        api::identity::GetAuthTokenResult::FromValueDeprecated(*result_value);
+    absl::optional<api::identity::GetAuthTokenResult> result =
+        api::identity::GetAuthTokenResult::FromValue(*result_value);
     ASSERT_TRUE(result);
 
     EXPECT_TRUE(result->token);
@@ -1032,8 +1031,8 @@
     } else {
       function_runner->WaitForOneResult(function, &result_value);
     }
-    std::unique_ptr<api::identity::GetAuthTokenResult> result =
-        api::identity::GetAuthTokenResult::FromValueDeprecated(result_value);
+    absl::optional<api::identity::GetAuthTokenResult> result =
+        api::identity::GetAuthTokenResult::FromValue(result_value);
     ASSERT_TRUE(result);
 
     ASSERT_TRUE(result->token);
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc b/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
index 511c87b..a39d102 100644
--- a/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
+++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
@@ -401,6 +401,13 @@
   return &insecure_credentials_manager_;
 }
 
+void PasswordCheckDelegate::OnBulkCheckServiceShutDown() {
+  // Stop observing BulkLeakCheckService when the service shuts down.
+  CHECK(observed_bulk_leak_check_service_.IsObservingSource(
+      BulkLeakCheckServiceFactory::GetForProfile(profile_)));
+  observed_bulk_leak_check_service_.Reset();
+}
+
 void PasswordCheckDelegate::OnSavedPasswordsChanged(
     const password_manager::PasswordStoreChangeList& changes) {
   // Getting the first notification about a change in saved passwords implies
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate.h b/chrome/browser/extensions/api/passwords_private/password_check_delegate.h
index f0264b5..f7689c3 100644
--- a/chrome/browser/extensions/api/passwords_private/password_check_delegate.h
+++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate.h
@@ -106,6 +106,7 @@
       password_manager::BulkLeakCheckService::State state) override;
   void OnCredentialDone(const password_manager::LeakCheckCredential& credential,
                         password_manager::IsLeaked is_leaked) override;
+  void OnBulkCheckServiceShutDown() override;
 
   // Starts the analyses of whether credentials are compromised and/or weak.
   // Assumes that `StartPasswordCheck()` was called prior.
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index cbf85ca..0c1a05d5 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -4422,6 +4422,11 @@
     "expiry_milestone": 130
   },
   {
+    "name": "fullscreen-improvement",
+    "owners": [ "alionadangla@google.com", "ajuma@google.com" ],
+    "expiry_milestone": 130
+  },
+  {
     "name": "fullscreen-popup-windows",
     "owners": [ "btriebw@chromium.org", "msw@chromium.org" ],
     "expiry_milestone": 125
diff --git a/chrome/browser/importer/profile_writer.cc b/chrome/browser/importer/profile_writer.cc
index d7782740..c72b8153 100644
--- a/chrome/browser/importer/profile_writer.cc
+++ b/chrome/browser/importer/profile_writer.cc
@@ -31,7 +31,7 @@
 #include "components/favicon/core/favicon_service.h"
 #include "components/history/core/browser/history_service.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "components/search_engines/template_url.h"
diff --git a/chrome/browser/password_manager/account_password_store_factory.cc b/chrome/browser/password_manager/account_password_store_factory.cc
index 775e5059..cfdb3c92 100644
--- a/chrome/browser/password_manager/account_password_store_factory.cc
+++ b/chrome/browser/password_manager/account_password_store_factory.cc
@@ -30,8 +30,8 @@
 #include "components/password_manager/core/browser/password_reuse_manager.h"
 #include "components/password_manager/core/browser/password_store/login_database.h"
 #include "components/password_manager/core/browser/password_store/password_store_built_in_backend.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_store_factory_util.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/network_service_instance.h"
diff --git a/chrome/browser/password_manager/account_password_store_factory.h b/chrome/browser/password_manager/account_password_store_factory.h
index 9e477a56..76fa1b33 100644
--- a/chrome/browser/password_manager/account_password_store_factory.h
+++ b/chrome/browser/password_manager/account_password_store_factory.h
@@ -8,7 +8,7 @@
 #include "base/no_destructor.h"
 #include "components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h"
 #include "components/keyed_service/core/service_access_type.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 class Profile;
 
diff --git a/chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller.cc b/chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller.cc
index 43e700f..84cd2297 100644
--- a/chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller.cc
+++ b/chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller.cc
@@ -18,7 +18,7 @@
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_manager_driver.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/gfx/native_widget_types.h"
diff --git a/chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller.h b/chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller.h
index 303e5c5..4455d44 100644
--- a/chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller.h
+++ b/chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller.h
@@ -13,7 +13,7 @@
 #include "components/autofill/core/common/mojom/autofill_types.mojom-forward.h"
 #include "components/device_reauth/device_authenticator.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "ui/gfx/native_widget_types.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/password_manager/android/all_passwords_bottom_sheet_helper.cc b/chrome/browser/password_manager/android/all_passwords_bottom_sheet_helper.cc
index dbb0498..5d7b55c 100644
--- a/chrome/browser/password_manager/android/all_passwords_bottom_sheet_helper.cc
+++ b/chrome/browser/password_manager/android/all_passwords_bottom_sheet_helper.cc
@@ -7,7 +7,7 @@
 #include "base/functional/not_fn.h"
 #include "base/ranges/algorithm.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 AllPasswordsBottomSheetHelper::AllPasswordsBottomSheetHelper(
     password_manager::PasswordStoreInterface* store) {
diff --git a/chrome/browser/password_manager/android/all_passwords_bottom_sheet_helper.h b/chrome/browser/password_manager/android/all_passwords_bottom_sheet_helper.h
index 61a2ce55..77ad730 100644
--- a/chrome/browser/password_manager/android/all_passwords_bottom_sheet_helper.h
+++ b/chrome/browser/password_manager/android/all_passwords_bottom_sheet_helper.h
@@ -8,7 +8,7 @@
 #include "base/functional/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 // This class helps to determine the visibility of the "All Passwords Sheet"
diff --git a/chrome/browser/password_manager/android/password_manager_error_message_delegate.h b/chrome/browser/password_manager/android/password_manager_error_message_delegate.h
index bb5fb205..1f5b26b 100644
--- a/chrome/browser/password_manager/android/password_manager_error_message_delegate.h
+++ b/chrome/browser/password_manager/android/password_manager_error_message_delegate.h
@@ -10,7 +10,7 @@
 #include "chrome/browser/password_manager/android/password_manager_error_message_helper_bridge.h"
 #include "components/messages/android/message_wrapper.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
-#include "components/password_manager/core/browser/password_store_backend_error.h"
+#include "components/password_manager/core/browser/password_store/password_store_backend_error.h"
 #include "components/prefs/pref_service.h"
 
 namespace content {
diff --git a/chrome/browser/password_manager/android/password_migration_warning_startup_launcher.cc b/chrome/browser/password_manager/android/password_migration_warning_startup_launcher.cc
index 3b78095e..a52617f 100644
--- a/chrome/browser/password_manager/android/password_migration_warning_startup_launcher.cc
+++ b/chrome/browser/password_manager/android/password_migration_warning_startup_launcher.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/password_manager/profile_password_store_factory.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_store/password_store_backend.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/password_manager/android/password_migration_warning_startup_launcher.h b/chrome/browser/password_manager/android/password_migration_warning_startup_launcher.h
index b3232d6..ad036dbb 100644
--- a/chrome/browser/password_manager/android/password_migration_warning_startup_launcher.h
+++ b/chrome/browser/password_manager/android/password_migration_warning_startup_launcher.h
@@ -8,7 +8,7 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "content/public/browser/web_contents.h"
 
 // Helper class used to launch the password migration warning on startup.
diff --git a/chrome/browser/password_manager/android/password_migration_warning_startup_launcher_unittest.cc b/chrome/browser/password_manager/android/password_migration_warning_startup_launcher_unittest.cc
index de44c52..f0d7e8e 100644
--- a/chrome/browser/password_manager/android/password_migration_warning_startup_launcher_unittest.cc
+++ b/chrome/browser/password_manager/android/password_migration_warning_startup_launcher_unittest.cc
@@ -13,8 +13,8 @@
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/password_manager/core/browser/mock_password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_store/test_password_store.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/password_manager/android/password_store_android_backend.cc b/chrome/browser/password_manager/android/password_store_android_backend.cc
index d4dbcff..cf08379 100644
--- a/chrome/browser/password_manager/android/password_store_android_backend.cc
+++ b/chrome/browser/password_manager/android/password_store_android_backend.cc
@@ -42,8 +42,8 @@
 #include "components/password_manager/core/browser/password_store/android_backend_error.h"
 #include "components/password_manager/core/browser/password_store/get_logins_with_affiliations_request_handler.h"
 #include "components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder.h"
+#include "components/password_manager/core/browser/password_store/password_store_util.h"
 #include "components/password_manager/core/browser/password_store/psl_matching_helper.h"
-#include "components/password_manager/core/browser/password_store_util.h"
 #include "components/password_manager/core/browser/password_sync_util.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/password_manager/android/password_store_bridge.h b/chrome/browser/password_manager/android/password_store_bridge.h
index d50c478..2673ea2a 100644
--- a/chrome/browser/password_manager/android/password_store_bridge.h
+++ b/chrome/browser/password_manager/android/password_store_bridge.h
@@ -15,7 +15,7 @@
 #include "chrome/browser/password_manager/profile_password_store_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
 
 class PasswordStoreBridge
diff --git a/chrome/browser/password_manager/android/password_store_proxy_backend.cc b/chrome/browser/password_manager/android/password_store_proxy_backend.cc
index 7109b9f..4856d10 100644
--- a/chrome/browser/password_manager/android/password_store_proxy_backend.cc
+++ b/chrome/browser/password_manager/android/password_store_proxy_backend.cc
@@ -18,7 +18,7 @@
 #include "base/notreached.h"
 #include "base/ranges/algorithm.h"
 #include "base/strings/strcat.h"
-#include "components/password_manager/core/browser/password_store_backend_error.h"
+#include "components/password_manager/core/browser/password_store/password_store_backend_error.h"
 #include "components/password_manager/core/browser/password_sync_util.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
diff --git a/chrome/browser/password_manager/android/password_store_proxy_backend.h b/chrome/browser/password_manager/android/password_store_proxy_backend.h
index 085db8c..a6a5921 100644
--- a/chrome/browser/password_manager/android/password_store_proxy_backend.h
+++ b/chrome/browser/password_manager/android/password_store_proxy_backend.h
@@ -12,7 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/types/strong_alias.h"
 #include "components/password_manager/core/browser/password_store/password_store_backend.h"
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class PrefService;
diff --git a/chrome/browser/password_manager/android/password_store_proxy_backend_unittest.cc b/chrome/browser/password_manager/android/password_store_proxy_backend_unittest.cc
index f54887ca..9aaad94 100644
--- a/chrome/browser/password_manager/android/password_store_proxy_backend_unittest.cc
+++ b/chrome/browser/password_manager/android/password_store_proxy_backend_unittest.cc
@@ -18,8 +18,8 @@
 #include "components/password_manager/core/browser/password_form_digest.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
 #include "components/password_manager/core/browser/password_store/mock_password_store_backend.h"
-#include "components/password_manager/core/browser/password_store_backend_error.h"
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_backend_error.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_registry_simple.h"
diff --git a/chrome/browser/password_manager/android/password_ui_view_android.h b/chrome/browser/password_manager/android/password_ui_view_android.h
index 0d414c5..93612ae 100644
--- a/chrome/browser/password_manager/android/password_ui_view_android.h
+++ b/chrome/browser/password_manager/android/password_ui_view_android.h
@@ -20,7 +20,7 @@
 #include "chrome/browser/password_manager/profile_password_store_factory.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
 
 namespace password_manager {
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h
index 243c6fb..ce4877a 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.h
+++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -28,7 +28,7 @@
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_manager_client_helper.h"
 #include "components/password_manager/core/browser/password_manager_metrics_recorder.h"
-#include "components/password_manager/core/browser/password_store_backend_error.h"
+#include "components/password_manager/core/browser/password_store/password_store_backend_error.h"
 #include "components/prefs/pref_member.h"
 #include "components/safe_browsing/buildflags.h"
 #include "components/signin/public/base/signin_buildflags.h"
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
index 86eea57..c3c0207 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -54,7 +54,7 @@
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "components/safe_browsing/buildflags.h"
 #include "components/safe_browsing/core/common/features.h"
 #include "components/sessions/content/content_record_password_state.h"
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index 789c125..7ce3672 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -66,8 +66,8 @@
 #include "components/password_manager/core/browser/password_form_manager.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_manager_driver.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_store/test_password_store.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
 #include "components/signin/public/base/signin_buildflags.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_task_traits.h"
diff --git a/chrome/browser/password_manager/password_manager_test_base.h b/chrome/browser/password_manager/password_manager_test_base.h
index 517edd4..197f3e2 100644
--- a/chrome/browser/password_manager/password_manager_test_base.h
+++ b/chrome/browser/password_manager/password_manager_test_base.h
@@ -14,7 +14,7 @@
 #include "chrome/browser/ssl/cert_verifier_browser_test.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
diff --git a/chrome/browser/password_manager/password_reuse_manager_factory.cc b/chrome/browser/password_manager/password_reuse_manager_factory.cc
index 5c1fc634..721b6155 100644
--- a/chrome/browser/password_manager/password_reuse_manager_factory.cc
+++ b/chrome/browser/password_manager/password_reuse_manager_factory.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/password_manager/core/browser/password_reuse_manager_impl.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_store_signin_notifier_impl.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
diff --git a/chrome/browser/password_manager/password_store_utils.cc b/chrome/browser/password_manager/password_store_utils.cc
index e162ee8..d1f51bae 100644
--- a/chrome/browser/password_manager/password_store_utils.cc
+++ b/chrome/browser/password_manager/password_store_utils.cc
@@ -16,7 +16,7 @@
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/sync/sync_service_factory.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/store_metrics_reporter.h"
 #include "components/safe_browsing/buildflags.h"
 
diff --git a/chrome/browser/password_manager/profile_password_store_factory.h b/chrome/browser/password_manager/profile_password_store_factory.h
index 6d165aa2..b7b0589 100644
--- a/chrome/browser/password_manager/profile_password_store_factory.h
+++ b/chrome/browser/password_manager/profile_password_store_factory.h
@@ -9,7 +9,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/profiles/refcounted_profile_keyed_service_factory.h"
 #include "components/keyed_service/core/service_access_type.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 class Profile;
 
diff --git a/chrome/browser/profiles/profile_manager_browsertest.cc b/chrome/browser/profiles/profile_manager_browsertest.cc
index 99aed06..91c3aae 100644
--- a/chrome/browser/profiles/profile_manager_browsertest.cc
+++ b/chrome/browser/profiles/profile_manager_browsertest.cc
@@ -47,8 +47,8 @@
 #include "components/keep_alive_registry/scoped_keep_alive.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/resources/chromeos/quickoffice b/chrome/browser/resources/chromeos/quickoffice
index 23bde34..79e797d 160000
--- a/chrome/browser/resources/chromeos/quickoffice
+++ b/chrome/browser/resources/chromeos/quickoffice
@@ -1 +1 @@
-Subproject commit 23bde3495989fbc0112213613d2498030be51417
+Subproject commit 79e797d69d4675a2f0ef916dbb65457fe9485fc9
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.h b/chrome/browser/safe_browsing/chrome_password_protection_service.h
index 1d56cee6..9e81bf6b 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.h
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.h
@@ -21,7 +21,7 @@
 #include "components/password_manager/core/browser/hash_password_manager.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_reuse_manager.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/safe_browsing/buildflags.h"
 #include "components/safe_browsing/content/browser/password_protection/password_protection_service.h"
diff --git a/chrome/browser/screen_ai/BUILD.gn b/chrome/browser/screen_ai/BUILD.gn
index 3dbca266..1f70b44 100644
--- a/chrome/browser/screen_ai/BUILD.gn
+++ b/chrome/browser/screen_ai/BUILD.gn
@@ -67,7 +67,8 @@
     ":screen_ai_install_state",
     "//chrome/browser/profiles:profile",
     "//components/keyed_service/core",
-    "//components/services/screen_ai/public/mojom",
+    "//components/services/screen_ai/public/mojom:factory",
+    "//components/services/screen_ai/public/mojom:mojom",
     "//content/public/browser",
   ]
 
diff --git a/chrome/browser/screen_ai/screen_ai_service_router.cc b/chrome/browser/screen_ai/screen_ai_service_router.cc
index 62dea07a..70b5b22fd 100644
--- a/chrome/browser/screen_ai/screen_ai_service_router.cc
+++ b/chrome/browser/screen_ai/screen_ai_service_router.cc
@@ -18,6 +18,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/service_process_host.h"
 #include "content/public/browser/service_process_host_passkeys.h"
+#include "mojo/public/mojom/base/file_path.mojom.h"
 
 #if BUILDFLAG(IS_WIN)
 #include "base/strings/utf_string_conversions.h"
@@ -43,7 +44,7 @@
   static std::unique_ptr<ComponentFiles> Load(
       const base::FilePath::CharType* files_list_file_name);
 
-  base::flat_map<std::string, base::File> model_files_;
+  base::flat_map<base::FilePath, base::File> model_files_;
   base::FilePath library_binary_path_;
 };
 
@@ -67,23 +68,22 @@
     return;
   }
 
-  // TODO(b/297824387): Consider fixing file path separators for Windows when
-  // files with sub-directories are added.
   for (auto& relative_file_path : files_list) {
     // Ignore comment lines.
     if (relative_file_path.empty() || relative_file_path[0] == '#') {
       continue;
     }
 
-    const base::FilePath full_path =
 #if BUILDFLAG(IS_WIN)
-        component_folder.Append(base::UTF8ToWide(relative_file_path));
+    base::FilePath relative_path(base::UTF8ToWide(relative_file_path));
 #else
-        component_folder.Append(relative_file_path);
+    base::FilePath relative_path(relative_file_path);
 #endif
-    model_files_[relative_file_path] =
+    const base::FilePath full_path = component_folder.Append(relative_path);
+
+    model_files_[relative_path] =
         base::File(full_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
-    if (!model_files_[relative_file_path].IsValid()) {
+    if (!model_files_[relative_path].IsValid()) {
       VLOG(0) << "Could not open " << full_path;
       model_files_.clear();
       return;
diff --git a/chrome/browser/screen_ai/screen_ai_service_router.h b/chrome/browser/screen_ai/screen_ai_service_router.h
index a4e901c..592e825 100644
--- a/chrome/browser/screen_ai/screen_ai_service_router.h
+++ b/chrome/browser/screen_ai/screen_ai_service_router.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/services/screen_ai/public/mojom/screen_ai_factory.mojom.h"
 #include "components/services/screen_ai/public/mojom/screen_ai_service.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index 25e0d1c..5de1464 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -58,7 +58,7 @@
 #include "components/desks_storage/core/desk_sync_service.h"
 #include "components/history/core/browser/history_service.h"
 #include "components/metrics/demographics/user_demographics.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/sharing/password_receiver_service.h"
 #include "components/password_manager/core/browser/sharing/password_sender_service.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/sync/test/integration/password_manager_sync_test.cc b/chrome/browser/sync/test/integration/password_manager_sync_test.cc
index a3ff6ade..f7329ead 100644
--- a/chrome/browser/sync/test/integration/password_manager_sync_test.cc
+++ b/chrome/browser/sync/test/integration/password_manager_sync_test.cc
@@ -41,7 +41,7 @@
 #include "components/password_manager/core/browser/features/password_manager_features_util.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_sync_util.h"
 #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
 #include "components/password_manager/core/common/password_manager_features.h"
diff --git a/chrome/browser/sync/test/integration/passwords_helper.cc b/chrome/browser/sync/test/integration/passwords_helper.cc
index adb043c..2cdb5d8 100644
--- a/chrome/browser/sync/test/integration/passwords_helper.cc
+++ b/chrome/browser/sync/test/integration/passwords_helper.cc
@@ -21,8 +21,8 @@
 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/sync/password_proto_utils.h"
 #include "components/sync/engine/loopback_server/persistent_unique_client_entity.h"
 #include "components/sync/engine/nigori/key_derivation_params.h"
diff --git a/chrome/browser/sync/test/integration/performance/passwords_sync_perf_test.cc b/chrome/browser/sync/test/integration/performance/passwords_sync_perf_test.cc
index fe9cf58..eb359e0 100644
--- a/chrome/browser/sync/test/integration/performance/passwords_sync_perf_test.cc
+++ b/chrome/browser/sync/test/integration/performance/passwords_sync_perf_test.cc
@@ -8,7 +8,7 @@
 #include "chrome/browser/sync/test/integration/passwords_helper.h"
 #include "chrome/browser/sync/test/integration/performance/sync_timing_helper.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "content/public/test/browser_test.h"
 #include "testing/perf/perf_result_reporter.h"
 
diff --git a/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc b/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc
index 102c509..fb44edb7 100644
--- a/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc
@@ -36,7 +36,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/password_manager/core/browser/features/password_features.h"
 #include "components/password_manager/core/browser/features/password_manager_features_util.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/signin/public/identity_manager/identity_test_utils.h"
 #include "components/sync/base/features.h"
 #include "components/sync/base/model_type.h"
diff --git a/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
index 1eb246c6..45572e6 100644
--- a/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
@@ -19,7 +19,7 @@
 #include "components/password_manager/core/browser/features/password_manager_features_util.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/sync/password_sync_bridge.h"
 #include "components/signin/public/identity_manager/identity_test_utils.h"
 #include "components/sync/base/features.h"
diff --git a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
index 0880244..f820e17b 100644
--- a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
@@ -20,7 +20,7 @@
 #include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
 #include "components/password_manager/core/browser/features/password_manager_features_util.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/sync/base/features.h"
 #include "components/sync/engine/cycle/entity_change_metric_recording.h"
diff --git a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_delegate_android_impl.cc b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_delegate_android_impl.cc
index 076791a..5207c66 100644
--- a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_delegate_android_impl.cc
+++ b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_delegate_android_impl.cc
@@ -247,14 +247,17 @@
                                                         bool is_virtual) {
   HideTouchToFill();
 
+  PersonalDataManager* pdm = manager_->client().GetPersonalDataManager();
+  CHECK(pdm);
+  CreditCard* card = pdm->GetCreditCardByGUID(unique_id);
   if (is_virtual) {
-    manager_->FillOrPreviewVirtualCardInformation(
-        mojom::ActionPersistence::kFill, unique_id, query_form_, query_field_,
+    // Virtual credit cards are not persisted in Chrome, modify record type
+    // locally.
+    CreditCard copy = CreditCard::CreateVirtualCard(*card);
+    manager_->FillOrPreviewCreditCardForm(
+        mojom::ActionPersistence::kFill, query_form_, query_field_, &copy,
         {.trigger_source = AutofillTriggerSource::kTouchToFillCreditCard});
   } else {
-    PersonalDataManager* pdm = manager_->client().GetPersonalDataManager();
-    DCHECK(pdm);
-    CreditCard* card = pdm->GetCreditCardByGUID(unique_id);
     manager_->FillOrPreviewCreditCardForm(
         mojom::ActionPersistence::kFill, query_form_, query_field_, card,
         {.trigger_source = AutofillTriggerSource::kTouchToFillCreditCard});
diff --git a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_delegate_android_impl_unittest.cc b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_delegate_android_impl_unittest.cc
index 043e018..962f601 100644
--- a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_delegate_android_impl_unittest.cc
+++ b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_delegate_android_impl_unittest.cc
@@ -100,13 +100,6 @@
                const CreditCard* credit_card,
                const AutofillTriggerDetails& trigger_details));
   MOCK_METHOD(void,
-              FillOrPreviewVirtualCardInformation,
-              (mojom::ActionPersistence action_persistence,
-               const std::string& guid,
-               const FormData& form,
-               const FormFieldData& field,
-               const AutofillTriggerDetails& trigger_details));
-  MOCK_METHOD(void,
               DidShowSuggestions,
               (bool has_autofill_suggestions,
                const FormData& form,
@@ -704,7 +697,7 @@
   TryToShowTouchToFill(/*expected_success=*/true);
 
   EXPECT_CALL(autofill_client_, HideTouchToFillCreditCard).Times(1);
-  touch_to_fill_delegate_->SuggestionSelected(credit_card.server_id(), false);
+  touch_to_fill_delegate_->SuggestionSelected(credit_card.guid(), false);
 }
 
 TEST_F(TouchToFillDelegateAndroidImplUnitTest, CardSelectionFillsCardForm) {
@@ -715,7 +708,7 @@
   TryToShowTouchToFill(/*expected_success=*/true);
 
   EXPECT_CALL(*browser_autofill_manager_, FillOrPreviewCreditCardForm);
-  touch_to_fill_delegate_->SuggestionSelected(credit_card.server_id(), false);
+  touch_to_fill_delegate_->SuggestionSelected(credit_card.guid(), false);
 }
 
 TEST_F(TouchToFillDelegateAndroidImplUnitTest,
@@ -727,8 +720,8 @@
 
   TryToShowTouchToFill(/*expected_success=*/true);
 
-  EXPECT_CALL(*browser_autofill_manager_, FillOrPreviewVirtualCardInformation);
-  touch_to_fill_delegate_->SuggestionSelected(credit_card.server_id(), true);
+  EXPECT_CALL(*browser_autofill_manager_, FillOrPreviewCreditCardForm);
+  touch_to_fill_delegate_->SuggestionSelected(credit_card.guid(), true);
 }
 
 TEST_F(TouchToFillDelegateAndroidImplUnitTest,
diff --git a/chrome/browser/touch_to_fill/touch_to_fill_controller.cc b/chrome/browser/touch_to_fill/touch_to_fill_controller.cc
index 5e6d4a9..361dae9d 100644
--- a/chrome/browser/touch_to_fill/touch_to_fill_controller.cc
+++ b/chrome/browser/touch_to_fill/touch_to_fill_controller.cc
@@ -161,7 +161,12 @@
 }
 
 void TouchToFillController::OnCredManUiClosed(bool success) {
-  ActionCompleted();
+  if (!ttf_delegate_) {
+    return;
+  }
+  // Unretained is safe here because TouchToFillController owns the delegate.
+  ttf_delegate_->OnCredManDismissed(base::BindOnce(
+      &TouchToFillController::ActionCompleted, base::Unretained(this)));
 }
 
 void TouchToFillController::OnDismiss() {
diff --git a/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.cc b/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.cc
index 22453fc..48a8e9df 100644
--- a/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.cc
+++ b/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.cc
@@ -205,6 +205,15 @@
   std::move(action_complete).Run();
 }
 
+void TouchToFillControllerAutofillDelegate::OnCredManDismissed(
+    base::OnceClosure action_completed) {
+  if (!filler_) {
+    return;
+  }
+  filler_->Dismiss(ToShowVirtualKeyboard(false));
+  std::move(action_completed).Run();
+}
+
 const GURL& TouchToFillControllerAutofillDelegate::GetFrameUrl() {
   CHECK(filler_);
   return filler_->GetFrameUrl();
diff --git a/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.h b/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.h
index b014692..573df1a 100644
--- a/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.h
+++ b/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.h
@@ -113,6 +113,7 @@
                                  base::OnceClosure action_completed) override;
   void OnHybridSignInSelected(base::OnceClosure action_completed) override;
   void OnDismiss(base::OnceClosure action_completed) override;
+  void OnCredManDismissed(base::OnceClosure action_completed) override;
   const GURL& GetFrameUrl() override;
   bool ShouldTriggerSubmission() override;
   bool ShouldShowHybridOption() override;
diff --git a/chrome/browser/touch_to_fill/touch_to_fill_controller_delegate.h b/chrome/browser/touch_to_fill/touch_to_fill_controller_delegate.h
index 575b0bb..db255ee 100644
--- a/chrome/browser/touch_to_fill/touch_to_fill_controller_delegate.h
+++ b/chrome/browser/touch_to_fill/touch_to_fill_controller_delegate.h
@@ -53,6 +53,10 @@
   // invoked repeatedly.
   virtual void OnDismiss(base::OnceClosure action_completed) = 0;
 
+  // Informs the controller that the user has dismissed the Android Credential
+  // Manager UI.
+  virtual void OnCredManDismissed(base::OnceClosure action_completed) = 0;
+
   // Gets the last committed URL for the frame that triggered this sheet to be
   // created.
   virtual const GURL& GetFrameUrl() = 0;
diff --git a/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.cc b/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.cc
index b6016bf..3e29ab5 100644
--- a/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.cc
+++ b/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.h"
 
+#include <algorithm>
 #include <vector>
 
 #include "base/containers/span.h"
@@ -66,6 +67,11 @@
   std::move(action_complete).Run();
 }
 
+void TouchToFillControllerWebAuthnDelegate::OnCredManDismissed(
+    base::OnceClosure action_completed) {
+  std::move(action_completed).Run();
+}
+
 const GURL& TouchToFillControllerWebAuthnDelegate::GetFrameUrl() {
   return request_delegate_->web_contents()->GetLastCommittedURL();
 }
diff --git a/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.h b/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.h
index 974fa17..387598344 100644
--- a/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.h
+++ b/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.h
@@ -50,6 +50,7 @@
                                  base::OnceClosure action_completed) override;
   void OnHybridSignInSelected(base::OnceClosure action_completed) override;
   void OnDismiss(base::OnceClosure action_completed) override;
+  void OnCredManDismissed(base::OnceClosure action_completed) override;
   const GURL& GetFrameUrl() override;
   bool ShouldTriggerSubmission() override;
   bool ShouldShowHybridOption() override;
diff --git a/chrome/browser/ui/android/fast_checkout/ui_view_android_utils.cc b/chrome/browser/ui/android/fast_checkout/ui_view_android_utils.cc
index a715b4f..e4abc8fe 100644
--- a/chrome/browser/ui/android/fast_checkout/ui_view_android_utils.cc
+++ b/chrome/browser/ui/android/fast_checkout/ui_view_android_utils.cc
@@ -48,7 +48,7 @@
   const autofill::AutofillCountry country(country_code, locale);
   return Java_FastCheckoutAutofillProfile_Constructor(
       env, ConvertUTF8ToJavaString(env, profile.guid()),
-      profile.record_type() == autofill::AutofillProfile::LOCAL_PROFILE,
+      /*isLocal=*/true,
       ConvertUTF16ToJavaString(
           env, profile.GetInfo(autofill::NAME_HONORIFIC_PREFIX, locale)),
       ConvertUTF16ToJavaString(env,
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
index 786ad33..14dbbde7 100644
--- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
+++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -77,6 +77,7 @@
 #include "chrome/browser/ui/views/select_file_dialog_extension_factory.h"
 #include "chrome/browser/ui/views/tabs/tab_scrubber_chromeos.h"
 #include "chromeos/ash/components/dbus/dbus_thread_manager.h"
+#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
 #include "chromeos/ash/components/heatmap/heatmap_palm_detector.h"
 #include "chromeos/ash/components/network/network_connect.h"
 #include "chromeos/ash/components/network/portal_detector/network_portal_detector.h"
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index e1a31e5..9b63245 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -399,8 +399,8 @@
   mf_controller->UpdateSourceAvailability(FillingSource::AUTOFILL,
                                           /*has_suggestions=*/false);
   mf_controller->Hide();
-#endif
 
+#endif
   if (suggestion.popup_item_id == PopupItemId::kVirtualCreditCardEntry) {
     std::string event_name =
         suggestion.feature_for_iph ==
@@ -428,7 +428,9 @@
   }
 
   delegate_->DidAcceptSuggestion(
-      suggestion, AutofillPopupDelegate::SuggestionPosition{.row = index},
+      suggestion,
+      AutofillPopupDelegate::SuggestionPosition{
+          .row = index, .sub_popup_level = GetPopupLevel()},
       trigger_source_);
 #if BUILDFLAG(IS_ANDROID)
   if ((suggestion.popup_item_id == PopupItemId::kPasswordEntry ||
@@ -692,6 +694,10 @@
   return view_ ? view_->CreateSubPopupView(controller) : nullptr;
 }
 
+int AutofillPopupControllerImpl::GetPopupLevel() const {
+  return !IsRootPopup() ? parent_controller_->get()->GetPopupLevel() + 1 : 0;
+}
+
 void AutofillPopupControllerImpl::FireControlsChangedEvent(bool is_show) {
   if (!accessibility_state_utils::IsScreenReaderEnabled())
     return;
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
index a01c2cc..aea3331 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
@@ -56,6 +56,11 @@
   // `nullptr` is returned in these cases.
   virtual base::WeakPtr<AutofillPopupView> CreateSubPopupView(
       base::WeakPtr<AutofillPopupController> sub_controller) = 0;
+
+  // Returns the number of popups above this one. For example, if `this` is the
+  // second popup, `GetPopupLevel()` returns 1, if `this` is the root popup,
+  // it returns 0.
+  virtual int GetPopupLevel() const = 0;
 };
 
 // This class is a controller for an AutofillPopupView. It implements
@@ -220,6 +225,7 @@
   // ExpandablePopupParentControllerImpl:
   base::WeakPtr<AutofillPopupView> CreateSubPopupView(
       base::WeakPtr<AutofillPopupController> controller) override;
+  int GetPopupLevel() const override;
 
   // Returns `true` if this popup has no parent, and `false` for sub-popups.
   bool IsRootPopup() const;
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc
index 4bec33ba..c6064f3 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc
@@ -34,6 +34,7 @@
 #include "components/autofill/core/browser/autofill_manager.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/browser_autofill_manager_test_api.h"
+#include "components/autofill/core/browser/ui/autofill_popup_delegate.h"
 #include "components/autofill/core/browser/ui/popup_item_ids.h"
 #include "components/autofill/core/browser/ui/suggestion.h"
 #include "components/autofill/core/common/aliases.h"
@@ -82,12 +83,23 @@
 using ::testing::Eq;
 using ::testing::Field;
 using ::testing::Invoke;
+using ::testing::Matcher;
 using ::testing::Mock;
 using ::testing::NiceMock;
 using ::testing::Optional;
 using ::testing::Return;
 using ::testing::StrictMock;
 
+#if !BUILDFLAG(IS_ANDROID)
+Matcher<const AutofillPopupDelegate::SuggestionPosition&>
+EqualsSuggestionPosition(AutofillPopupDelegate::SuggestionPosition position) {
+  return AllOf(
+      Field(&AutofillPopupDelegate::SuggestionPosition::row, position.row),
+      Field(&AutofillPopupDelegate::SuggestionPosition::sub_popup_level,
+            position.sub_popup_level));
+}
+#endif
+
 class MockAutofillDriver : public ContentAutofillDriver {
  public:
   MockAutofillDriver(content::RenderFrameHost* rfh,
@@ -943,6 +955,26 @@
               DidPerformButtonActionForSuggestion);
   client().popup_controller(manager()).PerformButtonActionForSuggestion(0);
 }
+
+// The second popup is also the second "sub_popup_level". This test asserts that
+// the information regarding the popup level is passed on to the delegate.
+TEST_F(AutofillPopupControllerImplTest, PopupForwardsSuggestionPosition) {
+  base::WeakPtr<AutofillPopupController> sub_controller =
+      client().popup_controller(manager()).OpenSubPopup(
+          {0, 0, 10, 10}, {Suggestion(PopupItemId::kAddressEntry)},
+          AutoselectFirstSuggestion(false));
+  ASSERT_TRUE(sub_controller);
+  static_cast<AutofillPopupControllerImpl*>(sub_controller.get())
+      ->SetViewForTesting(client().sub_popup_view().GetWeakPtr());
+
+  EXPECT_CALL(
+      manager().external_delegate(),
+      DidAcceptSuggestion(
+          _, EqualsSuggestionPosition({.row = 0, .sub_popup_level = 1}), _));
+
+  task_environment()->FastForwardBy(base::Milliseconds(1000));
+  sub_controller->AcceptSuggestion(/*index=*/0, base::TimeTicks::Now());
+}
 #endif
 
 // Tests that the popup controller queries the view for its screen location.
diff --git a/chrome/browser/ui/passwords/bubble_controllers/common_saved_account_manager_bubble_controller.h b/chrome/browser/ui/passwords/bubble_controllers/common_saved_account_manager_bubble_controller.h
index 09b001e..823a09e8 100644
--- a/chrome/browser/ui/passwords/bubble_controllers/common_saved_account_manager_bubble_controller.h
+++ b/chrome/browser/ui/passwords/bubble_controllers/common_saved_account_manager_bubble_controller.h
@@ -8,8 +8,8 @@
 #include "base/memory/raw_ptr.h"
 #include "chrome/browser/ui/passwords/bubble_controllers/password_bubble_controller_base.h"
 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
-#include "components/password_manager/core/browser/interactions_stats.h"
 #include "components/password_manager/core/browser/password_feature_manager.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
 
 namespace ui {
 class ImageModel;
diff --git a/chrome/browser/ui/passwords/bubble_controllers/manage_passwords_bubble_controller.cc b/chrome/browser/ui/passwords/bubble_controllers/manage_passwords_bubble_controller.cc
index 27dd9b42..9a86484 100644
--- a/chrome/browser/ui/passwords/bubble_controllers/manage_passwords_bubble_controller.cc
+++ b/chrome/browser/ui/passwords/bubble_controllers/manage_passwords_bubble_controller.cc
@@ -19,7 +19,7 @@
 #include "components/favicon/core/favicon_util.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_form_metrics_recorder.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_sync_util.h"
 #include "components/signin/public/base/consent_level.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
diff --git a/chrome/browser/ui/passwords/bubble_controllers/save_update_bubble_controller.cc b/chrome/browser/ui/passwords/bubble_controllers/save_update_bubble_controller.cc
index 200f962d..f3e28d4 100644
--- a/chrome/browser/ui/passwords/bubble_controllers/save_update_bubble_controller.cc
+++ b/chrome/browser/ui/passwords/bubble_controllers/save_update_bubble_controller.cc
@@ -21,8 +21,8 @@
 #include "components/password_manager/core/browser/manage_passwords_referrer.h"
 #include "components/password_manager/core/browser/password_feature_manager.h"
 #include "components/password_manager/core/browser/password_form_metrics_recorder.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_store/smart_bubble_stats_store.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
 #include "components/password_manager/core/browser/password_sync_util.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ui/passwords/bubble_controllers/save_update_bubble_controller_unittest.cc b/chrome/browser/ui/passwords/bubble_controllers/save_update_bubble_controller_unittest.cc
index f7819886..eb051c7 100644
--- a/chrome/browser/ui/passwords/bubble_controllers/save_update_bubble_controller_unittest.cc
+++ b/chrome/browser/ui/passwords/bubble_controllers/save_update_bubble_controller_unittest.cc
@@ -22,13 +22,13 @@
 #include "chrome/browser/sync/sync_service_factory.h"
 #include "chrome/browser/ui/passwords/passwords_model_delegate_mock.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/password_manager/core/browser/interactions_stats.h"
 #include "components/password_manager/core/browser/mock_password_feature_manager.h"
 #include "components/password_manager/core/browser/mock_password_store_interface.h"
 #include "components/password_manager/core/browser/mock_smart_bubble_stats_store.h"
 #include "components/password_manager/core/browser/password_form_metrics_recorder.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
 #include "components/password_manager/core/common/credential_manager_types.h"
 #include "components/password_manager/core/common/password_manager_ui.h"
 #include "components/sync/test/test_sync_service.h"
diff --git a/chrome/browser/ui/passwords/manage_passwords_state.h b/chrome/browser/ui/passwords/manage_passwords_state.h
index 486fa38..848aaf3 100644
--- a/chrome/browser/ui/passwords/manage_passwords_state.h
+++ b/chrome/browser/ui/passwords/manage_passwords_state.h
@@ -11,7 +11,7 @@
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 #include "components/password_manager/core/common/credential_manager_types.h"
 #include "components/password_manager/core/common/password_manager_ui.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
index f0e93656..501f554 100644
--- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -49,7 +49,6 @@
 #include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
 #include "components/password_manager/core/browser/features/password_features.h"
 #include "components/password_manager/core/browser/form_saver_impl.h"
-#include "components/password_manager/core/browser/interactions_stats.h"
 #include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
 #include "components/password_manager/core/browser/move_password_to_account_store_helper.h"
 #include "components/password_manager/core/browser/password_bubble_experiment.h"
@@ -57,6 +56,7 @@
 #include "components/password_manager/core/browser/password_manager_constants.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
 #include "components/password_manager/core/browser/ui/password_check_referrer.h"
 #include "components/password_manager/core/common/credential_manager_types.h"
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.h b/chrome/browser/ui/passwords/manage_passwords_ui_controller.h
index c0285550..397c710 100644
--- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.h
+++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.h
@@ -16,7 +16,7 @@
 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
 #include "chrome/common/buildflags.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/ui/post_save_compromised_helper.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/web_contents_observer.h"
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
index d43c42a..873da61f 100644
--- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
@@ -29,7 +29,6 @@
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/device_reauth/device_authenticator.h"
 #include "components/password_manager/core/browser/features/password_features.h"
-#include "components/password_manager/core/browser/interactions_stats.h"
 #include "components/password_manager/core/browser/mock_password_form_manager_for_ui.h"
 #include "components/password_manager/core/browser/mock_password_store_interface.h"
 #include "components/password_manager/core/browser/password_bubble_experiment.h"
@@ -37,6 +36,7 @@
 #include "components/password_manager/core/browser/password_form_metrics_recorder.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
diff --git a/chrome/browser/ui/passwords/well_known_change_password_navigation_throttle.cc b/chrome/browser/ui/passwords/well_known_change_password_navigation_throttle.cc
index c9dcd8927..cd4d9fb6 100644
--- a/chrome/browser/ui/passwords/well_known_change_password_navigation_throttle.cc
+++ b/chrome/browser/ui/passwords/well_known_change_password_navigation_throttle.cc
@@ -11,9 +11,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/common/webui_url_constants.h"
-#include "components/password_manager/content/browser/password_change_success_tracker_factory.h"
 #include "components/password_manager/core/browser/affiliation/affiliation_service.h"
-#include "components/password_manager/core/browser/password_change_success_tracker.h"
 #include "components/password_manager/core/browser/well_known_change_password/well_known_change_password_state.h"
 #include "components/password_manager/core/browser/well_known_change_password/well_known_change_password_util.h"
 #include "content/public/browser/browser_context.h"
@@ -36,7 +34,6 @@
 using content::NavigationThrottle;
 using content::WebContents;
 using password_manager::IsWellKnownChangePasswordUrl;
-using password_manager::PasswordChangeSuccessTracker;
 using password_manager::WellKnownChangePasswordResult;
 using password_manager::WellKnownChangePasswordState;
 
@@ -176,35 +173,19 @@
     bool is_supported) {
   GURL redirect_url = affiliation_service_->GetChangePasswordURL(request_url_);
 
-  // Extend the information of precisely what kind of flow the manual
-  // password change flow is.
-  raw_ptr<PasswordChangeSuccessTracker> password_change_success_tracker =
-      password_manager::PasswordChangeSuccessTrackerFactory::
-          GetForBrowserContext(
-              navigation_handle()->GetWebContents()->GetBrowserContext());
-
   // If affiliation service returns .well-known/change-password as change
   // password url - show it even if Chrome doesn't detect it as supported.
   if (is_supported || redirect_url == request_url_) {
     RecordMetric(WellKnownChangePasswordResult::kUsedWellKnownChangePassword);
-    password_change_success_tracker->OnChangePasswordFlowModified(
-        request_url_,
-        PasswordChangeSuccessTracker::StartEvent::kManualWellKnownUrlFlow);
     Resume();
     return;
   }
 
   if (redirect_url.is_valid()) {
     RecordMetric(WellKnownChangePasswordResult::kFallbackToOverrideUrl);
-    password_change_success_tracker->OnChangePasswordFlowModified(
-        request_url_,
-        PasswordChangeSuccessTracker::StartEvent::kManualChangePasswordUrlFlow);
     Redirect(redirect_url);
   } else {
     RecordMetric(WellKnownChangePasswordResult::kFallbackToOriginUrl);
-    password_change_success_tracker->OnChangePasswordFlowModified(
-        request_url_,
-        PasswordChangeSuccessTracker::StartEvent::kManualHomepageFlow);
     Redirect(request_url_.DeprecatedGetOriginAsURL());
   }
   CancelDeferredNavigation(NavigationThrottle::CANCEL);
diff --git a/chrome/browser/ui/passwords/well_known_change_password_navigation_throttle_browsertest.cc b/chrome/browser/ui/passwords/well_known_change_password_navigation_throttle_browsertest.cc
index 7fb363b..108b62bb 100644
--- a/chrome/browser/ui/passwords/well_known_change_password_navigation_throttle_browsertest.cc
+++ b/chrome/browser/ui/passwords/well_known_change_password_navigation_throttle_browsertest.cc
@@ -22,13 +22,10 @@
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/common/url_constants.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/password_manager/content/browser/password_change_success_tracker_factory.h"
 #include "components/password_manager/core/browser/affiliation/affiliation_api.pb.h"
 #include "components/password_manager/core/browser/affiliation/affiliation_service_impl.h"
 #include "components/password_manager/core/browser/affiliation/hash_affiliation_fetcher.h"
 #include "components/password_manager/core/browser/affiliation/mock_affiliation_service.h"
-#include "components/password_manager/core/browser/mock_password_change_success_tracker.h"
-#include "components/password_manager/core/browser/password_change_success_tracker.h"
 #include "components/password_manager/core/browser/well_known_change_password/well_known_change_password_util.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/sync/test/test_sync_service.h"
@@ -69,9 +66,6 @@
 using password_manager::kWellKnownChangePasswordPath;
 using password_manager::kWellKnownNotExistingResourcePath;
 using password_manager::MockAffiliationService;
-using password_manager::MockPasswordChangeSuccessTracker;
-using password_manager::PasswordChangeSuccessTracker;
-using password_manager::PasswordChangeSuccessTrackerFactory;
 using password_manager::WellKnownChangePasswordResult;
 using testing::_;
 using testing::Return;
@@ -127,14 +121,6 @@
                                 -> std::unique_ptr<KeyedService> {
           return std::make_unique<testing::NiceMock<MockAffiliationService>>();
         }));
-
-    PasswordChangeSuccessTrackerFactory::GetInstance()->SetTestingFactoryAndUse(
-        Profile::FromBrowserContext(context),
-        base::BindRepeating(
-            [](content::BrowserContext*) -> std::unique_ptr<KeyedService> {
-              return std::make_unique<
-                  testing::NiceMock<MockPasswordChangeSuccessTracker>>();
-            }));
   }
 
   void SetUpOnMainThread() override {
@@ -191,11 +177,6 @@
 
   ui::PageTransition page_transition() const { return std::get<0>(GetParam()); }
 
-  MockPasswordChangeSuccessTracker* password_change_success_tracker() {
-    return static_cast<MockPasswordChangeSuccessTracker*>(
-        PasswordChangeSuccessTrackerFactory::GetInstance()
-            ->GetForBrowserContext(browser()->profile()));
-  }
   MockAffiliationService* url_service() {
     return static_cast<MockAffiliationService*>(
         AffiliationServiceFactory::GetInstance()->GetForProfile(
@@ -254,18 +235,6 @@
   path_response_map_[kWellKnownNotExistingResourcePath] = {
       net::HTTP_NOT_FOUND, {}, response_delays().not_exist_delay};
 
-  if (page_transition() & ui::PAGE_TRANSITION_FROM_API) {
-    EXPECT_CALL(
-        *password_change_success_tracker(),
-        OnChangePasswordFlowModified(
-            test_server_->GetURL(kWellKnownChangePasswordPath),
-            PasswordChangeSuccessTracker::StartEvent::kManualWellKnownUrlFlow));
-  } else {
-    EXPECT_CALL(*password_change_success_tracker(),
-                OnChangePasswordFlowModified(_, _))
-        .Times(0);
-  }
-
   TestNavigationThrottleForLocalhost(
       /*expected_path=*/kWellKnownChangePasswordPath);
   if (page_transition() & ui::PAGE_TRANSITION_FROM_API) {
@@ -286,18 +255,6 @@
       net::HTTP_NOT_FOUND, {}, response_delays().not_exist_delay};
   path_response_map_["/change-password"] = {net::HTTP_OK, {}, 0};
 
-  if (page_transition() & ui::PAGE_TRANSITION_FROM_API) {
-    EXPECT_CALL(
-        *password_change_success_tracker(),
-        OnChangePasswordFlowModified(
-            test_server_->GetURL(kWellKnownChangePasswordPath),
-            PasswordChangeSuccessTracker::StartEvent::kManualWellKnownUrlFlow));
-  } else {
-    EXPECT_CALL(*password_change_success_tracker(),
-                OnChangePasswordFlowModified(_, _))
-        .Times(0);
-  }
-
   TestNavigationThrottleForLocalhost(/*expected_path=*/"/change-password");
   if (page_transition() & ui::PAGE_TRANSITION_FROM_API) {
     ExpectUmaAndUkmMetric(
@@ -323,12 +280,6 @@
   GURL navigate_url = test_server_->GetURL(kWellKnownChangePasswordPath);
   GURL expected_url = test_server_->GetURL("/change-password");
 
-  EXPECT_CALL(
-      *password_change_success_tracker(),
-      OnChangePasswordFlowModified(
-          navigate_url,
-          PasswordChangeSuccessTracker::StartEvent::kManualWellKnownUrlFlow));
-
   TestNavigationThrottle(
       navigate_url, expected_url,
       url::Origin::Create(GURL("chrome://settings/passwords/check")));
@@ -353,12 +304,6 @@
   GURL navigate_url = test_server_->GetURL(kWellKnownChangePasswordPath);
   GURL expected_url = test_server_->GetURL("/change-password");
 
-  EXPECT_CALL(
-      *password_change_success_tracker(),
-      OnChangePasswordFlowModified(
-          navigate_url,
-          PasswordChangeSuccessTracker::StartEvent::kManualWellKnownUrlFlow));
-
   TestNavigationThrottle(
       navigate_url, expected_url,
       url::Origin::Create(GURL("https://passwords.google.com/checkup")));
@@ -374,18 +319,6 @@
   path_response_map_[kWellKnownNotExistingResourcePath] = {
       net::HTTP_NOT_FOUND, {}, response_delays().not_exist_delay};
 
-  if (page_transition() & ui::PAGE_TRANSITION_FROM_API) {
-    EXPECT_CALL(
-        *password_change_success_tracker(),
-        OnChangePasswordFlowModified(
-            test_server_->GetURL(kWellKnownChangePasswordPath),
-            PasswordChangeSuccessTracker::StartEvent::kManualWellKnownUrlFlow));
-  } else {
-    EXPECT_CALL(*password_change_success_tracker(),
-                OnChangePasswordFlowModified(_, _))
-        .Times(0);
-  }
-
   TestNavigationThrottleForLocalhost(
       /*expected_path=*/kWellKnownChangePasswordPath);
   if (page_transition() & ui::PAGE_TRANSITION_FROM_API) {
@@ -412,18 +345,6 @@
   path_response_map_["/change-password"] = {net::HTTP_OK, {}, 0};
   path_response_map_["/not-found"] = {net::HTTP_NOT_FOUND, {}, 0};
 
-  if (page_transition() & ui::PAGE_TRANSITION_FROM_API) {
-    EXPECT_CALL(
-        *password_change_success_tracker(),
-        OnChangePasswordFlowModified(
-            test_server_->GetURL(kWellKnownChangePasswordPath),
-            PasswordChangeSuccessTracker::StartEvent::kManualWellKnownUrlFlow));
-  } else {
-    EXPECT_CALL(*password_change_success_tracker(),
-                OnChangePasswordFlowModified(_, _))
-        .Times(0);
-  }
-
   TestNavigationThrottle(test_server_->GetURL(kWellKnownChangePasswordPath),
                          change_password_url);
   if (page_transition() & ui::PAGE_TRANSITION_FROM_API) {
@@ -445,17 +366,9 @@
     EXPECT_CALL(*url_service(), GetChangePasswordURL(test_server_->GetURL(
                                     kWellKnownChangePasswordPath)))
         .WillRepeatedly(Return(GURL()));
-    EXPECT_CALL(
-        *password_change_success_tracker(),
-        OnChangePasswordFlowModified(
-            test_server_->GetURL(kWellKnownChangePasswordPath),
-            PasswordChangeSuccessTracker::StartEvent::kManualHomepageFlow));
     TestNavigationThrottleForLocalhost(/*expected_path=*/"/");
     ExpectUmaAndUkmMetric(WellKnownChangePasswordResult::kFallbackToOriginUrl);
   } else {
-    EXPECT_CALL(*password_change_success_tracker(),
-                OnChangePasswordFlowModified(_, _))
-        .Times(0);
     TestNavigationThrottleForLocalhost(
         /*expected_path=*/kWellKnownChangePasswordPath);
     ExpectNeitherUmaNorUkmMetric();
@@ -473,19 +386,11 @@
     EXPECT_CALL(*url_service(), GetChangePasswordURL(test_server_->GetURL(
                                     kWellKnownChangePasswordPath)))
         .WillRepeatedly(Return(test_server_->GetURL(kMockChangePasswordPath)));
-    EXPECT_CALL(*password_change_success_tracker(),
-                OnChangePasswordFlowModified(
-                    test_server_->GetURL(kWellKnownChangePasswordPath),
-                    PasswordChangeSuccessTracker::StartEvent::
-                        kManualChangePasswordUrlFlow));
     TestNavigationThrottleForLocalhost(
         /*expected_path=*/kMockChangePasswordPath);
     ExpectUmaAndUkmMetric(
         WellKnownChangePasswordResult::kFallbackToOverrideUrl);
   } else {
-    EXPECT_CALL(*password_change_success_tracker(),
-                OnChangePasswordFlowModified(_, _))
-        .Times(0);
     TestNavigationThrottleForLocalhost(
         /*expected_path=*/kWellKnownChangePasswordPath);
     ExpectNeitherUmaNorUkmMetric();
@@ -504,17 +409,9 @@
     EXPECT_CALL(*url_service(), GetChangePasswordURL(test_server_->GetURL(
                                     kWellKnownChangePasswordPath)))
         .WillRepeatedly(Return(GURL()));
-    EXPECT_CALL(
-        *password_change_success_tracker(),
-        OnChangePasswordFlowModified(
-            test_server_->GetURL(kWellKnownChangePasswordPath),
-            PasswordChangeSuccessTracker::StartEvent::kManualHomepageFlow));
     TestNavigationThrottleForLocalhost(/*expected_path=*/"/");
     ExpectUmaAndUkmMetric(WellKnownChangePasswordResult::kFallbackToOriginUrl);
   } else {
-    EXPECT_CALL(*password_change_success_tracker(),
-                OnChangePasswordFlowModified(_, _))
-        .Times(0);
     TestNavigationThrottleForLocalhost(
         /*expected_path=*/kWellKnownChangePasswordPath);
     ExpectNeitherUmaNorUkmMetric();
@@ -541,17 +438,9 @@
     EXPECT_CALL(*url_service(), GetChangePasswordURL(test_server_->GetURL(
                                     kWellKnownChangePasswordPath)))
         .WillRepeatedly(Return(GURL()));
-    EXPECT_CALL(
-        *password_change_success_tracker(),
-        OnChangePasswordFlowModified(
-            test_server_->GetURL(kWellKnownChangePasswordPath),
-            PasswordChangeSuccessTracker::StartEvent::kManualHomepageFlow));
     TestNavigationThrottleForLocalhost(/*expected_path=*/"/");
     ExpectUmaAndUkmMetric(WellKnownChangePasswordResult::kFallbackToOriginUrl);
   } else {
-    EXPECT_CALL(*password_change_success_tracker(),
-                OnChangePasswordFlowModified(_, _))
-        .Times(0);
     TestNavigationThrottle(test_server_->GetURL(kWellKnownChangePasswordPath),
                            not_found_url);
     ExpectNeitherUmaNorUkmMetric();
@@ -604,11 +493,6 @@
 
   GURL navigate_url = test_server_->GetURL(kWellKnownChangePasswordPath);
   GURL expected_url = test_server_->GetURL("/change-password");
-  EXPECT_CALL(
-      *password_change_success_tracker(),
-      OnChangePasswordFlowModified(
-          navigate_url,
-          PasswordChangeSuccessTracker::StartEvent::kManualWellKnownUrlFlow));
   TestNavigationThrottle(
       navigate_url, expected_url,
       url::Origin::Create(GURL("https://passwords.google.com/checkup")));
diff --git a/chrome/browser/ui/safety_hub/password_status_check_service.cc b/chrome/browser/ui/safety_hub/password_status_check_service.cc
index 98b4af3b..5358e53a2 100644
--- a/chrome/browser/ui/safety_hub/password_status_check_service.cc
+++ b/chrome/browser/ui/safety_hub/password_status_check_service.cc
@@ -182,6 +182,16 @@
       AccountPasswordStoreFactory::GetForProfile(
           profile_, ServiceAccessType::IMPLICIT_ACCESS);
 
+  // ProfilePasswordStore may not exist for some cases like non-user profiles on
+  // Ash. If ProfilePasswordStore does not exist, then no other password
+  // operations can be done. Hence, here is an early return to prevent
+  // initializing checks.
+  // TODO(crbug.com/1443466): Add CHECK for profile_store after making this
+  // service null if the store does not exist.
+  if (!profile_store) {
+    return;
+  }
+
   profile_password_store_observation_.Observe(profile_store.get());
   if (account_store) {
     account_password_store_observation_.Observe(account_store.get());
@@ -231,51 +241,79 @@
 
 void PasswordStatusCheckService::UpdateInsecureCredentialCountAsync() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  if (is_update_credential_count_pending_) {
+  // In case there is a running check, do not start checks again.
+  if (running_update_credential_count_ > 0) {
     return;
   }
 
-  is_update_credential_count_pending_ = true;
-
-  InitializePasswordCheckInfrastructure();
-
-  CHECK(saved_passwords_presenter_);
-  if (!saved_passwords_presenter_observation_.IsObserving()) {
-    saved_passwords_presenter_observation_.Observe(
-        saved_passwords_presenter_.get());
-  }
+  // Initializing the infra will cause the presenter to check for all saved
+  // passwords. running_update_credential_count_ will be increased in
+  // OnSavedPasswordsChanged where the weak and reused checks will be
+  // initialized.
+  MaybeInitializePasswordCheckInfrastructure();
 }
 
 void PasswordStatusCheckService::RunPasswordCheckAsync() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  if (is_password_check_running_) {
+  // In case there is a running check, do not start checks again.
+  if (password_check_state_ != PasswordCheckState::kStopped) {
     return;
   }
 
-  is_password_check_running_ = true;
+  // Initializing the infra will cause the presenter to check for all saved
+  // passwords.
+  MaybeInitializePasswordCheckInfrastructure();
 
-  InitializePasswordCheckInfrastructure();
-
-  CHECK(password_check_delegate_);
-  if (!bulk_leak_check_observation_.IsObserving()) {
-    bulk_leak_check_observation_.Observe(
-        BulkLeakCheckServiceFactory::GetForProfile(profile_));
-  }
-
-  password_check_delegate_->StartPasswordCheck();
+  // InitializePasswordCheckInfrastructure may return before the infra is ready.
+  // This is unexpected to happen just before the password check starts.
+  CHECK(IsInfrastructureReady());
+  password_check_state_ = PasswordCheckState::kStarting;
+  password_check_delegate_->StartPasswordCheck(
+      base::BindOnce(&PasswordStatusCheckService::OnStartedPasswordCheck,
+                     weak_ptr_factory_.GetWeakPtr()));
   base::RecordAction(base::UserMetricsAction("SafetyHub_PasswordCheckRun"));
 }
 
+void PasswordStatusCheckService::OnStartedPasswordCheck(
+    password_manager::BulkLeakCheckService::State state) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  switch (password_check_state_) {
+    case kStarting:
+      password_check_state_ = PasswordCheckState::kOnStartCallbackCompleted;
+      return;
+    case kOnStateChangedCalled:
+      password_check_state_ = PasswordCheckState::kStopped;
+      // If OnStateChanged and OnStartedPasswordCheck are already called, then
+      // it is safe to kill the infra asynchronously.
+      base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+          FROM_HERE,
+          base::BindOnce(&PasswordStatusCheckService::MaybeResetInfrastructure,
+                         weak_ptr_factory_.GetWeakPtr()));
+      return;
+    case kOnStartCallbackCompleted:
+      NOTREACHED() << "PasswordCheckState::kOnStartCallbackCompleted";
+      return;
+    case kStopped:
+      NOTREACHED() << "PasswordCheckState::kStopped";
+      return;
+  }
+}
+
 void PasswordStatusCheckService::OnSavedPasswordsChanged(
     const password_manager::PasswordStoreChangeList& changes) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   CHECK(IsInfrastructureReady());
 
-  no_passwords_saved_ =
-      saved_passwords_presenter_->GetSavedCredentials().size() == 0;
+  // Increase the counter for update credential count calls.
+  running_update_credential_count_++;
 
+  no_passwords_saved_ =
+      saved_passwords_presenter_->GetSavedCredentials().empty();
+
+  // TODO(crbug.com/1443466): Investigate if weak and reuse checks in
+  // InsecureCredentialsManager::OnSavedPasswordsChanged is enough to fetch
+  // insecure credential count instead of running checks here.
   base::RepeatingClosure on_done = base::BarrierClosure(
       /*num_closures=*/2,
       base::BindOnce(&PasswordStatusCheckService::OnWeakAndReuseChecksDone,
@@ -291,9 +329,12 @@
 }
 
 void PasswordStatusCheckService::OnWeakAndReuseChecksDone() {
-  is_update_credential_count_pending_ = false;
+  // Decrease the counter as one check is completed.
+  CHECK_GT(running_update_credential_count_, 0);
+  running_update_credential_count_--;
+
   UpdateInsecureCredentialCount();
-  MaybeResetInfrastructureAsync();
+  MaybeResetInfrastructure();
 }
 
 void PasswordStatusCheckService::OnStateChanged(
@@ -314,24 +355,35 @@
         kHashingFailure:
     case password_manager::BulkLeakCheckServiceInterface::State::kNetworkError:
     case password_manager::BulkLeakCheckServiceInterface::State::kQuotaLimit:
-      is_password_check_running_ = false;
 
-      // Set time for next password check and schedule the next run.
-      base::Time scheduled_check_time = GetScheduledPasswordCheckTime();
-      // If current check was scheduled to run a long time ago (larger than the
-      // interval) we make sure the next run is in the future with a minimum
-      // distance between subsequent checks.
-      while (scheduled_check_time <
-             base::Time::Now() + safety_hub::kMinTimeBetweenPasswordChecks) {
-        scheduled_check_time +=
-            features::kBackgroundPasswordCheckInterval.Get();
+      switch (password_check_state_) {
+        case kStarting:
+          // If password_check_delegate_->StartPasswordCheck is just called, the
+          // state should go to kOnStateChangedCalled.
+          password_check_state_ = PasswordCheckState::kOnStateChangedCalled;
+          ScheduleCheckAndStartRepeatedUpdates();
+          return;
+        case kOnStateChangedCalled:
+          // No-op, since if the state is already kOnStateChangedCalled, then
+          // ScheduleCheckAndStartRepeatedUpdates is called before. No need to
+          // call it again.
+          return;
+        case kOnStartCallbackCompleted:
+          ScheduleCheckAndStartRepeatedUpdates();
+          // If OnStateChanged and OnStartedPasswordCheck are already called,
+          // then
+          // it is safe to kill the infra asynchronously.
+          password_check_state_ = PasswordCheckState::kStopped;
+          base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+              FROM_HERE,
+              base::BindOnce(
+                  &PasswordStatusCheckService::MaybeResetInfrastructure,
+                  weak_ptr_factory_.GetWeakPtr()));
+          return;
+        case kStopped:
+          ScheduleCheckAndStartRepeatedUpdates();
+          return;
       }
-
-      SetPasswordCheckSchedulePrefsWithInterval(scheduled_check_time);
-
-      StartRepeatedUpdates();
-
-      MaybeResetInfrastructureAsync();
   }
 }
 
@@ -356,24 +408,40 @@
     password_manager::PasswordStoreInterface* store,
     const std::vector<password_manager::PasswordForm>& retained_passwords) {}
 
-void PasswordStatusCheckService::InitializePasswordCheckInfrastructure() {
+void PasswordStatusCheckService::MaybeInitializePasswordCheckInfrastructure() {
   if (IsInfrastructureReady()) {
     return;
   }
 
+  // ProfilePasswordStore must exist, otherwise the infrastructure couldn't have
+  // been initialized and this method could never have been called.
+  scoped_refptr<password_manager::PasswordStoreInterface> profile_store =
+      ProfilePasswordStoreFactory::GetForProfile(
+          profile_, ServiceAccessType::IMPLICIT_ACCESS);
+  CHECK(profile_store);
+
   credential_id_generator_ = std::make_unique<extensions::IdGenerator>();
   saved_passwords_presenter_ =
       std::make_unique<password_manager::SavedPasswordsPresenter>(
-          AffiliationServiceFactory::GetForProfile(profile_),
-          ProfilePasswordStoreFactory::GetForProfile(
-              profile_, ServiceAccessType::IMPLICIT_ACCESS),
+          AffiliationServiceFactory::GetForProfile(profile_), profile_store,
           AccountPasswordStoreFactory::GetForProfile(
               profile_, ServiceAccessType::IMPLICIT_ACCESS));
   saved_passwords_presenter_->Init();
+
   password_check_delegate_ =
       std::make_unique<extensions::PasswordCheckDelegate>(
           profile_, saved_passwords_presenter_.get(),
           credential_id_generator_.get());
+
+  // Observe new saved_passwords_presenter_.
+  saved_passwords_presenter_observation_.Reset();
+  saved_passwords_presenter_observation_.Observe(
+      saved_passwords_presenter_.get());
+
+  // Observe new BulkLeakCheckService.
+  bulk_leak_check_observation_.Reset();
+  bulk_leak_check_observation_.Observe(
+      BulkLeakCheckServiceFactory::GetForProfile(profile_));
 }
 
 void PasswordStatusCheckService::UpdateInsecureCredentialCount() {
@@ -404,24 +472,18 @@
   }
 }
 
-void PasswordStatusCheckService::MaybeResetInfrastructureAsync() {
+void PasswordStatusCheckService::MaybeResetInfrastructure() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  if (!is_update_credential_count_pending_ && !is_password_check_running_) {
-    saved_passwords_presenter_observation_.Reset();
-    bulk_leak_check_observation_.Reset();
-
-    // The reset is done as a task rather than directly because when observers
-    // are notified that e.g. the password check is done, it may be too early to
-    // reset the infrastructure immediately. Synchronous operations may still be
-    // ongoing in `SavedPasswordsPresenter`.
-    base::SingleThreadTaskRunner::GetCurrentDefault()->DeleteSoon(
-        FROM_HERE, std::move(password_check_delegate_));
-    base::SingleThreadTaskRunner::GetCurrentDefault()->DeleteSoon(
-        FROM_HERE, std::move(saved_passwords_presenter_));
-    base::SingleThreadTaskRunner::GetCurrentDefault()->DeleteSoon(
-        FROM_HERE, std::move(credential_id_generator_));
+  if (IsUpdateRunning()) {
+    return;
   }
+
+  saved_passwords_presenter_observation_.Reset();
+  bulk_leak_check_observation_.Reset();
+
+  password_check_delegate_.reset();
+  saved_passwords_presenter_.reset();
+  credential_id_generator_.reset();
 }
 
 bool PasswordStatusCheckService::IsInfrastructureReady() const {
@@ -507,6 +569,48 @@
   return GetNoWeakOrReusedPasswordCardData(signed_in);
 }
 
+void PasswordStatusCheckService::ScheduleCheckAndStartRepeatedUpdates() {
+  // Set time for next password check and schedule the next run.
+  base::Time scheduled_check_time = GetScheduledPasswordCheckTime();
+  // If current check was scheduled to run a long time ago (larger than the
+  // interval) we make sure the next run is in the future with a minimum
+  // distance between subsequent checks.
+  while (scheduled_check_time <
+         base::Time::Now() + safety_hub::kMinTimeBetweenPasswordChecks) {
+    scheduled_check_time += features::kBackgroundPasswordCheckInterval.Get();
+  }
+
+  SetPasswordCheckSchedulePrefsWithInterval(scheduled_check_time);
+
+  StartRepeatedUpdates();
+}
+
+void PasswordStatusCheckService::OnBulkCheckServiceShutDown() {
+  // Stop observing BulkLeakCheckService when the service shuts down.
+  CHECK(bulk_leak_check_observation_.IsObservingSource(
+      BulkLeakCheckServiceFactory::GetForProfile(profile_)));
+  bulk_leak_check_observation_.Reset();
+}
+
+bool PasswordStatusCheckService::IsUpdateRunning() const {
+  // CHECK to detect if the counters are decreased more than they are
+  // increased.
+  CHECK_GE(running_update_credential_count_, 0);
+  // If running_update_credential_count_ is larger than zero, then there are
+  // some ongoing insecure credential checks.
+  if (is_update_credential_count_pending()) {
+    return true;
+  }
+
+  // If password_check_state_ is not kStopped, then the password check is still
+  // ongoing.
+  if (is_password_check_running()) {
+    return true;
+  }
+
+  return false;
+}
+
 // TODO(crbug.com/1443466): Consider pass by value for GetCachedResult
 // functions.
 absl::optional<std::unique_ptr<SafetyHubService::Result>>
diff --git a/chrome/browser/ui/safety_hub/password_status_check_service.h b/chrome/browser/ui/safety_hub/password_status_check_service.h
index 562f593e..dd6eb20 100644
--- a/chrome/browser/ui/safety_hub/password_status_check_service.h
+++ b/chrome/browser/ui/safety_hub/password_status_check_service.h
@@ -11,7 +11,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/safety_hub/safety_hub_service.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
 
 class PasswordStatusCheckResult;
@@ -44,10 +44,12 @@
   size_t reused_credential_count() const { return reused_credential_count_; }
 
   bool is_update_credential_count_pending() const {
-    return is_update_credential_count_pending_;
+    return running_update_credential_count_ > 0;
   }
 
-  bool is_password_check_running() const { return is_password_check_running_; }
+  bool is_password_check_running() const {
+    return password_check_state_ != kStopped;
+  }
 
   bool no_passwords_saved() const { return no_passwords_saved_; }
 
@@ -71,6 +73,15 @@
   // TODO(crbug.com/1443466): This will be a SafetyHubService implementation.
   absl::optional<std::unique_ptr<SafetyHubService::Result>> GetCachedResult();
 
+  // Returns if there is any ongoing password check or insecure credential
+  // check. Returns true if is_update_credential_count_pending() or
+  // is_password_check_running().
+  bool IsUpdateRunning() const;
+
+  // Verifies that both `password_check_delegate_` and
+  // `saved_passwords_presenter_` are initialized.
+  bool IsInfrastructureReady() const;
+
   // Testing functions.
   bool IsObservingSavedPasswordsPresenterForTesting() const {
     return saved_passwords_presenter_observation_.IsObserving();
@@ -95,6 +106,23 @@
                            CheckTimeUpdatedAfterRunScheduledInThePast);
   FRIEND_TEST_ALL_PREFIXES(PasswordStatusCheckServiceBaseTest,
                            CheckTimeUpdatedAfterRunScheduledLongTimeInThePast);
+  // The enum to hold 4 password check states.
+  // As soon as the check is started, the state will be kStarting.
+  // When the state is kStarting:
+  // - if OnStateChanged is called, it will be kOnStateChangedCalled.
+  // - if OnStartedPasswordCheck is called, it will be
+  // kOnStartCallbackCompleted.
+  // When the state is kOnStateChangedCalled:
+  // - if OnStartedPasswordCheck is called, it will be kStopped.
+  // When the state is OnStartedPasswordCheck:
+  // - if OnStateChanged is called, it will be kStopped.
+  //  Whenever the state is kStopped, then the infra will be killed.
+  enum PasswordCheckState {
+    kStarting,
+    kOnStateChangedCalled,
+    kOnStartCallbackCompleted,
+    kStopped,
+  };
 
   // Triggers Password Manager's password check to discover new credential
   // issues.
@@ -111,6 +139,7 @@
       password_manager::BulkLeakCheckService::State state) override;
   void OnCredentialDone(const password_manager::LeakCheckCredential& credential,
                         password_manager::IsLeaked is_leaked) override;
+  void OnBulkCheckServiceShutDown() override;
 
   // PasswordStoreInterface::Observer implementation.
   // Used to trigger an update of the password issue counts when passwords
@@ -122,29 +151,34 @@
                         const std::vector<password_manager::PasswordForm>&
                             retained_passwords) override;
 
+  // Called whenever password_check_delegate_->StartPasswordCheck is completed.
+  // This is only used to prevent the infra being shutdown while there is an
+  // ongoing check in the delegate.
+  void OnStartedPasswordCheck(
+      password_manager::BulkLeakCheckService::State state);
+
   // This is called when weak and reuse checks are complete and
   // `InsecureCredentialsManager` is ready to be queried for credential issues.
   void OnWeakAndReuseChecksDone();
 
-  // Initializes |saved_passwords_presenter_| and |password_check_delegate_|.
-  void InitializePasswordCheckInfrastructure();
+  // Initializes `saved_passwords_presenter_` and `password_check_delegate_`. If
+  // there is no `password_store`, then the infra can not be initialized.
+  void MaybeInitializePasswordCheckInfrastructure();
 
   // Brings cached values for insecure credential counts up to date with
   // |saved_passwords_presenter_|.
   void UpdateInsecureCredentialCount();
 
-  // Posts a task to delete `password_check_delegate_` and
-  // `saved_passwords_presenter_` if async operations have concluded to keep
-  // memory footprint low.
-  void MaybeResetInfrastructureAsync();
-
-  // Verifies that both `password_check_delegate_` and
-  // `saved_passwords_presenter_` are initialized.
-  bool IsInfrastructureReady() const;
+  // Deletes `password_check_delegate_` and `saved_passwords_presenter_` if
+  // async operations have concluded to keep memory footprint low.
+  void MaybeResetInfrastructure();
 
   // Updates pref dict for scheduled password check.
   void SetPasswordCheckSchedulePrefsWithInterval(base::Time check_time);
 
+  // Schedules the next password check time and calls StartRepeatedUpdates.
+  void ScheduleCheckAndStartRepeatedUpdates();
+
   raw_ptr<Profile> profile_;
 
   // Required for `password_check_delegate_`. Because it is memory intensive,
@@ -194,10 +228,15 @@
   // True when password stores are empty and there are no saved passwords.
   bool no_passwords_saved_ = true;
 
-  // Flags to indicate which async operations are currently ongoing. Memory
-  // intensive objects will be reset after all have finished.
-  bool is_update_credential_count_pending_ = false;
-  bool is_password_check_running_ = false;
+  // Counter of running sync update credential count checks. Memory intensive
+  // objects will be reset after all have finished and password_check_state_ is
+  // kStopped.
+  int running_update_credential_count_ = 0;
+
+  // Enum to keep the state of password check. Memory intensive objects
+  // will be reset after the state is kStopped and
+  // running_update_credential_count_ is zero.
+  PasswordCheckState password_check_state_ = kStopped;
 
   // Timer to schedule the run of the password check after some time has passed.
   base::OneShotTimer password_check_timer_;
diff --git a/chrome/browser/ui/safety_hub/password_status_check_service_factory.cc b/chrome/browser/ui/safety_hub/password_status_check_service_factory.cc
index 31124e81..4522c9b 100644
--- a/chrome/browser/ui/safety_hub/password_status_check_service_factory.cc
+++ b/chrome/browser/ui/safety_hub/password_status_check_service_factory.cc
@@ -55,3 +55,8 @@
   return std::make_unique<PasswordStatusCheckService>(
       Profile::FromBrowserContext(context));
 }
+
+bool PasswordStatusCheckServiceFactory::ServiceIsCreatedWithBrowserContext()
+    const {
+  return base::FeatureList::IsEnabled(features::kSafetyHub);
+}
diff --git a/chrome/browser/ui/safety_hub/password_status_check_service_factory.h b/chrome/browser/ui/safety_hub/password_status_check_service_factory.h
index 082ba2d..491ffc1d 100644
--- a/chrome/browser/ui/safety_hub/password_status_check_service_factory.h
+++ b/chrome/browser/ui/safety_hub/password_status_check_service_factory.h
@@ -34,6 +34,8 @@
   ~PasswordStatusCheckServiceFactory() override;
 
   // BrowserContextKeyedServiceFactory:
+  bool ServiceIsCreatedWithBrowserContext() const override;
+
   std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext(
       content::BrowserContext* context) const override;
 };
diff --git a/chrome/browser/ui/safety_hub/password_status_check_service_unittest.cc b/chrome/browser/ui/safety_hub/password_status_check_service_unittest.cc
index acac6e4c..f9fb70cb 100644
--- a/chrome/browser/ui/safety_hub/password_status_check_service_unittest.cc
+++ b/chrome/browser/ui/safety_hub/password_status_check_service_unittest.cc
@@ -252,6 +252,25 @@
   }
 };
 
+class PasswordStatusCheckServiceWithoutPasswordStoreTest
+    : public testing::Test {
+ public:
+  PasswordStatusCheckService* service() { return service_.get(); }
+
+  content::BrowserTaskEnvironment* task_environment() { return &task_env_; }
+
+ private:
+  void SetUp() override {
+    service_ = std::make_unique<PasswordStatusCheckService>(&profile_);
+    task_env_.RunUntilIdle();
+  }
+
+  content::BrowserTaskEnvironment task_env_{
+      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+  TestingProfile profile_;
+  std::unique_ptr<PasswordStatusCheckService> service_;
+};
+
 TEST_F(PasswordStatusCheckServiceBaseTest, NoIssuesInitially) {
   UpdateInsecureCredentials();
   EXPECT_EQ(service()->weak_credential_count(), 0UL);
@@ -448,9 +467,7 @@
 
   bulk_leak_check_service()->set_state_and_notify(
       BulkLeakCheckService::State::kIdle);
-  static_cast<BulkLeakCheckDelegateInterface*>(bulk_leak_check_service())
-      ->OnFinishedCredential(LeakCheckCredential(kUsername1, kPassword),
-                             IsLeaked(true));
+  profile_store().UpdateLogin(MakeForm(kUsername1, kUsername1, kOrigin1, true));
   RunUntilIdle();
 
   // New leak is now picked up by service.
@@ -837,6 +854,20 @@
               testing::ElementsAre(kOrigin1));
 }
 
+TEST_F(PasswordStatusCheckServiceWithoutPasswordStoreTest, NoPasswordStored) {
+  // Let the time pass until a check should have happened.
+  task_environment()->AdvanceClock(base::Days(30));
+  task_environment()->RunUntilIdle();
+
+  // Expect that nothing is initialized.
+  EXPECT_FALSE(service()->GetSavedPasswordsPresenterForTesting());
+  EXPECT_FALSE(service()->GetPasswordCheckDelegateForTesting());
+  EXPECT_FALSE(service()->IsObservingSavedPasswordsPresenterForTesting());
+  EXPECT_FALSE(service()->IsObservingBulkLeakCheckForTesting());
+  EXPECT_FALSE(service()->is_password_check_running());
+  EXPECT_FALSE(service()->is_update_credential_count_pending());
+}
+
 INSTANTIATE_TEST_SUITE_P(
     All,
     PasswordStatusCheckServiceParameterizedCardTest,
diff --git a/chrome/browser/ui/safety_hub/safety_hub_test_util.cc b/chrome/browser/ui/safety_hub/safety_hub_test_util.cc
index c220041..f80bbd9 100644
--- a/chrome/browser/ui/safety_hub/safety_hub_test_util.cc
+++ b/chrome/browser/ui/safety_hub/safety_hub_test_util.cc
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/ui/safety_hub/safety_hub_test_util.h"
+
 #include <memory>
 
 #include "base/run_loop.h"
-#include "chrome/browser/ui/safety_hub/safety_hub_test_util.h"
+#include "base/test/run_until.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/crx_file/id_util.h"
 #include "extensions/browser/extension_prefs.h"
@@ -134,6 +136,15 @@
   service->RemoveObserver(test_observer.get());
 }
 
+void UpdatePasswordCheckServiceAsync(
+    PasswordStatusCheckService* password_service) {
+  password_service->UpdateInsecureCredentialCountAsync();
+  ASSERT_TRUE(base::test::RunUntil([&]() {
+    return !password_service->IsUpdateRunning() &&
+           !password_service->IsInfrastructureReady();
+  }));
+}
+
 std::unique_ptr<testing::NiceMock<MockCWSInfoService>> GetMockCWSInfoService(
     Profile* profile) {
   // Ensure that the mock CWSInfo service returns the needed information.
diff --git a/chrome/browser/ui/safety_hub/safety_hub_test_util.h b/chrome/browser/ui/safety_hub/safety_hub_test_util.h
index 42d1660..2a05d48 100644
--- a/chrome/browser/ui/safety_hub/safety_hub_test_util.h
+++ b/chrome/browser/ui/safety_hub/safety_hub_test_util.h
@@ -7,6 +7,7 @@
 
 #include "chrome/browser/extensions/cws_info_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/safety_hub/password_status_check_service.h"
 #include "chrome/browser/ui/safety_hub/safety_hub_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -30,6 +31,11 @@
 // the function returns.
 void UpdateSafetyHubServiceAsync(SafetyHubService* service);
 
+// This will run UpdateInsecureCredentialCountAsync on
+// PasswordStatusCheckService and return when the check is completed.
+void UpdatePasswordCheckServiceAsync(
+    PasswordStatusCheckService* password_service);
+
 // Creates a mock service that returns mock results for the CWS info service. In
 // total six extensions with different properties are mocked: malware, policy
 // violation, unpublished, combination of malware and unpublished, no violation,
diff --git a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
index 475f578..5a0f87f0 100644
--- a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
@@ -560,9 +560,7 @@
   // Let PasswordStatusCheckService to run till it fetches the latest data.
   PasswordStatusCheckService* password_service =
       PasswordStatusCheckServiceFactory::GetForProfile(profile());
-  // TODO(crbug.com/1443466): Replace this with password_service specific
-  // RunUntilIdle.
-  task_environment()->RunUntilIdle();
+  safety_hub_test_util::UpdatePasswordCheckServiceAsync(password_service);
   EXPECT_EQ(password_service->compromised_credential_count(), 0UL);
 
   // Creating and showing a notification for a site that has never been
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
index 03a2206..bf4a913f 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -12,6 +12,7 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/metrics/user_metrics.h"
 #include "base/ranges/algorithm.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -129,6 +130,7 @@
 
 void RecordUmaCancellation(DialogType dialog_type,
                            base::TimeTicks dialog_open_time) {
+  RecordAction(base::UserMetricsAction("GetDisplayMedia.Cancel"));
   if (dialog_type == DialogType::kPreferCurrentTab) {
     RecordUma(GDMPreferCurrentTabResult::kUserCancelled, dialog_open_time);
   } else {
@@ -151,6 +153,7 @@
       NOTREACHED_NORETURN();
 
     case DesktopMediaList::Type::kScreen:
+      RecordAction(base::UserMetricsAction("GetDisplayMedia.SelectScreen"));
       if (dialog_type == DialogType::kPreferCurrentTab) {
         RecordUma(GDMPreferCurrentTabResult::kUserSelectedScreen,
                   dialog_open_time);
@@ -160,6 +163,7 @@
       break;
 
     case DesktopMediaList::Type::kWindow:
+      RecordAction(base::UserMetricsAction("GetDisplayMedia.SelectWindow"));
       if (dialog_type == DialogType::kPreferCurrentTab) {
         RecordUma(GDMPreferCurrentTabResult::kUserSelectedWindow,
                   dialog_open_time);
@@ -169,6 +173,8 @@
       break;
 
     case DesktopMediaList::Type::kWebContents: {
+      RecordAction(
+          base::UserMetricsAction("GetDisplayMedia.SelectWebContents"));
       // Whether the current tab was selected. Note that this can happen
       // through a non-explicit selection of the current tab through the
       // list of all available tabs.
@@ -193,6 +199,7 @@
     }
 
     case DesktopMediaList::Type::kCurrentTab:
+      RecordAction(base::UserMetricsAction("GetDisplayMedia.SelectCurrentTab"));
       RecordUma(GDMPreferCurrentTabResult::kUserSelectedThisTab,
                 dialog_open_time);
       break;
@@ -390,7 +397,7 @@
       dialog_open_time_(base::TimeTicks::Now()) {
   DCHECK(!params.force_audio_checkboxes_to_default_checked ||
          !params.exclude_system_audio);
-
+  RecordAction(base::UserMetricsAction("GetDisplayMedia.ShowDialog"));
   SetProperty(views::kElementIdentifierKey,
               kDesktopMediaPickerDialogViewIdentifier);
   SetModalType(params.modality);
diff --git a/chrome/browser/ui/webui/settings/safety_hub_handler_unittest.cc b/chrome/browser/ui/webui/settings/safety_hub_handler_unittest.cc
index a4622a8..2760611 100644
--- a/chrome/browser/ui/webui/settings/safety_hub_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/safety_hub_handler_unittest.cc
@@ -5,6 +5,7 @@
 #include <ctime>
 #include <memory>
 
+#include "base/functional/bind.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/gtest_util.h"
@@ -72,14 +73,6 @@
   }
 
   void SetUp() override {
-    // Fully initialize |profile_| in the constructor since some children
-    // classes need it right away for SetUp().
-    TestingProfile::Builder profile_builder;
-    profile_builder.AddTestingFactory(
-        HistoryServiceFactory::GetInstance(),
-        HistoryServiceFactory::GetDefaultFactory());
-    profile_ = profile_builder.Build();
-
     // Set clock for HostContentSettingsMap.
     base::Time time;
     ASSERT_TRUE(base::Time::FromString("2022-09-07 13:00", &time));
@@ -91,10 +84,6 @@
     handler()->set_web_ui(web_ui());
     handler()->AllowJavascript();
 
-    // Create password stores for Password module.
-    profile_store_ = CreateAndUseTestPasswordStore(profile_.get());
-    account_store_ = CreateAndUseTestAccountPasswordStore(profile_.get());
-
     // Create a revoked permission.
     AddRevokedPermission();
 
@@ -105,14 +94,16 @@
     EXPECT_EQ(GURL(kUnusedTestSite),
               GURL(*revoked_permissions[0].GetDict().FindString(
                   site_settings::kOrigin)));
+
+    // Run password check to fetch latest result from disk.
+    safety_hub_test_util::UpdatePasswordCheckServiceAsync(
+        PasswordStatusCheckServiceFactory::GetForProfile(profile()));
   }
 
   void TearDown() override {
-    if (profile_) {
-      auto* partition = profile_->GetDefaultStoragePartition();
-      if (partition) {
-        partition->WaitForDeletionTasksForTesting();
-      }
+    auto* partition = profile()->GetDefaultStoragePartition();
+    if (partition) {
+      partition->WaitForDeletionTasksForTesting();
     }
   }
 
@@ -149,8 +140,8 @@
     profile_store().AddLogin(
         MakeForm(kUsername, kCompromisedPassword, kUsedTestSite, true));
     PasswordStatusCheckService* password_service =
-        PasswordStatusCheckServiceFactory::GetForProfile(profile_.get());
-    RunUntilIdle();
+        PasswordStatusCheckServiceFactory::GetForProfile(profile());
+    safety_hub_test_util::UpdatePasswordCheckServiceAsync(password_service);
     EXPECT_EQ(password_service->compromised_credential_count(), 1UL);
   }
 
@@ -158,8 +149,8 @@
     profile_store().UpdateLogin(
         MakeForm(kUsername, u"new_fnlsr4@cm^mls@fkspnsg3d"));
     PasswordStatusCheckService* password_service =
-        PasswordStatusCheckServiceFactory::GetForProfile(profile_.get());
-    RunUntilIdle();
+        PasswordStatusCheckServiceFactory::GetForProfile(profile());
+    safety_hub_test_util::UpdatePasswordCheckServiceAsync(password_service);
     EXPECT_EQ(password_service->compromised_credential_count(), 0UL);
   }
 
@@ -387,7 +378,7 @@
 
   void RunUntilIdle() { task_environment_.RunUntilIdle(); }
 
-  TestingProfile* profile() { return profile_.get(); }
+  TestingProfile* profile() { return &profile_; }
   content::TestWebUI* web_ui() { return &web_ui_; }
   SafetyHubHandler* handler() { return handler_.get(); }
   HostContentSettingsMap* hcsm() { return hcsm_.get(); }
@@ -403,12 +394,14 @@
   base::test::ScopedFeatureList feature_list_;
   content::BrowserTaskEnvironment task_environment_;
   std::unique_ptr<SafetyHubHandler> handler_;
-  std::unique_ptr<TestingProfile> profile_;
+  TestingProfile profile_;
   content::TestWebUI web_ui_;
   scoped_refptr<HostContentSettingsMap> hcsm_;
   base::SimpleTestClock clock_;
-  scoped_refptr<password_manager::TestPasswordStore> profile_store_;
-  scoped_refptr<password_manager::TestPasswordStore> account_store_;
+  scoped_refptr<TestPasswordStore> profile_store_ =
+      CreateAndUseTestPasswordStore(&profile_);
+  scoped_refptr<password_manager::TestPasswordStore> account_store_ =
+      CreateAndUseTestAccountPasswordStore(&profile_);
 };
 
 TEST_F(SafetyHubHandlerTest, PopulateUnusedSitePermissionsData) {
diff --git a/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.cc b/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.cc
index 7593f7b..87f799f 100644
--- a/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.cc
+++ b/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.cc
@@ -29,7 +29,7 @@
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/network_session_configurator/common/network_switches.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/sync/base/features.h"
 #include "components/sync/test/test_sync_service.h"
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index cb5b80f..c07428bd 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1699595874-faa3982cb69fcc7da93391509bd91481abd29470.profdata
+chrome-android32-main-1699617335-e2d7022eedc6095f77022e47c9f22fc2c0c9b23f.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index c40364d..72584e4 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1699595874-ce8dabb7239701a82c760d3268ef449c22dacd7a.profdata
+chrome-android64-main-1699617335-dde605504ecc10ee8c1c4fbea0fe2e0da32e390b.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index cb13dba..ad97e25 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1699574313-196ec7657aaa36cbe2dc99204f61fca63dd1f9cd.profdata
+chrome-linux-main-1699595874-50828f87e8b822c4a8f5bae6680990f71e47efca.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index bb25a60c..fbf862f 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1699588646-239a7f5d74840d365b72e34c6649461fb8610e29.profdata
+chrome-mac-arm-main-1699595874-cd7345b035a0f64886a5c5f226e29fae64041a37.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index beaed00..8501e1b 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1699574313-95bfde08b679b94e24dc0cc6cdfb3881908564e8.profdata
+chrome-mac-main-1699595874-eaedade8b7ab206ab1b904418c73bc11f4c2968e.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index df62233..69853a8 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1699574313-93c5961dcca784ae7255602deb40ccb68622266d.profdata
+chrome-win-arm64-main-1699617335-1d57351203f0afb552eee305330637584ee2084a.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index a484502..3d96815 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1699585108-cf0e2744794430c56898c5fe35dcafc190d9d701.profdata
+chrome-win32-main-1699606438-933476800caa5b555b93c109913fa8901b99c7fa.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index fc532f9..c88b0a6 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1699585108-7043c07a4f6de1337cc06dc62fc03086548c00da.profdata
+chrome-win64-main-1699606438-c37c23cd7bced425aa0c0f96745fb77b4e9d51cd.profdata
diff --git a/chrome/common/extensions/api/printing_metrics.idl b/chrome/common/extensions/api/printing_metrics.idl
index 777c325..caff1a6 100644
--- a/chrome/common/extensions/api/printing_metrics.idl
+++ b/chrome/common/extensions/api/printing_metrics.idl
@@ -17,7 +17,10 @@
     ANDROID_APP,
 
     // Specifies that the job was created by extension via Chrome API.
-    EXTENSION
+    EXTENSION,
+
+    // Specifies that the job was created by an Isolated Web App via API.
+    ISOLATED_WEB_APP
   };
 
   // Specifies the final status of the print job.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index cb0e310c..e368062 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -11187,6 +11187,7 @@
 
     if (is_mac) {
       sources += [
+        "../browser/app_controller_mac_interactive_uitest.mm",
         "../browser/global_keyboard_shortcuts_interactive_uitest_mac.mm",
         "../browser/notifications/mac/notification_interactive_uitest_mac.mm",
         "../browser/spellchecker/spellcheck_mac_view_interactive_uitest.mm",
diff --git a/chrome/test/chromedriver/keycode_text_conversion.h b/chrome/test/chromedriver/keycode_text_conversion.h
index 9a4b3d15..eb51195f 100644
--- a/chrome/test/chromedriver/keycode_text_conversion.h
+++ b/chrome/test/chromedriver/keycode_text_conversion.h
@@ -41,6 +41,7 @@
 #endif
 
 #if BUILDFLAG(IS_OZONE)
+void InitializeOzoneKeyboardEngineManager();
 #if BUILDFLAG(OZONE_PLATFORM_X11)
 // Uses X11 implementation if there is an X display.
 // TODO(crbug.com/987939): Support XKB.
diff --git a/chrome/test/chromedriver/keycode_text_conversion_ozone.cc b/chrome/test/chromedriver/keycode_text_conversion_ozone.cc
index f1f83d62..3a7cb6a 100644
--- a/chrome/test/chromedriver/keycode_text_conversion_ozone.cc
+++ b/chrome/test/chromedriver/keycode_text_conversion_ozone.cc
@@ -22,6 +22,13 @@
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #endif
 
+void InitializeOzoneKeyboardEngineManager() {
+  static std::unique_ptr<ui::StubKeyboardLayoutEngine> keyboard_layout_engine_ =
+      std::make_unique<ui::StubKeyboardLayoutEngine>();
+  ui::KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(
+      keyboard_layout_engine_.get());
+}
+
 #if BUILDFLAG(OZONE_PLATFORM_X11)
 bool ConvertKeyCodeToTextOzone
 #else
@@ -33,11 +40,8 @@
      std::string* error_msg) {
   ui::KeyboardLayoutEngine* keyboard_layout_engine =
       ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine();
-
-  std::unique_ptr<ui::StubKeyboardLayoutEngine> stub_layout_engine;
   if (!keyboard_layout_engine) {
-    stub_layout_engine = std::make_unique<ui::StubKeyboardLayoutEngine>();
-    keyboard_layout_engine = stub_layout_engine.get();
+    return false;
   }
   ui::DomCode dom_code = ui::UsLayoutKeyboardCodeToDomCode(key_code);
   int event_flags = ui::EF_NONE;
diff --git a/chrome/test/chromedriver/server/chromedriver_server.cc b/chrome/test/chromedriver/server/chromedriver_server.cc
index 069d77c..676927a 100644
--- a/chrome/test/chromedriver/server/chromedriver_server.cc
+++ b/chrome/test/chromedriver/server/chromedriver_server.cc
@@ -35,6 +35,7 @@
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/test/chromedriver/constants/version.h"
+#include "chrome/test/chromedriver/keycode_text_conversion.h"
 #include "chrome/test/chromedriver/logging.h"
 #include "chrome/test/chromedriver/server/http_handler.h"
 #include "chrome/test/chromedriver/server/http_server.h"
@@ -464,6 +465,10 @@
 
   mojo::core::Init();
 
+#if BUILDFLAG(IS_OZONE)
+  InitializeOzoneKeyboardEngineManager();
+#endif
+
   base::ThreadPoolInstance::CreateAndStartWithDefaultParams(
       kChromeDriverProductShortName);
 
diff --git a/chrome/utility/services.cc b/chrome/utility/services.cc
index dc7b371..6c6d9e0 100644
--- a/chrome/utility/services.cc
+++ b/chrome/utility/services.cc
@@ -34,6 +34,7 @@
 #include "ui/accessibility/accessibility_features.h"
 
 #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
+#include "components/services/screen_ai/public/mojom/screen_ai_factory.mojom.h"  // nogncheck
 #include "components/services/screen_ai/screen_ai_service_impl.h"  // nogncheck
 #endif
 
diff --git a/chromecast/app/cast_main_delegate.cc b/chromecast/app/cast_main_delegate.cc
index cdec40b1..245044f2 100644
--- a/chromecast/app/cast_main_delegate.cc
+++ b/chromecast/app/cast_main_delegate.cc
@@ -72,7 +72,7 @@
 
 CastMainDelegate::~CastMainDelegate() {}
 
-absl::optional<int> CastMainDelegate::BasicStartupComplete() {
+std::optional<int> CastMainDelegate::BasicStartupComplete() {
   RegisterPathProvider();
 
   logging::LoggingSettings settings;
@@ -160,7 +160,7 @@
   if (settings.logging_dest & logging::LOG_TO_FILE) {
     LOG(INFO) << "Logging to file: " << settings.log_file_path;
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 void CastMainDelegate::PreSandboxStartup() {
@@ -236,11 +236,11 @@
   return ShouldCreateFeatureList(invoked_in);
 }
 
-absl::optional<int> CastMainDelegate::PostEarlyInitialization(
+std::optional<int> CastMainDelegate::PostEarlyInitialization(
     InvokedIn invoked_in) {
   if (ShouldCreateFeatureList(invoked_in)) {
     // content is handling the feature list.
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   DCHECK(cast_feature_list_creator_);
@@ -284,7 +284,7 @@
 
   content::InitializeMojoCore();
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 void CastMainDelegate::InitializeResourceBundle() {
diff --git a/chromecast/app/cast_main_delegate.h b/chromecast/app/cast_main_delegate.h
index d285d217..7866ee0f 100644
--- a/chromecast/app/cast_main_delegate.h
+++ b/chromecast/app/cast_main_delegate.h
@@ -7,10 +7,10 @@
 
 #include <memory>
 
+#include <optional>
 #include "build/build_config.h"
 #include "chromecast/common/cast_content_client.h"
 #include "content/public/app/content_main_delegate.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace content {
 class BrowserMainRunner;
@@ -38,7 +38,7 @@
   ~CastMainDelegate() override;
 
   // content::ContentMainDelegate implementation:
-  absl::optional<int> BasicStartupComplete() override;
+  std::optional<int> BasicStartupComplete() override;
   void PreSandboxStartup() override;
   absl::variant<int, content::MainFunctionParams> RunProcess(
       const std::string& process_type,
@@ -48,7 +48,7 @@
 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
   bool ShouldCreateFeatureList(InvokedIn invoked_in) override;
   bool ShouldInitializeMojo(InvokedIn invoked_in) override;
-  absl::optional<int> PostEarlyInitialization(InvokedIn invoked_in) override;
+  std::optional<int> PostEarlyInitialization(InvokedIn invoked_in) override;
   content::ContentClient* CreateContentClient() override;
   content::ContentBrowserClient* CreateContentBrowserClient() override;
   content::ContentGpuClient* CreateContentGpuClient() override;
diff --git a/chromecast/base/device_capabilities_impl_unittest.cc b/chromecast/base/device_capabilities_impl_unittest.cc
index c01d2f7..ed5fa51 100644
--- a/chromecast/base/device_capabilities_impl_unittest.cc
+++ b/chromecast/base/device_capabilities_impl_unittest.cc
@@ -582,7 +582,7 @@
 
 // Test MergeDictionary.
 TEST_F(DeviceCapabilitiesImplTest, MergeDictionary) {
-  absl::optional<base::Value::Dict> deserialized_value =
+  std::optional<base::Value::Dict> deserialized_value =
       base::JSONReader::ReadDict(kSampleDictionaryCapability);
   ASSERT_TRUE(deserialized_value);
 
diff --git a/chromecast/base/metrics/cast_metrics_helper_unittest.cc b/chromecast/base/metrics/cast_metrics_helper_unittest.cc
index 2a8dadd..ebc6a3178 100644
--- a/chromecast/base/metrics/cast_metrics_helper_unittest.cc
+++ b/chromecast/base/metrics/cast_metrics_helper_unittest.cc
@@ -37,7 +37,7 @@
 constexpr base::TimeDelta kAppLoadTimeout = base::Minutes(5);
 
 MATCHER_P2(HasDouble, key, value, "") {
-  const absl::optional<base::Value> v = base::JSONReader::Read(arg);
+  const std::optional<base::Value> v = base::JSONReader::Read(arg);
   if (!v || !v->is_dict()) {
     return false;
   }
@@ -47,7 +47,7 @@
 }
 
 MATCHER_P2(HasInt, key, value, "") {
-  const absl::optional<base::Value> v = base::JSONReader::Read(arg);
+  const std::optional<base::Value> v = base::JSONReader::Read(arg);
   if (!v || !v->is_dict()) {
     return false;
   }
@@ -57,7 +57,7 @@
 }
 
 MATCHER_P2(HasString, key, value, "") {
-  const absl::optional<base::Value> v = base::JSONReader::Read(arg);
+  const std::optional<base::Value> v = base::JSONReader::Read(arg);
   if (!v || !v->is_dict()) {
     return false;
   }
diff --git a/chromecast/bindings/shared/proto_serializer.h b/chromecast/bindings/shared/proto_serializer.h
index 451d061..258e864 100644
--- a/chromecast/bindings/shared/proto_serializer.h
+++ b/chromecast/bindings/shared/proto_serializer.h
@@ -5,8 +5,8 @@
 #ifndef CHROMECAST_BINDINGS_SHARED_PROTO_SERIALIZER_H_
 #define CHROMECAST_BINDINGS_SHARED_PROTO_SERIALIZER_H_
 
+#include <optional>
 #include "base/base64.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 namespace bindings {
@@ -32,15 +32,15 @@
   // Deserializes |base64| to its proto representation, parsed into |result|.
   // Returns a value if parsing is successful; otherwise, returns false. Used
   // by bindings frontends and backends for consistent serialization logic.
-  static absl::optional<T> Deserialize(base::StringPiece base64_proto) {
+  static std::optional<T> Deserialize(base::StringPiece base64_proto) {
     std::string decoded;
     if (!base::Base64Decode(base64_proto, &decoded)) {
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     T result;
-    return result.ParseFromString(decoded) ? absl::make_optional<T>(result)
-                                           : absl::nullopt;
+    return result.ParseFromString(decoded) ? std::make_optional<T>(result)
+                                           : std::nullopt;
   }
 };
 
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 4cce48520..77755d3 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -691,14 +691,14 @@
   return true;
 }
 
-absl::optional<service_manager::Manifest>
+std::optional<service_manager::Manifest>
 CastContentBrowserClient::GetServiceManifestOverlay(
     base::StringPiece service_name) {
   if (service_name == ServiceManagerContext::kBrowserServiceName) {
     return GetCastContentBrowserOverlayManifest();
   }
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 std::vector<service_manager::Manifest>
@@ -828,7 +828,7 @@
 void CastContentBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
     int render_process_id,
     int render_frame_id,
-    const absl::optional<url::Origin>& request_initiator_origin,
+    const std::optional<url::Origin>& request_initiator_origin,
     NonNetworkURLLoaderFactoryMap* factories) {
   if (render_frame_id == MSG_ROUTING_NONE) {
     LOG(ERROR) << "Service worker not supported.";
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 82edb81c..77a22da 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -167,7 +167,7 @@
   virtual void RunServiceInstance(
       const service_manager::Identity& identity,
       mojo::PendingReceiver<service_manager::mojom::Service>* receiver);
-  virtual absl::optional<service_manager::Manifest> GetServiceManifestOverlay(
+  virtual std::optional<service_manager::Manifest> GetServiceManifestOverlay(
       base::StringPiece service_name);
   std::vector<service_manager::Manifest> GetExtraServiceManifests();
   std::vector<std::string> GetStartupServices();
@@ -245,7 +245,7 @@
   void RegisterNonNetworkSubresourceURLLoaderFactories(
       int render_process_id,
       int render_frame_id,
-      const absl::optional<url::Origin>& request_initiator_origin,
+      const std::optional<url::Origin>& request_initiator_origin,
       NonNetworkURLLoaderFactoryMap* factories) override;
   void OnNetworkServiceCreated(
       network::mojom::NetworkService* network_service) override;
diff --git a/chromecast/browser/cast_media_blocker.h b/chromecast/browser/cast_media_blocker.h
index 12706bd..2a5f176a 100644
--- a/chromecast/browser/cast_media_blocker.h
+++ b/chromecast/browser/cast_media_blocker.h
@@ -52,7 +52,7 @@
   void MediaSessionInfoChanged(
       media_session::mojom::MediaSessionInfoPtr session_info) override;
   void MediaSessionMetadataChanged(
-      const absl::optional<media_session::MediaMetadata>& metadata) override {}
+      const std::optional<media_session::MediaMetadata>& metadata) override {}
   void MediaSessionActionsChanged(
       const std::vector<media_session::mojom::MediaSessionAction>& action)
       override {}
@@ -61,7 +61,7 @@
                            std::vector<media_session::MediaImage>>& images)
       override {}
   void MediaSessionPositionChanged(
-      const absl::optional<media_session::MediaPosition>& position) override {}
+      const std::optional<media_session::MediaPosition>& position) override {}
 
  private:
   friend shell::CastMediaBlockerTest;
diff --git a/chromecast/browser/cast_web_contents.h b/chromecast/browser/cast_web_contents.h
index d0fa2bb..4bec6c8 100644
--- a/chromecast/browser/cast_web_contents.h
+++ b/chromecast/browser/cast_web_contents.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/containers/flat_set.h"
 #include "base/functional/callback_forward.h"
 #include "base/observer_list.h"
@@ -26,7 +27,6 @@
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/remote_set.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/messaging/web_message_port.h"
 #include "ui/gfx/geometry/rect.h"
 #include "url/gurl.h"
diff --git a/chromecast/browser/cast_web_contents_browsertest.cc b/chromecast/browser/cast_web_contents_browsertest.cc
index 49f0ecb..d9885f9 100644
--- a/chromecast/browser/cast_web_contents_browsertest.cc
+++ b/chromecast/browser/cast_web_contents_browsertest.cc
@@ -175,8 +175,8 @@
   ~TestMessageReceiver() override = default;
 
   void WaitForNextIncomingMessage(
-      base::OnceCallback<
-          void(std::string, absl::optional<blink::WebMessagePort>)> callback) {
+      base::OnceCallback<void(std::string,
+                              std::optional<blink::WebMessagePort>)> callback) {
     DCHECK(message_received_callback_.is_null())
         << "Only one waiting event is allowed.";
     message_received_callback_ = std::move(callback);
@@ -194,12 +194,12 @@
       return false;
     }
 
-    absl::optional<blink::WebMessagePort> incoming_port = absl::nullopt;
+    std::optional<blink::WebMessagePort> incoming_port = std::nullopt;
     // Only one MessagePort should be sent to here.
     if (!message.ports.empty()) {
       DCHECK(message.ports.size() == 1)
           << "Only one control port can be provided";
-      incoming_port = absl::make_optional<blink::WebMessagePort>(
+      incoming_port = std::make_optional<blink::WebMessagePort>(
           std::move(message.ports[0]));
     }
 
@@ -216,7 +216,7 @@
   }
 
   base::OnceCallback<void(std::string,
-                          absl::optional<blink::WebMessagePort> incoming_port)>
+                          std::optional<blink::WebMessagePort> incoming_port)>
       message_received_callback_;
 
   base::OnceCallback<void()> on_pipe_error_callback_;
@@ -809,7 +809,7 @@
     auto quit_closure = run_loop.QuitClosure();
     auto received_message_callback = base::BindOnce(
         [](base::OnceClosure loop_quit_closure, std::string port_msg,
-           absl::optional<blink::WebMessagePort> incoming_port) {
+           std::optional<blink::WebMessagePort> incoming_port) {
           EXPECT_EQ("got_port", port_msg);
           std::move(loop_quit_closure).Run();
         },
@@ -830,7 +830,7 @@
     auto quit_closure = run_loop.QuitClosure();
     auto received_message_callback = base::BindOnce(
         [](base::OnceClosure loop_quit_closure, std::string port_msg,
-           absl::optional<blink::WebMessagePort> incoming_port) {
+           std::optional<blink::WebMessagePort> incoming_port) {
           EXPECT_EQ("ack ping", port_msg);
           std::move(loop_quit_closure).Run();
         },
@@ -876,7 +876,7 @@
     auto quit_closure = run_loop.QuitClosure();
     auto received_message_callback = base::BindOnce(
         [](base::OnceClosure loop_quit_closure, std::string port_msg,
-           absl::optional<blink::WebMessagePort> incoming_port) {
+           std::optional<blink::WebMessagePort> incoming_port) {
           EXPECT_EQ("got_port", port_msg);
           std::move(loop_quit_closure).Run();
         },
diff --git a/chromecast/browser/cast_web_contents_impl.cc b/chromecast/browser/cast_web_contents_impl.cc
index e3dd24e..43890e6 100644
--- a/chromecast/browser/cast_web_contents_impl.cc
+++ b/chromecast/browser/cast_web_contents_impl.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/logging.h"
@@ -41,7 +42,6 @@
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/net_errors.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/autoplay/autoplay.mojom.h"
@@ -397,7 +397,7 @@
   data_utf16 = base::UTF8ToUTF16(data);
 
   // If origin is set as wildcard, no origin scoping would be applied.
-  absl::optional<std::u16string> target_origin_utf16;
+  std::optional<std::u16string> target_origin_utf16;
   constexpr char kWildcardOrigin[] = "*";
   if (target_origin != kWildcardOrigin) {
     target_origin_utf16 = base::UTF8ToUTF16(target_origin);
diff --git a/chromecast/browser/cast_web_contents_impl.h b/chromecast/browser/cast_web_contents_impl.h
index 43afceb5..b164a30 100644
--- a/chromecast/browser/cast_web_contents_impl.h
+++ b/chromecast/browser/cast_web_contents_impl.h
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
 #include "base/memory/platform_shared_memory_region.h"
@@ -36,7 +37,6 @@
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/favicon/favicon_url.mojom-forward.h"
 
 namespace content {
@@ -175,13 +175,13 @@
 
   content::WebContents* web_contents_;
   mojom::CastWebViewParamsPtr params_;
-  absl::optional<url_rewrite::UrlRequestRewriteRulesManager>
+  std::optional<url_rewrite::UrlRequestRewriteRulesManager>
       url_rewrite_rules_manager_;
   PageState page_state_;
   PageState last_state_;
   shell::RemoteDebuggingServer* const remote_debugging_server_;
   std::unique_ptr<CastMediaBlocker> media_blocker_;
-  absl::optional<std::vector<std::string>> activity_url_filter_;
+  std::optional<std::vector<std::string>> activity_url_filter_;
 
   // Retained so that this observer can be removed before being destroyed:
   content::RenderProcessHost* main_process_host_;
diff --git a/chromecast/browser/cast_web_preferences.h b/chromecast/browser/cast_web_preferences.h
index e7d12c8..31e5c6e 100644
--- a/chromecast/browser/cast_web_preferences.h
+++ b/chromecast/browser/cast_web_preferences.h
@@ -5,8 +5,8 @@
 #ifndef CHROMECAST_BROWSER_CAST_WEB_PREFERENCES_H_
 #define CHROMECAST_BROWSER_CAST_WEB_PREFERENCES_H_
 
+#include <optional>
 #include "base/supports_user_data.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h"
 
 namespace chromecast {
@@ -18,10 +18,10 @@
   struct Preferences {
     Preferences();
 
-    absl::optional<blink::mojom::AutoplayPolicy> autoplay_policy;
-    absl::optional<bool> hide_scrollbars;
-    absl::optional<bool> javascript_enabled;
-    absl::optional<bool> supports_multiple_windows;
+    std::optional<blink::mojom::AutoplayPolicy> autoplay_policy;
+    std::optional<bool> hide_scrollbars;
+    std::optional<bool> javascript_enabled;
+    std::optional<bool> supports_multiple_windows;
   };
 
   // Unique key used to identify CastWebPreferences in WebContents' user data.
diff --git a/chromecast/browser/devtools/remote_debugging_server.cc b/chromecast/browser/devtools/remote_debugging_server.cc
index 4cb67d3..b5b2e1f 100644
--- a/chromecast/browser/devtools/remote_debugging_server.cc
+++ b/chromecast/browser/devtools/remote_debugging_server.cc
@@ -90,7 +90,7 @@
     std::unique_ptr<net::ServerSocket> socket(
         new net::TCPServerSocket(nullptr, net::NetLogSource()));
 
-    if (socket->Listen(endpoint_, kBackLog, /*ipv6_only=*/absl::nullopt) !=
+    if (socket->Listen(endpoint_, kBackLog, /*ipv6_only=*/std::nullopt) !=
         net::OK) {
       return nullptr;
     }
diff --git a/chromecast/browser/service_manager_context.cc b/chromecast/browser/service_manager_context.cc
index f7d6fd78..d3435c1 100644
--- a/chromecast/browser/service_manager_context.cc
+++ b/chromecast/browser/service_manager_context.cc
@@ -9,6 +9,7 @@
 #include <string>
 #include <utility>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/functional/bind.h"
@@ -43,7 +44,6 @@
 #include "services/service_manager/service_manager.h"
 #include "services/service_manager/service_process_host.h"
 #include "services/service_manager/service_process_launcher.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/buildflags.h"
 #include "ui/base/ui_base_features.h"
 
@@ -316,7 +316,7 @@
   manifests.push_back(GetBrowserManifest());
   manifests.push_back(GetSystemManifest(cast_content_browser_client_));
   for (auto& manifest : manifests) {
-    absl::optional<service_manager::Manifest> overlay =
+    std::optional<service_manager::Manifest> overlay =
         cast_content_browser_client_->GetServiceManifestOverlay(
             manifest.service_name);
     if (overlay)
diff --git a/chromecast/browser/webui/cast_resource_data_source.h b/chromecast/browser/webui/cast_resource_data_source.h
index 7c74e09..edc1205 100644
--- a/chromecast/browser/webui/cast_resource_data_source.h
+++ b/chromecast/browser/webui/cast_resource_data_source.h
@@ -7,11 +7,11 @@
 
 #include <string>
 
+#include <optional>
 #include "chromecast/browser/webui/mojom/webui.mojom.h"
 #include "content/public/browser/url_data_source.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 
@@ -47,7 +47,7 @@
   const bool for_webui_;
   mojo::Remote<mojom::Resources> remote_;
 
-  absl::optional<std::string> frame_src_;
+  std::optional<std::string> frame_src_;
   bool deny_xframe_options_ = true;
 };
 
diff --git a/chromecast/cast_core/grpc/grpc_server_reactor.h b/chromecast/cast_core/grpc/grpc_server_reactor.h
index 8578e1e..2c666da 100644
--- a/chromecast/cast_core/grpc/grpc_server_reactor.h
+++ b/chromecast/cast_core/grpc/grpc_server_reactor.h
@@ -8,11 +8,11 @@
 #include <grpcpp/generic/async_generic_service.h>
 #include <grpcpp/grpcpp.h>
 
+#include <optional>
 #include "base/check_op.h"
 #include "base/logging.h"
 #include "base/memory/raw_ptr.h"
 #include "chromecast/cast_core/grpc/grpc_status_or.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace cast {
 namespace utils {
@@ -132,8 +132,8 @@
   const std::string name_;
   raw_ptr<grpc::CallbackServerContext> context_;
 
-  absl::optional<grpc::ByteBuffer> request_byte_buffer_;
-  absl::optional<grpc::ByteBuffer> response_byte_buffer_;
+  std::optional<grpc::ByteBuffer> request_byte_buffer_;
+  std::optional<grpc::ByteBuffer> response_byte_buffer_;
 };
 
 }  // namespace utils
diff --git a/chromecast/cast_core/grpc/grpc_status_or.h b/chromecast/cast_core/grpc/grpc_status_or.h
index 0b67351..fec7cca 100644
--- a/chromecast/cast_core/grpc/grpc_status_or.h
+++ b/chromecast/cast_core/grpc/grpc_status_or.h
@@ -10,8 +10,8 @@
 #include <string>
 #include <type_traits>
 
+#include <optional>
 #include "base/check.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace cast {
 namespace utils {
@@ -118,7 +118,7 @@
 
  private:
   grpc::Status status_;
-  absl::optional<T> data_;
+  std::optional<T> data_;
 };
 
 }  // namespace utils
diff --git a/chromecast/cast_core/runtime/browser/cast_runtime_metrics_recorder.cc b/chromecast/cast_core/runtime/browser/cast_runtime_metrics_recorder.cc
index 5c72fde4..67c1898 100644
--- a/chromecast/cast_core/runtime/browser/cast_runtime_metrics_recorder.cc
+++ b/chromecast/cast_core/runtime/browser/cast_runtime_metrics_recorder.cc
@@ -7,6 +7,7 @@
 #include <cfloat>
 #include <cmath>
 
+#include <optional>
 #include "base/json/json_string_value_serializer.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_base.h"
@@ -18,7 +19,6 @@
 #include "base/values.h"
 #include "chromecast/base/metrics/cast_histograms.h"
 #include "chromecast/base/metrics/cast_metrics_helper.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/metrics_proto/cast_logs.pb.h"
 
 namespace chromecast {
@@ -252,7 +252,7 @@
   }
 
   // Gets event creation time. If unavailable use now.
-  absl::optional<double> maybe_event_time = value_dict.FindDouble(kEventTime);
+  std::optional<double> maybe_event_time = value_dict.FindDouble(kEventTime);
   double event_time = 0;
   if (maybe_event_time && maybe_event_time.value() > 0) {
     event_time = maybe_event_time.value();
@@ -285,7 +285,7 @@
     std::unique_ptr<CastEventBuilder> event_builder(CreateEventBuilder(*name));
     PopulateEventBuilder(event_builder.get(), event_time, app_id, sdk_version,
                          session_id);
-    absl::optional<double> maybe_event_value =
+    std::optional<double> maybe_event_value =
         value_dict.FindDouble(kEventValue);
     if (maybe_event_value) {
       double event_value = maybe_event_value.value();
@@ -304,7 +304,7 @@
   }
 
   for (auto kv : *multiple_events) {
-    absl::optional<double> maybe_event_value = kv.second.GetIfDouble();
+    std::optional<double> maybe_event_value = kv.second.GetIfDouble();
     if (!maybe_event_value) {
       continue;
     }
diff --git a/chromecast/cast_core/runtime/browser/core_conversions.cc b/chromecast/cast_core/runtime/browser/core_conversions.cc
index 50dfa5e..ab58ce5 100644
--- a/chromecast/cast_core/runtime/browser/core_conversions.cc
+++ b/chromecast/cast_core/runtime/browser/core_conversions.cc
@@ -76,7 +76,7 @@
   if (core_config.has_cast_web_app_config()) {
     config.url = GURL(core_config.cast_web_app_config().url());
     if (!config.url->is_valid()) {
-      config.url = absl::nullopt;
+      config.url = std::nullopt;
     }
   }
 
diff --git a/chromecast/cast_core/runtime/browser/core_streaming_config_manager.cc b/chromecast/cast_core/runtime/browser/core_streaming_config_manager.cc
index 815b1e6..c2e7e38 100644
--- a/chromecast/cast_core/runtime/browser/core_streaming_config_manager.cc
+++ b/chromecast/cast_core/runtime/browser/core_streaming_config_manager.cc
@@ -62,9 +62,9 @@
     const PlatformInfoSerializer& deserializer) {
   cast_streaming::ReceiverConfig constraints;
 
-  const absl::optional<int> width = deserializer.MaxWidth();
-  const absl::optional<int> height = deserializer.MaxHeight();
-  const absl::optional<int> frame_rate = deserializer.MaxFrameRate();
+  const std::optional<int> width = deserializer.MaxWidth();
+  const std::optional<int> height = deserializer.MaxHeight();
+  const std::optional<int> frame_rate = deserializer.MaxFrameRate();
   if (width && *width && height && *height && frame_rate && *frame_rate) {
     cast_streaming::ReceiverConfig::Display display;
     display.dimensions = gfx::Rect{*width, *height};
@@ -209,7 +209,7 @@
 
   DCHECK(ports.empty());
 
-  absl::optional<PlatformInfoSerializer> deserializer =
+  std::optional<PlatformInfoSerializer> deserializer =
       PlatformInfoSerializer::Deserialize(message);
   if (!deserializer) {
     LOG(ERROR) << "AV Settings with invalid protobuf received: " << message;
diff --git a/chromecast/cast_core/runtime/browser/core_streaming_config_manager_unittest.cc b/chromecast/cast_core/runtime/browser/core_streaming_config_manager_unittest.cc
index 03610bbe..6a6bc805d 100644
--- a/chromecast/cast_core/runtime/browser/core_streaming_config_manager_unittest.cc
+++ b/chromecast/cast_core/runtime/browser/core_streaming_config_manager_unittest.cc
@@ -82,7 +82,7 @@
   auto config = streaming_config_manager_.config();
   ASSERT_EQ(config.audio_limits.size(), size_t{1});
   auto& limit = config.audio_limits.back();
-  EXPECT_EQ(limit.codec, absl::nullopt);
+  EXPECT_EQ(limit.codec, std::nullopt);
   EXPECT_EQ(limit.channel_layout, ::media::CHANNEL_LAYOUT_STEREO);
 }
 
diff --git a/chromecast/cast_core/runtime/browser/grpc_resource_data_source.h b/chromecast/cast_core/runtime/browser/grpc_resource_data_source.h
index b3dd32b..5542b44 100644
--- a/chromecast/cast_core/runtime/browser/grpc_resource_data_source.h
+++ b/chromecast/cast_core/runtime/browser/grpc_resource_data_source.h
@@ -5,9 +5,9 @@
 #ifndef CHROMECAST_CAST_CORE_RUNTIME_BROWSER_GRPC_RESOURCE_DATA_SOURCE_H_
 #define CHROMECAST_CAST_CORE_RUNTIME_BROWSER_GRPC_RESOURCE_DATA_SOURCE_H_
 
+#include <optional>
 #include "base/task/sequenced_task_runner.h"
 #include "content/public/browser/url_data_source.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cast_core/public/src/proto/v2/core_application_service.castcore.pb.h"
 
 namespace chromecast {
@@ -67,7 +67,7 @@
   const bool for_webui_;
   cast::v2::CoreApplicationServiceStub* const core_app_service_stub_;
 
-  absl::optional<std::string> frame_src_;
+  std::optional<std::string> frame_src_;
   bool deny_xframe_options_ = true;
 
   base::WeakPtrFactory<GrpcResourceDataSource> weak_factory_{this};
diff --git a/chromecast/cast_core/runtime/browser/runtime_application_service_impl.h b/chromecast/cast_core/runtime/browser/runtime_application_service_impl.h
index fd1d2ba..7878e09 100644
--- a/chromecast/cast_core/runtime/browser/runtime_application_service_impl.h
+++ b/chromecast/cast_core/runtime/browser/runtime_application_service_impl.h
@@ -163,11 +163,11 @@
   // use.
   std::unique_ptr<MessagePortServiceGrpc> message_port_service_;
 
-  absl::optional<cast::utils::GrpcServer> grpc_server_;
-  absl::optional<cast::v2::CoreApplicationServiceStub> core_app_stub_;
-  absl::optional<cast::v2::CoreMessagePortApplicationServiceStub>
+  std::optional<cast::utils::GrpcServer> grpc_server_;
+  std::optional<cast::v2::CoreApplicationServiceStub> core_app_stub_;
+  std::optional<cast::v2::CoreMessagePortApplicationServiceStub>
       core_message_port_app_stub_;
-  absl::optional<std::string> cast_media_service_grpc_endpoint_;
+  std::optional<std::string> cast_media_service_grpc_endpoint_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/chromecast/cast_core/runtime/browser/runtime_service_impl.h b/chromecast/cast_core/runtime/browser/runtime_service_impl.h
index 1a0b918..7440104a 100644
--- a/chromecast/cast_core/runtime/browser/runtime_service_impl.h
+++ b/chromecast/cast_core/runtime/browser/runtime_service_impl.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/memory/weak_ptr.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/time/time.h"
@@ -18,7 +19,6 @@
 #include "chromecast/cast_core/runtime/browser/runtime_application_service_impl.h"
 #include "components/cast_receiver/browser/public/runtime_application_dispatcher.h"
 #include "components/cast_receiver/common/public/status.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cast_core/public/src/proto/metrics/metrics_recorder.castcore.pb.h"
 #include "third_party/cast_core/public/src/proto/runtime/runtime_service.castcore.pb.h"
 
@@ -118,12 +118,12 @@
   // Allows metrics, histogram, action recording, which can be reported by
   // CastRuntimeMetricsRecorderService if Cast Core starts it.
   CastRuntimeMetricsRecorder metrics_recorder_;
-  absl::optional<CastRuntimeActionRecorder> action_recorder_;
+  std::optional<CastRuntimeActionRecorder> action_recorder_;
 
-  absl::optional<cast::utils::GrpcServer> grpc_server_;
-  absl::optional<cast::metrics::MetricsRecorderServiceStub>
+  std::optional<cast::utils::GrpcServer> grpc_server_;
+  std::optional<cast::metrics::MetricsRecorderServiceStub>
       metrics_recorder_stub_;
-  absl::optional<CastRuntimeMetricsRecorderService> metrics_recorder_service_;
+  std::optional<CastRuntimeMetricsRecorderService> metrics_recorder_service_;
 
   // Heartbeat period as set by Cast Core.
   base::TimeDelta heartbeat_period_;
diff --git a/chromecast/cast_core/runtime/browser/url_rewrite/url_request_rewrite_type_converters.cc b/chromecast/cast_core/runtime/browser/url_rewrite/url_request_rewrite_type_converters.cc
index 7d70a43..2b5a824 100644
--- a/chromecast/cast_core/runtime/browser/url_rewrite/url_request_rewrite_type_converters.cc
+++ b/chromecast/cast_core/runtime/browser/url_rewrite/url_request_rewrite_type_converters.cc
@@ -42,7 +42,7 @@
     url_rewrite::mojom::UrlRequestRewriteRemoveHeaderPtr remove_header =
         url_rewrite::mojom::UrlRequestRewriteRemoveHeader::New();
     if (!input.query_pattern().empty())
-      remove_header->query_pattern = absl::make_optional(input.query_pattern());
+      remove_header->query_pattern = std::make_optional(input.query_pattern());
     if (!input.header_name().empty())
       remove_header->header_name = input.header_name();
     return remove_header;
diff --git a/chromecast/cast_core/runtime/browser/url_rewrite/url_request_rewrite_type_converters_unittest.cc b/chromecast/cast_core/runtime/browser/url_rewrite/url_request_rewrite_type_converters_unittest.cc
index f381363..4000965 100644
--- a/chromecast/cast_core/runtime/browser/url_rewrite/url_request_rewrite_type_converters_unittest.cc
+++ b/chromecast/cast_core/runtime/browser/url_rewrite/url_request_rewrite_type_converters_unittest.cc
@@ -4,12 +4,12 @@
 
 #include "chromecast/cast_core/runtime/browser/url_rewrite/url_request_rewrite_type_converters.h"
 
+#include <optional>
 #include "base/run_loop.h"
 #include "base/strings/string_piece.h"
 #include "components/url_rewrite/browser/url_request_rewrite_rules_validation.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cast_core/public/src/proto/v2/url_rewrite.pb.h"
 
 namespace chromecast {
@@ -28,7 +28,7 @@
 }
 
 cast::v2::UrlRequestRewrite CreateRewriteRemoveHeader(
-    absl::optional<std::string> query_pattern,
+    std::optional<std::string> query_pattern,
     std::string header_name) {
   cast::v2::UrlRequestRewrite rewrite;
   auto* remove_header = rewrite.mutable_remove_header();
@@ -107,7 +107,7 @@
 // Tests RemoveHeader rewrites are properly converted to their Mojo equivalent.
 TEST_F(UrlRequestRewriteTypeConvertersTest, ConvertRemoveHeader) {
   EXPECT_TRUE(UpdateRulesFromRewrite(
-      CreateRewriteRemoveHeader(absl::make_optional("Test"), "Header")));
+      CreateRewriteRemoveHeader(std::make_optional("Test"), "Header")));
   ASSERT_THAT(cached_rules_->rules, SizeIs(1));
   ASSERT_FALSE(cached_rules_->rules[0]->hosts_filter);
   ASSERT_FALSE(cached_rules_->rules[0]->schemes_filter);
@@ -122,7 +122,7 @@
 
   // Create a RemoveHeader rewrite with no pattern.
   EXPECT_TRUE(UpdateRulesFromRewrite(
-      CreateRewriteRemoveHeader(absl::nullopt, "Header")));
+      CreateRewriteRemoveHeader(std::nullopt, "Header")));
   ASSERT_THAT(cached_rules_->rules, SizeIs(1));
   ASSERT_FALSE(cached_rules_->rules[0]->hosts_filter);
   ASSERT_FALSE(cached_rules_->rules[0]->schemes_filter);
diff --git a/chromecast/common/cast_content_client.cc b/chromecast/common/cast_content_client.cc
index 7fa579b..951155e 100644
--- a/chromecast/common/cast_content_client.cc
+++ b/chromecast/common/cast_content_client.cc
@@ -31,9 +31,9 @@
 #include "url/url_util.h"
 
 #if BUILDFLAG(IS_ANDROID)
+#include <optional>
 #include "chromecast/common/media/cast_media_drm_bridge_client.h"
 #include "components/cdm/common/android_cdm_registration.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #endif
 
 #if !BUILDFLAG(IS_FUCHSIA)
@@ -226,11 +226,11 @@
     cdms->push_back(
         content::CdmInfo(kChromecastPlayreadyKeySystem,
                          content::CdmInfo::Robustness::kSoftwareSecure,
-                         absl::nullopt, kPlayReadyCdmType));
+                         std::nullopt, kPlayReadyCdmType));
     cdms->push_back(
         content::CdmInfo(kChromecastPlayreadyKeySystem,
                          content::CdmInfo::Robustness::kHardwareSecure,
-                         absl::nullopt, kPlayReadyCdmType));
+                         std::nullopt, kPlayReadyCdmType));
 #endif  // BUILDFLAG(ENABLE_PLAYREADY)
 #endif  // BUILDFLAG(BUNDLE_WIDEVINE_CDM) && BUILDFLAG(IS_LINUX)
   }
diff --git a/chromecast/common/cast_resource_delegate.cc b/chromecast/common/cast_resource_delegate.cc
index e065a14..65a2cf0 100644
--- a/chromecast/common/cast_resource_delegate.cc
+++ b/chromecast/common/cast_resource_delegate.cc
@@ -68,9 +68,9 @@
   return NULL;
 }
 
-absl::optional<std::string> CastResourceDelegate::LoadDataResourceString(
+std::optional<std::string> CastResourceDelegate::LoadDataResourceString(
     int resource_id) {
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 bool CastResourceDelegate::GetRawDataResource(
diff --git a/chromecast/common/cast_resource_delegate.h b/chromecast/common/cast_resource_delegate.h
index 78e35b4..912a365 100644
--- a/chromecast/common/cast_resource_delegate.h
+++ b/chromecast/common/cast_resource_delegate.h
@@ -48,7 +48,7 @@
   base::RefCountedStaticMemory* LoadDataResourceBytes(
       int resource_id,
       ui::ResourceScaleFactor scale_factor) override;
-  absl::optional<std::string> LoadDataResourceString(int resource_id) override;
+  std::optional<std::string> LoadDataResourceString(int resource_id) override;
   bool GetRawDataResource(int resource_id,
                           ui::ResourceScaleFactor scale_factor,
                           base::StringPiece* value) const override;
diff --git a/chromecast/crash/linux/crash_testing_utils.cc b/chromecast/crash/linux/crash_testing_utils.cc
index 5f8f014..01a95ad0 100644
--- a/chromecast/crash/linux/crash_testing_utils.cc
+++ b/chromecast/crash/linux/crash_testing_utils.cc
@@ -31,10 +31,10 @@
 const char kRatelimitPeriodStartKey[] = "period_start";
 const char kRatelimitPeriodDumpsKey[] = "period_dumps";
 
-absl::optional<base::Value::List> ParseLockFile(const std::string& path) {
+std::optional<base::Value::List> ParseLockFile(const std::string& path) {
   std::string lockfile_string;
   RCHECK(base::ReadFileToString(base::FilePath(path), &lockfile_string),
-         absl::nullopt, "Failed to read file");
+         std::nullopt, "Failed to read file");
 
   std::vector<std::string> lines = base::SplitString(
       lockfile_string, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
@@ -45,10 +45,10 @@
   for (const std::string& line : lines) {
     if (line.size() == 0)
       continue;
-    absl::optional<base::Value> dump_info = base::JSONReader::Read(line);
-    RCHECK(dump_info.has_value(), absl::nullopt, "Invalid DumpInfo");
+    std::optional<base::Value> dump_info = base::JSONReader::Read(line);
+    RCHECK(dump_info.has_value(), std::nullopt, "Invalid DumpInfo");
     DumpInfo info(&dump_info.value());
-    RCHECK(info.valid(), absl::nullopt, "Invalid DumpInfo");
+    RCHECK(info.valid(), std::nullopt, "Invalid DumpInfo");
     dumps.Append(std::move(dump_info.value()));
   }
 
@@ -92,7 +92,7 @@
 }  // namespace
 
 std::unique_ptr<DumpInfo> CreateDumpInfo(const std::string& json_string) {
-  absl::optional<base::Value> value = base::JSONReader::Read(json_string);
+  std::optional<base::Value> value = base::JSONReader::Read(json_string);
   return value.has_value() ? std::make_unique<DumpInfo>(&value.value())
                            : std::make_unique<DumpInfo>(nullptr);
 }
@@ -100,7 +100,7 @@
 bool FetchDumps(const std::string& lockfile_path,
                 std::vector<std::unique_ptr<DumpInfo>>* dumps) {
   DCHECK(dumps);
-  absl::optional<base::Value::List> dump_list = ParseLockFile(lockfile_path);
+  std::optional<base::Value::List> dump_list = ParseLockFile(lockfile_path);
   RCHECK(dump_list, false, "Failed to parse lockfile");
 
   dumps->clear();
@@ -137,7 +137,7 @@
 bool AppendLockFile(const std::string& lockfile_path,
                     const std::string& metadata_path,
                     const DumpInfo& dump) {
-  absl::optional<base::Value::List> contents = ParseLockFile(lockfile_path);
+  std::optional<base::Value::List> contents = ParseLockFile(lockfile_path);
   if (!contents) {
     CreateFiles(lockfile_path, metadata_path);
     if (!(contents = ParseLockFile(lockfile_path))) {
diff --git a/chromecast/crash/linux/synchronized_minidump_manager.cc b/chromecast/crash/linux/synchronized_minidump_manager.cc
index 5698e03..9ceaefc0 100644
--- a/chromecast/crash/linux/synchronized_minidump_manager.cc
+++ b/chromecast/crash/linux/synchronized_minidump_manager.cc
@@ -15,6 +15,7 @@
 #include <string>
 #include <utility>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/files/dir_reader_posix.h"
 #include "base/files/file_util.h"
@@ -27,7 +28,6 @@
 #include "base/strings/string_split.h"
 #include "chromecast/base/path_utils.h"
 #include "chromecast/crash/linux/dump_info.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // if |cond| is false, returns |retval|.
 #define RCHECK(cond, retval) \
@@ -66,7 +66,7 @@
 // Gets the ratelimit parameter dictionary given a deserialized |metadata|.
 // Returns nullptr if invalid.
 base::Value::Dict* GetRatelimitParams(
-    absl::optional<base::Value::Dict>& metadata) {
+    std::optional<base::Value::Dict>& metadata) {
   if (!metadata)
     return nullptr;
   return metadata->FindDict(kLockfileRatelimitKey);
@@ -74,12 +74,11 @@
 
 // Returns the time of the current ratelimit period's start in |metadata|.
 // Returns base::Time() if an error occurs.
-base::Time GetRatelimitPeriodStart(
-    absl::optional<base::Value::Dict>& metadata) {
+base::Time GetRatelimitPeriodStart(std::optional<base::Value::Dict>& metadata) {
   base::Value::Dict* ratelimit_params = GetRatelimitParams(metadata);
   RCHECK(ratelimit_params, base::Time());
 
-  absl::optional<double> seconds =
+  std::optional<double> seconds =
       ratelimit_params->FindDouble(kLockfileRatelimitPeriodStartKey);
   RCHECK(seconds, base::Time());
 
@@ -91,7 +90,7 @@
 
 // Sets the time of the current ratelimit period's start in |metadata| to
 // |period_start|. Returns true on success, false on error.
-bool SetRatelimitPeriodStart(absl::optional<base::Value::Dict>& metadata,
+bool SetRatelimitPeriodStart(std::optional<base::Value::Dict>& metadata,
                              base::Time period_start) {
   DCHECK(!period_start.is_null());
 
@@ -105,18 +104,18 @@
 
 // Gets the number of dumps added to |metadata| in the current ratelimit
 // period. Returns < 0 on error.
-int GetRatelimitPeriodDumps(absl::optional<base::Value::Dict>& metadata) {
+int GetRatelimitPeriodDumps(std::optional<base::Value::Dict>& metadata) {
   base::Value::Dict* ratelimit_params = GetRatelimitParams(metadata);
   if (!ratelimit_params)
     return -1;
-  absl::optional<int> period_dumps =
+  std::optional<int> period_dumps =
       ratelimit_params->FindInt(kLockfileRatelimitPeriodDumpsKey);
   return period_dumps.value_or(-1);
 }
 
 // Sets the current ratelimit period's number of dumps in |metadata| to
 // |period_dumps|. Returns true on success, false on error.
-bool SetRatelimitPeriodDumps(absl::optional<base::Value::Dict>& metadata,
+bool SetRatelimitPeriodDumps(std::optional<base::Value::Dict>& metadata,
                              int period_dumps) {
   DCHECK_GE(period_dumps, 0);
 
@@ -129,7 +128,7 @@
 }
 
 // Returns true if |metadata| contains valid metadata, false otherwise.
-bool ValidateMetadata(absl::optional<base::Value::Dict>& metadata) {
+bool ValidateMetadata(std::optional<base::Value::Dict>& metadata) {
   RCHECK(metadata, false);
 
   // Validate ratelimit params
@@ -296,7 +295,7 @@
   for (const std::string& line : lines) {
     if (line.size() == 0)
       continue;
-    absl::optional<base::Value> dump_info = base::JSONReader::Read(line);
+    std::optional<base::Value> dump_info = base::JSONReader::Read(line);
     RCHECK(dump_info.has_value(), false);
     DumpInfo info(&dump_info.value());
     RCHECK(info.valid(), false);
@@ -312,7 +311,7 @@
       << "JSON error " << error_code << ":" << error_msg;
   RCHECK(metadata_ptr, false);
   RCHECK(metadata_ptr->is_dict(), false);
-  absl::optional<base::Value::Dict> metadata =
+  std::optional<base::Value::Dict> metadata =
       std::move(*metadata_ptr).TakeDict();
   RCHECK(ValidateMetadata(metadata), false);
 
diff --git a/chromecast/crash/linux/synchronized_minidump_manager.h b/chromecast/crash/linux/synchronized_minidump_manager.h
index ab0db4d..18d414a 100644
--- a/chromecast/crash/linux/synchronized_minidump_manager.h
+++ b/chromecast/crash/linux/synchronized_minidump_manager.h
@@ -7,10 +7,10 @@
 
 #include <vector>
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/values.h"
 #include "chromecast/crash/linux/dump_info.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 
@@ -146,8 +146,8 @@
   const base::FilePath lockfile_path_;
   const base::FilePath metadata_path_;
   int lockfile_fd_;
-  absl::optional<base::Value::Dict> metadata_;
-  absl::optional<base::Value::List> dumps_;
+  std::optional<base::Value::Dict> metadata_;
+  std::optional<base::Value::List> dumps_;
 };
 
 }  // namespace chromecast
diff --git a/chromecast/device/bluetooth/le/le_scan_manager.h b/chromecast/device/bluetooth/le/le_scan_manager.h
index 97d7a92c..5d627ba8 100644
--- a/chromecast/device/bluetooth/le/le_scan_manager.h
+++ b/chromecast/device/bluetooth/le/le_scan_manager.h
@@ -9,11 +9,11 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/functional/callback.h"
 #include "base/memory/scoped_refptr.h"
 #include "chromecast/device/bluetooth/le/le_scan_result.h"
 #include "chromecast/device/bluetooth/le/scan_filter.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class SingleThreadTaskRunner;
@@ -82,7 +82,7 @@
       base::OnceCallback<void(std::vector<LeScanResult>)>;
   virtual void GetScanResults(
       GetScanResultsCallback cb,
-      absl::optional<ScanFilter> scan_filter = absl::nullopt) = 0;
+      std::optional<ScanFilter> scan_filter = std::nullopt) = 0;
 
   virtual void ClearScanResults() = 0;
 
diff --git a/chromecast/device/bluetooth/le/le_scan_manager_impl.cc b/chromecast/device/bluetooth/le/le_scan_manager_impl.cc
index d1b64ff..9d170a95 100644
--- a/chromecast/device/bluetooth/le/le_scan_manager_impl.cc
+++ b/chromecast/device/bluetooth/le/le_scan_manager_impl.cc
@@ -118,7 +118,7 @@
 }
 
 void LeScanManagerImpl::GetScanResults(GetScanResultsCallback cb,
-                                       absl::optional<ScanFilter> scan_filter) {
+                                       std::optional<ScanFilter> scan_filter) {
   MAKE_SURE_IO_THREAD(GetScanResults, BindToCurrentSequence(std::move(cb)),
                       std::move(scan_filter));
   std::move(cb).Run(GetScanResultsInternal(std::move(scan_filter)));
@@ -225,7 +225,7 @@
 
 // Returns a list of all scan results. The results are sorted by RSSI.
 std::vector<LeScanResult> LeScanManagerImpl::GetScanResultsInternal(
-    absl::optional<ScanFilter> scan_filter) {
+    std::optional<ScanFilter> scan_filter) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   std::vector<LeScanResult> results;
   for (const auto& pair : addr_to_scan_results_) {
diff --git a/chromecast/device/bluetooth/le/le_scan_manager_impl.h b/chromecast/device/bluetooth/le/le_scan_manager_impl.h
index f4b5096e..4df4b822 100644
--- a/chromecast/device/bluetooth/le/le_scan_manager_impl.h
+++ b/chromecast/device/bluetooth/le/le_scan_manager_impl.h
@@ -42,7 +42,7 @@
   void RequestScan(RequestScanCallback cb) override;
   void GetScanResults(
       GetScanResultsCallback cb,
-      absl::optional<ScanFilter> service_uuid = absl::nullopt) override;
+      std::optional<ScanFilter> service_uuid = std::nullopt) override;
   void ClearScanResults() override;
   void PauseScan() override;
   void ResumeScan() override;
@@ -60,7 +60,7 @@
   // Returns a list of all BLE scan results. The results are sorted by RSSI.
   // Must be called on |io_task_runner|.
   std::vector<LeScanResult> GetScanResultsInternal(
-      absl::optional<ScanFilter> service_uuid);
+      std::optional<ScanFilter> service_uuid);
 
   void NotifyScanHandleDestroyed(int32_t id);
 
diff --git a/chromecast/device/bluetooth/le/le_scan_result.cc b/chromecast/device/bluetooth/le/le_scan_result.cc
index 539d903..511162f 100644
--- a/chromecast/device/bluetooth/le/le_scan_result.cc
+++ b/chromecast/device/bluetooth/le/le_scan_result.cc
@@ -15,19 +15,19 @@
 namespace {
 
 template <typename T, bluetooth_v2_shlib::Uuid (*converter)(T)>
-absl::optional<LeScanResult::UuidList> GetUuidsFromShort(
+std::optional<LeScanResult::UuidList> GetUuidsFromShort(
     const std::map<uint8_t, std::vector<std::vector<uint8_t>>>& type_to_data,
     uint8_t type) {
   auto it = type_to_data.find(type);
   if (it == type_to_data.end()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   LeScanResult::UuidList ret;
   for (const auto& field : it->second) {
     if (field.size() % sizeof(T)) {
       LOG(ERROR) << "Invalid length, expected multiple of " << sizeof(T);
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     for (size_t i = 0; i < field.size(); i += sizeof(T)) {
@@ -45,12 +45,12 @@
   return ret;
 }
 
-absl::optional<LeScanResult::UuidList> GetUuidsAsUuid(
+std::optional<LeScanResult::UuidList> GetUuidsAsUuid(
     const std::map<uint8_t, std::vector<std::vector<uint8_t>>>& type_to_data,
     uint8_t type) {
   auto it = type_to_data.find(type);
   if (it == type_to_data.end()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   LeScanResult::UuidList ret;
@@ -58,7 +58,7 @@
     if (field.size() % sizeof(bluetooth_v2_shlib::Uuid)) {
       LOG(ERROR) << "Invalid length, expected multiple of "
                  << sizeof(bluetooth_v2_shlib::Uuid);
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     for (size_t i = 0; i < field.size();
@@ -117,7 +117,7 @@
   return true;
 }
 
-absl::optional<std::string> LeScanResult::Name() const {
+std::optional<std::string> LeScanResult::Name() const {
   auto it = type_to_data.find(kGapCompleteName);
   if (it != type_to_data.end()) {
     DCHECK_GE(it->second.size(), 1u);
@@ -132,28 +132,28 @@
                        it->second[0].size());
   }
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<uint8_t> LeScanResult::Flags() const {
+std::optional<uint8_t> LeScanResult::Flags() const {
   auto it = type_to_data.find(kGapFlags);
   if (it == type_to_data.end()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   DCHECK_GE(it->second.size(), 1u);
   if (it->second[0].size() != 1) {
     LOG(ERROR) << "Invalid length for flags";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return it->second[0][0];
 }
 
-absl::optional<LeScanResult::UuidList> LeScanResult::AllServiceUuids() const {
+std::optional<LeScanResult::UuidList> LeScanResult::AllServiceUuids() const {
   bool any_exist = false;
   UuidList ret;
-  auto insert_if_exists = [&ret, &any_exist](absl::optional<UuidList> list) {
+  auto insert_if_exists = [&ret, &any_exist](std::optional<UuidList> list) {
     if (list) {
       any_exist = true;
       ret.insert(ret.end(), list->begin(), list->end());
@@ -168,42 +168,42 @@
   insert_if_exists(CompleteListOf128BitServiceUuids());
 
   if (!any_exist) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return ret;
 }
 
-absl::optional<LeScanResult::UuidList>
+std::optional<LeScanResult::UuidList>
 LeScanResult::IncompleteListOf16BitServiceUuids() const {
   return GetUuidsFromShort<uint16_t, util::UuidFromInt16>(
       type_to_data, kGapIncomplete16BitServiceUuids);
 }
 
-absl::optional<LeScanResult::UuidList>
+std::optional<LeScanResult::UuidList>
 LeScanResult::CompleteListOf16BitServiceUuids() const {
   return GetUuidsFromShort<uint16_t, util::UuidFromInt16>(
       type_to_data, kGapComplete16BitServiceUuids);
 }
 
-absl::optional<LeScanResult::UuidList>
+std::optional<LeScanResult::UuidList>
 LeScanResult::IncompleteListOf32BitServiceUuids() const {
   return GetUuidsFromShort<uint32_t, util::UuidFromInt32>(
       type_to_data, kGapIncomplete32BitServiceUuids);
 }
 
-absl::optional<LeScanResult::UuidList>
+std::optional<LeScanResult::UuidList>
 LeScanResult::CompleteListOf32BitServiceUuids() const {
   return GetUuidsFromShort<uint32_t, util::UuidFromInt32>(
       type_to_data, kGapComplete32BitServiceUuids);
 }
 
-absl::optional<LeScanResult::UuidList>
+std::optional<LeScanResult::UuidList>
 LeScanResult::IncompleteListOf128BitServiceUuids() const {
   return GetUuidsAsUuid(type_to_data, kGapIncomplete128BitServiceUuids);
 }
 
-absl::optional<LeScanResult::UuidList>
+std::optional<LeScanResult::UuidList>
 LeScanResult::CompleteListOf128BitServiceUuids() const {
   return GetUuidsAsUuid(type_to_data, kGapComplete128BitServiceUuids);
 }
diff --git a/chromecast/device/bluetooth/le/le_scan_result.h b/chromecast/device/bluetooth/le/le_scan_result.h
index fc72f835..476be5d8 100644
--- a/chromecast/device/bluetooth/le/le_scan_result.h
+++ b/chromecast/device/bluetooth/le/le_scan_result.h
@@ -9,9 +9,9 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "chromecast/public/bluetooth/bluetooth_types.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 namespace bluetooth {
@@ -43,18 +43,18 @@
 
   bool SetAdvData(base::span<const uint8_t> adv_data);
 
-  absl::optional<std::string> Name() const;
+  std::optional<std::string> Name() const;
 
-  absl::optional<uint8_t> Flags() const;
+  std::optional<uint8_t> Flags() const;
 
   using UuidList = std::vector<bluetooth_v2_shlib::Uuid>;
-  absl::optional<UuidList> AllServiceUuids() const;
-  absl::optional<UuidList> IncompleteListOf16BitServiceUuids() const;
-  absl::optional<UuidList> CompleteListOf16BitServiceUuids() const;
-  absl::optional<UuidList> IncompleteListOf32BitServiceUuids() const;
-  absl::optional<UuidList> CompleteListOf32BitServiceUuids() const;
-  absl::optional<UuidList> IncompleteListOf128BitServiceUuids() const;
-  absl::optional<UuidList> CompleteListOf128BitServiceUuids() const;
+  std::optional<UuidList> AllServiceUuids() const;
+  std::optional<UuidList> IncompleteListOf16BitServiceUuids() const;
+  std::optional<UuidList> CompleteListOf16BitServiceUuids() const;
+  std::optional<UuidList> IncompleteListOf32BitServiceUuids() const;
+  std::optional<UuidList> CompleteListOf32BitServiceUuids() const;
+  std::optional<UuidList> IncompleteListOf128BitServiceUuids() const;
+  std::optional<UuidList> CompleteListOf128BitServiceUuids() const;
 
   using ServiceDataMap =
       std::map<bluetooth_v2_shlib::Uuid, std::vector<uint8_t>>;
diff --git a/chromecast/device/bluetooth/le/le_scan_result_test.cc b/chromecast/device/bluetooth/le/le_scan_result_test.cc
index f86d210..0c534e31 100644
--- a/chromecast/device/bluetooth/le/le_scan_result_test.cc
+++ b/chromecast/device/bluetooth/le/le_scan_result_test.cc
@@ -62,7 +62,7 @@
       std::vector<uint8_t>(
           reinterpret_cast<const uint8_t*>(kName1),
           reinterpret_cast<const uint8_t*>(kName1) + strlen(kName1)));
-  absl::optional<std::string> name = scan_result.Name();
+  std::optional<std::string> name = scan_result.Name();
   ASSERT_TRUE(name);
   EXPECT_EQ(kName1, *name);
 
diff --git a/chromecast/device/bluetooth/le/mock_le_scan_manager.h b/chromecast/device/bluetooth/le/mock_le_scan_manager.h
index 066c3ab..6a0bd00 100644
--- a/chromecast/device/bluetooth/le/mock_le_scan_manager.h
+++ b/chromecast/device/bluetooth/le/mock_le_scan_manager.h
@@ -48,9 +48,9 @@
 
   MOCK_METHOD(std::vector<LeScanResult>,
               GetScanResults,
-              (absl::optional<ScanFilter> scan_filter));
+              (std::optional<ScanFilter> scan_filter));
   void GetScanResults(GetScanResultsCallback cb,
-                      absl::optional<ScanFilter> scan_filter) override {
+                      std::optional<ScanFilter> scan_filter) override {
     std::move(cb).Run(GetScanResults(std::move(scan_filter)));
   }
   MOCK_METHOD(void, ClearScanResults, (), (override));
diff --git a/chromecast/device/bluetooth/le/scan_filter.cc b/chromecast/device/bluetooth/le/scan_filter.cc
index 7a63311..6e70492 100644
--- a/chromecast/device/bluetooth/le/scan_filter.cc
+++ b/chromecast/device/bluetooth/le/scan_filter.cc
@@ -29,7 +29,7 @@
   }
 
   if (service_uuid) {
-    absl::optional<LeScanResult::UuidList> all_uuids =
+    std::optional<LeScanResult::UuidList> all_uuids =
         scan_result.AllServiceUuids();
     if (!all_uuids) {
       return false;
@@ -41,7 +41,7 @@
   }
 
   if (!name && regex_name) {
-    absl::optional<std::string> scan_name = scan_result.Name();
+    std::optional<std::string> scan_name = scan_result.Name();
     if (!scan_name || !RE2::PartialMatch(*scan_name, *regex_name)) {
       return false;
     }
diff --git a/chromecast/device/bluetooth/le/scan_filter.h b/chromecast/device/bluetooth/le/scan_filter.h
index b9b81272..9a872ae 100644
--- a/chromecast/device/bluetooth/le/scan_filter.h
+++ b/chromecast/device/bluetooth/le/scan_filter.h
@@ -7,9 +7,9 @@
 
 #include <string>
 
+#include <optional>
 #include "chromecast/device/bluetooth/le/le_scan_result.h"
 #include "chromecast/public/bluetooth/bluetooth_types.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 namespace bluetooth {
@@ -26,13 +26,13 @@
   bool Matches(const LeScanResult& scan_result) const;
 
   // Exact name.
-  absl::optional<std::string> name;
+  std::optional<std::string> name;
 
   // RE2 partial match on name. This is ignored if |name| is specified.
   // https://github.com/google/re2
-  absl::optional<std::string> regex_name;
+  std::optional<std::string> regex_name;
 
-  absl::optional<bluetooth_v2_shlib::Uuid> service_uuid;
+  std::optional<bluetooth_v2_shlib::Uuid> service_uuid;
 };
 
 }  // namespace bluetooth
diff --git a/chromecast/external_mojo/public/cpp/external_mojo_broker.cc b/chromecast/external_mojo/public/cpp/external_mojo_broker.cc
index edb1c20e..0aac0a5 100644
--- a/chromecast/external_mojo/public/cpp/external_mojo_broker.cc
+++ b/chromecast/external_mojo/public/cpp/external_mojo_broker.cc
@@ -15,6 +15,7 @@
 #include <sys/stat.h>
 #endif
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/location.h"
@@ -42,7 +43,6 @@
 #include "services/service_manager/public/cpp/service_receiver.h"
 #include "services/service_manager/public/mojom/connector.mojom.h"
 #include "services/service_manager/public/mojom/service.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(IS_ANDROID)
 #include "base/android/bundle_utils.h"
@@ -66,7 +66,7 @@
     const std::string& service_name,
     const std::string& interface_name,
     service_manager::mojom::ConnectResult result,
-    const absl::optional<service_manager::Identity>& identity) {
+    const std::optional<service_manager::Identity>& identity) {
   if (result != service_manager::mojom::ConnectResult::SUCCEEDED) {
     LOG(ERROR) << "Failed to bind " << service_name << ":" << interface_name
                << ", result = " << result;
@@ -147,7 +147,7 @@
       connector_->BindInterface(filter.service_name(), interface_name,
                                 std::move(interface_pipe));
       std::move(callback).Run(service_manager::mojom::ConnectResult::SUCCEEDED,
-                              absl::nullopt);
+                              std::nullopt);
     }
 
     void QueryService(const std::string& service_name,
@@ -159,7 +159,7 @@
     void WarmService(const ::service_manager::ServiceFilter& filter,
                      WarmServiceCallback callback) override {
       std::move(callback).Run(service_manager::mojom::ConnectResult::SUCCEEDED,
-                              absl::nullopt);
+                              std::nullopt);
     }
 
     void RegisterServiceInstance(
diff --git a/chromecast/graphics/cast_screen.h b/chromecast/graphics/cast_screen.h
index c044f5c4..672c3a2 100644
--- a/chromecast/graphics/cast_screen.h
+++ b/chromecast/graphics/cast_screen.h
@@ -5,8 +5,8 @@
 #ifndef CHROMECAST_GRAPHICS_CAST_SCREEN_H_
 #define CHROMECAST_GRAPHICS_CAST_SCREEN_H_
 
+#include <optional>
 #include "chromecast/public/graphics_types.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/display/display.h"
 #include "ui/display/screen_base.h"
 
@@ -54,7 +54,7 @@
   bool RestorePrimaryDisplaySettings();
 
  private:
-  absl::optional<display::Display> stashed_display_settings_;
+  std::optional<display::Display> stashed_display_settings_;
 };
 
 }  // namespace chromecast
diff --git a/chromecast/media/audio/audio_clock_simulator_impl.cc b/chromecast/media/audio/audio_clock_simulator_impl.cc
index fb4b0f3..7d4a45cc 100644
--- a/chromecast/media/audio/audio_clock_simulator_impl.cc
+++ b/chromecast/media/audio/audio_clock_simulator_impl.cc
@@ -8,13 +8,13 @@
 #include <cstdint>
 #include <memory>
 
+#include <optional>
 #include "base/check_op.h"
 #include "base/functional/bind.h"
 #include "chromecast/media/api/audio_clock_simulator.h"
 #include "chromecast/media/api/audio_provider.h"
 #include "media/base/audio_bus.h"
 #include "media/base/multi_channel_resampler.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 namespace media {
@@ -133,7 +133,7 @@
   int64_t request_timestamp_ = 0;
   double resampler_buffered_frames_ = 0.0;
   bool in_fill_ = false;
-  absl::optional<double> pending_rate_;
+  std::optional<double> pending_rate_;
 };
 
 }  // namespace
diff --git a/chromecast/media/audio/cast_audio_renderer.cc b/chromecast/media/audio/cast_audio_renderer.cc
index 5bf3b4a..3fec7e1 100644
--- a/chromecast/media/audio/cast_audio_renderer.cc
+++ b/chromecast/media/audio/cast_audio_renderer.cc
@@ -200,7 +200,7 @@
 }
 
 void CastAudioRenderer::SetLatencyHint(
-    absl::optional<base::TimeDelta> latency_hint) {
+    std::optional<base::TimeDelta> latency_hint) {
   NOTIMPLEMENTED();
 }
 
diff --git a/chromecast/media/audio/cast_audio_renderer.h b/chromecast/media/audio/cast_audio_renderer.h
index 80d00df..fe7f27d2 100644
--- a/chromecast/media/audio/cast_audio_renderer.h
+++ b/chromecast/media/audio/cast_audio_renderer.h
@@ -83,7 +83,7 @@
   void Flush(base::OnceClosure callback) override;
   void StartPlaying() override;
   void SetVolume(float volume) override;
-  void SetLatencyHint(absl::optional<base::TimeDelta> latency_hint) override;
+  void SetLatencyHint(std::optional<base::TimeDelta> latency_hint) override;
   void SetPreservesPitch(bool preserves_pitch) override;
   void SetWasPlayedWithUserActivation(
       bool was_played_with_user_activation) override;
diff --git a/chromecast/media/audio/net/audio_socket_service_tcp.cc b/chromecast/media/audio/net/audio_socket_service_tcp.cc
index e402251..8a43b2c 100644
--- a/chromecast/media/audio/net/audio_socket_service_tcp.cc
+++ b/chromecast/media/audio/net/audio_socket_service_tcp.cc
@@ -51,7 +51,7 @@
                                                           net::NetLogSource());
   int result = listen_socket_->Listen(
       net::IPEndPoint(net::IPAddress::IPv4Localhost(), port), kListenBacklog,
-      /*ipv6_only=*/absl::nullopt);
+      /*ipv6_only=*/std::nullopt);
 
   if (result != net::OK) {
     LOG(ERROR) << "Listen failed: " << net::ErrorToString(result);
diff --git a/chromecast/media/cma/backend/alsa/alsa_volume_control.cc b/chromecast/media/cma/backend/alsa/alsa_volume_control.cc
index 4b91fc61..cc79075 100644
--- a/chromecast/media/cma/backend/alsa/alsa_volume_control.cc
+++ b/chromecast/media/cma/backend/alsa/alsa_volume_control.cc
@@ -341,11 +341,11 @@
   return success;
 }
 
-absl::optional<bool> AlsaVolumeControl::IsElementAllMuted(
+std::optional<bool> AlsaVolumeControl::IsElementAllMuted(
     ScopedAlsaMixer* mixer) {
   if (!mixer || !mixer->element ||
       !alsa_->MixerSelemHasPlaybackSwitch(mixer->element)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   for (int32_t channel = 0; channel <= SND_MIXER_SCHN_LAST; ++channel) {
     int channel_unmuted;
@@ -354,7 +354,7 @@
         &channel_unmuted);
     if (err != 0) {
       LOG(ERROR) << "MixerSelemGetPlaybackSwitch: " << alsa_->StrError(err);
-      return absl::nullopt;
+      return std::nullopt;
     }
     if (channel_unmuted) {
       return false;
diff --git a/chromecast/media/cma/backend/alsa/alsa_volume_control.h b/chromecast/media/cma/backend/alsa/alsa_volume_control.h
index 713eb685..3c9b48c 100644
--- a/chromecast/media/cma/backend/alsa/alsa_volume_control.h
+++ b/chromecast/media/cma/backend/alsa/alsa_volume_control.h
@@ -9,10 +9,10 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/timer/timer.h"
 #include "chromecast/media/cma/backend/system_volume_control.h"
 #include "media/audio/alsa/alsa_wrapper.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 namespace media {
@@ -55,9 +55,9 @@
                                         unsigned int mask);
 
   bool SetElementMuted(ScopedAlsaMixer* mixer, bool muted);
-  // Returns true if all channels are muted, returns absl::nullopt if element
+  // Returns true if all channels are muted, returns std::nullopt if element
   // state is not accessible.
-  absl::optional<bool> IsElementAllMuted(ScopedAlsaMixer* mixer);
+  std::optional<bool> IsElementAllMuted(ScopedAlsaMixer* mixer);
 
   void OnVolumeOrMuteChanged();
 
diff --git a/chromecast/media/cma/backend/cast_audio_json.cc b/chromecast/media/cma/backend/cast_audio_json.cc
index 45761538..bc65ccf 100644
--- a/chromecast/media/cma/backend/cast_audio_json.cc
+++ b/chromecast/media/cma/backend/cast_audio_json.cc
@@ -29,7 +29,7 @@
 
   std::string contents;
   base::ReadFileToString(path, &contents);
-  absl::optional<base::Value> value = base::JSONReader::Read(contents);
+  std::optional<base::Value> value = base::JSONReader::Read(contents);
   if (value && value->is_dict()) {
     callback.Run(std::move(*value).TakeDict());
     return;
@@ -76,13 +76,13 @@
 
 CastAudioJsonProviderImpl::~CastAudioJsonProviderImpl() = default;
 
-absl::optional<base::Value::Dict>
+std::optional<base::Value::Dict>
 CastAudioJsonProviderImpl::GetCastAudioConfig() {
   std::string contents;
   base::ReadFileToString(CastAudioJson::GetFilePath(), &contents);
-  absl::optional<base::Value> value = base::JSONReader::Read(contents);
+  std::optional<base::Value> value = base::JSONReader::Read(contents);
   if (!value || value->is_dict()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return std::move(*value).TakeDict();
diff --git a/chromecast/media/cma/backend/cast_audio_json.h b/chromecast/media/cma/backend/cast_audio_json.h
index eeaa391..927c62c 100644
--- a/chromecast/media/cma/backend/cast_audio_json.h
+++ b/chromecast/media/cma/backend/cast_audio_json.h
@@ -5,13 +5,13 @@
 #ifndef CHROMECAST_MEDIA_CMA_BACKEND_CAST_AUDIO_JSON_H_
 #define CHROMECAST_MEDIA_CMA_BACKEND_CAST_AUDIO_JSON_H_
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/files/file_path_watcher.h"
 #include "base/functional/callback.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/threading/sequence_bound.h"
 #include "base/values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 namespace media {
@@ -30,7 +30,7 @@
 class CastAudioJsonProvider {
  public:
   using TuningChangedCallback =
-      base::RepeatingCallback<void(absl::optional<base::Value::Dict> contents)>;
+      base::RepeatingCallback<void(std::optional<base::Value::Dict> contents)>;
 
   virtual ~CastAudioJsonProvider() = default;
 
@@ -40,7 +40,7 @@
   // at CastAudioJson::GetReadOnlyFilePath() will be returned.
   // This function will run on the thread on which it is called, and may
   // perform blocking I/O.
-  virtual absl::optional<base::Value::Dict> GetCastAudioConfig() = 0;
+  virtual std::optional<base::Value::Dict> GetCastAudioConfig() = 0;
 
   // |callback| will be called when a new cast_audio config is available.
   // |callback| will always be called from the same thread, but not necessarily
@@ -71,7 +71,7 @@
   };
 
   // CastAudioJsonProvider implementation:
-  absl::optional<base::Value::Dict> GetCastAudioConfig() override;
+  std::optional<base::Value::Dict> GetCastAudioConfig() override;
   void SetTuningChangedCallback(TuningChangedCallback callback) override;
 
   base::SequenceBound<FileWatcher> cast_audio_watcher_;
diff --git a/chromecast/media/cma/backend/cplay/cplay.cc b/chromecast/media/cma/backend/cplay/cplay.cc
index 60173fb..138b106 100644
--- a/chromecast/media/cma/backend/cplay/cplay.cc
+++ b/chromecast/media/cma/backend/cplay/cplay.cc
@@ -339,11 +339,11 @@
   // Set volume.
   std::string contents;
   base::ReadFileToString(params.cast_audio_json_path, &contents);
-  absl::optional<base::Value> parsed_json = base::JSONReader::Read(contents);
+  std::optional<base::Value> parsed_json = base::JSONReader::Read(contents);
   if (parsed_json && parsed_json->is_dict()) {
     GetVolumeMap().LoadVolumeMap(std::move(*parsed_json).TakeDict());
   } else {
-    GetVolumeMap().LoadVolumeMap(absl::nullopt);
+    GetVolumeMap().LoadVolumeMap(std::nullopt);
   }
   float volume_dbfs = GetVolumeMap().VolumeToDbFS(params.cast_volume);
   float volume_multiplier = std::pow(10.0, volume_dbfs / 20.0);
diff --git a/chromecast/media/cma/backend/mixer/mixer_input_connection.cc b/chromecast/media/cma/backend/mixer/mixer_input_connection.cc
index 341b19c..4651021 100644
--- a/chromecast/media/cma/backend/mixer/mixer_input_connection.cc
+++ b/chromecast/media/cma/backend/mixer/mixer_input_connection.cc
@@ -11,6 +11,7 @@
 #include <limits>
 #include <utility>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/functional/bind.h"
 #include "base/location.h"
@@ -35,7 +36,6 @@
 #include "media/base/audio_bus.h"
 #include "media/base/audio_timestamp_helper.h"
 #include "media/filters/audio_renderer_algorithm.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 namespace media {
@@ -327,7 +327,7 @@
   const int num_channels_;
   const int sample_rate_;
 
-  absl::optional<int> pending_silence_;
+  std::optional<int> pending_silence_;
   FaderProvider fader_provider_;
   AudioFader fader_;
   bool after_silence_ = true;
diff --git a/chromecast/media/cma/backend/mixer/mock_post_processor_factory.cc b/chromecast/media/cma/backend/mixer/mock_post_processor_factory.cc
index a843325..4f71990 100644
--- a/chromecast/media/cma/backend/mixer/mock_post_processor_factory.cc
+++ b/chromecast/media/cma/backend/mixer/mock_post_processor_factory.cc
@@ -40,15 +40,15 @@
       const base::Value::Dict* processor_config_dict =
           elem.GetDict().FindDict("config");
       CHECK(processor_config_dict);
-      absl::optional<int> delay = processor_config_dict->FindInt("delay");
+      std::optional<int> delay = processor_config_dict->FindInt("delay");
       CHECK(delay.has_value());
       rendering_delay_frames_ += *delay;
-      absl::optional<bool> ringing = processor_config_dict->FindBool("ringing");
+      std::optional<bool> ringing = processor_config_dict->FindBool("ringing");
       if (ringing.has_value()) {
         ringing_ = *ringing;
       }
 
-      absl::optional<int> output_ch =
+      std::optional<int> output_ch =
           processor_config_dict->FindInt("output_channels");
       if (output_ch.has_value()) {
         num_output_channels_ = *output_ch;
diff --git a/chromecast/media/cma/backend/mixer/post_processing_pipeline_parser.cc b/chromecast/media/cma/backend/mixer/post_processing_pipeline_parser.cc
index 96c990a7..24cd5f0b 100644
--- a/chromecast/media/cma/backend/mixer/post_processing_pipeline_parser.cc
+++ b/chromecast/media/cma/backend/mixer/post_processing_pipeline_parser.cc
@@ -67,7 +67,7 @@
     base::Value prerender_pipeline_in,
     base::Value pipeline_in,
     const base::Value* stream_types_in,
-    const absl::optional<int> num_input_channels_in,
+    const std::optional<int> num_input_channels_in,
     const base::Value* volume_limits_in)
     : prerender_pipeline(std::move(prerender_pipeline_in)),
       pipeline(std::move(pipeline_in)),
@@ -179,7 +179,7 @@
                  << "\" in " << file_path_ << ". Using passthrough.";
     return StreamPipelineDescriptor(base::Value(base::Value::Type::LIST),
                                     base::Value(base::Value::Type::LIST),
-                                    nullptr, absl::nullopt, nullptr);
+                                    nullptr, std::nullopt, nullptr);
   }
 
   const base::Value::Dict& stream_dict = stream_value->GetDict();
diff --git a/chromecast/media/cma/backend/mixer/post_processing_pipeline_parser.h b/chromecast/media/cma/backend/mixer/post_processing_pipeline_parser.h
index 5a5fced..546e45cd 100644
--- a/chromecast/media/cma/backend/mixer/post_processing_pipeline_parser.h
+++ b/chromecast/media/cma/backend/mixer/post_processing_pipeline_parser.h
@@ -9,9 +9,9 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 namespace media {
@@ -27,13 +27,13 @@
   base::Value prerender_pipeline;
   base::Value pipeline;
   const base::Value* stream_types;
-  absl::optional<int> num_input_channels;
+  std::optional<int> num_input_channels;
   const base::Value* volume_limits;
 
   StreamPipelineDescriptor(base::Value prerender_pipeline_in,
                            base::Value pipeline_in,
                            const base::Value* stream_types_in,
-                           const absl::optional<int> num_input_channels_in,
+                           const std::optional<int> num_input_channels_in,
                            const base::Value* volume_limits_in);
   ~StreamPipelineDescriptor();
   StreamPipelineDescriptor(StreamPipelineDescriptor&& other);
diff --git a/chromecast/media/cma/backend/proxy/audio_channel_push_buffer_handler.h b/chromecast/media/cma/backend/proxy/audio_channel_push_buffer_handler.h
index 584b806..e9fe91bc 100644
--- a/chromecast/media/cma/backend/proxy/audio_channel_push_buffer_handler.h
+++ b/chromecast/media/cma/backend/proxy/audio_channel_push_buffer_handler.h
@@ -5,8 +5,8 @@
 #ifndef CHROMECAST_MEDIA_CMA_BACKEND_PROXY_AUDIO_CHANNEL_PUSH_BUFFER_HANDLER_H_
 #define CHROMECAST_MEDIA_CMA_BACKEND_PROXY_AUDIO_CHANNEL_PUSH_BUFFER_HANDLER_H_
 
+#include <optional>
 #include "chromecast/media/api/cma_backend.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cast_core/public/src/proto/runtime/cast_audio_channel_service.pb.h"
 
 namespace chromecast {
@@ -62,7 +62,7 @@
   // true.
   //
   // May only be called by the CONSUMER.
-  virtual absl::optional<PushBufferRequest> GetBufferedData() = 0;
+  virtual std::optional<PushBufferRequest> GetBufferedData() = 0;
 };
 
 }  // namespace media
diff --git a/chromecast/media/cma/backend/proxy/buffer_id_manager.h b/chromecast/media/cma/backend/proxy/buffer_id_manager.h
index 541ea1c..2c35979 100644
--- a/chromecast/media/cma/backend/proxy/buffer_id_manager.h
+++ b/chromecast/media/cma/backend/proxy/buffer_id_manager.h
@@ -9,11 +9,11 @@
 #include <queue>
 #include <utility>
 
+#include <optional>
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
 #include "chromecast/media/api/cma_backend.h"
 #include "chromecast/media/cma/backend/proxy/audio_decoder_pipeline_node.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 namespace media {
@@ -155,7 +155,7 @@
   int64_t pending_playback_time_in_microseconds_ = 0;
 
   // Information about the most recently played buffer.
-  mutable absl::optional<BufferPlayoutInfo> most_recently_played_buffer_;
+  mutable std::optional<BufferPlayoutInfo> most_recently_played_buffer_;
 
   BufferIdQueue buffer_id_queue_;
   std::queue<BufferInfo> buffer_infos_;
diff --git a/chromecast/media/cma/backend/proxy/cast_runtime_audio_channel_broker.h b/chromecast/media/cma/backend/proxy/cast_runtime_audio_channel_broker.h
index 6a13c981..aee01ae 100644
--- a/chromecast/media/cma/backend/proxy/cast_runtime_audio_channel_broker.h
+++ b/chromecast/media/cma/backend/proxy/cast_runtime_audio_channel_broker.h
@@ -7,8 +7,8 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/memory/weak_ptr.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cast_core/public/src/proto/runtime/cast_audio_channel_service.pb.h"
 #include "third_party/protobuf/src/google/protobuf/duration.pb.h"
 
@@ -71,7 +71,7 @@
 
     // Returns a PushBufferRequest to be sent across the |PushBuffer| RPC. May
     // only be called if |HasBufferedData()| is true.
-    virtual absl::optional<PushBufferRequest> GetBufferedData() = 0;
+    virtual std::optional<PushBufferRequest> GetBufferedData() = 0;
     virtual bool HasBufferedData() = 0;
 
     // Handlers for the responses of the messages defined in
@@ -103,7 +103,7 @@
 
     // Called when a |GetMediaTime| RPC call completes. If |status| is kOK, then
     // |time| is a valid non-empty MediaTime object. Else, |time| may be empty.
-    virtual void HandleGetMediaTimeResponse(absl::optional<MediaTime> time,
+    virtual void HandleGetMediaTimeResponse(std::optional<MediaTime> time,
                                             StatusCode status) = 0;
   };
 
diff --git a/chromecast/media/cma/backend/proxy/media_pipeline_buffer_extension.h b/chromecast/media/cma/backend/proxy/media_pipeline_buffer_extension.h
index 2eae453..a0b213c5 100644
--- a/chromecast/media/cma/backend/proxy/media_pipeline_buffer_extension.h
+++ b/chromecast/media/cma/backend/proxy/media_pipeline_buffer_extension.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <queue>
 
+#include <optional>
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
@@ -15,7 +16,6 @@
 #include "chromecast/media/api/cma_backend.h"
 #include "chromecast/media/cma/backend/proxy/audio_decoder_pipeline_node.h"
 #include "chromecast/public/media/cast_key_status.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 
@@ -61,8 +61,8 @@
     PendingCommand& operator=(const PendingCommand& other);
     PendingCommand& operator=(PendingCommand&& other);
 
-    absl::optional<scoped_refptr<DecoderBufferBase>> buffer;
-    absl::optional<AudioConfig> config;
+    std::optional<scoped_refptr<DecoderBufferBase>> buffer;
+    std::optional<AudioConfig> config;
   };
 
   // AudioDecoderPipelineNode overrides.
diff --git a/chromecast/media/cma/backend/proxy/proxy_call_translator.cc b/chromecast/media/cma/backend/proxy/proxy_call_translator.cc
index 3cf01702..257b8f25 100644
--- a/chromecast/media/cma/backend/proxy/proxy_call_translator.cc
+++ b/chromecast/media/cma/backend/proxy/proxy_call_translator.cc
@@ -288,7 +288,7 @@
       ToGrpcTypes(std::move(buffer), buffer_id));
 }
 
-absl::optional<ProxyCallTranslator::PushBufferRequest>
+std::optional<ProxyCallTranslator::PushBufferRequest>
 ProxyCallTranslator::GetBufferedData() {
   return push_buffer_handler_.GetBufferedData();
 }
@@ -339,7 +339,7 @@
 }
 
 void ProxyCallTranslator::HandleGetMediaTimeResponse(
-    absl::optional<MediaTime> time,
+    std::optional<MediaTime> time,
     CastRuntimeAudioChannelBroker::StatusCode status) {
   NOTREACHED();
 }
diff --git a/chromecast/media/cma/backend/proxy/proxy_call_translator.h b/chromecast/media/cma/backend/proxy/proxy_call_translator.h
index ca2c11d..f597d93 100644
--- a/chromecast/media/cma/backend/proxy/proxy_call_translator.h
+++ b/chromecast/media/cma/backend/proxy/proxy_call_translator.h
@@ -7,13 +7,13 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/memory/ref_counted.h"
 #include "chromecast/media/api/decoder_buffer_base.h"
 #include "chromecast/media/cma/backend/proxy/buffer_id_manager.h"
 #include "chromecast/media/cma/backend/proxy/cast_runtime_audio_channel_broker.h"
 #include "chromecast/media/cma/backend/proxy/cma_proxy_handler.h"
 #include "chromecast/media/cma/backend/proxy/push_buffer_pending_handler.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 
@@ -75,7 +75,7 @@
       std::unique_ptr<CastRuntimeAudioChannelBroker> decoder_channel);
 
   // CastRuntimeAudioChannelBroker::Handler overrides:
-  absl::optional<PushBufferRequest> GetBufferedData() override;
+  std::optional<PushBufferRequest> GetBufferedData() override;
   bool HasBufferedData() override;
   void HandleInitializeResponse(
       CastRuntimeAudioChannelBroker::StatusCode status) override;
@@ -90,7 +90,7 @@
       int64_t decoded_bytes,
       CastRuntimeAudioChannelBroker::StatusCode status) override;
   void HandleGetMediaTimeResponse(
-      absl::optional<MediaTime> time,
+      std::optional<MediaTime> time,
       CastRuntimeAudioChannelBroker::StatusCode status) override;
 
   // Helper to share error handling code.
diff --git a/chromecast/media/cma/backend/proxy/push_buffer_pending_handler.cc b/chromecast/media/cma/backend/proxy/push_buffer_pending_handler.cc
index 4f4201f..2cc00726 100644
--- a/chromecast/media/cma/backend/proxy/push_buffer_pending_handler.cc
+++ b/chromecast/media/cma/backend/proxy/push_buffer_pending_handler.cc
@@ -77,7 +77,7 @@
   return delegated_handler_->HasBufferedData();
 }
 
-absl::optional<AudioChannelPushBufferHandler::PushBufferRequest>
+std::optional<AudioChannelPushBufferHandler::PushBufferRequest>
 PushBufferPendingHandler::GetBufferedData() {
   // The pending data is only considered by the producer sequence, so this
   // consumer sequence call does not consider it.
diff --git a/chromecast/media/cma/backend/proxy/push_buffer_pending_handler.h b/chromecast/media/cma/backend/proxy/push_buffer_pending_handler.h
index f6792fb..58820f8 100644
--- a/chromecast/media/cma/backend/proxy/push_buffer_pending_handler.h
+++ b/chromecast/media/cma/backend/proxy/push_buffer_pending_handler.h
@@ -58,7 +58,7 @@
   CmaBackend::BufferStatus PushBuffer(
       const PushBufferRequest& request) override;
   bool HasBufferedData() const override;
-  absl::optional<PushBufferRequest> GetBufferedData() override;
+  std::optional<PushBufferRequest> GetBufferedData() override;
 
  private:
   friend class PushBufferPendingHandlerTest;
diff --git a/chromecast/media/cma/backend/proxy/push_buffer_pending_handler_unittest.cc b/chromecast/media/cma/backend/proxy/push_buffer_pending_handler_unittest.cc
index 911b5f4..000cc0d 100644
--- a/chromecast/media/cma/backend/proxy/push_buffer_pending_handler_unittest.cc
+++ b/chromecast/media/cma/backend/proxy/push_buffer_pending_handler_unittest.cc
@@ -71,7 +71,7 @@
 
   MOCK_METHOD1(PushBuffer, CmaBackend::BufferStatus(const PushBufferRequest&));
   MOCK_CONST_METHOD0(HasBufferedData, bool());
-  MOCK_METHOD0(GetBufferedData, absl::optional<PushBufferRequest>());
+  MOCK_METHOD0(GetBufferedData, std::optional<PushBufferRequest>());
 };
 
 }  // namespace
diff --git a/chromecast/media/cma/backend/proxy/push_buffer_queue.cc b/chromecast/media/cma/backend/proxy/push_buffer_queue.cc
index 04b2333..f824ada 100644
--- a/chromecast/media/cma/backend/proxy/push_buffer_queue.cc
+++ b/chromecast/media/cma/backend/proxy/push_buffer_queue.cc
@@ -32,9 +32,9 @@
 PushBufferQueue::PushBufferQueue()
     : producer_handler_(this),
       consumer_handler_(this),
-      consumer_stream_(absl::in_place, &consumer_handler_),
-      protobuf_consumer_stream_(absl::in_place, &consumer_stream_.value(), 1),
-      producer_stream_(absl::in_place, &producer_handler_) {
+      consumer_stream_(std::in_place, &consumer_handler_),
+      protobuf_consumer_stream_(std::in_place, &consumer_stream_.value(), 1),
+      producer_stream_(std::in_place, &producer_handler_) {
   DETACH_FROM_SEQUENCE(producer_sequence_checker_);
   DETACH_FROM_SEQUENCE(consumer_sequence_checker_);
 }
@@ -70,7 +70,7 @@
     // when the entire |buffer_| is full at time of writing.
     bytes_written_during_current_write_ = 0;
     producer_handler_.overflow();
-    producer_stream_ = absl::nullopt;
+    producer_stream_ = std::nullopt;
     producer_stream_.emplace(&producer_handler_);
   }
 
@@ -82,7 +82,7 @@
   return !is_in_invalid_state_ && GetAvailableyByteCount() != size_t{0};
 }
 
-absl::optional<PushBufferQueue::PushBufferRequest>
+std::optional<PushBufferQueue::PushBufferRequest>
 PushBufferQueue::GetBufferedData() {
   auto result = GetBufferedDataImpl();
   if (result.has_value()) {
@@ -92,7 +92,7 @@
   return result;
 }
 
-absl::optional<PushBufferQueue::PushBufferRequest>
+std::optional<PushBufferQueue::PushBufferRequest>
 PushBufferQueue::GetBufferedDataImpl() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(consumer_sequence_checker_);
   DCHECK(HasBufferedData());
@@ -124,12 +124,12 @@
 
     // If |!succeeded|, the streams have ended up in an unexpected state and
     // need to be recreated.
-    protobuf_consumer_stream_ = absl::nullopt;
-    consumer_stream_ = absl::nullopt;
+    protobuf_consumer_stream_ = std::nullopt;
+    consumer_stream_ = std::nullopt;
     consumer_stream_.emplace(&consumer_handler_);
     protobuf_consumer_stream_.emplace(&consumer_stream_.value(), 1);
 
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   consecuitive_read_failures_ = 0;
diff --git a/chromecast/media/cma/backend/proxy/push_buffer_queue.h b/chromecast/media/cma/backend/proxy/push_buffer_queue.h
index 6442e07..53ebb2f 100644
--- a/chromecast/media/cma/backend/proxy/push_buffer_queue.h
+++ b/chromecast/media/cma/backend/proxy/push_buffer_queue.h
@@ -9,11 +9,11 @@
 #include <istream>
 #include <ostream>
 
+#include <optional>
 #include "base/sequence_checker.h"
 #include "chromecast/media/api/cma_backend.h"
 #include "chromecast/media/api/decoder_buffer_base.h"
 #include "chromecast/media/cma/backend/proxy/audio_channel_push_buffer_handler.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cast_core/public/src/proto/runtime/cast_audio_channel_service.pb.h"
 #include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.h"
 
@@ -47,7 +47,7 @@
   CmaBackend::BufferStatus PushBuffer(
       const PushBufferRequest& request) override;
   bool HasBufferedData() const override;
-  absl::optional<PushBufferRequest> GetBufferedData() override;
+  std::optional<PushBufferRequest> GetBufferedData() override;
 
  private:
   // These classes exist for the following 2 reasons:
@@ -128,7 +128,7 @@
 
   // Helper methods to be used for test hooks.
   bool PushBufferImpl(const PushBufferRequest& request);
-  absl::optional<PushBufferRequest> GetBufferedDataImpl();
+  std::optional<PushBufferRequest> GetBufferedDataImpl();
 
   // Buffer where serialized PushBufferRequest data is stored.
   char buffer_[kBufferSizeBytes];
@@ -168,14 +168,14 @@
   // Input streams backed by this instance. They must be optional so that they
   // can be re-created following a failed read. These should only be used by the
   // CONSUMER.
-  absl::optional<std::istream> consumer_stream_;
-  absl::optional<google::protobuf::io::IstreamInputStream>
+  std::optional<std::istream> consumer_stream_;
+  std::optional<google::protobuf::io::IstreamInputStream>
       protobuf_consumer_stream_;
 
   // Output stream backed by this instance. This must be optional so it can be
   // re-created following a failed write. It should only be used by the
   // PRODUCER.
-  absl::optional<std::ostream> producer_stream_;
+  std::optional<std::ostream> producer_stream_;
 };
 
 }  // namespace media
diff --git a/chromecast/media/cma/backend/proxy/push_buffer_queue_unittest.cc b/chromecast/media/cma/backend/proxy/push_buffer_queue_unittest.cc
index 3ad7dc5..a41e7bfb 100644
--- a/chromecast/media/cma/backend/proxy/push_buffer_queue_unittest.cc
+++ b/chromecast/media/cma/backend/proxy/push_buffer_queue_unittest.cc
@@ -7,12 +7,12 @@
 #include <atomic>
 #include <sstream>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/location.h"
 #include "base/threading/thread.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cast_core/public/src/proto/runtime/cast_audio_channel_service.grpc.pb.h"
 
 namespace chromecast {
@@ -49,7 +49,7 @@
   void ReadData(const std::string& name,
                 const PushBufferQueue::PushBufferRequest& target_buffer) {
     ASSERT_TRUE(queue_.HasBufferedData()) << name;
-    absl::optional<PushBufferRequest> get = queue_.GetBufferedData();
+    std::optional<PushBufferRequest> get = queue_.GetBufferedData();
     ASSERT_TRUE(get.has_value()) << name;
     CheckEqual("first", get.value(), target_buffer);
   }
@@ -137,7 +137,7 @@
     return queue_.PushBufferImpl(request);
   }
 
-  absl::optional<PushBufferQueue::PushBufferRequest> StartGetBufferedData() {
+  std::optional<PushBufferQueue::PushBufferRequest> StartGetBufferedData() {
     return queue_.GetBufferedDataImpl();
   }
 
@@ -270,7 +270,7 @@
   UpdateBufferWriteStreamPositions();
 
   ASSERT_TRUE(queue_.HasBufferedData());
-  absl::optional<PushBufferRequest> pulled_buffer = queue_.GetBufferedData();
+  std::optional<PushBufferRequest> pulled_buffer = queue_.GetBufferedData();
   EXPECT_FALSE(pulled_buffer.has_value());
   EXPECT_TRUE(queue_.HasBufferedData());
 
diff --git a/chromecast/media/cma/backend/volume_control.cc b/chromecast/media/cma/backend/volume_control.cc
index 3fd2d01..17f899e6 100644
--- a/chromecast/media/cma/backend/volume_control.cc
+++ b/chromecast/media/cma/backend/volume_control.cc
@@ -203,7 +203,7 @@
 
     for (auto type : {AudioContentType::kMedia, AudioContentType::kAlarm,
                       AudioContentType::kCommunication}) {
-      absl::optional<double> dbfs =
+      std::optional<double> dbfs =
           stored_values_.FindDouble(ContentTypeToDbFSPath(type));
       CHECK(dbfs);
       volumes_[type] = VolumeControl::DbFSToVolume(*dbfs);
diff --git a/chromecast/media/cma/backend/volume_map.cc b/chromecast/media/cma/backend/volume_map.cc
index 200e69a..05fb504 100644
--- a/chromecast/media/cma/backend/volume_map.cc
+++ b/chromecast/media/cma/backend/volume_map.cc
@@ -49,7 +49,7 @@
 }
 
 void VolumeMap::LoadVolumeMap(
-    absl::optional<base::Value::Dict> cast_audio_config) {
+    std::optional<base::Value::Dict> cast_audio_config) {
   if (!cast_audio_config) {
     LOG(WARNING) << "No cast audio config found; using default volume map.";
     UseDefaultVolumeMap();
@@ -70,14 +70,14 @@
   for (const auto& value : *volume_map_list) {
     const base::Value::Dict& volume_map_entry = value.GetDict();
 
-    absl::optional<double> level = volume_map_entry.FindDouble(kKeyLevel);
+    std::optional<double> level = volume_map_entry.FindDouble(kKeyLevel);
     CHECK(level);
     CHECK_GE(*level, 0.0);
     CHECK_LE(*level, 1.0);
     CHECK_GT(*level, prev_level);
     prev_level = *level;
 
-    absl::optional<double> db = volume_map_entry.FindDouble(kKeyDb);
+    std::optional<double> db = volume_map_entry.FindDouble(kKeyDb);
     CHECK(db);
     CHECK_LE(*db, 0.0);
 
diff --git a/chromecast/media/cma/backend/volume_map.h b/chromecast/media/cma/backend/volume_map.h
index 4d3bdb9..d5e87b7c 100644
--- a/chromecast/media/cma/backend/volume_map.h
+++ b/chromecast/media/cma/backend/volume_map.h
@@ -36,7 +36,7 @@
 
   float DbFSToVolume(float db);
 
-  void LoadVolumeMap(absl::optional<base::Value::Dict> cast_audio_config);
+  void LoadVolumeMap(std::optional<base::Value::Dict> cast_audio_config);
 
  private:
   struct LevelToDb {
diff --git a/chromecast/media/cma/backend/volume_map_unittest.cc b/chromecast/media/cma/backend/volume_map_unittest.cc
index aa0c3ef..cb85ce2 100644
--- a/chromecast/media/cma/backend/volume_map_unittest.cc
+++ b/chromecast/media/cma/backend/volume_map_unittest.cc
@@ -39,7 +39,7 @@
   }
 
  private:
-  absl::optional<base::Value::Dict> GetCastAudioConfig() override {
+  std::optional<base::Value::Dict> GetCastAudioConfig() override {
     return base::test::ParseJsonDict(file_contents_);
   }
 
diff --git a/chromecast/media/cma/base/decoder_config_adapter.cc b/chromecast/media/cma/base/decoder_config_adapter.cc
index 12f63880..ff5c964 100644
--- a/chromecast/media/cma/base/decoder_config_adapter.cc
+++ b/chromecast/media/cma/base/decoder_config_adapter.cc
@@ -352,7 +352,7 @@
   video_config.matrix = static_cast<MatrixID>(config.color_space_info().matrix);
   video_config.range = static_cast<RangeID>(config.color_space_info().range);
 
-  absl::optional<::gfx::HDRMetadata> hdr_metadata = config.hdr_metadata();
+  std::optional<::gfx::HDRMetadata> hdr_metadata = config.hdr_metadata();
   if (hdr_metadata) {
     video_config.have_hdr_metadata = true;
 
diff --git a/chromecast/media/cma/decoder/cast_audio_decoder.cc b/chromecast/media/cma/decoder/cast_audio_decoder.cc
index a4f0560..75081d4 100644
--- a/chromecast/media/cma/decoder/cast_audio_decoder.cc
+++ b/chromecast/media/cma/decoder/cast_audio_decoder.cc
@@ -10,6 +10,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/containers/queue.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
@@ -30,7 +31,6 @@
 #include "media/base/sample_format.h"
 #include "media/base/status.h"
 #include "media/filters/ffmpeg_audio_decoder.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromecast {
 namespace media {
diff --git a/chromecast/media/gpu/cast_gpu_factory_impl.cc b/chromecast/media/gpu/cast_gpu_factory_impl.cc
index cb5b392..e457318 100644
--- a/chromecast/media/gpu/cast_gpu_factory_impl.cc
+++ b/chromecast/media/gpu/cast_gpu_factory_impl.cc
@@ -175,7 +175,7 @@
       request_overlay_info_cb, gfx::ColorSpace::CreateSRGB());
 }
 
-absl::optional<::media::VideoEncodeAccelerator::SupportedProfiles>
+std::optional<::media::VideoEncodeAccelerator::SupportedProfiles>
 CastGpuFactoryImpl::GetVideoEncodeAcceleratorSupportedProfiles() {
   return ::media::VideoEncodeAccelerator::SupportedProfiles();
 }
diff --git a/chromecast/media/gpu/cast_gpu_factory_impl.h b/chromecast/media/gpu/cast_gpu_factory_impl.h
index 1428830..3be4f47 100644
--- a/chromecast/media/gpu/cast_gpu_factory_impl.h
+++ b/chromecast/media/gpu/cast_gpu_factory_impl.h
@@ -63,7 +63,7 @@
   std::unique_ptr<media::VideoDecoder> CreateVideoDecoder(
       ::media::MediaLog* media_log,
       ::media::RequestOverlayInfoCB request_overlay_info_cb) override;
-  absl::optional<media::VideoEncodeAccelerator::SupportedProfiles>
+  std::optional<media::VideoEncodeAccelerator::SupportedProfiles>
   GetVideoEncodeAcceleratorSupportedProfiles() override;
   bool IsEncoderSupportKnown() override;
   void NotifyEncoderSupportKnown(base::OnceClosure) override;
diff --git a/chromecast/media/service/cast_renderer.cc b/chromecast/media/service/cast_renderer.cc
index b7336543..9408c93 100644
--- a/chromecast/media/service/cast_renderer.cc
+++ b/chromecast/media/service/cast_renderer.cc
@@ -348,8 +348,8 @@
   std::move(cdm_attached_cb).Run(true);
 }
 
-void CastRenderer::SetLatencyHint(
-    absl::optional<base::TimeDelta> latency_hint) {}
+void CastRenderer::SetLatencyHint(std::optional<base::TimeDelta> latency_hint) {
+}
 
 void CastRenderer::Flush(base::OnceClosure flush_cb) {
   DCHECK(task_runner_->BelongsToCurrentThread());
diff --git a/chromecast/media/service/cast_renderer.h b/chromecast/media/service/cast_renderer.h
index 8f0963f..7e4398f1 100644
--- a/chromecast/media/service/cast_renderer.h
+++ b/chromecast/media/service/cast_renderer.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/memory/weak_ptr.h"
 #include "base/no_destructor.h"
 #include "base/unguessable_token.h"
@@ -22,7 +23,6 @@
 #include "media/mojo/mojom/frame_interface_factory.mojom.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect_f.h"
 #include "ui/gfx/overlay_transform.h"
 
@@ -69,7 +69,7 @@
                   ::media::PipelineStatusCallback init_cb) override;
   void SetCdm(::media::CdmContext* cdm_context,
               CdmAttachedCB cdm_attached_cb) override;
-  void SetLatencyHint(absl::optional<base::TimeDelta> latency_hint) override;
+  void SetLatencyHint(std::optional<base::TimeDelta> latency_hint) override;
   void Flush(base::OnceClosure flush_cb) override;
   void StartPlayingFrom(base::TimeDelta time) override;
   void SetPlaybackRate(double playback_rate) override;
@@ -150,7 +150,7 @@
     return *g_overlay_composited_callback;
   }
 
-  absl::optional<float> pending_volume_;
+  std::optional<float> pending_volume_;
 
   const bool is_buffering_enabled_;
 
diff --git a/chromecast/renderer/activity_filtering_websocket_handshake_throttle.cc b/chromecast/renderer/activity_filtering_websocket_handshake_throttle.cc
index 7ebae0a5..6bd75a13 100644
--- a/chromecast/renderer/activity_filtering_websocket_handshake_throttle.cc
+++ b/chromecast/renderer/activity_filtering_websocket_handshake_throttle.cc
@@ -25,7 +25,7 @@
 
   // Pass through allowed URLs, block otherwise.
   if (url_filter_->UrlMatchesWhitelist(gurl)) {
-    std::move(completion_callback).Run(absl::nullopt);
+    std::move(completion_callback).Run(std::nullopt);
     return;
   }
 
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc
index 07d3940..f0b5d1c 100644
--- a/chromecast/renderer/cast_content_renderer_client.cc
+++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/strings/string_number_conversions.h"
@@ -40,7 +41,6 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/network/public/cpp/is_potentially_trustworthy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/platform/web_runtime_features.h"
 #include "third_party/blink/public/web/web_frame_widget.h"
@@ -338,7 +338,7 @@
       std::move(throttle_provider));
 }
 
-absl::optional<::media::AudioRendererAlgorithmParameters>
+std::optional<::media::AudioRendererAlgorithmParameters>
 CastContentRendererClient::GetAudioRendererAlgorithmParameters(
     ::media::AudioParameters audio_parameters) {
 #if BUILDFLAG(IS_ANDROID)
@@ -347,9 +347,9 @@
   parameters.starting_capacity = kAudioRendererStartingCapacity;
   parameters.starting_capacity_for_encrypted =
       kAudioRendererStartingCapacityEncrypted;
-  return absl::optional<::media::AudioRendererAlgorithmParameters>(parameters);
+  return std::optional<::media::AudioRendererAlgorithmParameters>(parameters);
 #else
-  return absl::nullopt;
+  return std::nullopt;
 #endif
 }
 
diff --git a/chromecast/renderer/cast_content_renderer_client.h b/chromecast/renderer/cast_content_renderer_client.h
index 78cb57d..c6a3cbb 100644
--- a/chromecast/renderer/cast_content_renderer_client.h
+++ b/chromecast/renderer/cast_content_renderer_client.h
@@ -75,7 +75,7 @@
   std::unique_ptr<blink::URLLoaderThrottleProvider>
   CreateURLLoaderThrottleProvider(
       blink::URLLoaderThrottleProviderType type) override;
-  absl::optional<::media::AudioRendererAlgorithmParameters>
+  std::optional<::media::AudioRendererAlgorithmParameters>
   GetAudioRendererAlgorithmParameters(
       ::media::AudioParameters audio_parameters) override;
 
diff --git a/chromecast/renderer/feature_manager_on_associated_interface.cc b/chromecast/renderer/feature_manager_on_associated_interface.cc
index 34dc5d1..1824f4f 100644
--- a/chromecast/renderer/feature_manager_on_associated_interface.cc
+++ b/chromecast/renderer/feature_manager_on_associated_interface.cc
@@ -57,7 +57,7 @@
       LOG(ERROR) << __func__ << " failed to receive valid app_id";
     }
     bool allow_insecure_content = false;
-    absl::optional<bool> allow_insecure_content_received =
+    std::optional<bool> allow_insecure_content_received =
         feature->config.FindBool(feature::kKeyAllowInsecureContent);
     if (allow_insecure_content_received) {
       allow_insecure_content = *allow_insecure_content_received;
diff --git a/chromecast/renderer/media/key_systems_cast.cc b/chromecast/renderer/media/key_systems_cast.cc
index 8c048c96..15b6fa2 100644
--- a/chromecast/renderer/media/key_systems_cast.cc
+++ b/chromecast/renderer/media/key_systems_cast.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include <optional>
 #include "base/check.h"
 #include "base/command_line.h"
 #include "build/build_config.h"
@@ -15,7 +16,6 @@
 #include "media/base/eme_constants.h"
 #include "media/base/key_system_info.h"
 #include "media/media_buildflags.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/widevine/cdm/buildflags.h"
 
 #if BUILDFLAG(ENABLE_WIDEVINE)
diff --git a/chromecast/shared/platform_info_serializer.cc b/chromecast/shared/platform_info_serializer.cc
index 77c280ee..20468c3 100644
--- a/chromecast/shared/platform_info_serializer.cc
+++ b/chromecast/shared/platform_info_serializer.cc
@@ -27,13 +27,13 @@
     PlatformInfoSerializer&& other) = default;
 
 // static
-absl::optional<PlatformInfoSerializer> PlatformInfoSerializer::Deserialize(
+std::optional<PlatformInfoSerializer> PlatformInfoSerializer::Deserialize(
     base::StringPiece base64) {
-  absl::optional<cast::bindings::MediaCapabilitiesMessage> proto =
+  std::optional<cast::bindings::MediaCapabilitiesMessage> proto =
       chromecast::bindings::ProtoSerializer<
           cast::bindings::MediaCapabilitiesMessage>::Deserialize(base64);
   if (!proto) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   PlatformInfoSerializer parser;
@@ -184,82 +184,81 @@
   }
 }
 
-absl::optional<int> PlatformInfoSerializer::MaxWidth() const {
+std::optional<int> PlatformInfoSerializer::MaxWidth() const {
   return platform_info_.max_width();
 }
 
-absl::optional<int> PlatformInfoSerializer::MaxHeight() const {
+std::optional<int> PlatformInfoSerializer::MaxHeight() const {
   return platform_info_.max_height();
 }
 
-absl::optional<int> PlatformInfoSerializer::MaxFrameRate() const {
+std::optional<int> PlatformInfoSerializer::MaxFrameRate() const {
   return platform_info_.max_frame_rate();
 }
 
-absl::optional<std::string> PlatformInfoSerializer::SupportedCryptoBlockFormat()
+std::optional<std::string> PlatformInfoSerializer::SupportedCryptoBlockFormat()
     const {
   return platform_info_.supported_cryptoblock_format();
 }
 
-absl::optional<int> PlatformInfoSerializer::MaxChannels() const {
+std::optional<int> PlatformInfoSerializer::MaxChannels() const {
   return platform_info_.max_channels();
 }
 
-absl::optional<bool> PlatformInfoSerializer::PcmSurroundSoundSupported() const {
+std::optional<bool> PlatformInfoSerializer::PcmSurroundSoundSupported() const {
   return platform_info_.is_pcm_surround_sound_supported();
 }
 
-absl::optional<bool> PlatformInfoSerializer::IsPlatformDolbyVisionEnabled()
+std::optional<bool> PlatformInfoSerializer::IsPlatformDolbyVisionEnabled()
     const {
   return platform_info_.is_platform_dolby_vision_enabled();
 }
 
-absl::optional<bool> PlatformInfoSerializer::IsDolbyVisionSupported() const {
+std::optional<bool> PlatformInfoSerializer::IsDolbyVisionSupported() const {
   return platform_info_.is_dolby_vision_supported();
 }
 
-absl::optional<bool> PlatformInfoSerializer::IsDolbyVision4kP60Supported()
+std::optional<bool> PlatformInfoSerializer::IsDolbyVision4kP60Supported()
     const {
   return platform_info_.is_dolby_vision4k_p60_supported();
 }
 
-absl::optional<bool>
+std::optional<bool>
 PlatformInfoSerializer::IsDolbyVisionSupportedByCurrentHdmiMode() const {
   return platform_info_.is_dolby_vision_supported_by_current_hdmi_mode();
 }
 
-absl::optional<bool> PlatformInfoSerializer::IsHdmiVideoModeSwitchEnabled()
+std::optional<bool> PlatformInfoSerializer::IsHdmiVideoModeSwitchEnabled()
     const {
   return platform_info_.is_hdmi_video_mode_switch_enabled();
 }
 
-absl::optional<bool> PlatformInfoSerializer::IsPlatformHevcEnabled() const {
+std::optional<bool> PlatformInfoSerializer::IsPlatformHevcEnabled() const {
   return platform_info_.is_platform_hevc_enabled();
 }
 
-absl::optional<bool> PlatformInfoSerializer::IsHdmiModeHdrCheckEnforced()
-    const {
+std::optional<bool> PlatformInfoSerializer::IsHdmiModeHdrCheckEnforced() const {
   return platform_info_.is_hdmi_mode_hdr_check_enforced();
 }
 
-absl::optional<bool> PlatformInfoSerializer::IsHdrSupportedByCurrentHdmiMode()
+std::optional<bool> PlatformInfoSerializer::IsHdrSupportedByCurrentHdmiMode()
     const {
   return platform_info_.is_hdr_supported_by_current_hdmi_mode();
 }
 
-absl::optional<bool> PlatformInfoSerializer::IsSmpteSt2084Supported() const {
+std::optional<bool> PlatformInfoSerializer::IsSmpteSt2084Supported() const {
   return platform_info_.is_smpte_st2084_supported();
 }
 
-absl::optional<bool> PlatformInfoSerializer::IsHlgSupported() const {
+std::optional<bool> PlatformInfoSerializer::IsHlgSupported() const {
   return platform_info_.is_hlg_supported();
 }
 
-absl::optional<bool> PlatformInfoSerializer::IsHdrFeatureEnabled() const {
+std::optional<bool> PlatformInfoSerializer::IsHdrFeatureEnabled() const {
   return platform_info_.is_hdr_feature_enabled();
 }
 
-absl::optional<std::vector<int>>
+std::optional<std::vector<int>>
 PlatformInfoSerializer::SupportedLegacyVp9Levels() const {
   std::vector<int> levels;
   levels.reserve(platform_info_.supported_legacy_vp9_levels_size());
@@ -270,20 +269,19 @@
   return levels;
 }
 
-absl::optional<int> PlatformInfoSerializer::HdcpVersion() const {
+std::optional<int> PlatformInfoSerializer::HdcpVersion() const {
   return platform_info_.hdcp_version();
 }
 
-absl::optional<int> PlatformInfoSerializer::SpatialRenderingSupportMask()
-    const {
+std::optional<int> PlatformInfoSerializer::SpatialRenderingSupportMask() const {
   return platform_info_.spatial_rendering_support_mask();
 }
 
-absl::optional<int> PlatformInfoSerializer::MaxFillRate() const {
+std::optional<int> PlatformInfoSerializer::MaxFillRate() const {
   return platform_info_.max_fill_rate();
 }
 
-absl::optional<std::vector<PlatformInfoSerializer::AudioCodecInfo>>
+std::optional<std::vector<PlatformInfoSerializer::AudioCodecInfo>>
 PlatformInfoSerializer::SupportedAudioCodecs() const {
   std::vector<AudioCodecInfo> infos;
   infos.reserve(platform_info_.supported_audio_codecs_size());
@@ -311,12 +309,12 @@
   }
 
   return infos.empty()
-             ? absl::nullopt
-             : absl::make_optional<
+             ? std::nullopt
+             : std::make_optional<
                    std::vector<PlatformInfoSerializer::AudioCodecInfo>>(infos);
 }
 
-absl::optional<std::vector<PlatformInfoSerializer::VideoCodecInfo>>
+std::optional<std::vector<PlatformInfoSerializer::VideoCodecInfo>>
 PlatformInfoSerializer::SupportedVideoCodecs() const {
   std::vector<VideoCodecInfo> infos;
   infos.reserve(platform_info_.supported_video_codecs_size());
@@ -340,8 +338,8 @@
   }
 
   return infos.empty()
-             ? absl::nullopt
-             : absl::make_optional<
+             ? std::nullopt
+             : std::make_optional<
                    std::vector<PlatformInfoSerializer::VideoCodecInfo>>(infos);
 }
 
diff --git a/chromecast/shared/platform_info_serializer.h b/chromecast/shared/platform_info_serializer.h
index 5ee3fda..fcb4718 100644
--- a/chromecast/shared/platform_info_serializer.h
+++ b/chromecast/shared/platform_info_serializer.h
@@ -8,9 +8,9 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/strings/string_piece.h"
 #include "chromecast/public/media/decoder_config.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cast_core/public/src/proto/bindings/media_capabilities.pb.h"
 
 namespace chromecast {
@@ -42,7 +42,7 @@
   cast::bindings::MediaCapabilitiesMessage* platform_info();
 
   std::string Serialize() const;
-  static absl::optional<PlatformInfoSerializer> Deserialize(
+  static std::optional<PlatformInfoSerializer> Deserialize(
       base::StringPiece base64);
 
   // Setters for known valid properties.
@@ -69,34 +69,34 @@
   void SetSupportedAudioCodecs(std::vector<AudioCodecInfo> codec_infos);
   void SetSupportedVideoCodecs(std::vector<VideoCodecInfo> codec_infos);
 
-  // Getters for the same properties. Returns absl::nullopt if no such value is
+  // Getters for the same properties. Returns std::nullopt if no such value is
   // set, and the set value in all other cases.
-  absl::optional<int> MaxWidth() const;
-  absl::optional<int> MaxHeight() const;
-  absl::optional<int> MaxFrameRate() const;
-  absl::optional<std::string> SupportedCryptoBlockFormat() const;
-  absl::optional<int> MaxChannels() const;
-  absl::optional<bool> PcmSurroundSoundSupported() const;
-  absl::optional<bool> IsPlatformDolbyVisionEnabled() const;
-  absl::optional<bool> IsDolbyVisionSupported() const;
-  absl::optional<bool> IsDolbyVision4kP60Supported() const;
-  absl::optional<bool> IsDolbyVisionSupportedByCurrentHdmiMode() const;
-  absl::optional<bool> IsHdmiVideoModeSwitchEnabled() const;
-  absl::optional<bool> IsPlatformHevcEnabled() const;
-  absl::optional<bool> IsHdmiModeHdrCheckEnforced() const;
-  absl::optional<bool> IsHdrSupportedByCurrentHdmiMode() const;
-  absl::optional<bool> IsSmpteSt2084Supported() const;
-  absl::optional<bool> IsHlgSupported() const;
-  absl::optional<bool> IsHdrFeatureEnabled() const;
-  absl::optional<int> HdcpVersion() const;
-  absl::optional<int> SpatialRenderingSupportMask() const;
-  absl::optional<int> MaxFillRate() const;
-  absl::optional<std::vector<AudioCodecInfo>> SupportedAudioCodecs() const;
-  absl::optional<std::vector<VideoCodecInfo>> SupportedVideoCodecs() const;
+  std::optional<int> MaxWidth() const;
+  std::optional<int> MaxHeight() const;
+  std::optional<int> MaxFrameRate() const;
+  std::optional<std::string> SupportedCryptoBlockFormat() const;
+  std::optional<int> MaxChannels() const;
+  std::optional<bool> PcmSurroundSoundSupported() const;
+  std::optional<bool> IsPlatformDolbyVisionEnabled() const;
+  std::optional<bool> IsDolbyVisionSupported() const;
+  std::optional<bool> IsDolbyVision4kP60Supported() const;
+  std::optional<bool> IsDolbyVisionSupportedByCurrentHdmiMode() const;
+  std::optional<bool> IsHdmiVideoModeSwitchEnabled() const;
+  std::optional<bool> IsPlatformHevcEnabled() const;
+  std::optional<bool> IsHdmiModeHdrCheckEnforced() const;
+  std::optional<bool> IsHdrSupportedByCurrentHdmiMode() const;
+  std::optional<bool> IsSmpteSt2084Supported() const;
+  std::optional<bool> IsHlgSupported() const;
+  std::optional<bool> IsHdrFeatureEnabled() const;
+  std::optional<int> HdcpVersion() const;
+  std::optional<int> SpatialRenderingSupportMask() const;
+  std::optional<int> MaxFillRate() const;
+  std::optional<std::vector<AudioCodecInfo>> SupportedAudioCodecs() const;
+  std::optional<std::vector<VideoCodecInfo>> SupportedVideoCodecs() const;
 
   // Deprecated fields.
   void SetSupportedLegacyVp9Levels(std::vector<int> levels);
-  absl::optional<std::vector<int>> SupportedLegacyVp9Levels() const;
+  std::optional<std::vector<int>> SupportedLegacyVp9Levels() const;
 
  private:
   // All currently produced values.
diff --git a/chromecast/shared/platform_info_serializer_unittest.cc b/chromecast/shared/platform_info_serializer_unittest.cc
index 60f4e16e..661720e 100644
--- a/chromecast/shared/platform_info_serializer_unittest.cc
+++ b/chromecast/shared/platform_info_serializer_unittest.cc
@@ -12,7 +12,7 @@
 PlatformInfoSerializer ConvertAndValidate(
     const PlatformInfoSerializer& parser) {
   std::string base64 = parser.Serialize();
-  absl::optional<PlatformInfoSerializer> deserialized_parser =
+  std::optional<PlatformInfoSerializer> deserialized_parser =
       PlatformInfoSerializer::Deserialize(base64);
   EXPECT_TRUE(deserialized_parser);
   EXPECT_EQ(parser.Serialize(), deserialized_parser->Serialize());
diff --git a/chromeos/ash/components/geolocation/simple_geolocation_provider.cc b/chromeos/ash/components/geolocation/simple_geolocation_provider.cc
index f3434b5..0f7f773 100644
--- a/chromeos/ash/components/geolocation/simple_geolocation_provider.cc
+++ b/chromeos/ash/components/geolocation/simple_geolocation_provider.cc
@@ -7,10 +7,12 @@
 #include <iterator>
 #include <memory>
 
+#include "base/check_is_test.h"
 #include "base/functional/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/ranges/algorithm.h"
 #include "chromeos/ash/components/geolocation/geoposition.h"
+#include "chromeos/ash/components/geolocation/simple_geolocation_request.h"
 #include "chromeos/ash/components/network/geolocation_handler.h"
 #include "chromeos/ash/components/network/network_handler.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -19,23 +21,62 @@
 
 namespace {
 
-const char kDefaultGeolocationProviderUrl[] =
-    "https://www.googleapis.com/geolocation/v1/geolocate?";
+SimpleGeolocationProvider* g_geolocation_provider = nullptr;
 
 }  // namespace
 
 SimpleGeolocationProvider::SimpleGeolocationProvider(
-    const Delegate* delegate,
-    scoped_refptr<network::SharedURLLoaderFactory> factory,
-    const GURL& url)
-    : delegate_(delegate),
-      shared_url_loader_factory_(std::move(factory)),
-      url_(url) {}
+    scoped_refptr<network::SharedURLLoaderFactory> factory)
+    : shared_url_loader_factory_(factory) {}
 
 SimpleGeolocationProvider::~SimpleGeolocationProvider() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 }
 
+// static
+void SimpleGeolocationProvider::Initialize(
+    scoped_refptr<network::SharedURLLoaderFactory> factory) {
+  CHECK_EQ(g_geolocation_provider, nullptr);
+
+  g_geolocation_provider = new SimpleGeolocationProvider(factory);
+}
+
+// static
+SimpleGeolocationProvider* SimpleGeolocationProvider::GetInstance() {
+  CHECK_NE(g_geolocation_provider, nullptr);
+  return g_geolocation_provider;
+}
+
+void SimpleGeolocationProvider::AllowGeolocationUsage() {
+  bool need_to_notify = (geolocation_usage_allowed_ == false);
+  geolocation_usage_allowed_ = true;
+
+  if (need_to_notify) {
+    NotifyObservers();
+  }
+}
+
+void SimpleGeolocationProvider::DisallowGeolocationUsage() {
+  bool need_to_notify = (geolocation_usage_allowed_ == true);
+  geolocation_usage_allowed_ = false;
+
+  if (need_to_notify) {
+    NotifyObservers();
+  }
+}
+
+void SimpleGeolocationProvider::AddObserver(Observer* obs) {
+  CHECK(obs);
+  CHECK(!observer_list_.HasObserver(obs));
+  observer_list_.AddObserver(obs);
+}
+
+void SimpleGeolocationProvider::RemoveObserver(Observer* obs) {
+  CHECK(obs);
+  CHECK(observer_list_.HasObserver(obs));
+  observer_list_.RemoveObserver(obs);
+}
+
 void SimpleGeolocationProvider::RequestGeolocation(
     base::TimeDelta timeout,
     bool send_wifi_access_points,
@@ -44,7 +85,7 @@
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   // Drop request if the system geolocation permission is not granted.
-  if (!delegate_->IsSystemGeolocationAllowed()) {
+  if (!IsGeolocationUsageAllowed()) {
     return;
   }
 
@@ -69,8 +110,8 @@
     cell_vector = nullptr;
 
   SimpleGeolocationRequest* request(new SimpleGeolocationRequest(
-      shared_url_loader_factory_, url_, timeout, std::move(wifi_vector),
-      std::move(cell_vector)));
+      shared_url_loader_factory_, GURL(GetGeolocationProviderUrl()), timeout,
+      std::move(wifi_vector), std::move(cell_vector)));
   requests_.push_back(base::WrapUnique(request));
 
   // SimpleGeolocationProvider owns all requests. It is safe to pass unretained
@@ -83,8 +124,23 @@
 }
 
 // static
-GURL SimpleGeolocationProvider::DefaultGeolocationProviderURL() {
-  return GURL(kDefaultGeolocationProviderUrl);
+void SimpleGeolocationProvider::DestroyForTesting() {
+  CHECK_IS_TEST();
+  CHECK_NE(g_geolocation_provider, nullptr);
+  delete g_geolocation_provider;
+  g_geolocation_provider = nullptr;
+}
+
+void SimpleGeolocationProvider::SetSharedUrlLoaderFactoryForTesting(
+    scoped_refptr<network::SharedURLLoaderFactory> factory) {
+  CHECK_IS_TEST();
+  shared_url_loader_factory_ = factory;
+}
+
+void SimpleGeolocationProvider::SetGeolocationProviderUrlForTesting(
+    const char* url) {
+  CHECK_IS_TEST();
+  url_for_testing_ = url;
 }
 
 void SimpleGeolocationProvider::OnGeolocationResponse(
@@ -107,4 +163,19 @@
   }
 }
 
+std::string SimpleGeolocationProvider::GetGeolocationProviderUrl() const {
+  // URL provider is overridden in tests.
+  if (!url_for_testing_.empty()) {
+    CHECK_IS_TEST();
+    return url_for_testing_;
+  }
+  return kGeolocationProviderUrl;
+}
+
+void SimpleGeolocationProvider::NotifyObservers() {
+  for (auto& obs : observer_list_) {
+    obs.OnGeolocationPermissionChanged(geolocation_usage_allowed_);
+  }
+}
+
 }  // namespace ash
diff --git a/chromeos/ash/components/geolocation/simple_geolocation_provider.h b/chromeos/ash/components/geolocation/simple_geolocation_provider.h
index aefbdedd..5ef6e728 100644
--- a/chromeos/ash/components/geolocation/simple_geolocation_provider.h
+++ b/chromeos/ash/components/geolocation/simple_geolocation_provider.h
@@ -8,13 +8,18 @@
 #include <memory>
 #include <vector>
 
+#include "base/check_is_test.h"
 #include "base/component_export.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/observer_list.h"
+#include "base/observer_list_types.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "chromeos/ash/components/geolocation/simple_geolocation_request.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "url/gurl.h"
 
 namespace network {
@@ -27,7 +32,7 @@
 
 // This class implements Google Maps Geolocation API.
 //
-// SimpleGeolocationProvider must be created and used on the same thread.
+// `SimpleGeolocationProvider` must be created and used on the same thread.
 //
 // Note: this should probably be a singleton to monitor requests rate.
 // But as it is used only during ChromeOS Out-of-Box, it can be owned by
@@ -35,35 +40,37 @@
 class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_GEOLOCATION)
     SimpleGeolocationProvider {
  public:
-  class Delegate {
+  class Observer : public base::CheckedObserver {
    public:
-    Delegate() = default;
-
-    Delegate(const Delegate&) = delete;
-    Delegate& operator=(const Delegate&) = delete;
-
-    virtual ~Delegate() = default;
-
-    // Determines if the geolocation resolution is allowed by the system, based
-    // on the existing enterprise policies, device preferences and user
-    // preferences.
-    virtual bool IsSystemGeolocationAllowed() const = 0;
+    virtual void OnGeolocationPermissionChanged(bool enabled) = 0;
   };
 
-  SimpleGeolocationProvider(
-      const Delegate* delegate,
-      scoped_refptr<network::SharedURLLoaderFactory> factory,
-      const GURL& url);
-
   SimpleGeolocationProvider(const SimpleGeolocationProvider&) = delete;
   SimpleGeolocationProvider& operator=(const SimpleGeolocationProvider&) =
       delete;
 
   virtual ~SimpleGeolocationProvider();
 
+  // This function has to be called first thing before using other members.
+  static void Initialize(
+      scoped_refptr<network::SharedURLLoaderFactory> factory);
+
+  static SimpleGeolocationProvider* GetInstance();
+
+  static GURL DefaultGeolocationProviderURL() {
+    return GURL(kGeolocationProviderUrl);
+  }
+
+  bool IsGeolocationUsageAllowed() const { return geolocation_usage_allowed_; }
+  void AllowGeolocationUsage();
+  void DisallowGeolocationUsage();
+
+  void AddObserver(Observer* obs);
+  void RemoveObserver(Observer* obs);
+
   // Initiates new request. If |send_wifi_access_points|, WiFi AP information
   // will be added to the request, similarly for |send_cell_towers| and Cell
-  // Tower information. See SimpleGeolocationRequest for the description of
+  // Tower information. See `SimpleGeolocationRequest` for the description of
   // the other parameters.
   void RequestGeolocation(base::TimeDelta timeout,
                           bool send_wifi_access_points,
@@ -74,10 +81,19 @@
     return shared_url_loader_factory_.get();
   }
 
-  // Returns default geolocation service URL.
-  static GURL DefaultGeolocationProviderURL();
+  static void DestroyForTesting();
+  void SetSharedUrlLoaderFactoryForTesting(
+      scoped_refptr<network::SharedURLLoaderFactory> factory);
+  void SetGeolocationProviderUrlForTesting(const char* url);
 
  private:
+  static constexpr char kGeolocationProviderUrl[] =
+      "https://www.googleapis.com/geolocation/v1/geolocate?";
+
+  // This class is a singleton.
+  explicit SimpleGeolocationProvider(
+      scoped_refptr<network::SharedURLLoaderFactory> factory);
+
   friend class TestGeolocationAPILoaderFactory;
   FRIEND_TEST_ALL_PREFIXES(SimpleGeolocationWirelessTest, CellularExists);
   FRIEND_TEST_ALL_PREFIXES(SimpleGeolocationWirelessTest, WiFiExists);
@@ -90,24 +106,34 @@
       bool server_error,
       const base::TimeDelta elapsed);
 
+  // Returns `DefaultGeolocaitonProivdeURL()` for production. Can be overridden
+  // in tests.
+  std::string GetGeolocationProviderUrl() const;
+
   void set_geolocation_handler(GeolocationHandler* geolocation_handler) {
     geolocation_handler_ = geolocation_handler;
   }
 
-  const raw_ptr<const Delegate, ExperimentalAsh> delegate_;
+  void NotifyObservers();
+
+  // Source of truth whether the clients can use geolocation or not.
+  // Takes into consideration geolocation policy, log-in or in-session
+  // geolocation prefs.
+  bool geolocation_usage_allowed_ = true;
+
+  base::ObserverList<Observer> observer_list_;
 
   scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
 
-  // URL of the Google Maps Geolocation API.
-  const GURL url_;
-
   // Requests in progress.
-  // SimpleGeolocationProvider owns all requests, so this vector is deleted on
+  // `SimpleGeolocationProvider` owns all requests, so this vector is deleted on
   // destroy.
   std::vector<std::unique_ptr<SimpleGeolocationRequest>> requests_;
 
   raw_ptr<GeolocationHandler, ExperimentalAsh> geolocation_handler_ = nullptr;
 
+  std::string url_for_testing_;
+
   // Creation and destruction should happen on the same thread.
   THREAD_CHECKER(thread_checker_);
 };
diff --git a/chromeos/ash/components/geolocation/simple_geolocation_unittest.cc b/chromeos/ash/components/geolocation/simple_geolocation_unittest.cc
index e1497edd..e08932f 100644
--- a/chromeos/ash/components/geolocation/simple_geolocation_unittest.cc
+++ b/chromeos/ash/components/geolocation/simple_geolocation_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/containers/contains.h"
 #include "base/functional/bind.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
@@ -80,12 +81,6 @@
 
 namespace ash {
 
-class MockUserGeolocationPermissionProvider
-    : public SimpleGeolocationProvider::Delegate {
- public:
-  MOCK_METHOD(bool, IsSystemGeolocationAllowed, (), (const, override));
-};
-
 // This implements fake Google MAPS Geolocation API remote endpoint.
 class TestGeolocationAPILoaderFactory : public network::TestURLLoaderFactory {
  public:
@@ -103,14 +98,24 @@
   TestGeolocationAPILoaderFactory& operator=(
       const TestGeolocationAPILoaderFactory&) = delete;
 
+  void Configure(const GURL& url,
+                 const std::string& response,
+                 const size_t require_retries) {
+    url_ = url;
+    response_ = response;
+    require_retries_ = require_retries;
+  }
+
   void Intercept(const network::ResourceRequest& request) {
     EXPECT_EQ(url_, request.url);
 
-    EXPECT_NE(nullptr, provider_);
-    EXPECT_EQ(provider_->requests_.size(), 1U);
+    SimpleGeolocationProvider* provider =
+        SimpleGeolocationProvider::GetInstance();
+    EXPECT_NE(nullptr, provider);
+    EXPECT_EQ(provider->requests_.size(), 1U);
 
     SimpleGeolocationRequest* geolocation_request =
-        provider_->requests_[0].get();
+        provider->requests_[0].get();
 
     const base::TimeDelta base_retry_interval =
         base::Milliseconds(kRequestRetryIntervalMilliSeconds);
@@ -123,9 +128,6 @@
       AddResponseWithCode(net::OK);
   }
 
-  void SetSimpleGeolocationProvider(SimpleGeolocationProvider* provider) {
-    provider_ = provider;
-  }
   size_t attempts() const { return attempts_; }
 
  private:
@@ -141,9 +143,8 @@
 
   GURL url_;
   std::string response_;
-  const size_t require_retries_;
+  size_t require_retries_;
   size_t attempts_ = 0;
-  raw_ptr<SimpleGeolocationProvider, ExperimentalAsh> provider_;
 };
 
 class GeolocationReceiver {
@@ -197,31 +198,53 @@
   unsigned int requests_count_ = 0;
 };
 
-class SimpleGeolocationTest : public testing::Test {
+class SimpleGeolocationTestBase {
+ public:
+  SimpleGeolocationTestBase()
+      : url_factory_(GURL(kTestGeolocationProviderUrl),
+                     kSimpleResponseBody,
+                     0 /* require_retries */) {}
+
+  ~SimpleGeolocationTestBase() = default;
+
+  void EnableGeolocationUsage() {
+    SimpleGeolocationProvider::GetInstance()->AllowGeolocationUsage();
+  }
+
+  void DisableGeolocatioUsage() {
+    SimpleGeolocationProvider::GetInstance()->DisallowGeolocationUsage();
+  }
+
  protected:
-  MockUserGeolocationPermissionProvider mock_permission_provider_;
+  void SetUp() {
+    SimpleGeolocationProvider::Initialize(
+        base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+            &url_factory_));
+    SimpleGeolocationProvider::GetInstance()
+        ->SetGeolocationProviderUrlForTesting(kTestGeolocationProviderUrl);
+  }
+
+  void TearDown() { SimpleGeolocationProvider::DestroyForTesting(); }
+  TestGeolocationAPILoaderFactory url_factory_;
+};
+
+class SimpleGeolocationTest : public SimpleGeolocationTestBase,
+                              public testing::Test {
+ protected:
+  void SetUp() override { SimpleGeolocationTestBase::SetUp(); }
+
+  void TearDown() override { SimpleGeolocationTestBase::TearDown(); }
 
  private:
   base::test::SingleThreadTaskEnvironment task_environment_;
 };
 
 TEST_F(SimpleGeolocationTest, ResponseOK) {
-  TestGeolocationAPILoaderFactory url_factory(GURL(kTestGeolocationProviderUrl),
-                                              kSimpleResponseBody,
-                                              0 /* require_retries */);
-  SimpleGeolocationProvider provider(
-      &mock_permission_provider_,
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &url_factory),
-      GURL(kTestGeolocationProviderUrl));
-  url_factory.SetSimpleGeolocationProvider(&provider);
-
   // Set user permission to granted.
-  EXPECT_CALL(mock_permission_provider_, IsSystemGeolocationAllowed())
-      .WillRepeatedly(testing::Return(true));
+  EnableGeolocationUsage();
 
   GeolocationReceiver receiver;
-  provider.RequestGeolocation(
+  SimpleGeolocationProvider::GetInstance()->RequestGeolocation(
       base::Seconds(1), false, false,
       base::BindOnce(&GeolocationReceiver::OnRequestDone,
                      base::Unretained(&receiver)));
@@ -229,50 +252,31 @@
 
   EXPECT_EQ(kExpectedPosition, receiver.position().ToString());
   EXPECT_FALSE(receiver.server_error());
-  EXPECT_EQ(1U, url_factory.attempts());
+  EXPECT_EQ(1U, url_factory_.attempts());
 }
 
 TEST_F(SimpleGeolocationTest, ResponseOKWithRetries) {
-  TestGeolocationAPILoaderFactory url_factory(GURL(kTestGeolocationProviderUrl),
-                                              kSimpleResponseBody,
-                                              3 /* require_retries */);
-
-  SimpleGeolocationProvider provider(
-      &mock_permission_provider_,
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &url_factory),
-      GURL(kTestGeolocationProviderUrl));
-  url_factory.SetSimpleGeolocationProvider(&provider);
+  url_factory_.Configure(GURL(kTestGeolocationProviderUrl), kSimpleResponseBody,
+                         3 /* require_retries */);
 
   // Set user permission to granted.
-  EXPECT_CALL(mock_permission_provider_, IsSystemGeolocationAllowed())
-      .WillRepeatedly(testing::Return(true));
+  EnableGeolocationUsage();
 
   GeolocationReceiver receiver;
-  provider.RequestGeolocation(
+  SimpleGeolocationProvider::GetInstance()->RequestGeolocation(
       base::Seconds(1), false, false,
       base::BindOnce(&GeolocationReceiver::OnRequestDone,
                      base::Unretained(&receiver)));
   receiver.WaitUntilRequestDone();
   EXPECT_EQ(kExpectedPosition, receiver.position().ToString());
   EXPECT_FALSE(receiver.server_error());
-  EXPECT_EQ(4U, url_factory.attempts());
+  EXPECT_EQ(4U, url_factory_.attempts());
 }
 
 TEST_F(SimpleGeolocationTest, InvalidResponse) {
-  TestGeolocationAPILoaderFactory url_factory(GURL(kTestGeolocationProviderUrl),
-                                              "invalid JSON string",
-                                              0 /* require_retries */);
-  SimpleGeolocationProvider provider(
-      &mock_permission_provider_,
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &url_factory),
-      GURL(kTestGeolocationProviderUrl));
-  url_factory.SetSimpleGeolocationProvider(&provider);
-
-  // Set user permission to granted.
-  EXPECT_CALL(mock_permission_provider_, IsSystemGeolocationAllowed())
-      .WillRepeatedly(testing::Return(true));
+  url_factory_.Configure(GURL(kTestGeolocationProviderUrl),
+                         "invalid JSON string", 0 /* require_retries */);
+  EnableGeolocationUsage();
 
   const int timeout_seconds = 1;
   size_t expected_retries = static_cast<size_t>(
@@ -280,7 +284,7 @@
   ASSERT_GE(expected_retries, 2U);
 
   GeolocationReceiver receiver;
-  provider.RequestGeolocation(
+  SimpleGeolocationProvider::GetInstance()->RequestGeolocation(
       base::Seconds(timeout_seconds), false, false,
       base::BindOnce(&GeolocationReceiver::OnRequestDone,
                      base::Unretained(&receiver)));
@@ -294,17 +298,17 @@
       "'https://localhost/' : JSONReader failed:"));
   EXPECT_TRUE(base::Contains(receiver_position, "status=4 (TIMEOUT)"));
   EXPECT_TRUE(receiver.server_error());
-  EXPECT_GE(url_factory.attempts(), 2U);
-  if (url_factory.attempts() > expected_retries + 1) {
+  EXPECT_GE(url_factory_.attempts(), 2U);
+  if (url_factory_.attempts() > expected_retries + 1) {
     LOG(WARNING)
         << "SimpleGeolocationTest::InvalidResponse: Too many attempts ("
-        << url_factory.attempts() << "), no more than " << expected_retries + 1
+        << url_factory_.attempts() << "), no more than " << expected_retries + 1
         << " expected.";
   }
-  if (url_factory.attempts() < expected_retries - 1) {
+  if (url_factory_.attempts() < expected_retries - 1) {
     LOG(WARNING)
         << "SimpleGeolocationTest::InvalidResponse: Too little attempts ("
-        << url_factory.attempts() << "), greater than " << expected_retries - 1
+        << url_factory_.attempts() << "), greater than " << expected_retries - 1
         << " expected.";
   }
 }
@@ -315,22 +319,12 @@
   WirelessTestMonitor requests_monitor;
   SimpleGeolocationRequest::SetTestMonitor(&requests_monitor);
 
-  TestGeolocationAPILoaderFactory url_factory(GURL(kTestGeolocationProviderUrl),
-                                              kSimpleResponseBody,
-                                              0 /* require_retries */);
-  SimpleGeolocationProvider provider(
-      &mock_permission_provider_,
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &url_factory),
-      GURL(kTestGeolocationProviderUrl));
-  url_factory.SetSimpleGeolocationProvider(&provider);
-
-  // Set geolocation permission to granted.
-  EXPECT_CALL(mock_permission_provider_, IsSystemGeolocationAllowed())
-      .WillRepeatedly(testing::Return(true));
+  url_factory_.Configure(GURL(kTestGeolocationProviderUrl), kSimpleResponseBody,
+                         0 /* require_retries */);
+  EnableGeolocationUsage();
 
   GeolocationReceiver receiver;
-  provider.RequestGeolocation(
+  SimpleGeolocationProvider::GetInstance()->RequestGeolocation(
       base::Seconds(1), true, false,
       base::BindOnce(&GeolocationReceiver::OnRequestDone,
                      base::Unretained(&receiver)));
@@ -339,7 +333,7 @@
 
   EXPECT_EQ(kExpectedPosition, receiver.position().ToString());
   EXPECT_FALSE(receiver.server_error());
-  EXPECT_EQ(1U, url_factory.attempts());
+  EXPECT_EQ(1U, url_factory_.attempts());
 }
 
 // Test SimpleGeolocationProvider when the system geolocation permission is
@@ -350,24 +344,16 @@
   WirelessTestMonitor requests_monitor;
 
   SimpleGeolocationRequest::SetTestMonitor(&requests_monitor);
-  TestGeolocationAPILoaderFactory url_factory(GURL(kTestGeolocationProviderUrl),
-                                              kSimpleResponseBody, 0);
-
-  SimpleGeolocationProvider provider(
-      &mock_permission_provider_,
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &url_factory),
-      GURL(kTestGeolocationProviderUrl));
-  url_factory.SetSimpleGeolocationProvider(&provider);
+  url_factory_.Configure(GURL(kTestGeolocationProviderUrl), kSimpleResponseBody,
+                         0);
 
   // Set system geolocation permission to disabled.
-  EXPECT_CALL(mock_permission_provider_, IsSystemGeolocationAllowed())
-      .WillRepeatedly(testing::Return(false));
+  DisableGeolocatioUsage();
 
   // Test for every request type.
   for (bool send_wifi : {false, true}) {
     for (bool send_cell : {false, true}) {
-      provider.RequestGeolocation(
+      SimpleGeolocationProvider::GetInstance()->RequestGeolocation(
           base::Seconds(1), send_wifi, send_cell,
           base::BindOnce(&GeolocationReceiver::OnRequestDone,
                          base::Unretained(&receiver)));
@@ -375,14 +361,15 @@
       // Waiting is not needed, requests are dropped, thus nothing is pending.
       EXPECT_EQ(0U, requests_monitor.requests_count());
       EXPECT_EQ(std::string(), requests_monitor.last_request_body());
-      EXPECT_EQ(0U, url_factory.attempts());
+      EXPECT_EQ(0U, url_factory_.attempts());
     }
   }
 }
 
 // Test sending of WiFi Access points and Cell Towers.
 // (This is mostly derived from GeolocationHandlerTest.)
-class SimpleGeolocationWirelessTest : public ::testing::TestWithParam<bool> {
+class SimpleGeolocationWirelessTest : public SimpleGeolocationTestBase,
+                                      public ::testing::TestWithParam<bool> {
  public:
   SimpleGeolocationWirelessTest() : manager_test_(nullptr) {}
 
@@ -398,10 +385,14 @@
     ASSERT_TRUE(manager_test_);
     geolocation_handler_.reset(new GeolocationHandler());
     geolocation_handler_->Init();
+    SimpleGeolocationTestBase::SetUp();
     base::RunLoop().RunUntilIdle();
   }
 
-  void TearDown() override { geolocation_handler_.reset(); }
+  void TearDown() override {
+    SimpleGeolocationTestBase::TearDown();
+    geolocation_handler_.reset();
+  }
 
   bool GetWifiAccessPoints() {
     return geolocation_handler_->GetWifiAccessPoints(&wifi_access_points_,
@@ -445,8 +436,15 @@
     base::RunLoop().RunUntilIdle();
   }
 
+  void EnableGeolocationUsage() {
+    SimpleGeolocationProvider::GetInstance()->AllowGeolocationUsage();
+  }
+
+  void DisableGeolocatioUsage() {
+    SimpleGeolocationProvider::GetInstance()->DisallowGeolocationUsage();
+  }
+
  protected:
-  MockUserGeolocationPermissionProvider mock_permission_provider_;
   base::test::SingleThreadTaskEnvironment task_environment_{
       base::test::SingleThreadTaskEnvironment::MainThreadType::UI};
   NetworkHandlerTestHelper network_handler_test_helper_;
@@ -463,24 +461,17 @@
   WirelessTestMonitor requests_monitor;
   SimpleGeolocationRequest::SetTestMonitor(&requests_monitor);
 
-  TestGeolocationAPILoaderFactory url_factory(GURL(kTestGeolocationProviderUrl),
-                                              kSimpleResponseBody,
-                                              0 /* require_retries */);
-  SimpleGeolocationProvider provider(
-      &mock_permission_provider_,
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &url_factory),
-      GURL(kTestGeolocationProviderUrl));
+  url_factory_.Configure(GURL(kTestGeolocationProviderUrl), kSimpleResponseBody,
+                         0 /* require_retries */);
   // Set system geolocation permission to allowed. This permission is tested
   // separately.
-  EXPECT_CALL(mock_permission_provider_, IsSystemGeolocationAllowed())
-      .WillRepeatedly(testing::Return(true));
+  EnableGeolocationUsage();
 
-  url_factory.SetSimpleGeolocationProvider(&provider);
-  provider.set_geolocation_handler(geolocation_handler_.get());
+  SimpleGeolocationProvider::GetInstance()->set_geolocation_handler(
+      geolocation_handler_.get());
   {
     GeolocationReceiver receiver;
-    provider.RequestGeolocation(
+    SimpleGeolocationProvider::GetInstance()->RequestGeolocation(
         base::Seconds(1), send_wifi_access_points, false,
         base::BindOnce(&GeolocationReceiver::OnRequestDone,
                        base::Unretained(&receiver)));
@@ -489,7 +480,7 @@
 
     EXPECT_EQ(kExpectedPosition, receiver.position().ToString());
     EXPECT_FALSE(receiver.server_error());
-    EXPECT_EQ(1U, url_factory.attempts());
+    EXPECT_EQ(1U, url_factory_.attempts());
   }
 
   // Add cell and wifi to ensure only wifi is sent when cellular disabled.
@@ -507,7 +498,7 @@
 
   {
     GeolocationReceiver receiver;
-    provider.RequestGeolocation(
+    SimpleGeolocationProvider::GetInstance()->RequestGeolocation(
         base::Seconds(1), send_wifi_access_points, false,
         base::BindOnce(&GeolocationReceiver::OnRequestDone,
                        base::Unretained(&receiver)));
@@ -523,7 +514,7 @@
     EXPECT_EQ(kExpectedPosition, receiver.position().ToString());
     EXPECT_FALSE(receiver.server_error());
     // This is total.
-    EXPECT_EQ(2U, url_factory.attempts());
+    EXPECT_EQ(2U, url_factory_.attempts());
   }
 }
 
@@ -534,23 +525,16 @@
   WirelessTestMonitor requests_monitor;
   SimpleGeolocationRequest::SetTestMonitor(&requests_monitor);
 
-  TestGeolocationAPILoaderFactory url_factory(GURL(kTestGeolocationProviderUrl),
-                                              kSimpleResponseBody,
-                                              0 /* require_retries */);
-  SimpleGeolocationProvider provider(
-      &mock_permission_provider_,
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &url_factory),
-      GURL(kTestGeolocationProviderUrl));
-  // Set user permission to the test parameter.
-  EXPECT_CALL(mock_permission_provider_, IsSystemGeolocationAllowed())
-      .WillRepeatedly(testing::Return(true));
+  url_factory_.Configure(GURL(kTestGeolocationProviderUrl), kSimpleResponseBody,
+                         0 /* require_retries */);
+  // Enable system permission for geolocation usage.
+  EnableGeolocationUsage();
 
-  url_factory.SetSimpleGeolocationProvider(&provider);
-  provider.set_geolocation_handler(geolocation_handler_.get());
+  SimpleGeolocationProvider::GetInstance()->set_geolocation_handler(
+      geolocation_handler_.get());
   {
     GeolocationReceiver receiver;
-    provider.RequestGeolocation(
+    SimpleGeolocationProvider::GetInstance()->RequestGeolocation(
         base::Seconds(1), false, send_cell_towers,
         base::BindOnce(&GeolocationReceiver::OnRequestDone,
                        base::Unretained(&receiver)));
@@ -559,7 +543,7 @@
 
     EXPECT_EQ(kExpectedPosition, receiver.position().ToString());
     EXPECT_FALSE(receiver.server_error());
-    EXPECT_EQ(1U, url_factory.attempts());
+    EXPECT_EQ(1U, url_factory_.attempts());
   }
 
   AddCellTower(1);
@@ -575,7 +559,7 @@
 
   {
     GeolocationReceiver receiver;
-    provider.RequestGeolocation(
+    SimpleGeolocationProvider::GetInstance()->RequestGeolocation(
         base::Seconds(1), false, send_cell_towers,
         base::BindOnce(&GeolocationReceiver::OnRequestDone,
                        base::Unretained(&receiver)));
@@ -591,7 +575,7 @@
     EXPECT_EQ(kExpectedPosition, receiver.position().ToString());
     EXPECT_FALSE(receiver.server_error());
     // This is total.
-    EXPECT_EQ(2U, url_factory.attempts());
+    EXPECT_EQ(2U, url_factory_.attempts());
   }
 }
 
diff --git a/chromeos/ash/components/timezone/timezone_resolver.cc b/chromeos/ash/components/timezone/timezone_resolver.cc
index f24ba3b..d41c5fc 100644
--- a/chromeos/ash/components/timezone/timezone_resolver.cc
+++ b/chromeos/ash/components/timezone/timezone_resolver.cc
@@ -107,7 +107,7 @@
 
   // Called by TZRequest.
   SimpleGeolocationProvider* geolocation_provider() {
-    return &geolocation_provider_;
+    return resolver_->geolocation_provider_;
   }
   TimeZoneProvider* timezone_provider() { return &timezone_provider_; }
 
@@ -137,7 +137,6 @@
   // Returns delay to next timezone update request
   base::TimeDelta CalculateNextInterval();
 
-  SimpleGeolocationProvider geolocation_provider_;
   TimeZoneProvider timezone_provider_;
 
   base::OneShotTimer refresh_timer_;
@@ -264,10 +263,7 @@
 TimeZoneResolver::TimeZoneResolverImpl::TimeZoneResolverImpl(
     const TimeZoneResolver* resolver)
     : resolver_(resolver),
-      geolocation_provider_(
-          resolver->delegate_,
-          resolver->shared_url_loader_factory(),
-          SimpleGeolocationProvider::DefaultGeolocationProviderURL()),
+
       timezone_provider_(resolver->shared_url_loader_factory(),
                          DefaultTimezoneProviderURL()),
       requests_count_(0) {
@@ -394,14 +390,14 @@
 
 TimeZoneResolver::TimeZoneResolver(
     Delegate* delegate,
+    SimpleGeolocationProvider* geolocation_provider,
     scoped_refptr<network::SharedURLLoaderFactory> factory,
-    const GURL& url,
     const ApplyTimeZoneCallback& apply_timezone,
     const DelayNetworkCallClosure& delay_network_call,
     PrefService* local_state)
     : delegate_(delegate),
+      geolocation_provider_(geolocation_provider),
       shared_url_loader_factory_(std::move(factory)),
-      url_(url),
       apply_timezone_(apply_timezone),
       delay_network_call_(delay_network_call),
       local_state_(local_state) {
diff --git a/chromeos/ash/components/timezone/timezone_resolver.h b/chromeos/ash/components/timezone/timezone_resolver.h
index 28b225a..ba40ffe 100644
--- a/chromeos/ash/components/timezone/timezone_resolver.h
+++ b/chromeos/ash/components/timezone/timezone_resolver.h
@@ -38,14 +38,14 @@
   using DelayNetworkCallClosure =
       base::RepeatingCallback<void(base::OnceClosure)>;
 
-  class Delegate : public SimpleGeolocationProvider::Delegate {
+  class Delegate {
    public:
     Delegate() = default;
 
     Delegate(const Delegate&) = delete;
     Delegate& operator=(const Delegate&) = delete;
 
-    ~Delegate() override = default;
+    virtual ~Delegate() = default;
 
     // Returns true if TimeZoneResolver should include WiFi data in request.
     virtual bool ShouldSendWiFiGeolocationData() const = 0;
@@ -59,8 +59,8 @@
   static const char kLastTimeZoneRefreshTime[];
 
   TimeZoneResolver(Delegate* delegate,
+                   SimpleGeolocationProvider* geolocation_provider_,
                    scoped_refptr<network::SharedURLLoaderFactory> factory,
-                   const GURL& url,
                    const ApplyTimeZoneCallback& apply_timezone,
                    const DelayNetworkCallClosure& delay_network_call,
                    PrefService* local_state);
@@ -109,8 +109,11 @@
   bool is_running_ = false;
   const raw_ptr<const Delegate, ExperimentalAsh> delegate_;
 
+  // Points to the `SimpleGeolocationProvider::GetInstance()` throughout the
+  // object lifecycle. Overridden in unit tests.
+  raw_ptr<SimpleGeolocationProvider> geolocation_provider_ = nullptr;
+
   scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
-  const GURL url_;
 
   const ApplyTimeZoneCallback apply_timezone_;
   const DelayNetworkCallClosure delay_network_call_;
diff --git a/chromeos/crosapi/mojom/local_printer.mojom b/chromeos/crosapi/mojom/local_printer.mojom
index 18d1aea..6c6167a 100644
--- a/chromeos/crosapi/mojom/local_printer.mojom
+++ b/chromeos/crosapi/mojom/local_printer.mojom
@@ -140,6 +140,7 @@
     kArc,
     kExtension,
     kPrintPreviewIncognito,
+    [MinVersion=1] kIsolatedWebApp,
   };
 };
 
diff --git a/chromeos/profiles/arm-exp.afdo.newest.txt b/chromeos/profiles/arm-exp.afdo.newest.txt
index 077bc509..84817b3 100644
--- a/chromeos/profiles/arm-exp.afdo.newest.txt
+++ b/chromeos/profiles/arm-exp.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-arm-exp-121-6085.0-1699270938-benchmark-121.0.6110.0-r1-redacted.afdo.xz
+chromeos-chrome-arm-exp-121-6085.0-1699270938-benchmark-121.0.6117.0-r2-redacted.afdo.xz
diff --git a/clank b/clank
index dcf0a93..12e8454 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit dcf0a93ec1e24456a5d335b278c99775a58dc7c6
+Subproject commit 12e84541a2d44aa5535caf8b1a073fa64376c0c6
diff --git a/codelabs/cpp101/solutions/factor.cc b/codelabs/cpp101/solutions/factor.cc
index b937563..3372918 100644
--- a/codelabs/cpp101/solutions/factor.cc
+++ b/codelabs/cpp101/solutions/factor.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <optional>
 #include "base/at_exit.h"
 #include "base/command_line.h"
 #include "base/functional/bind.h"
@@ -12,21 +13,20 @@
 #include "base/test/task_environment.h"
 #include "base/test/test_timeouts.h"
 #include "base/time/time.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
-absl::optional<int> FindNonTrivialFactor(int n) {
+std::optional<int> FindNonTrivialFactor(int n) {
   // Really naive algorithm.
   for (int i = 2; i < n; ++i) {
     if (n % i == 0) {
       return i;
     }
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-void FindNonTrivialFactorHelper(int n, absl::optional<int>* result) {
+void FindNonTrivialFactorHelper(int n, std::optional<int>* result) {
   *result = FindNonTrivialFactor(n);
 }
 
@@ -66,7 +66,7 @@
 
   base::RunLoop run_loop;
 
-  absl::optional<int> result;
+  std::optional<int> result;
   // Notice that we're posting the long-running factoring operation to
   // `base::ThreadPool` to avoid blocking the main thread.
   //
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 8a95249..36c7f0f 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -286,8 +286,13 @@
     "//components/reporting/util:unit_tests",
     "//components/safe_browsing/core/browser:safe_browsing_hats_delegate_unittest",
     "//components/safe_browsing/core/browser:safe_browsing_metrics_collector_unittest",
+    "//components/safe_browsing/core/browser:token_fetcher_unit_tests",
     "//components/safe_browsing/core/browser/hashprefix_realtime:unit_tests",
     "//components/safe_browsing/core/browser/password_protection:unit_tests",
+    "//components/safe_browsing/core/browser/realtime:unit_tests",
+    "//components/safe_browsing/core/browser/tailored_security_service:unit_tests",
+    "//components/safe_browsing/core/browser/utils:unit_tests",
+    "//components/safe_browsing/core/common:unit_tests",
     "//components/safe_search_api:unit_tests",
     "//components/saved_tab_groups:unit_tests",
     "//components/search:unit_tests",
@@ -547,11 +552,6 @@
       "//components/safe_browsing/content/browser/password_protection:password_protection_unittest",
       "//components/safe_browsing/content/browser/triggers:unit_tests",
       "//components/safe_browsing/content/browser/web_ui:unit_tests",
-      "//components/safe_browsing/core/browser:token_fetcher_unit_tests",
-      "//components/safe_browsing/core/browser/realtime:unit_tests",
-      "//components/safe_browsing/core/browser/tailored_security_service:unit_tests",
-      "//components/safe_browsing/core/browser/utils:unit_tests",
-      "//components/safe_browsing/core/common:unit_tests",
       "//components/safety_check:unit_tests",
       "//components/security_interstitials/content:unit_tests",
       "//components/services/paint_preview_compositor:unit_tests",
diff --git a/components/android_autofill/browser/form_data_android.cc b/components/android_autofill/browser/form_data_android.cc
index f7c0f43..7c0eca4 100644
--- a/components/android_autofill/browser/form_data_android.cc
+++ b/components/android_autofill/browser/form_data_android.cc
@@ -8,11 +8,15 @@
 #include <string_view>
 #include <tuple>
 
+#include "base/containers/flat_map.h"
 #include "components/android_autofill/browser/android_autofill_bridge_factory.h"
 #include "components/android_autofill/browser/form_data_android_bridge.h"
 #include "components/android_autofill/browser/form_field_data_android.h"
+#include "components/autofill/core/browser/autofill_field.h"
+#include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/common/form_field_data.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 namespace autofill {
 
@@ -86,25 +90,27 @@
 }
 
 void FormDataAndroid::UpdateFieldTypes(const FormStructure& form_structure) {
-  // This form has been changed after the query starts. Ignore this response,
-  // a new one is on the way.
-  if (form_structure.field_count() != fields_.size())
-    return;
-  auto form_field_data_android = fields_.begin();
-  for (const auto& autofill_field : form_structure) {
-    DCHECK(form_field_data_android->get()->SimilarFieldAs(*autofill_field));
-    std::vector<AutofillType> server_predictions;
-    for (const auto& prediction : autofill_field->server_predictions()) {
-      server_predictions.emplace_back(
-          static_cast<ServerFieldType>(prediction.type()));
+  // Map FieldGlobalId's to their respective AutofillField, this way we can
+  // quickly ignore below FormFieldDataAndroid's with no matching AutofillField.
+  auto autofill_fields = base::MakeFlatMap<FieldGlobalId, const AutofillField*>(
+      form_structure, {}, [](const auto& field) {
+        return std::make_pair(field->global_id(), field.get());
+      });
+  for (auto& form_field_data_android : fields_) {
+    if (auto it = autofill_fields.find(form_field_data_android->global_id());
+        it != autofill_fields.end()) {
+      const AutofillField* autofill_field = it->second;
+      std::vector<AutofillType> server_predictions;
+      for (const auto& prediction : autofill_field->server_predictions()) {
+        server_predictions.emplace_back(
+            ToSafeServerFieldType(prediction.type(), NO_SERVER_DATA));
+      }
+      form_field_data_android->UpdateAutofillTypes(
+          FormFieldDataAndroid::FieldTypes(
+              AutofillType(autofill_field->heuristic_type()),
+              AutofillType(autofill_field->server_type()),
+              autofill_field->ComputedType(), std::move(server_predictions)));
     }
-    form_field_data_android->get()->UpdateAutofillTypes(
-        FormFieldDataAndroid::FieldTypes(
-            AutofillType(autofill_field->heuristic_type()),
-            AutofillType(autofill_field->server_type()),
-            autofill_field->ComputedType(), std::move(server_predictions)));
-    if (++form_field_data_android == fields_.end())
-      break;
   }
 }
 
diff --git a/components/android_autofill/browser/form_data_android_unittest.cc b/components/android_autofill/browser/form_data_android_unittest.cc
index 0db1149f..fe428225 100644
--- a/components/android_autofill/browser/form_data_android_unittest.cc
+++ b/components/android_autofill/browser/form_data_android_unittest.cc
@@ -43,6 +43,7 @@
 }
 
 FormFieldData CreateTestField(std::u16string name = u"SomeName") {
+  static uint64_t renderer_id = 1;
   FormFieldData f;
   f.name = std::move(name);
   f.name_attribute = f.name;
@@ -51,6 +52,7 @@
   f.check_status = FormFieldData::CheckStatus::kChecked;
   f.role = FormFieldData::RoleAttribute::kOther;
   f.is_focusable = true;
+  f.unique_renderer_id = FieldRendererId(renderer_id++);
   return f;
 }
 
@@ -230,6 +232,31 @@
   form_android.UpdateFieldTypes(FormStructure(form));
 }
 
+// Tests that the calls to update field types are propagated to the fields.
+TEST(FormDataAndroidTest, UpdateFieldTypes_ChangedForm) {
+  std::vector<MockFormFieldDataAndroidBridge*> bridges;
+  EnableFieldTestingFactoryAndSaveBridges(&bridges);
+
+  FormData form = CreateTestForm();
+  form.fields = {CreateTestField(), CreateTestField()};
+  FormStructure form_structure(form);
+  ASSERT_EQ(form_structure.field_count(), 2u);
+
+  form.fields.push_back(CreateTestField());
+  std::swap(form.fields.front(), form.fields.back());
+  FormDataAndroid form_android(form);
+
+  ASSERT_THAT(bridges, SizeIs(3));
+  ASSERT_TRUE(bridges[0]);
+  ASSERT_TRUE(bridges[1]);
+  ASSERT_TRUE(bridges[2]);
+
+  EXPECT_CALL(*bridges[0], UpdateFieldTypes).Times(0);
+  EXPECT_CALL(*bridges[1], UpdateFieldTypes);
+  EXPECT_CALL(*bridges[2], UpdateFieldTypes);
+  form_android.UpdateFieldTypes(form_structure);
+}
+
 // Tests that calling `UpdateFieldVisibilities` propagates the visibility to the
 // affected fields and returns their indices.
 TEST(FormDataAndroidTest, UpdateFieldVisibilities) {
diff --git a/components/android_autofill/browser/form_field_data_android.h b/components/android_autofill/browser/form_field_data_android.h
index 9251ae19..bcc69a5 100644
--- a/components/android_autofill/browser/form_field_data_android.h
+++ b/components/android_autofill/browser/form_field_data_android.h
@@ -13,10 +13,11 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/memory/raw_ref.h"
 #include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/common/form_field_data.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 namespace autofill {
 
-struct FormFieldData;
 class FormFieldDataAndroidBridge;
 
 // This class is the native peer of FormFieldData.java. Its intention is
@@ -61,6 +62,8 @@
   bool SimilarFieldAs(const FormFieldData& field) const;
   void UpdateAutofillTypes(FieldTypes field_types);
 
+  FieldGlobalId global_id() { return field_.get().global_id(); }
+
  private:
   // The C++ <-> Java bridge.
   std::unique_ptr<FormFieldDataAndroidBridge> bridge_;
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index aaa307be..75124d28 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -1106,15 +1106,15 @@
     return true;
   }
 
-  if (element == trigger_element) {
-    return false;
-  }
-
   // Skip if there is no value to fill.
   if (field.value.empty() || !field.is_autofilled) {
     return true;
   }
 
+  if (element == trigger_element) {
+    return false;
+  }
+
   // Skip filling previously autofilled fields unless autofill is instructed to
   // override it.
   if (element.IsAutofilled() && !field.force_override) {
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc
index c3d83db0..fa6eb47 100644
--- a/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -376,9 +376,8 @@
           suggestion.main_text.value, suggestion.popup_item_id);
       break;
     case PopupItemId::kVirtualCreditCardEntry:
-      manager_->FillOrPreviewVirtualCardInformation(
-          mojom::ActionPersistence::kPreview, backend_id.value(), query_form_,
-          query_field_,
+      FillAutofillFormData(
+          suggestion.popup_item_id, backend_id, /*is_preview=*/true,
           {.trigger_source =
                TriggerSourceFromSuggestionTriggerSource(trigger_source)});
       break;
@@ -553,10 +552,12 @@
       // PopupItemId::kVirtualCreditCardEntry as a `popup_item_id`. In this
       // case, the payload contains the backend id, which is a GUID that
       // identifies the actually chosen credit card.
-      manager_->FillOrPreviewVirtualCardInformation(
-          mojom::ActionPersistence::kFill,
-          suggestion.GetPayload<Suggestion::BackendId>().value(), query_form_,
-          query_field_, {.trigger_source = AutofillTriggerSource::kPopup});
+      FillAutofillFormData(
+          suggestion.popup_item_id,
+          suggestion.GetPayload<Suggestion::BackendId>(),
+          /*is_preview=*/false,
+          {.trigger_source =
+               TriggerSourceFromSuggestionTriggerSource(trigger_source)});
       break;
     case PopupItemId::kSeePromoCodeDetails:
       manager_->OnSeePromoCodeOfferDetailsSelected(
@@ -837,11 +838,19 @@
                  : mojom::ActionPersistence::kFill;
 
   PersonalDataManager* pdm = manager_->client().GetPersonalDataManager();
-  if (const CreditCard* credit_card =
-          pdm->GetCreditCardByGUID(backend_id.value())) {
-    manager_->FillOrPreviewCreditCardForm(action_persistence, query_form_,
-                                          query_field_, credit_card,
-                                          trigger_details);
+  if (CreditCard* credit_card = pdm->GetCreditCardByGUID(backend_id.value())) {
+    if (popup_item_id == PopupItemId::kVirtualCreditCardEntry) {
+      // Virtual credit cards are not persisted in Chrome, modify record type
+      // locally.
+      CreditCard copy = CreditCard::CreateVirtualCard(*credit_card);
+      manager_->FillOrPreviewCreditCardForm(action_persistence, query_form_,
+                                            query_field_, &copy,
+                                            trigger_details);
+    } else {
+      manager_->FillOrPreviewCreditCardForm(action_persistence, query_form_,
+                                            query_field_, credit_card,
+                                            trigger_details);
+    }
   } else if (const AutofillProfile* profile =
                  pdm->GetProfileByGUID(backend_id.value())) {
     manager_->FillOrPreviewProfileForm(action_persistence, query_form_,
diff --git a/components/autofill/core/browser/autofill_external_delegate_unittest.cc b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
index 61d692c..b5d692f 100644
--- a/components/autofill/core/browser/autofill_external_delegate_unittest.cc
+++ b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -56,8 +56,6 @@
 #include "ui/gfx/geometry/rect_f.h"
 #include "url/origin.h"
 
-using SuggestionPosition = autofill::AutofillPopupDelegate::SuggestionPosition;
-
 namespace autofill {
 
 namespace {
@@ -233,11 +231,11 @@
               (const FormData& form, const FormFieldData& field),
               (override));
   MOCK_METHOD(void,
-              FillOrPreviewVirtualCardInformation,
+              FillOrPreviewCreditCardForm,
               (mojom::ActionPersistence action_persistence,
-               const std::string& guid,
                const FormData& form,
                const FormFieldData& field,
+               const CreditCard* credit_card,
                const AutofillTriggerDetails& trigger_details),
               (override));
 
@@ -1036,15 +1034,17 @@
                                      u"baz foo"),
       kDefaultTriggerSource);
 
+  CreditCard card = test::GetMaskedServerCard();
+  personal_data().AddCreditCard(card);
   // Ensure selecting a virtual card entry will cause any previews to
   // get cleared.
   EXPECT_CALL(*autofill_driver_, RendererShouldClearPreviewedForm());
   EXPECT_CALL(*browser_autofill_manager_,
-              FillOrPreviewVirtualCardInformation(
-                  mojom::ActionPersistence::kPreview, _, _, _, _));
-  external_delegate_->DidSelectSuggestion(
-      test::CreateAutofillSuggestion(PopupItemId::kVirtualCreditCardEntry),
-      kDefaultTriggerSource);
+              FillOrPreviewCreditCardForm(mojom::ActionPersistence::kPreview, _,
+                                          _, _, _));
+  Suggestion suggestion(PopupItemId::kVirtualCreditCardEntry);
+  suggestion.payload = Suggestion::BackendId(card.guid());
+  external_delegate_->DidSelectSuggestion(suggestion, kDefaultTriggerSource);
 }
 
 // Test that the popup is hidden once we are done editing the autofill field.
@@ -1129,7 +1129,7 @@
   external_delegate_->DidAcceptSuggestion(
       suggestion, SuggestionPosition{.row = 0}, kDefaultTriggerSource);
 
-  histogram_tester.ExpectUniqueSample("Autofill.FillingMethodUsed.",
+  histogram_tester.ExpectUniqueSample("Autofill.FillingMethodUsed",
                                       params.target_metric, 1);
 }
 
@@ -1920,20 +1920,26 @@
 // virtual card after users accept the suggestion to use a virtual card.
 TEST_F(AutofillExternalDelegateUnitTest, AcceptVirtualCardOptionItem) {
   FormData form;
-  EXPECT_CALL(*browser_autofill_manager_,
-              FillOrPreviewVirtualCardInformation(
-                  mojom::ActionPersistence::kFill, _, _, _, _));
+  CreditCard card = test::GetMaskedServerCard();
+  personal_data().AddCreditCard(card);
+  EXPECT_CALL(
+      *browser_autofill_manager_,
+      FillOrPreviewCreditCardForm(mojom::ActionPersistence::kFill, _, _, _, _));
+  Suggestion suggestion(PopupItemId::kVirtualCreditCardEntry);
+  suggestion.payload = Suggestion::BackendId(card.guid());
   external_delegate_->DidAcceptSuggestion(
-      Suggestion(PopupItemId::kVirtualCreditCardEntry),
-      SuggestionPosition{.row = 0}, kDefaultTriggerSource);
+      suggestion, SuggestionPosition{.row = 0}, kDefaultTriggerSource);
 }
 
 TEST_F(AutofillExternalDelegateUnitTest, SelectVirtualCardOptionItem) {
+  CreditCard card = test::GetMaskedServerCard();
+  personal_data().AddCreditCard(card);
   EXPECT_CALL(*browser_autofill_manager_,
-              FillOrPreviewVirtualCardInformation(
-                  mojom::ActionPersistence::kPreview, _, _, _, _));
-  external_delegate_->DidSelectSuggestion(
-      Suggestion(PopupItemId::kVirtualCreditCardEntry), kDefaultTriggerSource);
+              FillOrPreviewCreditCardForm(mojom::ActionPersistence::kPreview, _,
+                                          _, _, _));
+  Suggestion suggestion(PopupItemId::kVirtualCreditCardEntry);
+  suggestion.payload = Suggestion::BackendId(card.guid());
+  external_delegate_->DidSelectSuggestion(suggestion, kDefaultTriggerSource);
 }
 
 TEST_F(AutofillExternalDelegateUnitTest,
diff --git a/components/autofill/core/browser/autofill_profile_sync_util.cc b/components/autofill/core/browser/autofill_profile_sync_util.cc
index da74f828..8e6fc7f 100644
--- a/components/autofill/core/browser/autofill_profile_sync_util.cc
+++ b/components/autofill/core/browser/autofill_profile_sync_util.cc
@@ -225,8 +225,15 @@
       UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_STREET_LOCATION)));
   specifics->set_address_home_subpremise_name(
       UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_SUBPREMISE)));
-  specifics->set_address_home_apt_num(
-      UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_APT_NUM)));
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillEnableSupportForApartmentNumbers)) {
+    specifics->set_address_home_apt(
+        UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_APT)));
+    specifics->set_address_home_apt_num(
+        UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_APT_NUM)));
+    specifics->set_address_home_apt_type(
+        UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_APT_TYPE)));
+  }
   specifics->set_address_home_floor(
       UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_FLOOR)));
 
@@ -306,9 +313,18 @@
   specifics->set_address_home_subpremise_name_status(
       ConvertProfileToSpecificsVerificationStatus(
           entry.GetVerificationStatus(ADDRESS_HOME_SUBPREMISE)));
-  specifics->set_address_home_apt_num_status(
-      ConvertProfileToSpecificsVerificationStatus(
-          entry.GetVerificationStatus(ADDRESS_HOME_APT_NUM)));
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillEnableSupportForApartmentNumbers)) {
+    specifics->set_address_home_apt_status(
+        ConvertProfileToSpecificsVerificationStatus(
+            entry.GetVerificationStatus(ADDRESS_HOME_APT)));
+    specifics->set_address_home_apt_num_status(
+        ConvertProfileToSpecificsVerificationStatus(
+            entry.GetVerificationStatus(ADDRESS_HOME_APT_NUM)));
+    specifics->set_address_home_apt_type_status(
+        ConvertProfileToSpecificsVerificationStatus(
+            entry.GetVerificationStatus(ADDRESS_HOME_APT_TYPE)));
+  }
   specifics->set_address_home_floor_status(
       ConvertProfileToSpecificsVerificationStatus(
           entry.GetVerificationStatus(ADDRESS_HOME_FLOOR)));
@@ -583,10 +599,21 @@
       ConvertSpecificsToProfileVerificationStatus(
           specifics.address_home_subpremise_name_status()));
 
-  profile->SetRawInfoWithVerificationStatus(
-      ADDRESS_HOME_APT_NUM, UTF8ToUTF16(specifics.address_home_apt_num()),
-      ConvertSpecificsToProfileVerificationStatus(
-          specifics.address_home_apt_num_status()));
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillEnableSupportForApartmentNumbers)) {
+    profile->SetRawInfoWithVerificationStatus(
+        ADDRESS_HOME_APT, UTF8ToUTF16(specifics.address_home_apt()),
+        ConvertSpecificsToProfileVerificationStatus(
+            specifics.address_home_apt_status()));
+    profile->SetRawInfoWithVerificationStatus(
+        ADDRESS_HOME_APT_NUM, UTF8ToUTF16(specifics.address_home_apt_num()),
+        ConvertSpecificsToProfileVerificationStatus(
+            specifics.address_home_apt_num_status()));
+    profile->SetRawInfoWithVerificationStatus(
+        ADDRESS_HOME_APT_TYPE, UTF8ToUTF16(specifics.address_home_apt_type()),
+        ConvertSpecificsToProfileVerificationStatus(
+            specifics.address_home_apt_type_status()));
+  }
 
   // Set birthdate-related fields.
   profile->SetRawInfoAsInt(BIRTHDATE_DAY, specifics.birthdate_day());
diff --git a/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc b/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc
index 82cdf2bc..30b332d 100644
--- a/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc
+++ b/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc
@@ -163,12 +163,14 @@
   profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_OVERFLOW_AND_LANDMARK,
                                            u"apto. 1501, Top Hill Tower",
                                            VerificationStatus::kFormatted);
-  profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_SUBPREMISE, u"1501",
-                                           VerificationStatus::kFormatted);
-  profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_APT, u"1501",
-                                           VerificationStatus::kFormatted);
+  profile.SetRawInfoWithVerificationStatus(
+      ADDRESS_HOME_SUBPREMISE, u"apto. 1501", VerificationStatus::kFormatted);
+  profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_APT, u"apto. 1501",
+                                           VerificationStatus::kParsed);
   profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_APT_NUM, u"1501",
                                            VerificationStatus::kParsed);
+  profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_APT_TYPE, u"apto.",
+                                           VerificationStatus::kParsed);
 
   // Reset unused tokens from the default profile.
   profile.ClearFields({ADDRESS_HOME_FLOOR, ADDRESS_HOME_ADMIN_LEVEL2,
@@ -409,6 +411,16 @@
       sync_pb::
           AutofillProfileSpecifics_VerificationStatus_VERIFICATION_STATUS_UNSPECIFIED);
 
+  specifics.set_address_home_apt("");
+  specifics.set_address_home_apt_status(
+      sync_pb::
+          AutofillProfileSpecifics_VerificationStatus_VERIFICATION_STATUS_UNSPECIFIED);
+
+  specifics.set_address_home_apt_type("");
+  specifics.set_address_home_apt_type_status(
+      sync_pb::
+          AutofillProfileSpecifics_VerificationStatus_VERIFICATION_STATUS_UNSPECIFIED);
+
   return specifics;
 }
 
@@ -465,14 +477,22 @@
   specifics.set_address_home_overflow_and_landmark_status(
       sync_pb::AutofillProfileSpecifics_VerificationStatus_FORMATTED);
 
-  specifics.set_address_home_subpremise_name("1501");
+  specifics.set_address_home_subpremise_name("apto. 1501");
   specifics.set_address_home_subpremise_name_status(
       sync_pb::AutofillProfileSpecifics_VerificationStatus_FORMATTED);
 
+  specifics.set_address_home_apt("apto. 1501");
+  specifics.set_address_home_apt_status(
+      sync_pb::AutofillProfileSpecifics_VerificationStatus_PARSED);
+
   specifics.set_address_home_apt_num("1501");
   specifics.set_address_home_apt_num_status(
       sync_pb::AutofillProfileSpecifics_VerificationStatus_PARSED);
 
+  specifics.set_address_home_apt_type("apto.");
+  specifics.set_address_home_apt_type_status(
+      sync_pb::AutofillProfileSpecifics_VerificationStatus_PARSED);
+
   // Reset unused tokens from the default info.
   specifics.set_address_home_floor("");
   specifics.set_address_home_floor_status(
@@ -566,6 +586,10 @@
   specifics.set_address_home_subpremise_name_status(
       sync_pb::AutofillProfileSpecifics_VerificationStatus_FORMATTED);
 
+  specifics.set_address_home_apt("34");
+  specifics.set_address_home_apt_status(
+      sync_pb::AutofillProfileSpecifics_VerificationStatus_FORMATTED);
+
   specifics.set_address_home_apt_num("34");
   specifics.set_address_home_apt_num_status(
       sync_pb::AutofillProfileSpecifics_VerificationStatus_PARSED);
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc
index 27656ac..918a0ae7 100644
--- a/components/autofill/core/browser/autofill_test_utils.cc
+++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -253,46 +253,6 @@
   return profile;
 }
 
-AutofillProfile GetServerProfile() {
-  AutofillProfile profile(AutofillProfile::SERVER_PROFILE, "id1");
-  // Note: server profiles don't have email addresses and only have full names.
-  SetProfileInfo(&profile, "", "", "", "", "Google, Inc.", "123 Fake St.",
-                 "Apt. 42", "Mountain View", "California", "94043", "US",
-                 "1.800.555.1234");
-
-  profile.SetInfo(NAME_FULL, u"John K. Doe", "en");
-  profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, u"CEDEX");
-  profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, u"Santa Clara");
-
-  profile.set_language_code("en");
-  profile.set_use_count(7);
-  profile.set_use_date(base::Time::FromTimeT(54321));
-
-  profile.GenerateServerProfileIdentifier();
-
-  return profile;
-}
-
-AutofillProfile GetServerProfile2() {
-  AutofillProfile profile(AutofillProfile::SERVER_PROFILE, "id2");
-  // Note: server profiles don't have email addresses.
-  SetProfileInfo(&profile, "", "", "", "", "Main, Inc.", "4323 Wrong St.",
-                 "Apt. 1032", "Sunnyvale", "California", "10011", "US",
-                 "+1 514-123-1234");
-
-  profile.SetInfo(NAME_FULL, u"Jim S. Bristow", "en");
-  profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, u"XEDEC");
-  profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, u"Santa Monica");
-
-  profile.set_language_code("en");
-  profile.set_use_count(14);
-  profile.set_use_date(base::Time::FromTimeT(98765));
-
-  profile.GenerateServerProfileIdentifier();
-
-  return profile;
-}
-
 void SetProfileCategory(
     AutofillProfile& profile,
     autofill_metrics::AutofillProfileSourceCategory category) {
diff --git a/components/autofill/core/browser/autofill_test_utils.h b/components/autofill/core/browser/autofill_test_utils.h
index 12b8d1af..bf911684 100644
--- a/components/autofill/core/browser/autofill_test_utils.h
+++ b/components/autofill/core/browser/autofill_test_utils.h
@@ -126,12 +126,6 @@
 // Returns an incomplete profile of dummy info, different to the above.
 AutofillProfile GetIncompleteProfile2();
 
-// Returns a server profile full of dummy info.
-AutofillProfile GetServerProfile();
-
-// Returns a server profile full of dummy info, different to the above.
-AutofillProfile GetServerProfile2();
-
 // Sets the `profile`s source and initial creator to match `category`.
 void SetProfileCategory(
     AutofillProfile& profile,
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc
index 0a97390c..d9da8fb9 100644
--- a/components/autofill/core/browser/browser_autofill_manager.cc
+++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -1373,6 +1373,7 @@
   if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
     return;
 
+  // TODO(crbug.com/1330108): Accept credit card by reference.
   credit_card_ = credit_card ? *credit_card : CreditCard();
   bool is_preview = action_persistence != mojom::ActionPersistence::kFill;
   bool is_virtual_card_standalone_cvc =
@@ -1524,27 +1525,6 @@
                              /*is_refill=*/false);
 }
 
-void BrowserAutofillManager::FillOrPreviewVirtualCardInformation(
-    mojom::ActionPersistence action_persistence,
-    const std::string& guid,
-    const FormData& form,
-    const FormFieldData& field,
-    const AutofillTriggerDetails& trigger_details) {
-  if (!IsValidFormData(form) || !IsValidFormFieldData(field) ||
-      !RefreshDataModels()) {
-    return;
-  }
-
-  const CreditCard* credit_card =
-      client().GetPersonalDataManager()->GetCreditCardByGUID(guid);
-  if (credit_card) {
-    CreditCard copy = *credit_card;
-    copy.set_record_type(CreditCard::RecordType::kVirtualCard);
-    FillOrPreviewCreditCardForm(action_persistence, form, field, &copy,
-                                trigger_details);
-  }
-}
-
 void BrowserAutofillManager::OnFocusNoLongerOnFormImpl(
     bool had_interacted_form) {
   // For historical reasons, Chrome takes action on this message only if focus
@@ -1730,9 +1710,6 @@
   }
 
   if (profile) {
-    if (profile->record_type() != AutofillProfile::LOCAL_PROFILE)
-      return false;
-
     if (title) {
       std::u16string street_address = profile->GetRawInfo(ADDRESS_HOME_CITY);
       if (!street_address.empty())
@@ -1758,13 +1735,9 @@
     return credit_card_access_manager_->DeleteCard(credit_card);
   }
 
-  const AutofillProfile* profile = GetProfile(backend_id);
-  if (profile) {
-    bool is_local = profile->record_type() == AutofillProfile::LOCAL_PROFILE;
-    if (is_local)
-      client().GetPersonalDataManager()->RemoveByGUID(profile->guid());
-
-    return is_local;
+  if (const AutofillProfile* profile = GetProfile(backend_id)) {
+    client().GetPersonalDataManager()->RemoveByGUID(profile->guid());
+    return true;
   }
 
   return false;  // The ID was valid. The entry may have been deleted in a race.
@@ -2266,20 +2239,9 @@
   credit_card_access_manager_->UpdateCreditCardFormEventLogger();
 
   // Updating the FormEventLogger for addresses.
-  {
-    size_t server_record_type_count = 0;
-    size_t local_record_type_count = 0;
-    for (AutofillProfile* profile : profiles) {
-      if (profile->record_type() == AutofillProfile::LOCAL_PROFILE)
-        local_record_type_count++;
-      else if (profile->record_type() == AutofillProfile::SERVER_PROFILE)
-        server_record_type_count++;
-    }
-    address_form_event_logger_->set_server_record_type_count(
-        server_record_type_count);
-    address_form_event_logger_->set_local_record_type_count(
-        local_record_type_count);
-  }
+  address_form_event_logger_->set_local_record_type_count(profiles.size());
+  // TODO(crbug.com/1457187): Server addresses don't exist anymore. Remove.
+  address_form_event_logger_->set_server_record_type_count(0);
 
   return !profiles.empty() ||
          !client().GetPersonalDataManager()->GetCreditCards().empty();
diff --git a/components/autofill/core/browser/browser_autofill_manager.h b/components/autofill/core/browser/browser_autofill_manager.h
index f85ab7a..349477d 100644
--- a/components/autofill/core/browser/browser_autofill_manager.h
+++ b/components/autofill/core/browser/browser_autofill_manager.h
@@ -182,16 +182,6 @@
       const CreditCard* credit_card,
       const AutofillTriggerDetails& trigger_details);
 
-  // Fetches the related virtual card information given the related actual card
-  // |guid| and fills the information into the form.
-  // TODO(crbug.com/1330108): Clean up the API.
-  virtual void FillOrPreviewVirtualCardInformation(
-      mojom::ActionPersistence action_persistence,
-      const std::string& guid,
-      const FormData& form,
-      const FormFieldData& field,
-      const AutofillTriggerDetails& trigger_details);
-
   // Returns true if the value/identifier is deletable. Fills out
   // |title| and |body| with relevant user-facing text.
   bool GetDeletionConfirmationText(const std::u16string& value,
diff --git a/components/autofill/core/browser/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
index b19fc5c..7a11a1e 100644
--- a/components/autofill/core/browser/browser_autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
@@ -853,15 +853,15 @@
 
   FormData PreviewVirtualCardDataAndGetResults(
       mojom::ActionPersistence action_persistence,
-      const std::string& guid,
       const FormData& input_form,
-      const FormFieldData& input_field) {
+      const FormFieldData& input_field,
+      const CreditCard& virtual_card) {
     FormData response_data;
     EXPECT_CALL(*autofill_driver_, ApplyFormAction)
         .WillOnce((DoAll(SaveArg<2>(&response_data),
                          Return(std::vector<FieldGlobalId>{}))));
-    browser_autofill_manager_->FillOrPreviewVirtualCardInformation(
-        action_persistence, guid, input_form, input_field,
+    browser_autofill_manager_->FillOrPreviewCreditCardForm(
+        action_persistence, input_form, input_field, &virtual_card,
         {.trigger_source = AutofillTriggerSource::kPopup});
     return response_data;
   }
@@ -4560,8 +4560,7 @@
   FormsSeen({form});
 
   FormData response_data = PreviewVirtualCardDataAndGetResults(
-      mojom::ActionPersistence::kPreview, virtual_card.guid(), form,
-      form.fields[1]);
+      mojom::ActionPersistence::kPreview, form, form.fields[1], virtual_card);
 
   std::u16string expected_cardholder_name = u"Lorem Ipsum";
   // Virtual card number using obfuscated dots only: Virtual card Mastercard
diff --git a/components/autofill/core/browser/contact_info_sync_util.cc b/components/autofill/core/browser/contact_info_sync_util.cc
index 5f93e26..ad9f3a2 100644
--- a/components/autofill/core/browser/contact_info_sync_util.cc
+++ b/components/autofill/core/browser/contact_info_sync_util.cc
@@ -254,7 +254,12 @@
   s.Set(specifics.mutable_address_street_location(),
         ADDRESS_HOME_STREET_LOCATION);
   s.Set(specifics.mutable_address_subpremise_name(), ADDRESS_HOME_SUBPREMISE);
-  s.Set(specifics.mutable_address_apt_num(), ADDRESS_HOME_APT_NUM);
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillEnableSupportForApartmentNumbers)) {
+    s.Set(specifics.mutable_address_apt(), ADDRESS_HOME_APT);
+    s.Set(specifics.mutable_address_apt_num(), ADDRESS_HOME_APT_NUM);
+    s.Set(specifics.mutable_address_apt_type(), ADDRESS_HOME_APT_TYPE);
+  }
   s.Set(specifics.mutable_address_floor(), ADDRESS_HOME_FLOOR);
   if (base::FeatureList::IsEnabled(
           features::kAutofillEnableSupportForAddressOverflow)) {
@@ -386,7 +391,12 @@
   s.Set(specifics.address_thoroughfare_number(), ADDRESS_HOME_HOUSE_NUMBER);
   s.Set(specifics.address_street_location(), ADDRESS_HOME_STREET_LOCATION);
   s.Set(specifics.address_subpremise_name(), ADDRESS_HOME_SUBPREMISE);
-  s.Set(specifics.address_apt_num(), ADDRESS_HOME_APT_NUM);
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillEnableSupportForApartmentNumbers)) {
+    s.Set(specifics.address_apt(), ADDRESS_HOME_APT);
+    s.Set(specifics.address_apt_num(), ADDRESS_HOME_APT_NUM);
+    s.Set(specifics.address_apt_type(), ADDRESS_HOME_APT_TYPE);
+  }
   s.Set(specifics.address_floor(), ADDRESS_HOME_FLOOR);
   if (base::FeatureList::IsEnabled(
           features::kAutofillEnableSupportForAddressOverflow)) {
@@ -457,147 +467,118 @@
   if (d.Delete(trimmed_specifics.mutable_name_honorific())) {
     trimmed_specifics.clear_name_honorific();
   }
-
   if (d.Delete(trimmed_specifics.mutable_name_first())) {
     trimmed_specifics.clear_name_first();
   }
-
   if (d.Delete(trimmed_specifics.mutable_name_middle())) {
     trimmed_specifics.clear_name_middle();
   }
-
   if (d.Delete(trimmed_specifics.mutable_name_last())) {
     trimmed_specifics.clear_name_last();
   }
-
   if (d.Delete(trimmed_specifics.mutable_name_last_first())) {
     trimmed_specifics.clear_name_last_first();
   }
-
   if (d.Delete(trimmed_specifics.mutable_name_last_conjunction())) {
     trimmed_specifics.clear_name_last_conjunction();
   }
-
   if (d.Delete(trimmed_specifics.mutable_name_last_second())) {
     trimmed_specifics.clear_name_last_second();
   }
-
   if (d.Delete(trimmed_specifics.mutable_name_full())) {
     trimmed_specifics.clear_name_full();
   }
-
   if (d.Delete(trimmed_specifics.mutable_name_full_with_honorific())) {
     trimmed_specifics.clear_name_full_with_honorific();
   }
-
   // Delete address-related values and statuses.;
   if (d.Delete(trimmed_specifics.mutable_address_city())) {
     trimmed_specifics.clear_address_city();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_state())) {
     trimmed_specifics.clear_address_state();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_zip())) {
     trimmed_specifics.clear_address_zip();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_country())) {
     trimmed_specifics.clear_address_country();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_street_address())) {
     trimmed_specifics.clear_address_street_address();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_sorting_code())) {
     trimmed_specifics.clear_address_sorting_code();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_dependent_locality())) {
     trimmed_specifics.clear_address_dependent_locality();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_thoroughfare_name())) {
     trimmed_specifics.clear_address_thoroughfare_name();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_thoroughfare_number())) {
     trimmed_specifics.clear_address_thoroughfare_number();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_street_location())) {
     trimmed_specifics.clear_address_street_location();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_subpremise_name())) {
     trimmed_specifics.clear_address_subpremise_name();
   }
-
+  if (d.Delete(trimmed_specifics.mutable_address_apt())) {
+    trimmed_specifics.clear_address_apt();
+  }
   if (d.Delete(trimmed_specifics.mutable_address_apt_num())) {
     trimmed_specifics.clear_address_apt_num();
   }
-
+  if (d.Delete(trimmed_specifics.mutable_address_apt_type())) {
+    trimmed_specifics.clear_address_apt_type();
+  }
   if (d.Delete(trimmed_specifics.mutable_address_floor())) {
     trimmed_specifics.clear_address_floor();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_overflow())) {
     trimmed_specifics.clear_address_overflow();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_landmark())) {
     trimmed_specifics.clear_address_landmark();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_between_streets())) {
     trimmed_specifics.clear_address_between_streets();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_between_streets_1())) {
     trimmed_specifics.clear_address_between_streets_1();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_between_streets_2())) {
     trimmed_specifics.clear_address_between_streets_2();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_admin_level_2())) {
     trimmed_specifics.clear_address_admin_level_2();
   }
-
   if (d.Delete(
           trimmed_specifics.mutable_address_between_streets_or_landmark())) {
     trimmed_specifics.clear_address_between_streets_or_landmark();
   }
-
   if (d.Delete(trimmed_specifics.mutable_address_overflow_and_landmark())) {
     trimmed_specifics.clear_address_overflow_and_landmark();
   }
-
   // Delete email, phone and company values and statuses.
   if (d.Delete(trimmed_specifics.mutable_email_address())) {
     trimmed_specifics.clear_email_address();
   }
-
   if (d.Delete(trimmed_specifics.mutable_company_name())) {
     trimmed_specifics.clear_company_name();
   }
-
   if (d.Delete(trimmed_specifics.mutable_phone_home_whole_number())) {
     trimmed_specifics.clear_phone_home_whole_number();
   }
-
   // Delete birthdate-related values and statuses.
   if (d.Delete(trimmed_specifics.mutable_birthdate_day())) {
     trimmed_specifics.clear_birthdate_day();
   }
-
   if (d.Delete(trimmed_specifics.mutable_birthdate_month())) {
     trimmed_specifics.clear_birthdate_month();
   }
-
   if (d.Delete(trimmed_specifics.mutable_birthdate_year())) {
     trimmed_specifics.clear_birthdate_year();
   }
diff --git a/components/autofill/core/browser/contact_info_sync_util_unittest.cc b/components/autofill/core/browser/contact_info_sync_util_unittest.cc
index 823ca6df..dd34bfa 100644
--- a/components/autofill/core/browser/contact_info_sync_util_unittest.cc
+++ b/components/autofill/core/browser/contact_info_sync_util_unittest.cc
@@ -153,12 +153,14 @@
   profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_OVERFLOW_AND_LANDMARK,
                                            u"apto. 1501, Top Hill Tower",
                                            VerificationStatus::kFormatted);
-  profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_SUBPREMISE, u"1501",
-                                           VerificationStatus::kFormatted);
-  profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_APT, u"1501",
-                                           VerificationStatus::kFormatted);
+  profile.SetRawInfoWithVerificationStatus(
+      ADDRESS_HOME_SUBPREMISE, u"apto. 1501", VerificationStatus::kFormatted);
+  profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_APT, u"apto. 1501",
+                                           VerificationStatus::kParsed);
   profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_APT_NUM, u"1501",
                                            VerificationStatus::kParsed);
+  profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_APT_TYPE, u"apto",
+                                           VerificationStatus::kParsed);
 
   // Reset unused tokens from the default profile.
   profile.ClearFields({ADDRESS_HOME_FLOOR, ADDRESS_HOME_ADMIN_LEVEL2,
@@ -322,6 +324,10 @@
            ContactInfoSpecifics::VERIFICATION_STATUS_UNSPECIFIED);
   SetToken(specifics.mutable_address_overflow_and_landmark(), "",
            ContactInfoSpecifics::VERIFICATION_STATUS_UNSPECIFIED);
+  SetToken(specifics.mutable_address_apt(), "",
+           ContactInfoSpecifics::VERIFICATION_STATUS_UNSPECIFIED);
+  SetToken(specifics.mutable_address_apt_type(), "",
+           ContactInfoSpecifics::VERIFICATION_STATUS_UNSPECIFIED);
 
   // All of the following types don't store verification statuses in
   // AutofillProfile. This corresponds to `VERIFICATION_STATUS_UNSPECIFIED`.
@@ -385,10 +391,14 @@
            ContactInfoSpecifics::FORMATTED);
   SetToken(specifics.mutable_address_overflow_and_landmark(),
            "apto. 1501, Top Hill Tower", ContactInfoSpecifics::FORMATTED);
-  SetToken(specifics.mutable_address_subpremise_name(), "1501",
+  SetToken(specifics.mutable_address_subpremise_name(), "apto. 1501",
            ContactInfoSpecifics::FORMATTED);
+  SetToken(specifics.mutable_address_apt(), "apto. 1501",
+           ContactInfoSpecifics::PARSED);
   SetToken(specifics.mutable_address_apt_num(), "1501",
            ContactInfoSpecifics::PARSED);
+  SetToken(specifics.mutable_address_apt_type(), "apto",
+           ContactInfoSpecifics::PARSED);
 
   // Reset unused tokens from the default info.
   SetToken(specifics.mutable_address_floor(), "",
@@ -443,6 +453,8 @@
            ContactInfoSpecifics::PARSED);
   SetToken(specifics.mutable_address_subpremise_name(), "Piso 4 - 34",
            ContactInfoSpecifics::FORMATTED);
+  SetToken(specifics.mutable_address_apt(), "34",
+           ContactInfoSpecifics::FORMATTED);
   SetToken(specifics.mutable_address_apt_num(), "34",
            ContactInfoSpecifics::PARSED);
   SetToken(specifics.mutable_address_floor(), "4",
diff --git a/components/autofill/core/browser/data_model/autofill_metadata.cc b/components/autofill/core/browser/data_model/autofill_metadata.cc
index 668f7fa3..f6dde71 100644
--- a/components/autofill/core/browser/data_model/autofill_metadata.cc
+++ b/components/autofill/core/browser/data_model/autofill_metadata.cc
@@ -14,7 +14,6 @@
 bool AutofillMetadata::operator==(const AutofillMetadata& metadata) const {
   return id == metadata.id && use_count == metadata.use_count &&
          use_date == metadata.use_date &&
-         has_converted == metadata.has_converted &&
          billing_address_id == metadata.billing_address_id;
 }
 
@@ -28,8 +27,7 @@
 
 std::ostream& operator<<(std::ostream& os, const AutofillMetadata& metadata) {
   return os << metadata.id << " " << metadata.use_count << " "
-            << metadata.use_date << " " << metadata.has_converted << " "
-            << metadata.billing_address_id;
+            << metadata.use_date << " " << metadata.billing_address_id;
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/data_model/autofill_metadata.h b/components/autofill/core/browser/data_model/autofill_metadata.h
index 1369488..d7f9a7d 100644
--- a/components/autofill/core/browser/data_model/autofill_metadata.h
+++ b/components/autofill/core/browser/data_model/autofill_metadata.h
@@ -35,10 +35,6 @@
   // The last time the model was used.
   base::Time use_date;
 
-  // Only useful for SERVER_PROFILEs. Whether the server profile has been
-  // converted to a local profile.
-  bool has_converted = false;
-
   // Only useful for SERVER_CARDs. The identifier of the billing address for the
   // card.
   std::string billing_address_id;
diff --git a/components/autofill/core/browser/data_model/autofill_profile.cc b/components/autofill/core/browser/data_model/autofill_profile.cc
index 6c5a5ba..ae2f691 100644
--- a/components/autofill/core/browser/data_model/autofill_profile.cc
+++ b/components/autofill/core/browser/data_model/autofill_profile.cc
@@ -29,7 +29,6 @@
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/address.h"
-#include "components/autofill/core/browser/data_model/autofill_metadata.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
 #include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h"
 #include "components/autofill/core/browser/data_model/contact_info.h"
@@ -233,8 +232,6 @@
     : guid_(guid),
       phone_number_(this),
       address_(country_code),
-      record_type_(LOCAL_PROFILE),
-      has_converted_(false),
       source_(source),
       initial_creator_id_(kInitialCreatorOrModifierChrome),
       last_modifier_id_(kInitialCreatorOrModifierChrome),
@@ -245,21 +242,6 @@
                       source,
                       country_code) {}
 
-// TODO(crbug.com/1177366): Remove this constructor.
-AutofillProfile::AutofillProfile(RecordType type,
-                                 const std::string& server_id,
-                                 AddressCountryCode country_code)
-    : guid_(""),  // Server profiles are identified by a `server_id_`.
-      phone_number_(this),
-      address_(country_code),
-      server_id_(server_id),
-      record_type_(type),
-      has_converted_(false),
-      source_(Source::kLocalOrSyncable),
-      token_quality_(this) {
-  DCHECK(type == SERVER_PROFILE);
-}
-
 AutofillProfile::AutofillProfile(const AutofillProfile& profile)
     : phone_number_(this),
       address_(profile.GetAddress()),
@@ -281,8 +263,6 @@
 
   set_profile_label(profile.profile_label());
 
-  record_type_ = profile.record_type_;
-
   name_ = profile.name_;
   email_ = profile.email_;
   company_ = profile.company_;
@@ -293,9 +273,6 @@
   address_ = profile.address_;
   set_language_code(profile.language_code());
 
-  server_id_ = profile.server_id();
-  has_converted_ = profile.has_converted();
-
   source_ = profile.source_;
   initial_creator_id_ = profile.initial_creator_id_;
   last_modifier_id_ = profile.last_modifier_id_;
@@ -395,13 +372,6 @@
 }
 #endif  // BUILDFLAG(IS_ANDROID)
 
-AutofillMetadata AutofillProfile::GetMetadata() const {
-  AutofillMetadata metadata = AutofillDataModel::GetMetadata();
-  metadata.id = (record_type_ == LOCAL_PROFILE ? guid() : server_id_);
-  metadata.has_converted = has_converted_;
-  return metadata;
-}
-
 double AutofillProfile::GetRankingScore(base::Time current_time) const {
   if (base::FeatureList::IsEnabled(
           features::kAutofillEnableRankingFormulaAddressProfiles)) {
@@ -416,18 +386,6 @@
   return AutofillDataModel::GetRankingScore(current_time);
 }
 
-bool AutofillProfile::SetMetadata(const AutofillMetadata& metadata) {
-  // Make sure the ids matches.
-  if (metadata.id != (record_type_ == LOCAL_PROFILE ? guid() : server_id_))
-    return false;
-
-  if (!AutofillDataModel::SetMetadata(metadata))
-    return false;
-
-  has_converted_ = metadata.has_converted;
-  return true;
-}
-
 void AutofillProfile::GetMatchingTypes(
     const std::u16string& text,
     const std::string& app_locale,
@@ -1010,26 +968,6 @@
   return label;
 }
 
-void AutofillProfile::GenerateServerProfileIdentifier() {
-  DCHECK_EQ(SERVER_PROFILE, record_type());
-  std::u16string contents = GetRawInfo(NAME_FIRST);
-  contents.append(GetRawInfo(NAME_MIDDLE));
-  contents.append(GetRawInfo(NAME_LAST));
-  contents.append(GetRawInfo(EMAIL_ADDRESS));
-  contents.append(GetRawInfo(COMPANY_NAME));
-  contents.append(GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
-  contents.append(GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY));
-  contents.append(GetRawInfo(ADDRESS_HOME_CITY));
-  contents.append(GetRawInfo(ADDRESS_HOME_STATE));
-  contents.append(GetRawInfo(ADDRESS_HOME_ZIP));
-  contents.append(GetRawInfo(ADDRESS_HOME_SORTING_CODE));
-  contents.append(GetRawInfo(ADDRESS_HOME_COUNTRY));
-  contents.append(GetRawInfo(PHONE_HOME_WHOLE_NUMBER));
-  std::string contents_utf8 = UTF16ToUTF8(contents);
-  contents_utf8.append(language_code());
-  server_id_ = base::SHA1HashString(contents_utf8);
-}
-
 void AutofillProfile::RecordAndLogUse() {
   const base::Time now = AutofillClock::Now();
   const base::TimeDelta time_since_last_used = now - use_date();
@@ -1209,12 +1147,8 @@
 }
 
 std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) {
-  os << (profile.record_type() == AutofillProfile::LOCAL_PROFILE
-             ? profile.guid()
-             : base::HexEncode(profile.server_id().data(),
-                               profile.server_id().size()))
-     << " label: " << profile.profile_label() << " " << profile.has_converted()
-     << " " << profile.use_count() << " " << profile.use_date() << " "
+  os << profile.guid() << " label: " << profile.profile_label() << " "
+     << profile.use_count() << " " << profile.use_date() << " "
      << profile.language_code() << std::endl;
 
   // Lambda to print the value and verification status for |type|.
diff --git a/components/autofill/core/browser/data_model/autofill_profile.h b/components/autofill/core/browser/data_model/autofill_profile.h
index 71944ac..864848f 100644
--- a/components/autofill/core/browser/data_model/autofill_profile.h
+++ b/components/autofill/core/browser/data_model/autofill_profile.h
@@ -33,23 +33,12 @@
 
 class AutofillProfileComparator;
 
-struct AutofillMetadata;
-
 // A collection of FormGroups stored in a profile.  AutofillProfile also
 // implements the FormGroup interface so that owners of this object can request
 // form information from the profile, and the profile will delegate the request
 // to the requested form group type.
 class AutofillProfile : public AutofillDataModel {
  public:
-  // `RecordType` is deprecated and `SERVER_PROFILE` essentially unused.
-  // TODO(crbug.com/1177366): Remove
-  enum RecordType {
-    // A profile stored and editable locally.
-    LOCAL_PROFILE,
-    // A profile synced down from the server. These are read-only locally.
-    SERVER_PROFILE,
-  };
-
   // Describes where the profile is stored and how it is synced.
   // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.autofill
   enum class Source {
@@ -79,14 +68,6 @@
       AddressCountryCode country_code =
           i18n_model_definition::kLegacyHierarchyCountryCode);
 
-  // Server profile constructor. The type must be SERVER_PROFILE (this serves
-  // to differentiate this constructor). |server_id| can be empty. If empty,
-  // callers should invoke GenerateServerProfileIdentifier after setting data.
-  AutofillProfile(RecordType type,
-                  const std::string& server_id,
-                  AddressCountryCode country_code =
-                      i18n_model_definition::kLegacyHierarchyCountryCode);
-
   AutofillProfile(const AutofillProfile& profile);
   ~AutofillProfile() override;
 
@@ -116,9 +97,7 @@
 #endif  // BUILDFLAG(IS_ANDROID)
 
   // AutofillDataModel:
-  AutofillMetadata GetMetadata() const override;
   double GetRankingScore(base::Time current_time) const override;
-  bool SetMetadata(const AutofillMetadata& metadata) override;
 
   // FormGroup:
   void GetMatchingTypes(const std::u16string& text,
@@ -140,10 +119,6 @@
 
   void GetSupportedTypes(ServerFieldTypeSet* supported_types) const override;
 
-  // How this card is stored.
-  RecordType record_type() const { return record_type_; }
-  void set_record_type(RecordType type) { record_type_ = type; }
-
   // Returns true if there are no values (field types) set.
   bool IsEmpty(const std::string& app_locale) const;
 
@@ -253,15 +228,6 @@
     language_code_ = language_code;
   }
 
-  // Nonempty only when type() == SERVER_PROFILE. base::kSHA1Length bytes long.
-  // Not necessarily valid UTF-8.
-  const std::string& server_id() const { return server_id_; }
-
-  // Creates an identifier and saves it as |server_id_|. Only used for
-  // server credit cards. The server doesn't attach an identifier so Chrome
-  // creates its own. The ID is a hash of the data contained in the profile.
-  void GenerateServerProfileIdentifier();
-
   // Logs the number of days since the profile was last used and records its
   // use.
   // Also initiates the logging of the structured token verification statuses.
@@ -271,10 +237,6 @@
   // tokens. Should be called when a profile is used to fill a form.
   void LogVerificationStatuses();
 
-  // Valid only when |record_type()| == |SERVER_PROFILE|.
-  bool has_converted() const { return has_converted_; }
-  void set_has_converted(bool has_converted) { has_converted_ = has_converted; }
-
   // Calls |FinalizeAfterImport()| on all |FormGroup| members that are
   // implemented using the hybrid-structure |AddressComponent|.
   // If possible, this will initiate the completion of the structure tree to
@@ -386,10 +348,6 @@
   // A globally unique ID for this object. It identifies the profile across
   // browser restarts and is used as the primary key in the database.
   // The `guid_` is unique across profile sources.
-  // TODO(crbug.com/1177366): SERVER_PROFILEs still exist in the data model.
-  // This is a deprecated and essentially unused type of profile, which is
-  // identified by `server_id_` instead of `guid_`. For all practical purposes,
-  // this can be ignored and all relevant profiles are identified by `guid_`.
   std::string guid_;
 
   // Personal information for this profile.
@@ -409,17 +367,6 @@
   // The BCP 47 language code that can be used to format |address_| for display.
   std::string language_code_;
 
-  // ID used for identifying this profile. Only set for SERVER_PROFILEs. This is
-  // a hash of the contents.
-  // TODO(crbug.com/1457187): Remove.
-  std::string server_id_;
-
-  RecordType record_type_;
-
-  // Only useful for SERVER_PROFILEs. Whether this server profile has been
-  // converted to a local profile.
-  bool has_converted_;
-
   Source source_;
 
   // Indicates the application that initially created the profile and the
diff --git a/components/autofill/core/browser/data_model/autofill_profile_unittest.cc b/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
index 78034af8..4821548 100644
--- a/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
+++ b/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
@@ -1548,80 +1548,6 @@
   EXPECT_NE(p1, p2);
 }
 
-TEST(AutofillProfileTest, GetMetadata) {
-  AutofillProfile local_profile = test::GetFullProfile();
-  local_profile.set_use_count(2);
-  local_profile.set_use_date(base::Time::FromSecondsSinceUnixEpoch(25));
-  local_profile.set_has_converted(false);
-  AutofillMetadata local_metadata = local_profile.GetMetadata();
-  EXPECT_EQ(local_profile.guid(), local_metadata.id);
-  EXPECT_EQ(local_profile.has_converted(), local_metadata.has_converted);
-  EXPECT_EQ(local_profile.use_count(), local_metadata.use_count);
-  EXPECT_EQ(local_profile.use_date(), local_metadata.use_date);
-
-  AutofillProfile server_profile = test::GetServerProfile();
-  server_profile.set_use_count(10);
-  server_profile.set_use_date(base::Time::FromSecondsSinceUnixEpoch(100));
-  server_profile.set_has_converted(true);
-  AutofillMetadata server_metadata = server_profile.GetMetadata();
-  EXPECT_EQ(server_profile.server_id(), server_metadata.id);
-  EXPECT_EQ(server_profile.has_converted(), server_metadata.has_converted);
-  EXPECT_EQ(server_profile.use_count(), server_metadata.use_count);
-  EXPECT_EQ(server_profile.use_date(), server_metadata.use_date);
-}
-
-TEST(AutofillProfileTest, SetMetadata_MatchingId) {
-  AutofillProfile local_profile = test::GetFullProfile();
-  AutofillMetadata local_metadata;
-  local_metadata.id = local_profile.guid();
-  local_metadata.use_count = 100;
-  local_metadata.use_date = base::Time::FromSecondsSinceUnixEpoch(50);
-  local_metadata.has_converted = true;
-  EXPECT_TRUE(local_profile.SetMetadata(local_metadata));
-  EXPECT_EQ(local_metadata.id, local_profile.guid());
-  EXPECT_EQ(local_metadata.has_converted, local_profile.has_converted());
-  EXPECT_EQ(local_metadata.use_count, local_profile.use_count());
-  EXPECT_EQ(local_metadata.use_date, local_profile.use_date());
-
-  AutofillProfile server_profile = test::GetServerProfile();
-  AutofillMetadata server_metadata;
-  server_metadata.id = server_profile.server_id();
-  server_metadata.use_count = 100;
-  server_metadata.use_date = base::Time::FromSecondsSinceUnixEpoch(50);
-  server_metadata.has_converted = true;
-  EXPECT_TRUE(server_profile.SetMetadata(server_metadata));
-  EXPECT_EQ(server_metadata.id, server_profile.server_id());
-  EXPECT_EQ(server_metadata.has_converted, server_profile.has_converted());
-  EXPECT_EQ(server_metadata.use_count, server_profile.use_count());
-  EXPECT_EQ(server_metadata.use_date, server_profile.use_date());
-}
-
-TEST(AutofillProfileTest, SetMetadata_NotMatchingId) {
-  AutofillProfile local_profile = test::GetFullProfile();
-  AutofillMetadata local_metadata;
-  local_metadata.id = "WrongId";
-  local_metadata.use_count = 100;
-  local_metadata.use_date = base::Time::FromSecondsSinceUnixEpoch(50);
-  local_metadata.has_converted = true;
-  EXPECT_FALSE(local_profile.SetMetadata(local_metadata));
-  EXPECT_NE(local_metadata.id, local_profile.guid());
-  EXPECT_NE(local_metadata.has_converted, local_profile.has_converted());
-  EXPECT_NE(local_metadata.use_count, local_profile.use_count());
-  EXPECT_NE(local_metadata.use_date, local_profile.use_date());
-
-  AutofillProfile server_profile = test::GetServerProfile();
-  AutofillMetadata server_metadata;
-  server_metadata.id = "WrongId";
-  server_metadata.use_count = 100;
-  server_metadata.use_date = base::Time::FromSecondsSinceUnixEpoch(50);
-  server_metadata.has_converted = true;
-  EXPECT_FALSE(server_profile.SetMetadata(server_metadata));
-  EXPECT_NE(server_metadata.id, server_profile.guid());
-  EXPECT_NE(server_metadata.has_converted, server_profile.has_converted());
-  EXPECT_NE(server_metadata.use_count, server_profile.use_count());
-  EXPECT_NE(server_metadata.use_date, server_profile.use_date());
-}
-
 // Tests that `RecordUseAndLog()` only increments the use count if at least 60
 // seconds have passed.
 TEST(AutofillProfileTest, RecordUseAndLog_Delay) {
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc
index 6511c70..a0199dc 100644
--- a/components/autofill/core/browser/form_data_importer.cc
+++ b/components/autofill/core/browser/form_data_importer.cc
@@ -63,10 +63,11 @@
 
 // Return true if the |field_type| and |value| are valid within the context
 // of importing a form.
-bool IsValidFieldTypeAndValue(const ServerFieldTypeSet types_seen,
-                              ServerFieldType field_type,
-                              const std::u16string& value,
-                              LogBuffer* import_log_buffer) {
+bool IsValidFieldTypeAndValue(
+    const base::flat_map<ServerFieldType, std::u16string>& observed_types,
+    ServerFieldType field_type,
+    const std::u16string& value,
+    LogBuffer* import_log_buffer) {
   // Abandon the import if two fields of the same type are encountered.
   // This indicates ambiguous data or miscategorization of types.
   // Make an exception for:
@@ -76,7 +77,7 @@
   // numbers.
   // TODO(crbug.com/1156315) Clean up when launched.
   FieldTypeGroup field_type_group = GroupTypeOfServerFieldType(field_type);
-  if (types_seen.count(field_type) && field_type != EMAIL_ADDRESS &&
+  if (observed_types.contains(field_type) && field_type != EMAIL_ADDRESS &&
       (!base::FeatureList::IsEnabled(
            features::kAutofillEnableImportWhenMultiplePhoneNumbers) ||
        field_type_group != FieldTypeGroup::kPhone)) {
@@ -439,7 +440,6 @@
 
 AutofillProfile FormDataImporter::ConstructProfileFromObservedValues(
     const base::flat_map<ServerFieldType, std::u16string>& observed_values,
-    const PhoneNumber::PhoneCombineHelper& combined_phone,
     LogBuffer* import_log_buffer,
     autofill::ProfileImportMetadata& import_metadata) {
   AutofillProfile candidate_profile(
@@ -468,6 +468,10 @@
   import_metadata.did_complement_country =
       ComplementCountry(candidate_profile, predicted_country_code);
 
+  // We only set complete phone, so aggregate phone parts in these vars and set
+  // complete at the end.
+  PhoneNumber::PhoneCombineHelper combined_phone;
+
   // Populate the profile with the collected values. Note that this is after the
   // profile's country has been set to make sure the correct address
   // representation is used.
@@ -475,7 +479,13 @@
     // The profile country has already been stablished by this point. It's
     // ignored here to avoid re-setting up a potentially invalid country that
     // was present in the form.
-    if (type != ADDRESS_HOME_COUNTRY) {
+    if (type == ADDRESS_HOME_COUNTRY) {
+      continue;
+    }
+    // We need to store phone data in the variables, before building the whole
+    // number at the end. If |value| is not from a phone field, phone.SetInfo()
+    // returns false and data is stored directly in `candidate_profile`.
+    if (!combined_phone.SetInfo(AutofillType(type), value)) {
       candidate_profile.SetInfoWithVerificationStatus(
           type, value, app_locale_, VerificationStatus::kObserved);
     }
@@ -499,14 +509,6 @@
     std::vector<FormDataImporter::AddressProfileImportCandidate>*
         address_profile_import_candidates,
     LogBuffer* import_log_buffer) {
-  // We only set complete phone, so aggregate phone parts in these vars and set
-  // complete at the end.
-  PhoneNumber::PhoneCombineHelper combined_phone;
-
-  // Used to detect and discard address forms with multiple fields of the same
-  // type.
-  ServerFieldTypeSet types_seen;
-
   // Tracks if the form section contains multiple distinct email addresses.
   bool has_multiple_distinct_email_addresses = false;
 
@@ -527,7 +529,9 @@
   plus_addresses::PlusAddressService* plus_address_service =
       client_->GetPlusAddressService();
 
-  // Stores the values collected for each related `ServerFieldType`.
+  // Stores the values collected for each related `ServerFieldType`. Used as
+  // well to detect and discard address forms with multiple fields of the same
+  // type.
   base::flat_map<ServerFieldType, std::u16string> observed_field_values;
 
   // Go through each |form| field and attempt to constitute a valid profile.
@@ -566,20 +570,23 @@
     // fields) but they must all contain the same value, else the profile is
     // invalid.
     ServerFieldType server_field_type = field_type.GetStorableType();
-    if (server_field_type == EMAIL_ADDRESS &&
-        types_seen.count(server_field_type) &&
-        observed_field_values.at(EMAIL_ADDRESS) != value) {
-      LOG_AF(import_log_buffer)
-          << LogMessage::kImportAddressProfileFromFormFailed
-          << "Multiple different email addresses present." << CTag{};
-      has_multiple_distinct_email_addresses = true;
+    if (server_field_type == EMAIL_ADDRESS) {
+      auto email_it = observed_field_values.find(EMAIL_ADDRESS);
+      if (email_it != observed_field_values.end() &&
+          email_it->second != value) {
+        LOG_AF(import_log_buffer)
+            << LogMessage::kImportAddressProfileFromFormFailed
+            << "Multiple different email addresses present." << CTag{};
+        has_multiple_distinct_email_addresses = true;
+      }
     }
 
     // If the field type and |value| don't pass basic validity checks then
     // abandon the import.
-    if (!IsValidFieldTypeAndValue(types_seen, server_field_type, value,
-                                  import_log_buffer))
+    if (!IsValidFieldTypeAndValue(observed_field_values, server_field_type,
+                                  value, import_log_buffer)) {
       has_invalid_field_types = true;
+    }
 
     // Found phone number component field.
     // TODO(crbug.com/1156315) Remove feature check when launched.
@@ -592,21 +599,13 @@
       // type a second time implies that it belongs to a new number. Since
       // Autofill currently supports storing only one phone number per profile,
       // ignore this and all subsequent phone number fields.
-      if (types_seen.count(server_field_type)) {
+      if (observed_field_values.contains(server_field_type)) {
         ignore_phone_number_fields = true;
         continue;
       }
     }
 
-    types_seen.insert(server_field_type);
-
-    // We need to store phone data in the variables, before building the whole
-    // number at the end. If |value| is not from a phone field, home.SetInfo()
-    // returns false and data is stored directly in |candidate_profile|.
-    if (!combined_phone.SetInfo(field_type, value)) {
-      observed_field_values.insert_or_assign(field_type.GetStorableType(),
-                                             value);
-    }
+    observed_field_values.insert_or_assign(field_type.GetStorableType(), value);
 
     if (FieldTypeGroupToFormType(field_type.group()) ==
         FormType::kAddressForm) {
@@ -620,9 +619,8 @@
   }
 
   // The candidate for profile import.
-  AutofillProfile candidate_profile =
-      ConstructProfileFromObservedValues(observed_field_values, combined_phone,
-                                         import_log_buffer, import_metadata);
+  AutofillProfile candidate_profile = ConstructProfileFromObservedValues(
+      observed_field_values, import_log_buffer, import_metadata);
 
   // This is done prior to checking the validity of the profile, because multi-
   // step import profile merging requires the profile to be finalized. Ideally
diff --git a/components/autofill/core/browser/form_data_importer.h b/components/autofill/core/browser/form_data_importer.h
index 26a89c9..4890e64 100644
--- a/components/autofill/core/browser/form_data_importer.h
+++ b/components/autofill/core/browser/form_data_importer.h
@@ -252,7 +252,6 @@
   // form. Used during `ExtractAddressProfileFromSection()`.
   AutofillProfile ConstructProfileFromObservedValues(
       const base::flat_map<ServerFieldType, std::u16string>& observed_values,
-      const PhoneNumber::PhoneCombineHelper& combined_phone,
       LogBuffer* import_log_buffer,
       autofill::ProfileImportMetadata& import_metadata);
 
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.cc b/components/autofill/core/browser/metrics/autofill_metrics.cc
index 7c42d74..5ab743b 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics.cc
@@ -2210,22 +2210,17 @@
 }
 
 void AutofillMetrics::FormInteractionsUkmLogger::LogDidFillSuggestion(
-    absl::variant<AutofillProfile::RecordType, CreditCard::RecordType>
-        record_type,
     const FormStructure& form,
-    const AutofillField& field) {
+    const AutofillField& field,
+    std::optional<CreditCard::RecordType> record_type) {
   if (!CanLog())
     return;
 
-  bool is_for_credit_card =
-      absl::holds_alternative<CreditCard::RecordType>(record_type);
-
-  ukm::builders::Autofill_SuggestionFilled(GetSourceId())
-      .SetRecordType(is_for_credit_card
-                         ? base::to_underlying(
-                               absl::get<CreditCard::RecordType>(record_type))
-                         : absl::get<AutofillProfile::RecordType>(record_type))
-      .SetIsForCreditCard(is_for_credit_card)
+  auto metric = ukm::builders::Autofill_SuggestionFilled(GetSourceId());
+  if (record_type) {
+    metric.SetRecordType(base::to_underlying(*record_type));
+  }
+  metric.SetIsForCreditCard(record_type.has_value())
       .SetMillisecondsSinceFormParsed(
           MillisecondsSinceFormParsed(form.form_parsed_timestamp()))
       .SetFormSignature(HashFormSignature(form.form_signature()))
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.h b/components/autofill/core/browser/metrics/autofill_metrics.h
index a66a53e..ead5e03 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics.h
+++ b/components/autofill/core/browser/metrics/autofill_metrics.h
@@ -730,10 +730,11 @@
                              const AutofillField& field,
                              const base::TimeTicks& form_parsed_timestamp,
                              bool off_the_record);
-    void LogDidFillSuggestion(absl::variant<AutofillProfile::RecordType,
-                                            CreditCard::RecordType> record_type,
-                              const FormStructure& form,
-                              const AutofillField& field);
+    // For address suggestions, the `record_type` is irrelevant.
+    void LogDidFillSuggestion(
+        const FormStructure& form,
+        const AutofillField& field,
+        std::optional<CreditCard::RecordType> record_type = std::nullopt);
     void LogTextFieldDidChange(const FormStructure& form,
                                const AutofillField& field);
     void LogEditedAutofilledFieldAtSubmission(const FormStructure& form,
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc b/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc
index bfafdb1..3dcd46a95 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc
@@ -115,19 +115,11 @@
   personal_data().Refresh();
 }
 
-void AutofillMetricsBaseTest::RecreateProfile(bool is_server) {
+void AutofillMetricsBaseTest::RecreateProfile() {
   personal_data().ClearProfiles();
-
-  if (is_server) {
-    AutofillProfile profile(AutofillProfile::SERVER_PROFILE, "server_id");
-    SetProfileTestData(&profile);
-    personal_data().AddProfile(profile);
-  } else {
-    AutofillProfile profile;
-    SetProfileTestData(&profile);
-    personal_data().AddProfile(profile);
-  }
-
+  AutofillProfile profile;
+  SetProfileTestData(&profile);
+  personal_data().AddProfile(profile);
   personal_data().Refresh();
 }
 
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_test_base.h b/components/autofill/core/browser/metrics/autofill_metrics_test_base.h
index 9773095..f73f9c85 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics_test_base.h
+++ b/components/autofill/core/browser/metrics/autofill_metrics_test_base.h
@@ -58,8 +58,7 @@
   void CreateAmbiguousProfiles();
 
   // Removes all existing profiles and creates one profile.
-  // |is_server| allows creation of |SERVER_PROFILE|.
-  void RecreateProfile(bool is_server);
+  void RecreateProfile();
 
   // Removes all existing credit cards and then invokes CreateCreditCards to
   // create the cards.
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
index b353424..ab67235 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
@@ -192,6 +192,12 @@
             std::string("Autofill.FormEvents.CreditCard.") +
             (is_in_any_main_frame_ ? "IsInMainFrame" : "IsInIFrame")) {}
 
+  CreditCard GetVirtualCreditCard(const std::string& guid) {
+    CreditCard copy = *personal_data().GetCreditCardByGUID(guid);
+    copy.set_record_type(CreditCard::RecordType::kVirtualCard);
+    return copy;
+  }
+
  protected:
   const std::string credit_card_form_events_frame_histogram_;
 };
@@ -532,7 +538,7 @@
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(
       features::kAutofillUseParameterizedSectioning);
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
 
   FormData form = CreateForm({
       CreateTestFormField("Name", "name", "",
@@ -1993,8 +1999,7 @@
 
 // Test that the profile checkout flow user actions are correctly logged.
 TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) {
-  // Create a profile.
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
 
   FormData form = CreateForm(
       {CreateTestFormField("State", "state", "", FormControlType::kInputText),
@@ -2089,18 +2094,14 @@
   // call to |external_delegate().DidAcceptSuggestion|. Second, from call to
   // |autofill_manager().FillOrPreviewProfileForm|.
   VerifyUkm(&test_ukm_recorder(), form, UkmSuggestionFilledType::kEntryName,
-            {{{UkmSuggestionFilledType::kRecordTypeName,
-               AutofillProfile::LOCAL_PROFILE},
-              {UkmSuggestionFilledType::kIsForCreditCardName, false},
+            {{{UkmSuggestionFilledType::kIsForCreditCardName, false},
               {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
               {UkmSuggestionFilledType::kFieldSignatureName,
                Collapse(CalculateFieldSignatureForField(form.fields.front()))
                    .value()},
               {UkmSuggestionFilledType::kFormSignatureName,
                Collapse(CalculateFormSignature(form)).value()}},
-             {{UkmSuggestionFilledType::kRecordTypeName,
-               AutofillProfile::LOCAL_PROFILE},
-              {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
+             {{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
               {UkmSuggestionFilledType::kIsForCreditCardName, false},
               {UkmSuggestionsShownType::kFieldSignatureName,
                Collapse(CalculateFieldSignatureForField(form.fields.front()))
@@ -2230,7 +2231,7 @@
 // Tests that the Autofill_PolledProfileSuggestions user action is only logged
 // once if the field is queried repeatedly.
 TEST_F(AutofillMetricsTest, PolledProfileSuggestions_DebounceLogs) {
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
 
   FormData form = CreateForm(
       {CreateTestFormField("State", "state", "", FormControlType::kInputText),
@@ -2610,9 +2611,10 @@
     // Simulating selecting a virtual server suggestion by selecting the
     // option based on the enrolled masked card.
     base::HistogramTester histogram_tester;
-    autofill_manager().FillOrPreviewVirtualCardInformation(
-        mojom::ActionPersistence::kFill, kTestMaskedCardId, form,
-        form.fields[2], {.trigger_source = AutofillTriggerSource::kPopup});
+    CreditCard virtual_card = GetVirtualCreditCard(kTestMaskedCardId);
+    autofill_manager().FillOrPreviewCreditCardForm(
+        mojom::ActionPersistence::kFill, form, form.fields[2], &virtual_card,
+        {.trigger_source = AutofillTriggerSource::kPopup});
     OnCreditCardFetchingSuccessful(u"6011000990139424",
                                    /*is_virtual_card=*/true);
     EXPECT_THAT(
@@ -2635,14 +2637,15 @@
   {
     // Simulating selecting a virtual card multiple times.
     base::HistogramTester histogram_tester;
-    autofill_manager().FillOrPreviewVirtualCardInformation(
-        mojom::ActionPersistence::kFill, kTestMaskedCardId, form,
-        form.fields[2], {.trigger_source = AutofillTriggerSource::kPopup});
+    CreditCard virtual_card = GetVirtualCreditCard(kTestMaskedCardId);
+    autofill_manager().FillOrPreviewCreditCardForm(
+        mojom::ActionPersistence::kFill, form, form.fields[2], &virtual_card,
+        {.trigger_source = AutofillTriggerSource::kPopup});
     OnCreditCardFetchingSuccessful(u"6011000990139424",
                                    /*is_virtual_card=*/true);
-    autofill_manager().FillOrPreviewVirtualCardInformation(
-        mojom::ActionPersistence::kFill, kTestMaskedCardId, form,
-        form.fields[2], {.trigger_source = AutofillTriggerSource::kPopup});
+    autofill_manager().FillOrPreviewCreditCardForm(
+        mojom::ActionPersistence::kFill, form, form.fields[2], &virtual_card,
+        {.trigger_source = AutofillTriggerSource::kPopup});
     OnCreditCardFetchingSuccessful(u"6011000990139424",
                                    /*is_virtual_card=*/true);
     EXPECT_THAT(
@@ -2705,9 +2708,10 @@
     // Simulating filling a virtual card suggestion by selecting the option
     // based on the enrolled masked card.
     base::HistogramTester histogram_tester;
-    autofill_manager().FillOrPreviewVirtualCardInformation(
-        mojom::ActionPersistence::kFill, kTestMaskedCardId, form,
-        form.fields.front(), {.trigger_source = AutofillTriggerSource::kPopup});
+    CreditCard virtual_card = GetVirtualCreditCard(kTestMaskedCardId);
+    autofill_manager().FillOrPreviewCreditCardForm(
+        mojom::ActionPersistence::kFill, form, form.fields.front(),
+        &virtual_card, {.trigger_source = AutofillTriggerSource::kPopup});
     OnCreditCardFetchingSuccessful(u"6011000990139424",
                                    /*is_virtual_card=*/true);
     EXPECT_THAT(
@@ -3435,8 +3439,7 @@
 }
 
 TEST_F(AutofillMetricsTest, ShouldNotLogFormEventNoCardForAddressForm) {
-  // Create a profile.
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
   FormData form = CreateForm(
       {CreateTestFormField("State", "state", "", FormControlType::kInputText),
        CreateTestFormField("City", "city", "", FormControlType::kInputText),
@@ -3635,10 +3638,11 @@
     // Simulating submission with filled virtual card data by selecting the
     // option based on the enrolled masked card.
     base::HistogramTester histogram_tester;
+    CreditCard virtual_card = GetVirtualCreditCard(kTestMaskedCardId);
     autofill_manager().OnAskForValuesToFillTest(form, form.fields.back());
-    autofill_manager().FillOrPreviewVirtualCardInformation(
-        mojom::ActionPersistence::kFill, kTestMaskedCardId, form,
-        form.fields.front(), {.trigger_source = AutofillTriggerSource::kPopup});
+    autofill_manager().FillOrPreviewCreditCardForm(
+        mojom::ActionPersistence::kFill, form, form.fields.front(),
+        &virtual_card, {.trigger_source = AutofillTriggerSource::kPopup});
     OnCreditCardFetchingSuccessful(u"6011000990139424",
                                    /*is_virtual_card=*/true);
     SubmitForm(form);
@@ -3993,10 +3997,11 @@
     // Simulating submission with filled virtual card data by selecting the
     // option based on the enrolled masked card.
     base::HistogramTester histogram_tester;
+    CreditCard virtual_card = GetVirtualCreditCard(kTestMaskedCardId);
     autofill_manager().OnAskForValuesToFillTest(form, form.fields[0]);
-    autofill_manager().FillOrPreviewVirtualCardInformation(
-        mojom::ActionPersistence::kFill, kTestMaskedCardId, form,
-        form.fields.front(), {.trigger_source = AutofillTriggerSource::kPopup});
+    autofill_manager().FillOrPreviewCreditCardForm(
+        mojom::ActionPersistence::kFill, form, form.fields.front(),
+        &virtual_card, {.trigger_source = AutofillTriggerSource::kPopup});
     OnCreditCardFetchingSuccessful(u"6011000990139424",
                                    /*is_virtual_card=*/true);
     SubmitForm(form);
@@ -4658,8 +4663,7 @@
 
 // Test that we log suggestion shown form events for address.
 TEST_F(AutofillMetricsTest, AddressShownFormEvents) {
-  // Create a profile.
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
   FormData form = CreateForm(
       {CreateTestFormField("State", "state", "", FormControlType::kInputText),
        CreateTestFormField("City", "city", "", FormControlType::kInputText),
@@ -4754,8 +4758,7 @@
 
 // Test that we log filled form events for address.
 TEST_F(AutofillMetricsTest, AddressFilledFormEvents) {
-  // Create a profile.
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
   FormData form = CreateForm(
       {CreateTestFormField("State", "state", "", FormControlType::kInputText),
        CreateTestFormField("City", "city", "", FormControlType::kInputText),
@@ -4808,41 +4811,11 @@
         BucketsInclude(Bucket(FORM_EVENT_LOCAL_SUGGESTION_FILLED, 2),
                        Bucket(FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, 1)));
   }
-
-  // Create a server profile and reset the autofill manager state.
-  RecreateProfile(/*is_server=*/true);
-  autofill_manager().Reset();
-  autofill_manager().AddSeenForm(form, field_types);
-
-  {
-    // Simulate selecting/filling a server profile suggestion.
-    base::HistogramTester histogram_tester;
-    FillTestProfile(form);
-    EXPECT_THAT(
-        histogram_tester.GetAllSamples("Autofill.FormEvents.Address"),
-        BucketsInclude(Bucket(FORM_EVENT_SERVER_SUGGESTION_FILLED, 1),
-                       Bucket(FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE, 1)));
-  }
-
-  autofill_manager().Reset();
-  autofill_manager().AddSeenForm(form, field_types);
-
-  {
-    // Simulate selecting/filling a server profile suggestion more than once.
-    base::HistogramTester histogram_tester;
-    FillTestProfile(form);
-    FillTestProfile(form);
-    EXPECT_THAT(
-        histogram_tester.GetAllSamples("Autofill.FormEvents.Address"),
-        BucketsInclude(Bucket(FORM_EVENT_SERVER_SUGGESTION_FILLED, 2),
-                       Bucket(FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE, 1)));
-  }
 }
 
 // Test that we log submitted form events for address.
 TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
-  // Create a profile.
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
   FormData form = CreateForm(
       {CreateTestFormField("State", "state", "", FormControlType::kInputText),
        CreateTestFormField("City", "city", "", FormControlType::kInputText),
@@ -4989,8 +4962,7 @@
 
 // Test that we log "will submit" and "submitted" form events for address.
 TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
-  // Create a profile.
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
   FormData form = CreateForm(
       {CreateTestFormField("State", "state", "", FormControlType::kInputText),
        CreateTestFormField("City", "city", "", FormControlType::kInputText),
@@ -5253,7 +5225,7 @@
   // Reset the autofill manager state.
   autofill_manager().Reset();
   autofill_manager().AddSeenForm(form, field_types);
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
 
   {
     // Simulate activating the autofill popup for the street field.
@@ -6124,17 +6096,13 @@
          Collapse(CalculateFormSignature(form)).value()}}});
   VerifyUkm(
       &test_ukm_recorder(), form, UkmSuggestionFilledType::kEntryName,
-      {{{UkmSuggestionFilledType::kRecordTypeName,
-         AutofillProfile::LOCAL_PROFILE},
-        {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
+      {{{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
         {UkmSuggestionFilledType::kIsForCreditCardName, false},
         {UkmSuggestionFilledType::kFieldSignatureName,
          Collapse(CalculateFieldSignatureForField(form.fields[0])).value()},
         {UkmSuggestionFilledType::kFormSignatureName,
          Collapse(CalculateFormSignature(form)).value()}},
-       {{UkmSuggestionFilledType::kRecordTypeName,
-         AutofillProfile::LOCAL_PROFILE},
-        {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
+       {{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
         {UkmSuggestionFilledType::kFieldSignatureName,
          Collapse(CalculateFieldSignatureForField(form.fields[2])).value()},
         {UkmSuggestionFilledType::kFormSignatureName,
@@ -7768,7 +7736,7 @@
   base::test::ScopedFeatureList features;
   features.InitAndEnableFeature(
       features::kAutofillPreventOverridingPrefilledValues);
-  RecreateProfile(false);
+  RecreateProfile();
 
   FormData form = test::GetFormData(
       {.description_for_logging =
@@ -8258,8 +8226,7 @@
   TestAutofillTickClock test_clock;
   test_clock.SetNowTicks(now);
 
-  // Create a profile.
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
   FormData form;
   form.url = GURL("http://www.foo.com/");
 
@@ -8347,8 +8314,7 @@
   TestAutofillTickClock test_clock;
   test_clock.SetNowTicks(now);
 
-  // Create a profile.
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
   FormData form;
   form.url = GURL("http://www.foo.com/");
 
diff --git a/components/autofill/core/browser/metrics/form_events/address_form_event_logger.cc b/components/autofill/core/browser/metrics/form_events/address_form_event_logger.cc
index f6e5da77..a019be65 100644
--- a/components/autofill/core/browser/metrics/form_events/address_form_event_logger.cc
+++ b/components/autofill/core/browser/metrics/form_events/address_form_event_logger.cc
@@ -38,25 +38,15 @@
     const AutofillField& field,
     AutofillMetrics::PaymentsSigninState signin_state_for_metrics,
     const AutofillTriggerSource trigger_source) {
-  AutofillProfile::RecordType record_type = profile.record_type();
   signin_state_for_metrics_ = signin_state_for_metrics;
 
-  form_interactions_ukm_logger_->LogDidFillSuggestion(record_type, form, field);
+  form_interactions_ukm_logger_->LogDidFillSuggestion(form, field);
 
-  if (record_type == AutofillProfile::SERVER_PROFILE) {
-    Log(FORM_EVENT_SERVER_SUGGESTION_FILLED, form);
-  } else {
-    Log(FORM_EVENT_LOCAL_SUGGESTION_FILLED, form);
-  }
+  Log(FORM_EVENT_LOCAL_SUGGESTION_FILLED, form);
 
   if (!has_logged_suggestion_filled_) {
     has_logged_suggestion_filled_ = true;
-    logged_suggestion_filled_was_server_data_ =
-        record_type == AutofillProfile::SERVER_PROFILE;
-    Log(record_type == AutofillProfile::SERVER_PROFILE
-            ? FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE
-            : FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE,
-        form);
+    Log(FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, form);
   }
 
   base::RecordAction(
diff --git a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc
index 73fc916..502255c 100644
--- a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc
+++ b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc
@@ -168,7 +168,7 @@
       form_interactions_ukm_logger_->CreateCreditCardFillBuilder();
   builder.SetFormSignature(HashFormSignature(form.form_signature()));
 
-  form_interactions_ukm_logger_->LogDidFillSuggestion(record_type, form, field);
+  form_interactions_ukm_logger_->LogDidFillSuggestion(form, field, record_type);
 
   AutofillMetrics::LogCreditCardSeamlessnessAtFillTime(
       {.event_logger = raw_ref(*this),
diff --git a/components/autofill/core/browser/metrics/form_events/form_event_logger_base_unittest.cc b/components/autofill/core/browser/metrics/form_events/form_event_logger_base_unittest.cc
index 7c4dab1..5a65cd9 100644
--- a/components/autofill/core/browser/metrics/form_events/form_event_logger_base_unittest.cc
+++ b/components/autofill/core/browser/metrics/form_events/form_event_logger_base_unittest.cc
@@ -39,8 +39,7 @@
                          testing::Values(0, 1, 2, 3, 4));
 
 TEST_P(FormEventLoggerBaseFunnelTest, LogFunnelMetrics) {
-  // Create a profile.
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
 
   FormData form = CreateForm(
       {CreateTestFormField("State", "state", "", FormControlType::kInputText),
@@ -182,8 +181,7 @@
   scoped_feature_list.InitAndEnableFeatureWithParameters(
       features::kAutofillEnableAblationStudy, feature_parameters);
 
-  // Create a profile.
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
 
   FormData form = CreateForm(
       {CreateTestFormField("State", "state", "", FormControlType::kInputText),
@@ -240,8 +238,7 @@
 void FormEventLoggerBaseKeyMetricsTest::SetUp() {
   SetUpHelper();
 
-  // Create a profile.
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
 
   // Load a fillable form.
   form_ = CreateEmptyForm();
@@ -485,8 +482,7 @@
 void FormEventLoggerBaseEmailHeuristicOnlyMetricsTest::SetUp() {
   SetUpHelper();
 
-  // Create a profile.
-  RecreateProfile(/*is_server=*/false);
+  RecreateProfile();
 
   // Load a fillable form.
   form_ = test::GetFormData({.fields = {{.role = EMAIL_ADDRESS}}});
diff --git a/components/autofill/core/browser/metrics/granular_filling_metrics.cc b/components/autofill/core/browser/metrics/granular_filling_metrics.cc
index b48926e..e614d3b 100644
--- a/components/autofill/core/browser/metrics/granular_filling_metrics.cc
+++ b/components/autofill/core/browser/metrics/granular_filling_metrics.cc
@@ -20,7 +20,7 @@
 
 void LogFillingMethodUsed(AutofillFillingMethodMetric filling_method) {
   CHECK_LE(filling_method, AutofillFillingMethodMetric::kMaxValue);
-  base::UmaHistogramEnumeration("Autofill.FillingMethodUsed.", filling_method);
+  base::UmaHistogramEnumeration("Autofill.FillingMethodUsed", filling_method);
 }
 
 }  // namespace autofill::autofill_metrics
diff --git a/components/autofill/core/browser/webdata/autofill_change.h b/components/autofill/core/browser/webdata/autofill_change.h
index 7f5b299..c44f07d6 100644
--- a/components/autofill/core/browser/webdata/autofill_change.h
+++ b/components/autofill/core/browser/webdata/autofill_change.h
@@ -67,12 +67,12 @@
       CHECK(data_model_.guid() == key_ || data_model_.instrument_id() == key_);
     } else if constexpr (std::is_same_v<DataType, ServerCvc>) {
       CHECK(base::NumberToString(data_model_.instrument_id) == key_);
-    } else {
+    } else if constexpr (std::is_same_v<DataType, CreditCard>) {
       // TODO(crbug.com/1475085): Use `instrument_id()` for credit cards and
       // merge the `Iban` and `CreditCard` cases.
-      // TODO(crbug.com/1457187): Once server addresses are removed,
-      // `server_id()` becomes irrelevant for `AutofillProfile`.
       CHECK(data_model_.guid() == key_ || data_model_.server_id() == key_);
+    } else {
+      CHECK(data_model_.guid() == key_);
     }
   }
 
diff --git a/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc
index 0e4ce84..db5528b 100644
--- a/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc
+++ b/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc
@@ -206,7 +206,6 @@
 void AutofillProfileSyncBridge::ActOnLocalChange(
     const AutofillProfileChange& change) {
   if (!change_processor()->IsTrackingMetadata() ||
-      change.data_model().record_type() != AutofillProfile::LOCAL_PROFILE ||
       change.data_model().source() !=
           AutofillProfile::Source::kLocalOrSyncable) {
     return;
diff --git a/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc
index 3e88d3af..184f09e 100644
--- a/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc
@@ -485,22 +485,6 @@
   bridge()->AutofillProfileChanged(change);
 }
 
-// Server profile updates should be ignored.
-TEST_F(AutofillProfileSyncBridgeTest,
-       AutofillProfileChanged_Updated_IgnoreServerProfiles) {
-  StartSyncing({});
-
-  AutofillProfile server_profile(
-      AutofillProfile::SERVER_PROFILE, "server-id",
-      i18n_model_definition::kLegacyHierarchyCountryCode);
-  AutofillProfileChange change(AutofillProfileChange::UPDATE,
-                               server_profile.guid(), server_profile);
-
-  EXPECT_CALL(mock_processor(), Put).Times(0);
-  // Should not crash.
-  bridge()->AutofillProfileChanged(change);
-}
-
 TEST_F(AutofillProfileSyncBridgeTest, AutofillProfileChanged_Deleted) {
   StartSyncing({});
 
@@ -516,22 +500,6 @@
   bridge()->AutofillProfileChanged(change);
 }
 
-// Server profile updates should be ignored.
-TEST_F(AutofillProfileSyncBridgeTest,
-       AutofillProfileChanged_Deleted_IgnoreServerProfiles) {
-  StartSyncing({});
-
-  AutofillProfile server_profile(
-      AutofillProfile::SERVER_PROFILE, "server-id",
-      i18n_model_definition::kLegacyHierarchyCountryCode);
-  AutofillProfileChange change(AutofillProfileChange::REMOVE,
-                               server_profile.guid(), server_profile);
-
-  EXPECT_CALL(mock_processor(), Put).Times(0);
-  // Should not crash.
-  bridge()->AutofillProfileChanged(change);
-}
-
 TEST_F(AutofillProfileSyncBridgeTest, GetAllDataForDebugging) {
   AutofillProfile local1(kGuidA, AutofillProfile::Source::kLocalOrSyncable,
                          i18n_model_definition::kLegacyHierarchyCountryCode);
diff --git a/components/browser_sync/sync_api_component_factory_impl.cc b/components/browser_sync/sync_api_component_factory_impl.cc
index 16a41cf..8275ca28 100644
--- a/components/browser_sync/sync_api_component_factory_impl.cc
+++ b/components/browser_sync/sync_api_component_factory_impl.cc
@@ -29,7 +29,7 @@
 #include "components/browser_sync/browser_sync_client.h"
 #include "components/history/core/browser/sync/history_delete_directives_model_type_controller.h"
 #include "components/history/core/browser/sync/history_model_type_controller.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/sharing/incoming_password_sharing_invitation_model_type_controller.h"
 #include "components/password_manager/core/browser/sharing/outgoing_password_sharing_invitation_model_type_controller.h"
 #include "components/password_manager/core/browser/sharing/password_receiver_service.h"
diff --git a/components/browser_sync/sync_client_utils.cc b/components/browser_sync/sync_client_utils.cc
index d04253f..16a7617 100644
--- a/components/browser_sync/sync_client_utils.cc
+++ b/components/browser_sync/sync_client_utils.cc
@@ -17,8 +17,8 @@
 #include "base/ranges/algorithm.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/reading_list/core/dual_reading_list_model.h"
 #include "components/sync/base/data_type_histogram.h"
 #include "components/sync/service/local_data_description.h"
diff --git a/components/browsing_data/core/counters/passwords_counter.cc b/components/browsing_data/core/counters/passwords_counter.cc
index 98806039..72c1f95 100644
--- a/components/browsing_data/core/counters/passwords_counter.cc
+++ b/components/browsing_data/core/counters/passwords_counter.cc
@@ -13,8 +13,8 @@
 #include "base/time/time.h"
 #include "components/browsing_data/core/pref_names.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
-#include "components/password_manager/core/browser/password_store_change.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_sync_util.h"
 #include "components/sync/service/sync_service.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
diff --git a/components/browsing_data/core/counters/passwords_counter.h b/components/browsing_data/core/counters/passwords_counter.h
index 9510789..4792da2 100644
--- a/components/browsing_data/core/counters/passwords_counter.h
+++ b/components/browsing_data/core/counters/passwords_counter.h
@@ -12,7 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "components/browsing_data/core/counters/browsing_data_counter.h"
 #include "components/browsing_data/core/counters/sync_tracker.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 
 namespace password_manager {
 class PasswordStoreInterface;
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json
index c42a0a43..19edb08 100644
--- a/components/certificate_transparency/data/log_list.json
+++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@
 {
-  "version": "26.38",
-  "log_list_timestamp": "2023-11-09T12:55:00Z",
+  "version": "26.39",
+  "log_list_timestamp": "2023-11-10T12:54:16Z",
   "operators": [
     {
       "name": "Google",
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn
index bc47b131..d06dad3d 100644
--- a/components/cronet/android/BUILD.gn
+++ b/components/cronet/android/BUILD.gn
@@ -612,6 +612,7 @@
   sources = [
     "//base/android/proguard/chromium_code.flags",
     "//build/android/chromium_annotations.flags",
+    "//third_party/jni_zero/proguard.flags",
 
     # Massage the proguard to avoid incompatibilities when building internally.
     "//components/cronet/android/cronet_impl_native_proguard.cfg",
diff --git a/components/file_access/scoped_file_access.cc b/components/file_access/scoped_file_access.cc
index 7820b88..3e03f41 100644
--- a/components/file_access/scoped_file_access.cc
+++ b/components/file_access/scoped_file_access.cc
@@ -26,4 +26,13 @@
 #endif
 }
 
+// static
+ScopedFileAccess ScopedFileAccess::Denied() {
+#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
+  return ScopedFileAccess(/*allowed=*/false, base::ScopedFD());
+#else
+  return ScopedFileAccess(/*allowed=*/false);
+#endif
+}
+
 }  // namespace file_access
diff --git a/components/file_access/scoped_file_access.h b/components/file_access/scoped_file_access.h
index ad8a06a..93c2893f 100644
--- a/components/file_access/scoped_file_access.h
+++ b/components/file_access/scoped_file_access.h
@@ -37,6 +37,9 @@
   // Object identifying allowed access.
   static ScopedFileAccess Allowed();
 
+  // Object identifying denied access.
+  static ScopedFileAccess Denied();
+
  private:
   bool allowed_;
 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
diff --git a/components/guest_view/browser/BUILD.gn b/components/guest_view/browser/BUILD.gn
index 522080d..549f058 100644
--- a/components/guest_view/browser/BUILD.gn
+++ b/components/guest_view/browser/BUILD.gn
@@ -6,7 +6,7 @@
 # assert to prevent the accidental building of GuestViews on mobile
 # platforms. If you're now using GuestViews on mobile, go ahead and
 # remove this assert.
-assert(!is_android && !is_ios)
+assert(!is_android)
 
 static_library("browser") {
   output_name = "guest_view_browser"
diff --git a/components/infobars/core/BUILD.gn b/components/infobars/core/BUILD.gn
index 98f80eed..e8d25a04 100644
--- a/components/infobars/core/BUILD.gn
+++ b/components/infobars/core/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chrome_build.gni")
 import("//build/config/ui.gni")
 
 if (is_android) {
@@ -25,8 +26,13 @@
     "simple_alert_infobar_delegate.h",
   ]
 
+  if (is_chrome_for_testing) {
+    sources += [ "infobars_switches.h" ]
+  }
+
   public_deps = [
     "//base",
+    "//build:branding_buildflags",
     "//skia",
     "//ui/base",
   ]
diff --git a/components/infobars/core/infobar_manager.cc b/components/infobars/core/infobar_manager.cc
index 178089d..345e608 100644
--- a/components/infobars/core/infobar_manager.cc
+++ b/components/infobars/core/infobar_manager.cc
@@ -8,8 +8,14 @@
 
 #include "base/observer_list.h"
 #include "base/ranges/algorithm.h"
+#include "build/branding_buildflags.h"
 #include "components/infobars/core/infobar.h"
 
+#if BUILDFLAG(CHROME_FOR_TESTING)
+#include "base/command_line.h"
+#include "components/infobars/core/infobars_switches.h"
+#endif
+
 namespace infobars {
 
 
@@ -38,6 +44,9 @@
 InfoBar* InfoBarManager::AddInfoBar(std::unique_ptr<InfoBar> new_infobar,
                                     bool replace_existing) {
   DCHECK(new_infobar);
+  if (!infobars_enabled_) {
+    return nullptr;
+  }
 
   for (auto* infobar : infobars_) {
     if (infobar->delegate()->EqualsDelegate(new_infobar->delegate())) {
@@ -69,6 +78,10 @@
 InfoBar* InfoBarManager::ReplaceInfoBar(InfoBar* old_infobar,
                                         std::unique_ptr<InfoBar> new_infobar) {
   DCHECK(old_infobar);
+  if (!infobars_enabled_) {
+    // Deletes the infobar.
+    return AddInfoBar(std::move(new_infobar));
+  }
   DCHECK(new_infobar);
 
   auto i = base::ranges::find(infobars_, old_infobar);
@@ -97,9 +110,15 @@
   observer_list_.RemoveObserver(obs);
 }
 
-InfoBarManager::InfoBarManager() = default;
+InfoBarManager::InfoBarManager()
+#if BUILDFLAG(CHROME_FOR_TESTING)
+    : infobars_enabled_(!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableInfoBars)){}
+#else
+    = default;
+#endif
 
-InfoBarManager::~InfoBarManager() = default;
+      InfoBarManager::~InfoBarManager() = default;
 
 void InfoBarManager::ShutDown() {
   // Destroy all remaining InfoBars.  It's important to not animate here so that
@@ -123,6 +142,7 @@
 
 void InfoBarManager::RemoveInfoBarInternal(InfoBar* infobar, bool animate) {
   DCHECK(infobar);
+  DCHECK(infobars_enabled_);
 
   auto i = base::ranges::find(infobars_, infobar);
   // TODO(crbug.com/): Temporarily a CHECK instead of a DCHECK CHECK() in order
diff --git a/components/infobars/core/infobar_manager.h b/components/infobars/core/infobar_manager.h
index 35fd17e..3e7b13af 100644
--- a/components/infobars/core/infobar_manager.h
+++ b/components/infobars/core/infobar_manager.h
@@ -119,6 +119,7 @@
 
   InfoBars infobars_;
   bool animations_enabled_ = true;
+  const bool infobars_enabled_ = true;
 
   base::ObserverList<Observer, true>::Unchecked observer_list_;
 };
diff --git a/components/infobars/core/infobars_switches.h b/components/infobars/core/infobars_switches.h
new file mode 100644
index 0000000..1cb4c43
--- /dev/null
+++ b/components/infobars/core/infobars_switches.h
@@ -0,0 +1,14 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_INFOBARS_CORE_INFOBARS_SWITCHES_H_
+#define COMPONENTS_INFOBARS_CORE_INFOBARS_SWITCHES_H_
+
+namespace infobars::switches {
+
+inline constexpr char kDisableInfoBars[] = "disable-infobars";
+
+}  // namespace infobars::switches
+
+#endif  // COMPONENTS_INFOBARS_CORE_INFOBARS_SWITCHES_H_
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index 069643d..ed816a7 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -4,7 +4,6 @@
 
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
-import("//testing/libfuzzer/fuzzer_test.gni")
 import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
 
 if (is_android) {
@@ -286,17 +285,17 @@
 
 source_set("password_store_interface") {
   sources = [
-    "interactions_stats.cc",
-    "interactions_stats.h",
-    "password_store_backend_error.cc",
-    "password_store_backend_error.h",
-    "password_store_change.cc",
-    "password_store_change.h",
-    "password_store_consumer.cc",
-    "password_store_consumer.h",
-    "password_store_interface.h",
-    "password_store_util.cc",
-    "password_store_util.h",
+    "password_store/interactions_stats.cc",
+    "password_store/interactions_stats.h",
+    "password_store/password_store_backend_error.cc",
+    "password_store/password_store_backend_error.h",
+    "password_store/password_store_change.cc",
+    "password_store/password_store_change.h",
+    "password_store/password_store_consumer.cc",
+    "password_store/password_store_consumer.h",
+    "password_store/password_store_interface.h",
+    "password_store/password_store_util.cc",
+    "password_store/password_store_util.h",
   ]
   deps = [
     ":password_form",
@@ -645,7 +644,6 @@
     "//components/password_manager/core/browser/features:utils",
     "//components/password_manager/core/browser/form_parsing:form_parsing",
     "//components/password_manager/core/browser/form_parsing:unit_tests",
-    "//components/password_manager/core/browser/form_parsing/fuzzer:unit_tests",
     "//components/password_manager/core/browser/generation",
     "//components/password_manager/core/browser/import:csv",
     "//components/password_manager/core/browser/import:csv_unit_tests",
diff --git a/components/password_manager/core/browser/affiliation/affiliated_match_helper.h b/components/password_manager/core/browser/affiliation/affiliated_match_helper.h
index 52546eb1..06eaf23 100644
--- a/components/password_manager/core/browser/affiliation/affiliated_match_helper.h
+++ b/components/password_manager/core/browser/affiliation/affiliated_match_helper.h
@@ -15,7 +15,7 @@
 #include "base/time/time.h"
 #include "components/password_manager/core/browser/affiliation/affiliation_utils.h"
 #include "components/password_manager/core/browser/password_form_digest.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/affiliation/affiliations_prefetcher.h b/components/password_manager/core/browser/affiliation/affiliations_prefetcher.h
index ec5de4d3..999ca393 100644
--- a/components/password_manager/core/browser/affiliation/affiliations_prefetcher.h
+++ b/components/password_manager/core/browser/affiliation/affiliations_prefetcher.h
@@ -12,8 +12,8 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/affiliation/affiliations_prefetcher_unittest.cc b/components/password_manager/core/browser/affiliation/affiliations_prefetcher_unittest.cc
index be4fba7..e57bca5c 100644
--- a/components/password_manager/core/browser/affiliation/affiliations_prefetcher_unittest.cc
+++ b/components/password_manager/core/browser/affiliation/affiliations_prefetcher_unittest.cc
@@ -22,8 +22,8 @@
 #include "components/password_manager/core/browser/affiliation/affiliation_utils.h"
 #include "components/password_manager/core/browser/affiliation/mock_affiliation_service.h"
 #include "components/password_manager/core/browser/password_form.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_store/test_password_store.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
 #include "services/network/test/test_shared_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/password_manager/core/browser/credential_manager_pending_prevent_silent_access_task.cc b/components/password_manager/core/browser/credential_manager_pending_prevent_silent_access_task.cc
index 5146485b..d773897 100644
--- a/components/password_manager/core/browser/credential_manager_pending_prevent_silent_access_task.cc
+++ b/components/password_manager/core/browser/credential_manager_pending_prevent_silent_access_task.cc
@@ -5,7 +5,7 @@
 #include "components/password_manager/core/browser/credential_manager_pending_prevent_silent_access_task.h"
 
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/credential_manager_pending_prevent_silent_access_task.h b/components/password_manager/core/browser/credential_manager_pending_prevent_silent_access_task.h
index add8b52..838199a3 100644
--- a/components/password_manager/core/browser/credential_manager_pending_prevent_silent_access_task.h
+++ b/components/password_manager/core/browser/credential_manager_pending_prevent_silent_access_task.h
@@ -10,8 +10,8 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/fake_form_fetcher.h b/components/password_manager/core/browser/fake_form_fetcher.h
index 2b23548f..7bc8ada 100644
--- a/components/password_manager/core/browser/fake_form_fetcher.h
+++ b/components/password_manager/core/browser/fake_form_fetcher.h
@@ -9,8 +9,8 @@
 
 #include "base/observer_list.h"
 #include "components/password_manager/core/browser/form_fetcher.h"
-#include "components/password_manager/core/browser/interactions_stats.h"
 #include "components/password_manager/core/browser/password_form.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/form_fetcher.h b/components/password_manager/core/browser/form_fetcher.h
index bea7810..2509855c 100644
--- a/components/password_manager/core/browser/form_fetcher.h
+++ b/components/password_manager/core/browser/form_fetcher.h
@@ -11,7 +11,7 @@
 
 #include "base/observer_list_types.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_util.h"
+#include "components/password_manager/core/browser/password_store/password_store_util.h"
 #include "components/signin/public/base/gaia_id_hash.h"
 
 namespace password_manager {
diff --git a/components/password_manager/core/browser/form_fetcher_impl.cc b/components/password_manager/core/browser/form_fetcher_impl.cc
index 736332a..3ad5a3d 100644
--- a/components/password_manager/core/browser/form_fetcher_impl.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl.cc
@@ -17,15 +17,15 @@
 #include "components/autofill/core/common/save_password_progress_logger.h"
 #include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
 #include "components/password_manager/core/browser/credentials_filter.h"
-#include "components/password_manager/core/browser/interactions_stats.h"
 #include "components/password_manager/core/browser/password_feature_manager.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_util.h"
 #include "components/password_manager/core/browser/password_store/psl_matching_helper.h"
 #include "components/password_manager/core/browser/password_store/smart_bubble_stats_store.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
-#include "components/password_manager/core/browser/password_store_util.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 
 using Logger = autofill::SavePasswordProgressLogger;
diff --git a/components/password_manager/core/browser/form_fetcher_impl.h b/components/password_manager/core/browser/form_fetcher_impl.h
index baa2050..b39c2a5 100644
--- a/components/password_manager/core/browser/form_fetcher_impl.h
+++ b/components/password_manager/core/browser/form_fetcher_impl.h
@@ -15,8 +15,8 @@
 #include "base/observer_list.h"
 #include "components/password_manager/core/browser/form_fetcher.h"
 #include "components/password_manager/core/browser/http_password_store_migrator.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
index d8966b0..1f0fd36 100644
--- a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
@@ -20,13 +20,13 @@
 #include "components/password_manager/core/browser/affiliation/affiliated_match_helper.h"
 #include "components/password_manager/core/browser/affiliation/mock_affiliated_match_helper.h"
 #include "components/password_manager/core/browser/features/password_features.h"
-#include "components/password_manager/core/browser/interactions_stats.h"
 #include "components/password_manager/core/browser/mock_password_store_interface.h"
 #include "components/password_manager/core/browser/mock_smart_bubble_stats_store.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
-#include "components/password_manager/core/browser/password_store_util.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_util.h"
 #include "components/password_manager/core/browser/stub_credentials_filter.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
 #include "components/signin/public/base/gaia_id_hash.h"
diff --git a/components/password_manager/core/browser/form_parsing/BUILD.gn b/components/password_manager/core/browser/form_parsing/BUILD.gn
index b7bb3286..40d9636e2 100644
--- a/components/password_manager/core/browser/form_parsing/BUILD.gn
+++ b/components/password_manager/core/browser/form_parsing/BUILD.gn
@@ -49,3 +49,7 @@
     "//url",
   ]
 }
+
+group("fuzzers") {
+  deps = [ "//components/password_manager/core/browser/form_parsing/fuzzer" ]
+}
diff --git a/components/password_manager/core/browser/form_parsing/fuzzer/BUILD.gn b/components/password_manager/core/browser/form_parsing/fuzzer/BUILD.gn
index bff405c1..97311687 100644
--- a/components/password_manager/core/browser/form_parsing/fuzzer/BUILD.gn
+++ b/components/password_manager/core/browser/form_parsing/fuzzer/BUILD.gn
@@ -5,16 +5,17 @@
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//third_party/protobuf/proto_library.gni")
 
+# Empty group for package discovery.
+group("fuzzer") {
+}
+
 static_library("fuzzer_support") {
   sources = [
-    "data_accessor.cc",
-    "data_accessor.h",
     "form_data_producer.cc",
     "form_data_producer.h",
   ]
 
   deps = [
-    "//base",
     "//components/autofill/core/browser",
     "//components/autofill/core/common",
     "//components/password_manager/core/browser/form_parsing",
@@ -42,29 +43,6 @@
   ]
 }
 
-source_set("unit_tests") {
-  testonly = true
-  sources = [ "data_accessor_unittest.cc" ]
-
-  deps = [
-    ":fuzzer_support",
-    "//base",
-    "//testing/gtest",
-  ]
-}
-
-# TODO(crbug.com/845426): There are currently four fuzzers, all combinations of
-# two binary parameters. The first parameter is whether the input data for the
-# fuzzed code is prepared directly from the raw fuzzing string, or from a
-# protobuf description. The second parameter is whether the fuzzed code is the
-# iOS-specific FormData parser, or the generic one. Ultimately, there will be
-# only the generic one, but currently it is under development, so both parsers
-# are used (and need to be fuzzed). The iOS parser is older and its fuzzer's
-# name did not hint at the "iOS" restriction. It is better to keep that name
-# the same, because the security team watches statistics of the fuzzers
-# (https://crbug.com/828705#c11) and renaming causes confusion. So instead, the
-# new fuzzer has the "_generic" suffix on its target name.
-
 fuzzer_test("password_manager_form_data_parser_fuzzer") {
   sources = [ "form_data_parser_fuzzer.cc" ]
 
diff --git a/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.cc b/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.cc
deleted file mode 100644
index 652be62..0000000
--- a/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.cc
+++ /dev/null
@@ -1,111 +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 "components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h"
-
-#include <string.h>
-
-#include <algorithm>
-#include <bitset>
-
-#include "base/check_op.h"
-
-namespace password_manager {
-
-namespace {
-
-// The maximum byte length of a string to be returned by |ConsumeString*|.
-constexpr size_t kMaxStringBytes = 256;
-
-}  // namespace
-
-DataAccessor::DataAccessor(const uint8_t* data, size_t size)
-    : data_(data), bits_consumed_(0), size_(size) {
-  DCHECK(data_ || size_ == 0);  // Enforce the first invariant for data members.
-}
-
-DataAccessor::~DataAccessor() = default;
-
-bool DataAccessor::ConsumeBit() {
-  return ConsumeNumber(1) != 0;
-}
-
-size_t DataAccessor::ConsumeNumber(size_t bit_length) {
-  CHECK_LE(bit_length, sizeof(size_t) * 8);
-
-  // Fast track.
-  if (bit_length == 0)
-    return 0;
-
-  // No genuine input bits left, return padding.
-  if (size_ == 0)
-    return 0;
-
-  // Compute the number recursively, processing one byte from |data_| at a time.
-  std::bitset<8> b(*data_);
-  if (bits_consumed_ + bit_length < 8) {  // Base case: all within |*data_|.
-    // Shift the |bit_length|-sized interesting window up and down to discard
-    // uninteresting bits. An alternative approach would be:
-    // b << bit_length;  // Discard consumed bits.
-    // b &= std::bitset<8>((1 << bit_length) - 1); // Discard the tail.
-    // But the shifting below avoids the construction of the temproary bitset.
-    b <<= (8 - bits_consumed_ - bit_length);
-    b >>= (8 - bit_length);
-    bits_consumed_ += bit_length;
-    return b.to_ulong();
-  }
-  // Recursive case: crossing the byte boundary in |data_|.
-  const size_t original_bits_consumed = bits_consumed_;
-  bit_length -= (8 - bits_consumed_);
-  bits_consumed_ = 0;
-  ++data_;
-  --size_;
-  return (b.to_ulong() | (ConsumeNumber(bit_length) << 8)) >>
-         original_bits_consumed;
-}
-
-void DataAccessor::ConsumeBytesToBuffer(size_t length, uint8_t* string_buffer) {
-  // First of all, align to a whole byte for efficiency.
-  if (size_ > 0 && bits_consumed_ != 0) {
-    bits_consumed_ = 0;
-    ++data_;
-    --size_;
-  }
-
-  size_t non_padded_length = std::min(length, size_);
-  memcpy(string_buffer, data_, non_padded_length);
-
-  if (non_padded_length != length) {
-    // Pad with zeroes as needed.
-    memset(string_buffer + non_padded_length, 0, length - non_padded_length);
-    // The rest of the input string was not enough, so now it's certainly
-    // depleted.
-    size_ = 0;
-  } else {
-    // There was either more of the input string than needed, or just exactly
-    // enough bytes of it. Either way, the update below reflects the new
-    // situation.
-    size_ -= length;
-    data_ += length;
-  }
-}
-
-std::string DataAccessor::ConsumeString(size_t length) {
-  CHECK_LE(length, kMaxStringBytes);
-
-  uint8_t string_buffer[kMaxStringBytes];
-  ConsumeBytesToBuffer(length, string_buffer);
-  return std::string(reinterpret_cast<const char*>(string_buffer), length);
-}
-
-std::u16string DataAccessor::ConsumeString16(size_t length) {
-  CHECK_LE(2 * length, kMaxStringBytes);
-
-  uint8_t string_buffer[kMaxStringBytes];
-  ConsumeBytesToBuffer(2 * length, string_buffer);
-  return std::u16string(
-      reinterpret_cast<std::u16string::value_type*>(string_buffer), length);
-}
-
-}  // namespace password_manager
diff --git a/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h b/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h
deleted file mode 100644
index af6467e..0000000
--- a/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h
+++ /dev/null
@@ -1,68 +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.
-
-#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_DATA_ACCESSOR_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_DATA_ACCESSOR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-
-namespace password_manager {
-
-// DataAccessor is an encapsulation over the input string delivered by the
-// fuzzer framework. It pads the input string with zeroes after its end and
-// deliveres data based on the consumed string. More details in the design doc
-// linked from https://crbug.com/827945#c2.
-class DataAccessor {
- public:
-  // Wraps the input string of length |size| at address |data|. Does not own the
-  // input string. It sets the "reading head" to the start of the string and
-  // advances it with each Consume* operation to avoid generating data from the
-  // same part of input twice.
-  DataAccessor(const uint8_t* data, size_t size);
-
-  DataAccessor(const DataAccessor&) = delete;
-  DataAccessor& operator=(const DataAccessor&) = delete;
-
-  ~DataAccessor();
-
-  // Return the next bit and advance the "reading head" by one bit.
-  bool ConsumeBit();
-
-  // Return the number stored on the next |bit_length| bits and advance the
-  // "reading head" by |bit_length| bits.
-  size_t ConsumeNumber(size_t bit_length);
-
-  // Advance the "reading head" to the next whole-byte boundary, if needed, then
-  // return the string stored in the next |length| characters, advancing the
-  // "reading head" to point past the read data. A "character" means byte for
-  // std::string and two bytes for std::u16string. At most 256 bytes can be
-  // consumed at once, hence |length| is restricted as noted below.
-  std::string ConsumeString(size_t length);       // |length| <= 256
-  std::u16string ConsumeString16(size_t length);  // |length| <= 128
-
- private:
-  // Helper for |ConsumeString*|. It combines the |data_| and padding, if
-  // needed, into |string_buffer|, to provide |length| bytes for creating a new
-  // string. It also updates |data_|, |bits_consumed_| and |size_| accordingly.
-  void ConsumeBytesToBuffer(size_t length, uint8_t* string_buffer);
-
-  // The remaining portion of the input string (without padding) starts at
-  // |data_| without the least significant |bits_consumed_| bits, and lasts
-  // until |data_ + size_|, exclusively. If |size_| is 0, then there is not a
-  // single bit left and all available is just the 0-padding.
-  // Invariants:
-  // * |data_| is not null as long as |size_| > 0
-  // * |bits_consumed_| < 8
-  // * if |size_| == 0 then |bits_consumed_| == 0
-  const uint8_t* data_;
-  size_t bits_consumed_;
-  size_t size_;
-};
-
-}  // namespace password_manager
-
-#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_DATA_ACCESSOR_H_
diff --git a/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor_unittest.cc b/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor_unittest.cc
deleted file mode 100644
index 10c7f1c..0000000
--- a/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor_unittest.cc
+++ /dev/null
@@ -1,93 +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 "components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h"
-
-#include <string>
-
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::UTF8ToUTF16;
-
-namespace password_manager {
-
-namespace {
-
-TEST(DataAccessorTest, NullInput) {
-  DataAccessor accessor(nullptr, 0);
-  EXPECT_EQ(0u, accessor.ConsumeNumber(13));
-  EXPECT_EQ(false, accessor.ConsumeBit());
-  EXPECT_EQ(std::string("\0\0\0", 3), accessor.ConsumeString(3));
-  EXPECT_EQ(std::u16string(), accessor.ConsumeString16(0));
-}
-
-TEST(DataAccessorTest, Bit) {
-  const uint8_t x = 0b10110001;
-  DataAccessor accessor(&x, 1);
-  EXPECT_EQ(true, accessor.ConsumeBit());
-  EXPECT_EQ(false, accessor.ConsumeBit());
-  EXPECT_EQ(false, accessor.ConsumeBit());
-  EXPECT_EQ(false, accessor.ConsumeBit());
-  EXPECT_EQ(true, accessor.ConsumeBit());
-  EXPECT_EQ(true, accessor.ConsumeBit());
-  EXPECT_EQ(false, accessor.ConsumeBit());
-  EXPECT_EQ(true, accessor.ConsumeBit());
-}
-
-TEST(DataAccessorTest, Number) {
-  const uint8_t xs[] = {0b01100110, 0b11100110};
-  DataAccessor accessor(xs, sizeof(xs));
-  accessor.ConsumeBit();  // Just skip the first bit for fun.
-  EXPECT_EQ(0b011u, accessor.ConsumeNumber(3));
-  EXPECT_EQ(0b0u, accessor.ConsumeNumber(1));
-  EXPECT_EQ(0b11u, accessor.ConsumeNumber(2));
-  // 10 (2nd byte) ++ 0 (1st byte):
-  EXPECT_EQ(0b100u, accessor.ConsumeNumber(3));
-  EXPECT_EQ(0u, accessor.ConsumeNumber(0));  // An empty string represents 0.
-  EXPECT_EQ(0b11001u, accessor.ConsumeNumber(5));
-  EXPECT_EQ(0b01u, accessor.ConsumeNumber(2));       // 1, also reaching padding
-  EXPECT_EQ(0b0000000u, accessor.ConsumeNumber(7));  // padding
-}
-
-TEST(DataAccessorTest, String) {
-  const std::string str = "Test string 123.";
-  DataAccessor accessor(reinterpret_cast<const uint8_t*>(str.c_str()),
-                        str.size());
-  EXPECT_EQ("Test", accessor.ConsumeString(4));
-  accessor.ConsumeNumber(3);  // Skip 3 bits to test re-alignment.
-  EXPECT_EQ("string 123", accessor.ConsumeString(10));
-  EXPECT_EQ(std::string(), accessor.ConsumeString(0));
-  // Test also that padding is included.
-  EXPECT_EQ(std::string(".\0\0", 3), accessor.ConsumeString(3));
-}
-
-TEST(DataAccessorTest, String16) {
-  const std::u16string str = u"Test string 123.";
-  DataAccessor accessor(reinterpret_cast<const uint8_t*>(str.c_str()),
-                        str.size() * 2);
-  EXPECT_EQ(u"Test", accessor.ConsumeString16(4));
-  accessor.ConsumeNumber(13);  // Skip 13 bits to test re-alignment.
-  EXPECT_EQ(u"string 123", accessor.ConsumeString16(10));
-  EXPECT_EQ(std::u16string(), accessor.ConsumeString16(0));
-  // Test also that padding is included.
-  EXPECT_EQ(UTF8ToUTF16(std::string(".\0\0", 3)), accessor.ConsumeString16(3));
-}
-
-TEST(DataAccessorTest, Mix) {
-  const uint8_t xs[] = {'a',        'b', 0b11100101, 5,   9,
-                        0b10000001, 'c', 'd',        'e', 0};
-  DataAccessor accessor(xs, sizeof(xs));
-  EXPECT_EQ("ab", accessor.ConsumeString(2));
-  EXPECT_EQ(true, accessor.ConsumeBit());
-  EXPECT_EQ(0b1110010u, accessor.ConsumeNumber(7));
-  EXPECT_EQ(5u, accessor.ConsumeNumber(8));
-  EXPECT_EQ(9u + (1u << 8), accessor.ConsumeNumber(9));
-  EXPECT_EQ(false, accessor.ConsumeBit());
-  EXPECT_EQ("cd", accessor.ConsumeString(2));
-  EXPECT_EQ(u"e", accessor.ConsumeString16(1));
-}
-}  // namespace
-
-}  // namespace password_manager
diff --git a/components/password_manager/core/browser/form_parsing/fuzzer/form_data_parser_fuzzer.cc b/components/password_manager/core/browser/form_parsing/fuzzer/form_data_parser_fuzzer.cc
index f86d013d..e86969c 100644
--- a/components/password_manager/core/browser/form_parsing/fuzzer/form_data_parser_fuzzer.cc
+++ b/components/password_manager/core/browser/form_parsing/fuzzer/form_data_parser_fuzzer.cc
@@ -7,16 +7,17 @@
 
 #include <memory>
 
+#include <fuzzer/FuzzedDataProvider.h>
+
 #include "base/at_exit.h"
 #include "base/i18n/icu_util.h"
 #include "components/password_manager/core/browser/form_parsing/form_data_parser.h"
-#include "components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h"
 #include "components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h"
 #include "components/password_manager/core/browser/password_form.h"
 
 namespace password_manager {
 
-// ICU is used inside GURL parser, which is used by GenerateWithDataAccessor.
+// ICU is used inside GURL parser, which is used by GenerateFormData.
 struct IcuEnvironment {
   IcuEnvironment() { CHECK(base::i18n::InitializeICU()); }
   // used by ICU integration.
@@ -26,15 +27,14 @@
 IcuEnvironment* env = new IcuEnvironment();
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  DataAccessor accessor(data, size);
-  FormDataParser::Mode mode = accessor.ConsumeBit()
-                                  ? FormDataParser::Mode::kFilling
-                                  : FormDataParser::Mode::kSaving;
+  FuzzedDataProvider data_provider(data, size);
+  const auto mode = data_provider.ConsumeBool() ? FormDataParser::Mode::kFilling
+                                                : FormDataParser::Mode::kSaving;
 
-  bool use_predictions = accessor.ConsumeBit();
+  const bool use_predictions = data_provider.ConsumeBool();
   FormPredictions predictions;
-  autofill::FormData form_data = GenerateWithDataAccessor(
-      &accessor, use_predictions ? &predictions : nullptr);
+  autofill::FormData form_data =
+      GenerateFormData(data_provider, use_predictions ? &predictions : nullptr);
 
   FormDataParser parser;
   if (use_predictions)
diff --git a/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.cc b/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.cc
index 59b6fe9a..d629e3b 100644
--- a/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.cc
+++ b/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.cc
@@ -4,15 +4,17 @@
 
 #include "components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h"
 
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/types/cxx23_to_underlying.h"
+#include <string>
+#include <utility>
+
+#include <fuzzer/FuzzedDataProvider.h>
+
 #include "build/build_config.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/autofill/core/common/signatures.h"
 #include "components/autofill/core/common/unique_ids.h"
-#include "components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h"
+#include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -30,148 +32,118 @@
     autofill::NEW_PASSWORD, autofill::CONFIRMATION_PASSWORD,
     autofill::NOT_PASSWORD};
 
-struct FormFieldDataParams {
-  size_t form_control_type_length;
-  size_t autocomplete_attribute_length;
-  size_t label_length;
-  size_t name_length;
-  size_t id_length;
-  size_t value_length;
-  // In an array of FormFieldData, all instances with |same_value_field| true
-  // get the same value as the first such instance.
-  bool same_value_field;
-};
-
-// With probability 0.5 returns true and generates |prediction|, with
-// probability 0.5 returns false. Uses |accessor| as a source of randomness.
-bool MaybeGenerateFieldPrediction(DataAccessor* accessor,
-                                  PasswordFieldPrediction* prediction) {
-  bool generate_prediction = accessor->ConsumeBit();
-  if (!generate_prediction)
-    return false;
-  prediction->may_use_prefilled_placeholder = accessor->ConsumeBit();
-  const size_t prediction_idx = accessor->ConsumeNumber(3);
-  if (prediction_idx < std::size(kPasswordRelatedServerTypes)) {
-    prediction->type = kPasswordRelatedServerTypes[prediction_idx];
+void SetPredictionType(bool pick_meaningful_type,
+                       FuzzedDataProvider& provider,
+                       PasswordFieldPrediction& prediction) {
+  if (pick_meaningful_type) {
+    prediction.type = provider.PickValueInArray(kPasswordRelatedServerTypes);
   } else {
-    // Set random type, probably even invalid. FormParser should gracefully
-    // treat any type.
-    prediction->type = static_cast<ServerFieldType>(accessor->ConsumeNumber(8));
+    // Set a random type, probably even invalid.
+    prediction.type =
+        static_cast<ServerFieldType>(provider.ConsumeIntegral<uint8_t>());
   }
-  return true;
+}
+
+// A wrapper to get |std::u16string| from a |FuzzedDataProvider|. The result is
+// arbitrary bytes, not necessarily valid UTF16.
+std::u16string ConsumeU16String(FuzzedDataProvider& provider) {
+  // |FuzzedDataProvider| takes special steps to pick the length of the string
+  // to support evolution of the fuzzed input. Let's follow whatever it does.
+  const std::string s8 = provider.ConsumeRandomLengthString();
+  return std::u16string(
+      reinterpret_cast<const std::u16string::value_type*>(s8.data()),
+      s8.size() / 2);
 }
 
 }  // namespace
 
-autofill::FormData GenerateWithDataAccessor(
-    password_manager::DataAccessor* accessor,
-    FormPredictions* predictions) {
+autofill::FormData GenerateFormData(FuzzedDataProvider& provider,
+                                    FormPredictions* predictions) {
   FormData result;
 
-  // First determine the main non-string attributes not specific to particular
-  // fields.
-  result.is_form_tag = accessor->ConsumeBit();
+  result.is_form_tag = provider.ConsumeBool();
 
-  // To minimize wasting bits, string-based data itself gets extracted after all
-  // numbers and flags are. Their length can be determined now, however. A
-  // reasonable range is 0-127 characters, i.e., 7 bits.
-  const size_t name_length = accessor->ConsumeNumber(7);
-  const size_t action_length = accessor->ConsumeNumber(7);
-  const size_t origin_length = accessor->ConsumeNumber(7);
-  const size_t main_frame_origin_length = accessor->ConsumeNumber(7);
-
-  // Determine how many fields this form will have. 0-15, i.e., 4 bits.
-  const size_t number_of_fields = accessor->ConsumeNumber(4);
+  // Determine how many fields this form will have. Pick a low value because
+  // after the fuzzer's seed is exhausted, all will be 0s anyway.
+  const size_t number_of_fields =
+      provider.ConsumeIntegralInRange<size_t>(0, 15);
   result.fields.resize(number_of_fields);
-  FormFieldDataParams field_params[15];
+
+  result.name = ConsumeU16String(provider);
+  result.action = GURL(provider.ConsumeRandomLengthString());
+  result.url = GURL(provider.ConsumeRandomLengthString());
+  result.main_frame_origin =
+      url::Origin::Create(GURL(provider.ConsumeRandomLengthString()));
+
+  if (predictions) {
+    predictions->driver_id = provider.ConsumeIntegral<int>();
+    predictions->form_signature =
+        autofill::FormSignature(provider.ConsumeIntegral<uint64_t>());
+  }
 
   int first_field_with_same_value = -1;
   for (size_t i = 0; i < number_of_fields; ++i) {
-    // Determine the non-string value for each field.
-    result.fields[i].is_focusable = accessor->ConsumeBit();
-    // And the lengths of the string values.
-    field_params[i].form_control_type_length = accessor->ConsumeNumber(7);
-    field_params[i].autocomplete_attribute_length = accessor->ConsumeNumber(7);
-    field_params[i].label_length = accessor->ConsumeNumber(7);
-    field_params[i].name_length = accessor->ConsumeNumber(7);
-    field_params[i].id_length = accessor->ConsumeNumber(7);
-    field_params[i].same_value_field = accessor->ConsumeBit();
-    bool has_value_copy_from_earlier = field_params[i].same_value_field;
-    if (field_params[i].same_value_field && first_field_with_same_value == -1) {
-      first_field_with_same_value = static_cast<int>(i);
-      has_value_copy_from_earlier = false;
-    }
-    // Emtpy values are interesting from the parsing perspective. Ensure that a
-    // big chunk of the cases ends up with an empty value by letting an input
-    // bit decide.
-    field_params[i].value_length = 0;
-    if (!has_value_copy_from_earlier && accessor->ConsumeBit()) {
-      field_params[i].value_length = accessor->ConsumeNumber(7) + 1;
-    }
-  }
+    // Batch getting bits from the FuzzedDataProvider, because calling
+    // `ConsumeBool` throws out 7 bits and we need many Booleans for each
+    // iteration.
+    const auto packed_bools = provider.ConsumeIntegral<uint8_t>();
+    // All instances with |same_value_field| true share the same value.
+    const bool same_value_field = packed_bools & 1;
+    // Empty values are interesting from the parsing perspective. Ensure that
+    // at least half of the cases ends up with an empty value.
+    const bool force_empty_value = packed_bools & (1 << 1);
+    result.fields[i].is_focusable = packed_bools & (1 << 2);
+    const bool generate_prediction = packed_bools & (1 << 3);
+    const bool pick_meaningful_type = packed_bools & (1 << 4);
+    const bool use_placeholder = packed_bools & (1 << 5);
 
-  // Now go back and determine the string-based values of the form itself.
-  result.name = accessor->ConsumeString16(name_length);
-  result.action = GURL(accessor->ConsumeString(action_length));
-  result.url = GURL(accessor->ConsumeString(origin_length));
-  result.main_frame_origin = url::Origin::Create(
-      GURL(accessor->ConsumeString(main_frame_origin_length)));
-
-  if (predictions) {
-    predictions->driver_id = static_cast<int>(accessor->ConsumeNumber(32));
-    predictions->form_signature = autofill::FormSignature(
-        (static_cast<uint64_t>(accessor->ConsumeNumber(32)) << 32) +
-        accessor->ConsumeNumber(32));
-  }
-
-  // And finally do the same for all the fields.
-  for (size_t i = 0; i < number_of_fields; ++i) {
-    result.fields[i].form_control_type = static_cast<autofill::FormControlType>(
-        base::to_underlying(autofill::FormControlType::kMinValue) +
-        (accessor->ConsumeNumber(32) %
-         (base::to_underlying(autofill::FormControlType::kMaxValue) -
-          base::to_underlying(autofill::FormControlType::kMinValue) + 1)));
+    result.fields[i].form_control_type =
+        provider.ConsumeEnum<autofill::FormControlType>();
     result.fields[i].autocomplete_attribute =
-        accessor->ConsumeString(field_params[i].autocomplete_attribute_length);
-    result.fields[i].label =
-        accessor->ConsumeString16(field_params[i].label_length);
-    result.fields[i].name =
-        accessor->ConsumeString16(field_params[i].name_length);
+        provider.ConsumeRandomLengthString();
+    result.fields[i].label = ConsumeU16String(provider);
+    result.fields[i].name = ConsumeU16String(provider);
     result.fields[i].name_attribute = result.fields[i].name;
-    result.fields[i].id_attribute =
-        accessor->ConsumeString16(field_params[i].id_length);
-    // Check both positive and negatives numbers for renderer ids.
+    result.fields[i].id_attribute = ConsumeU16String(provider);
     result.fields[i].unique_renderer_id =
-        autofill::FieldRendererId(accessor->ConsumeNumber(6) - 32);
-    if (predictions) {
+        autofill::FieldRendererId(provider.ConsumeIntegralInRange(-32, 31));
+    if (predictions && generate_prediction) {
       PasswordFieldPrediction field_prediction;
-      if (MaybeGenerateFieldPrediction(accessor, &field_prediction)) {
-        field_prediction.renderer_id = result.fields[i].unique_renderer_id;
-        predictions->fields.push_back(field_prediction);
-      }
+      SetPredictionType(pick_meaningful_type, provider, field_prediction);
+      field_prediction.may_use_prefilled_placeholder = use_placeholder;
+      field_prediction.renderer_id = result.fields[i].unique_renderer_id;
+      predictions->fields.push_back(std::move(field_prediction));
     }
 
-    if (field_params[i].same_value_field &&
-        first_field_with_same_value != static_cast<int>(i)) {
-      result.fields[i].value = result.fields[first_field_with_same_value].value;
-    } else {
-      result.fields[i].value =
-          accessor->ConsumeString16(field_params[i].value_length);
+    if (same_value_field) {
+      if (first_field_with_same_value == -1) {
+        first_field_with_same_value = static_cast<int>(i);
+      } else {
+        result.fields[i].value =
+            result.fields[first_field_with_same_value].value;
+      }
+    } else if (!force_empty_value) {
+      result.fields[i].value = ConsumeU16String(provider);
     }
   }
 
-  if (predictions) {
-    // Generate predictions for non-existing fields.
-    size_t n_predictions = accessor->ConsumeNumber(4);
+  if (!predictions) {
+    return result;
+  }
+
+  // Generate predictions for non-existing fields.
+  const size_t num_predictions = provider.ConsumeIntegralInRange(0, 15);
+  for (size_t i = 0; i < num_predictions; ++i) {
+    const auto packed_bools = provider.ConsumeIntegral<uint8_t>();
+    const bool pick_meaningful_type = packed_bools & 1;
+    const bool use_placeholder = packed_bools & (1 << 2);
+
     PasswordFieldPrediction field_prediction;
-    for (size_t i = 0; i < n_predictions; ++i) {
-      if (MaybeGenerateFieldPrediction(accessor, &field_prediction)) {
-        // Check both positive and negavites numbers for renderer ids.
-        field_prediction.renderer_id =
-            autofill::FieldRendererId(accessor->ConsumeNumber(6) - 32);
-        predictions->fields.push_back(field_prediction);
-      }
-    }
+    SetPredictionType(pick_meaningful_type, provider, field_prediction);
+    field_prediction.may_use_prefilled_placeholder = use_placeholder;
+    field_prediction.renderer_id =
+        autofill::FieldRendererId(provider.ConsumeIntegralInRange(-32, 31));
+    predictions->fields.push_back(std::move(field_prediction));
   }
 
   return result;
diff --git a/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h b/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h
index 0e14ba4..fcc52065 100644
--- a/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h
+++ b/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h
@@ -6,16 +6,17 @@
 #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_FORM_DATA_PRODUCER_H_
 
 #include "components/autofill/core/common/form_data.h"
-#include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
+
+class FuzzedDataProvider;
 
 namespace password_manager {
 
-class DataAccessor;
+struct FormPredictions;
 
-// Generates a |FormData| and |predictions| object based on values obtained via
-// |accessor|. See https://goo.gl/29t6VH for a detailed design.
-autofill::FormData GenerateWithDataAccessor(DataAccessor* accessor,
-                                            FormPredictions* predictions);
+// Generates a |FormData| and (optionally) |predictions| object based on values
+// obtained via |provider|. See https://goo.gl/29t6VH for a detailed design.
+autofill::FormData GenerateFormData(FuzzedDataProvider& provider,
+                                    FormPredictions* predictions);
 
 }  // namespace password_manager
 
diff --git a/components/password_manager/core/browser/form_saver.h b/components/password_manager/core/browser/form_saver.h
index 330157b..35a2e2f 100644
--- a/components/password_manager/core/browser/form_saver.h
+++ b/components/password_manager/core/browser/form_saver.h
@@ -10,7 +10,7 @@
 #include <string>
 #include <vector>
 
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/form_saver_impl.cc b/components/password_manager/core/browser/form_saver_impl.cc
index e2b18d0..40fa7df5 100644
--- a/components/password_manager/core/browser/form_saver_impl.cc
+++ b/components/password_manager/core/browser/form_saver_impl.cc
@@ -12,7 +12,7 @@
 #include "base/time/time.h"
 #include "components/password_manager/core/browser/affiliation/affiliation_utils.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
diff --git a/components/password_manager/core/browser/http_auth_manager_unittest.cc b/components/password_manager/core/browser/http_auth_manager_unittest.cc
index 6d38877..732c8d5 100644
--- a/components/password_manager/core/browser/http_auth_manager_unittest.cc
+++ b/components/password_manager/core/browser/http_auth_manager_unittest.cc
@@ -25,8 +25,8 @@
 #include "components/password_manager/core/browser/password_form_manager.h"
 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
 #include "components/password_manager/core/browser/password_manager_driver.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/password_manager/core/browser/http_credentials_cleaner.cc b/components/password_manager/core/browser/http_credentials_cleaner.cc
index bdfe15e..8644b5e 100644
--- a/components/password_manager/core/browser/http_credentials_cleaner.cc
+++ b/components/password_manager/core/browser/http_credentials_cleaner.cc
@@ -10,7 +10,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "components/password_manager/core/browser/http_password_store_migrator.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "url/gurl.h"
diff --git a/components/password_manager/core/browser/http_credentials_cleaner.h b/components/password_manager/core/browser/http_credentials_cleaner.h
index 0060128..2b74a28 100644
--- a/components/password_manager/core/browser/http_credentials_cleaner.h
+++ b/components/password_manager/core/browser/http_credentials_cleaner.h
@@ -19,7 +19,7 @@
 #include "components/password_manager/core/browser/credentials_cleaner.h"
 #include "components/password_manager/core/browser/hsts_query.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 
 namespace network {
 namespace mojom {
diff --git a/components/password_manager/core/browser/http_password_store_migrator.cc b/components/password_manager/core/browser/http_password_store_migrator.cc
index 2ce75f1..86be0b48 100644
--- a/components/password_manager/core/browser/http_password_store_migrator.cc
+++ b/components/password_manager/core/browser/http_password_store_migrator.cc
@@ -14,8 +14,8 @@
 #include "base/strings/strcat.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_store/smart_bubble_stats_store.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
 #include "url/gurl.h"
 #include "url/url_constants.h"
 
diff --git a/components/password_manager/core/browser/http_password_store_migrator.h b/components/password_manager/core/browser/http_password_store_migrator.h
index 8e415387..12f4cac 100644
--- a/components/password_manager/core/browser/http_password_store_migrator.h
+++ b/components/password_manager/core/browser/http_password_store_migrator.h
@@ -12,7 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
 #include "components/password_manager/core/browser/hsts_query.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "url/origin.h"
 
 namespace password_manager {
diff --git a/components/password_manager/core/browser/insecure_credentials_helper.cc b/components/password_manager/core/browser/insecure_credentials_helper.cc
index 024a5c4..62e6913 100644
--- a/components/password_manager/core/browser/insecure_credentials_helper.cc
+++ b/components/password_manager/core/browser/insecure_credentials_helper.cc
@@ -12,8 +12,8 @@
 #include "base/memory/raw_ptr.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_reuse_detector.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/insecure_credentials_helper_unittest.cc b/components/password_manager/core/browser/insecure_credentials_helper_unittest.cc
index 11e8b7af..917d949 100644
--- a/components/password_manager/core/browser/insecure_credentials_helper_unittest.cc
+++ b/components/password_manager/core/browser/insecure_credentials_helper_unittest.cc
@@ -10,7 +10,7 @@
 #include "components/password_manager/core/browser/mock_password_store_interface.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/password_manager/core/browser/leak_detection_delegate.cc b/components/password_manager/core/browser/leak_detection_delegate.cc
index 0ef8dfac..609ce98a 100644
--- a/components/password_manager/core/browser/leak_detection_delegate.cc
+++ b/components/password_manager/core/browser/leak_detection_delegate.cc
@@ -16,7 +16,7 @@
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
diff --git a/components/password_manager/core/browser/leak_detection_delegate_helper.cc b/components/password_manager/core/browser/leak_detection_delegate_helper.cc
index 944c3851..34bc45b 100644
--- a/components/password_manager/core/browser/leak_detection_delegate_helper.cc
+++ b/components/password_manager/core/browser/leak_detection_delegate_helper.cc
@@ -10,8 +10,8 @@
 #include "base/ranges/algorithm.h"
 #include "components/password_manager/core/browser/leak_detection/encryption_utils.h"
 #include "components/password_manager/core/browser/password_form.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_store/psl_matching_helper.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/leak_detection_delegate_helper.h b/components/password_manager/core/browser/leak_detection_delegate_helper.h
index 9d633ee..c0eb0e3 100644
--- a/components/password_manager/core/browser/leak_detection_delegate_helper.h
+++ b/components/password_manager/core/browser/leak_detection_delegate_helper.h
@@ -14,7 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "url/gurl.h"
 
 namespace password_manager {
diff --git a/components/password_manager/core/browser/leak_detection_delegate_unittest.cc b/components/password_manager/core/browser/leak_detection_delegate_unittest.cc
index 10a8ed2..0931fcc 100644
--- a/components/password_manager/core/browser/leak_detection_delegate_unittest.cc
+++ b/components/password_manager/core/browser/leak_detection_delegate_unittest.cc
@@ -20,7 +20,7 @@
 #include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
 #include "components/password_manager/core/browser/mock_password_store_interface.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
diff --git a/components/password_manager/core/browser/mock_password_store_consumer.h b/components/password_manager/core/browser/mock_password_store_consumer.h
index 34239bed..f09d407f 100644
--- a/components/password_manager/core/browser/mock_password_store_consumer.h
+++ b/components/password_manager/core/browser/mock_password_store_consumer.h
@@ -7,7 +7,7 @@
 
 #include <memory>
 
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace password_manager {
diff --git a/components/password_manager/core/browser/mock_password_store_interface.h b/components/password_manager/core/browser/mock_password_store_interface.h
index e1f3159..a458df9 100644
--- a/components/password_manager/core/browser/mock_password_store_interface.h
+++ b/components/password_manager/core/browser/mock_password_store_interface.h
@@ -5,7 +5,7 @@
 #ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_MOCK_PASSWORD_STORE_INTERFACE_H_
 #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_MOCK_PASSWORD_STORE_INTERFACE_H_
 
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/sync/model/proxy_model_type_controller_delegate.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
diff --git a/components/password_manager/core/browser/old_google_credentials_cleaner.cc b/components/password_manager/core/browser/old_google_credentials_cleaner.cc
index d5057f6..5b755a0ce 100644
--- a/components/password_manager/core/browser/old_google_credentials_cleaner.cc
+++ b/components/password_manager/core/browser/old_google_credentials_cleaner.cc
@@ -6,7 +6,7 @@
 
 #include "base/time/time.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
 
diff --git a/components/password_manager/core/browser/old_google_credentials_cleaner.h b/components/password_manager/core/browser/old_google_credentials_cleaner.h
index 32d079f..74d05e6 100644
--- a/components/password_manager/core/browser/old_google_credentials_cleaner.h
+++ b/components/password_manager/core/browser/old_google_credentials_cleaner.h
@@ -9,7 +9,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "components/password_manager/core/browser/credentials_cleaner.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 
 class PrefService;
 
diff --git a/components/password_manager/core/browser/password_counter.cc b/components/password_manager/core/browser/password_counter.cc
index 9a7b4c3..5b64c80 100644
--- a/components/password_manager/core/browser/password_counter.cc
+++ b/components/password_manager/core/browser/password_counter.cc
@@ -9,7 +9,7 @@
 #include "base/check_op.h"
 #include "base/notreached.h"
 #include "components/password_manager/core/browser/password_store/password_store_backend.h"
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/password_counter.h b/components/password_manager/core/browser/password_counter.h
index 6c7ac4e..56fcd7a 100644
--- a/components/password_manager/core/browser/password_counter.h
+++ b/components/password_manager/core/browser/password_counter.h
@@ -8,8 +8,8 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index f10231d9b..1a39c407 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -34,7 +34,7 @@
 #include "components/password_manager/core/browser/form_fetcher_impl.h"
 #include "components/password_manager/core/browser/form_parsing/form_data_parser.h"
 #include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
-#include "components/password_manager/core/browser/interactions_stats.h"
+#include "components/password_manager/core/browser/password_change_success_tracker_impl.h"
 #include "components/password_manager/core/browser/password_feature_manager.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_form_filling.h"
@@ -43,8 +43,9 @@
 #include "components/password_manager/core/browser/password_manager_driver.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
+#include "components/password_manager/core/browser/password_store/password_store_backend_error.h"
 #include "components/password_manager/core/browser/password_store/psl_matching_helper.h"
-#include "components/password_manager/core/browser/password_store_backend_error.h"
 #include "components/password_manager/core/browser/possible_username_data.h"
 #include "components/password_manager/core/browser/votes_uploader.h"
 #include "components/password_manager/core/common/password_manager_features.h"
diff --git a/components/password_manager/core/browser/password_form_metrics_recorder.cc b/components/password_manager/core/browser/password_form_metrics_recorder.cc
index 2eabc693..0f83c3b 100644
--- a/components/password_manager/core/browser/password_form_metrics_recorder.cc
+++ b/components/password_manager/core/browser/password_form_metrics_recorder.cc
@@ -20,10 +20,10 @@
 #include "components/autofill/core/common/password_generation_util.h"
 #include "components/password_manager/core/browser/affiliation/affiliation_utils.h"
 #include "components/password_manager/core/browser/form_fetcher.h"
-#include "components/password_manager/core/browser/interactions_stats.h"
 #include "components/password_manager/core/browser/password_bubble_experiment.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
 
diff --git a/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc b/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc
index a5f042e..e724763c 100644
--- a/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc
+++ b/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc
@@ -18,9 +18,9 @@
 #include "build/build_config.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
-#include "components/password_manager/core/browser/interactions_stats.h"
 #include "components/password_manager/core/browser/password_manager.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "components/ukm/test_ukm_recorder.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
diff --git a/components/password_manager/core/browser/password_manager_client.h b/components/password_manager/core/browser/password_manager_client.h
index 42a31d0..1a00017 100644
--- a/components/password_manager/core/browser/password_manager_client.h
+++ b/components/password_manager/core/browser/password_manager_client.h
@@ -21,7 +21,7 @@
 #include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
 #include "components/password_manager/core/browser/manage_passwords_referrer.h"
 #include "components/password_manager/core/browser/password_manager.h"
-#include "components/password_manager/core/browser/password_store_backend_error.h"
+#include "components/password_manager/core/browser/password_store/password_store_backend_error.h"
 #include "components/password_manager/core/browser/webauthn_credentials_delegate.h"
 #include "components/profile_metrics/browser_profile_type.h"
 #include "components/safe_browsing/buildflags.h"
diff --git a/components/password_manager/core/browser/password_manager_test_utils.h b/components/password_manager/core/browser/password_manager_test_utils.h
index 8c19ef2..0b334d9 100644
--- a/components/password_manager/core/browser/password_manager_test_utils.h
+++ b/components/password_manager/core/browser/password_manager_test_utils.h
@@ -16,7 +16,7 @@
 #include "components/password_manager/core/browser/password_reuse_detector.h"
 #include "components/password_manager/core/browser/password_reuse_detector_consumer.h"
 #include "components/password_manager/core/browser/password_reuse_manager.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "url/gurl.h"
 
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index acff5a8..dba4d0d 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -48,8 +48,8 @@
 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_manager_driver.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_store/test_password_store.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
 #include "components/password_manager/core/browser/possible_username_data.h"
 #include "components/password_manager/core/browser/stub_credentials_filter.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
diff --git a/components/password_manager/core/browser/password_reuse_detector.cc b/components/password_manager/core/browser/password_reuse_detector.cc
index 26d9fd2..286b3d20a 100644
--- a/components/password_manager/core/browser/password_reuse_detector.cc
+++ b/components/password_manager/core/browser/password_reuse_detector.cc
@@ -14,8 +14,8 @@
 #include "components/password_manager/core/browser/password_hash_data.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_reuse_detector_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "components/password_manager/core/browser/password_store/psl_matching_helper.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
 #include "components/safe_browsing/core/common/features.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "google_apis/gaia/gaia_auth_util.h"
diff --git a/components/password_manager/core/browser/password_reuse_detector.h b/components/password_manager/core/browser/password_reuse_detector.h
index 054e357..520780c0 100644
--- a/components/password_manager/core/browser/password_reuse_detector.h
+++ b/components/password_manager/core/browser/password_reuse_detector.h
@@ -14,7 +14,7 @@
 
 #include "components/password_manager/core/browser/hash_password_manager.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace password_manager {
diff --git a/components/password_manager/core/browser/password_reuse_manager_impl.h b/components/password_manager/core/browser/password_reuse_manager_impl.h
index b82d251..9821f82 100644
--- a/components/password_manager/core/browser/password_reuse_manager_impl.h
+++ b/components/password_manager/core/browser/password_reuse_manager_impl.h
@@ -12,8 +12,8 @@
 #include "base/task/sequenced_task_runner.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_reuse_manager.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace password_manager {
diff --git a/components/password_manager/core/browser/password_save_manager.h b/components/password_manager/core/browser/password_save_manager.h
index 9832285..b7966b3 100644
--- a/components/password_manager/core/browser/password_save_manager.h
+++ b/components/password_manager/core/browser/password_save_manager.h
@@ -5,7 +5,7 @@
 #ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_SAVE_MANAGER_H_
 #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_SAVE_MANAGER_H_
 
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 namespace autofill {
 struct FormData;
diff --git a/components/password_manager/core/browser/password_store/get_logins_with_affiliations_request_handler.cc b/components/password_manager/core/browser/password_store/get_logins_with_affiliations_request_handler.cc
index 6aa96d73..73547d8 100644
--- a/components/password_manager/core/browser/password_store/get_logins_with_affiliations_request_handler.cc
+++ b/components/password_manager/core/browser/password_store/get_logins_with_affiliations_request_handler.cc
@@ -21,7 +21,7 @@
 #include "components/password_manager/core/browser/features/password_features.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "components/password_manager/core/browser/password_store/psl_matching_helper.h"
 #include "url/origin.h"
 
diff --git a/components/password_manager/core/browser/password_store/get_logins_with_affiliations_request_handler_unittest.cc b/components/password_manager/core/browser/password_store/get_logins_with_affiliations_request_handler_unittest.cc
index f9f071f..5bc704e 100644
--- a/components/password_manager/core/browser/password_store/get_logins_with_affiliations_request_handler_unittest.cc
+++ b/components/password_manager/core/browser/password_store/get_logins_with_affiliations_request_handler_unittest.cc
@@ -19,7 +19,7 @@
 #include "components/password_manager/core/browser/mock_password_store_consumer.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
-#include "components/password_manager/core/browser/password_store_backend_error.h"
+#include "components/password_manager/core/browser/password_store/password_store_backend_error.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/password_manager/core/browser/interactions_stats.cc b/components/password_manager/core/browser/password_store/interactions_stats.cc
similarity index 84%
rename from components/password_manager/core/browser/interactions_stats.cc
rename to components/password_manager/core/browser/password_store/interactions_stats.cc
index dcd8652..c08e6b3 100644
--- a/components/password_manager/core/browser/interactions_stats.cc
+++ b/components/password_manager/core/browser/password_store/interactions_stats.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/password_manager/core/browser/interactions_stats.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
 
 namespace password_manager {
 
@@ -13,5 +13,4 @@
          lhs.update_time == rhs.update_time;
 }
 
-} // namespace password_manager
- 
\ No newline at end of file
+} // namespace password_manager
\ No newline at end of file
diff --git a/components/password_manager/core/browser/interactions_stats.h b/components/password_manager/core/browser/password_store/interactions_stats.h
similarity index 72%
rename from components/password_manager/core/browser/interactions_stats.h
rename to components/password_manager/core/browser/password_store/interactions_stats.h
index 63efa14..a3b9383 100644
--- a/components/password_manager/core/browser/interactions_stats.h
+++ b/components/password_manager/core/browser/password_store/interactions_stats.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_INTERACTIONS_STATS_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_INTERACTIONS_STATS_H_
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_INTERACTIONS_STATS_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_INTERACTIONS_STATS_H_
 
 #include "base/time/time.h"
 #include "url/gurl.h"
@@ -29,4 +29,4 @@
 
 } // namespace password_manager
 
-#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_INTERACTIONS_STATS_H_
\ No newline at end of file
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_INTERACTIONS_STATS_H_
\ No newline at end of file
diff --git a/components/password_manager/core/browser/password_store/login_database.cc b/components/password_manager/core/browser/password_store/login_database.cc
index 9924c03..06e551af 100644
--- a/components/password_manager/core/browser/password_store/login_database.cc
+++ b/components/password_manager/core/browser/password_store/login_database.cc
@@ -34,11 +34,11 @@
 #include "components/os_crypt/sync/os_crypt.h"
 #include "components/password_manager/core/browser/affiliation/affiliation_utils.h"
 #include "components/password_manager/core/browser/features/password_features.h"
-#include "components/password_manager/core/browser/password_store/insecure_credentials_table.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/password_manager/core/browser/password_store/insecure_credentials_table.h"
 #include "components/password_manager/core/browser/password_store/password_notes_table.h"
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 #include "components/password_manager/core/browser/password_store/psl_matching_helper.h"
 #include "components/password_manager/core/browser/sql_table_builder.h"
 #include "components/password_manager/core/common/password_manager_features.h"
diff --git a/components/password_manager/core/browser/password_store/login_database.h b/components/password_manager/core/browser/password_store/login_database.h
index bb036c6..1c0bb50a 100644
--- a/components/password_manager/core/browser/password_store/login_database.h
+++ b/components/password_manager/core/browser/password_store/login_database.h
@@ -13,11 +13,11 @@
 #include "base/functional/callback.h"
 #include "base/pickle.h"
 #include "build/build_config.h"
-#include "components/password_manager/core/browser/password_store/insecure_credentials_table.h"
 #include "components/password_manager/core/browser/password_form.h"
+#include "components/password_manager/core/browser/password_store/insecure_credentials_table.h"
 #include "components/password_manager/core/browser/password_store/password_notes_table.h"
 #include "components/password_manager/core/browser/password_store/password_store.h"
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 #include "components/password_manager/core/browser/password_store/psl_matching_helper.h"
 #include "components/password_manager/core/browser/password_store/statistics_table.h"
 #include "components/password_manager/core/browser/sync/password_store_sync.h"
diff --git a/components/password_manager/core/browser/password_store/login_database_unittest.cc b/components/password_manager/core/browser/password_store/login_database_unittest.cc
index c73bf78..de2a585 100644
--- a/components/password_manager/core/browser/password_store/login_database_unittest.cc
+++ b/components/password_manager/core/browser/password_store/login_database_unittest.cc
@@ -30,7 +30,7 @@
 #include "components/password_manager/core/browser/features/password_features.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 #include "components/password_manager/core/browser/password_store/psl_matching_helper.h"
 #include "components/password_manager/core/browser/sync/password_store_sync.h"
 #include "components/password_manager/core/common/password_manager_features.h"
diff --git a/components/password_manager/core/browser/password_store/password_store.cc b/components/password_manager/core/browser/password_store/password_store.cc
index 600fda8c..40165e8d 100644
--- a/components/password_manager/core/browser/password_store/password_store.cc
+++ b/components/password_manager/core/browser/password_store/password_store.cc
@@ -30,8 +30,8 @@
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_store/password_store_backend.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_util.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_util.h"
 #include "components/password_manager/core/browser/password_store/psl_matching_helper.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
diff --git a/components/password_manager/core/browser/password_store/password_store.h b/components/password_manager/core/browser/password_store/password_store.h
index f18d9b7a..35826d8 100644
--- a/components/password_manager/core/browser/password_store/password_store.h
+++ b/components/password_manager/core/browser/password_store/password_store.h
@@ -27,8 +27,8 @@
 #include "components/password_manager/core/browser/password_form_digest.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_store/password_store_backend.h"
-#include "components/password_manager/core/browser/password_store_change.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_store/smart_bubble_stats_store.h"
 
 class PrefService;
diff --git a/components/password_manager/core/browser/password_store/password_store_backend.h b/components/password_manager/core/browser/password_store/password_store_backend.h
index ae73c801..2c02032 100644
--- a/components/password_manager/core/browser/password_store/password_store_backend.h
+++ b/components/password_manager/core/browser/password_store/password_store_backend.h
@@ -10,8 +10,8 @@
 #include "base/functional/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "components/password_manager/core/browser/password_form_digest.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace syncer {
diff --git a/components/password_manager/core/browser/password_store_backend_error.cc b/components/password_manager/core/browser/password_store/password_store_backend_error.cc
similarity index 94%
rename from components/password_manager/core/browser/password_store_backend_error.cc
rename to components/password_manager/core/browser/password_store/password_store_backend_error.cc
index 5924e67..5e821d3d 100644
--- a/components/password_manager/core/browser/password_store_backend_error.cc
+++ b/components/password_manager/core/browser/password_store/password_store_backend_error.cc
@@ -2,7 +2,8 @@
 // Copyright 2022 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-#include "components/password_manager/core/browser/password_store_backend_error.h"
+
+#include "components/password_manager/core/browser/password_store/password_store_backend_error.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/password_store_backend_error.h b/components/password_manager/core/browser/password_store/password_store_backend_error.h
similarity index 95%
rename from components/password_manager/core/browser/password_store_backend_error.h
rename to components/password_manager/core/browser/password_store/password_store_backend_error.h
index 17ec74362..677e534 100644
--- a/components/password_manager/core/browser/password_store_backend_error.h
+++ b/components/password_manager/core/browser/password_store/password_store_backend_error.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_BACKEND_ERROR_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_BACKEND_ERROR_H_
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_BACKEND_ERROR_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_BACKEND_ERROR_H_
 
 namespace password_manager {
 
@@ -55,4 +55,4 @@
 
 }  // namespace password_manager
 
-#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_BACKEND_ERROR_H_
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_BACKEND_ERROR_H_
diff --git a/components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder.h b/components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder.h
index 6ef9362..1880b9e 100644
--- a/components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder.h
+++ b/components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder.h
@@ -11,7 +11,7 @@
 #include "base/time/time.h"
 #include "base/types/strong_alias.h"
 #include "components/password_manager/core/browser/password_store/android_backend_error.h"
-#include "components/password_manager/core/browser/password_store_backend_error.h"
+#include "components/password_manager/core/browser/password_store/password_store_backend_error.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
 
diff --git a/components/password_manager/core/browser/password_store/password_store_built_in_backend.cc b/components/password_manager/core/browser/password_store/password_store_built_in_backend.cc
index d97379f..1578678c 100644
--- a/components/password_manager/core/browser/password_store/password_store_built_in_backend.cc
+++ b/components/password_manager/core/browser/password_store/password_store_built_in_backend.cc
@@ -15,8 +15,8 @@
 #include "components/password_manager/core/browser/password_store/login_database_async_helper.h"
 #include "components/password_manager/core/browser/password_store/password_store_backend.h"
 #include "components/password_manager/core/browser/password_store/password_store_backend_metrics_recorder.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_util.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_util.h"
 #include "components/sync/model/proxy_model_type_controller_delegate.h"
 
 namespace password_manager {
diff --git a/components/password_manager/core/browser/password_store/password_store_built_in_backend_unittest.cc b/components/password_manager/core/browser/password_store/password_store_built_in_backend_unittest.cc
index 84fd4ca2..51ad4618 100644
--- a/components/password_manager/core/browser/password_store/password_store_built_in_backend_unittest.cc
+++ b/components/password_manager/core/browser/password_store/password_store_built_in_backend_unittest.cc
@@ -24,12 +24,12 @@
 #include "components/password_manager/core/browser/affiliation/fake_affiliation_service.h"
 #include "components/password_manager/core/browser/affiliation/mock_affiliated_match_helper.h"
 #include "components/password_manager/core/browser/features/password_features.h"
-#include "components/password_manager/core/browser/password_store/login_database.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/browser/password_store/login_database.h"
 #include "components/password_manager/core/browser/password_store/password_store_backend.h"
-#include "components/password_manager/core/browser/password_store_change.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/password_manager/core/browser/password_store_change.cc b/components/password_manager/core/browser/password_store/password_store_change.cc
similarity index 98%
rename from components/password_manager/core/browser/password_store_change.cc
rename to components/password_manager/core/browser/password_store/password_store_change.cc
index 1e55c46..4062b66 100644
--- a/components/password_manager/core/browser/password_store_change.cc
+++ b/components/password_manager/core/browser/password_store/password_store_change.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/password_store_change.h b/components/password_manager/core/browser/password_store/password_store_change.h
similarity index 95%
rename from components/password_manager/core/browser/password_store_change.h
rename to components/password_manager/core/browser/password_store/password_store_change.h
index 53f61aae..561f567 100644
--- a/components/password_manager/core/browser/password_store_change.h
+++ b/components/password_manager/core/browser/password_store/password_store_change.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_CHANGE_H__
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_CHANGE_H__
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_CHANGE_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_CHANGE_H_
 
 #include <ostream>
 #include <vector>
 
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_backend_error.h"
+#include "components/password_manager/core/browser/password_store/password_store_backend_error.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace password_manager {
@@ -70,4 +70,4 @@
 
 }  // namespace password_manager
 
-#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_CHANGE_H_
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_CHANGE_H_
diff --git a/components/password_manager/core/browser/password_store_consumer.cc b/components/password_manager/core/browser/password_store/password_store_consumer.cc
similarity index 88%
rename from components/password_manager/core/browser/password_store_consumer.cc
rename to components/password_manager/core/browser/password_store/password_store_consumer.cc
index 53189fd..4d0086b1 100644
--- a/components/password_manager/core/browser/password_store_consumer.cc
+++ b/components/password_manager/core/browser/password_store/password_store_consumer.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
-#include "components/password_manager/core/browser/password_store_util.h"
-#include "components/password_manager/core/browser/interactions_stats.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_util.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/password_store_consumer.h b/components/password_manager/core/browser/password_store/password_store_consumer.h
similarity index 96%
rename from components/password_manager/core/browser/password_store_consumer.h
rename to components/password_manager/core/browser/password_store/password_store_consumer.h
index 735633a9..c01e768 100644
--- a/components/password_manager/core/browser/password_store_consumer.h
+++ b/components/password_manager/core/browser/password_store/password_store_consumer.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_CONSUMER_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_CONSUMER_H_
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_CONSUMER_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_CONSUMER_H_
 
 #include <memory>
 #include <vector>
 
 #include "base/memory/scoped_refptr.h"
 #include "base/task/cancelable_task_tracker.h"
-#include "components/password_manager/core/browser/password_store_backend_error.h"
+#include "components/password_manager/core/browser/password_store/password_store_backend_error.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
 
 namespace password_manager {
@@ -79,4 +79,4 @@
 
 }  // namespace password_manager
 
-#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_CONSUMER_H_
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_CONSUMER_H_
diff --git a/components/password_manager/core/browser/password_store_interface.h b/components/password_manager/core/browser/password_store/password_store_interface.h
similarity index 98%
rename from components/password_manager/core/browser/password_store_interface.h
rename to components/password_manager/core/browser/password_store/password_store_interface.h
index 3d37708..74092a5 100644
--- a/components/password_manager/core/browser/password_store_interface.h
+++ b/components/password_manager/core/browser/password_store/password_store_interface.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_INTERFACE_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_INTERFACE_H_
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_INTERFACE_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_INTERFACE_H_
 
 #include <vector>
 
@@ -12,7 +12,7 @@
 #include "base/observer_list_types.h"
 #include "components/keyed_service/core/refcounted_keyed_service.h"
 #include "components/password_manager/core/browser/password_form_digest.h"
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 
 namespace syncer {
 class ProxyModelTypeControllerDelegate;
@@ -193,4 +193,4 @@
 
 }  // namespace password_manager
 
-#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_INTERFACE_H_
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_INTERFACE_H_
diff --git a/components/password_manager/core/browser/password_store/password_store_unittest.cc b/components/password_manager/core/browser/password_store/password_store_unittest.cc
index 884e2f47..34620c5 100644
--- a/components/password_manager/core/browser/password_store/password_store_unittest.cc
+++ b/components/password_manager/core/browser/password_store/password_store_unittest.cc
@@ -28,17 +28,17 @@
 #include "components/password_manager/core/browser/fake_password_store_backend.h"
 #include "components/password_manager/core/browser/features/password_features.h"
 #include "components/password_manager/core/browser/form_parsing/form_data_parser.h"
-#include "components/password_manager/core/browser/password_store/login_database.h"
-#include "components/password_manager/core/browser/password_store/mock_password_store_backend.h"
 #include "components/password_manager/core/browser/mock_password_store_consumer.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
 #include "components/password_manager/core/browser/password_reuse_detector.h"
 #include "components/password_manager/core/browser/password_reuse_manager.h"
+#include "components/password_manager/core/browser/password_store/login_database.h"
+#include "components/password_manager/core/browser/password_store/mock_password_store_backend.h"
 #include "components/password_manager/core/browser/password_store/password_store.h"
 #include "components/password_manager/core/browser/password_store/password_store_backend.h"
 #include "components/password_manager/core/browser/password_store/password_store_built_in_backend.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "components/password_manager/core/browser/password_store_signin_notifier.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
diff --git a/components/password_manager/core/browser/password_store_util.cc b/components/password_manager/core/browser/password_store/password_store_util.cc
similarity index 97%
rename from components/password_manager/core/browser/password_store_util.cc
rename to components/password_manager/core/browser/password_store/password_store_util.cc
index 0516e47..99d61be 100644
--- a/components/password_manager/core/browser/password_store_util.cc
+++ b/components/password_manager/core/browser/password_store/password_store_util.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/password_manager/core/browser/password_store_util.h"
+#include "components/password_manager/core/browser/password_store/password_store_util.h"
 
 #include "base/ranges/algorithm.h"
 
diff --git a/components/password_manager/core/browser/password_store_util.h b/components/password_manager/core/browser/password_store/password_store_util.h
similarity index 90%
rename from components/password_manager/core/browser/password_store_util.h
rename to components/password_manager/core/browser/password_store/password_store_util.h
index 945586c3..6237d7d 100644
--- a/components/password_manager/core/browser/password_store_util.h
+++ b/components/password_manager/core/browser/password_store/password_store_util.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_UTIL_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_UTIL_H_
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_UTIL_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_UTIL_H_
 
 #include <vector>
 
-#include "components/password_manager/core/browser/password_store_change.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace password_manager {
@@ -30,4 +30,4 @@
 
 }  // namespace password_manager
 
-#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_UTIL_H_
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_PASSWORD_STORE_UTIL_H_
diff --git a/components/password_manager/core/browser/password_store/psl_matching_helper.h b/components/password_manager/core/browser/password_store/psl_matching_helper.h
index 400f1c9..2ce80ec0 100644
--- a/components/password_manager/core/browser/password_store/psl_matching_helper.h
+++ b/components/password_manager/core/browser/password_store/psl_matching_helper.h
@@ -8,7 +8,7 @@
 #include <iosfwd>
 #include <string>
 
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 class GURL;
 
diff --git a/components/password_manager/core/browser/password_store/statistics_table.h b/components/password_manager/core/browser/password_store/statistics_table.h
index da40f604..05ecebe 100644
--- a/components/password_manager/core/browser/password_store/statistics_table.h
+++ b/components/password_manager/core/browser/password_store/statistics_table.h
@@ -10,7 +10,7 @@
 
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ptr.h"
-#include "components/password_manager/core/browser/interactions_stats.h"
+#include "components/password_manager/core/browser/password_store/interactions_stats.h"
 
 namespace sql {
 class Database;
diff --git a/components/password_manager/core/browser/password_store_consumer_unittest.cc b/components/password_manager/core/browser/password_store_consumer_unittest.cc
index ceb921c..28e6631 100644
--- a/components/password_manager/core/browser/password_store_consumer_unittest.cc
+++ b/components/password_manager/core/browser/password_store_consumer_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "components/password_manager/core/browser/mock_password_store_consumer.h"
 #include "components/password_manager/core/browser/mock_password_store_interface.h"
 #include "components/password_manager/core/browser/password_form.h"
diff --git a/components/password_manager/core/browser/password_store_factory_util.cc b/components/password_manager/core/browser/password_store_factory_util.cc
index f3ba456..822d88dd 100644
--- a/components/password_manager/core/browser/password_store_factory_util.cc
+++ b/components/password_manager/core/browser/password_store_factory_util.cc
@@ -16,7 +16,7 @@
 #include "components/password_manager/core/browser/old_google_credentials_cleaner.h"
 #include "components/password_manager/core/browser/password_manager_constants.h"
 #include "components/password_manager/core/browser/password_store/login_database.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 namespace password_manager {
 
diff --git a/components/password_manager/core/browser/sharing/password_receiver_service_impl.cc b/components/password_manager/core/browser/sharing/password_receiver_service_impl.cc
index d4c2fff..47c2af8 100644
--- a/components/password_manager/core/browser/sharing/password_receiver_service_impl.cc
+++ b/components/password_manager/core/browser/sharing/password_receiver_service_impl.cc
@@ -12,7 +12,7 @@
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_form_digest.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/sharing/incoming_password_sharing_invitation_sync_bridge.h"
 #include "components/password_manager/core/browser/sharing/sharing_invitations.h"
 #include "components/prefs/pref_service.h"
diff --git a/components/password_manager/core/browser/sharing/password_receiver_service_impl.h b/components/password_manager/core/browser/sharing/password_receiver_service_impl.h
index 67add8f..99b7ffdd 100644
--- a/components/password_manager/core/browser/sharing/password_receiver_service_impl.h
+++ b/components/password_manager/core/browser/sharing/password_receiver_service_impl.h
@@ -11,7 +11,7 @@
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "components/password_manager/core/browser/sharing/password_receiver_service.h"
 #include "components/password_manager/core/browser/sharing/sharing_invitations.h"
 #include "components/sync/service/sync_service_observer.h"
diff --git a/components/password_manager/core/browser/store_metrics_reporter.cc b/components/password_manager/core/browser/store_metrics_reporter.cc
index d682035f..15a117a7 100644
--- a/components/password_manager/core/browser/store_metrics_reporter.cc
+++ b/components/password_manager/core/browser/store_metrics_reporter.cc
@@ -21,8 +21,8 @@
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_reuse_detector.h"
 #include "components/password_manager/core/browser/password_reuse_manager.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_sync_util.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
diff --git a/components/password_manager/core/browser/store_metrics_reporter.h b/components/password_manager/core/browser/store_metrics_reporter.h
index 33a5b7e..bdb149bb 100644
--- a/components/password_manager/core/browser/store_metrics_reporter.h
+++ b/components/password_manager/core/browser/store_metrics_reporter.h
@@ -11,7 +11,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "components/password_manager/core/browser/password_store/insecure_credentials_table.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 
 class PrefService;
 
diff --git a/components/password_manager/core/browser/sync/password_store_sync.h b/components/password_manager/core/browser/sync/password_store_sync.h
index b1712127..6e48169 100644
--- a/components/password_manager/core/browser/sync/password_store_sync.h
+++ b/components/password_manager/core/browser/sync/password_store_sync.h
@@ -9,7 +9,7 @@
 #include <memory>
 #include <vector>
 
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 #include "components/sync/model/sync_metadata_store.h"
 
 namespace syncer {
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge.cc b/components/password_manager/core/browser/sync/password_sync_bridge.cc
index d5d4354..19ad1f2c 100644
--- a/components/password_manager/core/browser/sync/password_sync_bridge.cc
+++ b/components/password_manager/core/browser/sync/password_sync_bridge.cc
@@ -21,7 +21,7 @@
 #include "components/password_manager/core/browser/features/password_features.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 #include "components/password_manager/core/browser/sync/password_proto_utils.h"
 #include "components/password_manager/core/browser/sync/password_store_sync.h"
 #include "components/password_manager/core/common/password_manager_features.h"
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge.h b/components/password_manager/core/browser/sync/password_sync_bridge.h
index e0ba922..3f843e30 100644
--- a/components/password_manager/core/browser/sync/password_sync_bridge.h
+++ b/components/password_manager/core/browser/sync/password_sync_bridge.h
@@ -8,7 +8,7 @@
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ptr.h"
 #include "base/sequence_checker.h"
-#include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store/password_store_change.h"
 #include "components/password_manager/core/browser/sync/password_store_sync.h"
 #include "components/sync/model/metadata_batch.h"
 #include "components/sync/model/model_type_sync_bridge.h"
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager.h b/components/password_manager/core/browser/ui/insecure_credentials_manager.h
index 34311b51..7bc2198b 100644
--- a/components/password_manager/core/browser/ui/insecure_credentials_manager.h
+++ b/components/password_manager/core/browser/ui/insecure_credentials_manager.h
@@ -22,7 +22,7 @@
 #include "base/types/strong_alias.h"
 #include "build/build_config.h"
 #include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/ui/credential_utils.h"
 #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
 #include "url/gurl.h"
diff --git a/components/password_manager/core/browser/ui/password_undo_helper.cc b/components/password_manager/core/browser/ui/password_undo_helper.cc
index eaca21e9..a3ea9b9fc 100644
--- a/components/password_manager/core/browser/ui/password_undo_helper.cc
+++ b/components/password_manager/core/browser/ui/password_undo_helper.cc
@@ -6,7 +6,7 @@
 
 #include "base/memory/raw_ptr.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
 #include "components/undo/undo_operation.h"
 
diff --git a/components/password_manager/core/browser/ui/post_save_compromised_helper.cc b/components/password_manager/core/browser/ui/post_save_compromised_helper.cc
index 08662ba..5a6063cf 100644
--- a/components/password_manager/core/browser/ui/post_save_compromised_helper.cc
+++ b/components/password_manager/core/browser/ui/post_save_compromised_helper.cc
@@ -8,7 +8,7 @@
 #include "base/feature_list.h"
 #include "base/ranges/algorithm.h"
 #include "base/task/single_thread_task_runner.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
diff --git a/components/password_manager/core/browser/ui/post_save_compromised_helper.h b/components/password_manager/core/browser/ui/post_save_compromised_helper.h
index 8e582f7..7e82354 100644
--- a/components/password_manager/core/browser/ui/post_save_compromised_helper.h
+++ b/components/password_manager/core/browser/ui/post_save_compromised_helper.h
@@ -11,7 +11,7 @@
 #include "base/functional/callback.h"
 #include "base/memory/weak_ptr.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class PrefService;
diff --git a/components/password_manager/core/browser/ui/saved_passwords_presenter.h b/components/password_manager/core/browser/ui/saved_passwords_presenter.h
index 6f48e6a..ea14f83 100644
--- a/components/password_manager/core/browser/ui/saved_passwords_presenter.h
+++ b/components/password_manager/core/browser/ui/saved_passwords_presenter.h
@@ -14,8 +14,8 @@
 #include "base/observer_list.h"
 #include "base/scoped_observation.h"
 #include "base/strings/string_piece.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/ui/affiliated_group.h"
 #include "components/password_manager/core/browser/ui/credential_ui_entry.h"
 #include "components/webauthn/core/browser/passkey_model.h"
diff --git a/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc b/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc
index a79aa596..ea10368 100644
--- a/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc
+++ b/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc
@@ -28,8 +28,8 @@
 #include "components/password_manager/core/browser/mock_password_store_interface.h"
 #include "components/password_manager/core/browser/passkey_credential.h"
 #include "components/password_manager/core/browser/password_form.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/password_store/test_password_store.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
 #include "components/password_manager/core/browser/ui/credential_ui_entry.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/sync/base/features.h"
diff --git a/components/permissions/BUILD.gn b/components/permissions/BUILD.gn
index b56fa81..c489339 100644
--- a/components/permissions/BUILD.gn
+++ b/components/permissions/BUILD.gn
@@ -139,7 +139,7 @@
       "contexts/geolocation_permission_context_system.h",
     ]
   }
-  if (!is_android && !is_ios) {
+  if (!is_android) {
     deps += [ "//components/guest_view/browser" ]
   }
   if (is_android) {
diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn
index 1c15bbf..2eef560 100644
--- a/components/resources/BUILD.gn
+++ b/components/resources/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/android/config.gni")
+import("//build/config/features.gni")
 import("//components/safe_browsing/buildflags.gni")
 import("//components/signin/features.gni")
 import("//components/supervised_user/buildflags.gni")
@@ -53,6 +54,7 @@
     "enable_supervised_users=$enable_supervised_users",
     "safe_browsing_mode=$safe_browsing_mode",
     "is_fuchsia=$is_fuchsia",
+    "use_blink=$use_blink",
   ]
 
   deps = [
@@ -62,7 +64,7 @@
     "//components/security_interstitials/core/browser/resources:bundle_js",
   ]
 
-  if (!is_ios) {
+  if (use_blink) {
     deps += [ "//components/resources/ssl/ssl_error_assistant:make_ssl_error_assistant_protobuf" ]
   }
 
diff --git a/components/resources/security_interstitials_resources.grdp b/components/resources/security_interstitials_resources.grdp
index 03aaac92..0414fb2 100644
--- a/components/resources/security_interstitials_resources.grdp
+++ b/components/resources/security_interstitials_resources.grdp
@@ -13,7 +13,7 @@
   <include name="IDR_KNOWN_INTERCEPTION_ICON_1X_PNG" file="../security_interstitials/core/browser/resources/images/1x/triangle_red.png" type="BINDATA" />
   <include name="IDR_KNOWN_INTERCEPTION_ICON_2X_PNG" file="../security_interstitials/core/browser/resources/images/2x/triangle_red.png" type="BINDATA" />
 
-  <if expr="not is_ios">
+  <if expr="use_blink">
     <include name="IDR_SSL_ERROR_ASSISTANT_PB" file="${root_gen_dir}/components/resources/ssl/ssl_error_assistant/ssl_error_assistant.pb" use_base_dir="false" type="BINDATA" compress="gzip" />
   </if>
 </grit-part>
diff --git a/components/safe_browsing/core/browser/BUILD.gn b/components/safe_browsing/core/browser/BUILD.gn
index 38a5be82..eeef858 100644
--- a/components/safe_browsing/core/browser/BUILD.gn
+++ b/components/safe_browsing/core/browser/BUILD.gn
@@ -209,6 +209,9 @@
     "//base/test:test_support",
     "//testing/gtest",
   ]
+  if (is_ios) {
+    deps += [ "//components/test:safe_browsing_test_bundle_data" ]
+  }
 }
 
 source_set("token_fetcher_testing_helper") {
diff --git a/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_utils.h b/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_utils.h
index bdc5bb04..019dbca 100644
--- a/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_utils.h
+++ b/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_utils.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_SAFE_BROWSING_CORE_BROWSER_HASHPREFIX_REALTIME_HASH_REALTIME_UTILS_H_
 #define COMPONENTS_SAFE_BROWSING_CORE_BROWSER_HASHPREFIX_REALTIME_HASH_REALTIME_UTILS_H_
 
+#include <optional>
+
 #include "components/safe_browsing/core/common/proto/safebrowsingv5.pb.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "url/gurl.h"
@@ -76,17 +78,17 @@
 // Based on the user's browser session and location, specifies whether
 // hash-prefix real-time lookups are eligible. Outside of tests,
 // |stored_permanent_country| should be determined with the helper function
-// |hash_realtime_utils::GetCountryCode|. If it's passed in as absl::nullopt,
+// |hash_realtime_utils::GetCountryCode|. If it's passed in as std::nullopt,
 // the location is considered eligible.
 bool IsHashRealTimeLookupEligibleInSessionAndLocation(
-    absl::optional<std::string> stored_permanent_country);
+    std::optional<std::string> stored_permanent_country);
 
 // Returns the stored permanent country. If |variations_service| is null,
-// returns absl::nullopt. This should be used only as a helper to determine the
+// returns std::nullopt. This should be used only as a helper to determine the
 // country code to pass into |IsHashRealTimeLookupEligibleInSessionAndLocation|
 // and |DetermineHashRealTimeSelection|. This is separated out into a function
 // to simplify tests.
-absl::optional<std::string> GetCountryCode(
+std::optional<std::string> GetCountryCode(
     variations::VariationsService* variations_service);
 
 // Based on the user's settings and session, determines which hash-prefix
@@ -94,11 +96,11 @@
 // this will log metrics related to whether hash real-time lookups were
 // available or why not. Outside of tests, |stored_permanent_country| should be
 // determined with the helper function |hash_realtime_utils::GetCountryCode|.
-// If it's passed in as absl::nullopt, the location is considered eligible.
+// If it's passed in as std::nullopt, the location is considered eligible.
 HashRealTimeSelection DetermineHashRealTimeSelection(
     bool is_off_the_record,
     PrefService* prefs,
-    absl::optional<std::string> stored_permanent_country,
+    std::optional<std::string> stored_permanent_country,
     bool log_usage_histograms = false);
 
 // A helper for consumers that want to recompute
diff --git a/components/safe_browsing/core/browser/realtime/BUILD.gn b/components/safe_browsing/core/browser/realtime/BUILD.gn
index 7b49328..2daca16 100644
--- a/components/safe_browsing/core/browser/realtime/BUILD.gn
+++ b/components/safe_browsing/core/browser/realtime/BUILD.gn
@@ -107,4 +107,7 @@
     "//testing/gtest",
     "//third_party/googletest:gmock",
   ]
+  if (is_ios) {
+    deps += [ "//components/test:safe_browsing_test_bundle_data" ]
+  }
 }
diff --git a/components/safe_browsing/core/browser/tailored_security_service/BUILD.gn b/components/safe_browsing/core/browser/tailored_security_service/BUILD.gn
index d75aba13..754fc9b7 100644
--- a/components/safe_browsing/core/browser/tailored_security_service/BUILD.gn
+++ b/components/safe_browsing/core/browser/tailored_security_service/BUILD.gn
@@ -59,4 +59,7 @@
     "//testing/gtest",
     "//url",
   ]
+  if (is_ios) {
+    deps += [ "//components/test:safe_browsing_test_bundle_data" ]
+  }
 }
diff --git a/components/safe_browsing/core/browser/utils/BUILD.gn b/components/safe_browsing/core/browser/utils/BUILD.gn
index a28ced4..d73e6954 100644
--- a/components/safe_browsing/core/browser/utils/BUILD.gn
+++ b/components/safe_browsing/core/browser/utils/BUILD.gn
@@ -28,4 +28,7 @@
     ":utils",
     "//base/test:test_support",
   ]
+  if (is_ios) {
+    deps += [ "//components/test:safe_browsing_test_bundle_data" ]
+  }
 }
diff --git a/components/safe_browsing/core/common/BUILD.gn b/components/safe_browsing/core/common/BUILD.gn
index 98def91..1a6d645 100644
--- a/components/safe_browsing/core/common/BUILD.gn
+++ b/components/safe_browsing/core/common/BUILD.gn
@@ -63,6 +63,9 @@
     "//testing/gtest",
     "//url:url",
   ]
+  if (is_ios) {
+    deps += [ "//components/test:safe_browsing_test_bundle_data" ]
+  }
 }
 
 source_set("common") {
diff --git a/components/safe_browsing/ios/browser/BUILD.gn b/components/safe_browsing/ios/browser/BUILD.gn
index e148eda9..af04b83 100644
--- a/components/safe_browsing/ios/browser/BUILD.gn
+++ b/components/safe_browsing/ios/browser/BUILD.gn
@@ -31,11 +31,7 @@
     "//components/safe_browsing/core/browser:user_population_unittest",
     "//components/safe_browsing/core/browser:verdict_cache_manager_unittest",
     "//components/safe_browsing/core/browser/db:unit_tests_local_db",
-    "//components/safe_browsing/core/browser/realtime:unit_tests",
-    "//components/safe_browsing/core/browser/tailored_security_service:unit_tests",
-    "//components/safe_browsing/core/browser/utils:unit_tests",
     "//components/safe_browsing/core/common",
-    "//components/safe_browsing/core/common:unit_tests",
     "//ios/web/public",
     "//ios/web/public/test",
     "//testing/gmock",
diff --git a/components/security_interstitials/content/utils.cc b/components/security_interstitials/content/utils.cc
index 7ad8cfc..f7a8cf7 100644
--- a/components/security_interstitials/content/utils.cc
+++ b/components/security_interstitials/content/utils.cc
@@ -80,7 +80,6 @@
 
 #elif BUILDFLAG(IS_MAC)
   base::mac::OpenSystemSettingsPane(base::mac::SystemSettingsPane::kDateTime);
-
 #elif BUILDFLAG(IS_WIN)
   base::FilePath path;
   base::PathService::Get(base::DIR_SYSTEM, &path);
@@ -94,8 +93,9 @@
   options.wait = false;
   base::LaunchProcess(command, options);
 
-#elif BUILDFLAG(IS_FUCHSIA)
+#elif BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_IOS)
   // TODO(crbug.com/1233494): Send to the platform settings.
+  // The iOS Blink port also need to send the platform settings.
   NOTIMPLEMENTED_LOG_ONCE();
 #else
 #error Unsupported target architecture.
diff --git a/components/security_interstitials_strings.grdp b/components/security_interstitials_strings.grdp
index 9da973d0..6011d332 100644
--- a/components/security_interstitials_strings.grdp
+++ b/components/security_interstitials_strings.grdp
@@ -500,7 +500,7 @@
     Proceed
   </message>
 
-  <if expr="not is_ios">
+  <if expr="use_blink">
     <!-- Blocked interception interstitial strings -->
     <message name="IDS_BLOCKED_INTERCEPTION_HEADING" desc="Large heading of the known interception interstitial.">
       Your activity on <ph name="HOSTNAME">$1<ex>example.com</ex></ph> is being monitored
diff --git a/components/services/screen_ai/BUILD.gn b/components/services/screen_ai/BUILD.gn
index 93fce1e..24fc205 100644
--- a/components/services/screen_ai/BUILD.gn
+++ b/components/services/screen_ai/BUILD.gn
@@ -19,7 +19,8 @@
   deps = [
     "//components/services/screen_ai/proto",
     "//components/services/screen_ai/public/cpp:utilities",
-    "//components/services/screen_ai/public/mojom",
+    "//components/services/screen_ai/public/mojom:factory",
+    "//components/services/screen_ai/public/mojom:mojom",
     "//content/public/browser",
     "//mojo/public/cpp/bindings",
     "//sandbox/policy",
diff --git a/components/services/screen_ai/public/mojom/BUILD.gn b/components/services/screen_ai/public/mojom/BUILD.gn
index 40390a2..0303daa 100644
--- a/components/services/screen_ai/public/mojom/BUILD.gn
+++ b/components/services/screen_ai/public/mojom/BUILD.gn
@@ -9,7 +9,15 @@
 
   public_deps = [
     "//media/mojo/mojom",
-    "//sandbox/policy/mojom",
     "//ui/accessibility/mojom",
   ]
 }
+
+mojom("factory") {
+  disable_variants = true
+  sources = [ "screen_ai_factory.mojom" ]
+  public_deps = [
+    ":mojom",
+    "//sandbox/policy/mojom",
+  ]
+}
diff --git a/components/services/screen_ai/public/mojom/screen_ai_factory.mojom b/components/services/screen_ai/public/mojom/screen_ai_factory.mojom
new file mode 100644
index 0000000..cfb67cfb
--- /dev/null
+++ b/components/services/screen_ai/public/mojom/screen_ai_factory.mojom
@@ -0,0 +1,51 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module screen_ai.mojom;
+
+import "mojo/public/mojom/base/file_path.mojom";
+import "mojo/public/mojom/base/read_only_file.mojom";
+import "sandbox/policy/mojom/sandbox.mojom";
+import "components/services/screen_ai/public/mojom/screen_ai_service.mojom";
+
+// The service runs in a sandboxed process to run Screen AI service library. The
+// library provides two AI modules:
+//   1) An image processing module to analyze snapshots of the browser or an
+//      image in a PDF and add more details to the accessibility tree.
+//   2) A text processing module that receives the accessibility tree and
+//      returns the main content of the tree.
+// The services require initialization before running. This factory interface
+// binds interfaces to the actual services after library load and initialization
+// for each of them.
+[ServiceSandbox=sandbox.mojom.Sandbox.kScreenAI]
+interface ScreenAIServiceFactory {
+  // Triggers the service to load and initialize the Screen AI library at
+  // |library_path| for OCR. Model files are read from |library_path| folder.
+  // This should be called from the browser process.
+  // |model_files| includes a map from file paths relative the the library base
+  // path, to opened file handles. The list of files is downloaded with the
+  // component. The file handles will be closed once the file is read.
+  InitializeOCR(
+    mojo_base.mojom.FilePath library_path,
+    map<mojo_base.mojom.RelativeFilePath, mojo_base.mojom.ReadOnlyFile>
+      model_files,
+    pending_receiver<OCRService> ocr_service_receiver) =>
+      (bool initialized);
+
+  // Triggers the service to load and initialize the Screen AI library at
+  // |library_path| for main content extraction.
+  // This should be called from the browser process.
+  // |model_files| includes a map from file paths relative to the library base
+  // path, to opened file handles. The list of files is downloaded with the
+  // component. The file handles will be closed once the file is read.
+  InitializeMainContentExtraction(
+    mojo_base.mojom.FilePath library_path,
+    map<mojo_base.mojom.RelativeFilePath, mojo_base.mojom.ReadOnlyFile>
+      model_files,
+    pending_receiver<MainContentExtractionService>
+      main_content_extractor_service) =>
+      (bool initialized);
+
+  // TODO(crbug.com/1443349): Add Initialization for Layout Extractor.
+};
diff --git a/components/services/screen_ai/public/mojom/screen_ai_service.mojom b/components/services/screen_ai/public/mojom/screen_ai_service.mojom
index 4d80f53f..b35301cc 100644
--- a/components/services/screen_ai/public/mojom/screen_ai_service.mojom
+++ b/components/services/screen_ai/public/mojom/screen_ai_service.mojom
@@ -4,9 +4,6 @@
 
 module screen_ai.mojom;
 
-import "mojo/public/mojom/base/file_path.mojom";
-import "mojo/public/mojom/base/read_only_file.mojom";
-import "sandbox/policy/mojom/sandbox.mojom";
 import "skia/public/mojom/bitmap.mojom";
 import "ui/accessibility/mojom/ax_tree_id.mojom";
 import "ui/accessibility/mojom/ax_tree_update.mojom";
@@ -122,44 +119,3 @@
   BindMainContentExtractor(pending_receiver<Screen2xMainContentExtractor>
     main_content_extractor);
 };
-
-// The service runs in a sandboxed process to run Screen AI service library. The
-// library provides two AI modules:
-//   1) An image processing module to analyze snapshots of the browser or an
-//      image in a PDF and add more details to the accessibility tree.
-//   2) A text processing module that receives the accessibility tree and
-//      returns the main content of the tree.
-// The services require initialization before running. This factory interface
-// binds interfaces to the actual services after library load and initialization
-// for each of them.
-[ServiceSandbox=sandbox.mojom.Sandbox.kScreenAI]
-interface ScreenAIServiceFactory {
-  // Triggers the service to load and initialize the Screen AI library at
-  // |library_path| for OCR. Model files are read from |library_path| folder.
-  // This should be called from the browser process.
-  // |model_files| includes a map from file paths relative to the library base
-  // path, to opened file handles. The list of files is downloaded with the
-  // component. The file handles will be closed once the file is read.
-  // TODO(b/297824387): Replace `string` with `RelativePath`.
-  InitializeOCR(
-    mojo_base.mojom.FilePath library_path,
-    map<string, mojo_base.mojom.ReadOnlyFile> model_files,
-    pending_receiver<OCRService> ocr_service_receiver) =>
-      (bool initialized);
-
-  // Triggers the service to load and initialize the Screen AI library at
-  // |library_path| for main content extraction.
-  // This should be called from the browser process.
-  // |model_files| includes a map from file paths relative the the library base
-  // path, to opened file handles. The list of files is downloaded with the
-  // component. The file handles will be closed once the file is read.
-  // TODO(b/297824387): Replace `string` with `RelativePath`.
-  InitializeMainContentExtraction(
-    mojo_base.mojom.FilePath library_path,
-    map<string, mojo_base.mojom.ReadOnlyFile> model_files,
-    pending_receiver<MainContentExtractionService>
-      main_content_extractor_service) =>
-      (bool initialized);
-
-  // TODO(crbug.com/1443349): Add Initialization for Layout Extractor.
-};
diff --git a/components/services/screen_ai/screen_ai_service_impl.cc b/components/services/screen_ai/screen_ai_service_impl.cc
index 9802c1c..cc679a8 100644
--- a/components/services/screen_ai/screen_ai_service_impl.cc
+++ b/components/services/screen_ai/screen_ai_service_impl.cc
@@ -59,7 +59,7 @@
   }
 
   static std::unique_ptr<PreloadedModelData> Create(
-      base::flat_map<std::string, base::File> model_files) {
+      base::flat_map<base::FilePath, base::File> model_files) {
     return base::WrapUnique<PreloadedModelData>(
         new PreloadedModelData(std::move(model_files)));
   }
@@ -91,7 +91,7 @@
 
  private:
   explicit PreloadedModelData(
-      base::flat_map<std::string, base::File> model_files) {
+      base::flat_map<base::FilePath, base::File> model_files) {
     CHECK_EQ(g_preloaded_model_data_instance, nullptr);
     g_preloaded_model_data_instance = this;
 
@@ -110,7 +110,7 @@
                 << model_file.first;
         continue;
       }
-      data_[model_file.first] = std::move(buffer);
+      data_[model_file.first.MaybeAsASCII()] = std::move(buffer);
     }
   }
 };
@@ -156,7 +156,7 @@
 
 void ScreenAIService::InitializeMainContentExtraction(
     const base::FilePath& library_path,
-    base::flat_map<std::string, base::File> model_files,
+    base::flat_map<base::FilePath, base::File> model_files,
     mojo::PendingReceiver<mojom::MainContentExtractionService>
         main_content_extractor_service_receiver,
     InitializeMainContentExtractionCallback callback) {
@@ -207,7 +207,7 @@
 
 void ScreenAIService::InitializeOCR(
     const base::FilePath& library_path,
-    base::flat_map<std::string, base::File> model_files,
+    base::flat_map<base::FilePath, base::File> model_files,
     mojo::PendingReceiver<mojom::OCRService> ocr_service_receiver,
     InitializeOCRCallback callback) {
   if (!library_) {
diff --git a/components/services/screen_ai/screen_ai_service_impl.h b/components/services/screen_ai/screen_ai_service_impl.h
index 16d61b6..0137312 100644
--- a/components/services/screen_ai/screen_ai_service_impl.h
+++ b/components/services/screen_ai/screen_ai_service_impl.h
@@ -15,6 +15,7 @@
 #include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
+#include "components/services/screen_ai/public/mojom/screen_ai_factory.mojom.h"
 #include "components/services/screen_ai/public/mojom/screen_ai_service.mojom.h"
 #include "components/services/screen_ai/screen_ai_library_wrapper.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -81,7 +82,7 @@
   // mojom::ScreenAIServiceFactory:
   void InitializeMainContentExtraction(
       const base::FilePath& library_path,
-      base::flat_map<std::string, base::File> model_files,
+      base::flat_map<base::FilePath, base::File> model_files,
       mojo::PendingReceiver<mojom::MainContentExtractionService>
           main_content_extractor_service_receiver,
       InitializeMainContentExtractionCallback callback) override;
@@ -89,7 +90,7 @@
   // mojom::ScreenAIServiceFactory:
   void InitializeOCR(
       const base::FilePath& library_path,
-      base::flat_map<std::string, base::File> model_files,
+      base::flat_map<base::FilePath, base::File> model_files,
       mojo::PendingReceiver<mojom::OCRService> ocr_service_receiver,
       InitializeOCRCallback callback) override;
 
diff --git a/components/services/storage/sandboxed_vfs_delegate.cc b/components/services/storage/sandboxed_vfs_delegate.cc
index 1bb53636..cb87156 100644
--- a/components/services/storage/sandboxed_vfs_delegate.cc
+++ b/components/services/storage/sandboxed_vfs_delegate.cc
@@ -7,11 +7,11 @@
 #include <cstdint>
 #include <utility>
 
+#include <optional>
 #include "base/files/file.h"
 #include "base/files/file_error_or.h"
 #include "base/files/file_path.h"
 #include "components/services/storage/public/cpp/filesystem/filesystem_proxy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace storage {
 
@@ -34,12 +34,12 @@
   return filesystem_->DeleteFile(file_path) ? SQLITE_OK : SQLITE_IOERR_DELETE;
 }
 
-absl::optional<sql::SandboxedVfs::PathAccessInfo>
+std::optional<sql::SandboxedVfs::PathAccessInfo>
 SandboxedVfsDelegate::GetPathAccess(const base::FilePath& file_path) {
-  absl::optional<FilesystemProxy::PathAccessInfo> info =
+  std::optional<FilesystemProxy::PathAccessInfo> info =
       filesystem_->GetPathAccess(file_path);
   if (!info)
-    return absl::nullopt;
+    return std::nullopt;
 
   sql::SandboxedVfs::PathAccessInfo access;
   access.can_read = info->can_read;
diff --git a/components/services/storage/sandboxed_vfs_delegate.h b/components/services/storage/sandboxed_vfs_delegate.h
index 206a28f3..9535f8b4 100644
--- a/components/services/storage/sandboxed_vfs_delegate.h
+++ b/components/services/storage/sandboxed_vfs_delegate.h
@@ -21,7 +21,7 @@
   // sql::SandboxedVfs::Delegate implementation:
   base::File OpenFile(const base::FilePath& file_path,
                       int sqlite_requested_flags) override;
-  absl::optional<sql::SandboxedVfs::PathAccessInfo> GetPathAccess(
+  std::optional<sql::SandboxedVfs::PathAccessInfo> GetPathAccess(
       const base::FilePath& file_path) override;
   int DeleteFile(const base::FilePath& file_path, bool sync_dir) override;
   bool SetFileLength(const base::FilePath& file_path,
diff --git a/components/signin/public/base/signin_client.h b/components/signin/public/base/signin_client.h
index 398b2a1..3c79a903 100644
--- a/components/signin/public/base/signin_client.h
+++ b/components/signin/public/base/signin_client.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_CLIENT_H_
 
 #include <memory>
+#include <optional>
 
 #include "base/callback_list.h"
 #include "base/functional/callback.h"
@@ -23,7 +24,6 @@
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "components/account_manager_core/account.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #endif
 
 class PrefService;
@@ -126,12 +126,12 @@
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   // Returns an account used to sign into Chrome OS session if available.
-  virtual absl::optional<account_manager::Account>
+  virtual std::optional<account_manager::Account>
   GetInitialPrimaryAccount() = 0;
 
   // Returns whether account used to sign into Chrome OS is a child account.
   // Returns nullopt for secondary / non-main profiles in LaCrOS.
-  virtual absl::optional<bool> IsInitialPrimaryAccountChild() const = 0;
+  virtual std::optional<bool> IsInitialPrimaryAccountChild() const = 0;
 
   // Remove account.
   virtual void RemoveAccount(
@@ -153,7 +153,7 @@
           event_source) = 0;
 
  protected:
-  absl::optional<SignoutDecision> is_clear_primary_account_allowed_for_testing_;
+  std::optional<SignoutDecision> is_clear_primary_account_allowed_for_testing_;
 };
 
 namespace base {
diff --git a/components/stylus_handwriting/android/java/src/org/chromium/components/stylus_handwriting/DirectWritingTrigger.java b/components/stylus_handwriting/android/java/src/org/chromium/components/stylus_handwriting/DirectWritingTrigger.java
index 5bc5b221..3a68278 100644
--- a/components/stylus_handwriting/android/java/src/org/chromium/components/stylus_handwriting/DirectWritingTrigger.java
+++ b/components/stylus_handwriting/android/java/src/org/chromium/components/stylus_handwriting/DirectWritingTrigger.java
@@ -73,8 +73,6 @@
     public void onWebContentsChanged(Context context, WebContents webContents) {
         updateDWSettings(context);
         webContents.setStylusWritingHandler(this);
-        // TODO(crbug.com/1457860): Drop StylusHandwritingImeCallback reference when webContents is
-        // destroyed.
         mStylusWritingImeCallback = webContents.getStylusWritingImeCallback();
         mCallback.setImeCallback(mStylusWritingImeCallback);
     }
@@ -222,6 +220,11 @@
         mBinder.unbindService(context);
     }
 
+    @Override
+    public void onImeAdapterDestroyed() {
+        mStylusWritingImeCallback = null;
+    }
+
     /*
      * This API needs to be called before starting recognition to bind direct writing service.
      */
@@ -254,6 +257,11 @@
     }
 
     @VisibleForTesting
+    StylusWritingImeCallback getStylusWritingImeCallbackForTest() {
+        return mStylusWritingImeCallback;
+    }
+
+    @VisibleForTesting
     boolean stylusWritingDetected() {
         return mStylusWritingDetected;
     }
diff --git a/components/stylus_handwriting/android/junit/src/org/chromium/components/stylus_handwriting/DirectWritingTriggerTest.java b/components/stylus_handwriting/android/junit/src/org/chromium/components/stylus_handwriting/DirectWritingTriggerTest.java
index 4c2d8e65..5685a3f84 100644
--- a/components/stylus_handwriting/android/junit/src/org/chromium/components/stylus_handwriting/DirectWritingTriggerTest.java
+++ b/components/stylus_handwriting/android/junit/src/org/chromium/components/stylus_handwriting/DirectWritingTriggerTest.java
@@ -120,6 +120,18 @@
 
     @Test
     @Feature({"Stylus Handwriting"})
+    public void testOnImeAdapterDestroyed() {
+        // Set Ime callback via onWebContentsChanged.
+        doReturn(mStylusWritingImeCallback).when(mWebContents).getStylusWritingImeCallback();
+        mDwTrigger.onWebContentsChanged(mContext, mWebContents);
+        assertNotNull(mDwTrigger.getStylusWritingImeCallbackForTest());
+
+        mDwTrigger.onImeAdapterDestroyed();
+        assertNull(mDwTrigger.getStylusWritingImeCallbackForTest());
+    }
+
+    @Test
+    @Feature({"Stylus Handwriting"})
     public void testServiceCallbackCreation() {
         // Test that callback is created when settings are updated.
         assertNull(mDwTrigger.getServiceCallback());
diff --git a/components/sync/invalidations/fcm_handler.h b/components/sync/invalidations/fcm_handler.h
index 16779b8..85ffdadc 100644
--- a/components/sync/invalidations/fcm_handler.h
+++ b/components/sync/invalidations/fcm_handler.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_SYNC_INVALIDATIONS_FCM_HANDLER_H_
 #define COMPONENTS_SYNC_INVALIDATIONS_FCM_HANDLER_H_
 
+#include <optional>
 #include <string>
 
 #include "base/containers/circular_deque.h"
@@ -78,7 +79,7 @@
   void RemoveTokenObserver(FCMRegistrationTokenObserver* observer);
 
   // Used to get an obtained FCM token. Returns null if it doesn't have a token.
-  const absl::optional<std::string>& GetFCMRegistrationToken() const;
+  const std::optional<std::string>& GetFCMRegistrationToken() const;
 
   // GCMAppHandler overrides.
   void ShutdownHandler() override;
@@ -111,7 +112,7 @@
 
   // Contains an FCM registration token. Token is null if the experiment is off
   // or we don't have a valid token yet and contains valid token otherwise.
-  absl::optional<std::string> fcm_registration_token_;
+  std::optional<std::string> fcm_registration_token_;
 
   base::OneShotTimer token_validation_timer_;
 
diff --git a/components/sync/protocol/autofill_specifics.proto b/components/sync/protocol/autofill_specifics.proto
index 5b8449b..bae6f84 100644
--- a/components/sync/protocol/autofill_specifics.proto
+++ b/components/sync/protocol/autofill_specifics.proto
@@ -124,7 +124,16 @@
   optional string address_home_thoroughfare_number = 39;
   optional string address_home_street_location = 73;
   optional string address_home_subpremise_name = 42;
+  // All the information related to the apartment. Normally a combination of the
+  // apartment type (address_home_apt_type) and number (address_home_apt_num).
+  // E.g. "Apt 5".
+  optional string address_home_apt = 85;
+  // The raw number (or identifier) of an apartment (e.g. "5") but without a
+  // prefix. The value "apt 5" would correspond to the address_home_apt.
   optional string address_home_apt_num = 56;
+  // Information describing the type of apartment (e.g. Apt, Apartamento, Sala,
+  // Departamento).
+  optional string address_home_apt_type = 87;
   optional string address_home_floor = 57;
   optional string address_home_landmark = 67;
   // The type indicates that the address is at the intersection between two
@@ -170,7 +179,9 @@
   optional VerificationStatus address_home_thoroughfare_number_status = 52;
   optional VerificationStatus address_home_street_location_status = 74;
   optional VerificationStatus address_home_subpremise_name_status = 55;
+  optional VerificationStatus address_home_apt_status = 86;
   optional VerificationStatus address_home_apt_num_status = 58;
+  optional VerificationStatus address_home_apt_type_status = 88;
   optional VerificationStatus address_home_floor_status = 59;
 
   // Phone.
diff --git a/components/sync/protocol/contact_info_specifics.proto b/components/sync/protocol/contact_info_specifics.proto
index fa00775..405bf26 100644
--- a/components/sync/protocol/contact_info_specifics.proto
+++ b/components/sync/protocol/contact_info_specifics.proto
@@ -165,8 +165,15 @@
   reserved "address_premise_name";
   // Contains the floor, staircase or apartment number within a building.
   optional StringToken address_subpremise_name = 30;
+  // All the information related to the apartment. Normally a combination of the
+  // apartment type (address_apt_type) and number (address_apt_num).
+  // E.g. "Apt 5".
+  optional StringToken address_apt = 50;
   // The apartment number within a building.
   optional StringToken address_apt_num = 31;
+  // Information describing the type of apartment (e.g. Apt, Apartamento, Sala,
+  // Departamento).
+  optional StringToken address_apt_type = 51;
   // The floor number within a building.
   optional StringToken address_floor = 32;
   // Contains both the street and house number.
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h
index 851b3b7..811e17e 100644
--- a/components/sync/protocol/proto_visitors.h
+++ b/components/sync/protocol/proto_visitors.h
@@ -247,6 +247,9 @@
   VISIT(address_home_thoroughfare_name);
   VISIT(address_home_thoroughfare_number);
   VISIT(address_home_subpremise_name);
+  VISIT(address_home_apt);
+  VISIT(address_home_apt_num);
+  VISIT(address_home_apt_type);
 
   VISIT_ENUM(address_home_city_status);
   VISIT_ENUM(address_home_state_status);
@@ -266,6 +269,9 @@
   VISIT_ENUM(address_home_thoroughfare_name_status);
   VISIT_ENUM(address_home_thoroughfare_number_status);
   VISIT_ENUM(address_home_subpremise_name_status);
+  VISIT_ENUM(address_home_apt_status);
+  VISIT_ENUM(address_home_apt_num_status);
+  VISIT_ENUM(address_home_apt_type_status);
 
   VISIT(address_home_language_code);
   VISIT_REP(phone_home_whole_number);
@@ -361,7 +367,9 @@
   VISIT(address_thoroughfare_name);
   VISIT(address_thoroughfare_number);
   VISIT(address_subpremise_name);
+  VISIT(address_apt);
   VISIT(address_apt_num);
+  VISIT(address_apt_type);
   VISIT(address_floor);
   VISIT(address_landmark);
   VISIT(address_between_streets);
diff --git a/components/test/BUILD.gn b/components/test/BUILD.gn
index 97685f7..7554afa 100644
--- a/components/test/BUILD.gn
+++ b/components/test/BUILD.gn
@@ -99,6 +99,10 @@
     testonly = true
     filelist_name = "data/performance_manager/unit_tests_bundle_data.filelist"
   }
+  bundle_data_from_filelist("safe_browsing_test_bundle_data") {
+    testonly = true
+    filelist_name = "data/safe_browsing/unit_tests_bundle_data.filelist"
+  }
   bundle_data_from_filelist("service_worker_test_bundle_data") {
     testonly = true
     filelist_name = "data/service_worker/unit_tests_bundle_data.filelist"
diff --git a/components/test/PRESUBMIT.py b/components/test/PRESUBMIT.py
index 62d9821..04e443b7 100644
--- a/components/test/PRESUBMIT.py
+++ b/components/test/PRESUBMIT.py
@@ -47,6 +47,9 @@
                 input_api, output_api, 'data/history/unit_tests_bundle_data')
         results += presubmit_support.CheckBundleData(
                 input_api, output_api,
+                'data/safe_browsing/unit_tests_bundle_data')
+        results += presubmit_support.CheckBundleData(
+                input_api, output_api,
                 'data/service_worker/unit_tests_bundle_data')
         results += presubmit_support.CheckBundleData(
                 input_api, output_api,
diff --git a/components/test/data/safe_browsing/OWNERS b/components/test/data/safe_browsing/OWNERS
new file mode 100644
index 0000000..4e6079c
--- /dev/null
+++ b/components/test/data/safe_browsing/OWNERS
@@ -0,0 +1,2 @@
+# Anyone can update the test bundle data filelist.
+per-file unit_tests_bundle_data.filelist=*
diff --git a/components/test/data/safe_browsing/unit_tests_bundle_data.filelist b/components/test/data/safe_browsing/unit_tests_bundle_data.filelist
new file mode 100644
index 0000000..ad2d5d52
--- /dev/null
+++ b/components/test/data/safe_browsing/unit_tests_bundle_data.filelist
@@ -0,0 +1,10 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# NOTE: this file is generated by build/ios/update_bundle_filelist.py
+#       If it requires updating, you should get a presubmit error with
+#       instructions on how to regenerate. Otherwise, do not edit.
+//components/test/data/safe_browsing/client_model.pb
+//components/test/data/safe_browsing/image_embedding.tflite
+//components/test/data/safe_browsing/visual_model_android.tflite
+//components/test/data/safe_browsing/visual_model_desktop.tflite
diff --git a/components/test/data/safe_browsing/unit_tests_bundle_data.globlist b/components/test/data/safe_browsing/unit_tests_bundle_data.globlist
new file mode 100644
index 0000000..130dca9
--- /dev/null
+++ b/components/test/data/safe_browsing/unit_tests_bundle_data.globlist
@@ -0,0 +1,11 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# See build/ios/update_bundle_filelist.py for details on how .globlist
+# files are used to update their .filelist counterparts.
+
+//components/test/data/safe_browsing/**
+-//components/test/data/safe_browsing/*.filelist
+-//components/test/data/safe_browsing/*.globlist
+-//components/test/data/safe_browsing/OWNERS
diff --git a/content/browser/network_context_client_base_impl.cc b/content/browser/network_context_client_base_impl.cc
index b07a2447..ff206b75 100644
--- a/content/browser/network_context_client_base_impl.cc
+++ b/content/browser/network_context_client_base_impl.cc
@@ -17,6 +17,7 @@
 #include "content/public/browser/network_context_client_base.h"
 #include "content/public/common/content_client.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "net/base/net_errors.h"
 #include "services/network/public/mojom/trust_tokens.mojom.h"
 
 #if BUILDFLAG(IS_ANDROID)
@@ -78,6 +79,10 @@
     network::mojom::NetworkContextClient::OnFileUploadRequestedCallback
         callback,
     file_access::ScopedFileAccess scoped_file_access) {
+  if (!scoped_file_access.is_allowed()) {
+    std::move(callback).Run(net::Error::ERR_ACCESS_DENIED, /*files=*/{});
+    return;
+  }
   base::ThreadPool::PostTask(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
       base::BindOnce(&HandleFileUploadRequest, process_id, async, file_paths,
diff --git a/content/browser/preloading/prefetch/prefetch_streaming_url_loader_common_types.h b/content/browser/preloading/prefetch/prefetch_streaming_url_loader_common_types.h
index 9252c7d3..70edd64a 100644
--- a/content/browser/preloading/prefetch/prefetch_streaming_url_loader_common_types.h
+++ b/content/browser/preloading/prefetch/prefetch_streaming_url_loader_common_types.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_STREAMING_URL_LOADER_COMMON_TYPES_H_
 #define CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_STREAMING_URL_LOADER_COMMON_TYPES_H_
 
+#include <optional>
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/network/public/mojom/url_loader.mojom-forward.h"
@@ -76,7 +77,7 @@
 
 // This callback is used by the owner to determine if the prefetch is valid
 // based on |head|. If the prefetch should be servable based on |head|, then
-// the callback should return `absl::nullopt`. Otherwise it should return a
+// the callback should return `std::nullopt`. Otherwise it should return a
 // failure reason.
 enum class PrefetchErrorOnResponseReceived {
   kPrefetchWasDecoy,
@@ -86,7 +87,7 @@
   kFailedMIMENotSupported
 };
 using OnPrefetchResponseStartedCallback =
-    base::OnceCallback<absl::optional<PrefetchErrorOnResponseReceived>(
+    base::OnceCallback<std::optional<PrefetchErrorOnResponseReceived>(
         network::mojom::URLResponseHead* head)>;
 
 using OnPrefetchResponseCompletedCallback = base::OnceCallback<void(
diff --git a/content/browser/renderer_host/input/fling_scheduler.h b/content/browser/renderer_host/input/fling_scheduler.h
index f14d0659..cb39a69 100644
--- a/content/browser/renderer_host/input/fling_scheduler.h
+++ b/content/browser/renderer_host/input/fling_scheduler.h
@@ -41,7 +41,7 @@
 
  protected:
   virtual ui::Compositor* GetCompositor();
-  raw_ptr<RenderWidgetHostImpl, DanglingUntriaged> host_;
+  raw_ptr<RenderWidgetHostImpl> host_;
   base::WeakPtr<FlingController> fling_controller_;
   raw_ptr<ui::Compositor> observed_compositor_ = nullptr;
 
diff --git a/content/browser/renderer_host/input/fling_scheduler_unittest.cc b/content/browser/renderer_host/input/fling_scheduler_unittest.cc
index 5d7e480..2db73af0 100644
--- a/content/browser/renderer_host/input/fling_scheduler_unittest.cc
+++ b/content/browser/renderer_host/input/fling_scheduler_unittest.cc
@@ -71,6 +71,8 @@
   }
 
   void TearDown() override {
+    fling_controller_.reset();
+    fling_scheduler_.reset();
     view_.release()->Destroy();  // 'delete this' is called internally.
     widget_host_->ShutdownAndDestroyWidget(false);
     widget_host_.reset();
@@ -82,25 +84,6 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  std::unique_ptr<TestRenderWidgetHostView> CreateView() {
-    browser_context_ = std::make_unique<TestBrowserContext>();
-    process_host_ =
-        std::make_unique<MockRenderProcessHost>(browser_context_.get());
-    process_host_->Init();
-    site_instance_group_ =
-        base::WrapRefCounted(SiteInstanceGroup::CreateForTesting(
-            browser_context_.get(), process_host_.get()));
-    int32_t routing_id = process_host_->GetNextRoutingID();
-    delegate_ = std::make_unique<MockRenderWidgetHostDelegate>();
-    widget_host_ = TestRenderWidgetHost::Create(
-        /* frame_tree= */ nullptr, delegate_.get(),
-        RenderWidgetHostImpl::DefaultFrameSinkId(*site_instance_group_,
-                                                 routing_id),
-        site_instance_group_->GetSafeRef(), routing_id, false);
-    delegate_->set_widget_host(widget_host_.get());
-    return std::make_unique<TestRenderWidgetHostView>(widget_host_.get());
-  }
-
   void SimulateFlingStart(const gfx::Vector2dF& velocity) {
     blink::WebGestureEvent fling_start(
         blink::WebInputEvent::Type::kGestureFlingStart, 0,
@@ -131,13 +114,34 @@
     return gfx::Size(1920, 1080);
   }
 
-  std::unique_ptr<FlingController> fling_controller_;
-  std::unique_ptr<FakeFlingScheduler> fling_scheduler_;
+  FlingController* fling_controller() { return fling_controller_.get(); }
+  FakeFlingScheduler* fling_scheduler() { return fling_scheduler_.get(); }
 
  private:
+  std::unique_ptr<TestRenderWidgetHostView> CreateView() {
+    browser_context_ = std::make_unique<TestBrowserContext>();
+    process_host_ =
+        std::make_unique<MockRenderProcessHost>(browser_context_.get());
+    process_host_->Init();
+    site_instance_group_ =
+        base::WrapRefCounted(SiteInstanceGroup::CreateForTesting(
+            browser_context_.get(), process_host_.get()));
+    int32_t routing_id = process_host_->GetNextRoutingID();
+    delegate_ = std::make_unique<MockRenderWidgetHostDelegate>();
+    widget_host_ = TestRenderWidgetHost::Create(
+        /* frame_tree= */ nullptr, delegate_.get(),
+        RenderWidgetHostImpl::DefaultFrameSinkId(*site_instance_group_,
+                                                 routing_id),
+        site_instance_group_->GetSafeRef(), routing_id, false);
+    delegate_->set_widget_host(widget_host_.get());
+    return std::make_unique<TestRenderWidgetHostView>(widget_host_.get());
+  }
+
   BrowserTaskEnvironment task_environment_;
   std::unique_ptr<TestBrowserContext> browser_context_;
   std::unique_ptr<RenderWidgetHostImpl> widget_host_;
+  std::unique_ptr<FakeFlingScheduler> fling_scheduler_;
+  std::unique_ptr<FlingController> fling_controller_;
   std::unique_ptr<MockRenderProcessHost> process_host_;
   scoped_refptr<SiteInstanceGroup> site_instance_group_;
   std::unique_ptr<TestRenderWidgetHostView> view_;
@@ -151,29 +155,27 @@
 TEST_F(FlingSchedulerTest, ScheduleNextFlingProgress) {
   base::TimeTicks progress_time = base::TimeTicks::Now();
   SimulateFlingStart(gfx::Vector2dF(1000, 0));
-  EXPECT_TRUE(fling_scheduler_->fling_in_progress());
-  EXPECT_EQ(fling_controller_.get(),
-            fling_scheduler_->fling_controller().get());
-  EXPECT_EQ(fling_scheduler_->compositor(),
-            fling_scheduler_->observed_compositor());
+  EXPECT_TRUE(fling_scheduler()->fling_in_progress());
+  EXPECT_EQ(fling_controller(), fling_scheduler()->fling_controller().get());
+  EXPECT_EQ(fling_scheduler()->compositor(),
+            fling_scheduler()->observed_compositor());
 
   progress_time += base::Milliseconds(17);
-  fling_controller_->ProgressFling(progress_time);
-  EXPECT_TRUE(fling_scheduler_->fling_in_progress());
+  fling_controller()->ProgressFling(progress_time);
+  EXPECT_TRUE(fling_scheduler()->fling_in_progress());
 }
 
 TEST_F(FlingSchedulerTest, FlingCancelled) {
   SimulateFlingStart(gfx::Vector2dF(1000, 0));
-  EXPECT_TRUE(fling_scheduler_->fling_in_progress());
-  EXPECT_EQ(fling_controller_.get(),
-            fling_scheduler_->fling_controller().get());
-  EXPECT_EQ(fling_scheduler_->compositor(),
-            fling_scheduler_->observed_compositor());
+  EXPECT_TRUE(fling_scheduler()->fling_in_progress());
+  EXPECT_EQ(fling_controller(), fling_scheduler()->fling_controller().get());
+  EXPECT_EQ(fling_scheduler()->compositor(),
+            fling_scheduler()->observed_compositor());
 
   SimulateFlingCancel();
-  EXPECT_FALSE(fling_scheduler_->fling_in_progress());
-  EXPECT_EQ(nullptr, fling_scheduler_->fling_controller());
-  EXPECT_EQ(nullptr, fling_scheduler_->observed_compositor());
+  EXPECT_FALSE(fling_scheduler()->fling_in_progress());
+  EXPECT_EQ(nullptr, fling_scheduler()->fling_controller());
+  EXPECT_EQ(nullptr, fling_scheduler()->observed_compositor());
 }
 
 }  // namespace content
diff --git a/content/browser/utility_sandbox_delegate.h b/content/browser/utility_sandbox_delegate.h
index 49b9f842..0e07a97 100644
--- a/content/browser/utility_sandbox_delegate.h
+++ b/content/browser/utility_sandbox_delegate.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_UTILITY_SANDBOX_DELEGATE_H_
 #define CONTENT_BROWSER_UTILITY_SANDBOX_DELEGATE_H_
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/environment.h"
 #include "base/files/file_path.h"
@@ -73,7 +74,7 @@
 #endif  // BUILDFLAG(IS_WIN)
 
 #if BUILDFLAG(USE_ZYGOTE)
-  absl::optional<raw_ptr<ZygoteCommunication>> zygote_;
+  std::optional<raw_ptr<ZygoteCommunication>> zygote_;
 #endif  // BUILDFLAG(USE_ZYGOTE)
 
   sandbox::mojom::Sandbox sandbox_type_;
diff --git a/content/common/fetch/fetch_request_type_converters.cc b/content/common/fetch/fetch_request_type_converters.cc
index c833ec1..cd7b6d9 100644
--- a/content/common/fetch/fetch_request_type_converters.cc
+++ b/content/common/fetch/fetch_request_type_converters.cc
@@ -98,8 +98,8 @@
   if (input.trust_token_params) {
     output->trust_token_params = input.trust_token_params->Clone();
   }
-  output->target_address_space =
-      static_cast<network::mojom::IPAddressSpace>(input.target_address_space);
+  output->target_address_space = static_cast<network::mojom::IPAddressSpace>(
+      input.required_ip_address_space);
   output->attribution_reporting_eligibility =
       input.attribution_reporting_eligibility;
   return output;
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
index 735e546..fff6df3 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
@@ -813,6 +813,10 @@
         if (mCursorAnchorInfoController != null) {
             mCursorAnchorInfoController.focusedNodeChanged(false);
         }
+        mStylusWritingImeCallback = null;
+        if (mWebContents.getStylusWritingHandler() != null) {
+            mWebContents.getStylusWritingHandler().onImeAdapterDestroyed();
+        }
     }
 
     /**
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/StylusWritingHandler.java b/content/public/android/java/src/org/chromium/content_public/browser/StylusWritingHandler.java
index 3f251a4..37e2d18 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/StylusWritingHandler.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/StylusWritingHandler.java
@@ -105,4 +105,7 @@
             Rect focusedEditBounds, Point cursorPosition, float scaleFactor, int contentOffsetY) {
         return null;
     }
+
+    /** Notify that ImeAdapter is destroyed. */
+    default void onImeAdapterDestroyed() {}
 }
diff --git a/content/public/test/OWNERS b/content/public/test/OWNERS
index 03f3192f..c0f8b653 100644
--- a/content/public/test/OWNERS
+++ b/content/public/test/OWNERS
@@ -40,3 +40,7 @@
 
 # For Service Worker tests support review.
 per-file embedded_worker_instance_test_harness.*=file://content/browser/service_worker/OWNERS
+
+# For preloading changes.
+per-file preloading*=file://content/browser/preloading/OWNERS
+per-file prerender*=file://content/browser/preloading/OWNERS
diff --git a/content/public/test/permissions_test_utils.h b/content/public/test/permissions_test_utils.h
index 0f17e27..f64eaa1 100644
--- a/content/public/test/permissions_test_utils.h
+++ b/content/public/test/permissions_test_utils.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_PUBLIC_TEST_PERMISSIONS_TEST_UTILS_H_
 #define CONTENT_PUBLIC_TEST_PERMISSIONS_TEST_UTILS_H_
 
+#include <optional>
 #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
 
 namespace blink {
@@ -21,7 +22,7 @@
 
 void SetPermissionControllerOverrideForDevTools(
     PermissionController* permission_controller,
-    const absl::optional<url::Origin>& origin,
+    const std::optional<url::Origin>& origin,
     blink::PermissionType permission,
     const blink::mojom::PermissionStatus& status);
 
diff --git a/crypto/aead.cc b/crypto/aead.cc
index b3b26d95..b0845c307 100644
--- a/crypto/aead.cc
+++ b/crypto/aead.cc
@@ -87,7 +87,7 @@
   return true;
 }
 
-absl::optional<std::vector<uint8_t>> Aead::Open(
+std::optional<std::vector<uint8_t>> Aead::Open(
     base::span<const uint8_t> ciphertext,
     base::span<const uint8_t> nonce,
     base::span<const uint8_t> additional_data) const {
@@ -98,7 +98,7 @@
   size_t output_length;
   if (!Open(ciphertext, nonce, additional_data, ret.data(), &output_length,
             max_output_length)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   ret.resize(output_length);
diff --git a/crypto/aead.h b/crypto/aead.h
index 9a0c7061..0bfe4721 100644
--- a/crypto/aead.h
+++ b/crypto/aead.h
@@ -12,10 +12,10 @@
 #include <string_view>
 #include <vector>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/memory/raw_ptr.h"
 #include "crypto/crypto_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 struct evp_aead_st;
 
@@ -56,7 +56,7 @@
             std::string_view additional_data,
             std::string* ciphertext) const;
 
-  absl::optional<std::vector<uint8_t>> Open(
+  std::optional<std::vector<uint8_t>> Open(
       base::span<const uint8_t> ciphertext,
       base::span<const uint8_t> nonce,
       base::span<const uint8_t> additional_data) const;
@@ -85,7 +85,7 @@
             size_t* output_length,
             size_t max_output_length) const;
 
-  absl::optional<base::span<const uint8_t>> key_;
+  std::optional<base::span<const uint8_t>> key_;
   raw_ptr<const evp_aead_st> aead_;
 };
 
diff --git a/crypto/aead_unittest.cc b/crypto/aead_unittest.cc
index 4f9a1c4..fc8a423 100644
--- a/crypto/aead_unittest.cc
+++ b/crypto/aead_unittest.cc
@@ -51,7 +51,7 @@
       aead.Seal(kPlaintext, nonce, kAdditionalData);
   EXPECT_LT(sizeof(kPlaintext), ciphertext.size());
 
-  absl::optional<std::vector<uint8_t>> decrypted =
+  std::optional<std::vector<uint8_t>> decrypted =
       aead.Open(ciphertext, nonce, kAdditionalData);
   ASSERT_TRUE(decrypted);
   ASSERT_EQ(decrypted->size(), sizeof(kPlaintext));
diff --git a/crypto/apple_keychain.h b/crypto/apple_keychain.h
index c248cb61..ebb7915d 100644
--- a/crypto/apple_keychain.h
+++ b/crypto/apple_keychain.h
@@ -7,9 +7,9 @@
 
 #include <Security/Security.h>
 
+#include <optional>
 #include "build/build_config.h"
 #include "crypto/crypto_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace crypto {
 
@@ -79,7 +79,7 @@
   ~ScopedKeychainUserInteractionAllowed();
 
  private:
-  absl::optional<Boolean> was_allowed_;
+  std::optional<Boolean> was_allowed_;
 };
 
 #endif  // BUILDFLAG(IS_MAC)
diff --git a/crypto/encryptor.cc b/crypto/encryptor.cc
index 46e3be0f..0677147 100644
--- a/crypto/encryptor.cc
+++ b/crypto/encryptor.cc
@@ -99,7 +99,7 @@
                             std::string_view input,
                             std::string* output) {
   std::string result(MaxOutput(do_encrypt, input.size()), '\0');
-  absl::optional<size_t> len =
+  std::optional<size_t> len =
       (mode_ == CTR)
           ? CryptCTR(do_encrypt, base::as_bytes(base::make_span(input)),
                      base::as_writable_bytes(base::make_span(result)))
@@ -117,9 +117,9 @@
                            base::span<const uint8_t> input,
                            std::vector<uint8_t>* output) {
   std::vector<uint8_t> result(MaxOutput(do_encrypt, input.size()));
-  absl::optional<size_t> len = (mode_ == CTR)
-                                   ? CryptCTR(do_encrypt, input, result)
-                                   : Crypt(do_encrypt, input, result);
+  std::optional<size_t> len = (mode_ == CTR)
+                                  ? CryptCTR(do_encrypt, input, result)
+                                  : Crypt(do_encrypt, input, result);
   if (!len)
     return false;
 
@@ -134,9 +134,9 @@
   return result;
 }
 
-absl::optional<size_t> Encryptor::Crypt(bool do_encrypt,
-                                        base::span<const uint8_t> input,
-                                        base::span<uint8_t> output) {
+std::optional<size_t> Encryptor::Crypt(bool do_encrypt,
+                                       base::span<const uint8_t> input,
+                                       base::span<uint8_t> output) {
   DCHECK(key_);  // Must call Init() before En/De-crypt.
 
   const EVP_CIPHER* cipher = GetCipherForKey(key_);
@@ -151,7 +151,7 @@
   if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr,
                          reinterpret_cast<const uint8_t*>(key.data()),
                          iv_.data(), do_encrypt)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Encrypting needs a block size of space to allow for any padding.
@@ -159,31 +159,31 @@
   int out_len;
   if (!EVP_CipherUpdate(ctx.get(), output.data(), &out_len, input.data(),
                         input.size()))
-    return absl::nullopt;
+    return std::nullopt;
 
   // Write out the final block plus padding (if any) to the end of the data
   // just written.
   int tail_len;
   if (!EVP_CipherFinal_ex(ctx.get(), output.data() + out_len, &tail_len))
-    return absl::nullopt;
+    return std::nullopt;
 
   out_len += tail_len;
   DCHECK_LE(out_len, static_cast<int>(output.size()));
   return out_len;
 }
 
-absl::optional<size_t> Encryptor::CryptCTR(bool do_encrypt,
-                                           base::span<const uint8_t> input,
-                                           base::span<uint8_t> output) {
+std::optional<size_t> Encryptor::CryptCTR(bool do_encrypt,
+                                          base::span<const uint8_t> input,
+                                          base::span<uint8_t> output) {
   if (iv_.size() != AES_BLOCK_SIZE) {
     LOG(ERROR) << "Counter value not set in CTR mode.";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   AES_KEY aes_key;
   if (AES_set_encrypt_key(reinterpret_cast<const uint8_t*>(key_->key().data()),
                           key_->key().size() * 8, &aes_key) != 0) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   uint8_t ecount_buf[AES_BLOCK_SIZE] = { 0 };
diff --git a/crypto/encryptor.h b/crypto/encryptor.h
index 88ebb883..ee77f4b 100644
--- a/crypto/encryptor.h
+++ b/crypto/encryptor.h
@@ -12,11 +12,11 @@
 #include <string>
 #include <string_view>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/memory/raw_ptr.h"
 #include "build/build_config.h"
 #include "crypto/crypto_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace crypto {
 
@@ -86,12 +86,12 @@
   // On success, these helper functions return the number of bytes written to
   // |output|.
   size_t MaxOutput(bool do_encrypt, size_t length);
-  absl::optional<size_t> Crypt(bool do_encrypt,
-                               base::span<const uint8_t> input,
-                               base::span<uint8_t> output);
-  absl::optional<size_t> CryptCTR(bool do_encrypt,
-                                  base::span<const uint8_t> input,
-                                  base::span<uint8_t> output);
+  std::optional<size_t> Crypt(bool do_encrypt,
+                              base::span<const uint8_t> input,
+                              base::span<uint8_t> output);
+  std::optional<size_t> CryptCTR(bool do_encrypt,
+                                 base::span<const uint8_t> input,
+                                 base::span<uint8_t> output);
 
   // In CBC mode, the IV passed to Init(). In CTR mode, the counter value passed
   // to SetCounter().
diff --git a/crypto/unexportable_key.h b/crypto/unexportable_key.h
index 63acf4b6..f4aa85a 100644
--- a/crypto/unexportable_key.h
+++ b/crypto/unexportable_key.h
@@ -7,9 +7,9 @@
 
 #include <memory>
 
+#include <optional>
 #include "crypto/crypto_export.h"
 #include "crypto/signature_verifier.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace crypto {
 
@@ -50,7 +50,7 @@
   // during signing.
   //
   // Note: this may take a second or more to run.
-  virtual absl::optional<std::vector<uint8_t>> SignSlowly(
+  virtual std::optional<std::vector<uint8_t>> SignSlowly(
       base::span<const uint8_t> data) = 0;
 };
 
@@ -62,7 +62,7 @@
   // SelectAlgorithm returns which signature algorithm from
   // |acceptable_algorithms| would be used if |acceptable_algorithms| was passed
   // to |GenerateSigningKeySlowly|.
-  virtual absl::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
+  virtual std::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
       base::span<const SignatureVerifier::SignatureAlgorithm>
           acceptable_algorithms) = 0;
 
@@ -133,7 +133,7 @@
   // during signing.
   //
   // Note: this is expected to be under 10ms.
-  virtual absl::optional<std::vector<uint8_t>> Sign(
+  virtual std::optional<std::vector<uint8_t>> Sign(
       base::span<const uint8_t> data) = 0;
 
   // Deletes the key from storage in the virtual machine. As the virtual machine
@@ -150,7 +150,7 @@
   // SelectAlgorithm returns which signature algorithm from
   // |acceptable_algorithms| would be used if |acceptable_algorithms| was passed
   // to |GenerateSigningKeySlowly|.
-  virtual absl::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
+  virtual std::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
       base::span<const SignatureVerifier::SignatureAlgorithm>
           acceptable_algorithms) = 0;
 
diff --git a/crypto/unexportable_key_metrics.cc b/crypto/unexportable_key_metrics.cc
index 2b4b9a95..66242428 100644
--- a/crypto/unexportable_key_metrics.cc
+++ b/crypto/unexportable_key_metrics.cc
@@ -177,7 +177,7 @@
 
   const uint8_t msg[] = {1, 2, 3, 4};
   base::ElapsedTimer message_signing_timer;
-  absl::optional<std::vector<uint8_t>> signed_bytes = current_key->Sign(msg);
+  std::optional<std::vector<uint8_t>> signed_bytes = current_key->Sign(msg);
   ReportUmaTpmOperation(TPMOperation::kMessageSigning, supported_virtual_algo,
                         message_signing_timer.Elapsed(),
                         signed_bytes.has_value(), KeyType::kVirtualizedKey);
@@ -257,7 +257,7 @@
 
   const uint8_t msg[] = {1, 2, 3, 4};
   base::ElapsedTimer message_signing_timer;
-  absl::optional<std::vector<uint8_t>> signed_bytes =
+  std::optional<std::vector<uint8_t>> signed_bytes =
       current_key->SignSlowly(msg);
   ReportUmaTpmOperation(TPMOperation::kMessageSigning, supported_algo,
                         message_signing_timer.Elapsed(),
diff --git a/crypto/unexportable_key_software_unsecure.cc b/crypto/unexportable_key_software_unsecure.cc
index 64ca3f0..e6167ec 100644
--- a/crypto/unexportable_key_software_unsecure.cc
+++ b/crypto/unexportable_key_software_unsecure.cc
@@ -50,7 +50,7 @@
     return CBBToVector(cbb.get());
   }
 
-  absl::optional<std::vector<uint8_t>> SignSlowly(
+  std::optional<std::vector<uint8_t>> SignSlowly(
       base::span<const uint8_t> data) override {
     std::vector<uint8_t> ret(ECDSA_size(key_.get()));
     std::array<uint8_t, kSHA256Length> digest = SHA256Hash(data);
@@ -69,7 +69,7 @@
  public:
   ~SoftwareProvider() override = default;
 
-  absl::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
+  std::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
       base::span<const SignatureVerifier::SignatureAlgorithm>
           acceptable_algorithms) override {
     for (auto algo : acceptable_algorithms) {
@@ -78,7 +78,7 @@
       }
     }
 
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   std::unique_ptr<UnexportableSigningKey> GenerateSigningKeySlowly(
diff --git a/crypto/unexportable_key_unittest.cc b/crypto/unexportable_key_unittest.cc
index 85c97df0..4b29336 100644
--- a/crypto/unexportable_key_unittest.cc
+++ b/crypto/unexportable_key_unittest.cc
@@ -6,11 +6,11 @@
 
 #include <tuple>
 
+#include <optional>
 #include "base/logging.h"
 #include "base/time/time.h"
 #include "crypto/scoped_mock_unexportable_key_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -47,7 +47,7 @@
   SCOPED_TRACE(static_cast<int>(algo));
   SCOPED_TRACE(mock_enabled);
 
-  absl::optional<crypto::ScopedMockUnexportableKeyProvider> mock;
+  std::optional<crypto::ScopedMockUnexportableKeyProvider> mock;
   if (mock_enabled) {
     mock.emplace();
   }
@@ -78,7 +78,7 @@
   const uint8_t msg[] = {1, 2, 3, 4};
 
   const base::TimeTicks sign_start = base::TimeTicks::Now();
-  const absl::optional<std::vector<uint8_t>> sig = key->SignSlowly(msg);
+  const std::optional<std::vector<uint8_t>> sig = key->SignSlowly(msg);
   LOG(INFO) << "Signing took " << (base::TimeTicks::Now() - sign_start);
   ASSERT_TRUE(sig);
 
@@ -94,7 +94,7 @@
   LOG(INFO) << "Import took " << (base::TimeTicks::Now() - import2_start);
 
   const base::TimeTicks sign2_start = base::TimeTicks::Now();
-  const absl::optional<std::vector<uint8_t>> sig2 = key->SignSlowly(msg);
+  const std::optional<std::vector<uint8_t>> sig2 = key->SignSlowly(msg);
   LOG(INFO) << "Signing took " << (base::TimeTicks::Now() - sign2_start);
   ASSERT_TRUE(sig2);
 
diff --git a/crypto/unexportable_key_win.cc b/crypto/unexportable_key_win.cc
index 58d1441..7e39e10 100644
--- a/crypto/unexportable_key_win.cc
+++ b/crypto/unexportable_key_win.cc
@@ -49,7 +49,7 @@
 
 // BCryptAlgorithmFor returns the BCrypt algorithm ID for the given Chromium
 // signing algorithm.
-absl::optional<LPCWSTR> BCryptAlgorithmFor(
+std::optional<LPCWSTR> BCryptAlgorithmFor(
     SignatureVerifier::SignatureAlgorithm algo) {
   switch (algo) {
     case SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256:
@@ -59,18 +59,18 @@
       return BCRYPT_ECDSA_P256_ALGORITHM;
 
     default:
-      return absl::nullopt;
+      return std::nullopt;
   }
 }
 
 // GetBestSupported returns the first element of |acceptable_algorithms| that
 // |provider| supports, or |nullopt| if there isn't any.
-absl::optional<SignatureVerifier::SignatureAlgorithm> GetBestSupported(
+std::optional<SignatureVerifier::SignatureAlgorithm> GetBestSupported(
     NCRYPT_PROV_HANDLE provider,
     base::span<const SignatureVerifier::SignatureAlgorithm>
         acceptable_algorithms) {
   for (auto algo : acceptable_algorithms) {
-    absl::optional<LPCWSTR> bcrypto_algo_name = BCryptAlgorithmFor(algo);
+    std::optional<LPCWSTR> bcrypto_algo_name = BCryptAlgorithmFor(algo);
     if (!bcrypto_algo_name) {
       continue;
     }
@@ -82,22 +82,22 @@
     }
   }
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 // GetKeyProperty returns the given NCrypt key property of |key|.
-absl::optional<std::vector<uint8_t>> GetKeyProperty(NCRYPT_KEY_HANDLE key,
-                                                    LPCWSTR property) {
+std::optional<std::vector<uint8_t>> GetKeyProperty(NCRYPT_KEY_HANDLE key,
+                                                   LPCWSTR property) {
   SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
   DWORD size;
   if (FAILED(NCryptGetProperty(key, property, nullptr, 0, &size, 0))) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   std::vector<uint8_t> ret(size);
   if (FAILED(
           NCryptGetProperty(key, property, ret.data(), ret.size(), &size, 0))) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   CHECK_EQ(ret.size(), size);
 
@@ -105,30 +105,30 @@
 }
 
 // ExportKey returns |key| exported in the given format or nullopt on error.
-absl::optional<std::vector<uint8_t>> ExportKey(NCRYPT_KEY_HANDLE key,
-                                               LPCWSTR format) {
+std::optional<std::vector<uint8_t>> ExportKey(NCRYPT_KEY_HANDLE key,
+                                              LPCWSTR format) {
   SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
   DWORD output_size;
   if (FAILED(NCryptExportKey(key, 0, format, nullptr, nullptr, 0, &output_size,
                              0))) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   std::vector<uint8_t> output(output_size);
   if (FAILED(NCryptExportKey(key, 0, format, nullptr, output.data(),
                              output.size(), &output_size, 0))) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   CHECK_EQ(output.size(), output_size);
 
   return output;
 }
 
-absl::optional<std::vector<uint8_t>> GetP256ECDSASPKI(NCRYPT_KEY_HANDLE key) {
-  const absl::optional<std::vector<uint8_t>> pub_key =
+std::optional<std::vector<uint8_t>> GetP256ECDSASPKI(NCRYPT_KEY_HANDLE key) {
+  const std::optional<std::vector<uint8_t>> pub_key =
       ExportKey(key, BCRYPT_ECCPUBLIC_BLOB);
   if (!pub_key) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // The exported key is a |BCRYPT_ECCKEY_BLOB| followed by the bytes of the
@@ -136,7 +136,7 @@
   // https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/ns-bcrypt-bcrypt_ecckey_blob
   BCRYPT_ECCKEY_BLOB header;
   if (pub_key->size() < sizeof(header)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   memcpy(&header, pub_key->data(), sizeof(header));
   // |cbKey| is documented[1] as "the length, in bytes, of the key". It is
@@ -145,23 +145,23 @@
        header.dwMagic != BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC) ||
       header.cbKey != 256 / 8 ||
       pub_key->size() - sizeof(BCRYPT_ECCKEY_BLOB) != 64) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Sometimes NCrypt will return a generic dwMagic even when asked for a P-256
   // key. In that case, do extra validation to make sure that `key` is in fact
   // a P-256 key.
   if (header.dwMagic == BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC) {
-    const absl::optional<std::vector<uint8_t>> curve_name =
+    const std::optional<std::vector<uint8_t>> curve_name =
         GetKeyProperty(key, NCRYPT_ECC_CURVE_NAME_PROPERTY);
     if (!curve_name) {
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     if (curve_name->size() != sizeof(BCRYPT_ECC_CURVE_NISTP256) ||
         memcmp(curve_name->data(), BCRYPT_ECC_CURVE_NISTP256,
                sizeof(BCRYPT_ECC_CURVE_NISTP256)) != 0) {
-      return absl::nullopt;
+      return std::nullopt;
     }
   }
 
@@ -174,7 +174,7 @@
   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(p256.get()));
   if (!EC_POINT_oct2point(p256.get(), point.get(), x962, sizeof(x962),
                           /*ctx=*/nullptr)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   bssl::UniquePtr<EC_KEY> ec_key(
       EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
@@ -188,11 +188,11 @@
   return CBBToVector(cbb.get());
 }
 
-absl::optional<std::vector<uint8_t>> GetRSASPKI(NCRYPT_KEY_HANDLE key) {
-  const absl::optional<std::vector<uint8_t>> pub_key =
+std::optional<std::vector<uint8_t>> GetRSASPKI(NCRYPT_KEY_HANDLE key) {
+  const std::optional<std::vector<uint8_t>> pub_key =
       ExportKey(key, BCRYPT_RSAPUBLIC_BLOB);
   if (!pub_key) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // The exported key is a |BCRYPT_RSAKEY_BLOB| followed by the bytes of the
@@ -200,11 +200,11 @@
   // https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/ns-bcrypt-bcrypt_rsakey_blob
   BCRYPT_RSAKEY_BLOB header;
   if (pub_key->size() < sizeof(header)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   memcpy(&header, pub_key->data(), sizeof(header));
   if (header.Magic != static_cast<ULONG>(BCRYPT_RSAPUBLIC_MAGIC)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   size_t bytes_needed;
@@ -212,7 +212,7 @@
                       base::CheckAdd(header.cbPublicExp, header.cbModulus))
            .AssignIfValid(&bytes_needed) ||
       pub_key->size() < bytes_needed) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   bssl::UniquePtr<BIGNUM> e(
@@ -233,8 +233,8 @@
   return CBBToVector(cbb.get());
 }
 
-absl::optional<std::vector<uint8_t>> SignECDSA(NCRYPT_KEY_HANDLE key,
-                                               base::span<const uint8_t> data) {
+std::optional<std::vector<uint8_t>> SignECDSA(NCRYPT_KEY_HANDLE key,
+                                              base::span<const uint8_t> data) {
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::WILL_BLOCK);
 
@@ -248,7 +248,7 @@
     if (FAILED(NCryptSignHash(key, nullptr, digest.data(), digest.size(),
                               sig.data(), sig.size(), &sig_size,
                               NCRYPT_SILENT_FLAG))) {
-      return absl::nullopt;
+      return std::nullopt;
     }
   }
   CHECK_EQ(sig.size(), sig_size);
@@ -265,8 +265,8 @@
   return CBBToVector(cbb.get());
 }
 
-absl::optional<std::vector<uint8_t>> SignRSA(NCRYPT_KEY_HANDLE key,
-                                             base::span<const uint8_t> data) {
+std::optional<std::vector<uint8_t>> SignRSA(NCRYPT_KEY_HANDLE key,
+                                            base::span<const uint8_t> data) {
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::WILL_BLOCK);
 
@@ -279,14 +279,14 @@
   if (FAILED(NCryptSignHash(key, &padding_info, digest.data(), digest.size(),
                             nullptr, 0, &sig_size,
                             NCRYPT_SILENT_FLAG | BCRYPT_PAD_PKCS1))) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   std::vector<uint8_t> sig(sig_size);
   if (FAILED(NCryptSignHash(key, &padding_info, digest.data(), digest.size(),
                             sig.data(), sig.size(), &sig_size,
                             NCRYPT_SILENT_FLAG | BCRYPT_PAD_PKCS1))) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   CHECK_EQ(sig.size(), sig_size);
 
@@ -313,7 +313,7 @@
 
   std::vector<uint8_t> GetWrappedKey() const override { return wrapped_; }
 
-  absl::optional<std::vector<uint8_t>> SignSlowly(
+  std::optional<std::vector<uint8_t>> SignSlowly(
       base::span<const uint8_t> data) override {
     return SignECDSA(key_.get(), data);
   }
@@ -344,7 +344,7 @@
 
   std::vector<uint8_t> GetWrappedKey() const override { return wrapped_; }
 
-  absl::optional<std::vector<uint8_t>> SignSlowly(
+  std::optional<std::vector<uint8_t>> SignSlowly(
       base::span<const uint8_t> data) override {
     return SignRSA(key_.get(), data);
   }
@@ -361,7 +361,7 @@
  public:
   ~UnexportableKeyProviderWin() override = default;
 
-  absl::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
+  std::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
       base::span<const SignatureVerifier::SignatureAlgorithm>
           acceptable_algorithms) override {
     ScopedNCryptProvider provider;
@@ -370,7 +370,7 @@
       if (FAILED(NCryptOpenStorageProvider(
               ScopedNCryptProvider::Receiver(provider).get(),
               MS_PLATFORM_CRYPTO_PROVIDER, /*flags=*/0))) {
-        return absl::nullopt;
+        return std::nullopt;
       }
     }
 
@@ -393,7 +393,7 @@
       }
     }
 
-    absl::optional<SignatureVerifier::SignatureAlgorithm> algo =
+    std::optional<SignatureVerifier::SignatureAlgorithm> algo =
         GetBestSupported(provider.get(), acceptable_algorithms);
     if (!algo) {
       return nullptr;
@@ -415,13 +415,13 @@
       }
     }
 
-    const absl::optional<std::vector<uint8_t>> wrapped_key =
+    const std::optional<std::vector<uint8_t>> wrapped_key =
         ExportKey(key.get(), BCRYPT_OPAQUE_KEY_BLOB);
     if (!wrapped_key) {
       return nullptr;
     }
 
-    absl::optional<std::vector<uint8_t>> spki;
+    std::optional<std::vector<uint8_t>> spki;
     switch (*algo) {
       case SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256:
         spki = GetP256ECDSASPKI(key.get());
@@ -466,7 +466,7 @@
       }
     }
 
-    const absl::optional<std::vector<uint8_t>> algo_bytes =
+    const std::optional<std::vector<uint8_t>> algo_bytes =
         GetKeyProperty(key.get(), NCRYPT_ALGORITHM_PROPERTY);
     if (!algo_bytes) {
       return nullptr;
@@ -478,7 +478,7 @@
     static const wchar_t kECDSA[] = L"ECDSA";
     static const wchar_t kRSA[] = BCRYPT_RSA_ALGORITHM;
 
-    absl::optional<std::vector<uint8_t>> spki;
+    std::optional<std::vector<uint8_t>> spki;
     if (algo_bytes->size() == sizeof(kECDSA) &&
         memcmp(algo_bytes->data(), kECDSA, sizeof(kECDSA)) == 0) {
       spki = GetP256ECDSASPKI(key.get());
@@ -521,10 +521,10 @@
 
   std::string GetKeyName() const override { return name_; }
 
-  absl::optional<std::vector<uint8_t>> Sign(
+  std::optional<std::vector<uint8_t>> Sign(
       base::span<const uint8_t> data) override {
     if (!key_.is_valid()) {
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     return SignECDSA(key_.get(), data);
@@ -569,10 +569,10 @@
 
   std::string GetKeyName() const override { return name_; }
 
-  absl::optional<std::vector<uint8_t>> Sign(
+  std::optional<std::vector<uint8_t>> Sign(
       base::span<const uint8_t> data) override {
     if (!key_.is_valid()) {
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     return SignRSA(key_.get(), data);
@@ -606,7 +606,7 @@
  public:
   ~VirtualUnexportableKeyProviderWin() override = default;
 
-  absl::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
+  std::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
       base::span<const SignatureVerifier::SignatureAlgorithm>
           acceptable_algorithms) override {
     ScopedNCryptProvider provider;
@@ -617,7 +617,7 @@
           MS_KEY_STORAGE_PROVIDER, /*dwFlags=*/0);
       if (FAILED(status)) {
         base::UmaHistogramSparse(kMetricVirtualOpenStorageError, status);
-        return absl::nullopt;
+        return std::nullopt;
       }
     }
 
@@ -643,7 +643,7 @@
       }
     }
 
-    absl::optional<SignatureVerifier::SignatureAlgorithm> algo =
+    std::optional<SignatureVerifier::SignatureAlgorithm> algo =
         GetBestSupported(provider.get(), acceptable_algorithms);
     if (!algo) {
       return nullptr;
@@ -671,7 +671,7 @@
       }
     }
 
-    absl::optional<std::vector<uint8_t>> spki;
+    std::optional<std::vector<uint8_t>> spki;
     switch (*algo) {
       case SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256:
         spki = GetP256ECDSASPKI(key.get());
@@ -719,7 +719,7 @@
       }
     }
 
-    const absl::optional<std::vector<uint8_t>> algo_bytes =
+    const std::optional<std::vector<uint8_t>> algo_bytes =
         GetKeyProperty(key.get(), NCRYPT_ALGORITHM_PROPERTY);
 
     // This is the expected behavior, but note it is different from
@@ -727,7 +727,7 @@
     static const wchar_t kECDSA[] = BCRYPT_ECDSA_P256_ALGORITHM;
     static const wchar_t kRSA[] = BCRYPT_RSA_ALGORITHM;
 
-    absl::optional<std::vector<uint8_t>> spki;
+    std::optional<std::vector<uint8_t>> spki;
     if (algo_bytes->size() == sizeof(kECDSA) &&
         memcmp(algo_bytes->data(), kECDSA, sizeof(kECDSA)) == 0) {
       spki = GetP256ECDSASPKI(key.get());
diff --git a/dbus/end_to_end_async_unittest.cc b/dbus/end_to_end_async_unittest.cc
index 4a31038c..ae43c4c 100644
--- a/dbus/end_to_end_async_unittest.cc
+++ b/dbus/end_to_end_async_unittest.cc
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/memory/raw_ptr.h"
@@ -26,7 +27,6 @@
 #include "dbus/object_proxy.h"
 #include "dbus/test_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace dbus {
 
@@ -252,7 +252,7 @@
   }
 
   base::test::SingleThreadTaskEnvironment task_environment_;
-  absl::optional<base::ScopedDisallowBlocking> disallow_blocking_;
+  std::optional<base::ScopedDisallowBlocking> disallow_blocking_;
   std::unique_ptr<base::RunLoop> run_loop_;
   std::vector<std::string> response_strings_;
   std::vector<std::string> error_names_;
diff --git a/dbus/object_manager_unittest.cc b/dbus/object_manager_unittest.cc
index 859220a..eb38eda 100644
--- a/dbus/object_manager_unittest.cc
+++ b/dbus/object_manager_unittest.cc
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/memory/raw_ptr.h"
 #include "base/message_loop/message_pump_type.h"
@@ -26,7 +27,6 @@
 #include "dbus/property.h"
 #include "dbus/test_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace dbus {
 
@@ -208,7 +208,7 @@
   }
 
   base::test::SingleThreadTaskEnvironment task_environment_;
-  absl::optional<base::ScopedDisallowBlocking> disallow_blocking_;
+  std::optional<base::ScopedDisallowBlocking> disallow_blocking_;
   std::unique_ptr<base::RunLoop> run_loop_;
   std::unique_ptr<base::Thread> dbus_thread_;
   scoped_refptr<Bus> bus_;
diff --git a/dbus/property_unittest.cc b/dbus/property_unittest.cc
index 2842509f..3461686 100644
--- a/dbus/property_unittest.cc
+++ b/dbus/property_unittest.cc
@@ -156,7 +156,7 @@
   }
 
   base::test::SingleThreadTaskEnvironment task_environment_;
-  absl::optional<base::ScopedDisallowBlocking> disallow_blocking_;
+  std::optional<base::ScopedDisallowBlocking> disallow_blocking_;
   std::unique_ptr<base::RunLoop> run_loop_;
   std::unique_ptr<base::Thread> dbus_thread_;
   scoped_refptr<Bus> bus_;
diff --git a/fuchsia_web/common/test/frame_test_util.cc b/fuchsia_web/common/test/frame_test_util.cc
index a36ffb5..d9fea4d 100644
--- a/fuchsia_web/common/test/frame_test_util.cc
+++ b/fuchsia_web/common/test/frame_test_util.cc
@@ -7,6 +7,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/check.h"
 #include "base/fuchsia/mem_buffer_util.h"
 #include "base/json/json_reader.h"
@@ -15,7 +16,6 @@
 #include "base/test/test_future.h"
 #include "fuchsia_web/common/test/fit_adapter.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 bool LoadUrlAndExpectResponse(
     fuchsia::web::NavigationController* navigation_controller,
@@ -37,8 +37,8 @@
   return LoadUrlAndExpectResponse(controller.get(), std::move(params), url);
 }
 
-absl::optional<base::Value> ExecuteJavaScript(fuchsia::web::Frame* frame,
-                                              base::StringPiece script) {
+std::optional<base::Value> ExecuteJavaScript(fuchsia::web::Frame* frame,
+                                             base::StringPiece script) {
   base::test::TestFuture<fuchsia::web::Frame_ExecuteJavaScript_Result> result;
   frame->ExecuteJavaScript({"*"}, base::MemBufferFromString(script, "test"),
                            CallbackToFitFunction(result.GetCallback()));
@@ -46,7 +46,7 @@
   if (!result.Wait() || !result.Get().is_response())
     return {};
 
-  absl::optional<std::string> result_json =
+  std::optional<std::string> result_json =
       base::StringFromMemBuffer(result.Get().response().result);
   if (!result_json) {
     return {};
diff --git a/fuchsia_web/common/test/frame_test_util.h b/fuchsia_web/common/test/frame_test_util.h
index 8845577..4c01cbfb 100644
--- a/fuchsia_web/common/test/frame_test_util.h
+++ b/fuchsia_web/common/test/frame_test_util.h
@@ -8,9 +8,9 @@
 #include <fuchsia/mem/cpp/fidl.h>
 #include <fuchsia/web/cpp/fidl.h>
 
+#include <optional>
 #include "base/strings/string_piece.h"
 #include "base/values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // Uses |navigation_controller| to load |url| with |load_url_params|. Returns
 // after the load is completed. Returns true if the load was successful, false
@@ -25,9 +25,9 @@
     base::StringPiece url);
 
 // Executes |script| in the context of |frame|'s top-level document.
-// Returns an un-set |absl::optional<>| on failure.
-absl::optional<base::Value> ExecuteJavaScript(fuchsia::web::Frame* frame,
-                                              base::StringPiece script);
+// Returns an un-set |std::optional<>| on failure.
+std::optional<base::Value> ExecuteJavaScript(fuchsia::web::Frame* frame,
+                                             base::StringPiece script);
 
 // Creates and returns a LoadUrlParams with was_user_activated set to true.
 // This allows user actions to propagate to the frame, allowing features such as
diff --git a/fuchsia_web/common/test/url_request_rewrite_test_util.cc b/fuchsia_web/common/test/url_request_rewrite_test_util.cc
index 4430966..af6c4c9 100644
--- a/fuchsia_web/common/test/url_request_rewrite_test_util.cc
+++ b/fuchsia_web/common/test/url_request_rewrite_test_util.cc
@@ -26,7 +26,7 @@
 }
 
 fuchsia::web::UrlRequestRewrite CreateRewriteRemoveHeader(
-    absl::optional<base::StringPiece> query_pattern,
+    std::optional<base::StringPiece> query_pattern,
     base::StringPiece header_name) {
   fuchsia::web::UrlRequestRewriteRemoveHeader remove_header;
   if (query_pattern)
diff --git a/fuchsia_web/common/test/url_request_rewrite_test_util.h b/fuchsia_web/common/test/url_request_rewrite_test_util.h
index 6fe6d6c..1b8e8cc 100644
--- a/fuchsia_web/common/test/url_request_rewrite_test_util.h
+++ b/fuchsia_web/common/test/url_request_rewrite_test_util.h
@@ -7,8 +7,8 @@
 
 #include <fuchsia/web/cpp/fidl.h>
 
+#include <optional>
 #include "base/strings/string_piece.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // Utility functions to create a fuchsia.web.UrlRequestRewrite in one line.
 
@@ -17,7 +17,7 @@
     base::StringPiece header_value);
 
 fuchsia::web::UrlRequestRewrite CreateRewriteRemoveHeader(
-    absl::optional<base::StringPiece> query_pattern,
+    std::optional<base::StringPiece> query_pattern,
     base::StringPiece header_name);
 
 fuchsia::web::UrlRequestRewrite CreateRewriteSubstituteQueryPattern(
diff --git a/fuchsia_web/runners/cast/api_bindings_client.h b/fuchsia_web/runners/cast/api_bindings_client.h
index 3bffa7d..c682cd0 100644
--- a/fuchsia_web/runners/cast/api_bindings_client.h
+++ b/fuchsia_web/runners/cast/api_bindings_client.h
@@ -9,10 +9,10 @@
 #include <fuchsia/web/cpp/fidl.h>
 #include <vector>
 
+#include <optional>
 #include "base/memory/weak_ptr.h"
 #include "components/cast/message_port/message_port.h"
 #include "components/cast/named_message_port_connector/named_message_port_connector.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // Injects scripts received from the ApiBindings service, and provides connected
 // ports to the Agent.
@@ -60,7 +60,7 @@
   // Used by AttachToFrame() to invoke `on_error_callback` asynchronously.
   void CallOnErrorCallback(base::OnceClosure on_error_callback);
 
-  absl::optional<std::vector<chromium::cast::ApiBinding>> bindings_;
+  std::optional<std::vector<chromium::cast::ApiBinding>> bindings_;
   fuchsia::web::Frame* frame_ = nullptr;
   cast_api_bindings::NamedMessagePortConnector* connector_ = nullptr;
   chromium::cast::ApiBindingsPtr bindings_service_;
diff --git a/fuchsia_web/runners/cast/api_bindings_client_browsertest.cc b/fuchsia_web/runners/cast/api_bindings_client_browsertest.cc
index d20b1fb..b6a88ad 100644
--- a/fuchsia_web/runners/cast/api_bindings_client_browsertest.cc
+++ b/fuchsia_web/runners/cast/api_bindings_client_browsertest.cc
@@ -144,7 +144,7 @@
   port->ReceiveMessage(CallbackToFitFunction(response.GetCallback()));
   ASSERT_TRUE(response.Wait());
 
-  absl::optional<std::string> response_string =
+  std::optional<std::string> response_string =
       base::StringFromMemBuffer(response.Get().data());
   ASSERT_TRUE(response_string.has_value());
   EXPECT_EQ("ack ping", *response_string);
diff --git a/fuchsia_web/runners/cast/application_controller_impl.h b/fuchsia_web/runners/cast/application_controller_impl.h
index 1d23824..187349c 100644
--- a/fuchsia_web/runners/cast/application_controller_impl.h
+++ b/fuchsia_web/runners/cast/application_controller_impl.h
@@ -11,7 +11,7 @@
 #include <lib/fidl/cpp/binding.h>
 #include <lib/fidl/cpp/interface_request.h>
 
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include <optional>
 
 class ApplicationControllerImpl final
     : public fidl::Server<chromium_cast::ApplicationController> {
@@ -43,7 +43,7 @@
       GetPrivateMemorySizeCompleter::Sync& completer) override;
 
  private:
-  absl::optional<fidl::ServerBinding<chromium_cast::ApplicationController>>
+  std::optional<fidl::ServerBinding<chromium_cast::ApplicationController>>
       binding_;
   fuchsia::web::Frame* const frame_;
   const uint64_t trace_flow_id_;
diff --git a/fuchsia_web/runners/cast/application_controller_impl_unittest.cc b/fuchsia_web/runners/cast/application_controller_impl_unittest.cc
index 23a2f4d..b1bf68f 100644
--- a/fuchsia_web/runners/cast/application_controller_impl_unittest.cc
+++ b/fuchsia_web/runners/cast/application_controller_impl_unittest.cc
@@ -85,10 +85,10 @@
       base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
 
   MockFrame frame_;
-  absl::optional<fidl::ServerBinding<chromium_cast::ApplicationContext>>
+  std::optional<fidl::ServerBinding<chromium_cast::ApplicationContext>>
       application_context_binding_;
   fidl::Client<chromium_cast::ApplicationContext> application_context_;
-  absl::optional<ApplicationControllerImpl> application_;
+  std::optional<ApplicationControllerImpl> application_;
 
   fidl::Client<chromium_cast::ApplicationController> application_client_;
   base::OnceClosure wait_for_controller_callback_;
diff --git a/fuchsia_web/runners/cast/cast_component.h b/fuchsia_web/runners/cast/cast_component.h
index fc8018c..f6bb93ee 100644
--- a/fuchsia_web/runners/cast/cast_component.h
+++ b/fuchsia_web/runners/cast/cast_component.h
@@ -13,6 +13,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/fuchsia/startup_context.h"
 #include "base/gtest_prod_util.h"
 #include "base/message_loop/message_pump_for_io.h"
@@ -21,7 +22,6 @@
 #include "fuchsia_web/runners/cast/application_controller_impl.h"
 #include "fuchsia_web/runners/cast/named_message_port_connector_fuchsia.h"
 #include "fuchsia_web/runners/common/web_component.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 FORWARD_DECLARE_TEST(HeadlessCastRunnerIntegrationTest, Headless);
 
@@ -53,9 +53,9 @@
     std::unique_ptr<ApiBindingsClient> api_bindings_client;
     chromium::cast::ApplicationConfig application_config;
     fidl::ClientEnd<chromium_cast::ApplicationContext> application_context;
-    absl::optional<std::vector<fuchsia::web::UrlRequestRewriteRule>>
+    std::optional<std::vector<fuchsia::web::UrlRequestRewriteRule>>
         initial_url_rewrite_rules;
-    absl::optional<fuchsia::web::FrameMediaSettings> media_settings;
+    std::optional<fuchsia::web::FrameMediaSettings> media_settings;
 
     // ID of flow used in the with the Fuchsia Trace API to trace the
     // application lifetime.
diff --git a/fuchsia_web/runners/cast/cast_runner.cc b/fuchsia_web/runners/cast/cast_runner.cc
index 5bed74dd..9652f15e 100644
--- a/fuchsia_web/runners/cast/cast_runner.cc
+++ b/fuchsia_web/runners/cast/cast_runner.cc
@@ -97,13 +97,13 @@
 // Exits the Runner process if creation of data storage fails for any reason.
 void SetDataParamsForMainContext(fuchsia::web::CreateContextParams* params) {
   // Set the web data quota based on the CastRunner configuration.
-  const absl::optional<base::Value::Dict>& config =
+  const std::optional<base::Value::Dict>& config =
       fuchsia_component_support::LoadPackageConfig();
   if (!config)
     return;
 
   constexpr char kDataQuotaBytesSwitch[] = "data-quota-bytes";
-  const absl::optional<int> data_quota_bytes =
+  const std::optional<int> data_quota_bytes =
       config->FindInt(kDataQuotaBytesSwitch);
   if (!data_quota_bytes)
     return;
@@ -130,11 +130,11 @@
 // CDM data persistence is always enabled, with an optional soft quota.
 // Exits the Runner if creation of CDM storage fails for any reason.
 void SetCdmParamsForMainContext(fuchsia::web::CreateContextParams* params) {
-  const absl::optional<base::Value::Dict>& config =
+  const std::optional<base::Value::Dict>& config =
       fuchsia_component_support::LoadPackageConfig();
   if (config) {
     constexpr char kCdmDataQuotaBytesSwitch[] = "cdm-data-quota-bytes";
-    const absl::optional<int> cdm_data_quota_bytes =
+    const std::optional<int> cdm_data_quota_bytes =
         config->FindInt(kCdmDataQuotaBytesSwitch);
     if (cdm_data_quota_bytes)
       params->set_cdm_data_quota_bytes(*cdm_data_quota_bytes);
@@ -414,26 +414,26 @@
   return config;
 }
 
-absl::optional<WebContentRunner::WebInstanceConfig>
+std::optional<WebContentRunner::WebInstanceConfig>
 CastRunner::GetWebInstanceConfigForAppConfig(
     chromium::cast::ApplicationConfig* app_config) {
   if (IsAppConfigForCastStreaming(*app_config)) {
     // TODO(crbug.com/1082821): Remove this once the CastStreamingReceiver
     // Component has been implemented.
-    return absl::make_optional(GetIsolatedWebInstanceConfigForCastStreaming());
+    return std::make_optional(GetIsolatedWebInstanceConfigForCastStreaming());
   }
 
   const bool is_isolated_app =
       app_config->has_content_directories_for_isolated_application();
   if (is_isolated_app) {
-    return absl::make_optional(
+    return std::make_optional(
         GetIsolatedWebInstanceConfigWithFuchsiaDirs(std::move(
             *app_config
                  ->mutable_content_directories_for_isolated_application())));
   }
 
   // No need to create an isolated context in other cases.
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 WebContentRunner* CastRunner::CreateIsolatedRunner(
diff --git a/fuchsia_web/runners/cast/cast_runner.h b/fuchsia_web/runners/cast/cast_runner.h
index abc8631..2c699a87 100644
--- a/fuchsia_web/runners/cast/cast_runner.h
+++ b/fuchsia_web/runners/cast/cast_runner.h
@@ -13,6 +13,7 @@
 #include <set>
 #include <vector>
 
+#include <optional>
 #include "base/containers/flat_set.h"
 #include "base/containers/unique_ptr_adapters.h"
 #include "base/fuchsia/startup_context.h"
@@ -20,7 +21,6 @@
 #include "fuchsia_web/runners/cast/cast_component.h"
 #include "fuchsia_web/runners/cast/pending_cast_component.h"
 #include "fuchsia_web/runners/common/web_content_runner.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class WebInstanceHost;
 
@@ -88,7 +88,7 @@
 
   // Returns CreateContextParams for |app_config|. Returns nullopt if there is
   // no need to create an isolated context.
-  absl::optional<WebContentRunner::WebInstanceConfig>
+  std::optional<WebContentRunner::WebInstanceConfig>
   GetWebInstanceConfigForAppConfig(
       chromium::cast::ApplicationConfig* app_config);
 
@@ -150,7 +150,7 @@
 
   // Used to fetch & cache the list of CORS exempt HTTP headers to configure
   // each web.Context with.
-  absl::optional<std::vector<std::vector<uint8_t>>> cors_exempt_headers_;
+  std::optional<std::vector<std::vector<uint8_t>>> cors_exempt_headers_;
   chromium::cast::CorsExemptHeaderProviderPtr cors_exempt_headers_provider_;
   std::vector<base::OnceClosure> on_have_cors_exempt_headers_;
 
diff --git a/fuchsia_web/runners/cast/cast_runner_integration_test.cc b/fuchsia_web/runners/cast/cast_runner_integration_test.cc
index bac17e4..30b6509 100644
--- a/fuchsia_web/runners/cast/cast_runner_integration_test.cc
+++ b/fuchsia_web/runners/cast/cast_runner_integration_test.cc
@@ -138,7 +138,7 @@
     loop.Run();
   }
 
-  absl::optional<int64_t> WaitForApplicationTerminated() {
+  std::optional<int64_t> WaitForApplicationTerminated() {
     if (application_exit_code_.has_value()) {
       return application_exit_code_;
     }
@@ -171,7 +171,7 @@
   chromium::cast::ApplicationControllerPtr application_controller_;
   base::OnceClosure on_set_application_controller_;
 
-  absl::optional<int64_t> application_exit_code_;
+  std::optional<int64_t> application_exit_code_;
   base::OnceClosure on_application_terminated_;
 };
 
@@ -265,7 +265,7 @@
     test_port_->ReceiveMessage(CallbackToFitFunction(response.GetCallback()));
     EXPECT_TRUE(response.Wait());
 
-    absl::optional<std::string> response_string =
+    std::optional<std::string> response_string =
         base::StringFromMemBuffer(response.Get().data());
     EXPECT_TRUE(response_string.has_value());
 
@@ -400,9 +400,9 @@
   bool offer_services_ = true;
 
   // Holds the service directory and fake services offered to `component_`.
-  absl::optional<FakeComponentServices> services_;
+  std::optional<FakeComponentServices> services_;
 
-  absl::optional<fuchsia_component_support::DynamicComponentHost> component_;
+  std::optional<fuchsia_component_support::DynamicComponentHost> component_;
 
   fuchsia::web::MessagePortPtr test_port_;
 
@@ -874,7 +874,7 @@
 
   // Have the web content close itself, and wait for OnApplicationTerminated().
   EXPECT_EQ(component.ExecuteJavaScript("window.close()"), "undefined");
-  absl::optional<zx_status_t> exit_code =
+  std::optional<zx_status_t> exit_code =
       component.application_context().WaitForApplicationTerminated();
   ASSERT_TRUE(exit_code);
   EXPECT_EQ(exit_code.value(), ZX_OK);
@@ -896,7 +896,7 @@
   // Request that the component be destroyed, and wait for
   // OnApplicationTerminated().
   component.ShutdownComponent();
-  absl::optional<zx_status_t> exit_code =
+  std::optional<zx_status_t> exit_code =
       component.application_context().WaitForApplicationTerminated();
   ASSERT_TRUE(exit_code);
   EXPECT_EQ(exit_code.value(), ZX_OK);
diff --git a/fuchsia_web/runners/cast/cast_streaming.cc b/fuchsia_web/runners/cast/cast_streaming.cc
index 33b8016..f66ecd6 100644
--- a/fuchsia_web/runners/cast/cast_streaming.cc
+++ b/fuchsia_web/runners/cast/cast_streaming.cc
@@ -6,8 +6,8 @@
 
 #include <string>
 
+#include <optional>
 #include "components/fuchsia_component_support/config_reader.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -26,7 +26,7 @@
 }
 
 std::string GetMessagePortOriginForAppId(const std::string& app_id) {
-  const absl::optional<base::Value::Dict>& config =
+  const std::optional<base::Value::Dict>& config =
       fuchsia_component_support::LoadPackageConfig();
   if (!config) {
     return kCastStreamingMessagePortOrigin;
diff --git a/fuchsia_web/runners/cast/main.cc b/fuchsia_web/runners/cast/main.cc
index 6e97b98..9dc0a2d 100644
--- a/fuchsia_web/runners/cast/main.cc
+++ b/fuchsia_web/runners/cast/main.cc
@@ -9,6 +9,7 @@
 
 #include <utility>
 
+#include <optional>
 #include "base/check.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
@@ -33,7 +34,6 @@
 #include "fuchsia_web/runners/cast/cast_runner.h"
 #include "fuchsia_web/runners/cast/cast_runner_switches.h"
 #include "fuchsia_web/webinstance_host/web_instance_host.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -49,7 +49,7 @@
 
 // Returns the value of |config_key| or false if it is not set.
 bool GetConfigBool(base::StringPiece config_key) {
-  const absl::optional<base::Value::Dict>& config =
+  const std::optional<base::Value::Dict>& config =
       fuchsia_component_support::LoadPackageConfig();
   if (config)
     return config->FindBool(config_key).value_or(false);
diff --git a/fuchsia_web/runners/cast/test/cast_runner_launcher.h b/fuchsia_web/runners/cast/test/cast_runner_launcher.h
index 3f758d7e..8b28903 100644
--- a/fuchsia_web/runners/cast/test/cast_runner_launcher.h
+++ b/fuchsia_web/runners/cast/test/cast_runner_launcher.h
@@ -11,10 +11,10 @@
 #include <memory>
 #include <string_view>
 
+#include <optional>
 #include "fuchsia_web/common/test/fake_feedback_service.h"
 #include "fuchsia_web/runners/cast/test/cast_runner_features.h"
 #include "fuchsia_web/runners/cast/test/fake_cast_agent.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace test {
 
@@ -51,7 +51,7 @@
   FakeCastAgent& fake_cast_agent() { return *fake_cast_agent_; }
 
  private:
-  absl::optional<::component_testing::RealmRoot> realm_root_;
+  std::optional<::component_testing::RealmRoot> realm_root_;
 
   std::unique_ptr<sys::ServiceDirectory> exposed_services_;
 
diff --git a/fuchsia_web/runners/cast/test/fake_application_config_manager.cc b/fuchsia_web/runners/cast/test/fake_application_config_manager.cc
index 813f4ec..e7bfc24 100644
--- a/fuchsia_web/runners/cast/test/fake_application_config_manager.cc
+++ b/fuchsia_web/runners/cast/test/fake_application_config_manager.cc
@@ -9,9 +9,9 @@
 #include <string>
 #include <utility>
 
+#include <optional>
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/logging.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 constexpr char FakeApplicationConfigManager::kFakeAgentUrl[] =
     "fuchsia-pkg://fuchsia.com/fake_agent#meta/fake_agent.cmx";
@@ -60,7 +60,7 @@
   // ContextDirectoryProviders contain move-only fuchsia.io.Directory resources,
   // so if those are present then remove them, manually clone them, then
   // put them back.
-  absl::optional<std::vector<fuchsia::web::ContentDirectoryProvider>>
+  std::optional<std::vector<fuchsia::web::ContentDirectoryProvider>>
       content_directories;
   chromium::cast::ApplicationConfig& config = it->second;
   if (config.has_content_directories_for_isolated_application()) {
diff --git a/fuchsia_web/shell/cast_streaming_shell.cc b/fuchsia_web/shell/cast_streaming_shell.cc
index 63b7dd3..12a5e3ec 100644
--- a/fuchsia_web/shell/cast_streaming_shell.cc
+++ b/fuchsia_web/shell/cast_streaming_shell.cc
@@ -8,6 +8,7 @@
 #include <lib/sys/cpp/component_context.h>
 #include <lib/sys/cpp/service_directory.h>
 
+#include <optional>
 #include "base/base_paths.h"
 #include "base/check.h"
 #include "base/command_line.h"
@@ -38,7 +39,6 @@
 #include "fuchsia_web/webinstance_host/web_instance_host.h"
 #include "media/base/media_util.h"
 #include "media/gpu/test/video_test_helpers.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -88,7 +88,7 @@
 }
 
 // Set autoplay, enable all logging, and present fullscreen view of `frame`.
-absl::optional<fuchsia::element::GraphicalPresenterPtr> ConfigureFrame(
+std::optional<fuchsia::element::GraphicalPresenterPtr> ConfigureFrame(
     fuchsia::web::Frame* frame,
     fidl::InterfaceHandle<fuchsia::element::AnnotationController>
         annotation_controller) {
@@ -115,7 +115,7 @@
     return optional_exit_code.value();
   }
 
-  absl::optional<uint16_t> remote_debugging_port =
+  std::optional<uint16_t> remote_debugging_port =
       GetRemoteDebuggingPort(*command_line);
   if (!remote_debugging_port) {
     PrintUsage();
@@ -224,7 +224,7 @@
   // Send `sender_message_port` to a Sender and start it.
   cast_streaming::CastStreamingTestSender sender;
   sender.Start(std::move(sender_message_port), net::IPAddress::IPv6Localhost(),
-               absl::nullopt, GetDefaultVideoConfig());
+               std::nullopt, GetDefaultVideoConfig());
 
   // Navigate `frame` to `receiver.html`.
   fuchsia::web::LoadUrlParams load_params;
@@ -262,7 +262,7 @@
   // Load video.
   base::FilePath video_file(
       pkg_path.AppendASCII("media/test/data/bear-1280x720.ivf"));
-  absl::optional<std::vector<uint8_t>> video_stream =
+  std::optional<std::vector<uint8_t>> video_stream =
       base::ReadFileToBytes(video_file);
   CHECK(video_stream.has_value());
   media::test::EncodedDataHelper video_helper(video_stream.value(),
diff --git a/fuchsia_web/shell/remote_debugging_port.cc b/fuchsia_web/shell/remote_debugging_port.cc
index 05a550f4..729902ef 100644
--- a/fuchsia_web/shell/remote_debugging_port.cc
+++ b/fuchsia_web/shell/remote_debugging_port.cc
@@ -10,7 +10,7 @@
 
 constexpr char kRemoteDebuggingPortSwitch[] = "remote-debugging-port";
 
-absl::optional<uint16_t> GetRemoteDebuggingPort(
+std::optional<uint16_t> GetRemoteDebuggingPort(
     const base::CommandLine& command_line) {
   if (!command_line.HasSwitch(kRemoteDebuggingPortSwitch)) {
     return 0;
@@ -22,7 +22,7 @@
         port_parsed > 65535) {
       LOG(ERROR) << "Invalid value for --remote-debugging-port (must be in the "
                     "range 0-65535).";
-      return absl::nullopt;
+      return std::nullopt;
     }
     return static_cast<uint16_t>(port_parsed);
   }
diff --git a/fuchsia_web/shell/remote_debugging_port.h b/fuchsia_web/shell/remote_debugging_port.h
index 3454ff6..a8865f3 100644
--- a/fuchsia_web/shell/remote_debugging_port.h
+++ b/fuchsia_web/shell/remote_debugging_port.h
@@ -5,7 +5,7 @@
 #ifndef FUCHSIA_WEB_SHELL_REMOTE_DEBUGGING_PORT_H_
 #define FUCHSIA_WEB_SHELL_REMOTE_DEBUGGING_PORT_H_
 
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include <optional>
 
 extern const char kRemoteDebuggingPortSwitch[];
 
@@ -19,7 +19,7 @@
 // port switch. If |command_line| contains the appropriate switch, returns the
 // remote debugging port specified in the |command_line| or nullopt on parsing
 // failure.
-absl::optional<uint16_t> GetRemoteDebuggingPort(
+std::optional<uint16_t> GetRemoteDebuggingPort(
     const base::CommandLine& command_line);
 
 #endif  // FUCHSIA_WEB_SHELL_REMOTE_DEBUGGING_PORT_H_
diff --git a/fuchsia_web/shell/shell_relauncher.cc b/fuchsia_web/shell/shell_relauncher.cc
index 3aa2567..b4a9337 100644
--- a/fuchsia_web/shell/shell_relauncher.cc
+++ b/fuchsia_web/shell/shell_relauncher.cc
@@ -16,13 +16,13 @@
 #include "base/run_loop.h"
 #include "fuchsia_web/common/test/test_realm_support.h"
 
-absl::optional<int> RelaunchForWebInstanceHostIfParent(
+std::optional<int> RelaunchForWebInstanceHostIfParent(
     base::StringPiece relative_component_url,
     const base::CommandLine& command_line) {
   // Nothing to do if running from the context of a relaunched process.
   static constexpr char kNoRelaunch[] = "no-relaunch";
   if (command_line.HasSwitch(kNoRelaunch)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   auto realm_builder = component_testing::RealmBuilder::CreateFromRelativeUrl(
diff --git a/fuchsia_web/shell/shell_relauncher.h b/fuchsia_web/shell/shell_relauncher.h
index c0b2f2f9..7b0614e 100644
--- a/fuchsia_web/shell/shell_relauncher.h
+++ b/fuchsia_web/shell/shell_relauncher.h
@@ -5,8 +5,8 @@
 #ifndef FUCHSIA_WEB_SHELL_SHELL_RELAUNCHER_H_
 #define FUCHSIA_WEB_SHELL_SHELL_RELAUNCHER_H_
 
+#include <optional>
 #include "base/strings/string_piece.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class CommandLine;
@@ -17,7 +17,7 @@
 // use RealmBuilder to relaunch the shell via the given package-relative URL
 // (which includes `--no-relaunch` on its command line) with the contents of
 // this process's command line.
-absl::optional<int> RelaunchForWebInstanceHostIfParent(
+std::optional<int> RelaunchForWebInstanceHostIfParent(
     base::StringPiece relative_component_url,
     const base::CommandLine& command_line);
 
diff --git a/fuchsia_web/shell/web_engine_shell.cc b/fuchsia_web/shell/web_engine_shell.cc
index 9b1746bc..b29c348 100644
--- a/fuchsia_web/shell/web_engine_shell.cc
+++ b/fuchsia_web/shell/web_engine_shell.cc
@@ -13,6 +13,7 @@
 #include <iostream>
 #include <utility>
 
+#include <optional>
 #include "base/base_paths.h"
 #include "base/check.h"
 #include "base/command_line.h"
@@ -36,7 +37,6 @@
 #include "fuchsia_web/shell/shell_relauncher.h"
 #include "fuchsia_web/webinstance_host/web_instance_host.h"
 #include "fuchsia_web/webinstance_host/web_instance_host_constants.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/widevine/cdm/buildflags.h"
 #include "url/gurl.h"
 
@@ -112,7 +112,7 @@
     }
   }
 
-  absl::optional<uint16_t> remote_debugging_port =
+  std::optional<uint16_t> remote_debugging_port =
       GetRemoteDebuggingPort(*command_line);
   if (!remote_debugging_port) {
     PrintUsage();
diff --git a/fuchsia_web/webengine/browser/accessibility_browsertest.cc b/fuchsia_web/webengine/browser/accessibility_browsertest.cc
index 8ef090c..5cf4361 100644
--- a/fuchsia_web/webengine/browser/accessibility_browsertest.cc
+++ b/fuchsia_web/webengine/browser/accessibility_browsertest.cc
@@ -144,7 +144,7 @@
 
  protected:
   // TODO(crbug.com/1038786): Maybe move to WebEngineBrowserTest.
-  absl::optional<base::TestComponentContextForProcess> test_context_;
+  std::optional<base::TestComponentContextForProcess> test_context_;
 
   FrameForTest frame_;
   FrameImpl* frame_impl_;
@@ -152,7 +152,7 @@
 
   // Binding to the fake semantics manager.
   // Optional so that it can be instantiated outside the constructor.
-  absl::optional<base::ScopedServiceBinding<
+  std::optional<base::ScopedServiceBinding<
       fuchsia::accessibility::semantics::SemanticsManager>>
       semantics_manager_binding_;
 };
diff --git a/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc b/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc
index 6c41f36..a80898e8 100644
--- a/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc
+++ b/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc
@@ -149,8 +149,8 @@
   frame.navigation_listener().RunUntilTitleEquals("loadedmetadata");
 
   EXPECT_TRUE(post_result.Wait());
-  EXPECT_NE(sender.audio_decoder_config(), absl::nullopt);
-  EXPECT_NE(sender.video_decoder_config(), absl::nullopt);
+  EXPECT_NE(sender.audio_decoder_config(), std::nullopt);
+  EXPECT_NE(sender.video_decoder_config(), std::nullopt);
 }
 
 // Check that attempting to start a video-only receiver properly disables audio.
@@ -194,6 +194,6 @@
   frame.navigation_listener().RunUntilTitleEquals("loadedmetadata");
 
   EXPECT_TRUE(post_result.Wait());
-  EXPECT_EQ(sender.audio_decoder_config(), absl::nullopt);
-  EXPECT_NE(sender.video_decoder_config(), absl::nullopt);
+  EXPECT_EQ(sender.audio_decoder_config(), std::nullopt);
+  EXPECT_NE(sender.video_decoder_config(), std::nullopt);
 }
diff --git a/fuchsia_web/webengine/browser/client_hints_browsertest.cc b/fuchsia_web/webengine/browser/client_hints_browsertest.cc
index ae9fc46..1f371ed 100644
--- a/fuchsia_web/webengine/browser/client_hints_browsertest.cc
+++ b/fuchsia_web/webengine/browser/client_hints_browsertest.cc
@@ -97,7 +97,7 @@
                              url.spec());
     frame_for_test_.navigation_listener().RunUntilUrlEquals(url);
 
-    absl::optional<base::Value> value =
+    std::optional<base::Value> value =
         ExecuteJavaScript(frame_for_test_.get(), "document.body.innerText;");
     return value->GetString();
   }
@@ -369,7 +369,7 @@
                            url.spec());
   frame_for_test_.navigation_listener().RunUntilUrlEquals(url);
 
-  absl::optional<base::Value> value =
+  std::optional<base::Value> value =
       ExecuteJavaScript(frame_for_test_.get(), "document.body.innerText;");
   EXPECT_EQ(value->GetString(), k64Bitness);
 }
diff --git a/fuchsia_web/webengine/browser/content_directory_loader_factory.cc b/fuchsia_web/webengine/browser/content_directory_loader_factory.cc
index f8ba7572..dd7850dd 100644
--- a/fuchsia_web/webengine/browser/content_directory_loader_factory.cc
+++ b/fuchsia_web/webengine/browser/content_directory_loader_factory.cc
@@ -53,7 +53,7 @@
 //            will assume the charset to be "text/plain" by default.
 scoped_refptr<net::HttpResponseHeaders> CreateHeaders(
     base::StringPiece mime_type,
-    const absl::optional<std::string>& charset) {
+    const std::optional<std::string>& charset) {
   constexpr char kXFrameOptions[] = "X-Frame-Options";
   constexpr char kXFrameOptionsValue[] = "DENY";
   constexpr char kCacheControl[] = "Cache-Control";
@@ -174,11 +174,11 @@
     auto response = network::mojom::URLResponseHead::New();
 
     // Read the charset and MIME type from the optional _metadata file.
-    absl::optional<std::string> charset;
-    absl::optional<std::string> mime_type;
+    std::optional<std::string> charset;
+    std::optional<std::string> mime_type;
     base::MemoryMappedFile metadata_mmap;
     if (MapFile(std::move(metadata_channel), &metadata_mmap)) {
-      absl::optional<base::Value> metadata_parsed = base::JSONReader::Read(
+      std::optional<base::Value> metadata_parsed = base::JSONReader::Read(
           base::StringPiece(reinterpret_cast<char*>(metadata_mmap.data()),
                             metadata_mmap.length()));
 
@@ -236,7 +236,7 @@
     }
 
     client_->OnReceiveResponse(std::move(response), std::move(consumer_handle),
-                               absl::nullopt);
+                               std::nullopt);
 
     // Start reading the contents of |mmap_| into the response DataPipe.
     body_writer_ =
@@ -257,7 +257,7 @@
       const std::vector<std::string>& removed_headers,
       const net::HttpRequestHeaders& modified_request_headers,
       const net::HttpRequestHeaders& modified_cors_exempt_request_headers,
-      const absl::optional<GURL>& new_url) override {}
+      const std::optional<GURL>& new_url) override {}
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
   void PauseReadingBodyFromNet() override {}
diff --git a/fuchsia_web/webengine/browser/context_impl.cc b/fuchsia_web/webengine/browser/context_impl.cc
index 8f25b63f..d16068b 100644
--- a/fuchsia_web/webengine/browser/context_impl.cc
+++ b/fuchsia_web/webengine/browser/context_impl.cc
@@ -130,7 +130,7 @@
 
   // Verify the explicit sites filter error page content. If the parameter is
   // present, it will be provided to the FrameImpl after it is created below.
-  absl::optional<std::string> explicit_sites_filter_error_page;
+  std::optional<std::string> explicit_sites_filter_error_page;
   if (params.has_explicit_sites_filter_error_page()) {
     explicit_sites_filter_error_page =
         base::StringFromMemData(params.explicit_sites_filter_error_page());
diff --git a/fuchsia_web/webengine/browser/cookie_manager_impl.cc b/fuchsia_web/webengine/browser/cookie_manager_impl.cc
index 36f537ad..cfb6840 100644
--- a/fuchsia_web/webengine/browser/cookie_manager_impl.cc
+++ b/fuchsia_web/webengine/browser/cookie_manager_impl.cc
@@ -189,7 +189,7 @@
                           std::move(changes));
 
   if (url) {
-    absl::optional<std::string> maybe_name;
+    std::optional<std::string> maybe_name;
     if (name)
       maybe_name = *name;
     cookie_manager_->AddCookieChangeListener(GURL(*url), maybe_name,
diff --git a/fuchsia_web/webengine/browser/cookie_manager_impl_unittest.cc b/fuchsia_web/webengine/browser/cookie_manager_impl_unittest.cc
index cb8556b..b2ea2614 100644
--- a/fuchsia_web/webengine/browser/cookie_manager_impl_unittest.cc
+++ b/fuchsia_web/webengine/browser/cookie_manager_impl_unittest.cc
@@ -7,6 +7,7 @@
 #include <map>
 #include <vector>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/run_loop.h"
 #include "base/strings/string_piece.h"
@@ -22,7 +23,6 @@
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/test/fake_test_cert_verifier_params_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -45,7 +45,7 @@
       /*secure=*/true,
       /*httponly*/ false, net::CookieSameSite::NO_RESTRICTION,
       net::COOKIE_PRIORITY_MEDIUM, /*same_party=*/false,
-      /*partition_key=*/absl::nullopt);
+      /*partition_key=*/std::nullopt);
 }
 
 class CookieManagerImplTest : public testing::Test {
@@ -101,8 +101,8 @@
   }
 
   // Synchronously fetches all cookies via the |cookie_manager_|.
-  // Returns a absl::nullopt if the iterator closes before a GetNext() returns.
-  absl::optional<std::vector<fuchsia::web::Cookie>> GetAllCookies() {
+  // Returns a std::nullopt if the iterator closes before a GetNext() returns.
+  std::optional<std::vector<fuchsia::web::Cookie>> GetAllCookies() {
     base::RunLoop get_cookies_loop;
     fuchsia::web::CookiesIteratorPtr cookies_iterator;
     cookies_iterator.set_error_handler([&](zx_status_t status) {
@@ -111,7 +111,7 @@
     });
     cookie_manager_.GetCookieList(nullptr, nullptr,
                                   cookies_iterator.NewRequest());
-    absl::optional<std::vector<fuchsia::web::Cookie>> cookies;
+    std::optional<std::vector<fuchsia::web::Cookie>> cookies;
     std::function<void(std::vector<fuchsia::web::Cookie>)> get_next_callback =
         [&](std::vector<fuchsia::web::Cookie> new_cookies) {
           if (!cookies.has_value()) {
@@ -160,18 +160,18 @@
   ~GetNextCookiesIteratorResult() = default;
 
   void ExpectSingleCookie(base::StringPiece name,
-                          absl::optional<base::StringPiece> value) {
+                          std::optional<base::StringPiece> value) {
     ExpectCookieUpdates({{name, value}});
   }
 
   void ExpectDeleteSingleCookie(base::StringPiece name) {
-    ExpectCookieUpdates({{name, absl::nullopt}});
+    ExpectCookieUpdates({{name, std::nullopt}});
   }
 
   // Specifies the cookie name/value pairs expected in the GetNext() results.
-  // Deletions expectations are specified by using absl::nullopt as the value.
+  // Deletions expectations are specified by using std::nullopt as the value.
   void ExpectCookieUpdates(
-      std::map<base::StringPiece, absl::optional<base::StringPiece>> expected) {
+      std::map<base::StringPiece, std::optional<base::StringPiece>> expected) {
     ASSERT_TRUE(result_.Wait());
     ASSERT_EQ(result_.Get().size(), expected.size());
     std::map<base::StringPiece, base::StringPiece> result_updates;
@@ -362,7 +362,7 @@
 
     GetNextCookiesIteratorResult global_updates(global_changes.get());
     global_updates.ExpectCookieUpdates(
-        {{kCookieName1, absl::nullopt}, {kCookieName2, absl::nullopt}});
+        {{kCookieName1, std::nullopt}, {kCookieName2, std::nullopt}});
   }
 }
 
diff --git a/fuchsia_web/webengine/browser/fake_semantics_manager.h b/fuchsia_web/webengine/browser/fake_semantics_manager.h
index 9d048695..fd89213 100644
--- a/fuchsia_web/webengine/browser/fake_semantics_manager.h
+++ b/fuchsia_web/webengine/browser/fake_semantics_manager.h
@@ -9,9 +9,9 @@
 #include <fuchsia/accessibility/semantics/cpp/fidl_test_base.h>
 #include <lib/fidl/cpp/binding.h>
 
+#include <optional>
 #include "base/functional/callback.h"
 #include "fuchsia_web/webengine/browser/fake_semantic_tree.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class FakeSemanticsManager : public fuchsia::accessibility::semantics::testing::
                                  SemanticsManager_TestBase {
@@ -75,7 +75,7 @@
   // which can support many.
   FakeSemanticTree semantic_tree_;
 
-  absl::optional<uint32_t> hit_test_result_;
+  std::optional<uint32_t> hit_test_result_;
   int32_t num_actions_handled_ = 0;
   int32_t num_actions_unhandled_ = 0;
   int32_t expected_num_actions_ = 0;
diff --git a/fuchsia_web/webengine/browser/favicon_browsertest.cc b/fuchsia_web/webengine/browser/favicon_browsertest.cc
index 8ddaaa2..f5f702b 100644
--- a/fuchsia_web/webengine/browser/favicon_browsertest.cc
+++ b/fuchsia_web/webengine/browser/favicon_browsertest.cc
@@ -43,7 +43,7 @@
   ASSERT_TRUE(favicon.has_height());
   EXPECT_EQ(favicon.height(), expected_height);
   ASSERT_TRUE(favicon.has_data());
-  absl::optional<std::string> data = base::StringFromMemBuffer(favicon.data());
+  std::optional<std::string> data = base::StringFromMemBuffer(favicon.data());
   ASSERT_TRUE(data.has_value());
   size_t expected_size = expected_width * expected_height * sizeof(uint32_t);
   ASSERT_EQ(data->size(), expected_size);
diff --git a/fuchsia_web/webengine/browser/frame_impl.cc b/fuchsia_web/webengine/browser/frame_impl.cc
index 67ba5e2..51e83f1 100644
--- a/fuchsia_web/webengine/browser/frame_impl.cc
+++ b/fuchsia_web/webengine/browser/frame_impl.cc
@@ -253,20 +253,20 @@
       nullptr);
 }
 
-absl::optional<url::Origin> ParseAndValidateWebOrigin(
+std::optional<url::Origin> ParseAndValidateWebOrigin(
     const std::string& origin_str) {
   GURL origin_url(origin_str);
   if (!origin_url.username().empty() || !origin_url.password().empty() ||
       !origin_url.query().empty() || !origin_url.ref().empty()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (!origin_url.path().empty() && origin_url.path() != "/")
-    return absl::nullopt;
+    return std::nullopt;
 
   auto origin = url::Origin::Create(origin_url);
   if (origin.opaque())
-    return absl::nullopt;
+    return std::nullopt;
 
   return origin;
 }
@@ -378,7 +378,7 @@
   }
 
   std::unique_ptr<content::AudioStreamBrokerFactory> base_factory_;
-  absl::optional<fuchsia::media::AudioRenderUsage> output_usage_;
+  std::optional<fuchsia::media::AudioRenderUsage> output_usage_;
   base::WeakPtrFactory<AudioStreamBrokerFactory> weak_factory_{this};
 };
 
@@ -531,7 +531,7 @@
     return;
   }
 
-  absl::optional<std::u16string> script_utf16 =
+  std::optional<std::u16string> script_utf16 =
       base::ReadUTF8FromVMOAsUTF16(script);
   if (!script_utf16) {
     callback(fpromise::error(fuchsia::web::FrameError::BUFFER_NOT_UTF8));
@@ -945,7 +945,7 @@
     return;
   }
 
-  absl::optional<std::string> script_as_string =
+  std::optional<std::string> script_as_string =
       base::StringFromMemBuffer(script);
   if (!script_as_string) {
     LOG(ERROR) << "Couldn't read script from buffer.";
@@ -1003,11 +1003,11 @@
     return;
   }
 
-  absl::optional<std::u16string> origin_utf16;
+  std::optional<std::u16string> origin_utf16;
   if (origin != kWildcardOrigin)
     origin_utf16 = base::UTF8ToUTF16(origin);
 
-  absl::optional<std::u16string> data_utf16 =
+  std::optional<std::u16string> data_utf16 =
       base::ReadUTF8FromVMOAsUTF16(message.data());
   if (!data_utf16) {
     callback(fpromise::error(fuchsia::web::FrameError::BUFFER_NOT_UTF8));
diff --git a/fuchsia_web/webengine/browser/frame_impl.h b/fuchsia_web/webengine/browser/frame_impl.h
index f078887..0e15bea 100644
--- a/fuchsia_web/webengine/browser/frame_impl.h
+++ b/fuchsia_web/webengine/browser/frame_impl.h
@@ -19,6 +19,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/fuchsia/scoped_fx_logger.h"
 #include "base/gtest_prod_util.h"
 #include "base/logging.h"
@@ -35,7 +36,6 @@
 #include "fuchsia_web/webengine/browser/navigation_controller_impl.h"
 #include "fuchsia_web/webengine/browser/theme_manager.h"
 #include "fuchsia_web/webengine/web_engine_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "ui/accessibility/platform/fuchsia/accessibility_bridge_fuchsia_impl.h"
 #include "ui/aura/window_tree_host.h"
@@ -116,7 +116,7 @@
   // empty, the default error page will be used.
   void EnableExplicitSitesFilter(std::string error_page);
 
-  const absl::optional<std::string>& explicit_sites_filter_error_page() const {
+  const std::optional<std::string>& explicit_sites_filter_error_page() const {
     return explicit_sites_filter_error_page_;
   }
 
@@ -387,8 +387,8 @@
   std::unique_ptr<ui::AccessibilityBridgeFuchsiaImpl> accessibility_bridge_;
 
   // Test settings.
-  absl::optional<gfx::Size> window_size_for_test_;
-  absl::optional<float> device_scale_factor_for_test_;
+  std::optional<gfx::Size> window_size_for_test_;
+  std::optional<float> device_scale_factor_for_test_;
 
   EventFilter event_filter_;
   NavigationControllerImpl navigation_controller_;
@@ -418,7 +418,7 @@
   // The error page to be displayed when a navigation to an explicit site is
   // filtered. Explicit sites are filtered if it has a value. If set to the
   // empty string, the default error page will be displayed.
-  absl::optional<std::string> explicit_sites_filter_error_page_;
+  std::optional<std::string> explicit_sites_filter_error_page_;
 
   // Used to publish Frame details to Inspect.
   inspect::Node inspect_node_;
diff --git a/fuchsia_web/webengine/browser/frame_impl_browsertest.cc b/fuchsia_web/webengine/browser/frame_impl_browsertest.cc
index 957f84fd..a3fcade 100644
--- a/fuchsia_web/webengine/browser/frame_impl_browsertest.cc
+++ b/fuchsia_web/webengine/browser/frame_impl_browsertest.cc
@@ -921,7 +921,7 @@
                                        url.spec()));
   frame.navigation_listener().RunUntilUrlAndTitleEquals(url, "done");
 
-  absl::optional<base::Value> default_dpr =
+  std::optional<base::Value> default_dpr =
       ExecuteJavaScript(frame.ptr().get(), "window.devicePixelRatio");
   ASSERT_TRUE(default_dpr);
 
@@ -933,7 +933,7 @@
   settings.set_page_scale(kZoomInScale);
   frame->SetContentAreaSettings(std::move(settings));
 
-  absl::optional<base::Value> scaled_dpr =
+  std::optional<base::Value> scaled_dpr =
       ExecuteJavaScript(frame.ptr().get(), "window.devicePixelRatio");
   ASSERT_TRUE(scaled_dpr);
 
@@ -949,7 +949,7 @@
                                        url2.spec()));
   frame.navigation_listener().RunUntilUrlAndTitleEquals(url2, "done");
 
-  absl::optional<base::Value> dpr_after_navigation =
+  std::optional<base::Value> dpr_after_navigation =
       ExecuteJavaScript(frame.ptr().get(), "window.devicePixelRatio");
   ASSERT_TRUE(scaled_dpr);
 
@@ -962,7 +962,7 @@
   settings2.set_page_scale(kDefaultScale);
   frame->SetContentAreaSettings(std::move(settings2));
 
-  absl::optional<base::Value> dpr_after_reset =
+  std::optional<base::Value> dpr_after_reset =
       ExecuteJavaScript(frame.ptr().get(), "window.devicePixelRatio");
   ASSERT_TRUE(dpr_after_reset);
 
@@ -974,7 +974,7 @@
   settings3.set_page_scale(kZoomOutScale);
   frame->SetContentAreaSettings(std::move(settings3));
 
-  absl::optional<base::Value> zoomed_out_dpr =
+  std::optional<base::Value> zoomed_out_dpr =
       ExecuteJavaScript(frame.ptr().get(), "window.devicePixelRatio");
   ASSERT_TRUE(zoomed_out_dpr);
 
@@ -998,7 +998,7 @@
                                        url.spec()));
   frame2.navigation_listener().RunUntilUrlAndTitleEquals(url, "done");
 
-  absl::optional<base::Value> frame2_dpr =
+  std::optional<base::Value> frame2_dpr =
       ExecuteJavaScript(frame2.ptr().get(), "window.devicePixelRatio");
   ASSERT_TRUE(frame2_dpr);
 
diff --git a/fuchsia_web/webengine/browser/input_browsertest.cc b/fuchsia_web/webengine/browser/input_browsertest.cc
index e89a12e0e..cf0ef1a 100644
--- a/fuchsia_web/webengine/browser/input_browsertest.cc
+++ b/fuchsia_web/webengine/browser/input_browsertest.cc
@@ -251,7 +251,7 @@
     frame_for_test_.navigation_listener().RunUntilTitleEquals(
         base::NumberToString(expected.size()));
 
-    absl::optional<base::Value> actual =
+    std::optional<base::Value> actual =
         ExecuteJavaScript(frame_for_test_.ptr().get(), kKeyDicts);
     EXPECT_EQ(*actual, base::Value(std::move(expected)));
   }
@@ -264,13 +264,13 @@
   }
 
   // Used to publish fake services.
-  absl::optional<base::TestComponentContextForProcess> component_context_;
+  std::optional<base::TestComponentContextForProcess> component_context_;
 
   FrameForTest frame_for_test_;
   ScenicTestHelper scenic_test_helper_;
-  absl::optional<FakeKeyboard> keyboard_service_;
+  std::optional<FakeKeyboard> keyboard_service_;
   base::test::ScopedFeatureList scoped_feature_list_;
-  absl::optional<
+  std::optional<
       NeverConnectedChecker<fuchsia_input_virtualkeyboard::ControllerCreator>>
       virtual_keyboard_checker_;
 };
@@ -592,7 +592,7 @@
     keyboard_input_checker_.emplace(component_context_->additional_services());
   }
 
-  absl::optional<NeverConnectedChecker<fuchsia_ui_input3::Keyboard>>
+  std::optional<NeverConnectedChecker<fuchsia_ui_input3::Keyboard>>
       keyboard_input_checker_;
 };
 
diff --git a/fuchsia_web/webengine/browser/media_browsertest.cc b/fuchsia_web/webengine/browser/media_browsertest.cc
index 8bac4a8..8928863 100644
--- a/fuchsia_web/webengine/browser/media_browsertest.cc
+++ b/fuchsia_web/webengine/browser/media_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include <fuchsia/mediacodec/cpp/fidl_test_base.h>
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/fuchsia/scoped_service_binding.h"
 #include "base/fuchsia/test_component_context_for_process.h"
@@ -17,7 +18,6 @@
 #include "fuchsia_web/webengine/features.h"
 #include "fuchsia_web/webengine/test/test_data.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -84,7 +84,7 @@
   }
 
   // Used to disconnect fuchsia.mediacodec.CodecFactory.
-  absl::optional<base::TestComponentContextForProcess> component_context_;
+  std::optional<base::TestComponentContextForProcess> component_context_;
 };
 
 // Verify that a codec only supported by a software decoder is reported as
diff --git a/fuchsia_web/webengine/browser/media_player_impl.cc b/fuchsia_web/webengine/browser/media_player_impl.cc
index 334f1b87..0274b06 100644
--- a/fuchsia_web/webengine/browser/media_player_impl.cc
+++ b/fuchsia_web/webengine/browser/media_player_impl.cc
@@ -211,7 +211,7 @@
 }
 
 void MediaPlayerImpl::MediaSessionMetadataChanged(
-    const absl::optional<media_session::MediaMetadata>& metadata_mojo) {
+    const std::optional<media_session::MediaMetadata>& metadata_mojo) {
   fuchsia_media::Metadata metadata;
   if (metadata_mojo) {
     AddMetadata(fuchsia_media::kMetadataLabelTitle, metadata_mojo->title,
@@ -247,7 +247,7 @@
 }
 
 void MediaPlayerImpl::MediaSessionPositionChanged(
-    const absl::optional<media_session::MediaPosition>& position) {
+    const std::optional<media_session::MediaPosition>& position) {
   // TODO(https://crbug.com/879317): Implement media position changes.
   NOTIMPLEMENTED_LOG_ONCE();
 }
@@ -259,7 +259,7 @@
     return;
   // std::exchange(foo, {}) returns the contents of |foo|, while ensuring that
   // |foo| is reset to the initial/empty state.
-  std::exchange(pending_info_change_callback_, absl::nullopt)
+  std::exchange(pending_info_change_callback_, std::nullopt)
       ->Reply(std::exchange(pending_info_delta_, {}));
 }
 
diff --git a/fuchsia_web/webengine/browser/media_player_impl.h b/fuchsia_web/webengine/browser/media_player_impl.h
index f128ee7e..f1c781d 100644
--- a/fuchsia_web/webengine/browser/media_player_impl.h
+++ b/fuchsia_web/webengine/browser/media_player_impl.h
@@ -8,11 +8,11 @@
 #include <fidl/fuchsia.media.sessions2/cpp/fidl.h>
 #include <string>
 
+#include <optional>
 #include "base/functional/callback.h"
 #include "fuchsia_web/webengine/web_engine_export.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "services/media_session/public/mojom/media_session.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace content {
 class MediaSession;
@@ -63,7 +63,7 @@
   void MediaSessionInfoChanged(
       media_session::mojom::MediaSessionInfoPtr info) override;
   void MediaSessionMetadataChanged(
-      const absl::optional<media_session::MediaMetadata>& metadata) override;
+      const std::optional<media_session::MediaMetadata>& metadata) override;
   void MediaSessionActionsChanged(
       const std::vector<media_session::mojom::MediaSessionAction>& action)
       override;
@@ -72,7 +72,7 @@
                            std::vector<media_session::MediaImage>>& images)
       override;
   void MediaSessionPositionChanged(
-      const absl::optional<media_session::MediaPosition>& position) override;
+      const std::optional<media_session::MediaPosition>& position) override;
 
   // Sends changes accumulated in |pending_info_delta_|, if any, to the
   // |pending_info_change_callback_|, if it is set.
@@ -95,7 +95,7 @@
   mojo::Receiver<media_session::mojom::MediaSessionObserver> observer_receiver_;
 
   // Pending PlayerInfo deltas and info-change callback.
-  absl::optional<WatchInfoChangeCompleter::Async> pending_info_change_callback_;
+  std::optional<WatchInfoChangeCompleter::Async> pending_info_change_callback_;
   fuchsia_media_sessions2::PlayerInfoDelta pending_info_delta_;
 };
 
diff --git a/fuchsia_web/webengine/browser/media_player_impl_unittest.cc b/fuchsia_web/webengine/browser/media_player_impl_unittest.cc
index f01e24ad..b481c29 100644
--- a/fuchsia_web/webengine/browser/media_player_impl_unittest.cc
+++ b/fuchsia_web/webengine/browser/media_player_impl_unittest.cc
@@ -329,7 +329,7 @@
   // Calling WatchInfoChange() now should succeed, but not immediately return
   // any new data.
   base::RunLoop change_loop;
-  absl::optional<fuchsia_media_sessions2::PlayerState> state_after_change;
+  std::optional<fuchsia_media_sessions2::PlayerState> state_after_change;
 
   player_->WatchInfoChange().Then(
       [&change_loop, &state_after_change](
diff --git a/fuchsia_web/webengine/browser/message_port.cc b/fuchsia_web/webengine/browser/message_port.cc
index 8fda5e2..8efbbd6 100644
--- a/fuchsia_web/webengine/browser/message_port.cc
+++ b/fuchsia_web/webengine/browser/message_port.cc
@@ -30,14 +30,14 @@
 // Converts a fuchsia::web::WebMessage to a BlinkMessage.
 // An empty result indicates that conversion was successful.
 // Data validation errors are returned as a FrameError.
-absl::optional<fuchsia::web::FrameError> BlinkMessageFromFidl(
+std::optional<fuchsia::web::FrameError> BlinkMessageFromFidl(
     fuchsia::web::WebMessage fidl_message,
     BlinkMessage* blink_message) {
   if (!fidl_message.has_data()) {
     return fuchsia::web::FrameError::NO_DATA_IN_MESSAGE;
   }
 
-  absl::optional<std::u16string> data_utf16 =
+  std::optional<std::u16string> data_utf16 =
       base::ReadUTF8FromVMOAsUTF16(fidl_message.data());
   if (!data_utf16) {
     return fuchsia::web::FrameError::BUFFER_NOT_UTF8;
@@ -67,7 +67,7 @@
     }
   }
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 // Defines a MessagePortAdapter, which translates and routes messages between a
@@ -103,9 +103,9 @@
 
   // Returns the next messagefrom Blink, or an empty value if there
   // are no more messages in the incoming queue.
-  absl::optional<fuchsia::web::WebMessage> GetNextBlinkMessage() {
+  std::optional<fuchsia::web::WebMessage> GetNextBlinkMessage() {
     if (message_queue_.empty())
-      return absl::nullopt;
+      return std::nullopt;
 
     return std::move(message_queue_.front());
   }
@@ -118,7 +118,7 @@
  private:
   // blink::WebMessagePort::MessageReceiver implementation:
   bool OnMessage(BlinkMessage message) override {
-    absl::optional<fuchsia::web::WebMessage> message_converted =
+    std::optional<fuchsia::web::WebMessage> message_converted =
         FidlWebMessageFromBlink(std::move(message),
                                 TransferableHostType::kLocal);
     if (!message_converted) {
@@ -178,7 +178,7 @@
 
   void OnMessageReceived(fuchsia::web::WebMessage message) {
     BlinkMessage blink_message;
-    absl::optional<fuchsia::web::FrameError> result =
+    std::optional<fuchsia::web::FrameError> result =
         BlinkMessageFromFidl(std::move(message), &blink_message);
     if (result) {
       LOG(WARNING) << "Received bad message, error: "
@@ -205,7 +205,7 @@
 
   // MessagePortAdapter implementation.
   void DeliverMessageToFidl() override {
-    absl::optional<fuchsia::web::WebMessage> message = GetNextBlinkMessage();
+    std::optional<fuchsia::web::WebMessage> message = GetNextBlinkMessage();
     if (!message)
       return;
 
@@ -259,7 +259,7 @@
     if (!pending_receive_message_callback_)
       return;
 
-    absl::optional<fuchsia::web::WebMessage> message = GetNextBlinkMessage();
+    std::optional<fuchsia::web::WebMessage> message = GetNextBlinkMessage();
     if (!message)
       return;
 
@@ -272,7 +272,7 @@
   void PostMessage(fuchsia::web::WebMessage message,
                    PostMessageCallback callback) override {
     BlinkMessage blink_message;
-    absl::optional<fuchsia::web::FrameError> status =
+    std::optional<fuchsia::web::FrameError> status =
         BlinkMessageFromFidl(std::move(message), &blink_message);
 
     if (status) {
@@ -339,7 +339,7 @@
   return adapter->NewBinding();
 }
 
-absl::optional<fuchsia::web::WebMessage> FidlWebMessageFromBlink(
+std::optional<fuchsia::web::WebMessage> FidlWebMessageFromBlink(
     BlinkMessage blink_message,
     TransferableHostType port_type) {
   fuchsia::web::WebMessage fidl_message;
@@ -370,7 +370,7 @@
   std::u16string data_utf16 = std::move(blink_message.data);
   std::string data_utf8;
   if (!base::UTF16ToUTF8(data_utf16.data(), data_utf16.size(), &data_utf8))
-    return absl::nullopt;
+    return std::nullopt;
 
   base::STLClearObject(&data_utf16);
 
@@ -378,7 +378,7 @@
   fuchsia::mem::Buffer data_buffer =
       base::MemBufferFromString(data_utf8, kBufferVmoName);
   if (!data_buffer.vmo)
-    return absl::nullopt;
+    return std::nullopt;
 
   fidl_message.set_data(std::move(data_buffer));
   return fidl_message;
diff --git a/fuchsia_web/webengine/browser/message_port.h b/fuchsia_web/webengine/browser/message_port.h
index d13136d..4aa2ecc 100644
--- a/fuchsia_web/webengine/browser/message_port.h
+++ b/fuchsia_web/webengine/browser/message_port.h
@@ -9,7 +9,7 @@
 #include <lib/fidl/cpp/interface_handle.h>
 #include <lib/fidl/cpp/interface_request.h>
 
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include <optional>
 #include "third_party/blink/public/common/messaging/web_message_port.h"
 
 // Creates a connected MessagePort from a FIDL MessagePort request and
@@ -38,7 +38,7 @@
 };
 
 // Converts a BlinkMessage to a fuchsia::web::WebMessage.
-absl::optional<fuchsia::web::WebMessage> FidlWebMessageFromBlink(
+std::optional<fuchsia::web::WebMessage> FidlWebMessageFromBlink(
     blink::WebMessagePort::Message blink_message,
     TransferableHostType port_type);
 
diff --git a/fuchsia_web/webengine/browser/mock_virtual_keyboard.h b/fuchsia_web/webengine/browser/mock_virtual_keyboard.h
index b6bc920..374f6fe8 100644
--- a/fuchsia_web/webengine/browser/mock_virtual_keyboard.h
+++ b/fuchsia_web/webengine/browser/mock_virtual_keyboard.h
@@ -8,11 +8,11 @@
 #include <fidl/fuchsia.input.virtualkeyboard/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
 
+#include <optional>
 #include "base/fuchsia/scoped_service_binding.h"
 #include "base/fuchsia/test_component_context_for_process.h"
 #include "base/functional/callback.h"
 #include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class MockVirtualKeyboardController
     : public fidl::Server<fuchsia_input_virtualkeyboard::Controller> {
@@ -48,12 +48,12 @@
   void WatchVisibility(WatchVisibilityCompleter::Sync& completer) final;
 
   base::OnceClosure on_watch_visibility_;
-  absl::optional<fidl::Server<fuchsia_input_virtualkeyboard::Controller>::
-                     WatchVisibilityCompleter::Async>
+  std::optional<fidl::Server<fuchsia_input_virtualkeyboard::Controller>::
+                    WatchVisibilityCompleter::Async>
       watch_visibility_completer_;
   fuchsia_ui_views::ViewRef view_ref_;
   fuchsia_input_virtualkeyboard::TextType text_type_;
-  absl::optional<fidl::ServerBinding<fuchsia_input_virtualkeyboard::Controller>>
+  std::optional<fidl::ServerBinding<fuchsia_input_virtualkeyboard::Controller>>
       binding_;
 };
 
diff --git a/fuchsia_web/webengine/browser/request_monitoring_browsertest.cc b/fuchsia_web/webengine/browser/request_monitoring_browsertest.cc
index e4ce6855..609c85cf 100644
--- a/fuchsia_web/webengine/browser/request_monitoring_browsertest.cc
+++ b/fuchsia_web/webengine/browser/request_monitoring_browsertest.cc
@@ -290,7 +290,7 @@
 
   std::vector<fuchsia::web::UrlRequestRewrite> rewrites;
   rewrites.push_back(CreateRewriteAddHeaders("Test", "Value"));
-  rewrites.push_back(CreateRewriteRemoveHeader(absl::nullopt, "Test"));
+  rewrites.push_back(CreateRewriteRemoveHeader(std::nullopt, "Test"));
   fuchsia::web::UrlRequestRewriteRule rule;
   rule.set_rewrites(std::move(rewrites));
   std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
@@ -330,7 +330,7 @@
   std::vector<fuchsia::web::UrlRequestRewrite> rewrites;
   rewrites.push_back(CreateRewriteAddHeaders("Test", "Value"));
   rewrites.push_back(
-      CreateRewriteRemoveHeader(absl::make_optional("[pattern]"), "Test"));
+      CreateRewriteRemoveHeader(std::make_optional("[pattern]"), "Test"));
   fuchsia::web::UrlRequestRewriteRule rule;
   rule.set_rewrites(std::move(rewrites));
   std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
diff --git a/fuchsia_web/webengine/browser/theme_manager.cc b/fuchsia_web/webengine/browser/theme_manager.cc
index 3413e3c..73f1ac6 100644
--- a/fuchsia_web/webengine/browser/theme_manager.cc
+++ b/fuchsia_web/webengine/browser/theme_manager.cc
@@ -137,7 +137,7 @@
        settings.theme().theme_type() == ThemeType::LIGHT)) {
     system_theme_ = settings.theme().theme_type();
   } else {
-    system_theme_ = absl::nullopt;
+    system_theme_ = std::nullopt;
   }
 
   web_contents_->OnWebPreferencesChanged();
diff --git a/fuchsia_web/webengine/browser/theme_manager.h b/fuchsia_web/webengine/browser/theme_manager.h
index b44299f..6c01c55 100644
--- a/fuchsia_web/webengine/browser/theme_manager.h
+++ b/fuchsia_web/webengine/browser/theme_manager.h
@@ -9,10 +9,10 @@
 #include <fuchsia/web/cpp/fidl.h>
 #include <lib/sys/cpp/component_context.h>
 
+#include <optional>
 #include "base/fuchsia/process_context.h"
 #include "content/public/browser/web_contents.h"
 #include "fuchsia_web/webengine/web_engine_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 
 class WEB_ENGINE_EXPORT ThemeManager {
@@ -48,8 +48,8 @@
 
   bool observed_display_service_error_ = false;
   bool did_receive_first_watch_result_ = false;
-  absl::optional<fuchsia::settings::ThemeType> requested_theme_;
-  absl::optional<fuchsia::settings::ThemeType> system_theme_;
+  std::optional<fuchsia::settings::ThemeType> requested_theme_;
+  std::optional<fuchsia::settings::ThemeType> system_theme_;
   content::WebContents* web_contents_;
   fuchsia::settings::DisplayPtr display_service_;
   base::OnceClosure on_display_error_;
diff --git a/fuchsia_web/webengine/browser/theme_manager_browsertest.cc b/fuchsia_web/webengine/browser/theme_manager_browsertest.cc
index 0e5825d..d816695 100644
--- a/fuchsia_web/webengine/browser/theme_manager_browsertest.cc
+++ b/fuchsia_web/webengine/browser/theme_manager_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include <fuchsia/settings/cpp/fidl_test_base.h>
 
+#include <optional>
 #include "base/fuchsia/scoped_service_binding.h"
 #include "base/fuchsia/test_component_context_for_process.h"
 #include "base/json/json_writer.h"
@@ -19,7 +20,6 @@
 #include "fuchsia_web/webengine/test/test_data.h"
 #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -80,7 +80,7 @@
     theme.set_theme_type(theme_type);
     settings.set_theme(std::move(theme));
     (*watch_callback_)(std::move(settings));
-    watch_callback_ = absl::nullopt;
+    watch_callback_ = std::nullopt;
     base::RunLoop().RunUntilIdle();
   }
 
@@ -127,13 +127,13 @@
     ADD_FAILURE() << "Unexpected call: " << name;
   }
 
-  absl::optional<base::TestComponentContextForProcess> component_context_;
-  absl::optional<base::ScopedServiceBinding<fuchsia::settings::Display>>
+  std::optional<base::TestComponentContextForProcess> component_context_;
+  std::optional<base::ScopedServiceBinding<fuchsia::settings::Display>>
       display_binding_;
   FrameForTest frame_;
 
   base::OnceClosure on_watch_closure_;
-  absl::optional<WatchCallback> watch_callback_;
+  std::optional<WatchCallback> watch_callback_;
 };
 
 IN_PROC_BROWSER_TEST_F(ThemeManagerTest, Default) {
@@ -166,7 +166,7 @@
 
   ASSERT_TRUE(display_binding_->has_clients());
 
-  display_binding_ = absl::nullopt;
+  display_binding_ = std::nullopt;
   base::RunLoop().RunUntilIdle();
 
   ASSERT_FALSE(display_binding_);
diff --git a/fuchsia_web/webengine/browser/url_request_rewrite_type_converters.cc b/fuchsia_web/webengine/browser/url_request_rewrite_type_converters.cc
index 931182a..4b3fdd4 100644
--- a/fuchsia_web/webengine/browser/url_request_rewrite_type_converters.cc
+++ b/fuchsia_web/webengine/browser/url_request_rewrite_type_converters.cc
@@ -49,7 +49,7 @@
     url_rewrite::mojom::UrlRequestRewriteRemoveHeaderPtr remove_header =
         url_rewrite::mojom::UrlRequestRewriteRemoveHeader::New();
     if (input.has_query_pattern())
-      remove_header->query_pattern = absl::make_optional(input.query_pattern());
+      remove_header->query_pattern = std::make_optional(input.query_pattern());
     if (input.has_header_name()) {
       remove_header->header_name =
           std::string(BytesAsString(input.header_name()));
@@ -177,7 +177,7 @@
     }
 
     if (input.has_schemes_filter())
-      rule->schemes_filter = absl::make_optional(input.schemes_filter());
+      rule->schemes_filter = std::make_optional(input.schemes_filter());
 
     if (input.has_rewrites()) {
       rule->actions =
diff --git a/fuchsia_web/webengine/browser/url_request_rewrite_type_converters_unittest.cc b/fuchsia_web/webengine/browser/url_request_rewrite_type_converters_unittest.cc
index 0359ebb..6763122 100644
--- a/fuchsia_web/webengine/browser/url_request_rewrite_type_converters_unittest.cc
+++ b/fuchsia_web/webengine/browser/url_request_rewrite_type_converters_unittest.cc
@@ -51,7 +51,7 @@
 TEST(UrlRequestRewriteTypeConvertersTest, ConvertRemoveHeader) {
   url_rewrite::mojom::UrlRequestRewriteRulesPtr rules =
       ConvertFuchsiaRulesToMojom(
-          CreateRewriteRemoveHeader(absl::make_optional("Test"), "Header"));
+          CreateRewriteRemoveHeader(std::make_optional("Test"), "Header"));
   ASSERT_EQ(rules->rules.size(), 1u);
   ASSERT_FALSE(rules->rules[0]->hosts_filter);
   ASSERT_FALSE(rules->rules[0]->schemes_filter);
@@ -66,7 +66,7 @@
 
   // Create a RemoveHeader rewrite with no pattern.
   rules = ConvertFuchsiaRulesToMojom(
-      CreateRewriteRemoveHeader(absl::nullopt, "Header"));
+      CreateRewriteRemoveHeader(std::nullopt, "Header"));
   ASSERT_EQ(rules->rules.size(), 1u);
   ASSERT_FALSE(rules->rules[0]->hosts_filter);
   ASSERT_FALSE(rules->rules[0]->schemes_filter);
diff --git a/fuchsia_web/webengine/browser/virtual_keyboard_browsertest.cc b/fuchsia_web/webengine/browser/virtual_keyboard_browsertest.cc
index bbc770b..9386bbf 100644
--- a/fuchsia_web/webengine/browser/virtual_keyboard_browsertest.cc
+++ b/fuchsia_web/webengine/browser/virtual_keyboard_browsertest.cc
@@ -118,7 +118,7 @@
     // Distance to click from the top/left extents of an input field.
     constexpr int kInputFieldClickInset = 8;
 
-    absl::optional<base::Value> result = ExecuteJavaScript(
+    std::optional<base::Value> result = ExecuteJavaScript(
         frame_for_test_.ptr().get(),
         base::StringPrintf("getPointInsideText('%.*s')",
                            base::saturated_cast<int>(id.length()), id.data()));
@@ -140,12 +140,12 @@
   ScenicTestHelper scenic_test_helper_;
   base::test::ScopedFeatureList scoped_feature_list_;
 
-  absl::optional<EnsureConnectedChecker<fuchsia_ui_input3::Keyboard>>
+  std::optional<EnsureConnectedChecker<fuchsia_ui_input3::Keyboard>>
       keyboard_input_checker_;
 
   // Fake virtual keyboard services for the InputMethod to use.
-  absl::optional<base::TestComponentContextForProcess> component_context_;
-  absl::optional<MockVirtualKeyboardControllerCreator> controller_creator_;
+  std::optional<base::TestComponentContextForProcess> component_context_;
+  std::optional<MockVirtualKeyboardControllerCreator> controller_creator_;
   std::unique_ptr<MockVirtualKeyboardController> controller_;
 
   content::WebContents* web_contents_ = nullptr;
diff --git a/fuchsia_web/webengine/browser/web_engine_browser_main_parts.cc b/fuchsia_web/webengine/browser/web_engine_browser_main_parts.cc
index 69388fd..98ca4c0d 100644
--- a/fuchsia_web/webengine/browser/web_engine_browser_main_parts.cc
+++ b/fuchsia_web/webengine/browser/web_engine_browser_main_parts.cc
@@ -139,7 +139,7 @@
   std::string cdm_data_directory =
       command_line->GetSwitchValueASCII(switches::kCdmDataDirectory);
 
-  absl::optional<uint64_t> cdm_data_quota_bytes;
+  std::optional<uint64_t> cdm_data_quota_bytes;
   if (command_line->HasSwitch(switches::kCdmDataQuotaBytes)) {
     uint64_t value = 0;
     CHECK(base::StringToUint64(
diff --git a/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc b/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc
index 5da496b..ccbc05b 100644
--- a/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc
+++ b/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc
@@ -237,7 +237,7 @@
     RegisterNonNetworkSubresourceURLLoaderFactories(
         int render_process_id,
         int render_frame_id,
-        const absl::optional<url::Origin>& request_initiator_origin,
+        const std::optional<url::Origin>& request_initiator_origin,
         NonNetworkURLLoaderFactoryMap* factories) {
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableContentDirectories)) {
@@ -319,7 +319,7 @@
         navigation_handle, frame_impl->navigation_policy_handler()));
   }
 
-  const absl::optional<std::string>& explicit_sites_filter_error_page =
+  const std::optional<std::string>& explicit_sites_filter_error_page =
       frame_impl->explicit_sites_filter_error_page();
 
   if (explicit_sites_filter_error_page) {
diff --git a/fuchsia_web/webengine/browser/web_engine_content_browser_client.h b/fuchsia_web/webengine/browser/web_engine_content_browser_client.h
index f9b382a..716441d 100644
--- a/fuchsia_web/webengine/browser/web_engine_content_browser_client.h
+++ b/fuchsia_web/webengine/browser/web_engine_content_browser_client.h
@@ -44,7 +44,7 @@
   void RegisterNonNetworkSubresourceURLLoaderFactories(
       int render_process_id,
       int render_frame_id,
-      const absl::optional<url::Origin>& request_initiator_origin,
+      const std::optional<url::Origin>& request_initiator_origin,
       NonNetworkURLLoaderFactoryMap* factories) override;
   bool ShouldEnableStrictSiteIsolation() override;
   void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
diff --git a/fuchsia_web/webengine/browser/web_engine_devtools_controller.cc b/fuchsia_web/webengine/browser/web_engine_devtools_controller.cc
index d08768eb..daa8883 100644
--- a/fuchsia_web/webengine/browser/web_engine_devtools_controller.cc
+++ b/fuchsia_web/webengine/browser/web_engine_devtools_controller.cc
@@ -9,6 +9,7 @@
 #include <lib/sys/cpp/component_context.h>
 #include <vector>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/containers/flat_set.h"
 #include "base/fuchsia/process_context.h"
@@ -22,7 +23,6 @@
 #include "net/base/net_errors.h"
 #include "net/base/port_util.h"
 #include "net/socket/tcp_server_socket.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -45,7 +45,7 @@
     auto socket =
         std::make_unique<net::TCPServerSocket>(nullptr, net::NetLogSource());
     int error = socket->Listen(ip_end_point_, kTcpListenBackLog,
-                               /*ipv6_only=*/absl::nullopt);
+                               /*ipv6_only=*/std::nullopt);
     if (error != net::OK) {
       LOG(WARNING) << "Failed to start the HTTP debugger service. "
                    << net::ErrorToString(error);
@@ -186,7 +186,7 @@
   bool is_remote_debugging_started_ = false;
 
   // Currently active DevTools port. Set to 0 on service startup error.
-  absl::optional<uint16_t> devtools_port_;
+  std::optional<uint16_t> devtools_port_;
 
   // Set of Frames' content::WebContents which are remotely debuggable.
   base::flat_set<content::WebContents*> debuggable_contents_;
@@ -247,7 +247,7 @@
   }
 
   // Currently active DevTools port. Set to 0 on service startup error.
-  absl::optional<uint16_t> devtools_port_;
+  std::optional<uint16_t> devtools_port_;
 
  private:
   // fuchsia::web::Debug implementation.
@@ -335,7 +335,7 @@
 std::unique_ptr<WebEngineDevToolsController>
 WebEngineDevToolsController::CreateFromCommandLine(
     const base::CommandLine& command_line) {
-  absl::optional<uint16_t> devtools_port;
+  std::optional<uint16_t> devtools_port;
   if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
     // Set up DevTools to listen on all network routes on the command-line
     // provided port.
diff --git a/fuchsia_web/webengine/browser/web_engine_memory_inspector.cc b/fuchsia_web/webengine/browser/web_engine_memory_inspector.cc
index 3a2be26..2b7919d 100644
--- a/fuchsia_web/webengine/browser/web_engine_memory_inspector.cc
+++ b/fuchsia_web/webengine/browser/web_engine_memory_inspector.cc
@@ -17,7 +17,7 @@
 namespace {
 
 std::vector<std::string> GetAllocatorDumpNamesFromConfig() {
-  const absl::optional<base::Value::Dict>& config =
+  const std::optional<base::Value::Dict>& config =
       fuchsia_component_support::LoadPackageConfig();
   if (!config)
     return {};
diff --git a/fuchsia_web/webengine/context_provider_impl_unittest.cc b/fuchsia_web/webengine/context_provider_impl_unittest.cc
index a5dbe14..4bf2448 100644
--- a/fuchsia_web/webengine/context_provider_impl_unittest.cc
+++ b/fuchsia_web/webengine/context_provider_impl_unittest.cc
@@ -20,6 +20,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/containers/contains.h"
@@ -42,7 +43,6 @@
 #include "services/network/public/cpp/network_switches.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -445,7 +445,7 @@
   // A mock fuchsia::component/Realm used to bridge to `fake_realm_`.
   ::testing::StrictMock<fuchsia_component_support::MockRealm> mock_realm_;
   fidl::BindingSet<fuchsia::web::ContextProvider> bindings_;
-  absl::optional<ContextProviderImpl> provider_;
+  std::optional<ContextProviderImpl> provider_;
   fuchsia::web::ContextProviderPtr provider_ptr_;
 };
 
diff --git a/fuchsia_web/webengine/renderer/web_engine_audio_renderer.cc b/fuchsia_web/webengine/renderer/web_engine_audio_renderer.cc
index 3da5717d..d0941d2 100644
--- a/fuchsia_web/webengine/renderer/web_engine_audio_renderer.cc
+++ b/fuchsia_web/webengine/renderer/web_engine_audio_renderer.cc
@@ -23,7 +23,7 @@
 
 // nullopt is returned in case the codec is not supported. nullptr is returned
 // for uncompressed PCM streams.
-absl::optional<std::unique_ptr<fuchsia::media::Compression>>
+std::optional<std::unique_ptr<fuchsia::media::Compression>>
 GetFuchsiaCompressionFromDecoderConfig(media::AudioDecoderConfig config) {
   auto compression = std::make_unique<fuchsia::media::Compression>();
   switch (config.codec()) {
@@ -49,7 +49,7 @@
       break;
 
     default:
-      return absl::nullopt;
+      return std::nullopt;
   }
 
   if (!config.extra_data().empty()) {
@@ -59,7 +59,7 @@
   return std::move(compression);
 }
 
-absl::optional<fuchsia::media::AudioSampleFormat>
+std::optional<fuchsia::media::AudioSampleFormat>
 GetFuchsiaSampleFormatFromSampleFormat(media::SampleFormat sample_format) {
   switch (sample_format) {
     case media::kSampleFormatU8:
@@ -72,7 +72,7 @@
       return fuchsia::media::AudioSampleFormat::FLOAT;
 
     default:
-      return absl::nullopt;
+      return std::nullopt;
   }
 }
 
@@ -253,7 +253,7 @@
 
   // Set sample_format for uncompressed streams.
   if (!compression.value()) {
-    absl::optional<fuchsia::media::AudioSampleFormat> sample_format =
+    std::optional<fuchsia::media::AudioSampleFormat> sample_format =
         GetFuchsiaSampleFormatFromSampleFormat(config.sample_format());
     if (!sample_format) {
       LOG(ERROR) << "Unsupported sample format: "
@@ -330,7 +330,7 @@
 }
 
 void WebEngineAudioRenderer::SetLatencyHint(
-    absl::optional<base::TimeDelta> latency_hint) {
+    std::optional<base::TimeDelta> latency_hint) {
   // TODO(crbug.com/1131116): Implement at some later date after we've vetted
   // the API shape and usefulness outside of fuchsia.
   NOTIMPLEMENTED();
diff --git a/fuchsia_web/webengine/renderer/web_engine_audio_renderer.h b/fuchsia_web/webengine/renderer/web_engine_audio_renderer.h
index 9a2a649..79d89a7 100644
--- a/fuchsia_web/webengine/renderer/web_engine_audio_renderer.h
+++ b/fuchsia_web/webengine/renderer/web_engine_audio_renderer.h
@@ -50,7 +50,7 @@
   void Flush(base::OnceClosure callback) override;
   void StartPlaying() override;
   void SetVolume(float volume) override;
-  void SetLatencyHint(absl::optional<base::TimeDelta> latency_hint) override;
+  void SetLatencyHint(std::optional<base::TimeDelta> latency_hint) override;
   void SetPreservesPitch(bool preserves_pitch) override;
   void SetWasPlayedWithUserActivation(
       bool was_played_with_user_activation) override;
diff --git a/fuchsia_web/webengine/renderer/web_engine_audio_renderer_test.cc b/fuchsia_web/webengine/renderer/web_engine_audio_renderer_test.cc
index aab78436..22bc603d 100644
--- a/fuchsia_web/webengine/renderer/web_engine_audio_renderer_test.cc
+++ b/fuchsia_web/webengine/renderer/web_engine_audio_renderer_test.cc
@@ -8,6 +8,7 @@
 #include <fuchsia/media/cpp/fidl_test_base.h>
 #include <lib/fidl/cpp/binding.h>
 
+#include <optional>
 #include "base/containers/queue.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/logging.h"
@@ -23,7 +24,6 @@
 #include "media/fuchsia/common/passthrough_sysmem_buffer_stream.h"
 #include "media/fuchsia/common/sysmem_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -41,7 +41,7 @@
     explicit ReadResult(const media::AudioDecoderConfig& config)
         : config(config) {}
 
-    absl::optional<media::AudioDecoderConfig> config;
+    std::optional<media::AudioDecoderConfig> config;
     scoped_refptr<media::DecoderBuffer> buffer;
   };
 
@@ -211,8 +211,8 @@
     EXPECT_TRUE(started_);
   }
 
-  void UpdateStatus(absl::optional<base::TimeTicks> reference_time,
-                    absl::optional<base::TimeDelta> media_time) {
+  void UpdateStatus(std::optional<base::TimeTicks> reference_time,
+                    std::optional<base::TimeDelta> media_time) {
     fuchsia::media::AudioConsumerStatus status;
     if (reference_time) {
       CHECK(media_time);
@@ -305,7 +305,7 @@
 
     std::move(status_callback_)(std::move(status_update_.value()));
     status_callback_ = {};
-    status_update_ = absl::nullopt;
+    status_update_ = std::nullopt;
   }
 
   fidl::Binding<fuchsia::media::AudioConsumer> binding_;
@@ -318,7 +318,7 @@
   bool create_stream_sink_called_ = false;
 
   WatchStatusCallback status_callback_;
-  absl::optional<fuchsia::media::AudioConsumerStatus> status_update_;
+  std::optional<fuchsia::media::AudioConsumerStatus> status_update_;
 
   bool started_ = false;
   base::TimeDelta start_media_time_;
@@ -348,7 +348,7 @@
 
   media::BufferingState buffering_state() const { return buffering_state_; }
 
-  absl::optional<media::AudioDecoderConfig> last_config_change() const {
+  std::optional<media::AudioDecoderConfig> last_config_change() const {
     return last_config_change_;
   }
 
@@ -386,7 +386,7 @@
   }
   void OnVideoNaturalSizeChange(const gfx::Size& size) override { FAIL(); }
   void OnVideoOpacityChange(bool opaque) override { FAIL(); }
-  void OnVideoFrameRateChange(absl::optional<int> fps) override { FAIL(); }
+  void OnVideoFrameRateChange(std::optional<int> fps) override { FAIL(); }
 
  private:
   media::PipelineStatus expected_error_ = media::PIPELINE_OK;
@@ -394,7 +394,7 @@
   bool expect_eos_ = false;
   media::BufferingState buffering_state_ = media::BUFFERING_HAVE_NOTHING;
   size_t bytes_decoded_ = 0;
-  absl::optional<media::AudioDecoderConfig> last_config_change_;
+  std::optional<media::AudioDecoderConfig> last_config_change_;
 };
 
 // media::SysmemBufferStream that asynchronously decouples buffer production
@@ -501,7 +501,7 @@
   void FillDemuxerStream(base::TimeDelta end_pos);
   void FillBuffer();
   void StartPlayback(base::TimeDelta start_time = base::TimeDelta());
-  void CheckGetWallClockTimes(absl::optional<base::TimeDelta> media_timestamp,
+  void CheckGetWallClockTimes(std::optional<base::TimeDelta> media_timestamp,
                               base::TimeTicks expected_wall_clock,
                               bool is_time_moving);
 
@@ -561,7 +561,7 @@
 
   ASSERT_EQ(pipeline_status, media::PIPELINE_OK);
 
-  audio_consumer_->UpdateStatus(absl::nullopt, absl::nullopt);
+  audio_consumer_->UpdateStatus(std::nullopt, std::nullopt);
 
   task_environment_.RunUntilIdle();
 }
@@ -633,7 +633,7 @@
 }
 
 void WebEngineAudioRendererTestBase::CheckGetWallClockTimes(
-    absl::optional<base::TimeDelta> media_timestamp,
+    std::optional<base::TimeDelta> media_timestamp,
     base::TimeTicks expected_wall_clock,
     bool is_time_moving) {
   std::vector<base::TimeDelta> media_timestamps;
@@ -664,7 +664,7 @@
   task_environment_.FastForwardBy(kTimeStep);
   EXPECT_EQ(time_source_->CurrentMediaTime(), start_time);
 
-  CheckGetWallClockTimes(absl::nullopt, base::TimeTicks(), false);
+  CheckGetWallClockTimes(std::nullopt, base::TimeTicks(), false);
   CheckGetWallClockTimes(start_time + kTimeStep,
                          base::TimeTicks::Now() + kTimeStep, false);
 
@@ -680,7 +680,7 @@
   EXPECT_EQ(time_source_->CurrentMediaTime(),
             start_time + (-kStartDelay + kTimeStep) * playback_rate);
 
-  CheckGetWallClockTimes(absl::nullopt, base::TimeTicks::Now(), true);
+  CheckGetWallClockTimes(std::nullopt, base::TimeTicks::Now(), true);
   CheckGetWallClockTimes(start_time + kTimeStep,
                          start_wall_clock + kTimeStep / playback_rate, true);
   CheckGetWallClockTimes(start_time + 2 * kTimeStep,
diff --git a/fuchsia_web/webengine/renderer/web_engine_content_renderer_client.cc b/fuchsia_web/webengine/renderer/web_engine_content_renderer_client.cc
index d56cb1c..80c7c01 100644
--- a/fuchsia_web/webengine/renderer/web_engine_content_renderer_client.cc
+++ b/fuchsia_web/webengine/renderer/web_engine_content_renderer_client.cc
@@ -6,6 +6,7 @@
 
 #include <tuple>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "build/chromecast_buildflags.h"
@@ -24,7 +25,6 @@
 #include "media/base/video_codecs.h"
 #include "services/network/public/cpp/features.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/web/web_view.h"
diff --git a/fuchsia_web/webengine/test/isolated_archivist.h b/fuchsia_web/webengine/test/isolated_archivist.h
index 7237a68..75f6543 100644
--- a/fuchsia_web/webengine/test/isolated_archivist.h
+++ b/fuchsia_web/webengine/test/isolated_archivist.h
@@ -8,8 +8,8 @@
 #include <fidl/fuchsia.logger/cpp/fidl.h>
 #include <lib/sys/cpp/outgoing_directory.h>
 
+#include <optional>
 #include "base/fuchsia/scoped_service_publisher.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // Runs an isolated archivist-for-embedding, publishing its
 // fuchsia_logger::LogSink into a given OutgoingDirectory, and providing access
@@ -26,7 +26,7 @@
   fidl::Client<fuchsia_logger::Log>& log() { return log_; }
 
  private:
-  absl::optional<base::ScopedNaturalServicePublisher<fuchsia_logger::LogSink>>
+  std::optional<base::ScopedNaturalServicePublisher<fuchsia_logger::LogSink>>
       log_sink_publisher_;
   fidl::Client<fuchsia_logger::Log> log_;
 };
diff --git a/fuchsia_web/webengine/web_engine_integration_logging_test.cc b/fuchsia_web/webengine/web_engine_integration_logging_test.cc
index b1d861f..0e75d27e 100644
--- a/fuchsia_web/webengine/web_engine_integration_logging_test.cc
+++ b/fuchsia_web/webengine/web_engine_integration_logging_test.cc
@@ -6,6 +6,7 @@
 
 #include <cstring>
 
+#include <optional>
 #include "base/containers/contains.h"
 #include "base/fuchsia/test_log_listener_safe.h"
 #include "base/strings/string_piece.h"
@@ -14,7 +15,6 @@
 #include "fuchsia_web/webengine/test/context_provider_for_test.h"
 #include "fuchsia_web/webengine/test/isolated_archivist.h"
 #include "fuchsia_web/webengine/web_engine_integration_test_base.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -67,7 +67,7 @@
   fidl::Client<fuchsia_logger::Log>& log() { return isolated_archivist_.log(); }
 
   IsolatedArchivist isolated_archivist_;
-  absl::optional<ContextProviderForTest> context_provider_;
+  std::optional<ContextProviderForTest> context_provider_;
 };
 
 // Verifies that calling messages from console.debug() calls go to the Fuchsia
@@ -91,7 +91,7 @@
   navigation_listener()->RunUntilTitleEquals("ended");
 
   // Run until the message passed to console.debug() is received.
-  absl::optional<fuchsia_logger::LogMessage> logged_message =
+  std::optional<fuchsia_logger::LogMessage> logged_message =
       log_listener.RunUntilMessageReceived(kLogTestPageDebugMessage);
 
   ASSERT_TRUE(logged_message.has_value());
diff --git a/fuchsia_web/webengine/web_engine_integration_test.cc b/fuchsia_web/webengine/web_engine_integration_test.cc
index ded1373..e4c2f8891 100644
--- a/fuchsia_web/webengine/web_engine_integration_test.cc
+++ b/fuchsia_web/webengine/web_engine_integration_test.cc
@@ -10,6 +10,7 @@
 
 #include <string>
 
+#include <optional>
 #include "base/containers/contains.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/fuchsia/mem_buffer_util.h"
@@ -29,7 +30,6 @@
 #include "media/fuchsia/camera/fake_fuchsia_camera.h"
 #include "net/http/http_request_headers.h"
 #include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -74,7 +74,7 @@
   void RunPermissionTest(bool grant);
 
  private:
-  absl::optional<ContextProviderForTest> context_provider_;
+  std::optional<ContextProviderForTest> context_provider_;
 };
 
 class WebEngineIntegrationUserAgentTest : public WebEngineIntegrationTest {
@@ -361,7 +361,7 @@
     binding_.AddBinding(this, std::move(request));
   }
 
-  const absl::optional<fuchsia::media::AudioRenderUsage>& usage() const {
+  const std::optional<fuchsia::media::AudioRenderUsage>& usage() const {
     return usage_;
   }
 
@@ -376,7 +376,7 @@
  private:
   fidl::BindingSet<fuchsia::media::AudioRenderer> binding_;
   base::OnceClosure on_set_usage_callback_;
-  absl::optional<fuchsia::media::AudioRenderUsage> usage_;
+  std::optional<fuchsia::media::AudioRenderUsage> usage_;
 };
 
 class FakeAudio : public fuchsia::media::testing::Audio_TestBase {
@@ -448,9 +448,8 @@
   }
 
   media::FakeAudioConsumerService fake_audio_consumer_service_;
-  absl::optional<media::FakeAudioDeviceEnumerator>
-      fake_audio_device_enumerator_;
-  absl::optional<FakeAudio> fake_audio_;
+  std::optional<media::FakeAudioDeviceEnumerator> fake_audio_device_enumerator_;
+  std::optional<FakeAudio> fake_audio_;
 
   size_t num_audio_connections_ = 0;
 };
diff --git a/fuchsia_web/webengine/web_engine_integration_test_base.cc b/fuchsia_web/webengine/web_engine_integration_test_base.cc
index 2af36c1..73af37df 100644
--- a/fuchsia_web/webengine/web_engine_integration_test_base.cc
+++ b/fuchsia_web/webengine/web_engine_integration_test_base.cc
@@ -172,19 +172,19 @@
 
 std::string WebEngineIntegrationTestBase::ExecuteJavaScriptWithStringResult(
     base::StringPiece script) {
-  absl::optional<base::Value> value = ExecuteJavaScript(frame_.get(), script);
+  std::optional<base::Value> value = ExecuteJavaScript(frame_.get(), script);
   return value ? value->GetString() : std::string();
 }
 
 double WebEngineIntegrationTestBase::ExecuteJavaScriptWithDoubleResult(
     base::StringPiece script) {
-  absl::optional<base::Value> value = ExecuteJavaScript(frame_.get(), script);
+  std::optional<base::Value> value = ExecuteJavaScript(frame_.get(), script);
   return value ? value->GetDouble() : 0.0;
 }
 
 bool WebEngineIntegrationTestBase::ExecuteJavaScriptWithBoolResult(
     base::StringPiece script) {
-  absl::optional<base::Value> value = ExecuteJavaScript(frame_.get(), script);
+  std::optional<base::Value> value = ExecuteJavaScript(frame_.get(), script);
   return value ? value->GetBool() : false;
 }
 
diff --git a/fuchsia_web/webengine/web_engine_main_delegate.cc b/fuchsia_web/webengine/web_engine_main_delegate.cc
index 2d6138f8..1b6f23be 100644
--- a/fuchsia_web/webengine/web_engine_main_delegate.cc
+++ b/fuchsia_web/webengine/web_engine_main_delegate.cc
@@ -73,7 +73,7 @@
 
 WebEngineMainDelegate::~WebEngineMainDelegate() = default;
 
-absl::optional<int> WebEngineMainDelegate::BasicStartupComplete() {
+std::optional<int> WebEngineMainDelegate::BasicStartupComplete() {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
 
   if (!InitLoggingFromCommandLine(*command_line)) {
@@ -94,7 +94,7 @@
           switches::kCorsExemptHeaders),
       ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY));
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 void WebEngineMainDelegate::PreSandboxStartup() {
diff --git a/fuchsia_web/webengine/web_engine_main_delegate.h b/fuchsia_web/webengine/web_engine_main_delegate.h
index 09af735..861c09e 100644
--- a/fuchsia_web/webengine/web_engine_main_delegate.h
+++ b/fuchsia_web/webengine/web_engine_main_delegate.h
@@ -10,9 +10,9 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "content/public/app/content_main_delegate.h"
 #include "fuchsia_web/webengine/web_engine_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace content {
 class ContentClient;
@@ -36,7 +36,7 @@
   }
 
   // ContentMainDelegate implementation.
-  absl::optional<int> BasicStartupComplete() override;
+  std::optional<int> BasicStartupComplete() override;
   void PreSandboxStartup() override;
   absl::variant<int, content::MainFunctionParams> RunProcess(
       const std::string& process_type,
diff --git a/gin/array_buffer.cc b/gin/array_buffer.cc
index 76610a36..5f3cfd8 100644
--- a/gin/array_buffer.cc
+++ b/gin/array_buffer.cc
@@ -151,7 +151,7 @@
 
 class ArrayBufferSharedMemoryMapper : public base::SharedMemoryMapper {
  public:
-  absl::optional<base::span<uint8_t>> Map(
+  std::optional<base::span<uint8_t>> Map(
       base::subtle::PlatformSharedMemoryHandle handle,
       bool write_allowed,
       uint64_t offset,
@@ -186,7 +186,7 @@
     uintptr_t mapping = v8::V8::GetSandboxAddressSpace()->AllocateSharedPages(
         0, mapping_size, permissions, v8_handle, offset);
     if (!mapping)
-      return absl::nullopt;
+      return std::nullopt;
 
     return base::make_span(reinterpret_cast<uint8_t*>(mapping), size);
   }
diff --git a/gin/v8_initializer.cc b/gin/v8_initializer.cc
index ff9655bf..14aae19 100644
--- a/gin/v8_initializer.cc
+++ b/gin/v8_initializer.cc
@@ -13,6 +13,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/allocator/partition_allocator/src/partition_alloc/page_allocator.h"
 #include "base/allocator/partition_allocator/src/partition_alloc/partition_address_space.h"
 #include "base/bits.h"
@@ -39,7 +40,6 @@
 #include "build/build_config.h"
 #include "gin/array_buffer.h"
 #include "gin/gin_features.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "tools/v8_context_snapshot/buildflags.h"
 #include "v8/include/v8-initialization.h"
 #include "v8/include/v8-snapshot.h"
@@ -60,7 +60,7 @@
 base::MemoryMappedFile* g_mapped_snapshot = nullptr;
 
 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
-absl::optional<gin::V8SnapshotFileType> g_snapshot_file_type;
+std::optional<gin::V8SnapshotFileType> g_snapshot_file_type;
 #endif
 
 bool GenerateEntropy(unsigned char* buffer, size_t amount) {
diff --git a/google_apis/calendar/calendar_api_response_types.cc b/google_apis/calendar/calendar_api_response_types.cc
index 94225d58..786f58b 100644
--- a/google_apis/calendar/calendar_api_response_types.cc
+++ b/google_apis/calendar/calendar_api_response_types.cc
@@ -10,6 +10,7 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/containers/fixed_flat_map.h"
 #include "base/json/json_value_converter.h"
 #include "base/ranges/algorithm.h"
@@ -20,7 +21,6 @@
 #include "base/values.h"
 #include "google_apis/common/parser_util.h"
 #include "google_apis/common/time_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace google_apis {
 
@@ -92,13 +92,13 @@
   return true;
 }
 
-// Returns user's self response status on the event, or `absl::nullopt` in case
+// Returns user's self response status on the event, or `std::nullopt` in case
 // the passed value is structurally different from expected.
-absl::optional<CalendarEvent::ResponseStatus> CalculateSelfResponseStatus(
+std::optional<CalendarEvent::ResponseStatus> CalculateSelfResponseStatus(
     const base::Value& value) {
   const auto* event = value.GetIfDict();
   if (!event)
-    return absl::nullopt;
+    return std::nullopt;
 
   const auto* attendees_raw_value = event->Find(kAttendees);
   if (!attendees_raw_value) {
@@ -125,12 +125,12 @@
 
   const auto* attendees = attendees_raw_value->GetIfList();
   if (!attendees)
-    return absl::nullopt;
+    return std::nullopt;
 
   for (const auto& x : *attendees) {
     const auto* attendee = x.GetIfDict();
     if (!attendee)
-      return absl::nullopt;
+      return std::nullopt;
 
     const bool is_self = attendee->FindBool(kAttendeesSelf).value_or(false);
     if (!is_self) {
@@ -143,7 +143,7 @@
 
     const auto* responseStatus = attendee->FindString(kAttendeesResponseStatus);
     if (!responseStatus)
-      return absl::nullopt;
+      return std::nullopt;
 
     const auto* it = kAttendeesResponseStatuses.find(*responseStatus);
     if (it != kAttendeesResponseStatuses.end()) {
diff --git a/google_apis/calendar/calendar_api_url_generator.cc b/google_apis/calendar/calendar_api_url_generator.cc
index 51af894c..20a78cb 100644
--- a/google_apis/calendar/calendar_api_url_generator.cc
+++ b/google_apis/calendar/calendar_api_url_generator.cc
@@ -4,10 +4,10 @@
 
 #include "google_apis/calendar/calendar_api_url_generator.h"
 
+#include <optional>
 #include "base/strings/string_number_conversions.h"
 #include "google_apis/common/time_util.h"
 #include "net/base/url_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace google_apis {
 
@@ -40,8 +40,8 @@
     const base::Time& start_time,
     const base::Time& end_time,
     bool single_events,
-    absl::optional<int> max_attendees,
-    absl::optional<int> max_results) const {
+    std::optional<int> max_attendees,
+    std::optional<int> max_results) const {
   GURL url = base_url_.Resolve(kCalendarV3EventsUrl);
   std::string start_time_string = util::FormatTimeAsString(start_time);
   std::string end_time_string = util::FormatTimeAsString(end_time);
diff --git a/google_apis/calendar/calendar_api_url_generator.h b/google_apis/calendar/calendar_api_url_generator.h
index 1372df5..70666f5 100644
--- a/google_apis/calendar/calendar_api_url_generator.h
+++ b/google_apis/calendar/calendar_api_url_generator.h
@@ -7,9 +7,9 @@
 
 #include <string>
 
+#include <optional>
 #include "base/time/time.h"
 #include "google_apis/gaia/gaia_urls.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace google_apis {
@@ -40,8 +40,8 @@
   GURL GetCalendarEventListUrl(const base::Time& start_time,
                                const base::Time& end_time,
                                bool single_events,
-                               absl::optional<int> max_attendees,
-                               absl::optional<int> max_results) const;
+                               std::optional<int> max_attendees,
+                               std::optional<int> max_results) const;
 
   // Returns a URL to fetch a map of calendar color id to color code.
   GURL GetCalendarColorListUrl() const;
diff --git a/google_apis/calendar/calendar_api_url_generator_unittest.cc b/google_apis/calendar/calendar_api_url_generator_unittest.cc
index d163ba3..0e1f3d7 100644
--- a/google_apis/calendar/calendar_api_url_generator_unittest.cc
+++ b/google_apis/calendar/calendar_api_url_generator_unittest.cc
@@ -52,8 +52,8 @@
       "&singleEvents=true",
       url_generator_
           .GetCalendarEventListUrl(start, end, /*single_events=*/true,
-                                   /*max_attendees=*/absl::nullopt,
-                                   /*max_results=*/absl::nullopt)
+                                   /*max_attendees=*/std::nullopt,
+                                   /*max_results=*/std::nullopt)
           .spec());
 }
 
diff --git a/google_apis/classroom/classroom_api_course_work_response_types.cc b/google_apis/classroom/classroom_api_course_work_response_types.cc
index da38542..27ec33c 100644
--- a/google_apis/classroom/classroom_api_course_work_response_types.cc
+++ b/google_apis/classroom/classroom_api_course_work_response_types.cc
@@ -7,13 +7,13 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/json/json_value_converter.h"
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "google_apis/common/parser_util.h"
 #include "google_apis/common/time_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace google_apis::classroom {
@@ -70,12 +70,12 @@
          base::Nanoseconds(nanos.value_or(0));
 }
 
-absl::optional<CourseWorkItem::DueDateTime> GetCourseWorkItemDueDateTime(
+std::optional<CourseWorkItem::DueDateTime> GetCourseWorkItemDueDateTime(
     const base::Value::Dict& raw_course_work_item) {
   const auto* const date =
       raw_course_work_item.FindDict(kApiResponseCourseWorkItemDueDateKey);
   if (!date) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   const auto year = date->FindInt(kDueDateYearComponent);
@@ -83,7 +83,7 @@
   const auto day = date->FindInt(kDueDateDayComponent);
 
   if (!year.has_value() && !month.has_value() && !day.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return CourseWorkItem::DueDateTime{
diff --git a/google_apis/classroom/classroom_api_course_work_response_types.h b/google_apis/classroom/classroom_api_course_work_response_types.h
index 5f15c2a..866d8a9b 100644
--- a/google_apis/classroom/classroom_api_course_work_response_types.h
+++ b/google_apis/classroom/classroom_api_course_work_response_types.h
@@ -9,8 +9,8 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/time/time.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace base {
@@ -68,7 +68,7 @@
   const std::string& title() const { return title_; }
   State state() const { return state_; }
   const GURL& alternate_link() const { return alternate_link_; }
-  const absl::optional<DueDateTime>& due_date_time() const {
+  const std::optional<DueDateTime>& due_date_time() const {
     return due_date_time_;
   }
   const base::Time& creation_time() const { return creation_time_; }
@@ -93,7 +93,7 @@
   // specifying zeroes in different date components (e.g. a month and day with
   // a zero year means a repeating annual assignment). That is why it was safer,
   // more flexible and forward compatible to use the same approach here.
-  absl::optional<DueDateTime> due_date_time_ = absl::nullopt;
+  std::optional<DueDateTime> due_date_time_ = std::nullopt;
 
   // The timestamp when this course work was created.
   base::Time creation_time_;
diff --git a/google_apis/classroom/classroom_api_student_submissions_response_types.cc b/google_apis/classroom/classroom_api_student_submissions_response_types.cc
index 69c0d316..57ed64d 100644
--- a/google_apis/classroom/classroom_api_student_submissions_response_types.cc
+++ b/google_apis/classroom/classroom_api_student_submissions_response_types.cc
@@ -43,13 +43,13 @@
 }
 
 bool ConvertAssignedGrade(const base::Value* input,
-                          absl::optional<double>* assigned_grade) {
+                          std::optional<double>* assigned_grade) {
   *assigned_grade = input->GetIfDouble();
   return true;
 }
 
 bool ConvertUpdateTime(base::StringPiece input,
-                       absl::optional<base::Time>* output) {
+                       std::optional<base::Time>* output) {
   base::Time update_time;
   if (!util::GetTimeFromString(input, &update_time)) {
     return false;
@@ -71,10 +71,10 @@
   converter->RegisterCustomField<StudentSubmission::State>(
       kApiResponseStudentSubmissionStateKey, &StudentSubmission::state_,
       &ConvertStudentSubmissionState);
-  converter->RegisterCustomValueField<absl::optional<double>>(
+  converter->RegisterCustomValueField<std::optional<double>>(
       kApiResponseStudentSubmissionAssignedGradeKey,
       &StudentSubmission::assigned_grade_, &ConvertAssignedGrade);
-  converter->RegisterCustomField<absl::optional<base::Time>>(
+  converter->RegisterCustomField<std::optional<base::Time>>(
       kApiResponseStudentSubmissionUpdateTimeKey,
       &StudentSubmission::last_update_, &ConvertUpdateTime);
 }
diff --git a/google_apis/classroom/classroom_api_student_submissions_response_types.h b/google_apis/classroom/classroom_api_student_submissions_response_types.h
index abadf7fa..0089bbb 100644
--- a/google_apis/classroom/classroom_api_student_submissions_response_types.h
+++ b/google_apis/classroom/classroom_api_student_submissions_response_types.h
@@ -9,8 +9,8 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/time/time.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 template <class StructType>
@@ -45,8 +45,8 @@
 
   const std::string& course_work_id() const { return course_work_id_; }
   const std::string& id() const { return id_; }
-  absl::optional<double> assigned_grade() const { return assigned_grade_; }
-  const absl::optional<base::Time>& last_update() const { return last_update_; }
+  std::optional<double> assigned_grade() const { return assigned_grade_; }
+  const std::optional<base::Time>& last_update() const { return last_update_; }
   State state() const { return state_; }
 
  private:
@@ -58,11 +58,11 @@
 
   // Optional grade. If unset, no grade was set. This value is a
   // non-negative decimal rounded to two decimal places.
-  absl::optional<double> assigned_grade_ = absl::nullopt;
+  std::optional<double> assigned_grade_ = std::nullopt;
 
   // The last update time of this submission. May be unset if student has not
   // accessed this item.
-  absl::optional<base::Time> last_update_ = absl::nullopt;
+  std::optional<base::Time> last_update_ = std::nullopt;
 
   // State of the student submission.
   State state_ = State::kOther;
diff --git a/google_apis/common/base_requests.cc b/google_apis/common/base_requests.cc
index 92b9219..de746d6 100644
--- a/google_apis/common/base_requests.cc
+++ b/google_apis/common/base_requests.cc
@@ -54,8 +54,7 @@
 
 namespace google_apis {
 
-absl::optional<std::string> MapJsonErrorToReason(
-    const std::string& error_body) {
+std::optional<std::string> MapJsonErrorToReason(const std::string& error_body) {
   DVLOG(1) << error_body;
   const char kErrorKey[] = "error";
   const char kErrorErrorsKey[] = "errors";
@@ -70,7 +69,7 @@
   if (error) {
     // Get error message and code.
     const std::string* message = error->FindString(kErrorMessageKey);
-    absl::optional<int> code = error->FindInt(kErrorCodeKey);
+    std::optional<int> code = error->FindInt(kErrorCodeKey);
     DLOG(ERROR) << "code: " << (code ? code.value() : OTHER_ERROR)
                 << ", message: " << (message ? *message : "");
 
@@ -85,7 +84,7 @@
       }
     }
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 std::unique_ptr<base::Value> ParseJson(const std::string& json) {
@@ -378,7 +377,7 @@
     }
     if (!download_data_->response_body.empty()) {
       if (!IsSuccessfulErrorCode(error_code_.value())) {
-        absl::optional<std::string> reason =
+        std::optional<std::string> reason =
             MapJsonErrorToReason(download_data_->response_body);
         if (reason.has_value())
           error_code_ = MapReasonToError(error_code_.value(), reason.value());
diff --git a/google_apis/common/base_requests.h b/google_apis/common/base_requests.h
index 51f7792..a05d97f 100644
--- a/google_apis/common/base_requests.h
+++ b/google_apis/common/base_requests.h
@@ -57,7 +57,7 @@
 std::unique_ptr<base::Value> ParseJson(const std::string& json);
 
 // Maps the error body to reason and logs the error code.
-absl::optional<std::string> MapJsonErrorToReason(const std::string& error_body);
+std::optional<std::string> MapJsonErrorToReason(const std::string& error_body);
 
 // Stringifies `HttpRequestMethod` enum value.
 std::string HttpRequestMethodToString(HttpRequestMethod method);
@@ -268,7 +268,7 @@
   int re_authenticate_count_;
   std::unique_ptr<network::SimpleURLLoader> url_loader_;
   raw_ptr<RequestSender> sender_;
-  absl::optional<ApiErrorCode> error_code_;
+  std::optional<ApiErrorCode> error_code_;
   const ProgressCallback upload_progress_callback_;
   const ProgressCallback download_progress_callback_;
   std::unique_ptr<DownloadData> download_data_;
diff --git a/google_apis/common/base_requests_unittest.cc b/google_apis/common/base_requests_unittest.cc
index e7aa530..ef3af81 100644
--- a/google_apis/common/base_requests_unittest.cc
+++ b/google_apis/common/base_requests_unittest.cc
@@ -160,7 +160,7 @@
   base::Value::Dict* root_dict = json->GetIfDict();
   ASSERT_TRUE(root_dict);
 
-  absl::optional<int> int_value = root_dict->FindInt("test");
+  std::optional<int> int_value = root_dict->FindInt("test");
   ASSERT_TRUE(int_value.has_value());
   EXPECT_EQ(123, *int_value);
 }
diff --git a/google_apis/drive/drive_base_requests.cc b/google_apis/drive/drive_base_requests.cc
index 865057b..e9a6822 100644
--- a/google_apis/drive/drive_base_requests.cc
+++ b/google_apis/drive/drive_base_requests.cc
@@ -531,7 +531,7 @@
                        weak_ptr_factory_.GetWeakPtr(), code,
                        std::move(notify_complete_callback)));
   } else {
-    absl::optional<std::string> reason = MapJsonErrorToReason(body);
+    std::optional<std::string> reason = MapJsonErrorToReason(body);
     NotifyError(reason.has_value() ? MapDriveReasonToError(code, reason.value())
                                    : code);
     std::move(notify_complete_callback).Run();
diff --git a/google_apis/gaia/fake_gaia.cc b/google_apis/gaia/fake_gaia.cc
index 0ea731f..28357902 100644
--- a/google_apis/gaia/fake_gaia.cc
+++ b/google_apis/gaia/fake_gaia.cc
@@ -817,7 +817,7 @@
                                   BasicHttpResponse* http_response) {
   GURL request_url = GURL("http://localhost").Resolve(request.relative_url);
 
-  absl::optional<GURL> redirect_url = GetSamlRedirectUrl(request_url);
+  std::optional<GURL> redirect_url = GetSamlRedirectUrl(request_url);
   if (!redirect_url) {
     http_response->set_code(net::HTTP_BAD_REQUEST);
     return;
@@ -951,7 +951,7 @@
   return response_with_iframe;
 }
 
-absl::optional<GURL> FakeGaia::GetSamlRedirectUrl(
+std::optional<GURL> FakeGaia::GetSamlRedirectUrl(
     const GURL& request_url) const {
   // When deciding on saml redirection, gaia is expected to prioritize sso
   // profile over the domain.
@@ -972,5 +972,5 @@
     return itr_domain->second;
   }
 
-  return absl::nullopt;
+  return std::nullopt;
 }
diff --git a/google_apis/gaia/fake_gaia.h b/google_apis/gaia/fake_gaia.h
index deb113a..f9cc6fd 100644
--- a/google_apis/gaia/fake_gaia.h
+++ b/google_apis/gaia/fake_gaia.h
@@ -9,11 +9,11 @@
 #include <set>
 #include <string>
 
+#include <optional>
 #include "base/containers/flat_map.h"
 #include "base/functional/callback.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
 #include "net/http/http_status_code.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace base {
@@ -339,7 +339,7 @@
 
   // Returns saml redirect based on given `request_url`. Returns empty object if
   // it fails to determine appropriate redirect url.
-  absl::optional<GURL> GetSamlRedirectUrl(const GURL& request_url) const;
+  std::optional<GURL> GetSamlRedirectUrl(const GURL& request_url) const;
 
   Configuration configuration_;
   EmailToGaiaIdMap email_to_gaia_id_map_;
diff --git a/google_apis/gaia/gaia_auth_fetcher.cc b/google_apis/gaia/gaia_auth_fetcher.cc
index 702edab..0a38ef9 100644
--- a/google_apis/gaia/gaia_auth_fetcher.cc
+++ b/google_apis/gaia/gaia_auth_fetcher.cc
@@ -8,6 +8,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
@@ -37,7 +38,6 @@
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -52,14 +52,14 @@
 
 std::unique_ptr<const GaiaAuthConsumer::ClientOAuthResult>
 ExtractOAuth2TokenPairResponse(const std::string& data) {
-  absl::optional<base::Value> value = base::JSONReader::Read(data);
+  std::optional<base::Value> value = base::JSONReader::Read(data);
   if (!value || !value->is_dict())
     return nullptr;
   base::Value::Dict& dict = value->GetDict();
 
   std::string* refresh_token = dict.FindString("refresh_token");
   std::string* access_token = dict.FindString("access_token");
-  absl::optional<int> expires_in_secs = dict.FindInt("expires_in");
+  std::optional<int> expires_in_secs = dict.FindInt("expires_in");
   if (!refresh_token || !access_token || !expires_in_secs.has_value())
     return nullptr;
 
@@ -95,7 +95,7 @@
   if (response_code == net::HTTP_INTERNAL_SERVER_ERROR)
     return GaiaAuthConsumer::TokenRevocationStatus::kServerError;
 
-  absl::optional<base::Value> value = base::JSONReader::Read(data);
+  std::optional<base::Value> value = base::JSONReader::Read(data);
   if (!value || !value->is_dict())
     return GaiaAuthConsumer::TokenRevocationStatus::kUnknownError;
   base::Value::Dict& dict = value->GetDict();
@@ -114,7 +114,7 @@
 
 base::Value::Dict ParseJSONDict(const std::string& data) {
   base::Value::Dict response_dict;
-  absl::optional<base::Value> message_value = base::JSONReader::Read(data);
+  std::optional<base::Value> message_value = base::JSONReader::Read(data);
   if (message_value && message_value->is_dict()) {
     response_dict.Merge(std::move(message_value->GetDict()));
   }
diff --git a/google_apis/gaia/gaia_auth_test_util.cc b/google_apis/gaia/gaia_auth_test_util.cc
index 08e764d..bcc0f76 100644
--- a/google_apis/gaia/gaia_auth_test_util.cc
+++ b/google_apis/gaia/gaia_auth_test_util.cc
@@ -9,9 +9,9 @@
 namespace gaia {
 
 std::string GenerateOAuth2MintTokenConsentResult(
-    absl::optional<bool> approved,
-    const absl::optional<std::string>& encrypted_approval_data,
-    const absl::optional<std::string>& obfuscated_id,
+    std::optional<bool> approved,
+    const std::optional<std::string>& encrypted_approval_data,
+    const std::optional<std::string>& obfuscated_id,
     base::Base64UrlEncodePolicy encode_policy) {
   OAuth2MintTokenConsentResult consent_result;
   if (approved.has_value())
diff --git a/google_apis/gaia/gaia_auth_test_util.h b/google_apis/gaia/gaia_auth_test_util.h
index 5904d3b9b..10a865f 100644
--- a/google_apis/gaia/gaia_auth_test_util.h
+++ b/google_apis/gaia/gaia_auth_test_util.h
@@ -5,17 +5,17 @@
 #ifndef GOOGLE_APIS_GAIA_GAIA_AUTH_TEST_UTIL_H_
 #define GOOGLE_APIS_GAIA_GAIA_AUTH_TEST_UTIL_H_
 
+#include <optional>
 #include "base/base64url.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #include <string>
 
 namespace gaia {
 
 std::string GenerateOAuth2MintTokenConsentResult(
-    absl::optional<bool> approved,
-    const absl::optional<std::string>& encrypted_approval_data,
-    const absl::optional<std::string>& obfuscated_id,
+    std::optional<bool> approved,
+    const std::optional<std::string>& encrypted_approval_data,
+    const std::optional<std::string>& obfuscated_id,
     base::Base64UrlEncodePolicy encode_policy =
         base::Base64UrlEncodePolicy::OMIT_PADDING);
 
diff --git a/google_apis/gaia/gaia_auth_util.cc b/google_apis/gaia/gaia_auth_util.cc
index ae6e2c464..ded245e 100644
--- a/google_apis/gaia/gaia_auth_util.cc
+++ b/google_apis/gaia/gaia_auth_util.cc
@@ -134,7 +134,7 @@
     signed_out_accounts->clear();
 
   // Parse returned data and make sure we have data.
-  absl::optional<base::Value> value = base::JSONReader::Read(data);
+  std::optional<base::Value> value = base::JSONReader::Read(data);
   if (!value)
     return false;
 
diff --git a/google_apis/gaia/gaia_auth_util_unittest.cc b/google_apis/gaia/gaia_auth_util_unittest.cc
index 890d858..57203ce 100644
--- a/google_apis/gaia/gaia_auth_util_unittest.cc
+++ b/google_apis/gaia/gaia_auth_util_unittest.cc
@@ -374,7 +374,7 @@
 TEST(GaiaAuthUtilTest, ParseConsentResultApprovedEmptyData) {
   const char kApprovedConsent[] = "CAEaDGZha2VfZ2FpYV9pZA";
   EXPECT_EQ(kApprovedConsent,
-            GenerateOAuth2MintTokenConsentResult(true, absl::nullopt, kGaiaId));
+            GenerateOAuth2MintTokenConsentResult(true, std::nullopt, kGaiaId));
   bool approved = false;
   std::string gaia_id;
   ASSERT_TRUE(
@@ -386,7 +386,7 @@
 TEST(GaiaAuthUtilTest, ParseConsentResultApprovedEmptyGaiaId) {
   const char kApprovedConsent[] = "CAESCUVOQ1JZUFRFRA";
   EXPECT_EQ(kApprovedConsent, GenerateOAuth2MintTokenConsentResult(
-                                  true, "ENCRYPTED", absl::nullopt));
+                                  true, "ENCRYPTED", std::nullopt));
   bool approved = false;
   std::string gaia_id;
   ASSERT_TRUE(
@@ -397,8 +397,8 @@
 
 TEST(GaiaAuthUtilTest, ParseConsentResultNotApproved) {
   const char kNoGrantConsent[] = "CAAaDGZha2VfZ2FpYV9pZA";
-  EXPECT_EQ(kNoGrantConsent, GenerateOAuth2MintTokenConsentResult(
-                                 false, absl::nullopt, kGaiaId));
+  EXPECT_EQ(kNoGrantConsent,
+            GenerateOAuth2MintTokenConsentResult(false, std::nullopt, kGaiaId));
   bool approved = false;
   std::string gaia_id;
   ASSERT_TRUE(
@@ -408,8 +408,8 @@
 }
 
 TEST(GaiaAuthUtilTest, ParseConsentResultEmpty) {
-  EXPECT_EQ("", GenerateOAuth2MintTokenConsentResult(
-                    absl::nullopt, absl::nullopt, absl::nullopt));
+  EXPECT_EQ("", GenerateOAuth2MintTokenConsentResult(std::nullopt, std::nullopt,
+                                                     std::nullopt));
   bool approved = false;
   std::string gaia_id;
   ASSERT_TRUE(ParseOAuth2MintTokenConsentResult("", &approved, &gaia_id));
@@ -423,7 +423,7 @@
   const char kApprovedConsentWithPadding[] = "CAE=";
   EXPECT_EQ(kApprovedConsentWithPadding,
             GenerateOAuth2MintTokenConsentResult(
-                true, absl::nullopt, absl::nullopt,
+                true, std::nullopt, std::nullopt,
                 base::Base64UrlEncodePolicy::INCLUDE_PADDING));
   bool approved = false;
   std::string gaia_id;
diff --git a/google_apis/gaia/gaia_config.cc b/google_apis/gaia/gaia_config.cc
index 64a14535..d5aacff 100644
--- a/google_apis/gaia/gaia_config.cc
+++ b/google_apis/gaia/gaia_config.cc
@@ -4,6 +4,7 @@
 
 #include "google_apis/gaia/gaia_config.h"
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/json/json_reader.h"
@@ -15,7 +16,6 @@
 #include "base/threading/thread_restrictions.h"
 #include "google_apis/gaia/gaia_switches.h"
 #include "google_apis/google_api_keys.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 // static
@@ -100,7 +100,7 @@
 // static
 std::unique_ptr<GaiaConfig> GaiaConfig::ReadConfigFromString(
     const std::string& config_contents) {
-  absl::optional<base::Value> dict = base::JSONReader::Read(config_contents);
+  std::optional<base::Value> dict = base::JSONReader::Read(config_contents);
   if (!dict || !dict->is_dict()) {
     LOG(FATAL) << "Couldn't parse Gaia config file";
     return nullptr;
diff --git a/google_apis/gaia/gaia_config_unittest.cc b/google_apis/gaia/gaia_config_unittest.cc
index 4939f59..785d1e9 100644
--- a/google_apis/gaia/gaia_config_unittest.cc
+++ b/google_apis/gaia/gaia_config_unittest.cc
@@ -4,12 +4,12 @@
 
 #include "google_apis/gaia/gaia_config.h"
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/json/json_reader.h"
 #include "google_apis/gaia/gaia_switches.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace {
@@ -30,8 +30,7 @@
 })";
 
 TEST(GaiaConfigTest, ShouldGetURLIfExists) {
-  absl::optional<base::Value> dict =
-      base::JSONReader::Read(kTestConfigContents);
+  std::optional<base::Value> dict = base::JSONReader::Read(kTestConfigContents);
   ASSERT_TRUE(dict.has_value());
 
   GaiaConfig config(std::move(dict->GetDict()));
@@ -41,8 +40,7 @@
 }
 
 TEST(GaiaConfigTest, ShouldReturnNullIfURLDoesNotExists) {
-  absl::optional<base::Value> dict =
-      base::JSONReader::Read(kTestConfigContents);
+  std::optional<base::Value> dict = base::JSONReader::Read(kTestConfigContents);
   ASSERT_TRUE(dict.has_value());
 
   GaiaConfig config(std::move(dict->GetDict()));
@@ -51,8 +49,7 @@
 }
 
 TEST(GaiaConfigTest, ShouldGetAPIKeyIfExists) {
-  absl::optional<base::Value> dict =
-      base::JSONReader::Read(kTestConfigContents);
+  std::optional<base::Value> dict = base::JSONReader::Read(kTestConfigContents);
   ASSERT_TRUE(dict.has_value());
 
   GaiaConfig config(std::move(dict->GetDict()));
@@ -62,8 +59,7 @@
 }
 
 TEST(GaiaConfigTest, ShouldReturnNullIfAPIKeyDoesNotExists) {
-  absl::optional<base::Value> dict =
-      base::JSONReader::Read(kTestConfigContents);
+  std::optional<base::Value> dict = base::JSONReader::Read(kTestConfigContents);
   ASSERT_TRUE(dict.has_value());
 
   GaiaConfig config(std::move(dict->GetDict()));
@@ -72,8 +68,7 @@
 }
 
 TEST(GaiaConfigTest, ShouldSerializeContentsToCommandLineSwitch) {
-  absl::optional<base::Value> dict =
-      base::JSONReader::Read(kTestConfigContents);
+  std::optional<base::Value> dict = base::JSONReader::Read(kTestConfigContents);
   ASSERT_TRUE(dict.has_value());
 
   GaiaConfig config(std::move(dict->GetDict()));
diff --git a/google_apis/gaia/gaia_oauth_client.cc b/google_apis/gaia/gaia_oauth_client.cc
index 0b595496..cb3e81e0 100644
--- a/google_apis/gaia/gaia_oauth_client.cc
+++ b/google_apis/gaia/gaia_oauth_client.cc
@@ -127,7 +127,7 @@
       std::string post_body /* may be empty if not needed*/,
       std::string authorization_header /* empty if not needed */,
       std::string http_method_override_header /* empty if not needed */,
-      absl::optional<net::RequestPriority> priority,
+      std::optional<net::RequestPriority> priority,
       int max_retries,
       GaiaOAuthClient::Delegate* delegate,
       const net::MutableNetworkTrafficAnnotationTag& traffic_annotation);
@@ -147,7 +147,7 @@
   net::BackoffEntry backoff_entry_;
 
   int num_retries_;
-  absl::optional<net::RequestPriority> priority_;
+  std::optional<net::RequestPriority> priority_;
   int max_retries_;
   GURL url_;
   net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
@@ -210,7 +210,7 @@
               GURL(GaiaUrls::GetInstance()->oauth2_token_url()), post_body,
               /* authorization_header = */ std::string(),
               /* http_method_override_header = */ std::string(),
-              /* priority = */ absl::nullopt, max_retries, delegate,
+              /* priority = */ std::nullopt, max_retries, delegate,
               traffic_annotation);
 }
 
@@ -265,7 +265,7 @@
               post_body,
               /* authorization_header = */ std::string(),
               /* http_method_override_header = */ std::string(),
-              /* priority = */ absl::nullopt, max_retries, delegate,
+              /* priority = */ std::nullopt, max_retries, delegate,
               traffic_annotation);
 }
 
@@ -323,7 +323,7 @@
   MakeRequest(type, GaiaUrls::GetInstance()->oauth_user_info_url(),
               /* post_body = */ std::string(), auth,
               /* http_method_override_header = */ std::string(),
-              /* priority = */ absl::nullopt, max_retries, delegate,
+              /* priority = */ std::nullopt, max_retries, delegate,
               traffic_annotation);
 }
 
@@ -370,7 +370,7 @@
               GURL(GaiaUrls::GetInstance()->oauth2_token_info_url()), post_body,
               /* authorization_header = */ std::string(),
               /* http_method_override_header = */ std::string(),
-              /* priority = */ absl::nullopt, max_retries, delegate,
+              /* priority = */ std::nullopt, max_retries, delegate,
               traffic_annotation);
 }
 
@@ -436,7 +436,7 @@
     std::string post_body,
     std::string authorization_header,
     std::string http_method_override_header,
-    absl::optional<net::RequestPriority> priority,
+    std::optional<net::RequestPriority> priority,
     int max_retries,
     GaiaOAuthClient::Delegate* delegate,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
@@ -541,7 +541,7 @@
     return;
   }
 
-  absl::optional<base::Value> message_value;
+  std::optional<base::Value> message_value;
   if (response_code == net::HTTP_OK && body) {
     std::string data = std::move(*body);
     message_value = base::JSONReader::Read(data);
@@ -605,7 +605,7 @@
         refresh_token = *dict_value;
       }
       int expires_in_seconds = 0;
-      if (const absl::optional<int> dict_value =
+      if (const std::optional<int> dict_value =
               response_dict.FindInt(kExpiresInValue)) {
         expires_in_seconds = *dict_value;
       }
diff --git a/google_apis/gaia/gaia_oauth_client_unittest.cc b/google_apis/gaia/gaia_oauth_client_unittest.cc
index 62f3c5fa..7677cc3 100644
--- a/google_apis/gaia/gaia_oauth_client_unittest.cc
+++ b/google_apis/gaia/gaia_oauth_client_unittest.cc
@@ -463,7 +463,7 @@
   auth.GetUserInfo("access_token", 1, &delegate);
   FlushNetwork();
 
-  absl::optional<base::Value> expected_value =
+  std::optional<base::Value> expected_value =
       base::JSONReader::Read(kDummyFullUserInfoResult);
   DCHECK(expected_value);
   ASSERT_TRUE(expected_value->is_dict());
diff --git a/google_apis/gaia/oauth2_access_token_fetcher_impl.cc b/google_apis/gaia/oauth2_access_token_fetcher_impl.cc
index f8d66cd4a..abba8e35c 100644
--- a/google_apis/gaia/oauth2_access_token_fetcher_impl.cc
+++ b/google_apis/gaia/oauth2_access_token_fetcher_impl.cc
@@ -244,7 +244,7 @@
                                      &error_subtype, &error_description);
   OAuth2Response response = OAuth2ResponseErrorToOAuth2Response(oauth2_error);
   RecordOAuth2Response(response);
-  absl::optional<GoogleServiceAuthError> error;
+  std::optional<GoogleServiceAuthError> error;
 
   switch (response) {
     case kOk:
@@ -396,7 +396,7 @@
   if (access_token)
     token_response->access_token = *access_token;
 
-  absl::optional<int> expires_in = dict->FindInt(kExpiresInKey);
+  std::optional<int> expires_in = dict->FindInt(kExpiresInKey);
   bool ok = access_token && expires_in.has_value();
   if (ok) {
     // The token will expire in |expires_in| seconds. Take a 10% error margin to
diff --git a/google_apis/gaia/oauth2_id_token_decoder.cc b/google_apis/gaia/oauth2_id_token_decoder.cc
index 008482a..c2111d2 100644
--- a/google_apis/gaia/oauth2_id_token_decoder.cc
+++ b/google_apis/gaia/oauth2_id_token_decoder.cc
@@ -6,13 +6,13 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/base64url.h"
 #include "base/containers/contains.h"
 #include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/strings/string_split.h"
 #include "base/values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -28,13 +28,13 @@
 
 // Decodes the JWT ID token to a dictionary. Returns whether the decoding was
 // successful.
-absl::optional<base::Value::Dict> DecodeIdToken(const std::string id_token) {
+std::optional<base::Value::Dict> DecodeIdToken(const std::string id_token) {
   const std::vector<base::StringPiece> token_pieces =
       base::SplitStringPiece(base::StringPiece(id_token), ".",
                              base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
   if (token_pieces.size() != 3) {
     VLOG(1) << "Invalid id_token: not in JWT format";
-    return absl::nullopt;
+    return std::nullopt;
   }
   // Only the payload is used. The header is ignored, and signature
   // verification is not needed since the token was obtained directly from LSO.
@@ -43,13 +43,13 @@
                              base::Base64UrlDecodePolicy::IGNORE_PADDING,
                              &payload)) {
     VLOG(1) << "Invalid id_token: not in Base64Url encoding";
-    return absl::nullopt;
+    return std::nullopt;
   }
-  absl::optional<base::Value> decoded_payload = base::JSONReader::Read(payload);
+  std::optional<base::Value> decoded_payload = base::JSONReader::Read(payload);
   if (!decoded_payload.has_value() ||
       decoded_payload->type() != base::Value::Type::DICT) {
     VLOG(1) << "Invalid id_token: paylod is not a well-formed JSON";
-    return absl::nullopt;
+    return std::nullopt;
   }
   return std::move(decoded_payload->GetDict());
 }
@@ -61,7 +61,7 @@
                      std::vector<std::string>* out_service_flags) {
   DCHECK(out_service_flags->empty());
 
-  absl::optional<base::Value::Dict> decoded_payload = DecodeIdToken(id_token);
+  std::optional<base::Value::Dict> decoded_payload = DecodeIdToken(id_token);
   if (!decoded_payload.has_value()) {
     VLOG(1) << "Failed to decode the id_token";
     return false;
diff --git a/google_apis/gaia/oauth2_mint_token_flow.cc b/google_apis/gaia/oauth2_mint_token_flow.cc
index 1c97493..7d3b0b0 100644
--- a/google_apis/gaia/oauth2_mint_token_flow.cc
+++ b/google_apis/gaia/oauth2_mint_token_flow.cc
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/containers/span.h"
 #include "base/functional/bind.h"
@@ -28,7 +29,6 @@
 #include "net/base/net_errors.h"
 #include "net/cookies/cookie_constants.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -80,7 +80,7 @@
   if (body)
     response_body = std::move(*body);
 
-  absl::optional<base::Value> value = base::JSONReader::Read(response_body);
+  std::optional<base::Value> value = base::JSONReader::Read(response_body);
   if (!value || !value->is_dict()) {
     int http_response_code = -1;
     if (head && head->headers)
@@ -296,7 +296,7 @@
   if (body)
     response_body = std::move(*body);
 
-  absl::optional<base::Value> value = base::JSONReader::Read(response_body);
+  std::optional<base::Value> value = base::JSONReader::Read(response_body);
   if (!value || !value->is_dict()) {
     RecordApiCallResult(OAuth2MintTokenApiCallResult::kParseJsonFailure);
     ReportFailure(GoogleServiceAuthError::FromUnexpectedServiceResponse(
@@ -452,8 +452,8 @@
       const std::string* path = cookie_dict->FindString("path");
       const std::string* max_age_seconds =
           cookie_dict->FindString("maxAgeSeconds");
-      absl::optional<bool> is_secure = cookie_dict->FindBool("isSecure");
-      absl::optional<bool> is_http_only = cookie_dict->FindBool("isHttpOnly");
+      std::optional<bool> is_secure = cookie_dict->FindBool("isSecure");
+      std::optional<bool> is_http_only = cookie_dict->FindBool("isHttpOnly");
       const std::string* same_site = cookie_dict->FindString("sameSite");
 
       int64_t max_age = -1;
@@ -474,7 +474,7 @@
               is_http_only ? *is_http_only : false,
               net::StringToCookieSameSite(same_site ? *same_site : ""),
               net::COOKIE_PRIORITY_DEFAULT, /* same_party */ false,
-              /* partition_key */ absl::nullopt);
+              /* partition_key */ std::nullopt);
       cookies.push_back(*cookie);
     }
   }
diff --git a/google_apis/gaia/oauth2_mint_token_flow_unittest.cc b/google_apis/gaia/oauth2_mint_token_flow_unittest.cc
index 7bb88d6..35b4673 100644
--- a/google_apis/gaia/oauth2_mint_token_flow_unittest.cc
+++ b/google_apis/gaia/oauth2_mint_token_flow_unittest.cc
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/json/json_reader.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
@@ -25,7 +26,6 @@
 #include "services/network/test/test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 using testing::_;
 using testing::ByRef;
@@ -119,13 +119,13 @@
           resolution_data.url, "test_name", "test_value", "test.com", "/",
           base::Time(), base::Time(), base::Time(), false, true,
           net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_DEFAULT, false,
-          absl::nullopt));
+          std::nullopt));
   resolution_data.cookies.push_back(
       *net::CanonicalCookie::CreateSanitizedCookie(
           resolution_data.url, "test_name2", "test_value2", "test.com", "/",
           base::Time(), base::Time(), base::Time(), false, false,
           net::CookieSameSite::UNSPECIFIED, net::COOKIE_PRIORITY_DEFAULT, false,
-          absl::nullopt));
+          std::nullopt));
   return resolution_data;
 }
 
diff --git a/google_apis/gaia/oauth_multilogin_result.cc b/google_apis/gaia/oauth_multilogin_result.cc
index 15f0e692..41c6694 100644
--- a/google_apis/gaia/oauth_multilogin_result.cc
+++ b/google_apis/gaia/oauth_multilogin_result.cc
@@ -6,13 +6,13 @@
 
 #include <algorithm>
 
+#include <optional>
 #include "base/compiler_specific.h"
 #include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -99,10 +99,10 @@
     const std::string* domain = cookie_dict.FindString("domain");
     const std::string* host = cookie_dict.FindString("host");
     const std::string* path = cookie_dict.FindString("path");
-    absl::optional<bool> is_secure = cookie_dict.FindBool("isSecure");
-    absl::optional<bool> is_http_only = cookie_dict.FindBool("isHttpOnly");
+    std::optional<bool> is_secure = cookie_dict.FindBool("isSecure");
+    std::optional<bool> is_http_only = cookie_dict.FindBool("isHttpOnly");
     const std::string* priority = cookie_dict.FindString("priority");
-    absl::optional<double> expiration_delta = cookie_dict.FindDouble("maxAge");
+    std::optional<double> expiration_delta = cookie_dict.FindDouble("maxAge");
     const std::string* same_site = cookie_dict.FindString("sameSite");
     const std::string* same_party = cookie_dict.FindString("sameParty");
 
@@ -138,7 +138,7 @@
             /*last_access=*/now, /*last_update=*/now, is_secure.value_or(true),
             is_http_only.value_or(true), samesite_mode,
             net::StringToCookiePriority(priority ? *priority : "medium"),
-            same_party_bool, /*partition_key=*/absl::nullopt,
+            same_party_bool, /*partition_key=*/std::nullopt,
             net::CookieSourceScheme::kUnset, url::PORT_UNSPECIFIED);
     // If the unique_ptr is null, it means the cookie was not canonical.
     // FromStorage() also uses a less strict version of IsCanonical(), we need
@@ -154,7 +154,7 @@
 OAuthMultiloginResult::OAuthMultiloginResult(const std::string& raw_data) {
   base::StringPiece data = StripXSSICharacters(raw_data);
   status_ = OAuthMultiloginResponseStatus::kUnknownStatus;
-  absl::optional<base::Value> json_data = base::JSONReader::Read(data);
+  std::optional<base::Value> json_data = base::JSONReader::Read(data);
   if (!json_data) {
     RecordMultiloginResponseStatus(status_);
     return;
diff --git a/google_apis/gcm/base/socket_stream_unittest.cc b/google_apis/gcm/base/socket_stream_unittest.cc
index eadd92a..2c37173 100644
--- a/google_apis/gcm/base/socket_stream_unittest.cc
+++ b/google_apis/gcm/base/socket_stream_unittest.cc
@@ -243,8 +243,8 @@
       mojo_socket_remote_.BindNewPipeAndPassReceiver(),
       mojo::NullRemote() /* observer */,
       base::BindLambdaForTesting(
-          [&](int result, const absl::optional<net::IPEndPoint>& local_addr,
-              const absl::optional<net::IPEndPoint>& peer_addr,
+          [&](int result, const std::optional<net::IPEndPoint>& local_addr,
+              const std::optional<net::IPEndPoint>& peer_addr,
               mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
               mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
             net_error = result;
diff --git a/google_apis/gcm/engine/connection_factory_impl.cc b/google_apis/gcm/engine/connection_factory_impl.cc
index a6404ee..b010f25 100644
--- a/google_apis/gcm/engine/connection_factory_impl.cc
+++ b/google_apis/gcm/engine/connection_factory_impl.cc
@@ -412,8 +412,8 @@
 
 void ConnectionFactoryImpl::OnConnectDone(
     int result,
-    const absl::optional<net::IPEndPoint>& local_addr,
-    const absl::optional<net::IPEndPoint>& peer_addr,
+    const std::optional<net::IPEndPoint>& local_addr,
+    const std::optional<net::IPEndPoint>& peer_addr,
     mojo::ScopedDataPipeConsumerHandle receive_stream,
     mojo::ScopedDataPipeProducerHandle send_stream) {
   DCHECK_NE(net::ERR_IO_PENDING, result);
diff --git a/google_apis/gcm/engine/connection_factory_impl.h b/google_apis/gcm/engine/connection_factory_impl.h
index dd45984..284aa3fdfd 100644
--- a/google_apis/gcm/engine/connection_factory_impl.h
+++ b/google_apis/gcm/engine/connection_factory_impl.h
@@ -96,8 +96,8 @@
 
   // Callback for Socket connection completion. This is public for testing.
   void OnConnectDone(int result,
-                     const absl::optional<net::IPEndPoint>& local_addr,
-                     const absl::optional<net::IPEndPoint>& peer_addr,
+                     const std::optional<net::IPEndPoint>& local_addr,
+                     const std::optional<net::IPEndPoint>& peer_addr,
                      mojo::ScopedDataPipeConsumerHandle receive_stream,
                      mojo::ScopedDataPipeProducerHandle send_stream);
 
diff --git a/google_apis/gcm/engine/connection_factory_impl_unittest.cc b/google_apis/gcm/engine/connection_factory_impl_unittest.cc
index dc9c35a..5081aa63 100644
--- a/google_apis/gcm/engine/connection_factory_impl_unittest.cc
+++ b/google_apis/gcm/engine/connection_factory_impl_unittest.cc
@@ -8,6 +8,7 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/memory/raw_ptr.h"
 #include "base/run_loop.h"
@@ -27,7 +28,6 @@
 #include "services/network/test/fake_test_cert_verifier_params_factory.h"
 #include "services/network/test/test_network_connection_tracker.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Policy;
 
diff --git a/google_apis/gcm/engine/connection_handler_impl_unittest.cc b/google_apis/gcm/engine/connection_handler_impl_unittest.cc
index 1c0dea2..25880b5 100644
--- a/google_apis/gcm/engine/connection_handler_impl_unittest.cc
+++ b/google_apis/gcm/engine/connection_handler_impl_unittest.cc
@@ -262,8 +262,8 @@
       mojo_socket_remote_.BindNewPipeAndPassReceiver(),
       mojo::NullRemote() /* observer */,
       base::BindLambdaForTesting(
-          [&](int result, const absl::optional<net::IPEndPoint>& local_addr,
-              const absl::optional<net::IPEndPoint>& peer_addr,
+          [&](int result, const std::optional<net::IPEndPoint>& local_addr,
+              const std::optional<net::IPEndPoint>& peer_addr,
               mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
               mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
             net_error = result;
diff --git a/google_apis/tasks/tasks_api_response_types.cc b/google_apis/tasks/tasks_api_response_types.cc
index 11338e7..a158c75 100644
--- a/google_apis/tasks/tasks_api_response_types.cc
+++ b/google_apis/tasks/tasks_api_response_types.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/json/json_value_converter.h"
 #include "base/logging.h"
 #include "base/time/time.h"
@@ -14,7 +15,6 @@
 #include "google_apis/common/parser_util.h"
 #include "google_apis/common/time_util.h"
 #include "google_apis/tasks/tasks_api_task_status.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace google_apis::tasks {
 namespace {
@@ -43,7 +43,7 @@
 }
 
 bool ConvertTaskDueDate(base::StringPiece input,
-                        absl::optional<base::Time>* output) {
+                        std::optional<base::Time>* output) {
   base::Time due;
   if (!util::GetTimeFromString(input, &due)) {
     return false;
@@ -120,7 +120,7 @@
       kApiResponseStatusKey, &Task::status_, &ConvertTaskStatus);
   converter->RegisterStringField(kApiResponseParentKey, &Task::parent_id_);
   converter->RegisterStringField(kApiResponsePositionKey, &Task::position_);
-  converter->RegisterCustomField<absl::optional<base::Time>>(
+  converter->RegisterCustomField<std::optional<base::Time>>(
       kApiResponseDueKey, &Task::due_, &ConvertTaskDueDate);
   converter->RegisterRepeatedMessage<TaskLink>(kApiResponseLinksKey,
                                                &Task::links_);
diff --git a/google_apis/tasks/tasks_api_response_types.h b/google_apis/tasks/tasks_api_response_types.h
index 8821b50..61f810c 100644
--- a/google_apis/tasks/tasks_api_response_types.h
+++ b/google_apis/tasks/tasks_api_response_types.h
@@ -9,9 +9,9 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/time/time.h"
 #include "google_apis/tasks/tasks_api_task_status.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 template <class StructType>
@@ -123,7 +123,7 @@
   TaskStatus status() const { return status_; }
   const std::string& parent_id() const { return parent_id_; }
   const std::string& position() const { return position_; }
-  const absl::optional<base::Time>& due() const { return due_; }
+  const std::optional<base::Time>& due() const { return due_; }
   const std::vector<std::unique_ptr<TaskLink>>& links() const { return links_; }
   const std::string& notes() const { return notes_; }
 
@@ -146,7 +146,7 @@
   // Due date of the task (comes as a RFC 3339 timestamp and converted to
   // `base::Time`). The due date only records date information. Not all tasks
   // have a due date.
-  absl::optional<base::Time> due_ = absl::nullopt;
+  std::optional<base::Time> due_ = std::nullopt;
 
   // Collection of links related to this task.
   std::vector<std::unique_ptr<TaskLink>> links_;
diff --git a/google_apis/tasks/tasks_api_url_generator_utils.cc b/google_apis/tasks/tasks_api_url_generator_utils.cc
index 37e7dbd..862bc9e 100644
--- a/google_apis/tasks/tasks_api_url_generator_utils.cc
+++ b/google_apis/tasks/tasks_api_url_generator_utils.cc
@@ -6,12 +6,12 @@
 
 #include <string>
 
+#include <optional>
 #include "base/check.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/base/url_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace google_apis::tasks {
@@ -40,7 +40,7 @@
 
 }  // namespace
 
-GURL GetListTaskListsUrl(absl::optional<int> max_results,
+GURL GetListTaskListsUrl(std::optional<int> max_results,
                          const std::string& page_token) {
   GURL url = GetBaseUrl().Resolve(kTaskListsListUrl);
   url = net::AppendOrReplaceQueryParameter(url, kFieldsParameterName,
@@ -59,7 +59,7 @@
 
 GURL GetListTasksUrl(const std::string& task_list_id,
                      bool include_completed,
-                     absl::optional<int> max_results,
+                     std::optional<int> max_results,
                      const std::string& page_token) {
   CHECK(!task_list_id.empty());
   GURL url = GetBaseUrl().Resolve(base::ReplaceStringPlaceholders(
diff --git a/google_apis/tasks/tasks_api_url_generator_utils.h b/google_apis/tasks/tasks_api_url_generator_utils.h
index cf75800b..f16ed74 100644
--- a/google_apis/tasks/tasks_api_url_generator_utils.h
+++ b/google_apis/tasks/tasks_api_url_generator_utils.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include <optional>
 
 class GURL;
 
@@ -15,11 +15,11 @@
 
 // Returns a URL to fetch all the authenticated user's task lists.
 // `max_results` - maximum number of task lists returned on one page.
-//                 Adds `maxResults` query parameter if not `absl::nullopt`.
+//                 Adds `maxResults` query parameter if not `std::nullopt`.
 // `page_token`  - token specifying the result page to return.
 //                 Adds `pageToken` query parameter if not empty.
 // https://developers.google.com/tasks/reference/rest/v1/tasklists/list
-GURL GetListTaskListsUrl(absl::optional<int> max_results,
+GURL GetListTaskListsUrl(std::optional<int> max_results,
                          const std::string& page_token);
 
 // Returns a URL to fetch all tasks in the specified task list.
@@ -27,13 +27,13 @@
 // `include_completed` - flag indicating whether completed tasks are returned
 //                       in the result.
 // `max_results`       - maximum number of tasks returned on one page. Adds
-//                       `maxResults` query parameter if not `absl::nullopt`.
+//                       `maxResults` query parameter if not `std::nullopt`.
 // `page_token`        - token specifying the result page to return. Adds
 //                       `pageToken` query parameter if not empty.
 // https://developers.google.com/tasks/reference/rest/v1/tasks/list
 GURL GetListTasksUrl(const std::string& task_list_id,
                      bool include_completed,
-                     absl::optional<int> max_results,
+                     std::optional<int> max_results,
                      const std::string& page_token);
 
 // Returns a URL to partially update the specified task.
diff --git a/google_apis/tasks/tasks_api_url_generator_utils_unittest.cc b/google_apis/tasks/tasks_api_url_generator_utils_unittest.cc
index 6d7e3b8..991f377 100644
--- a/google_apis/tasks/tasks_api_url_generator_utils_unittest.cc
+++ b/google_apis/tasks/tasks_api_url_generator_utils_unittest.cc
@@ -4,14 +4,14 @@
 
 #include "google_apis/tasks/tasks_api_url_generator_utils.h"
 
+#include <optional>
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace google_apis::tasks {
 
 TEST(TasksApiUrlGeneratorUtilsTest, ReturnsListTaskListsUrl) {
-  EXPECT_EQ(GetListTaskListsUrl(/*max_results=*/absl::nullopt,
+  EXPECT_EQ(GetListTaskListsUrl(/*max_results=*/std::nullopt,
                                 /*page_token=*/""),
             "https://tasks.googleapis.com/tasks/v1/users/@me/lists"
             "?fields=kind%2Citems(id%2Ctitle%2Cupdated)%2CnextPageToken");
@@ -28,7 +28,7 @@
 
 TEST(TasksApiUrlGeneratorUtilsTest, ReturnsListTasksUrl) {
   EXPECT_EQ(GetListTasksUrl("task-list-id", /*include_completed=*/false,
-                            /*max_results=*/absl::nullopt,
+                            /*max_results=*/std::nullopt,
                             /*page_token=*/""),
             "https://tasks.googleapis.com/tasks/v1/lists/task-list-id/tasks"
             "?fields=kind%2Citems(id%2Ctitle%2Cstatus%2Cparent%2Cposition"
diff --git a/gpu/command_buffer/client/client_transfer_cache.cc b/gpu/command_buffer/client/client_transfer_cache.cc
index fa3b59f..e45e08d0 100644
--- a/gpu/command_buffer/client/client_transfer_cache.cc
+++ b/gpu/command_buffer/client/client_transfer_cache.cc
@@ -16,7 +16,7 @@
   DCHECK(!transfer_buffer_ptr_);
   mapped_ptr_.emplace(size, client_->cmd_buffer_helper(), mapped_memory);
   if (!mapped_ptr_->valid()) {
-    mapped_ptr_ = absl::nullopt;
+    mapped_ptr_ = std::nullopt;
     return nullptr;
   }
   return mapped_ptr_->address();
@@ -30,7 +30,7 @@
   transfer_buffer_ptr_.emplace(size, client_->cmd_buffer_helper(),
                                transfer_buffer);
   if (!transfer_buffer_ptr_->valid()) {
-    transfer_buffer_ptr_ = absl::nullopt;
+    transfer_buffer_ptr_ = std::nullopt;
     return nullptr;
   }
   return transfer_buffer_ptr_->address();
@@ -44,8 +44,8 @@
   if (!handle.IsValid()) {
     // Release any data pointers. Keeping these alive longer can lead to issues
     // with transfer buffer reallocation.
-    mapped_ptr_ = absl::nullopt;
-    transfer_buffer_ptr_ = absl::nullopt;
+    mapped_ptr_ = std::nullopt;
+    transfer_buffer_ptr_ = std::nullopt;
     return;
   }
 
@@ -54,14 +54,14 @@
     client_->IssueCreateTransferCacheEntry(
         type, id, handle.shm_id(), handle.byte_offset(), mapped_ptr_->shm_id(),
         mapped_ptr_->offset(), mapped_ptr_->size());
-    mapped_ptr_ = absl::nullopt;
+    mapped_ptr_ = std::nullopt;
   } else {
     DCHECK(!mapped_ptr_);
     client_->IssueCreateTransferCacheEntry(
         type, id, handle.shm_id(), handle.byte_offset(),
         transfer_buffer_ptr_->shm_id(), transfer_buffer_ptr_->offset(),
         transfer_buffer_ptr_->size());
-    transfer_buffer_ptr_ = absl::nullopt;
+    transfer_buffer_ptr_ = std::nullopt;
   }
 }
 
diff --git a/gpu/command_buffer/client/client_transfer_cache.h b/gpu/command_buffer/client/client_transfer_cache.h
index d13297f..a03f273 100644
--- a/gpu/command_buffer/client/client_transfer_cache.h
+++ b/gpu/command_buffer/client/client_transfer_cache.h
@@ -7,6 +7,7 @@
 
 #include <map>
 
+#include <optional>
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "base/synchronization/lock.h"
@@ -15,7 +16,6 @@
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/mapped_memory.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace gpu {
 class MappedMemoryManager;
@@ -119,8 +119,8 @@
 
   const raw_ptr<Client> client_;  // not owned --- client_ outlives this
 
-  absl::optional<ScopedMappedMemoryPtr> mapped_ptr_;
-  absl::optional<ScopedTransferBufferPtr> transfer_buffer_ptr_;
+  std::optional<ScopedMappedMemoryPtr> mapped_ptr_;
+  std::optional<ScopedTransferBufferPtr> transfer_buffer_ptr_;
 
   // Access to other members must always be done with |lock_| held.
   base::Lock lock_;
diff --git a/gpu/command_buffer/client/gl_helper.cc b/gpu/command_buffer/client/gl_helper.cc
index 279a015..872b391 100644
--- a/gpu/command_buffer/client/gl_helper.cc
+++ b/gpu/command_buffer/client/gl_helper.cc
@@ -126,11 +126,11 @@
   const std::unique_ptr<GLHelper::ScalerInterface> v_planerizer_;
 
   // Intermediate texture, holding the scaler's output.
-  absl::optional<TextureHolder> intermediate_;
+  std::optional<TextureHolder> intermediate_;
 
   // Intermediate texture, holding the UV interim output (if the MRT shader
   // is being used).
-  absl::optional<ScopedTexture> uv_;
+  std::optional<ScopedTexture> uv_;
 };
 
 }  // namespace
@@ -696,7 +696,7 @@
     if (!intermediate_ || intermediate_->size() != scaler_output_size)
       intermediate_.emplace(gl_, scaler_output_size);
   } else {
-    intermediate_ = absl::nullopt;
+    intermediate_ = std::nullopt;
   }
 
   // Size the interim UV plane and the three output planes.
diff --git a/gpu/command_buffer/client/gl_helper_scaling.cc b/gpu/command_buffer/client/gl_helper_scaling.cc
index fc254d3..c4600b3 100644
--- a/gpu/command_buffer/client/gl_helper_scaling.cc
+++ b/gpu/command_buffer/client/gl_helper_scaling.cc
@@ -11,6 +11,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/containers/circular_deque.h"
 #include "base/functional/bind.h"
 #include "base/lazy_instance.h"
@@ -21,7 +22,6 @@
 #include "base/trace_event/trace_event.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/rect_f.h"
@@ -581,7 +581,7 @@
     gfx::Vector2d scale_to;
     GLenum readback_format;
   };
-  absl::optional<ChainProperties> chain_properties_;
+  std::optional<ChainProperties> chain_properties_;
 };
 
 // The important inputs for this function is |x_ops| and |y_ops|. They represent
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 750bfd0..326fc96 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -16,6 +16,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/compiler_specific.h"
 #include "base/containers/queue.h"
 #include "base/memory/raw_ptr.h"
@@ -39,7 +40,6 @@
 #include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/common/context_result.h"
 #include "gpu/command_buffer/common/debug_marker_manager.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace gpu {
 
@@ -814,8 +814,8 @@
   std::unique_ptr<BufferTracker> buffer_tracker_;
   std::unique_ptr<ReadbackBufferShadowTracker> readback_buffer_shadow_tracker_;
 
-  absl::optional<ScopedMappedMemoryPtr> font_mapped_buffer_;
-  absl::optional<ScopedTransferBufferPtr> raster_mapped_buffer_;
+  std::optional<ScopedMappedMemoryPtr> font_mapped_buffer_;
+  std::optional<ScopedTransferBufferPtr> raster_mapped_buffer_;
 
   base::RepeatingCallback<void(const char*, int32_t)> error_message_callback_;
   bool deferring_error_callbacks_ = false;
diff --git a/gpu/command_buffer/client/query_tracker.h b/gpu/command_buffer/client/query_tracker.h
index 4d5e74a8..719de63 100644
--- a/gpu/command_buffer/client/query_tracker.h
+++ b/gpu/command_buffer/client/query_tracker.h
@@ -14,6 +14,7 @@
 #include <memory>
 #include <unordered_map>
 
+#include <optional>
 #include "base/atomicops.h"
 #include "base/containers/circular_deque.h"
 #include "base/containers/flat_map.h"
@@ -21,7 +22,6 @@
 #include "base/memory/raw_ptr.h"
 #include "gles2_impl_export.h"
 #include "gpu/command_buffer/common/gles2_cmd_format.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace gpu {
 
@@ -201,7 +201,7 @@
     uint64_t client_begin_time_us_;  // Only used for latency query target.
     uint64_t result_;
 
-    absl::optional<base::OnceClosure> on_completed_callback_;
+    std::optional<base::OnceClosure> on_completed_callback_;
   };
 
   explicit QueryTracker(MappedMemoryManager* manager);
diff --git a/gpu/command_buffer/client/raster_implementation.cc b/gpu/command_buffer/client/raster_implementation.cc
index c206e05..357b50e4 100644
--- a/gpu/command_buffer/client/raster_implementation.cc
+++ b/gpu/command_buffer/client/raster_implementation.cc
@@ -150,8 +150,8 @@
   }
 
  private:
-  absl::optional<ScopedMappedMemoryPtr> scoped_mapped_ptr_;
-  absl::optional<ScopedTransferBufferPtr> scoped_transfer_ptr_;
+  std::optional<ScopedMappedMemoryPtr> scoped_mapped_ptr_;
+  std::optional<ScopedTransferBufferPtr> scoped_transfer_ptr_;
 };
 
 }  // namespace
@@ -1106,7 +1106,7 @@
   raster_mapped_buffer_.emplace(size, helper_, transfer_buffer_);
   if (!raster_mapped_buffer_->valid()) {
     SetGLError(GL_INVALID_OPERATION, "glMapRasterCHROMIUM", "size too big");
-    raster_mapped_buffer_ = absl::nullopt;
+    raster_mapped_buffer_ = std::nullopt;
     return nullptr;
   }
   *size_allocated = raster_mapped_buffer_->size();
@@ -1128,7 +1128,7 @@
   font_mapped_buffer_.emplace(size, helper_, mapped_memory_.get());
   if (!font_mapped_buffer_->valid()) {
     SetGLError(GL_INVALID_OPERATION, "glMapFontBufferCHROMIUM", "size too big");
-    font_mapped_buffer_ = absl::nullopt;
+    font_mapped_buffer_ = std::nullopt;
     return nullptr;
   }
   return font_mapped_buffer_->address();
@@ -1143,7 +1143,7 @@
   DCHECK(raster_mapped_buffer_->valid());
   if (total_written_size == 0) {
     raster_mapped_buffer_->Discard();
-    raster_mapped_buffer_ = absl::nullopt;
+    raster_mapped_buffer_ = std::nullopt;
     return;
   }
   raster_mapped_buffer_->Shrink(total_written_size);
@@ -1163,8 +1163,8 @@
         raster_written_size, font_shm_id, font_shm_offset, font_shm_size);
   }
 
-  raster_mapped_buffer_ = absl::nullopt;
-  font_mapped_buffer_ = absl::nullopt;
+  raster_mapped_buffer_ = std::nullopt;
+  font_mapped_buffer_ = std::nullopt;
   CheckGLError();
 }
 
diff --git a/gpu/command_buffer/client/raster_implementation.h b/gpu/command_buffer/client/raster_implementation.h
index 10890e9..810cfb8 100644
--- a/gpu/command_buffer/client/raster_implementation.h
+++ b/gpu/command_buffer/client/raster_implementation.h
@@ -13,6 +13,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/memory/raw_ptr.h"
 #include "base/trace_event/memory_dump_provider.h"
 #include "cc/paint/paint_cache.h"
@@ -31,7 +32,6 @@
 #include "gpu/command_buffer/common/id_allocator.h"
 #include "gpu/command_buffer/common/raster_cmd_format.h"
 #include "gpu/raster_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace cc {
 class TransferCacheSerializeHelper;
@@ -399,8 +399,8 @@
   // Used to check for single threaded access.
   int use_count_;
 
-  absl::optional<ScopedMappedMemoryPtr> font_mapped_buffer_;
-  absl::optional<ScopedTransferBufferPtr> raster_mapped_buffer_;
+  std::optional<ScopedMappedMemoryPtr> font_mapped_buffer_;
+  std::optional<ScopedTransferBufferPtr> raster_mapped_buffer_;
 
   base::RepeatingCallback<void(const char*, int32_t)> error_message_callback_;
 
@@ -431,7 +431,7 @@
     bool can_use_lcd_text = false;
     sk_sp<SkColorSpace> color_space;
   };
-  absl::optional<RasterProperties> raster_properties_;
+  std::optional<RasterProperties> raster_properties_;
 
   uint32_t max_inlined_entry_size_;
   ClientTransferCache transfer_cache_;
diff --git a/gpu/command_buffer/common/skia_utils.cc b/gpu/command_buffer/common/skia_utils.cc
index 99d368d..1b37f93d1 100644
--- a/gpu/command_buffer/common/skia_utils.cc
+++ b/gpu/command_buffer/common/skia_utils.cc
@@ -26,7 +26,7 @@
   // This should never outlive the provided ProcessMemoryDump, as it should
   // always be scoped to a single OnMemoryDump funciton call.
   SkiaGpuTraceMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
-                         absl::optional<uint64_t> share_group_tracing_guid)
+                         std::optional<uint64_t> share_group_tracing_guid)
       : pmd_(pmd),
         share_group_tracing_guid_(share_group_tracing_guid),
         tracing_process_id_(base::trace_event::MemoryDumpManager::GetInstance()
@@ -131,7 +131,7 @@
   }
 
   raw_ptr<base::trace_event::ProcessMemoryDump> pmd_;
-  absl::optional<uint64_t> share_group_tracing_guid_;
+  std::optional<uint64_t> share_group_tracing_guid_;
   uint64_t tracing_process_id_;
 };
 
@@ -139,7 +139,7 @@
 
 void DumpGrMemoryStatistics(const GrDirectContext* context,
                             base::trace_event::ProcessMemoryDump* pmd,
-                            absl::optional<uint64_t> tracing_guid) {
+                            std::optional<uint64_t> tracing_guid) {
   SkiaGpuTraceMemoryDump trace_memory_dump(pmd, tracing_guid);
   context->dumpMemoryStatistics(&trace_memory_dump);
 }
diff --git a/gpu/command_buffer/common/skia_utils.h b/gpu/command_buffer/common/skia_utils.h
index 04720d2..d9e106c 100644
--- a/gpu/command_buffer/common/skia_utils.h
+++ b/gpu/command_buffer/common/skia_utils.h
@@ -6,8 +6,8 @@
 #define GPU_COMMAND_BUFFER_COMMON_SKIA_UTILS_H_
 
 #include <cstdint>
+#include <optional>
 #include "gpu/raster_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class GrDirectContext;
 
@@ -25,7 +25,7 @@
 RASTER_EXPORT void DumpGrMemoryStatistics(
     const GrDirectContext* context,
     base::trace_event::ProcessMemoryDump* pmd,
-    absl::optional<uint64_t> tracing_guid);
+    std::optional<uint64_t> tracing_guid);
 
 // Dumps a single"skia/grpu_resources/context_0x{&context}" entry with total
 // cache usage. Designed for background dumps.
diff --git a/gpu/command_buffer/common/swap_buffers_complete_params.h b/gpu/command_buffer/common/swap_buffers_complete_params.h
index a14a3fc0e..59ee7523 100644
--- a/gpu/command_buffer/common/swap_buffers_complete_params.h
+++ b/gpu/command_buffer/common/swap_buffers_complete_params.h
@@ -7,9 +7,9 @@
 
 #include <vector>
 
+#include <optional>
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/gpu_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/ca_layer_params.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/swap_result.h"
@@ -29,7 +29,7 @@
   // Damage area of the current backing buffer compare to the previous swapped
   // buffer. The renderer can use it as hint for minimizing drawing area for the
   // next frame.
-  absl::optional<gfx::Rect> frame_buffer_damage_area;
+  std::optional<gfx::Rect> frame_buffer_damage_area;
 
   // The mailbox corresponding to the primary plane that was just swapped to
   // the front buffer. The overlay processor can use it to extract the buffer
diff --git a/gpu/command_buffer/service/context_state.cc b/gpu/command_buffer/service/context_state.cc
index 126e09d5..4a875af 100644
--- a/gpu/command_buffer/service/context_state.cc
+++ b/gpu/command_buffer/service/context_state.cc
@@ -9,13 +9,13 @@
 #include <algorithm>
 #include <cmath>
 
+#include <optional>
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "gpu/command_buffer/service/buffer_manager.h"
 #include "gpu/command_buffer/service/framebuffer_manager.h"
 #include "gpu/command_buffer/service/program_manager.h"
 #include "gpu/command_buffer/service/renderbuffer_manager.h"
 #include "gpu/command_buffer/service/transform_feedback_manager.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_version_info.h"
@@ -339,7 +339,7 @@
   if (const auto& cur_sampler = sampler_units[unit])
     cur_id = cur_sampler->service_id();
 
-  absl::optional<GLuint> prev_id;
+  std::optional<GLuint> prev_id;
   if (prev_state) {
     const auto& prev_sampler = prev_state->sampler_units[unit];
     prev_id.emplace(prev_sampler ? prev_sampler->service_id() : 0);
diff --git a/gpu/command_buffer/service/dawn_context_provider.cc b/gpu/command_buffer/service/dawn_context_provider.cc
index 6de2d30d..d652dbd 100644
--- a/gpu/command_buffer/service/dawn_context_provider.cc
+++ b/gpu/command_buffer/service/dawn_context_provider.cc
@@ -439,7 +439,7 @@
   return device_.HasFeature(feature);
 }
 
-absl::optional<error::ContextLostReason> DawnContextProvider::GetResetStatus()
+std::optional<error::ContextLostReason> DawnContextProvider::GetResetStatus()
     const {
   base::AutoLock auto_lock(context_lost_lock_);
   return context_lost_reason_;
diff --git a/gpu/command_buffer/service/dawn_context_provider.h b/gpu/command_buffer/service/dawn_context_provider.h
index 75380b7..2c37d59 100644
--- a/gpu/command_buffer/service/dawn_context_provider.h
+++ b/gpu/command_buffer/service/dawn_context_provider.h
@@ -9,6 +9,7 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/memory/raw_ptr.h"
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
@@ -18,7 +19,6 @@
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "gpu/config/gpu_preferences.h"
 #include "gpu/gpu_gles2_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/dawn/include/dawn/native/DawnNative.h"
 #include "third_party/skia/include/gpu/graphite/ContextOptions.h"
 #include "third_party/skia/include/gpu/graphite/dawn/DawnTypes.h"
@@ -87,7 +87,7 @@
 
   bool SupportsFeature(wgpu::FeatureName feature);
 
-  absl::optional<error::ContextLostReason> GetResetStatus() const;
+  std::optional<error::ContextLostReason> GetResetStatus() const;
 
   void OnError(WGPUErrorType error_type, const char* message);
 
@@ -110,7 +110,7 @@
   std::unique_ptr<skgpu::graphite::Context> graphite_context_;
 
   mutable base::Lock context_lost_lock_;
-  absl::optional<error::ContextLostReason> context_lost_reason_
+  std::optional<error::ContextLostReason> context_lost_reason_
       GUARDED_BY(context_lost_lock_);
 };
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index e29e6553..d1b38d3 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -19,6 +19,7 @@
 #include <unordered_map>
 #include <utility>
 
+#include <optional>
 #include "base/containers/contains.h"
 #include "base/containers/cxx20_erase.h"
 #include "base/containers/flat_set.h"
@@ -85,7 +86,6 @@
 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
 #include "gpu/config/gpu_finch_features.h"
 #include "gpu/config/gpu_preferences.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/buffer_types.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/geometry/point.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
index 3532ff0..51a3214 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -11,6 +11,7 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/containers/circular_deque.h"
 #include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
@@ -31,7 +32,6 @@
 #include "gpu/command_buffer/service/shared_context_state.h"
 #include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
 #include "gpu/command_buffer/service/texture_manager.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_fence.h"
@@ -143,7 +143,7 @@
     std::unique_ptr<GLTexturePassthroughImageRepresentation> representation_;
     std::unique_ptr<GLTexturePassthroughImageRepresentation::ScopedAccess>
         scoped_access_;
-    absl::optional<GLenum> access_mode_;
+    std::optional<GLenum> access_mode_;
   };
   // Mapping of client texture IDs to GLTexturePassthroughImageRepresentations.
   // TODO(ericrk): Remove this once TexturePassthrough holds a reference to
diff --git a/gpu/command_buffer/service/gles2_external_framebuffer.cc b/gpu/command_buffer/service/gles2_external_framebuffer.cc
index 063e8f6c..bef7411 100644
--- a/gpu/command_buffer/service/gles2_external_framebuffer.cc
+++ b/gpu/command_buffer/service/gles2_external_framebuffer.cc
@@ -428,7 +428,7 @@
   if (clear_flags) {
     gl::ScopedCapability scoped_scissor(GL_SCISSOR_TEST, GL_FALSE);
 
-    absl::optional<ScopedRestoreWindowRectangles> window_rectangles_restore;
+    std::optional<ScopedRestoreWindowRectangles> window_rectangles_restore;
     if (supports_window_rectangles_) {
       window_rectangles_restore.emplace(api);
       api->glWindowRectanglesEXTFn(GL_EXCLUSIVE_EXT, 0, nullptr);
@@ -513,7 +513,7 @@
       ScopedRestoreWriteMasks write_mask_restore(api);
       api->glColorMaskFn(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
-      absl::optional<ScopedRestoreWindowRectangles> window_rectangles_restore;
+      std::optional<ScopedRestoreWindowRectangles> window_rectangles_restore;
       if (supports_window_rectangles_) {
         window_rectangles_restore.emplace(api);
         api->glWindowRectanglesEXTFn(GL_EXCLUSIVE_EXT, 0, nullptr);
diff --git a/gpu/command_buffer/service/gr_cache_controller.cc b/gpu/command_buffer/service/gr_cache_controller.cc
index e45da1ae..cab1a1d 100644
--- a/gpu/command_buffer/service/gr_cache_controller.cc
+++ b/gpu/command_buffer/service/gr_cache_controller.cc
@@ -106,7 +106,7 @@
   // Force Skia to check fences to determine what can be freed.
   context_state_->gr_context()->checkAsyncWorkCompletion();
   {
-    absl::optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
+    std::optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
     // ScopedCacheUse is to avoid the empty/invalid client id DCHECKS caused
     // while accessing GrShaderCache. Note that since the actual client_id here
     // does not matter, we are using gpu::kDisplayCompositorClientId.
diff --git a/gpu/command_buffer/service/image_reader_gl_owner.h b/gpu/command_buffer/service/image_reader_gl_owner.h
index 0c20c3c6..9d87325 100644
--- a/gpu/command_buffer/service/image_reader_gl_owner.h
+++ b/gpu/command_buffer/service/image_reader_gl_owner.h
@@ -120,7 +120,7 @@
 
   // Most recently acquired image using image reader. This works like a cached
   // image until next new image is acquired which overwrites this.
-  absl::optional<ScopedCurrentImageRef> current_image_ref_ GUARDED_BY(lock_);
+  std::optional<ScopedCurrentImageRef> current_image_ref_ GUARDED_BY(lock_);
   std::unique_ptr<AImageReader_ImageListener> listener_;
 
   // A map consisting of pending refs on an AImage. If an image has any refs, it
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 011e435..e81aa8a5 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -364,7 +364,7 @@
   }
 
   const scoped_refptr<SharedContextState> shared_context_state_;
-  absl::optional<base::TimeTicks> begin_time_;
+  std::optional<base::TimeTicks> begin_time_;
   bool finished_ = false;
   base::WeakPtrFactory<RasterCommandsCompletedQuery> weak_ptr_factory_{this};
 };
@@ -3018,7 +3018,7 @@
 
   SkColor4f sk_color_4f = {r, g, b, a};
   if (shared_image_raster_) {
-    absl::optional<SkColor4f> clear_color;
+    std::optional<SkColor4f> clear_color;
     if (needs_clear)
       clear_color.emplace(sk_color_4f);
     scoped_shared_image_raster_write_ =
diff --git a/gpu/command_buffer/service/service_transfer_cache.cc b/gpu/command_buffer/service/service_transfer_cache.cc
index d70f20b..737dc31c 100644
--- a/gpu/command_buffer/service/service_transfer_cache.cc
+++ b/gpu/command_buffer/service/service_transfer_cache.cc
@@ -127,7 +127,7 @@
 }  // namespace
 
 ServiceTransferCache::CacheEntryInternal::CacheEntryInternal(
-    absl::optional<ServiceDiscardableHandle> handle,
+    std::optional<ServiceDiscardableHandle> handle,
     std::unique_ptr<cc::ServiceTransferCacheEntry> entry)
     : handle(handle), entry(std::move(entry)) {}
 
@@ -212,7 +212,7 @@
     total_image_size_ += entry->CachedSize();
   }
 
-  entries_.Put(key, CacheEntryInternal(absl::nullopt, std::move(entry)));
+  entries_.Put(key, CacheEntryInternal(std::nullopt, std::move(entry)));
   EnforceLimits();
 }
 
diff --git a/gpu/command_buffer/service/service_transfer_cache.h b/gpu/command_buffer/service/service_transfer_cache.h
index f185630..19159e48 100644
--- a/gpu/command_buffer/service/service_transfer_cache.h
+++ b/gpu/command_buffer/service/service_transfer_cache.h
@@ -108,12 +108,12 @@
 
  private:
   struct CacheEntryInternal {
-    CacheEntryInternal(absl::optional<ServiceDiscardableHandle> handle,
+    CacheEntryInternal(std::optional<ServiceDiscardableHandle> handle,
                        std::unique_ptr<cc::ServiceTransferCacheEntry> entry);
     CacheEntryInternal(CacheEntryInternal&& other);
     CacheEntryInternal& operator=(CacheEntryInternal&& other);
     ~CacheEntryInternal();
-    absl::optional<ServiceDiscardableHandle> handle;
+    std::optional<ServiceDiscardableHandle> handle;
     std::unique_ptr<cc::ServiceTransferCacheEntry> entry;
 
     // For metrics.
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc
index 338769f..758863b 100644
--- a/gpu/command_buffer/service/shared_context_state.cc
+++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -703,7 +703,7 @@
       base::trace_event::MemoryDumpLevelOfDetail::kBackground) {
     raster::DumpBackgroundGrMemoryStatistics(gr_context_, pmd);
   } else {
-    raster::DumpGrMemoryStatistics(gr_context_, pmd, absl::nullopt);
+    raster::DumpGrMemoryStatistics(gr_context_, pmd, std::nullopt);
   }
 
   return true;
@@ -743,7 +743,7 @@
       // With critical pressure, purge as much as possible.
       sk_surface_cache_.Clear();
       {
-        absl::optional<raster::GrShaderCache::ScopedCacheUse> cache_use;
+        std::optional<raster::GrShaderCache::ScopedCacheUse> cache_use;
         // ScopedCacheUse is to avoid the empty/invalid client id DCHECKS caused
         // while accessing GrShaderCache. Note that since the actual client_id
         // here does not matter, we are using gpu::kDisplayCompositorClientId.
@@ -804,7 +804,7 @@
 }
 
 void SharedContextState::UseShaderCache(
-    absl::optional<gpu::raster::GrShaderCache::ScopedCacheUse>& cache_use,
+    std::optional<gpu::raster::GrShaderCache::ScopedCacheUse>& cache_use,
     int32_t client_id) const {
   if (gr_shader_cache_) {
     cache_use.emplace(gr_shader_cache_, client_id);
@@ -902,7 +902,7 @@
   return nullptr;
 }
 
-absl::optional<error::ContextLostReason> SharedContextState::GetResetStatus(
+std::optional<error::ContextLostReason> SharedContextState::GetResetStatus(
     bool needs_gl) {
   DCHECK(!context_lost());
 
@@ -928,11 +928,11 @@
 
   // Not using GL.
   if (!GrContextIsGL() && !needs_gl)
-    return absl::nullopt;
+    return std::nullopt;
 
   // GL is not initialized.
   if (!context_state_)
-    return absl::nullopt;
+    return std::nullopt;
 
   GLenum error;
   while ((error = context_state_->api()->glGetErrorFn()) != GL_NO_ERROR) {
@@ -949,13 +949,13 @@
   base::Time now = base::Time::Now();
   if (!disable_check_reset_status_throttling_for_test_ &&
       now < last_gl_check_graphics_reset_status_ + kMinCheckDelay) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   last_gl_check_graphics_reset_status_ = now;
 
   GLenum driver_status = context()->CheckStickyGraphicsResetStatus();
   if (driver_status == GL_NO_ERROR)
-    return absl::nullopt;
+    return std::nullopt;
   LOG(ERROR) << "SharedContextState context lost via ARB/EXT_robustness. Reset "
                 "status = "
              << gles2::GLES2Util::GetStringEnum(driver_status);
@@ -971,7 +971,7 @@
       NOTREACHED();
       break;
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 bool SharedContextState::CheckResetStatus(bool need_gl) {
diff --git a/gpu/command_buffer/service/shared_context_state.h b/gpu/command_buffer/service/shared_context_state.h
index 7c21a810..680d2bd 100644
--- a/gpu/command_buffer/service/shared_context_state.h
+++ b/gpu/command_buffer/service/shared_context_state.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/containers/lru_cache.h"
 #include "base/memory/memory_pressure_listener.h"
 #include "base/memory/raw_ptr.h"
@@ -30,7 +31,6 @@
 #include "gpu/ipc/common/gpu_peak_memory.h"
 #include "gpu/vulkan/buildflags.h"
 #include "skia/buildflags.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkSurface.h"
 #include "third_party/skia/include/gpu/GrDirectContext.h"
 #include "ui/gl/progress_reporter.h"
@@ -137,7 +137,7 @@
   void StoreVkPipelineCacheIfNeeded();
 
   void UseShaderCache(
-      absl::optional<gpu::raster::GrShaderCache::ScopedCacheUse>& cache_use,
+      std::optional<gpu::raster::GrShaderCache::ScopedCacheUse>& cache_use,
       int32_t client_id) const;
 
   gl::GLShareGroup* share_group() const { return share_group_.get(); }
@@ -175,7 +175,7 @@
   gles2::FeatureInfo* feature_info() { return feature_info_.get(); }
   gles2::ContextState* context_state() const { return context_state_.get(); }
   bool context_lost() const { return !!context_lost_reason_; }
-  absl::optional<error::ContextLostReason> context_lost_reason() {
+  std::optional<error::ContextLostReason> context_lost_reason() {
     return context_lost_reason_;
   }
   bool need_context_state_reset() const { return need_context_state_reset_; }
@@ -330,7 +330,7 @@
   bool InitializeGraphite(const GpuPreferences& gpu_preferences,
                           const GpuDriverBugWorkarounds& workarounds);
 
-  absl::optional<error::ContextLostReason> GetResetStatus(bool needs_gl);
+  std::optional<error::ContextLostReason> GetResetStatus(bool needs_gl);
 
   // gpu::GLContextVirtualDelegate implementation.
   bool initialized() const override;
@@ -399,7 +399,7 @@
   // driver's GL state.
   bool need_context_state_reset_ = false;
 
-  absl::optional<error::ContextLostReason> context_lost_reason_;
+  std::optional<error::ContextLostReason> context_lost_reason_;
   base::ObserverList<ContextLostObserver>::Unchecked context_lost_observers_;
 
   base::LRUCache<void*, sk_sp<SkSurface>> sk_surface_cache_;
diff --git a/gpu/command_buffer/service/shared_image/android_video_image_backing.cc b/gpu/command_buffer/service/shared_image/android_video_image_backing.cc
index 830e1e8..a0ca401 100644
--- a/gpu/command_buffer/service/shared_image/android_video_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/android_video_image_backing.cc
@@ -67,16 +67,16 @@
 }
 
 // Static.
-absl::optional<VulkanYCbCrInfo> AndroidVideoImageBacking::GetYcbcrInfo(
+std::optional<VulkanYCbCrInfo> AndroidVideoImageBacking::GetYcbcrInfo(
     TextureOwner* texture_owner,
     viz::VulkanContextProvider* vulkan_context_provider) {
   if (!vulkan_context_provider)
-    return absl::nullopt;
+    return std::nullopt;
 
   // Get AHardwareBuffer from the latest frame.
   auto scoped_hardware_buffer = texture_owner->GetAHardwareBuffer();
   if (!scoped_hardware_buffer)
-    return absl::nullopt;
+    return std::nullopt;
 
   DCHECK(scoped_hardware_buffer->buffer());
   VulkanImplementation* vk_implementation =
@@ -88,9 +88,9 @@
   if (!vk_implementation->GetSamplerYcbcrConversionInfo(
           vk_device, scoped_hardware_buffer->TakeBuffer(), &ycbcr_info)) {
     LOG(ERROR) << "Failed to get the ycbcr info.";
-    return absl::nullopt;
+    return std::nullopt;
   }
-  return absl::optional<VulkanYCbCrInfo>(ycbcr_info);
+  return std::optional<VulkanYCbCrInfo>(ycbcr_info);
 }
 
 std::unique_ptr<AbstractTextureAndroid>
diff --git a/gpu/command_buffer/service/shared_image/android_video_image_backing.h b/gpu/command_buffer/service/shared_image/android_video_image_backing.h
index a27bde0..091cd66d 100644
--- a/gpu/command_buffer/service/shared_image/android_video_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/android_video_image_backing.h
@@ -7,10 +7,10 @@
 
 #include <memory>
 
+#include <optional>
 #include "gpu/command_buffer/service/shared_image/android_image_backing.h"
 #include "gpu/gpu_gles2_export.h"
 #include "gpu/ipc/common/vulkan_ycbcr_info.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace viz {
 class VulkanContextProvider;
@@ -41,7 +41,7 @@
 
   // Returns ycbcr information. This is only valid in vulkan context and
   // nullopt for other context.
-  static absl::optional<VulkanYCbCrInfo> GetYcbcrInfo(
+  static std::optional<VulkanYCbCrInfo> GetYcbcrInfo(
       TextureOwner* texture_owner,
       viz::VulkanContextProvider* vulkan_context_provider);
 
diff --git a/gpu/command_buffer/service/shared_image/compound_image_backing.cc b/gpu/command_buffer/service/shared_image/compound_image_backing.cc
index 87ba17c..92ccf5b9 100644
--- a/gpu/command_buffer/service/shared_image/compound_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/compound_image_backing.cc
@@ -329,7 +329,7 @@
     return wrapped_->EndReadAccess(std::move(release_fence));
   }
 #if BUILDFLAG(IS_WIN)
-  absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() final {
+  std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() final {
     return wrapped_->GetDCLayerOverlayImage();
   }
 #endif
@@ -495,7 +495,7 @@
     bool allow_shm_overlays,
     std::unique_ptr<SharedMemoryImageBacking> shm_backing,
     base::WeakPtr<SharedImageBackingFactory> gpu_backing_factory,
-    absl::optional<gfx::BufferUsage> buffer_usage)
+    std::optional<gfx::BufferUsage> buffer_usage)
     : SharedImageBacking(mailbox,
                          format,
                          size,
diff --git a/gpu/command_buffer/service/shared_image/compound_image_backing.h b/gpu/command_buffer/service/shared_image/compound_image_backing.h
index aba24e5..34ae8ff5 100644
--- a/gpu/command_buffer/service/shared_image/compound_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/compound_image_backing.h
@@ -185,7 +185,7 @@
       bool allow_shm_overlays,
       std::unique_ptr<SharedMemoryImageBacking> shm_backing,
       base::WeakPtr<SharedImageBackingFactory> gpu_backing_factory,
-      absl::optional<gfx::BufferUsage> buffer_usage = absl::nullopt);
+      std::optional<gfx::BufferUsage> buffer_usage = std::nullopt);
 
   base::trace_event::MemoryAllocatorDump* OnMemoryDump(
       const std::string& dump_name,
diff --git a/gpu/command_buffer/service/shared_image/compound_image_backing_unittest.cc b/gpu/command_buffer/service/shared_image/compound_image_backing_unittest.cc
index 2d30e88b..6c56db4 100644
--- a/gpu/command_buffer/service/shared_image/compound_image_backing_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/compound_image_backing_unittest.cc
@@ -353,7 +353,7 @@
   auto access = overlay_rep->BeginScopedReadAccess();
 
 #if BUILDFLAG(IS_WIN)
-  absl::optional<gl::DCLayerOverlayImage> overlay_image =
+  std::optional<gl::DCLayerOverlayImage> overlay_image =
       access->GetDCLayerOverlayImage();
   ASSERT_TRUE(overlay_image);
   EXPECT_EQ(overlay_image->type(), gl::DCLayerOverlayType::kNV12Pixmap);
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
index bbfb04de..27ca2ea 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
@@ -1054,13 +1054,13 @@
                                                          texture_d3d11_device_);
 }
 
-absl::optional<gl::DCLayerOverlayImage>
+std::optional<gl::DCLayerOverlayImage>
 D3DImageBacking::GetDCLayerOverlayImage() {
   if (swap_chain_) {
-    return absl::make_optional<gl::DCLayerOverlayImage>(size(), swap_chain_);
+    return std::make_optional<gl::DCLayerOverlayImage>(size(), swap_chain_);
   }
-  return absl::make_optional<gl::DCLayerOverlayImage>(size(), d3d11_texture_,
-                                                      array_slice_);
+  return std::make_optional<gl::DCLayerOverlayImage>(size(), d3d11_texture_,
+                                                     array_slice_);
 }
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing.h b/gpu/command_buffer/service/shared_image/d3d_image_backing.h
index 0ee2117..7503bda 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing.h
@@ -117,7 +117,7 @@
   void EndAccessDawn(const wgpu::Device& device, wgpu::Texture texture);
 #endif
 
-  absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage();
+  std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage();
 
   bool has_keyed_mutex() const {
     return dxgi_shared_handle_state_ &&
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.h b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.h
index 12eacf2e..ef7bef3 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.h
@@ -12,9 +12,9 @@
 
 #include <memory>
 
+#include <optional>
 #include "gpu/command_buffer/service/shared_image/shared_image_backing_factory.h"
 #include "gpu/gpu_gles2_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 namespace gfx {
@@ -153,8 +153,8 @@
   // D3D11 device used for creating textures. This is also Skia's D3D11 device.
   // Can be different from |angle_d3d11_device_| when using Graphite.
   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_;
-  absl::optional<bool> map_on_default_textures_;
-  absl::optional<bool> supports_bgra8unorm_storage_;
+  std::optional<bool> map_on_default_textures_;
+  std::optional<bool> supports_bgra8unorm_storage_;
 
   scoped_refptr<DXGISharedHandleManager> dxgi_shared_handle_manager_;
 
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory_unittest.cc
index 77a21e2..bf7cf01b 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory_unittest.cc
@@ -1902,7 +1902,7 @@
   auto scoped_read_access = overlay_representation->BeginScopedReadAccess();
   ASSERT_TRUE(scoped_read_access);
 
-  absl::optional<gl::DCLayerOverlayImage> overlay_image =
+  std::optional<gl::DCLayerOverlayImage> overlay_image =
       scoped_read_access->GetDCLayerOverlayImage();
   ASSERT_TRUE(overlay_image);
   EXPECT_EQ(overlay_image->type(), gl::DCLayerOverlayType::kNV12Texture);
@@ -2122,7 +2122,7 @@
     auto scoped_read_access = overlay_representation->BeginScopedReadAccess();
     ASSERT_TRUE(scoped_read_access);
 
-    absl::optional<gl::DCLayerOverlayImage> overlay_image =
+    std::optional<gl::DCLayerOverlayImage> overlay_image =
         scoped_read_access->GetDCLayerOverlayImage();
     ASSERT_TRUE(overlay_image);
     EXPECT_EQ(overlay_image->type(), gl::DCLayerOverlayType::kNV12Pixmap);
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_representation.cc b/gpu/command_buffer/service/shared_image/d3d_image_representation.cc
index a58044f1..66751d3 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_representation.cc
@@ -126,7 +126,7 @@
   static_cast<D3DImageBacking*>(backing())->EndAccessD3D11(d3d11_device_);
 }
 
-absl::optional<gl::DCLayerOverlayImage>
+std::optional<gl::DCLayerOverlayImage>
 OverlayD3DImageRepresentation::GetDCLayerOverlayImage() {
   return static_cast<D3DImageBacking*>(backing())->GetDCLayerOverlayImage();
 }
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_representation.h b/gpu/command_buffer/service/shared_image/d3d_image_representation.h
index 11377814d..ee570a8 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/d3d_image_representation.h
@@ -82,7 +82,7 @@
   bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) override;
   void EndReadAccess(gfx::GpuFenceHandle release_fence) override;
 
-  absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() override;
+  std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() override;
 
   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_;
 };
diff --git a/gpu/command_buffer/service/shared_image/dawn_fallback_image_representation.cc b/gpu/command_buffer/service/shared_image/dawn_fallback_image_representation.cc
index fc126b9..91b19ae 100644
--- a/gpu/command_buffer/service/shared_image/dawn_fallback_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/dawn_fallback_image_representation.cc
@@ -39,9 +39,8 @@
 
   const viz::SharedImageFormat format = this->format();
 
-  absl::optional<size_t> min_bytes_per_row(
-      format.MaybeEstimatedPlaneSizeInBytes(plane_index,
-                                            gfx::Size(size().width(), 1)));
+  std::optional<size_t> min_bytes_per_row(format.MaybeEstimatedPlaneSizeInBytes(
+      plane_index, gfx::Size(size().width(), 1)));
 
   if (!min_bytes_per_row.has_value()) {
     return false;
diff --git a/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory_unittest.cc
index d097a14b..2761dee 100644
--- a/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory_unittest.cc
@@ -672,7 +672,7 @@
   };
 
   gfx::Size window_size_;
-  absl::optional<SkColor4f> background_fill_override_;
+  std::optional<SkColor4f> background_fill_override_;
 
   TestPlatformDelegate platform_delegate_;
   ui::WinWindow window_;
diff --git a/gpu/command_buffer/service/shared_image/dcomp_surface_image_backing.h b/gpu/command_buffer/service/shared_image/dcomp_surface_image_backing.h
index 7763fd8..c90be4b0 100644
--- a/gpu/command_buffer/service/shared_image/dcomp_surface_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/dcomp_surface_image_backing.h
@@ -88,9 +88,9 @@
 
   // For DCompSurfaceOverlayImageRepresentation implementation.
   friend class DCompSurfaceOverlayImageRepresentation;
-  absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() {
-    return absl::make_optional<gl::DCLayerOverlayImage>(size(), dcomp_surface_,
-                                                        dcomp_surface_serial_);
+  std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() {
+    return std::make_optional<gl::DCLayerOverlayImage>(size(), dcomp_surface_,
+                                                       dcomp_surface_serial_);
   }
 
   Microsoft::WRL::ComPtr<ID3D11Texture2D> BeginDraw(
@@ -114,7 +114,7 @@
   void EndDrawDawn(const wgpu::Device& device, wgpu::Texture texture);
 
   // Used to restore the surface that was current before BeginDraw at EndDraw.
-  absl::optional<ui::ScopedMakeCurrent> scoped_make_current_;
+  std::optional<ui::ScopedMakeCurrent> scoped_make_current_;
 
   // GLSurface that binds |dcomp_surface_|'s draw texture to GL FB0 between
   // |BeginDrawGanesh| and |EndDrawGanesh|.
diff --git a/gpu/command_buffer/service/shared_image/dcomp_surface_image_representation.cc b/gpu/command_buffer/service/shared_image/dcomp_surface_image_representation.cc
index fc28e4a8..a9b2007a 100644
--- a/gpu/command_buffer/service/shared_image/dcomp_surface_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/dcomp_surface_image_representation.cc
@@ -27,7 +27,7 @@
 DCompSurfaceOverlayImageRepresentation::
     ~DCompSurfaceOverlayImageRepresentation() = default;
 
-absl::optional<gl::DCLayerOverlayImage>
+std::optional<gl::DCLayerOverlayImage>
 DCompSurfaceOverlayImageRepresentation::GetDCLayerOverlayImage() {
   return static_cast<DCompSurfaceImageBacking*>(backing())
       ->GetDCLayerOverlayImage();
diff --git a/gpu/command_buffer/service/shared_image/dcomp_surface_image_representation.h b/gpu/command_buffer/service/shared_image/dcomp_surface_image_representation.h
index ce17310d..e5876cf 100644
--- a/gpu/command_buffer/service/shared_image/dcomp_surface_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/dcomp_surface_image_representation.h
@@ -19,7 +19,7 @@
   ~DCompSurfaceOverlayImageRepresentation() override;
 
  protected:
-  absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() override;
+  std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() override;
 
  private:
   bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) override;
diff --git a/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.cc b/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.cc
index b25c575..1a456fe 100644
--- a/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.cc
@@ -197,7 +197,7 @@
 
   gfx::Rect pending_swap_rect = swap_rect;
 
-  absl::optional<SkColor4f> initialize_color;
+  std::optional<SkColor4f> initialize_color;
 
   // SharedImage allows an incomplete first draw so long as we only read from
   // the part that we've previously drawn to. However, IDXGISwapChain requires a
diff --git a/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.h b/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.h
index 26de401..41c10c8 100644
--- a/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.h
@@ -84,9 +84,9 @@
 
   friend class DXGISwapChainOverlayImageRepresentation;
   bool Present(bool should_synchronize_present_with_vblank);
-  absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() {
-    return absl::make_optional<gl::DCLayerOverlayImage>(size(),
-                                                        dxgi_swap_chain_);
+  std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() {
+    return std::make_optional<gl::DCLayerOverlayImage>(size(),
+                                                       dxgi_swap_chain_);
   }
 
   friend class SkiaGLImageRepresentationDXGISwapChain;
@@ -99,7 +99,7 @@
                                 const gfx::Rect& update_rect);
   void EndAccessDawn(const wgpu::Device& device, wgpu::Texture texture);
 
-  absl::optional<gfx::Rect> pending_swap_rect_;
+  std::optional<gfx::Rect> pending_swap_rect_;
 
   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_;
   Microsoft::WRL::ComPtr<IDXGISwapChain1> dxgi_swap_chain_;
diff --git a/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_representation.cc b/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_representation.cc
index 47956aa2..1086001 100644
--- a/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_representation.cc
@@ -29,7 +29,7 @@
 DXGISwapChainOverlayImageRepresentation::
     ~DXGISwapChainOverlayImageRepresentation() = default;
 
-absl::optional<gl::DCLayerOverlayImage>
+std::optional<gl::DCLayerOverlayImage>
 DXGISwapChainOverlayImageRepresentation::GetDCLayerOverlayImage() {
   return static_cast<DXGISwapChainImageBacking*>(backing())
       ->GetDCLayerOverlayImage();
diff --git a/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_representation.h b/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_representation.h
index 94617ce..6327209d 100644
--- a/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_representation.h
@@ -24,7 +24,7 @@
   ~DXGISwapChainOverlayImageRepresentation() override;
 
  protected:
-  absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() override;
+  std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() override;
 
  private:
   bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) override;
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
index 7879b67..a8f2ea5 100644
--- a/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <thread>
 
+#include <optional>
 #include "base/bits.h"
 #include "base/functional/callback_helpers.h"
 #include "base/memory/raw_ptr.h"
@@ -32,7 +33,6 @@
 #include "gpu/config/gpu_test_config.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/gpu/GrBackendSemaphore.h"
 #include "third_party/skia/include/gpu/GrBackendSurface.h"
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc b/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc
index 89ee0d3..9447f31 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc
@@ -267,7 +267,7 @@
     GrSurfaceOrigin surface_origin,
     SkAlphaType alpha_type,
     uint32_t usage,
-    absl::optional<gfx::BufferUsage> buffer_usage) {
+    std::optional<gfx::BufferUsage> buffer_usage) {
   if (!gpu::IsImageSizeValidForGpuMemoryBufferFormat(size,
                                                      ToBufferFormat(format))) {
     DLOG(ERROR) << "Invalid image size for format.";
@@ -368,7 +368,7 @@
     VulkanCommandPool* command_pool,
     bool use_separate_gl_texture,
     gfx::GpuMemoryBufferHandle handle,
-    absl::optional<gfx::BufferUsage> buffer_usage)
+    std::optional<gfx::BufferUsage> buffer_usage)
     : ClearTrackingSharedImageBacking(mailbox,
                                       format,
                                       size,
@@ -754,7 +754,7 @@
   auto& gl_texture = gl_textures_.emplace_back(plane_format, plane_size,
                                                is_passthrough, nullptr);
 
-  absl::optional<ScopedDedicatedMemoryObject> memory_object;
+  std::optional<ScopedDedicatedMemoryObject> memory_object;
   if (!use_separate_gl_texture()) {
     GrVkImageInfo image_info = vk_texture.GetGrVkImageInfo();
 
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_backing.h b/gpu/command_buffer/service/shared_image/external_vk_image_backing.h
index 549fb86..a282356 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_backing.h
@@ -58,7 +58,7 @@
       GrSurfaceOrigin surface_origin,
       SkAlphaType alpha_type,
       uint32_t usage,
-      absl::optional<gfx::BufferUsage> buffer_usage = absl::nullopt);
+      std::optional<gfx::BufferUsage> buffer_usage = std::nullopt);
 
   static std::unique_ptr<ExternalVkImageBacking> CreateWithPixmap(
       scoped_refptr<SharedContextState> context_state,
@@ -88,7 +88,7 @@
       VulkanCommandPool* command_pool,
       bool use_separate_gl_texture,
       gfx::GpuMemoryBufferHandle handle = gfx::GpuMemoryBufferHandle(),
-      absl::optional<gfx::BufferUsage> buffer_usage = absl::nullopt);
+      std::optional<gfx::BufferUsage> buffer_usage = std::nullopt);
 
   ExternalVkImageBacking(const ExternalVkImageBacking&) = delete;
   ExternalVkImageBacking& operator=(const ExternalVkImageBacking&) = delete;
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing.h b/gpu/command_buffer/service/shared_image/iosurface_image_backing.h
index 466b769..419a6e38 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing.h
@@ -252,7 +252,7 @@
       bool framebuffer_attachment_angle,
       bool is_cleared,
       bool retain_gl_texture,
-      absl::optional<gfx::BufferUsage> buffer_usage = absl::nullopt);
+      std::optional<gfx::BufferUsage> buffer_usage = std::nullopt);
   IOSurfaceImageBacking(const IOSurfaceImageBacking& other) = delete;
   IOSurfaceImageBacking& operator=(const IOSurfaceImageBacking& other) = delete;
   ~IOSurfaceImageBacking() override;
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm b/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
index e616904..c625ce3 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
@@ -721,7 +721,7 @@
     bool framebuffer_attachment_angle,
     bool is_cleared,
     bool retain_gl_texture,
-    absl::optional<gfx::BufferUsage> buffer_usage)
+    std::optional<gfx::BufferUsage> buffer_usage)
     : SharedImageBacking(mailbox,
                          format,
                          size,
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h
index 6575101..6ab0975 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h
@@ -128,7 +128,7 @@
       uint32_t io_surface_plane,
       gfx::BufferPlane buffer_plane,
       bool is_plane_format,
-      absl::optional<gfx::BufferUsage> buffer_usage = absl::nullopt);
+      std::optional<gfx::BufferUsage> buffer_usage = std::nullopt);
 
   const GrContextType gr_context_type_;
   const int32_t max_texture_size_;
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
index f07a34e0..0547883 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
@@ -4,6 +4,7 @@
 
 #include "gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h"
 
+#include <optional>
 #include "base/memory/scoped_refptr.h"
 #include "build/build_config.h"
 #include "components/viz/common/resources/resource_sizes.h"
@@ -18,7 +19,6 @@
 #include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
 #include "gpu/command_buffer/service/skia_utils.h"
 #include "gpu/command_buffer/service/texture_manager.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/gpu_memory_buffer.h"
 #include "ui/gfx/mac/io_surface.h"
@@ -413,7 +413,7 @@
     uint32_t io_surface_plane,
     gfx::BufferPlane buffer_plane,
     bool is_plane_format,
-    absl::optional<gfx::BufferUsage> buffer_usage) {
+    std::optional<gfx::BufferUsage> buffer_usage) {
   if (handle.type != gfx::IO_SURFACE_BUFFER || !handle.io_surface) {
     LOG(ERROR) << "Invalid IOSurface GpuMemoryBufferHandle.";
     return nullptr;
diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing.cc b/gpu/command_buffer/service/shared_image/ozone_image_backing.cc
index e82c9f5..e83a1d12 100644
--- a/gpu/command_buffer/service/shared_image/ozone_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/ozone_image_backing.cc
@@ -386,7 +386,7 @@
     scoped_refptr<gfx::NativePixmap> pixmap,
     const GpuDriverBugWorkarounds& workarounds,
     bool use_passthrough,
-    absl::optional<gfx::BufferUsage> buffer_usage)
+    std::optional<gfx::BufferUsage> buffer_usage)
     : ClearTrackingSharedImageBacking(mailbox,
                                       format,
                                       size,
diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing.h b/gpu/command_buffer/service/shared_image/ozone_image_backing.h
index 73b481b..32b4544 100644
--- a/gpu/command_buffer/service/shared_image/ozone_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/ozone_image_backing.h
@@ -52,7 +52,7 @@
       scoped_refptr<gfx::NativePixmap> pixmap,
       const GpuDriverBugWorkarounds& workarounds,
       bool use_passthrough,
-      absl::optional<gfx::BufferUsage> buffer_usage = absl::nullopt);
+      std::optional<gfx::BufferUsage> buffer_usage = std::nullopt);
 
   OzoneImageBacking(const OzoneImageBacking&) = delete;
   OzoneImageBacking& operator=(const OzoneImageBacking&) = delete;
diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc
index 17f7b99a..9e611db3 100644
--- a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc
@@ -91,7 +91,7 @@
     GrSurfaceOrigin surface_origin,
     SkAlphaType alpha_type,
     uint32_t usage,
-    absl::optional<gfx::BufferUsage> buffer_usage) {
+    std::optional<gfx::BufferUsage> buffer_usage) {
   gfx::BufferFormat buffer_format = ToBufferFormat(format);
   VulkanDeviceQueue* device_queue = nullptr;
 #if BUILDFLAG(ENABLE_VULKAN)
diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.h b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.h
index cb2f8f0..48da266 100644
--- a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.h
@@ -5,6 +5,7 @@
 #ifndef GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_OZONE_IMAGE_BACKING_FACTORY_H_
 #define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_OZONE_IMAGE_BACKING_FACTORY_H_
 
+#include <optional>
 #include "base/memory/raw_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_refptr.h"
@@ -13,7 +14,6 @@
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "gpu/config/gpu_preferences.h"
 #include "gpu/gpu_gles2_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace gpu {
 class SharedContextState;
@@ -119,7 +119,7 @@
       GrSurfaceOrigin surface_origin,
       SkAlphaType alpha_type,
       uint32_t usage,
-      absl::optional<gfx::BufferUsage> buffer_usage = absl::nullopt);
+      std::optional<gfx::BufferUsage> buffer_usage = std::nullopt);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/raw_draw_image_backing.cc b/gpu/command_buffer/service/shared_image/raw_draw_image_backing.cc
index 6550806..ec7ec89 100644
--- a/gpu/command_buffer/service/shared_image/raw_draw_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/raw_draw_image_backing.cc
@@ -35,7 +35,7 @@
       scoped_refptr<SharedContextState> context_state,
       int final_msaa_count,
       const SkSurfaceProps& surface_props,
-      const absl::optional<SkColor4f>& clear_color,
+      const std::optional<SkColor4f>& clear_color,
       bool visible) override {
     return raw_draw_backing()->BeginRasterWriteAccess(
         std::move(context_state), final_msaa_count, surface_props, clear_color,
@@ -47,7 +47,7 @@
   }
 
   cc::PaintOpBuffer* BeginReadAccess(
-      absl::optional<SkColor4f>& clear_color) override {
+      std::optional<SkColor4f>& clear_color) override {
     return raw_draw_backing()->BeginRasterReadAccess(clear_color);
   }
 
@@ -252,7 +252,7 @@
     scoped_refptr<SharedContextState> context_state,
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
-    const absl::optional<SkColor4f>& clear_color,
+    const std::optional<SkColor4f>& clear_color,
     bool visible) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   AutoLock auto_lock(this);
@@ -317,7 +317,7 @@
 }
 
 cc::PaintOpBuffer* RawDrawImageBacking::BeginRasterReadAccess(
-    absl::optional<SkColor4f>& clear_color) {
+    std::optional<SkColor4f>& clear_color) {
   // paint ops will be read on compositor thread, so do not check thread with
   // DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   AutoLock auto_lock(this);
diff --git a/gpu/command_buffer/service/shared_image/raw_draw_image_backing.h b/gpu/command_buffer/service/shared_image/raw_draw_image_backing.h
index 0196e70..25e1dda8 100644
--- a/gpu/command_buffer/service/shared_image/raw_draw_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/raw_draw_image_backing.h
@@ -5,12 +5,12 @@
 #ifndef GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_RAW_DRAW_IMAGE_BACKING_H_
 #define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_RAW_DRAW_IMAGE_BACKING_H_
 
+#include <optional>
 #include "base/functional/callback.h"
 #include "base/thread_annotations.h"
 #include "base/threading/thread_checker.h"
 #include "cc/paint/paint_op_buffer.h"
 #include "gpu/command_buffer/service/shared_image/shared_image_backing.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkSurfaceProps.h"
 #include "third_party/skia/include/gpu/GrBackendSurface.h"
@@ -56,19 +56,19 @@
       scoped_refptr<SharedContextState> context_state,
       int final_msaa_count,
       const SkSurfaceProps& surface_props,
-      const absl::optional<SkColor4f>& clear_color,
+      const std::optional<SkColor4f>& clear_color,
       bool visible);
   void EndRasterWriteAccess(base::OnceClosure callback);
   cc::PaintOpBuffer* BeginRasterReadAccess(
-      absl::optional<SkColor4f>& clear_color);
+      std::optional<SkColor4f>& clear_color);
   sk_sp<GrPromiseImageTexture> BeginSkiaReadAccess();
   void EndReadAccess();
 
   int32_t final_msaa_count_ GUARDED_BY_CONTEXT(thread_checker_) = 0;
   SkSurfaceProps surface_props_ GUARDED_BY_CONTEXT(thread_checker_){};
-  absl::optional<SkColor4f> clear_color_ GUARDED_BY(lock_);
+  std::optional<SkColor4f> clear_color_ GUARDED_BY(lock_);
   bool visible_ GUARDED_BY(lock_) = false;
-  absl::optional<cc::PaintOpBuffer> paint_op_buffer_ GUARDED_BY(lock_);
+  std::optional<cc::PaintOpBuffer> paint_op_buffer_ GUARDED_BY(lock_);
   base::OnceClosure paint_op_release_callback_
       GUARDED_BY_CONTEXT(thread_checker_);
   scoped_refptr<SharedContextState> context_state_
diff --git a/gpu/command_buffer/service/shared_image/shared_image_backing.cc b/gpu/command_buffer/service/shared_image/shared_image_backing.cc
index acc664a..bb24504 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_backing.cc
@@ -79,7 +79,7 @@
     uint32_t usage,
     size_t estimated_size,
     bool is_thread_safe,
-    absl::optional<gfx::BufferUsage> buffer_usage)
+    std::optional<gfx::BufferUsage> buffer_usage)
     : mailbox_(mailbox),
       format_(format),
       size_(size),
@@ -395,7 +395,7 @@
     uint32_t usage,
     size_t estimated_size,
     bool is_thread_safe,
-    absl::optional<gfx::BufferUsage> buffer_usage)
+    std::optional<gfx::BufferUsage> buffer_usage)
     : SharedImageBacking(mailbox,
                          format,
                          size,
diff --git a/gpu/command_buffer/service/shared_image/shared_image_backing.h b/gpu/command_buffer/service/shared_image/shared_image_backing.h
index cd31d5e..5c89c5c 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/shared_image_backing.h
@@ -9,6 +9,7 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_macros.h"
@@ -20,7 +21,6 @@
 #include "components/viz/common/resources/shared_image_format.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/gpu_gles2_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkImageInfo.h"
 #include "third_party/skia/include/core/SkPixmap.h"
 #include "third_party/skia/include/gpu/GrTypes.h"
@@ -114,7 +114,7 @@
       uint32_t usage,
       size_t estimated_size,
       bool is_thread_safe,
-      absl::optional<gfx::BufferUsage> buffer_usage = absl::nullopt);
+      std::optional<gfx::BufferUsage> buffer_usage = std::nullopt);
 
   virtual ~SharedImageBacking();
 
@@ -339,7 +339,7 @@
   // Protects non-const members here and in derived classes. Protected access
   // to allow GUARDED_BY macros in derived classes. Should not be used
   // directly. Use AutoLock instead.
-  mutable absl::optional<base::Lock> lock_;
+  mutable std::optional<base::Lock> lock_;
 
  private:
   class ScopedWriteUMA {
@@ -371,7 +371,7 @@
   size_t estimated_size_ GUARDED_BY(lock_);
 
   // Note that this will be eventually removed and merged into SharedImageUsage.
-  const absl::optional<gfx::BufferUsage> buffer_usage_;
+  const std::optional<gfx::BufferUsage> buffer_usage_;
 
   bool is_ref_counted_ = true;
 
@@ -384,7 +384,7 @@
   bool have_context_ GUARDED_BY(lock_) = true;
 
   // A scoped object for recording write UMA.
-  absl::optional<ScopedWriteUMA> scoped_write_uma_ GUARDED_BY(lock_);
+  std::optional<ScopedWriteUMA> scoped_write_uma_ GUARDED_BY(lock_);
 
   // A vector of SharedImageRepresentations which hold references to this
   // backing. The first reference is considered the owner, and the vector is
@@ -408,7 +408,7 @@
       uint32_t usage,
       size_t estimated_size,
       bool is_thread_safe,
-      absl::optional<gfx::BufferUsage> buffer_usage = absl::nullopt);
+      std::optional<gfx::BufferUsage> buffer_usage = std::nullopt);
 
   gfx::Rect ClearedRect() const override;
   void SetClearedRect(const gfx::Rect& cleared_rect) override;
diff --git a/gpu/command_buffer/service/shared_image/shared_image_gl_utils.h b/gpu/command_buffer/service/shared_image/shared_image_gl_utils.h
index 12d179c..11234c6 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_gl_utils.h
+++ b/gpu/command_buffer/service/shared_image/shared_image_gl_utils.h
@@ -5,9 +5,9 @@
 #ifndef GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_SHARED_IMAGE_GL_UTILS_H_
 #define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_SHARED_IMAGE_GL_UTILS_H_
 
+#include <optional>
 #include "base/memory/raw_ptr.h"
 #include "gpu/command_buffer/service/texture_manager.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gl/gl_utils.h"
 
 namespace gpu {
@@ -28,10 +28,10 @@
   const raw_ptr<gl::GLApi> api_;
 
   GLint pack_buffer_ = 0;
-  absl::optional<gl::ScopedPixelStore> pack_alignment_;
-  absl::optional<gl::ScopedPixelStore> pack_row_length_;
-  absl::optional<gl::ScopedPixelStore> pack_skip_pixels_;
-  absl::optional<gl::ScopedPixelStore> pack_skip_rows_;
+  std::optional<gl::ScopedPixelStore> pack_alignment_;
+  std::optional<gl::ScopedPixelStore> pack_row_length_;
+  std::optional<gl::ScopedPixelStore> pack_skip_pixels_;
+  std::optional<gl::ScopedPixelStore> pack_skip_rows_;
 };
 
 // Sets GL state for upload and copy.
@@ -53,21 +53,21 @@
   GLint unpack_buffer_ = 0;
 
   // Always used when |uploading_data|.
-  absl::optional<gl::ScopedPixelStore> unpack_alignment_;
+  std::optional<gl::ScopedPixelStore> unpack_alignment_;
 
   // Used when |uploading_data_| and (|es3_capable| or
   // |supports_unpack_subimage|).
-  absl::optional<gl::ScopedPixelStore> unpack_row_length_;
-  absl::optional<gl::ScopedPixelStore> unpack_skip_pixels_;
-  absl::optional<gl::ScopedPixelStore> unpack_skip_rows_;
+  std::optional<gl::ScopedPixelStore> unpack_row_length_;
+  std::optional<gl::ScopedPixelStore> unpack_skip_pixels_;
+  std::optional<gl::ScopedPixelStore> unpack_skip_rows_;
 
   // Used when |uploading_data| and |es3_capable|.
-  absl::optional<gl::ScopedPixelStore> unpack_skip_images_;
-  absl::optional<gl::ScopedPixelStore> unpack_image_height_;
+  std::optional<gl::ScopedPixelStore> unpack_skip_images_;
+  std::optional<gl::ScopedPixelStore> unpack_image_height_;
 
   // Used when |desktop_gl|.
-  absl::optional<gl::ScopedPixelStore> unpack_swap_bytes_;
-  absl::optional<gl::ScopedPixelStore> unpack_lsb_first_;
+  std::optional<gl::ScopedPixelStore> unpack_swap_bytes_;
+  std::optional<gl::ScopedPixelStore> unpack_lsb_first_;
 };
 
 // Creates a new GL texture and returns GL texture ID.
diff --git a/gpu/command_buffer/service/shared_image/shared_image_manager.h b/gpu/command_buffer/service/shared_image/shared_image_manager.h
index ad24455..9bf8364 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_manager.h
+++ b/gpu/command_buffer/service/shared_image/shared_image_manager.h
@@ -5,6 +5,7 @@
 #ifndef GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_SHARED_IMAGE_MANAGER_H_
 #define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_SHARED_IMAGE_MANAGER_H_
 
+#include <optional>
 #include "base/containers/flat_set.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/synchronization/lock.h"
@@ -14,7 +15,6 @@
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/command_buffer/service/shared_image/shared_image_backing.h"
 #include "gpu/gpu_gles2_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(IS_WIN)
 namespace gfx {
@@ -145,7 +145,7 @@
  private:
   class AutoLock;
   // The lock for protecting |images_|.
-  absl::optional<base::Lock> lock_;
+  std::optional<base::Lock> lock_;
 
   base::flat_set<std::unique_ptr<SharedImageBacking>> images_ GUARDED_BY(lock_);
 
diff --git a/gpu/command_buffer/service/shared_image/shared_image_representation.cc b/gpu/command_buffer/service/shared_image/shared_image_representation.cc
index 3f5a72f..f437ece6 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_representation.cc
@@ -724,10 +724,10 @@
   return backing()->GetNativePixmap();
 }
 #elif BUILDFLAG(IS_WIN)
-absl::optional<gl::DCLayerOverlayImage>
+std::optional<gl::DCLayerOverlayImage>
 OverlayImageRepresentation::GetDCLayerOverlayImage() {
   NOTREACHED();
-  return absl::nullopt;
+  return std::nullopt;
 }
 #elif BUILDFLAG(IS_APPLE)
 gfx::ScopedIOSurface OverlayImageRepresentation::GetIOSurface() const {
@@ -916,7 +916,7 @@
     base::PassKey<RasterImageRepresentation> pass_key,
     RasterImageRepresentation* representation,
     const cc::PaintOpBuffer* paint_op_buffer,
-    const absl::optional<SkColor4f>& clear_color)
+    const std::optional<SkColor4f>& clear_color)
     : ScopedAccessBase(representation, AccessMode::kRead),
       paint_op_buffer_(paint_op_buffer),
       clear_color_(clear_color) {}
@@ -938,7 +938,7 @@
 
 std::unique_ptr<RasterImageRepresentation::ScopedReadAccess>
 RasterImageRepresentation::BeginScopedReadAccess() {
-  absl::optional<SkColor4f> clear_color;
+  std::optional<SkColor4f> clear_color;
   auto* paint_op_buffer = BeginReadAccess(clear_color);
   if (!paint_op_buffer) {
     return nullptr;
@@ -953,7 +953,7 @@
     scoped_refptr<SharedContextState> context_state,
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
-    const absl::optional<SkColor4f>& clear_color,
+    const std::optional<SkColor4f>& clear_color,
     bool visible) {
   return std::make_unique<ScopedWriteAccess>(
       base::PassKey<RasterImageRepresentation>(), this,
diff --git a/gpu/command_buffer/service/shared_image/shared_image_representation.h b/gpu/command_buffer/service/shared_image/shared_image_representation.h
index 257f37d..78e241f 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/shared_image_representation.h
@@ -813,7 +813,7 @@
       return representation()->GetNativePixmap();
     }
 #elif BUILDFLAG(IS_WIN)
-    absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() {
+    std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() {
       return representation()->GetDCLayerOverlayImage();
     }
 #elif BUILDFLAG(IS_APPLE)
@@ -864,7 +864,7 @@
 #elif BUILDFLAG(IS_OZONE)
   scoped_refptr<gfx::NativePixmap> GetNativePixmap();
 #elif BUILDFLAG(IS_WIN)
-  virtual absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage();
+  virtual std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage();
 #elif BUILDFLAG(IS_APPLE)
   virtual gfx::ScopedIOSurface GetIOSurface() const;
   // Return true if the macOS WindowServer is currently using the underlying
@@ -1008,19 +1008,17 @@
     ScopedReadAccess(base::PassKey<RasterImageRepresentation> pass_key,
                      RasterImageRepresentation* representation,
                      const cc::PaintOpBuffer* paint_op_buffer,
-                     const absl::optional<SkColor4f>& clear_color);
+                     const std::optional<SkColor4f>& clear_color);
     ~ScopedReadAccess();
 
     const cc::PaintOpBuffer* paint_op_buffer() const {
       return paint_op_buffer_;
     }
-    const absl::optional<SkColor4f>& clear_color() const {
-      return clear_color_;
-    }
+    const std::optional<SkColor4f>& clear_color() const { return clear_color_; }
 
    private:
     const raw_ptr<const cc::PaintOpBuffer> paint_op_buffer_;
-    absl::optional<SkColor4f> clear_color_;
+    std::optional<SkColor4f> clear_color_;
   };
 
   class GPU_GLES2_EXPORT ScopedWriteAccess
@@ -1056,18 +1054,18 @@
       scoped_refptr<SharedContextState> context_state,
       int final_msaa_count,
       const SkSurfaceProps& surface_props,
-      const absl::optional<SkColor4f>& clear_color,
+      const std::optional<SkColor4f>& clear_color,
       bool visible);
 
  protected:
   virtual cc::PaintOpBuffer* BeginReadAccess(
-      absl::optional<SkColor4f>& clear_color) = 0;
+      std::optional<SkColor4f>& clear_color) = 0;
   virtual void EndReadAccess() = 0;
   virtual cc::PaintOpBuffer* BeginWriteAccess(
       scoped_refptr<SharedContextState> context_state,
       int final_msaa_count,
       const SkSurfaceProps& surface_props,
-      const absl::optional<SkColor4f>& clear_color,
+      const std::optional<SkColor4f>& clear_color,
       bool visible) = 0;
   virtual void EndWriteAccess(base::OnceClosure callback) = 0;
 };
diff --git a/gpu/command_buffer/service/shared_image/shared_memory_image_backing.cc b/gpu/command_buffer/service/shared_image/shared_memory_image_backing.cc
index 7dd6a8a92..3c92a17 100644
--- a/gpu/command_buffer/service/shared_image/shared_memory_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/shared_memory_image_backing.cc
@@ -66,13 +66,13 @@
   void EndReadAccess(gfx::GpuFenceHandle release_fence) override {}
 
 #if BUILDFLAG(IS_WIN)
-  absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() override {
+  std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() override {
     // This should only be called for the backing which references the Y plane,
     // eg. plane_index=0, of an NV12 shmem GMB - see allow_shm_overlay in
     // SharedImageFactory. This allows access to both Y and UV planes.
     const auto& shm_wrapper = static_cast<SharedMemoryImageBacking*>(backing())
                                   ->shared_memory_wrapper();
-    return absl::make_optional<gl::DCLayerOverlayImage>(
+    return std::make_optional<gl::DCLayerOverlayImage>(
         size(), shm_wrapper.GetMemory(0), shm_wrapper.GetStride(0));
   }
 #endif
@@ -204,7 +204,7 @@
     uint32_t usage,
     SharedMemoryRegionWrapper wrapper,
     gfx::GpuMemoryBufferHandle handle,
-    absl::optional<gfx::BufferUsage> buffer_usage)
+    std::optional<gfx::BufferUsage> buffer_usage)
     : SharedImageBacking(mailbox,
                          format,
                          size,
diff --git a/gpu/command_buffer/service/shared_image/shared_memory_image_backing.h b/gpu/command_buffer/service/shared_image/shared_memory_image_backing.h
index 9c97cea..07a74cf 100644
--- a/gpu/command_buffer/service/shared_image/shared_memory_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/shared_memory_image_backing.h
@@ -32,7 +32,7 @@
       uint32_t usage,
       SharedMemoryRegionWrapper wrapper,
       gfx::GpuMemoryBufferHandle handle = gfx::GpuMemoryBufferHandle(),
-      absl::optional<gfx::BufferUsage> buffer_usage = absl::nullopt);
+      std::optional<gfx::BufferUsage> buffer_usage = std::nullopt);
 
   ~SharedMemoryImageBacking() override;
 
diff --git a/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing.cc b/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing.cc
index 70e048b0..86053942 100644
--- a/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing.cc
@@ -265,7 +265,7 @@
   textures_.resize(1);
 
   {
-    absl::optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
+    std::optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
     // ScopedCacheUse is used to avoid the empty/invalid client id DCHECKS
     // caused while accessing GrShaderCache. Even though other clients can
     // create shared images, the context used to create the backend texture
diff --git a/gpu/command_buffer/service/shared_image_interface_in_process.cc b/gpu/command_buffer/service/shared_image_interface_in_process.cc
index 8ef587a..e56d40b6 100644
--- a/gpu/command_buffer/service/shared_image_interface_in_process.cc
+++ b/gpu/command_buffer/service/shared_image_interface_in_process.cc
@@ -4,6 +4,7 @@
 
 #include "gpu/command_buffer/service/shared_image_interface_in_process.h"
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/memory/raw_ptr.h"
 #include "base/synchronization/waitable_event.h"
@@ -23,7 +24,6 @@
 #include "gpu/config/gpu_feature_info.h"
 #include "gpu/config/gpu_preferences.h"
 #include "gpu/ipc/common/gpu_client_ids.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gl/gl_context.h"
 
 namespace gpu {
diff --git a/gpu/command_buffer/service/skia_utils.cc b/gpu/command_buffer/service/skia_utils.cc
index db2b00ee..521cfd3 100644
--- a/gpu/command_buffer/service/skia_utils.cc
+++ b/gpu/command_buffer/service/skia_utils.cc
@@ -364,7 +364,7 @@
     VkImageTiling tiling,
     VkFormat format,
     const gfx::ColorSpace& color_space,
-    const absl::optional<VulkanYCbCrInfo>& ycbcr_info) {
+    const std::optional<VulkanYCbCrInfo>& ycbcr_info) {
   auto valid_ycbcr_info = ycbcr_info;
   if (!valid_ycbcr_info) {
     if (!VkFormatNeedsYcbcrSampler(format)) {
@@ -440,7 +440,7 @@
     viz::VulkanContextProvider* context_provider) {
 #if BUILDFLAG(ENABLE_VULKAN)
   if (context_provider) {
-    const absl::optional<uint32_t>& sync_cpu_memory_limit =
+    const std::optional<uint32_t>& sync_cpu_memory_limit =
         context_provider->GetSyncCpuMemoryLimit();
     if (sync_cpu_memory_limit.has_value()) {
       uint64_t total_allocated_bytes =
diff --git a/gpu/command_buffer/service/skia_utils.h b/gpu/command_buffer/service/skia_utils.h
index d0751e463..7d52d2b 100644
--- a/gpu/command_buffer/service/skia_utils.h
+++ b/gpu/command_buffer/service/skia_utils.h
@@ -5,6 +5,7 @@
 #ifndef GPU_COMMAND_BUFFER_SERVICE_SKIA_UTILS_H_
 #define GPU_COMMAND_BUFFER_SERVICE_SKIA_UTILS_H_
 
+#include <optional>
 #include "base/functional/callback_forward.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "gpu/config/gpu_preferences.h"
@@ -12,7 +13,6 @@
 #include "gpu/ipc/common/vulkan_ycbcr_info.h"
 #include "gpu/vulkan/buildflags.h"
 #include "skia/buildflags.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkSurface.h"
 #include "third_party/skia/include/gpu/GrContextOptions.h"
 #include "third_party/skia/include/gpu/GrTypes.h"
@@ -108,12 +108,12 @@
 GPU_GLES2_EXPORT GrVkImageInfo
 CreateGrVkImageInfo(VulkanImage* image, const gfx::ColorSpace& color_space);
 
-GPU_GLES2_EXPORT GrVkYcbcrConversionInfo CreateGrVkYcbcrConversionInfo(
-    VkPhysicalDevice physical_device,
-    VkImageTiling tiling,
-    VkFormat format,
-    const gfx::ColorSpace& color_space,
-    const absl::optional<VulkanYCbCrInfo>& ycbcr_info);
+GPU_GLES2_EXPORT GrVkYcbcrConversionInfo
+CreateGrVkYcbcrConversionInfo(VkPhysicalDevice physical_device,
+                              VkImageTiling tiling,
+                              VkFormat format,
+                              const gfx::ColorSpace& color_space,
+                              const std::optional<VulkanYCbCrInfo>& ycbcr_info);
 #endif  // BUILDFLAG(ENABLE_VULKAN)
 
 // Helper that returns true when Vulkan memory usage is high enough
diff --git a/gpu/command_buffer/service/texture_owner.cc b/gpu/command_buffer/service/texture_owner.cc
index fa767f8..ccb982d 100644
--- a/gpu/command_buffer/service/texture_owner.cc
+++ b/gpu/command_buffer/service/texture_owner.cc
@@ -58,7 +58,7 @@
 
 TextureOwner::~TextureOwner() {
   bool have_context = true;
-  absl::optional<ui::ScopedMakeCurrent> scoped_make_current;
+  std::optional<ui::ScopedMakeCurrent> scoped_make_current;
   if (!context_state_) {
     have_context = false;
   } else {
diff --git a/gpu/command_buffer/service/webgpu_decoder.h b/gpu/command_buffer/service/webgpu_decoder.h
index 58f7bf2..c292665 100644
--- a/gpu/command_buffer/service/webgpu_decoder.h
+++ b/gpu/command_buffer/service/webgpu_decoder.h
@@ -5,12 +5,12 @@
 #ifndef GPU_COMMAND_BUFFER_SERVICE_WEBGPU_DECODER_H_
 #define GPU_COMMAND_BUFFER_SERVICE_WEBGPU_DECODER_H_
 
+#include <optional>
 #include "base/memory/raw_ptr.h"
 #include "gpu/command_buffer/service/common_decoder.h"
 #include "gpu/command_buffer/service/decoder_context.h"
 #include "gpu/gpu_gles2_export.h"
 #include "gpu/ipc/common/gpu_disk_cache_type.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace gpu {
 
@@ -33,7 +33,7 @@
 // Options specifically passed for Dawn caching;
 struct DawnCacheOptions {
   raw_ptr<DawnCachingInterfaceFactory> caching_interface_factory = nullptr;
-  absl::optional<GpuDiskCacheHandle> handle = {};
+  std::optional<GpuDiskCacheHandle> handle = {};
 };
 
 class GPU_GLES2_EXPORT WebGPUDecoder : public DecoderContext,
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc
index 3aa4427..cd60ba7 100644
--- a/gpu/command_buffer/service/webgpu_decoder_impl.cc
+++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -13,6 +13,7 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/auto_reset.h"
 #include "base/bits.h"
 #include "base/containers/contains.h"
@@ -52,7 +53,6 @@
 #include "gpu/config/webgpu_blocklist.h"
 #include "gpu/webgpu/callback.h"
 #include "third_party/abseil-cpp/absl/base/attributes.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
 #include "third_party/skia/include/gpu/GrBackendSemaphore.h"
 #include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
@@ -445,7 +445,7 @@
 
   // Isolation key that is necessary for device requests. Optional to
   // differentiate between an empty isolation key, and an unset one.
-  absl::optional<std::string> isolation_key_;
+  std::optional<std::string> isolation_key_;
 
   std::unique_ptr<dawn::wire::WireServer> wire_server_;
   std::unique_ptr<DawnServiceSerializer> wire_serializer_;
@@ -2159,7 +2159,7 @@
   blink::WebGPUExecutionContextToken::Tag type{c.type};
   uint64_t high = uint64_t(c.high_high) << 32 | uint64_t(c.high_low);
   uint64_t low = uint64_t(c.low_high) << 32 | uint64_t(c.low_low);
-  absl::optional<base::UnguessableToken> unguessable_token =
+  std::optional<base::UnguessableToken> unguessable_token =
       base::UnguessableToken::Deserialize(high, low);
   if (!unguessable_token.has_value()) {
     return error::kInvalidArguments;
diff --git a/gpu/config/device_perf_info.cc b/gpu/config/device_perf_info.cc
index 5376ef23..495408cc7 100644
--- a/gpu/config/device_perf_info.cc
+++ b/gpu/config/device_perf_info.cc
@@ -11,7 +11,7 @@
 
 namespace {
 // Global instance in browser process.
-absl::optional<DevicePerfInfo> g_device_perf_info;
+std::optional<DevicePerfInfo> g_device_perf_info;
 
 base::Lock& GetLock() {
   static base::NoDestructor<base::Lock> lock;
@@ -19,7 +19,7 @@
 }
 }  // namespace
 
-absl::optional<DevicePerfInfo> GetDevicePerfInfo() {
+std::optional<DevicePerfInfo> GetDevicePerfInfo() {
   base::AutoLock lock(GetLock());
   return g_device_perf_info;
 }
diff --git a/gpu/config/device_perf_info.h b/gpu/config/device_perf_info.h
index bdcdbc4..521d251 100644
--- a/gpu/config/device_perf_info.h
+++ b/gpu/config/device_perf_info.h
@@ -6,9 +6,9 @@
 #define GPU_CONFIG_DEVICE_PERF_INFO_H_
 
 #include <cstdint>
+#include <optional>
 #include "build/build_config.h"
 #include "gpu/gpu_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(IS_WIN)
 #include <d3dcommon.h>
@@ -61,7 +61,7 @@
 };
 
 // Thread-safe getter and setter of global instance of DevicePerfInfo.
-GPU_EXPORT absl::optional<DevicePerfInfo> GetDevicePerfInfo();
+GPU_EXPORT std::optional<DevicePerfInfo> GetDevicePerfInfo();
 GPU_EXPORT void SetDevicePerfInfo(const DevicePerfInfo& device_perf_info);
 
 }  // namespace gpu
diff --git a/gpu/config/gpu_info.cc b/gpu/config/gpu_info.cc
index eb74a1091..2dde12c6 100644
--- a/gpu/config/gpu_info.cc
+++ b/gpu/config/gpu_info.cc
@@ -349,7 +349,7 @@
     uint32_t visibility_callback_call_count;
 
 #if BUILDFLAG(ENABLE_VULKAN)
-    absl::optional<VulkanInfo> vulkan_info;
+    std::optional<VulkanInfo> vulkan_info;
 #endif
   };
 
diff --git a/gpu/config/gpu_info.h b/gpu/config/gpu_info.h
index 72c9521..cc11375 100644
--- a/gpu/config/gpu_info.h
+++ b/gpu/config/gpu_info.h
@@ -13,6 +13,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/clang_profiling_buildflags.h"
 #include "base/containers/flat_map.h"
 #include "base/containers/span.h"
@@ -22,7 +23,6 @@
 #include "gpu/config/dx_diag_node.h"
 #include "gpu/gpu_export.h"
 #include "gpu/vulkan/buildflags.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gpu_preference.h"
@@ -495,7 +495,7 @@
   uint32_t visibility_callback_call_count = 0;
 
 #if BUILDFLAG(ENABLE_VULKAN)
-  absl::optional<VulkanInfo> vulkan_info;
+  std::optional<VulkanInfo> vulkan_info;
 #endif
 
   // Note: when adding new members, please remember to update EnumerateFields
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc
index ab8754d..14a5a0e 100644
--- a/gpu/config/gpu_info_collector.cc
+++ b/gpu/config/gpu_info_collector.cc
@@ -11,6 +11,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/base_paths.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
@@ -27,7 +28,6 @@
 #include "gpu/config/gpu_switches.h"
 #include "gpu/config/webgpu_blocklist.h"
 #include "skia/buildflags.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/angle/src/gpu_info_util/SystemInfo.h"  // nogncheck
 #include "third_party/skia/include/core/SkGraphics.h"
 #include "ui/gl/buildflags.h"
@@ -528,7 +528,7 @@
       gl::UsePassthroughCommandDecoder(command_line);
 
   bool fallback_to_software = false;
-  absl::optional<gl::GLImplementationParts> implementation =
+  std::optional<gl::GLImplementationParts> implementation =
       gl::GetRequestedGLImplementationFromCommandLine(command_line,
                                                       &fallback_to_software);
 
diff --git a/gpu/config/gpu_util.cc b/gpu/config/gpu_util.cc
index 87e0039..89f88c8 100644
--- a/gpu/config/gpu_util.cc
+++ b/gpu/config/gpu_util.cc
@@ -19,6 +19,7 @@
 #include <thread>
 #include <vector>
 
+#include <optional>
 #include "base/base_paths.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
@@ -44,7 +45,6 @@
 #include "gpu/config/gpu_switches.h"
 #include "gpu/vulkan/buildflags.h"
 #include "skia/buildflags.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/extension_set.h"
 #include "ui/gl/buildflags.h"
 #include "ui/gl/gl_display.h"
@@ -534,7 +534,7 @@
   bool use_swift_shader = false;
 
   bool fallback_to_software_gl = false;
-  absl::optional<gl::GLImplementationParts> requested_impl =
+  std::optional<gl::GLImplementationParts> requested_impl =
       gl::GetRequestedGLImplementationFromCommandLine(command_line,
                                                       &fallback_to_software_gl);
   if (requested_impl) {
@@ -1020,7 +1020,7 @@
 }
 
 void RecordDevicePerfInfoHistograms() {
-  absl::optional<DevicePerfInfo> device_perf_info = GetDevicePerfInfo();
+  std::optional<DevicePerfInfo> device_perf_info = GetDevicePerfInfo();
   if (!device_perf_info.has_value())
     return;
   UMA_HISTOGRAM_COUNTS_1000("Hardware.TotalDiskSpace",
diff --git a/gpu/ipc/client/command_buffer_proxy_impl.cc b/gpu/ipc/client/command_buffer_proxy_impl.cc
index 2e255dca..23619f17 100644
--- a/gpu/ipc/client/command_buffer_proxy_impl.cc
+++ b/gpu/ipc/client/command_buffer_proxy_impl.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
@@ -34,7 +35,6 @@
 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
 #include "mojo/public/cpp/system/buffer.h"
 #include "mojo/public/cpp/system/platform_handle.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/gpu_fence.h"
diff --git a/gpu/ipc/client/gpu_channel_host.h b/gpu/ipc/client/gpu_channel_host.h
index a1a5501c..b6ecec0 100644
--- a/gpu/ipc/client/gpu_channel_host.h
+++ b/gpu/ipc/client/gpu_channel_host.h
@@ -257,7 +257,7 @@
   mutable base::Lock context_lock_;
   std::vector<mojom::DeferredRequestPtr> deferred_messages_
       GUARDED_BY(context_lock_);
-  absl::optional<OrderingBarrierInfo> pending_ordering_barrier_
+  std::optional<OrderingBarrierInfo> pending_ordering_barrier_
       GUARDED_BY(context_lock_);
   uint32_t next_deferred_message_id_ GUARDED_BY(context_lock_) = 1;
   // Highest deferred message id in |deferred_messages_|.
diff --git a/gpu/ipc/common/gpu_info_mojom_traits.h b/gpu/ipc/common/gpu_info_mojom_traits.h
index 1697d6fe..33ea2f0 100644
--- a/gpu/ipc/common/gpu_info_mojom_traits.h
+++ b/gpu/ipc/common/gpu_info_mojom_traits.h
@@ -5,13 +5,13 @@
 #ifndef GPU_IPC_COMMON_GPU_INFO_MOJOM_TRAITS_H_
 #define GPU_IPC_COMMON_GPU_INFO_MOJOM_TRAITS_H_
 
+#include <optional>
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "gpu/config/gpu_info.h"
 #include "gpu/gpu_export.h"
 #include "gpu/ipc/common/dx_diag_node_mojom_traits.h"
 #include "gpu/ipc/common/gpu_info.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/buffer_types.h"
 #include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
 
@@ -423,7 +423,7 @@
   }
 
 #if BUILDFLAG(ENABLE_VULKAN)
-  static const absl::optional<gpu::VulkanInfo>& vulkan_info(
+  static const std::optional<gpu::VulkanInfo>& vulkan_info(
       const gpu::GPUInfo& input) {
     return input.vulkan_info;
   }
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc
index 9591f762..160d3665 100644
--- a/gpu/ipc/in_process_command_buffer.cc
+++ b/gpu/ipc/in_process_command_buffer.cc
@@ -157,7 +157,7 @@
 }
 
 void InProcessCommandBuffer::CreateCacheUse(
-    absl::optional<gles2::ProgramCache::ScopedCacheUse>& cache_use) {
+    std::optional<gles2::ProgramCache::ScopedCacheUse>& cache_use) {
   if (context_group_->has_program_cache()) {
     cache_use.emplace(
         context_group_->get_program_cache(),
@@ -491,7 +491,7 @@
   gpu_thread_weak_ptr_factory_.InvalidateWeakPtrs();
   // Clean up GL resources if possible.
   bool have_context = context_.get() && context_->MakeCurrent(surface_.get());
-  absl::optional<gles2::ProgramCache::ScopedCacheUse> cache_use;
+  std::optional<gles2::ProgramCache::ScopedCacheUse> cache_use;
   if (have_context)
     CreateCacheUse(cache_use);
 
@@ -613,11 +613,11 @@
 
   if (!MakeCurrent())
     return;
-  absl::optional<gles2::ProgramCache::ScopedCacheUse> cache_use;
+  std::optional<gles2::ProgramCache::ScopedCacheUse> cache_use;
   CreateCacheUse(cache_use);
 
   {
-    absl::optional<raster::GrShaderCache::ScopedCacheUse> gr_cache_use;
+    std::optional<raster::GrShaderCache::ScopedCacheUse> gr_cache_use;
     if (gr_shader_cache_)
       gr_cache_use.emplace(gr_shader_cache_, kDisplayCompositorClientId);
     command_buffer_->Flush(put_offset, decoder_.get());
@@ -646,7 +646,7 @@
   delayed_work_pending_ = false;
 
   if (MakeCurrent()) {
-    absl::optional<gles2::ProgramCache::ScopedCacheUse> cache_use;
+    std::optional<gles2::ProgramCache::ScopedCacheUse> cache_use;
     CreateCacheUse(cache_use);
     decoder_->PerformIdleWork();
     decoder_->ProcessPendingQueries(false);
diff --git a/gpu/ipc/in_process_command_buffer.h b/gpu/ipc/in_process_command_buffer.h
index 91d1ef9..9319dbb 100644
--- a/gpu/ipc/in_process_command_buffer.h
+++ b/gpu/ipc/in_process_command_buffer.h
@@ -13,6 +13,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/compiler_specific.h"
 #include "base/functional/callback.h"
 #include "base/functional/callback_helpers.h"
@@ -44,7 +45,6 @@
 #include "gpu/ipc/common/surface_handle.h"
 #include "gpu/ipc/gl_in_process_context_export.h"
 #include "gpu/ipc/service/context_url.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/gpu_memory_buffer.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gl/gl_surface.h"
@@ -216,7 +216,7 @@
   bool MakeCurrent();
 
   void CreateCacheUse(
-      absl::optional<gles2::ProgramCache::ScopedCacheUse>& cache_use);
+      std::optional<gles2::ProgramCache::ScopedCacheUse>& cache_use);
 
   // Client callbacks are posted back to |origin_task_runner_|, or run
   // synchronously if there's no task runner or message loop.
diff --git a/gpu/ipc/service/command_buffer_stub.cc b/gpu/ipc/service/command_buffer_stub.cc
index 2fc7c68..0f76edfd 100644
--- a/gpu/ipc/service/command_buffer_stub.cc
+++ b/gpu/ipc/service/command_buffer_stub.cc
@@ -189,7 +189,7 @@
                                                                         : "0");
   if (decoder_context_.get() && !MakeCurrent())
     return;
-  absl::optional<gles2::ProgramCache::ScopedCacheUse> cache_use;
+  std::optional<gles2::ProgramCache::ScopedCacheUse> cache_use;
   CreateCacheUse(cache_use);
 
   if (decoder_context_) {
@@ -283,7 +283,7 @@
 }
 
 void CommandBufferStub::CreateCacheUse(
-    absl::optional<gles2::ProgramCache::ScopedCacheUse>& cache_use) {
+    std::optional<gles2::ProgramCache::ScopedCacheUse>& cache_use) {
   cache_use.emplace(
       channel_->gpu_channel_manager()->program_cache(),
       base::BindRepeating(&DecoderClient::CacheBlob, base::Unretained(this),
@@ -330,7 +330,7 @@
         decoder_context_->GetGLContext()->MakeCurrent(surface_.get());
   }
 
-  absl::optional<gles2::ProgramCache::ScopedCacheUse> cache_use;
+  std::optional<gles2::ProgramCache::ScopedCacheUse> cache_use;
   if (have_context)
     CreateCacheUse(cache_use);
 
@@ -346,7 +346,7 @@
 
   if (decoder_context_) {
     auto* gr_shader_cache = channel_->gpu_channel_manager()->gr_shader_cache();
-    absl::optional<raster::GrShaderCache::ScopedCacheUse> gr_cache_use;
+    std::optional<raster::GrShaderCache::ScopedCacheUse> gr_cache_use;
     if (gr_shader_cache)
       gr_cache_use.emplace(gr_shader_cache, channel_->client_id());
 
@@ -501,7 +501,7 @@
 
   {
     auto* gr_shader_cache = channel_->gpu_channel_manager()->gr_shader_cache();
-    absl::optional<raster::GrShaderCache::ScopedCacheUse> cache_use;
+    std::optional<raster::GrShaderCache::ScopedCacheUse> cache_use;
     if (gr_shader_cache)
       cache_use.emplace(gr_shader_cache, channel_->client_id());
     command_buffer_->Flush(put_offset, decoder_context_.get());
diff --git a/gpu/ipc/service/command_buffer_stub.h b/gpu/ipc/service/command_buffer_stub.h
index 5fe890b..68ad357 100644
--- a/gpu/ipc/service/command_buffer_stub.h
+++ b/gpu/ipc/service/command_buffer_stub.h
@@ -12,6 +12,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/raw_ref.h"
@@ -38,7 +39,6 @@
 #include "gpu/ipc/service/gpu_ipc_service_export.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/shared_associated_remote.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/gpu_memory_buffer.h"
 #include "ui/gfx/swap_result.h"
@@ -209,7 +209,7 @@
    private:
     const raw_ref<CommandBufferStub> stub_;
     bool have_context_ = false;
-    absl::optional<gles2::ProgramCache::ScopedCacheUse> cache_use_;
+    std::optional<gles2::ProgramCache::ScopedCacheUse> cache_use_;
   };
 
   mojom::CommandBufferClient& client() { return *client_.get(); }
@@ -290,7 +290,7 @@
   void Destroy();
 
   void CreateCacheUse(
-      absl::optional<gles2::ProgramCache::ScopedCacheUse>& cache_use);
+      std::optional<gles2::ProgramCache::ScopedCacheUse>& cache_use);
 
   // Message handlers:
   void OnAsyncFlush(int32_t put_offset,
diff --git a/gpu/ipc/service/dcomp_texture_win.cc b/gpu/ipc/service/dcomp_texture_win.cc
index db51373b..88354cb 100644
--- a/gpu/ipc/service/dcomp_texture_win.cc
+++ b/gpu/ipc/service/dcomp_texture_win.cc
@@ -45,9 +45,9 @@
       : OverlayImageRepresentation(manager, backing, tracker),
         dcomp_surface_proxy_(std::move(dcomp_surface_proxy)) {}
 
-  absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() override {
-    return absl::make_optional<gl::DCLayerOverlayImage>(size(),
-                                                        dcomp_surface_proxy_);
+  std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() override {
+    return std::make_optional<gl::DCLayerOverlayImage>(size(),
+                                                       dcomp_surface_proxy_);
   }
 
   bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) override {
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc
index 725f8df..c8a70a47a 100644
--- a/gpu/ipc/service/gpu_channel.cc
+++ b/gpu/ipc/service/gpu_channel.cc
@@ -1217,7 +1217,7 @@
 }
 #endif  // BUILDFLAG(IS_FUCHSIA)
 
-absl::optional<gpu::GpuDiskCacheHandle> GpuChannel::GetCacheHandleForType(
+std::optional<gpu::GpuDiskCacheHandle> GpuChannel::GetCacheHandleForType(
     gpu::GpuDiskCacheType type) {
   auto it = caches_.find(type);
   if (it == caches_.end()) {
diff --git a/gpu/ipc/service/gpu_channel.h b/gpu/ipc/service/gpu_channel.h
index 144ff81..be8fbf3a 100644
--- a/gpu/ipc/service/gpu_channel.h
+++ b/gpu/ipc/service/gpu_channel.h
@@ -11,6 +11,7 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/containers/flat_map.h"
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
@@ -33,7 +34,6 @@
 #include "ipc/ipc_sync_channel.h"
 #include "mojo/public/cpp/bindings/generic_pending_associated_receiver.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/gpu_extra_info.h"
 #include "ui/gfx/native_widget_types.h"
@@ -139,7 +139,7 @@
   // Called to remove a listener for a particular message routing ID.
   void RemoveRoute(int32_t route_id);
 
-  absl::optional<gpu::GpuDiskCacheHandle> GetCacheHandleForType(
+  std::optional<gpu::GpuDiskCacheHandle> GetCacheHandleForType(
       gpu::GpuDiskCacheType type);
   void RegisterCacheHandle(const gpu::GpuDiskCacheHandle& handle);
   void CacheBlob(gpu::GpuDiskCacheType type,
diff --git a/gpu/ipc/service/gpu_channel_manager.h b/gpu/ipc/service/gpu_channel_manager.h
index 7b9c992..7201816 100644
--- a/gpu/ipc/service/gpu_channel_manager.h
+++ b/gpu/ipc/service/gpu_channel_manager.h
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/containers/flat_map.h"
 #include "base/memory/memory_pressure_listener.h"
 #include "base/memory/raw_ptr.h"
@@ -39,7 +40,6 @@
 #include "gpu/ipc/common/gpu_disk_cache_type.h"
 #include "gpu/ipc/common/gpu_peak_memory.h"
 #include "gpu/ipc/service/gpu_ipc_service_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/gpu_memory_buffer.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gl/gl_surface.h"
@@ -387,7 +387,7 @@
   // order to avoid having the GpuChannelManager keep the lost context state
   // alive until all clients have recovered, we use a ref-counted object and
   // allow the decoders to manage its lifetime.
-  absl::optional<raster::GrShaderCache> gr_shader_cache_;
+  std::optional<raster::GrShaderCache> gr_shader_cache_;
   scoped_refptr<SharedContextState> shared_context_state_;
 
   raw_ptr<webgpu::DawnCachingInterfaceFactory> dawn_caching_interface_factory_;
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc
index c5ab7f07..4adc2ec 100644
--- a/gpu/ipc/service/gpu_init.cc
+++ b/gpu/ipc/service/gpu_init.cc
@@ -7,6 +7,7 @@
 #include <cstdlib>
 #include <string>
 
+#include <optional>
 #include "base/base_paths.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
@@ -35,7 +36,6 @@
 #include "gpu/config/gpu_switching.h"
 #include "gpu/config/gpu_util.h"
 #include "gpu/ipc/service/gpu_watchdog_thread.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/gfx/switches.h"
 #include "ui/gl/buildflags.h"
diff --git a/gpu/ipc/service/gpu_init.h b/gpu/ipc/service/gpu_init.h
index eb23ec15..b65c831 100644
--- a/gpu/ipc/service/gpu_init.h
+++ b/gpu/ipc/service/gpu_init.h
@@ -5,6 +5,7 @@
 #ifndef GPU_IPC_SERVICE_GPU_INIT_H_
 #define GPU_IPC_SERVICE_GPU_INIT_H_
 
+#include <optional>
 #include "base/memory/raw_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "gpu/config/device_perf_info.h"
@@ -14,7 +15,6 @@
 #include "gpu/ipc/service/gpu_ipc_service_export.h"
 #include "gpu/ipc/service/gpu_watchdog_thread.h"
 #include "gpu/vulkan/buildflags.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/gpu_extra_info.h"
 
 namespace base {
@@ -63,14 +63,14 @@
   const GPUInfo& gpu_info() const { return gpu_info_; }
   const GpuFeatureInfo& gpu_feature_info() const { return gpu_feature_info_; }
   const gfx::GpuExtraInfo& gpu_extra_info() const { return gpu_extra_info_; }
-  const absl::optional<GPUInfo>& gpu_info_for_hardware_gpu() const {
+  const std::optional<GPUInfo>& gpu_info_for_hardware_gpu() const {
     return gpu_info_for_hardware_gpu_;
   }
-  const absl::optional<GpuFeatureInfo>& gpu_feature_info_for_hardware_gpu()
+  const std::optional<GpuFeatureInfo>& gpu_feature_info_for_hardware_gpu()
       const {
     return gpu_feature_info_for_hardware_gpu_;
   }
-  const absl::optional<DevicePerfInfo>& device_perf_info() const {
+  const std::optional<DevicePerfInfo>& device_perf_info() const {
     return device_perf_info_;
   }
   const GpuPreferences& gpu_preferences() const { return gpu_preferences_; }
@@ -101,13 +101,13 @@
 
   // The following data are collected from hardware GPU and saved before
   // switching to SwiftShader.
-  absl::optional<GPUInfo> gpu_info_for_hardware_gpu_;
-  absl::optional<GpuFeatureInfo> gpu_feature_info_for_hardware_gpu_;
+  std::optional<GPUInfo> gpu_info_for_hardware_gpu_;
+  std::optional<GpuFeatureInfo> gpu_feature_info_for_hardware_gpu_;
 
   gfx::GpuExtraInfo gpu_extra_info_;
 
   // The following data are collected by the info collection GPU process.
-  absl::optional<DevicePerfInfo> device_perf_info_;
+  std::optional<DevicePerfInfo> device_perf_info_;
 
 #if BUILDFLAG(ENABLE_VULKAN)
   std::unique_ptr<VulkanImplementation> vulkan_implementation_;
diff --git a/gpu/ipc/service/gpu_watchdog_thread_unittest.cc b/gpu/ipc/service/gpu_watchdog_thread_unittest.cc
index f9a861cb..08888ce 100644
--- a/gpu/ipc/service/gpu_watchdog_thread_unittest.cc
+++ b/gpu/ipc/service/gpu_watchdog_thread_unittest.cc
@@ -137,7 +137,7 @@
   } else {
     // Check Mac machine model version.
     std::string model_str = base::SysInfo::HardwareModelName();
-    absl::optional<base::SysInfo::HardwareModelNameSplit> split =
+    std::optional<base::SysInfo::HardwareModelNameSplit> split =
         base::SysInfo::SplitHardwareModelNameDoNotUse(model_str);
 
     if (split && split.value().category == "MacBookPro" &&
diff --git a/gpu/ipc/service/image_decode_accelerator_stub.cc b/gpu/ipc/service/image_decode_accelerator_stub.cc
index bc847e8b..d3d70cb0 100644
--- a/gpu/ipc/service/image_decode_accelerator_stub.cc
+++ b/gpu/ipc/service/image_decode_accelerator_stub.cc
@@ -11,6 +11,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/feature_list.h"
 #include "base/functional/bind.h"
@@ -44,7 +45,6 @@
 #include "gpu/ipc/service/gpu_channel.h"
 #include "gpu/ipc/service/gpu_channel_manager.h"
 #include "gpu/ipc/service/shared_image_stub.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColorSpace.h"
 #include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkImageInfo.h"
@@ -226,7 +226,7 @@
   }
 
   std::vector<sk_sp<SkImage>> plane_sk_images;
-  absl::optional<base::ScopedClosureRunner> notify_gl_state_changed;
+  std::optional<base::ScopedClosureRunner> notify_gl_state_changed;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // Right now, we only support YUV 4:2:0 for the output of the decoder (either
   // as YV12 or NV12).
@@ -383,7 +383,7 @@
 
   {
     auto* gr_shader_cache = channel_->gpu_channel_manager()->gr_shader_cache();
-    absl::optional<raster::GrShaderCache::ScopedCacheUse> cache_use;
+    std::optional<raster::GrShaderCache::ScopedCacheUse> cache_use;
     if (gr_shader_cache)
       cache_use.emplace(gr_shader_cache,
                         base::strict_cast<int32_t>(channel_->client_id()));
diff --git a/gpu/vulkan/tests/vulkan_test.cc b/gpu/vulkan/tests/vulkan_test.cc
index 123bc04..b7030cfb 100644
--- a/gpu/vulkan/tests/vulkan_test.cc
+++ b/gpu/vulkan/tests/vulkan_test.cc
@@ -4,6 +4,7 @@
 
 #include <memory>
 
+#include <optional>
 #include "gpu/vulkan/tests/basic_vulkan_test.h"
 #include "gpu/vulkan/vulkan_command_buffer.h"
 #include "gpu/vulkan/vulkan_command_pool.h"
@@ -11,7 +12,6 @@
 #include "gpu/vulkan/vulkan_surface.h"
 #include "gpu/vulkan/vulkan_swap_chain.h"
 #include "gpu/vulkan/vulkan_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // This file tests basic vulkan initialization steps.
 
@@ -45,7 +45,7 @@
 
   constexpr VkSemaphore kNullSemaphore = VK_NULL_HANDLE;
 
-  absl::optional<VulkanSwapChain::ScopedWrite> scoped_write;
+  std::optional<VulkanSwapChain::ScopedWrite> scoped_write;
   scoped_write.emplace(surface->swap_chain());
   EXPECT_TRUE(scoped_write->success());
 
diff --git a/gpu/vulkan/vulkan_image.cc b/gpu/vulkan/vulkan_image.cc
index a0a6dc4..b9a09c5 100644
--- a/gpu/vulkan/vulkan_image.cc
+++ b/gpu/vulkan/vulkan_image.cc
@@ -8,13 +8,13 @@
 
 #include <algorithm>
 
+#include <optional>
 #include "base/logging.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "gpu/vulkan/vulkan_device_queue.h"
 #include "gpu/vulkan/vulkan_function_pointers.h"
 #include "gpu/vulkan/vulkan_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace gpu {
 namespace {
@@ -100,7 +100,7 @@
     VkImageTiling image_tiling,
     VkDeviceSize device_size,
     uint32_t memory_type_index,
-    absl::optional<VulkanYCbCrInfo>& ycbcr_info,
+    std::optional<VulkanYCbCrInfo>& ycbcr_info,
     VkImageUsageFlags usage,
     VkImageCreateFlags flags) {
   auto image = std::make_unique<VulkanImage>(base::PassKey<VulkanImage>());
diff --git a/gpu/vulkan/vulkan_image.h b/gpu/vulkan/vulkan_image.h
index de511af8..631a18691 100644
--- a/gpu/vulkan/vulkan_image.h
+++ b/gpu/vulkan/vulkan_image.h
@@ -10,6 +10,7 @@
 #include <array>
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/files/scoped_file.h"
 #include "base/memory/raw_ptr.h"
@@ -17,7 +18,6 @@
 #include "build/build_config.h"
 #include "gpu/ipc/common/vulkan_ycbcr_info.h"
 #include "gpu/vulkan/vulkan_memory.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/gpu_memory_buffer.h"
 #include "ui/gfx/native_pixmap.h"
@@ -83,7 +83,7 @@
       VkImageTiling image_tiling,
       VkDeviceSize device_size,
       uint32_t memory_type_index,
-      absl::optional<VulkanYCbCrInfo>& ycbcr_info,
+      std::optional<VulkanYCbCrInfo>& ycbcr_info,
       VkImageUsageFlags usage,
       VkImageCreateFlags flags);
 
@@ -137,7 +137,7 @@
   VkImageTiling image_tiling() const { return create_info_.tiling; }
   uint32_t queue_family_index() const { return queue_family_index_; }
   void set_queue_family_index(uint32_t index) { queue_family_index_ = index; }
-  const absl::optional<VulkanYCbCrInfo>& ycbcr_info() const {
+  const std::optional<VulkanYCbCrInfo>& ycbcr_info() const {
     return ycbcr_info_;
   }
   VkImage image() const { return image_; }
@@ -213,7 +213,7 @@
   // Image has multi planes and planes are not joint.
   bool disjoint_planes_ = false;
   uint32_t queue_family_index_ = VK_QUEUE_FAMILY_IGNORED;
-  absl::optional<VulkanYCbCrInfo> ycbcr_info_;
+  std::optional<VulkanYCbCrInfo> ycbcr_info_;
   VkImage image_ = VK_NULL_HANDLE;
   // Device memory for each plane.
   std::array<std::unique_ptr<VulkanMemory>, 4> memories_;
diff --git a/gpu/vulkan/vulkan_memory.cc b/gpu/vulkan/vulkan_memory.cc
index 62ed777..785d09da 100644
--- a/gpu/vulkan/vulkan_memory.cc
+++ b/gpu/vulkan/vulkan_memory.cc
@@ -6,16 +6,16 @@
 
 #include <vulkan/vulkan.h>
 
+#include <optional>
 #include "base/logging.h"
 #include "build/build_config.h"
 #include "gpu/vulkan/vulkan_device_queue.h"
 #include "gpu/vulkan/vulkan_function_pointers.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace gpu {
 namespace {
 
-absl::optional<uint32_t> FindMemoryTypeIndex(
+std::optional<uint32_t> FindMemoryTypeIndex(
     VkPhysicalDevice physical_device,
     const VkMemoryRequirements* requirements,
     VkMemoryPropertyFlags flags) {
@@ -32,7 +32,7 @@
     return i;
   }
   NOTREACHED();
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 }  // namespace
diff --git a/gpu/vulkan/vulkan_swap_chain.h b/gpu/vulkan/vulkan_swap_chain.h
index b61d4ca..e957476 100644
--- a/gpu/vulkan/vulkan_swap_chain.h
+++ b/gpu/vulkan/vulkan_swap_chain.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/containers/circular_deque.h"
 #include "base/functional/callback.h"
@@ -20,7 +21,6 @@
 #include "base/synchronization/lock.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/threading/thread_checker.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/swap_result.h"
@@ -191,7 +191,7 @@
   VkResult state_ GUARDED_BY(lock_) = VK_SUCCESS;
 
   // Acquired images queue.
-  absl::optional<uint32_t> acquired_image_ GUARDED_BY(lock_);
+  std::optional<uint32_t> acquired_image_ GUARDED_BY(lock_);
 
   bool destroy_swapchain_will_hang_ = false;
 
diff --git a/headless/lib/browser/devtools_api/client_api_generator.py b/headless/lib/browser/devtools_api/client_api_generator.py
index 394a96b..f7c91f8 100644
--- a/headless/lib/browser/devtools_api/client_api_generator.py
+++ b/headless/lib/browser/devtools_api/client_api_generator.py
@@ -153,12 +153,12 @@
 
 def CreateObjectTypeDefinition():
   return {
-      'return_type': 'absl::optional<base::Value::Dict>',
-      'pass_type': 'absl::optional<base::Value::Dict>',
+      'return_type': 'std::optional<base::Value::Dict>',
+      'pass_type': 'std::optional<base::Value::Dict>',
       'to_raw_type': '*%s',
       'to_raw_return_type': '*%s',
       'to_pass_type': 'std::move(%s)',
-      'type': 'absl::optional<base::Value::Dict>',
+      'type': 'std::optional<base::Value::Dict>',
       'raw_type': 'base::Value::Dict',
       'raw_pass_type': 'base::Value::Dict*',
       'raw_return_type': 'const base::Value::Dict&',
diff --git a/headless/lib/browser/headless_browser_context_options.cc b/headless/lib/browser/headless_browser_context_options.cc
index 5e4193a..8f56b16 100644
--- a/headless/lib/browser/headless_browser_context_options.cc
+++ b/headless/lib/browser/headless_browser_context_options.cc
@@ -12,7 +12,7 @@
 namespace {
 
 template <class T>
-const T& ReturnOverriddenValue(const absl::optional<T>& value,
+const T& ReturnOverriddenValue(const std::optional<T>& value,
                                const T& default_value) {
   return value ? *value : default_value;
 }
diff --git a/headless/lib/browser/headless_browser_context_options.h b/headless/lib/browser/headless_browser_context_options.h
index 43fbfde3..a9509f04 100644
--- a/headless/lib/browser/headless_browser_context_options.h
+++ b/headless/lib/browser/headless_browser_context_options.h
@@ -7,10 +7,10 @@
 
 #include <string>
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/memory/raw_ptr.h"
 #include "headless/public/headless_browser.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/font_render_params.h"
 
 namespace headless {
@@ -61,16 +61,16 @@
 
   raw_ptr<HeadlessBrowser::Options> browser_options_;
 
-  absl::optional<std::string> accept_language_;
-  absl::optional<std::string> user_agent_;
+  std::optional<std::string> accept_language_;
+  std::optional<std::string> user_agent_;
   std::unique_ptr<net::ProxyConfig> proxy_config_;
-  absl::optional<gfx::Size> window_size_;
-  absl::optional<base::FilePath> user_data_dir_;
-  absl::optional<base::FilePath> disk_cache_dir_;
-  absl::optional<bool> incognito_mode_;
-  absl::optional<bool> block_new_web_contents_;
+  std::optional<gfx::Size> window_size_;
+  std::optional<base::FilePath> user_data_dir_;
+  std::optional<base::FilePath> disk_cache_dir_;
+  std::optional<bool> incognito_mode_;
+  std::optional<bool> block_new_web_contents_;
 
-  absl::optional<gfx::FontRenderParams::Hinting> font_render_hinting_;
+  std::optional<gfx::FontRenderParams::Hinting> font_render_hinting_;
 };
 
 }  // namespace headless
diff --git a/headless/lib/browser/headless_browser_impl.cc b/headless/lib/browser/headless_browser_impl.cc
index 2663278..695ef05c 100644
--- a/headless/lib/browser/headless_browser_impl.cc
+++ b/headless/lib/browser/headless_browser_impl.cc
@@ -177,12 +177,12 @@
 
   // Rengenerate the brand version lists with kHeadlessProductName.
   metadata.brand_version_list = embedder_support::GenerateBrandVersionList(
-      seed, kHeadlessProductName, significant_version, absl::nullopt,
-      absl::nullopt, kEnableUpdatedGreaseByPolicy,
+      seed, kHeadlessProductName, significant_version, std::nullopt,
+      std::nullopt, kEnableUpdatedGreaseByPolicy,
       blink::UserAgentBrandVersionType::kMajorVersion);
   metadata.brand_full_version_list = embedder_support::GenerateBrandVersionList(
-      seed, kHeadlessProductName, metadata.full_version, absl::nullopt,
-      absl::nullopt, kEnableUpdatedGreaseByPolicy,
+      seed, kHeadlessProductName, metadata.full_version, std::nullopt,
+      std::nullopt, kEnableUpdatedGreaseByPolicy,
       blink::UserAgentBrandVersionType::kFullVersion);
   return metadata;
 }
diff --git a/headless/lib/browser/headless_browser_impl.h b/headless/lib/browser/headless_browser_impl.h
index 6932f1e5..196933f 100644
--- a/headless/lib/browser/headless_browser_impl.h
+++ b/headless/lib/browser/headless_browser_impl.h
@@ -132,7 +132,7 @@
 #endif
 
   base::OnceCallback<void(HeadlessBrowser*)> on_start_callback_;
-  absl::optional<HeadlessBrowser::Options> options_;
+  std::optional<HeadlessBrowser::Options> options_;
 
   int exit_code_ = 0;
 
diff --git a/headless/lib/browser/headless_content_browser_client.cc b/headless/lib/browser/headless_content_browser_client.cc
index 8d5fc50..db6c42d 100644
--- a/headless/lib/browser/headless_content_browser_client.cc
+++ b/headless/lib/browser/headless_content_browser_client.cc
@@ -345,7 +345,7 @@
 
 #if BUILDFLAG(IS_WIN)
 void HeadlessContentBrowserClient::SessionEnding(
-    absl::optional<DWORD> control_type) {
+    std::optional<DWORD> control_type) {
   DCHECK_LT(control_type.value_or(0), 0x7fu);
   browser_->ShutdownWithExitCode(control_type.value_or(0) + 0x80u);
 }
diff --git a/headless/lib/browser/headless_content_browser_client.h b/headless/lib/browser/headless_content_browser_client.h
index dfdef1bd..18f90a11 100644
--- a/headless/lib/browser/headless_content_browser_client.h
+++ b/headless/lib/browser/headless_content_browser_client.h
@@ -95,7 +95,7 @@
   bool CanAcceptUntrustedExchangesIfNeeded() override;
   device::GeolocationManager* GetGeolocationManager() override;
 #if BUILDFLAG(IS_WIN)
-  void SessionEnding(absl::optional<DWORD> control_type) override;
+  void SessionEnding(std::optional<DWORD> control_type) override;
 #endif
 
 #if defined(HEADLESS_USE_POLICY)
diff --git a/headless/lib/browser/headless_window_tree_host.cc b/headless/lib/browser/headless_window_tree_host.cc
index 6ced9c9..fe7614e 100644
--- a/headless/lib/browser/headless_window_tree_host.cc
+++ b/headless/lib/browser/headless_window_tree_host.cc
@@ -79,7 +79,7 @@
 void HeadlessWindowTreeHost::ReleaseCapture() {}
 
 bool HeadlessWindowTreeHost::CaptureSystemKeyEventsImpl(
-    absl::optional<base::flat_set<ui::DomCode>> codes) {
+    std::optional<base::flat_set<ui::DomCode>> codes) {
   return false;
 }
 
diff --git a/headless/lib/browser/headless_window_tree_host.h b/headless/lib/browser/headless_window_tree_host.h
index 6903afc..5096ce6 100644
--- a/headless/lib/browser/headless_window_tree_host.h
+++ b/headless/lib/browser/headless_window_tree_host.h
@@ -53,7 +53,7 @@
   void SetCapture() override;
   void ReleaseCapture() override;
   bool CaptureSystemKeyEventsImpl(
-      absl::optional<base::flat_set<ui::DomCode>> codes) override;
+      std::optional<base::flat_set<ui::DomCode>> codes) override;
   void ReleaseSystemKeyEventCapture() override;
   bool IsKeyLocked(ui::DomCode dom_code) override;
   base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
diff --git a/headless/lib/browser/protocol/page_handler.cc b/headless/lib/browser/protocol/page_handler.cc
index 1951561..5e8f6969 100644
--- a/headless/lib/browser/protocol/page_handler.cc
+++ b/headless/lib/browser/protocol/page_handler.cc
@@ -8,8 +8,8 @@
 #include "content/public/browser/web_contents.h"
 
 #if BUILDFLAG(ENABLE_PRINTING)
+#include <optional>
 #include "components/printing/browser/print_to_pdf/pdf_print_utils.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #endif
 
 namespace headless {
@@ -17,8 +17,8 @@
 
 #if BUILDFLAG(ENABLE_PRINTING)
 template <typename T>
-absl::optional<T> OptionalFromMaybe(const Maybe<T>& maybe) {
-  return maybe.has_value() ? absl::optional<T>(maybe.value()) : absl::nullopt;
+std::optional<T> OptionalFromMaybe(const Maybe<T>& maybe) {
+  return maybe.has_value() ? std::optional<T>(maybe.value()) : std::nullopt;
 }
 #endif
 
diff --git a/headless/lib/headless_content_main_delegate.cc b/headless/lib/headless_content_main_delegate.cc
index c607d36..f36b434 100644
--- a/headless/lib/headless_content_main_delegate.cc
+++ b/headless/lib/headless_content_main_delegate.cc
@@ -188,7 +188,7 @@
   g_current_headless_content_main_delegate = nullptr;
 }
 
-absl::optional<int> HeadlessContentMainDelegate::BasicStartupComplete() {
+std::optional<int> HeadlessContentMainDelegate::BasicStartupComplete() {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
 
   // The DevTools remote debugging pipe file descriptors need to be checked
@@ -240,7 +240,7 @@
 #endif
 
   content::Profiling::ProcessStarted();
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 void HeadlessContentMainDelegate::InitLogging(
@@ -462,7 +462,7 @@
   return g_current_headless_content_main_delegate;
 }
 
-absl::optional<int> HeadlessContentMainDelegate::PreBrowserMain() {
+std::optional<int> HeadlessContentMainDelegate::PreBrowserMain() {
   HeadlessBrowser::Options::Builder builder;
 
   if (!HandleCommandLineSwitches(*base::CommandLine::ForCurrentProcess(),
@@ -479,7 +479,7 @@
 #if BUILDFLAG(IS_MAC)
   PlatformPreBrowserMain();
 #endif
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 #if BUILDFLAG(IS_WIN)
@@ -514,10 +514,10 @@
   return utility_client_.get();
 }
 
-absl::optional<int> HeadlessContentMainDelegate::PostEarlyInitialization(
+std::optional<int> HeadlessContentMainDelegate::PostEarlyInitialization(
     InvokedIn invoked_in) {
   if (absl::holds_alternative<InvokedInChildProcess>(invoked_in))
-    return absl::nullopt;
+    return std::nullopt;
 
   if (base::FeatureList::IsEnabled(features::kVirtualTime)) {
     // Only pass viz flags into the virtual time mode.
@@ -543,7 +543,7 @@
       base::CommandLine::ForCurrentProcess()->AppendSwitch(flag);
   }
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 }  // namespace headless
diff --git a/headless/lib/headless_content_main_delegate.h b/headless/lib/headless_content_main_delegate.h
index 2ba42481..ccaf7a3 100644
--- a/headless/lib/headless_content_main_delegate.h
+++ b/headless/lib/headless_content_main_delegate.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "build/build_config.h"
 #include "content/public/app/content_main_delegate.h"
 #include "content/public/browser/content_browser_client.h"
@@ -15,7 +16,6 @@
 #include "headless/lib/headless_content_client.h"
 #include "headless/public/headless_browser.h"
 #include "headless/public/headless_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class CommandLine;
@@ -40,12 +40,12 @@
 
  private:
   // content::ContentMainDelegate implementation:
-  absl::optional<int> BasicStartupComplete() override;
+  std::optional<int> BasicStartupComplete() override;
   void PreSandboxStartup() override;
   absl::variant<int, content::MainFunctionParams> RunProcess(
       const std::string& process_type,
       content::MainFunctionParams main_function_params) override;
-  absl::optional<int> PreBrowserMain() override;
+  std::optional<int> PreBrowserMain() override;
 #if BUILDFLAG(IS_WIN)
   bool ShouldHandleConsoleControlEvents() override;
 #endif
@@ -54,7 +54,7 @@
   content::ContentUtilityClient* CreateContentUtilityClient() override;
   content::ContentRendererClient* CreateContentRendererClient() override;
 
-  absl::optional<int> PostEarlyInitialization(InvokedIn invoked_in) override;
+  std::optional<int> PostEarlyInitialization(InvokedIn invoked_in) override;
 #if BUILDFLAG(IS_MAC)
   void PlatformPreBrowserMain();
 #endif
diff --git a/headless/public/internal/value_conversions.h b/headless/public/internal/value_conversions.h
index 1da0bcc4..48d0401 100644
--- a/headless/public/internal/value_conversions.h
+++ b/headless/public/internal/value_conversions.h
@@ -127,11 +127,11 @@
 
 template <>
 struct FromValue<base::Value::Dict> {
-  static absl::optional<base::Value::Dict> Parse(const base::Value& value,
-                                                 ErrorReporter* errors) {
+  static std::optional<base::Value::Dict> Parse(const base::Value& value,
+                                                ErrorReporter* errors) {
     if (!value.is_dict()) {
       errors->AddError("dictionary value expected");
-      return absl::nullopt;
+      return std::nullopt;
     }
     return value.GetDict().Clone();
   }
diff --git a/headless/test/headless_browser_test_utils.cc b/headless/test/headless_browser_test_utils.cc
index 11b102e..6f6a2c3a 100644
--- a/headless/test/headless_browser_test_utils.cc
+++ b/headless/test/headless_browser_test_utils.cc
@@ -4,6 +4,7 @@
 
 #include "headless/test/headless_browser_test_utils.h"
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/json/json_writer.h"
 #include "base/logging.h"
@@ -15,7 +16,6 @@
 #include "headless/lib/browser/headless_web_contents_impl.h"
 #include "headless/public/headless_web_contents.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 using simple_devtools_protocol_client::SimpleDevToolsProtocolClient;
 
@@ -100,14 +100,14 @@
 }
 
 int DictInt(const base::Value::Dict& dict, base::StringPiece path) {
-  absl::optional<int> result = dict.FindIntByDottedPath(path);
+  std::optional<int> result = dict.FindIntByDottedPath(path);
   CHECK(result) << "Missing value for '" << path << "' in:\n"
                 << dict.DebugString();
   return *result;
 }
 
 bool DictBool(const base::Value::Dict& dict, base::StringPiece path) {
-  absl::optional<bool> result = dict.FindBoolByDottedPath(path);
+  std::optional<bool> result = dict.FindBoolByDottedPath(path);
   CHECK(result) << "Missing value for '" << path << "' in:\n"
                 << dict.DebugString();
   return *result;
diff --git a/headless/test/headless_browser_user_agent_metadata_browsertest.cc b/headless/test/headless_browser_user_agent_metadata_browsertest.cc
index 1bf2b034..f243cc1 100644
--- a/headless/test/headless_browser_user_agent_metadata_browsertest.cc
+++ b/headless/test/headless_browser_user_agent_metadata_browsertest.cc
@@ -289,7 +289,7 @@
 
   bool IsRequestHeaderSet(
       const std::string header,
-      const absl::optional<std::string> value = absl::nullopt) {
+      const std::optional<std::string> value = std::nullopt) {
     if (!got_headers_.contains(header)) {
       return false;
     }
diff --git a/headless/test/headless_command_browsertest.cc b/headless/test/headless_command_browsertest.cc
index abf0c83..cadf888 100644
--- a/headless/test/headless_command_browsertest.cc
+++ b/headless/test/headless_command_browsertest.cc
@@ -5,6 +5,7 @@
 #include <cmath>
 #include <string>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/containers/cxx20_erase.h"
 #include "base/files/file_path.h"
@@ -36,7 +37,6 @@
 #include "pdf/buildflags.h"
 #include "printing/buildflags/buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/display/display_switches.h"
@@ -116,7 +116,7 @@
 
   void set_aborted() { aborted_ = true; }
 
-  absl::optional<HeadlessCommandHandler::Result> result() const {
+  std::optional<HeadlessCommandHandler::Result> result() const {
     return result_;
   }
 
@@ -129,7 +129,7 @@
   }
 
   bool aborted_ = false;
-  absl::optional<HeadlessCommandHandler::Result> result_;
+  std::optional<HeadlessCommandHandler::Result> result_;
 };
 
 class HeadlessFileCommandBrowserTest : public HeadlessCommandBrowserTest {
diff --git a/headless/test/headless_devtools_client_browsertest.cc b/headless/test/headless_devtools_client_browsertest.cc
index 6d953e5..f33a753 100644
--- a/headless/test/headless_devtools_client_browsertest.cc
+++ b/headless/test/headless_devtools_client_browsertest.cc
@@ -590,14 +590,16 @@
 
       // Golden file expects scrollOffsetXY to have fractional part.
       // TODO(kvitekp): Consider updating golden files.
-      if (absl::optional<double> x = node_dict.FindDouble("scrollOffsetX"))
+      if (std::optional<double> x = node_dict.FindDouble("scrollOffsetX")) {
         node_dict.Set("scrollOffsetX", *x);
+      }
 
-      if (absl::optional<double> y = node_dict.FindDouble("scrollOffsetY"))
+      if (std::optional<double> y = node_dict.FindDouble("scrollOffsetY")) {
         node_dict.Set("scrollOffsetY", *y);
+      }
 
       // Merge LayoutTreeNode data into the dom_node dictionary.
-      if (absl::optional<int> layout_node_index =
+      if (std::optional<int> layout_node_index =
               node_dict.FindInt("layoutNodeIndex")) {
         ASSERT_LE(0, *layout_node_index);
         ASSERT_GT(layout_tree_nodes_list->size(),
@@ -617,7 +619,7 @@
           node_dict.Set("layoutText", *layout_text);
         }
 
-        if (absl::optional<int> style_index =
+        if (std::optional<int> style_index =
                 layout_tree_node.FindInt("styleIndex")) {
           node_dict.Set("styleIndex", *style_index);
         }
diff --git a/headless/test/headless_printtopdf_browsertest.cc b/headless/test/headless_printtopdf_browsertest.cc
index b37e5476..8a21ae4 100644
--- a/headless/test/headless_printtopdf_browsertest.cc
+++ b/headless/test/headless_printtopdf_browsertest.cc
@@ -6,6 +6,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/base64.h"
 #include "base/command_line.h"
 #include "base/functional/bind.h"
@@ -28,7 +29,6 @@
 #include "printing/units.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/inspector_protocol/crdtp/dispatch.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size_conversions.h"
@@ -96,7 +96,7 @@
         .render_device_type = chrome_pdf::RenderDeviceType::kPrinter,
     };
     for (int i = 0; i < num_pages; i++) {
-      absl::optional<gfx::SizeF> size_in_points =
+      std::optional<gfx::SizeF> size_in_points =
           chrome_pdf::GetPDFPageSizeByIndex(pdf_span, i);
       ASSERT_TRUE(size_in_points.has_value());
       EXPECT_EQ(static_cast<int>(size_in_points.value().width()),
@@ -198,7 +198,7 @@
     EXPECT_TRUE(chrome_pdf::GetPDFDocInfo(pdf_span, &num_pages, nullptr));
     EXPECT_EQ(std::ceil(kDocHeight / kPaperHeight), num_pages);
 
-    absl::optional<bool> tagged = chrome_pdf::IsPDFDocTagged(pdf_span);
+    std::optional<bool> tagged = chrome_pdf::IsPDFDocTagged(pdf_span);
     ASSERT_TRUE(tagged.has_value());
     EXPECT_FALSE(tagged.value());
 
@@ -236,7 +236,7 @@
   }
 
   void OnPDFCreated(base::Value::Dict result) {
-    absl::optional<int> error_code = result.FindIntByDottedPath("error.code");
+    std::optional<int> error_code = result.FindIntByDottedPath("error.code");
     const std::string* error_message =
         result.FindStringByDottedPath("error.message");
     ASSERT_EQ(error_code.has_value(), !!error_message);
@@ -654,7 +654,7 @@
   void OnPDFReady(base::span<const uint8_t> pdf_span, int num_pages) override {
     EXPECT_THAT(num_pages, testing::Eq(1));
 
-    absl::optional<bool> tagged = chrome_pdf::IsPDFDocTagged(pdf_span);
+    std::optional<bool> tagged = chrome_pdf::IsPDFDocTagged(pdf_span);
     ASSERT_THAT(tagged, testing::Optional(true));
 
     constexpr int kFirstPage = 0;
@@ -690,7 +690,7 @@
   void OnPDFReady(base::span<const uint8_t> pdf_span, int num_pages) override {
     EXPECT_THAT(num_pages, testing::Eq(1));
 
-    absl::optional<bool> tagged = chrome_pdf::IsPDFDocTagged(pdf_span);
+    std::optional<bool> tagged = chrome_pdf::IsPDFDocTagged(pdf_span);
     EXPECT_THAT(tagged, testing::Optional(false));
   }
 };
@@ -718,7 +718,7 @@
   void OnPDFReady(base::span<const uint8_t> pdf_span, int num_pages) override {
     EXPECT_THAT(num_pages, testing::Eq(1));
 
-    absl::optional<bool> is_pdf_tagged = chrome_pdf::IsPDFDocTagged(pdf_span);
+    std::optional<bool> is_pdf_tagged = chrome_pdf::IsPDFDocTagged(pdf_span);
     EXPECT_THAT(is_pdf_tagged, testing::Optional(generate_tagged_pdf()));
   }
 };
diff --git a/headless/test/headless_web_contents_browsertest.cc b/headless/test/headless_web_contents_browsertest.cc
index 10ccaf3b..4156f4e0 100644
--- a/headless/test/headless_web_contents_browsertest.cc
+++ b/headless/test/headless_web_contents_browsertest.cc
@@ -6,6 +6,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/base64.h"
 #include "base/check_op.h"
 #include "base/command_line.h"
@@ -31,7 +32,6 @@
 #include "headless/test/test_network_interceptor.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/switches.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
diff --git a/headless/test/test_network_interceptor.cc b/headless/test/test_network_interceptor.cc
index 46c4a28..4e2e50e 100644
--- a/headless/test/test_network_interceptor.cc
+++ b/headless/test/test_network_interceptor.cc
@@ -44,7 +44,7 @@
       const std::vector<std::string>& removed_headers,
       const net::HttpRequestHeaders& modified_headers,
       const net::HttpRequestHeaders& modified_cors_exempt_headers,
-      const absl::optional<GURL>& new_url) override;
+      const std::optional<GURL>& new_url) override;
 
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
@@ -132,7 +132,7 @@
     const std::vector<std::string>& removed_headers /* unused */,
     const net::HttpRequestHeaders& modified_headers /* unused */,
     const net::HttpRequestHeaders& modified_cors_exempt_headers /* unused */,
-    const absl::optional<GURL>& new_url) {
+    const std::optional<GURL>& new_url) {
   response_ = interceptor_impl_->FindResponse(method_, url_.spec());
   CHECK(response_) << "No content for " << url_.spec();
   std::string location;
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl
index 7021c96..82b9733 100644
--- a/infra/config/generated/testing/variants.pyl
+++ b/infra/config/generated/testing/variants.pyl
@@ -472,7 +472,7 @@
     'identifier': 'BRYA_RELEASE_DEV',
     'skylab': {
       'cros_board': 'brya',
-      'cros_img': 'brya-release/R120-15662.4.0',
+      'cros_img': 'brya-release/R120-15662.9.0',
       'dut_pool': 'chrome',
     },
   },
@@ -503,7 +503,7 @@
     'identifier': 'DEDEDE_RELEASE_DEV',
     'skylab': {
       'cros_board': 'dedede',
-      'cros_img': 'dedede-release/R120-15656.0.0',
+      'cros_img': 'dedede-release/R120-15662.9.0',
     },
   },
   'CROS_DEDEDE_RELEASE_BETA': {
@@ -532,7 +532,7 @@
     'identifier': 'FIZZ_RELEASE_DEV',
     'skylab': {
       'cros_board': 'fizz',
-      'cros_img': 'fizz-release/R120-15662.4.0',
+      'cros_img': 'fizz-release/R120-15662.9.0',
       'dut_pool': 'chrome',
     },
   },
@@ -564,7 +564,7 @@
     'identifier': 'GUYBRUSH_RELEASE_DEV',
     'skylab': {
       'cros_board': 'guybrush',
-      'cros_img': 'guybrush-release/R120-15662.4.0',
+      'cros_img': 'guybrush-release/R120-15662.9.0',
       'dut_pool': 'chrome',
     },
   },
@@ -596,7 +596,7 @@
     'identifier': 'PUFF_RELEASE_DEV',
     'skylab': {
       'cros_board': 'puff',
-      'cros_img': 'puff-release/R120-15662.4.0',
+      'cros_img': 'puff-release/R120-15662.9.0',
       'dut_pool': 'chrome',
     },
   },
@@ -638,7 +638,7 @@
     'identifier': 'HANA_RELEASE_DEV',
     'skylab': {
       'cros_board': 'hana',
-      'cros_img': 'hana-release/R120-15662.4.0',
+      'cros_img': 'hana-release/R120-15662.9.0',
     },
   },
   'CROS_HANA_RELEASE_BETA': {
@@ -666,7 +666,7 @@
     'identifier': 'JACUZZI_RELEASE_DEV',
     'skylab': {
       'cros_board': 'jacuzzi',
-      'cros_img': 'jacuzzi-release/R120-15662.4.0',
+      'cros_img': 'jacuzzi-release/R120-15662.9.0',
     },
   },
   'CROS_JACUZZI_RELEASE_BETA': {
@@ -742,7 +742,7 @@
     'identifier': 'OCTOPUS_RELEASE_DEV',
     'skylab': {
       'cros_board': 'octopus',
-      'cros_img': 'octopus-release/R120-15662.4.0',
+      'cros_img': 'octopus-release/R120-15662.9.0',
     },
   },
   'CROS_OCTOPUS_RELEASE_BETA': {
@@ -770,7 +770,7 @@
     'identifier': 'strongbad_RELEASE_DEV',
     'skylab': {
       'cros_board': 'strongbad',
-      'cros_img': 'strongbad-release/R120-15662.4.0',
+      'cros_img': 'strongbad-release/R120-15662.9.0',
     },
   },
   'CROS_STRONGBAD_RELEASE_BETA': {
diff --git a/infra/config/targets/cros-skylab-variants.json b/infra/config/targets/cros-skylab-variants.json
index 7510ca9..b1b04342 100644
--- a/infra/config/targets/cros-skylab-variants.json
+++ b/infra/config/targets/cros-skylab-variants.json
@@ -19,8 +19,8 @@
   "CROS_BRYA_RELEASE_DEV": {
     "skylab": {
       "cros_board": "brya",
-      "cros_chrome_version": "120.0.6099.8",
-      "cros_img": "brya-release/R120-15662.4.0",
+      "cros_chrome_version": "120.0.6099.13",
+      "cros_img": "brya-release/R120-15662.9.0",
       "dut_pool": "chrome"
     },
     "enabled": true,
@@ -57,8 +57,8 @@
   "CROS_DEDEDE_RELEASE_DEV": {
     "skylab": {
       "cros_board": "dedede",
-      "cros_chrome_version": "120.0.6085.0",
-      "cros_img": "dedede-release/R120-15656.0.0"
+      "cros_chrome_version": "120.0.6099.13",
+      "cros_img": "dedede-release/R120-15662.9.0"
     },
     "enabled": true,
     "identifier": "DEDEDE_RELEASE_DEV"
@@ -93,8 +93,8 @@
   "CROS_FIZZ_RELEASE_DEV": {
     "skylab": {
       "cros_board": "fizz",
-      "cros_chrome_version": "120.0.6099.8",
-      "cros_img": "fizz-release/R120-15662.4.0",
+      "cros_chrome_version": "120.0.6099.13",
+      "cros_img": "fizz-release/R120-15662.9.0",
       "dut_pool": "chrome"
     },
     "enabled": true,
@@ -132,8 +132,8 @@
   "CROS_GUYBRUSH_RELEASE_DEV": {
     "skylab": {
       "cros_board": "guybrush",
-      "cros_chrome_version": "120.0.6099.8",
-      "cros_img": "guybrush-release/R120-15662.4.0",
+      "cros_chrome_version": "120.0.6099.13",
+      "cros_img": "guybrush-release/R120-15662.9.0",
       "dut_pool": "chrome"
     },
     "enabled": true,
@@ -171,8 +171,8 @@
   "CROS_PUFF_RELEASE_DEV": {
     "skylab": {
       "cros_board": "puff",
-      "cros_chrome_version": "120.0.6099.8",
-      "cros_img": "puff-release/R120-15662.4.0",
+      "cros_chrome_version": "120.0.6099.13",
+      "cros_img": "puff-release/R120-15662.9.0",
       "dut_pool": "chrome"
     },
     "enabled": true,
@@ -222,8 +222,8 @@
   "CROS_HANA_RELEASE_DEV": {
     "skylab": {
       "cros_board": "hana",
-      "cros_chrome_version": "120.0.6099.8",
-      "cros_img": "hana-release/R120-15662.4.0"
+      "cros_chrome_version": "120.0.6099.13",
+      "cros_img": "hana-release/R120-15662.9.0"
     },
     "enabled": true,
     "identifier": "HANA_RELEASE_DEV"
@@ -257,8 +257,8 @@
   "CROS_JACUZZI_RELEASE_DEV": {
     "skylab": {
       "cros_board": "jacuzzi",
-      "cros_chrome_version": "120.0.6099.8",
-      "cros_img": "jacuzzi-release/R120-15662.4.0"
+      "cros_chrome_version": "120.0.6099.13",
+      "cros_img": "jacuzzi-release/R120-15662.9.0"
     },
     "enabled": true,
     "identifier": "JACUZZI_RELEASE_DEV"
@@ -348,8 +348,8 @@
   "CROS_OCTOPUS_RELEASE_DEV": {
     "skylab": {
       "cros_board": "octopus",
-      "cros_chrome_version": "120.0.6099.8",
-      "cros_img": "octopus-release/R120-15662.4.0"
+      "cros_chrome_version": "120.0.6099.13",
+      "cros_img": "octopus-release/R120-15662.9.0"
     },
     "enabled": true,
     "identifier": "OCTOPUS_RELEASE_DEV"
@@ -383,8 +383,8 @@
   "CROS_STRONGBAD_RELEASE_DEV": {
     "skylab": {
       "cros_board": "strongbad",
-      "cros_chrome_version": "120.0.6099.8",
-      "cros_img": "strongbad-release/R120-15662.4.0"
+      "cros_chrome_version": "120.0.6099.13",
+      "cros_img": "strongbad-release/R120-15662.9.0"
     },
     "enabled": true,
     "identifier": "strongbad_RELEASE_DEV"
diff --git a/internal b/internal
index 5a39204..8c572c9 160000
--- a/internal
+++ b/internal
@@ -1 +1 @@
-Subproject commit 5a392040dbeaedc5f2cfabe8ac08793c446f8d6c
+Subproject commit 8c572c92ad2038d9a0488d55599a138ab24941eb
diff --git a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.mm b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.mm
index ee80c9ed..1af8733 100644
--- a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.mm
+++ b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.mm
@@ -8,8 +8,8 @@
 #import "base/timer/timer.h"
 #import "components/password_manager/core/browser/affiliation/affiliation_utils.h"
 #import "components/password_manager/core/browser/password_form.h"
-#import "components/password_manager/core/browser/password_store_consumer.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "ios/chrome/browser/autofill/manual_fill/password_list_sorter.h"
 #import "ios/chrome/browser/passwords/model/password_store_observer_bridge.h"
 #import "ios/chrome/browser/passwords/model/save_passwords_consumer.h"
diff --git a/ios/chrome/browser/browsing_data/model/browsing_data_counter_wrapper.cc b/ios/chrome/browser/browsing_data/model/browsing_data_counter_wrapper.cc
index 99a0c7a..2548d1e 100644
--- a/ios/chrome/browser/browsing_data/model/browsing_data_counter_wrapper.cc
+++ b/ios/chrome/browser/browsing_data/model/browsing_data_counter_wrapper.cc
@@ -13,7 +13,7 @@
 #include "components/browsing_data/core/counters/passwords_counter.h"
 #include "components/browsing_data/core/pref_names.h"
 #include "components/keyed_service/core/service_access_type.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/prefs/pref_service.h"
 #include "components/sync/service/sync_service.h"
 #include "ios/chrome/browser/browsing_data/model/browsing_data_features.h"
diff --git a/ios/chrome/browser/browsing_data/model/browsing_data_remover_impl.mm b/ios/chrome/browser/browsing_data/model/browsing_data_remover_impl.mm
index 94dd6675..49ae099a 100644
--- a/ios/chrome/browser/browsing_data/model/browsing_data_remover_impl.mm
+++ b/ios/chrome/browser/browsing_data/model/browsing_data_remover_impl.mm
@@ -28,7 +28,7 @@
 #import "components/language/core/browser/url_language_histogram.h"
 #import "components/omnibox/browser/omnibox_prefs.h"
 #import "components/open_from_clipboard/clipboard_recent_content.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "components/prefs/pref_service.h"
 #import "components/search_engines/template_url_service.h"
 #import "components/sessions/core/tab_restore_service.h"
diff --git a/ios/chrome/browser/credential_provider/model/credential_provider_migrator.h b/ios/chrome/browser/credential_provider/model/credential_provider_migrator.h
index 5b71d29..7ead2c4 100644
--- a/ios/chrome/browser/credential_provider/model/credential_provider_migrator.h
+++ b/ios/chrome/browser/credential_provider/model/credential_provider_migrator.h
@@ -7,7 +7,7 @@
 
 #import <Foundation/Foundation.h>
 
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 @interface CredentialProviderMigrator : NSObject
 - (instancetype)
diff --git a/ios/chrome/browser/credential_provider/model/credential_provider_migrator.mm b/ios/chrome/browser/credential_provider/model/credential_provider_migrator.mm
index b9f28a2..8acbabc 100644
--- a/ios/chrome/browser/credential_provider/model/credential_provider_migrator.mm
+++ b/ios/chrome/browser/credential_provider/model/credential_provider_migrator.mm
@@ -5,7 +5,7 @@
 #import "ios/chrome/browser/credential_provider/model/credential_provider_migrator.h"
 
 #import "components/password_manager/core/browser/password_form.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "ios/chrome/browser/credential_provider/model/archivable_credential+password_form.h"
 #import "ios/chrome/common/credential_provider/user_defaults_credential_store.h"
 
diff --git a/ios/chrome/browser/credential_provider/model/credential_provider_service.h b/ios/chrome/browser/credential_provider/model/credential_provider_service.h
index 00df895..fd3fb69 100644
--- a/ios/chrome/browser/credential_provider/model/credential_provider_service.h
+++ b/ios/chrome/browser/credential_provider/model/credential_provider_service.h
@@ -9,9 +9,9 @@
 #include "base/memory/ref_counted.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_store_backend_error.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_backend_error.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/prefs/pref_member.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/sync/service/sync_service_observer.h"
diff --git a/ios/chrome/browser/credential_provider/model/credential_provider_service.mm b/ios/chrome/browser/credential_provider/model/credential_provider_service.mm
index 2494885..bc0f079c 100644
--- a/ios/chrome/browser/credential_provider/model/credential_provider_service.mm
+++ b/ios/chrome/browser/credential_provider/model/credential_provider_service.mm
@@ -16,9 +16,9 @@
 #import "components/password_manager/core/browser/affiliation/affiliation_service.h"
 #import "components/password_manager/core/browser/affiliation/affiliation_utils.h"
 #import "components/password_manager/core/browser/password_manager_util.h"
-#import "components/password_manager/core/browser/password_store_change.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
-#import "components/password_manager/core/browser/password_store_util.h"
+#import "components/password_manager/core/browser/password_store/password_store_change.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_util.h"
 #import "components/password_manager/core/browser/password_sync_util.h"
 #import "components/password_manager/core/common/password_manager_features.h"
 #import "components/password_manager/core/common/password_manager_pref_names.h"
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index dca2df7..91ce947 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -501,6 +501,8 @@
     {kTabPickupThresholdParameterName, kTabPickupThresholdOneHourParam}};
 const FeatureEntry::FeatureParam kTabPickupThresholdTwoHours[] = {
     {kTabPickupThresholdParameterName, kTabPickupThresholdTwoHoursParam}};
+const FeatureEntry::FeatureParam kTabPickupNoFavicon[] = {
+    {kTabPickupThresholdParameterName, kTabPickupNoFaviconParam}};
 
 const FeatureEntry::FeatureVariation kTabPickupThresholdVariations[] = {
     {"Ten Minutes", kTabPickupThresholdTenMinutes,
@@ -509,6 +511,8 @@
      std::size(kTabPickupThresholdOneHour), nullptr},
     {"Two Hours", kTabPickupThresholdTwoHours,
      std::size(kTabPickupThresholdTwoHours), nullptr},
+    {"No favicon", kTabPickupNoFavicon, std::size(kTabPickupNoFavicon),
+     nullptr},
 };
 
 const FeatureEntry::FeatureParam kTabResumptionMostRecentTabOnly[] = {
@@ -1627,7 +1631,9 @@
      flag_descriptions::kSetUpListContentNotificationName,
      flag_descriptions::kSetUpListContentNotificationDescription,
      flags_ui::kOsIos, FEATURE_VALUE_TYPE(kSetUpListContentNotification)},
-
+    {"fullscreen-improvement", flag_descriptions::kFullscreenImprovementName,
+     flag_descriptions::kFullscreenImprovementDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(kFullscreenImprovement)},
 };
 
 bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 699eb5e..131e5804 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -484,6 +484,10 @@
     "When enabled, the startup sign-in promo is always displayed when starting "
     "Chrome.";
 
+const char kFullscreenImprovementName[] = "Improve fullscreen";
+const char kFullscreenImprovementDescription[] =
+    "When enabled, fullscreen should have a better stability.";
+
 const char kFullScreenPromoOnOmniboxCopyPasteName[] =
     "Trigger Default Browser full-screen promo on omnibox copy-paste";
 const char kFullScreenPromoOnOmniboxCopyPasteDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 5610dfb..1ec713e 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -411,6 +411,11 @@
 extern const char kForceStartupSigninPromoName[];
 extern const char kForceStartupSigninPromoDescription[];
 
+// Title and description for the flag to trigger improvement for fullscreen
+// feature.
+extern const char kFullscreenImprovementName[];
+extern const char kFullscreenImprovementDescription[];
+
 // Title and description for the flag to enable default browser full-screen
 // promo on omnibox copy-paste.
 extern const char kFullScreenPromoOnOmniboxCopyPasteName[];
diff --git a/ios/chrome/browser/history/model/BUILD.gn b/ios/chrome/browser/history/model/BUILD.gn
new file mode 100644
index 0000000..8a52c8a
--- /dev/null
+++ b/ios/chrome/browser/history/model/BUILD.gn
@@ -0,0 +1,8 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("model") {
+  sources = [ "history_service_factory.h" ]
+  public_deps = [ "//ios/chrome/browser/history" ]
+}
diff --git a/ios/chrome/browser/history/model/history_service_factory.h b/ios/chrome/browser/history/model/history_service_factory.h
new file mode 100644
index 0000000..0a548a2
--- /dev/null
+++ b/ios/chrome/browser/history/model/history_service_factory.h
@@ -0,0 +1,10 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_HISTORY_MODEL_HISTORY_SERVICE_FACTORY_H_
+#define IOS_CHROME_BROWSER_HISTORY_MODEL_HISTORY_SERVICE_FACTORY_H_
+
+#import "ios/chrome/browser/history/history_service_factory.h"
+
+#endif  // IOS_CHROME_BROWSER_HISTORY_MODEL_HISTORY_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/passwords/model/ios_chrome_password_receiver_service_factory.mm b/ios/chrome/browser/passwords/model/ios_chrome_password_receiver_service_factory.mm
index 36381b8..598f73e 100644
--- a/ios/chrome/browser/passwords/model/ios_chrome_password_receiver_service_factory.mm
+++ b/ios/chrome/browser/passwords/model/ios_chrome_password_receiver_service_factory.mm
@@ -12,7 +12,7 @@
 #import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
 #import "components/password_manager/core/browser/features/password_features.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "components/password_manager/core/browser/sharing/incoming_password_sharing_invitation_sync_bridge.h"
 #import "components/password_manager/core/browser/sharing/password_receiver_service_impl.h"
 #import "components/sync/base/model_type.h"
diff --git a/ios/chrome/browser/passwords/model/ios_chrome_password_reuse_manager_factory.cc b/ios/chrome/browser/passwords/model/ios_chrome_password_reuse_manager_factory.cc
index bd2a451..179ec91 100644
--- a/ios/chrome/browser/passwords/model/ios_chrome_password_reuse_manager_factory.cc
+++ b/ios/chrome/browser/passwords/model/ios_chrome_password_reuse_manager_factory.cc
@@ -9,7 +9,7 @@
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/keyed_service/ios/browser_state_dependency_manager.h"
 #include "components/password_manager/core/browser/password_reuse_manager_impl.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "ios/chrome/browser/passwords/model/ios_chrome_account_password_store_factory.h"
 #include "ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h"
diff --git a/ios/chrome/browser/passwords/model/ios_password_store_utils.mm b/ios/chrome/browser/passwords/model/ios_password_store_utils.mm
index 8d64c245..3387871 100644
--- a/ios/chrome/browser/passwords/model/ios_password_store_utils.mm
+++ b/ios/chrome/browser/passwords/model/ios_password_store_utils.mm
@@ -11,7 +11,7 @@
 #import "base/task/sequenced_task_runner.h"
 #import "components/keyed_service/core/service_access_type.h"
 #import "components/password_manager/core/browser/password_manager_util.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "components/password_manager/core/browser/store_metrics_reporter.h"
 #import "ios/chrome/browser/passwords/model/ios_chrome_account_password_store_factory.h"
 #import "ios/chrome/browser/passwords/model/ios_chrome_password_reuse_manager_factory.h"
diff --git a/ios/chrome/browser/passwords/model/password_controller_unittest.mm b/ios/chrome/browser/passwords/model/password_controller_unittest.mm
index 1450a14..5919726 100644
--- a/ios/chrome/browser/passwords/model/password_controller_unittest.mm
+++ b/ios/chrome/browser/passwords/model/password_controller_unittest.mm
@@ -33,7 +33,7 @@
 #import "components/password_manager/core/browser/password_form_manager.h"
 #import "components/password_manager/core/browser/password_form_metrics_recorder.h"
 #import "components/password_manager/core/browser/password_manager.h"
-#import "components/password_manager/core/browser/password_store_consumer.h"
+#import "components/password_manager/core/browser/password_store/password_store_consumer.h"
 #import "components/password_manager/core/browser/stub_password_manager_client.h"
 #import "components/password_manager/core/common/password_manager_features.h"
 #import "components/password_manager/core/common/password_manager_pref_names.h"
diff --git a/ios/chrome/browser/passwords/model/password_manager_app_interface.mm b/ios/chrome/browser/passwords/model/password_manager_app_interface.mm
index ab4d490..d3894f1 100644
--- a/ios/chrome/browser/passwords/model/password_manager_app_interface.mm
+++ b/ios/chrome/browser/passwords/model/password_manager_app_interface.mm
@@ -9,8 +9,8 @@
 #import "base/test/ios/wait_util.h"
 #import "components/keyed_service/core/service_access_type.h"
 #import "components/password_manager/core/browser/password_form.h"
-#import "components/password_manager/core/browser/password_store_consumer.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "components/password_manager/core/common/password_manager_pref_names.h"
 #import "components/prefs/pref_service.h"
 #import "ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h"
diff --git a/ios/chrome/browser/passwords/model/password_store_observer_bridge.h b/ios/chrome/browser/passwords/model/password_store_observer_bridge.h
index 4ec877e..0b77b08 100644
--- a/ios/chrome/browser/passwords/model/password_store_observer_bridge.h
+++ b/ios/chrome/browser/passwords/model/password_store_observer_bridge.h
@@ -7,7 +7,7 @@
 
 #import <Foundation/Foundation.h>
 
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 
 // Protocol to observe changes on the Password Store.
 @protocol PasswordStoreObserver <NSObject>
diff --git a/ios/chrome/browser/passwords/model/save_passwords_consumer.h b/ios/chrome/browser/passwords/model/save_passwords_consumer.h
index d059a58..4d7b56e 100644
--- a/ios/chrome/browser/passwords/model/save_passwords_consumer.h
+++ b/ios/chrome/browser/passwords/model/save_passwords_consumer.h
@@ -10,7 +10,7 @@
 #include <memory>
 #include <vector>
 
-#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
 
 @protocol SavePasswordsConsumerDelegate
 
diff --git a/ios/chrome/browser/providers/signin/chromium_choice.mm b/ios/chrome/browser/providers/signin/chromium_choice.mm
index b75a788..60bf9d71 100644
--- a/ios/chrome/browser/providers/signin/chromium_choice.mm
+++ b/ios/chrome/browser/providers/signin/chromium_choice.mm
@@ -25,19 +25,10 @@
   NOTREACHED_NORETURN();
 }
 
-id<StandardPromoDisplayHandler> CreateChoiceDisplayHandler(
-    ChromeBrowserState* browserState) {
-  NOTREACHED_NORETURN();
-}
-
 id<StandardPromoDisplayHandler> CreateChoiceDisplayHandler() {
   NOTREACHED_NORETURN();
 }
 
-id<SceneAgent> CreateChoiceSceneAgent(PromosManager* promosManager) {
-  NOTREACHED_NORETURN();
-}
-
 id<SceneAgent> CreateChoiceSceneAgent(PromosManager* promosManager,
                                       ChromeBrowserState* browserState) {
   NOTREACHED_NORETURN();
diff --git a/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service.h b/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service.h
index 506d4b3..0c1315f1 100644
--- a/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service.h
+++ b/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service.h
@@ -14,7 +14,7 @@
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/password_manager/core/browser/insecure_credentials_helper.h"
 #include "components/password_manager/core/browser/password_reuse_detector.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/safe_browsing/core/browser/password_protection/metrics_util.h"
 #include "components/safe_browsing/core/common/proto/csd.pb.h"
 #import "components/safe_browsing/ios/browser/password_protection/password_protection_service.h"
diff --git a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
index 2f1b9f4..4ec6fe4 100644
--- a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
+++ b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
@@ -1005,7 +1005,8 @@
                            initWithPromosManager:promosManager]];
 
   if (ios::provider::IsChoiceEnabled()) {
-    [sceneState addAgent:ios::provider::CreateChoiceSceneAgent(promosManager)];
+    [sceneState addAgent:ios::provider::CreateChoiceSceneAgent(promosManager,
+                                                               browserState)];
   }
 
   // Do not gate by feature flag so it can run for enabled -> disabled
diff --git a/ios/chrome/browser/shared/public/features/features.h b/ios/chrome/browser/shared/public/features/features.h
index 4476051..a027661d 100644
--- a/ios/chrome/browser/shared/public/features/features.h
+++ b/ios/chrome/browser/shared/public/features/features.h
@@ -309,6 +309,9 @@
 // Engine choice.
 BASE_DECLARE_FEATURE(kIOSHideFeedWithSearchChoice);
 
+// Feature flag to enable a more stable fullscreen.
+BASE_DECLARE_FEATURE(kFullscreenImprovement);
+
 // Feature param under `kEnableFeedBackgroundRefresh` to also enable background
 // refresh for the Following feed.
 extern const char kEnableFollowingFeedBackgroundRefresh[];
diff --git a/ios/chrome/browser/shared/public/features/features.mm b/ios/chrome/browser/shared/public/features/features.mm
index 744e91d..ce8fa2bf 100644
--- a/ios/chrome/browser/shared/public/features/features.mm
+++ b/ios/chrome/browser/shared/public/features/features.mm
@@ -360,6 +360,10 @@
              "IOSHideFeedWithSearchChoice",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kFullscreenImprovement,
+             "FullscreenImprovement",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // Key for NSUserDefaults containing a bool indicating whether the next run
 // should enable feed background refresh capability. This is used because
 // registering for background refreshes must happen early in app initialization
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.h b/ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.h
index a46a0a4..c19ea16 100644
--- a/ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.h
+++ b/ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.h
@@ -24,8 +24,12 @@
 // The switch view.
 @property(nonatomic, readonly, strong) UISwitch* switchView;
 
-// Returns the default text color used for the given `state`.
-+ (UIColor*)defaultTextColorForState:(UIControlState)state;
+// Configures the cell with its `title`, `subtitle` and whether the switch is
+// `enabled` and `on`.
+- (void)configureCellWithTitle:(NSString*)title
+                      subtitle:(NSString*)subtitle
+                 switchEnabled:(BOOL)enabled
+                            on:(BOOL)on;
 
 // Sets the `image` that should be displayed at the leading edge of the cell
 // with a `tintColor`. If set to nil, the icon will be hidden and the text
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.mm b/ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.mm
index 5d04599..8b67742 100644
--- a/ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.mm
+++ b/ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.mm
@@ -176,10 +176,21 @@
   return self;
 }
 
-+ (UIColor*)defaultTextColorForState:(UIControlState)state {
-  return (state & UIControlStateDisabled)
-             ? [UIColor colorNamed:kTextSecondaryColor]
-             : [UIColor colorNamed:kTextPrimaryColor];
+- (void)configureCellWithTitle:(NSString*)title
+                      subtitle:(NSString*)subtitle
+                 switchEnabled:(BOOL)enabled
+                            on:(BOOL)on {
+  self.textLabel.text = title;
+  self.detailTextLabel.text = subtitle;
+  self.switchView.enabled = enabled;
+  self.switchView.on = on;
+  self.switchView.accessibilityIdentifier =
+      [NSString stringWithFormat:@"%@, switch", title];
+
+  UIColor* textColor = enabled ? [UIColor colorNamed:kTextPrimaryColor]
+                               : [UIColor colorNamed:kTextSecondaryColor];
+  self.textLabel.textColor = textColor;
+  self.selectionStyle = UITableViewCellSelectionStyleNone;
 }
 
 - (void)setIconImage:(UIImage*)image
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_item.mm b/ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_item.mm
index 01949afa..1a2d657 100644
--- a/ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_item.mm
+++ b/ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_item.mm
@@ -22,15 +22,10 @@
 - (void)configureCell:(TableViewSwitchCell*)cell
            withStyler:(ChromeTableViewStyler*)styler {
   [super configureCell:cell withStyler:styler];
-  cell.textLabel.text = self.text;
-  cell.detailTextLabel.text = self.detailText;
-  cell.switchView.enabled = self.enabled;
-  cell.switchView.on = self.on;
-  cell.switchView.accessibilityIdentifier =
-      [NSString stringWithFormat:@"%@, %@", self.text, @"switch"];
-  cell.textLabel.textColor =
-      [TableViewSwitchCell defaultTextColorForState:cell.switchView.state];
-  cell.selectionStyle = UITableViewCellSelectionStyleNone;
+  [cell configureCellWithTitle:self.text
+                      subtitle:self.detailText
+                 switchEnabled:self.enabled
+                            on:self.on];
 
   [cell setIconImage:self.iconImage
             tintColor:self.iconTintColor
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/table_view_text_header_footer_item.h b/ios/chrome/browser/shared/ui/table_view/cells/table_view_text_header_footer_item.h
index dc7fd41..0fd86fc 100644
--- a/ios/chrome/browser/shared/ui/table_view/cells/table_view_text_header_footer_item.h
+++ b/ios/chrome/browser/shared/ui/table_view/cells/table_view_text_header_footer_item.h
@@ -48,22 +48,22 @@
 // title, above the link text.
 @interface TableViewTextHeaderFooterView : UITableViewHeaderFooterView
 
-// The UILabel containing the text stored in `text`.
-@property(nonatomic, readonly, strong) UILabel* textLabel;
-
-// UITextView corresponding to `subtitle` from the item.
-@property(nonatomic, readonly, strong) UITextView* subtitleLabel;
-
 // Delegate to notify when the link is tapped.
 @property(nonatomic, weak) id<TableViewTextHeaderFooterItemDelegate> delegate;
 
 // The URLs to open when text with a link attribute is tapped.
 @property(nonatomic, strong) NSArray<CrURL*>* URLs;
 
-// Sets the `text` displayed by this cell. If the `text` contains a link, the
-// link is appropriately colored.
+// Sets the `title` displayed by this cell.
+- (void)setTitle:(NSString*)title;
+
+// Sets the `subtitle` displayed by this cell with a default coloring.
 - (void)setSubtitle:(NSString*)subtitle;
 
+// Sets the `subtitle` displayed by this cell with a `color`. If the `subtitle`
+// contains a link, the link has its own color.
+- (void)setSubtitle:(NSString*)subtitle withColor:(UIColor*)color;
+
 // If forceIndents is YES, activates the constraint to align the header/footer
 // with section items.
 - (void)setForceIndents:(BOOL)forceIndents;
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/table_view_text_header_footer_item.mm b/ios/chrome/browser/shared/ui/table_view/cells/table_view_text_header_footer_item.mm
index fec5a70..5e1afde4 100644
--- a/ios/chrome/browser/shared/ui/table_view/cells/table_view_text_header_footer_item.mm
+++ b/ios/chrome/browser/shared/ui/table_view/cells/table_view_text_header_footer_item.mm
@@ -56,9 +56,7 @@
   }
 
   [headerFooter setSubtitle:self.subtitle];
-  headerFooter.textLabel.text = self.text;
-  headerFooter.textLabel.accessibilityTraits = UIAccessibilityTraitHeader;
-  headerFooter.isAccessibilityElement = NO;
+  [headerFooter setTitle:self.text];
 }
 
 @end
@@ -68,6 +66,9 @@
 // UITextView corresponding to `subtitle` from the item.
 @property(nonatomic, readonly, strong) UITextView* subtitleView;
 
+// The UILabel containing the text stored in `text`.
+@property(nonatomic, readonly, strong) UILabel* textLabel;
+
 @end
 
 @implementation TableViewTextHeaderFooterView {
@@ -82,6 +83,8 @@
 - (instancetype)initWithReuseIdentifier:(NSString*)reuseIdentifier {
   self = [super initWithReuseIdentifier:reuseIdentifier];
   if (self) {
+    self.isAccessibilityElement = NO;
+
     _URLs = @[];
     _subtitleView = CreateUITextViewWithTextKit1();
     _subtitleView.scrollEnabled = NO;
@@ -97,11 +100,13 @@
     _subtitleView.textAlignment = NSTextAlignmentLeft;
     _subtitleView.textContainer.lineFragmentPadding = 0;
     _subtitleView.textContainerInset = UIEdgeInsetsZero;
+    _subtitleView.hidden = YES;
 
     // Labels, set font sizes using dynamic type.
     _textLabel = [[UILabel alloc] init];
     _textLabel.font =
         [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
+    _textLabel.accessibilityTraits = UIAccessibilityTraitHeader;
 
     // Vertical StackView.
     UIStackView* verticalStack = [[UIStackView alloc]
@@ -169,7 +174,8 @@
 
 - (void)prepareForReuse {
   [super prepareForReuse];
-  self.subtitleView.text = nil;
+  [self setTitle:nil];
+  [self setSubtitle:nil];
   self.delegate = nil;
   self.URLs = @[];
   self.forceIndents = NO;
@@ -177,7 +183,15 @@
 
 #pragma mark - Properties
 
+- (void)setTitle:(NSString*)title {
+  self.textLabel.text = title;
+}
+
 - (void)setSubtitle:(NSString*)subtitle {
+  [self setSubtitle:subtitle withColor:nil];
+}
+
+- (void)setSubtitle:(NSString*)subtitle withColor:(UIColor*)color {
   if (!subtitle) {
     // If no subtitle, hide the subtitle view to avoid taking space for nothing.
     self.subtitleView.hidden = YES;
@@ -188,10 +202,12 @@
 
   StringWithTags parsedString = ParseStringWithLinks(subtitle);
 
+  UIColor* textColor = color ? color : [UIColor colorNamed:kTextSecondaryColor];
+
   NSDictionary* textAttributes = @{
     NSFontAttributeName :
         [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote],
-    NSForegroundColorAttributeName : [UIColor colorNamed:kTextSecondaryColor]
+    NSForegroundColorAttributeName : textColor
   };
 
   NSMutableAttributedString* attributedText =
diff --git a/ios/chrome/browser/sync/model/ios_chrome_sync_client.mm b/ios/chrome/browser/sync/model/ios_chrome_sync_client.mm
index 575f0ea..2d3b89c 100644
--- a/ios/chrome/browser/sync/model/ios_chrome_sync_client.mm
+++ b/ios/chrome/browser/sync/model/ios_chrome_sync_client.mm
@@ -23,7 +23,7 @@
 #import "components/history/core/browser/history_service.h"
 #import "components/keyed_service/core/service_access_type.h"
 #import "components/metrics/demographics/user_demographics.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "components/password_manager/core/browser/sharing/password_receiver_service.h"
 #import "components/password_manager/core/browser/sharing/password_sender_service.h"
 #import "components/reading_list/core/dual_reading_list_model.h"
diff --git a/ios/chrome/browser/tabs/model/tab_pickup/features.h b/ios/chrome/browser/tabs/model/tab_pickup/features.h
index cadb3b2..8279491 100644
--- a/ios/chrome/browser/tabs/model/tab_pickup/features.h
+++ b/ios/chrome/browser/tabs/model/tab_pickup/features.h
@@ -25,6 +25,7 @@
 extern const char kTabPickupThresholdTenMinutesParam[];
 extern const char kTabPickupThresholdOneHourParam[];
 extern const char kTabPickupThresholdTwoHoursParam[];
+extern const char kTabPickupNoFaviconParam[];
 
 // Convenience method for determining if the tab pickup feature is available.
 bool IsTabPickupEnabled();
@@ -37,6 +38,10 @@
 // disabled by the user.
 bool IsTabPickupDisabledByUser();
 
+// Convenience method for determining if the tab pickup favicon should be
+// displayed.
+bool IsTabPickupFaviconAvaible();
+
 // Convenience method for determining the tab pickup threshold.
 // The default is 10 minutes.
 const base::TimeDelta TabPickupTimeThreshold();
diff --git a/ios/chrome/browser/tabs/model/tab_pickup/features.mm b/ios/chrome/browser/tabs/model/tab_pickup/features.mm
index f21977f..fa03db85 100644
--- a/ios/chrome/browser/tabs/model/tab_pickup/features.mm
+++ b/ios/chrome/browser/tabs/model/tab_pickup/features.mm
@@ -25,6 +25,7 @@
 const char kTabPickupThresholdOneHourParam[] = "tab-pickup-threshold-one-hour";
 const char kTabPickupThresholdTwoHoursParam[] =
     "tab-pickup-threshold-two-hours";
+const char kTabPickupNoFaviconParam[] = "tab-pickup-no-favicon";
 
 bool IsTabPickupEnabled() {
   return base::FeatureList::IsEnabled(kTabPickupThreshold);
@@ -53,3 +54,9 @@
   return !GetApplicationContext()->GetLocalState()->GetBoolean(
       prefs::kTabPickupEnabled);
 }
+
+bool IsTabPickupFaviconAvaible() {
+  std::string feature_param = base::GetFieldTrialParamValueByFeature(
+      kTabPickupThreshold, kTabPickupThresholdParameterName);
+  return feature_param != kTabPickupNoFaviconParam;
+}
diff --git a/ios/chrome/browser/tabs/model/tab_pickup/tab_pickup_browser_agent.mm b/ios/chrome/browser/tabs/model/tab_pickup/tab_pickup_browser_agent.mm
index dd3ad996..4fd4a05 100644
--- a/ios/chrome/browser/tabs/model/tab_pickup/tab_pickup_browser_agent.mm
+++ b/ios/chrome/browser/tabs/model/tab_pickup/tab_pickup_browser_agent.mm
@@ -145,6 +145,9 @@
   auto const synced_sessions =
       std::make_unique<synced_sessions::SyncedSessions>(session_sync_service_);
 
+  if (!IsTabPickupFaviconAvaible()) {
+    CheckDistantTabsOrder(synced_sessions.get());
+  }
   LastActiveDistantTab last_active_tab =
       GetLastActiveDistantTab(synced_sessions.get(), TabPickupTimeThreshold());
   if (last_active_tab.tab) {
diff --git a/ios/chrome/browser/tabs/model/tab_pickup/tab_pickup_infobar_delegate.mm b/ios/chrome/browser/tabs/model/tab_pickup/tab_pickup_infobar_delegate.mm
index c0827f4..fc07409 100644
--- a/ios/chrome/browser/tabs/model/tab_pickup/tab_pickup_infobar_delegate.mm
+++ b/ios/chrome/browser/tabs/model/tab_pickup/tab_pickup_infobar_delegate.mm
@@ -49,6 +49,10 @@
 
 void TabPickupInfobarDelegate::FetchFavIconImage(
     ProceduralBlock block_handler) {
+  if (!IsTabPickupFaviconAvaible()) {
+    block_handler();
+    return;
+  }
   favicon_loader_->FaviconForPageUrl(
       tab_url_, kDesiredSmallFaviconSizePt, kMinFaviconSizePt,
       /*fallback_to_google_server=*/true, ^(FaviconAttributes* attributes) {
diff --git a/ios/chrome/browser/tabs/model/tab_sync_util.h b/ios/chrome/browser/tabs/model/tab_sync_util.h
index 7b8405f..7f75ffd 100644
--- a/ios/chrome/browser/tabs/model/tab_sync_util.h
+++ b/ios/chrome/browser/tabs/model/tab_sync_util.h
@@ -27,6 +27,9 @@
   const raw_ptr<const synced_sessions::DistantSession> session;
 };
 
+// Checks that distant sessions and tabs are sorted by their `modified_time`.
+void CheckDistantTabsOrder(synced_sessions::SyncedSessions* synced_sessions);
+
 // Returns the latest active tab that was used below the given `time_threshold`.
 LastActiveDistantTab GetLastActiveDistantTab(
     synced_sessions::SyncedSessions* synced_sessions,
diff --git a/ios/chrome/browser/tabs/model/tab_sync_util.mm b/ios/chrome/browser/tabs/model/tab_sync_util.mm
index c0e525f..e61f6104 100644
--- a/ios/chrome/browser/tabs/model/tab_sync_util.mm
+++ b/ios/chrome/browser/tabs/model/tab_sync_util.mm
@@ -19,6 +19,25 @@
 
 }  // namespace
 
+void CheckDistantTabsOrder(synced_sessions::SyncedSessions* synced_sessions) {
+  base::Time previous_session_modified_time = base::Time::Now();
+  for (size_t session_index = 0;
+       session_index < synced_sessions->GetSessionCount(); ++session_index) {
+    const synced_sessions::DistantSession* session =
+        synced_sessions->GetSession(session_index);
+    CHECK(previous_session_modified_time >= session->modified_time);
+    previous_session_modified_time = session->modified_time;
+
+    base::Time previous_modified_time = base::Time::Now();
+
+    for (const auto& distant_tab : session->tabs) {
+      CHECK(previous_modified_time >= distant_tab->modified_time);
+      CHECK(distant_tab->modified_time >= distant_tab->last_active_time);
+      previous_modified_time = distant_tab->modified_time;
+    }
+  }
+}
+
 LastActiveDistantTab GetLastActiveDistantTab(
     synced_sessions::SyncedSessions* synced_sessions,
     base::TimeDelta delta_threshold) {
diff --git a/ios/chrome/browser/ui/autofill/autofill_app_interface.mm b/ios/chrome/browser/ui/autofill/autofill_app_interface.mm
index 75c578c..3829166 100644
--- a/ios/chrome/browser/ui/autofill/autofill_app_interface.mm
+++ b/ios/chrome/browser/ui/autofill/autofill_app_interface.mm
@@ -20,8 +20,8 @@
 #import "components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h"
 #import "components/autofill/ios/browser/ios_test_event_waiter.h"
 #import "components/keyed_service/core/service_access_type.h"
-#import "components/password_manager/core/browser/password_store_consumer.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "ios/chrome/browser/autofill/personal_data_manager_factory.h"
 #import "ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
diff --git a/ios/chrome/browser/ui/autofill/card_expiration_date_fix_flow_view_bridge.mm b/ios/chrome/browser/ui/autofill/card_expiration_date_fix_flow_view_bridge.mm
index 6cc4976..3f44d90 100644
--- a/ios/chrome/browser/ui/autofill/card_expiration_date_fix_flow_view_bridge.mm
+++ b/ios/chrome/browser/ui/autofill/card_expiration_date_fix_flow_view_bridge.mm
@@ -166,7 +166,6 @@
   textField.delegate = self;
 
   _footerView = [[TableViewTextHeaderFooterView alloc] init];
-  _footerView.subtitleLabel.textColor = [UIColor colorNamed:kRedColor];
 
   // Set initial value.
   [self didSelectMonth:_expirationDatePicker.month
@@ -255,11 +254,13 @@
   if ([_expirationDateYear intValue] < currentYear ||
       ([_expirationDateYear intValue] == currentYear &&
        [_expirationDateMonth intValue] < currentMonth)) {
-    _footerView.subtitleLabel.text = base::SysUTF16ToNSString(
-        _bridge->GetController()->GetInvalidDateError());
+    [_footerView
+        setSubtitle:base::SysUTF16ToNSString(
+                        _bridge->GetController()->GetInvalidDateError())
+          withColor:[UIColor colorNamed:kRedColor]];
     _confirmButton.enabled = NO;
   } else {
-    _footerView.subtitleLabel.text = nil;
+    [_footerView setSubtitle:nil];
     _confirmButton.enabled = YES;
   }
 }
diff --git a/ios/chrome/browser/ui/autofill/card_name_fix_flow_view_bridge.mm b/ios/chrome/browser/ui/autofill/card_name_fix_flow_view_bridge.mm
index 6ba0bc7a2..bb59bca 100644
--- a/ios/chrome/browser/ui/autofill/card_name_fix_flow_view_bridge.mm
+++ b/ios/chrome/browser/ui/autofill/card_name_fix_flow_view_bridge.mm
@@ -150,9 +150,7 @@
           : nil;
 
   _footerView = [[TableViewTextHeaderFooterView alloc] init];
-  _footerView.subtitleLabel.textColor =
-      [UIColor colorNamed:kTextSecondaryColor];
-  _footerView.subtitleLabel.text = inferredNameTooltipText;
+  [_footerView setSubtitle:inferredNameTooltipText];
 
   [self.tableView registerClass:[TableViewTextEditCell class]
          forCellReuseIdentifier:kCellReuseID];
@@ -240,7 +238,7 @@
                                           .whitespaceAndNewlineCharacterSet];
 
   // After an edit, refresh footer text to no longer include name tooltip.
-  _footerView.subtitleLabel.text = nil;
+  [_footerView setSubtitle:nil];
 
   _confirmedName = confirmedName;
   [self updateSaveButtonEnabledStatus];
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.h b/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.h
index 534a4fe9..bbd42e1 100644
--- a/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.h
+++ b/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.h
@@ -7,7 +7,7 @@
 
 #import <Foundation/Foundation.h>
 
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "components/prefs/pref_service.h"
 #import "ios/chrome/browser/autofill/form_input_navigator.h"
 #import "ios/chrome/browser/autofill/form_suggestion_client.h"
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_all_password_coordinator.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_all_password_coordinator.mm
index 9c2f9ba..d5c794f1 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_all_password_coordinator.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_all_password_coordinator.mm
@@ -6,7 +6,7 @@
 
 #import "base/ios/block_types.h"
 #import "components/keyed_service/core/service_access_type.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "ios/chrome/browser/favicon/favicon_loader.h"
 #import "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h"
 #import "ios/chrome/browser/net/crurl.h"
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_coordinator.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_coordinator.mm
index ba36ed8..9b5de94 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_coordinator.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_coordinator.mm
@@ -6,7 +6,7 @@
 
 #import "base/apple/foundation_util.h"
 #import "components/keyed_service/core/service_access_type.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "ios/chrome/browser/favicon/favicon_loader.h"
 #import "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h"
 #import "ios/chrome/browser/passwords/model/ios_chrome_account_password_store_factory.h"
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_mediator.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_mediator.mm
index 88a5a4ea..9a39dab2 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_mediator.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_mediator.mm
@@ -12,7 +12,7 @@
 #import "components/autofill/ios/form_util/form_activity_observer_bridge.h"
 #import "components/autofill/ios/form_util/form_activity_params.h"
 #import "components/password_manager/core/browser/password_manager_client.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "components/password_manager/core/common/password_manager_features.h"
 #import "components/sync/base/model_type.h"
 #import "components/sync/service/sync_service.h"
diff --git a/ios/chrome/browser/ui/bookmarks/home/BUILD.gn b/ios/chrome/browser/ui/bookmarks/home/BUILD.gn
index d4b6eb6..1fbc2f5 100644
--- a/ios/chrome/browser/ui/bookmarks/home/BUILD.gn
+++ b/ios/chrome/browser/ui/bookmarks/home/BUILD.gn
@@ -25,6 +25,7 @@
     "//ios/chrome/browser/favicon",
     "//ios/chrome/browser/intents:intents_donation_helper",
     "//ios/chrome/browser/metrics:metrics_internal",
+    "//ios/chrome/browser/net:crurl",
     "//ios/chrome/browser/policy:policy_util",
     "//ios/chrome/browser/shared/coordinator/alert",
     "//ios/chrome/browser/shared/coordinator/scene:scene_state_browser_agent",
diff --git a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.mm
index aac17c9..fbae9c8 100644
--- a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.mm
@@ -33,6 +33,7 @@
 #import "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h"
 #import "ios/chrome/browser/intents/intents_donation_helper.h"
 #import "ios/chrome/browser/metrics/new_tab_page_uma.h"
+#import "ios/chrome/browser/net/crurl.h"
 #import "ios/chrome/browser/policy/policy_util.h"
 #import "ios/chrome/browser/shared/coordinator/alert/action_sheet_coordinator.h"
 #import "ios/chrome/browser/shared/coordinator/alert/alert_coordinator.h"
@@ -678,10 +679,10 @@
   DCHECK_EQ(bookmarkNode->type(), BookmarkNode::URL);
   GURL nodeURL = bookmarkNode->url();
   // Record that this context menu was shown to the user.
-  RecordMenuShown(MenuScenarioHistogram::kBookmarkEntry);
+  RecordMenuShown(kMenuScenarioHistogramBookmarkEntry);
   BrowserActionFactory* actionFactory = [[BrowserActionFactory alloc]
       initWithBrowser:_browser.get()
-             scenario:MenuScenarioHistogram::kBookmarkEntry];
+             scenario:kMenuScenarioHistogramBookmarkEntry];
   NSMutableArray<UIMenuElement*>* menuElements = [[NSMutableArray alloc] init];
   __weak __typeof(self) weakSelf = self;
   // Add open URL menu item.
@@ -715,7 +716,9 @@
                 actionToOpenInNewWindowWithURL:nodeURL
                                 activityOrigin:WindowActivityBookmarksOrigin]];
   }
-  [menuElements addObject:[actionFactory actionToCopyURL:nodeURL]];
+  [menuElements
+      addObject:[actionFactory
+                    actionToCopyURL:[[CrURL alloc] initWithGURL:nodeURL]]];
   // Add edit menu item.
   UIAction* editAction = [actionFactory actionToEditWithBlock:^{
     __strong __typeof(weakSelf) strongSelf = weakSelf;
@@ -753,9 +756,9 @@
   DCHECK_EQ(folderNode, FindNodeByNodeReference(nodeReference));
   DCHECK_EQ(folderNode->type(), BookmarkNode::FOLDER);
   // Record that this context menu was shown to the user.
-  RecordMenuShown(MenuScenarioHistogram::kBookmarkFolder);
+  RecordMenuShown(kMenuScenarioHistogramBookmarkFolder);
   ActionFactory* actionFactory = [[ActionFactory alloc]
-      initWithScenario:MenuScenarioHistogram::kBookmarkFolder];
+      initWithScenario:kMenuScenarioHistogramBookmarkFolder];
   NSMutableArray<UIMenuElement*>* menuElements = [[NSMutableArray alloc] init];
   // Add edit menu item.
   __weak __typeof(self) weakSelf = self;
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
index 9858be4..381e550 100644
--- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -77,6 +77,7 @@
     "//ios/chrome/browser/favicon",
     "//ios/chrome/browser/intents:intents_donation_helper",
     "//ios/chrome/browser/metrics:metrics_internal",
+    "//ios/chrome/browser/net:crurl",
     "//ios/chrome/browser/ntp",
     "//ios/chrome/browser/ntp:set_up_list",
     "//ios/chrome/browser/ntp:set_up_list_item_type",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
index 257add2..a364b86 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -27,6 +27,7 @@
 #import "ios/chrome/browser/favicon/ios_chrome_large_icon_cache_factory.h"
 #import "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h"
 #import "ios/chrome/browser/favicon/large_icon_cache.h"
+#import "ios/chrome/browser/net/crurl.h"
 #import "ios/chrome/browser/ntp/new_tab_page_tab_helper.h"
 #import "ios/chrome/browser/ntp/set_up_list_item_type.h"
 #import "ios/chrome/browser/ntp/set_up_list_prefs.h"
@@ -481,11 +482,11 @@
         ContentSuggestionsCoordinator* strongSelf = weakSelf;
 
         // Record that this context menu was shown to the user.
-        RecordMenuShown(MenuScenarioHistogram::kMostVisitedEntry);
+        RecordMenuShown(kMenuScenarioHistogramMostVisitedEntry);
 
         BrowserActionFactory* actionFactory = [[BrowserActionFactory alloc]
             initWithBrowser:strongSelf.browser
-                   scenario:MenuScenarioHistogram::kMostVisitedEntry];
+                   scenario:kMenuScenarioHistogramMostVisitedEntry];
 
         NSMutableArray<UIMenuElement*>* menuElements =
             [[NSMutableArray alloc] init];
@@ -527,7 +528,8 @@
           [menuElements addObject:newWindowAction];
         }
 
-        [menuElements addObject:[actionFactory actionToCopyURL:item.URL]];
+        CrURL* URL = [[CrURL alloc] initWithGURL:item.URL];
+        [menuElements addObject:[actionFactory actionToCopyURL:URL]];
 
         [menuElements addObject:[actionFactory actionToShareWithBlock:^{
                         [weakSelf shareURL:item.URL
diff --git a/ios/chrome/browser/ui/context_menu/BUILD.gn b/ios/chrome/browser/ui/context_menu/BUILD.gn
index 9f4312a..4743303 100644
--- a/ios/chrome/browser/ui/context_menu/BUILD.gn
+++ b/ios/chrome/browser/ui/context_menu/BUILD.gn
@@ -14,6 +14,7 @@
     "//components/search_engines",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/favicon",
+    "//ios/chrome/browser/net:crurl",
     "//ios/chrome/browser/photos/model:metrics",
     "//ios/chrome/browser/photos/model:photos_availability",
     "//ios/chrome/browser/policy:policy_util",
diff --git a/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.mm b/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.mm
index 0cf4516..d619d22 100644
--- a/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.mm
+++ b/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.mm
@@ -11,6 +11,7 @@
 #import "components/search_engines/template_url_service.h"
 #import "ios/chrome/browser/favicon/favicon_loader.h"
 #import "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h"
+#import "ios/chrome/browser/net/crurl.h"
 #import "ios/chrome/browser/photos/model/photos_availability.h"
 #import "ios/chrome/browser/photos/model/photos_metrics.h"
 #import "ios/chrome/browser/policy/policy_util.h"
@@ -166,9 +167,9 @@
   NSMutableArray<UIMenuElement*>* menuElements = [[NSMutableArray alloc] init];
   // TODO(crbug.com/1299758) add scenario for not a link and not an image.
   MenuScenarioHistogram menuScenario =
-      isImage && isLink ? MenuScenarioHistogram::kContextMenuImageLink
-      : isImage         ? MenuScenarioHistogram::kContextMenuImage
-                        : MenuScenarioHistogram::kContextMenuLink;
+      isImage && isLink ? kMenuScenarioHistogramContextMenuImageLink
+      : isImage         ? kMenuScenarioHistogramContextMenuImage
+                        : kMenuScenarioHistogramContextMenuLink;
 
   BrowserActionFactory* actionFactory =
       [[BrowserActionFactory alloc] initWithBrowser:self.browser
@@ -241,7 +242,8 @@
     }
 
     // Copy Link.
-    UIAction* copyLink = [actionFactory actionToCopyURL:linkURL];
+    UIAction* copyLink =
+        [actionFactory actionToCopyURL:[[CrURL alloc] initWithGURL:linkURL]];
     [menuElements addObject:copyLink];
   }
 
diff --git a/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider_unittest.mm b/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider_unittest.mm
index 120c47a..62b488cc 100644
--- a/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider_unittest.mm
+++ b/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider_unittest.mm
@@ -33,7 +33,8 @@
 namespace {
 
 // Menu scenario to create a BrowserActionFactory.
-MenuScenarioHistogram kTestMenuScenario = MenuScenarioHistogram::kHistoryEntry;
+const MenuScenarioHistogram kTestMenuScenario =
+    kMenuScenarioHistogramHistoryEntry;
 
 // Email for the primary account when signing-in.
 const char kPrimaryAccountEmail[] = "peter.parker@gmail.com";
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer.mm
index 701e3d1c..a0e2c3c 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer.mm
@@ -7,6 +7,7 @@
 #import "base/apple/foundation_util.h"
 #import "base/ios/ios_util.h"
 #import "ios/chrome/browser/shared/model/url/chrome_url_constants.h"
+#import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h"
 #import "ios/web/common/features.h"
@@ -120,24 +121,28 @@
     }
   }
 
-  // Update the content offset of the scroll view to match the padding
-  // that will be included in the frame.
   CGFloat currentTopInset = webView.frame.origin.y;
   CGPoint newContentOffset = scrollViewProxy.contentOffset;
   newContentOffset.y += insets.top - currentTopInset;
-  if (self.compensateFrameChangeByOffset) {
-    scrollViewProxy.contentOffset = newContentOffset;
+  if (!base::FeatureList::IsEnabled(kFullscreenImprovement)) {
+    // Update the content offset of the scroll view to match the padding
+    // that will be included in the frame.
+    if (self.compensateFrameChangeByOffset) {
+      scrollViewProxy.contentOffset = newContentOffset;
+    }
   }
 
   webView.frame = newFrame;
 
-  // Setting WKWebView frame can mistakenly reset contentOffset. Change it
-  // back to the initial value if necessary.
-  // TODO(crbug.com/645857): Remove this workaround once WebKit bug is
-  // fixed.
-  if (self.compensateFrameChangeByOffset &&
-      [scrollViewProxy contentOffset].y != newContentOffset.y) {
-    [scrollViewProxy setContentOffset:newContentOffset];
+  if (!base::FeatureList::IsEnabled(kFullscreenImprovement)) {
+    // Setting WKWebView frame can mistakenly reset contentOffset. Change it
+    // back to the initial value if necessary.
+    // TODO(crbug.com/645857): Remove this workaround once WebKit bug is
+    // fixed.
+    if (self.compensateFrameChangeByOffset &&
+        [scrollViewProxy contentOffset].y != newContentOffset.y) {
+      [scrollViewProxy setContentOffset:newContentOffset];
+    }
   }
 }
 
diff --git a/ios/chrome/browser/ui/history/history_coordinator.mm b/ios/chrome/browser/ui/history/history_coordinator.mm
index 666ff52..00b4815 100644
--- a/ios/chrome/browser/ui/history/history_coordinator.mm
+++ b/ios/chrome/browser/ui/history/history_coordinator.mm
@@ -11,6 +11,7 @@
 #import "components/sync/service/sync_service.h"
 #import "ios/chrome/browser/history/history_service_factory.h"
 #import "ios/chrome/browser/history/web_history_service_factory.h"
+#import "ios/chrome/browser/net/crurl.h"
 #import "ios/chrome/browser/policy/policy_util.h"
 #import "ios/chrome/browser/shared/coordinator/alert/action_sheet_coordinator.h"
 #import "ios/chrome/browser/shared/model/browser/browser.h"
@@ -246,11 +247,11 @@
     HistoryCoordinator* strongSelf = weakSelf;
 
     // Record that this context menu was shown to the user.
-    RecordMenuShown(MenuScenarioHistogram::kHistoryEntry);
+    RecordMenuShown(kMenuScenarioHistogramHistoryEntry);
 
     BrowserActionFactory* actionFactory = [[BrowserActionFactory alloc]
         initWithBrowser:strongSelf.browser
-               scenario:MenuScenarioHistogram::kHistoryEntry];
+               scenario:kMenuScenarioHistogramHistoryEntry];
 
     NSMutableArray<UIMenuElement*>* menuElements =
         [[NSMutableArray alloc] init];
@@ -282,7 +283,8 @@
                                   activityOrigin:WindowActivityHistoryOrigin]];
     }
 
-    [menuElements addObject:[actionFactory actionToCopyURL:item.URL]];
+    CrURL* URL = [[CrURL alloc] initWithGURL:item.URL];
+    [menuElements addObject:[actionFactory actionToCopyURL:URL]];
 
     [menuElements addObject:[actionFactory actionToShareWithBlock:^{
                     [weakSelf shareURL:item.URL title:item.text fromView:view];
diff --git a/ios/chrome/browser/ui/menu/BUILD.gn b/ios/chrome/browser/ui/menu/BUILD.gn
index f60e8be..101b897 100644
--- a/ios/chrome/browser/ui/menu/BUILD.gn
+++ b/ios/chrome/browser/ui/menu/BUILD.gn
@@ -19,6 +19,7 @@
     "//components/prefs",
     "//components/search_engines",
     "//ios/chrome/app/strings",
+    "//ios/chrome/browser/net:crurl",
     "//ios/chrome/browser/policy:policy_util",
     "//ios/chrome/browser/search_engines/model",
     "//ios/chrome/browser/shared/coordinator/scene:scene_state_browser_agent",
@@ -59,6 +60,7 @@
     "//components/policy/core/common:common_constants",
     "//components/sync_preferences:test_support",
     "//ios/chrome/app/strings",
+    "//ios/chrome/browser/net:crurl",
     "//ios/chrome/browser/policy:policy_util",
     "//ios/chrome/browser/sessions:test_support",
     "//ios/chrome/browser/shared/coordinator/scene:scene_state_browser_agent",
diff --git a/ios/chrome/browser/ui/menu/action_factory+protected.h b/ios/chrome/browser/ui/menu/action_factory+protected.h
index e0517fbe..54db351 100644
--- a/ios/chrome/browser/ui/menu/action_factory+protected.h
+++ b/ios/chrome/browser/ui/menu/action_factory+protected.h
@@ -7,6 +7,8 @@
 
 #import "ios/chrome/browser/ui/menu/action_factory.h"
 
+#import "ios/chrome/browser/ui/menu/menu_action_type.h"
+
 @interface ActionFactory (Protected)
 
 // Creates a UIAction instance configured with the given `title` and `image`.
diff --git a/ios/chrome/browser/ui/menu/action_factory.h b/ios/chrome/browser/ui/menu/action_factory.h
index 88e2469b..a7cdfb5e 100644
--- a/ios/chrome/browser/ui/menu/action_factory.h
+++ b/ios/chrome/browser/ui/menu/action_factory.h
@@ -8,10 +8,10 @@
 #import <UIKit/UIKit.h>
 
 #import "base/ios/block_types.h"
-#import "ios/chrome/browser/ui/menu/menu_action_type.h"
+
 #import "ios/chrome/browser/ui/menu/menu_histograms.h"
 
-class GURL;
+@class CrURL;
 
 // Factory providing methods to create UIActions with consistent titles, images
 // and metrics structure. When using any action from this class, an histogram
@@ -25,7 +25,7 @@
 
 // Creates a UIAction instance configured to copy the given `URL` to the
 // pasteboard.
-- (UIAction*)actionToCopyURL:(const GURL)URL;
+- (UIAction*)actionToCopyURL:(CrURL*)URL;
 
 // Creates a UIAction instance configured for sharing which will invoke
 // the given `block` upon execution.
diff --git a/ios/chrome/browser/ui/menu/action_factory.mm b/ios/chrome/browser/ui/menu/action_factory.mm
index 5d9b168..f68d7da 100644
--- a/ios/chrome/browser/ui/menu/action_factory.mm
+++ b/ios/chrome/browser/ui/menu/action_factory.mm
@@ -6,11 +6,13 @@
 
 #import "base/metrics/histogram_functions.h"
 #import "base/metrics/user_metrics.h"
+#import "ios/chrome/browser/net/crurl.h"
 #import "ios/chrome/browser/shared/public/commands/application_commands.h"
 #import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/shared/ui/symbols/symbols.h"
 #import "ios/chrome/browser/shared/ui/util/pasteboard_util.h"
+#import "ios/chrome/browser/ui/menu/menu_action_type.h"
 #import "ios/chrome/grit/ios_strings.h"
 #import "ui/base/l10n/l10n_util_mac.h"
 #import "url/gurl.h"
@@ -48,7 +50,7 @@
                            }];
 }
 
-- (UIAction*)actionToCopyURL:(const GURL)URL {
+- (UIAction*)actionToCopyURL:(CrURL*)URL {
   UIImage* image =
       DefaultSymbolWithPointSize(kLinkActionSymbol, kSymbolActionPointSize);
   return [self
@@ -56,7 +58,7 @@
                 image:image
                  type:MenuActionType::CopyURL
                 block:^{
-                  StoreURLInPasteboard(URL);
+                  StoreURLInPasteboard(URL.gurl);
                 }];
 }
 
diff --git a/ios/chrome/browser/ui/menu/action_factory_unittest.mm b/ios/chrome/browser/ui/menu/action_factory_unittest.mm
index f781443..37526c6 100644
--- a/ios/chrome/browser/ui/menu/action_factory_unittest.mm
+++ b/ios/chrome/browser/ui/menu/action_factory_unittest.mm
@@ -7,6 +7,7 @@
 #import "base/test/metrics/histogram_tester.h"
 #import "base/test/scoped_feature_list.h"
 #import "base/test/task_environment.h"
+#import "ios/chrome/browser/net/crurl.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/shared/ui/symbols/symbols.h"
 #import "ios/chrome/browser/ui/menu/action_factory+protected.h"
@@ -24,7 +25,8 @@
 #import "url/gurl.h"
 
 namespace {
-MenuScenarioHistogram kTestMenuScenario = MenuScenarioHistogram::kHistoryEntry;
+const MenuScenarioHistogram kTestMenuScenario =
+    kMenuScenarioHistogramHistoryEntry;
 }  // namespace
 
 // Test fixture for the ActionFactory.
@@ -122,8 +124,7 @@
   NSString* expectedTitle =
       l10n_util::GetNSString(IDS_IOS_COPY_LINK_ACTION_TITLE);
 
-  GURL testURL = GURL("https://example.com");
-
+  CrURL* testURL = [[CrURL alloc] initWithGURL:GURL("https://example.com")];
   UIAction* action = [factory actionToCopyURL:testURL];
 
   EXPECT_TRUE([expectedTitle isEqualToString:action.title]);
diff --git a/ios/chrome/browser/ui/menu/browser_action_factory_unittest.mm b/ios/chrome/browser/ui/menu/browser_action_factory_unittest.mm
index 0f3f46e6..4042f20 100644
--- a/ios/chrome/browser/ui/menu/browser_action_factory_unittest.mm
+++ b/ios/chrome/browser/ui/menu/browser_action_factory_unittest.mm
@@ -41,7 +41,8 @@
 #import "url/gurl.h"
 
 namespace {
-MenuScenarioHistogram kTestMenuScenario = MenuScenarioHistogram::kHistoryEntry;
+const MenuScenarioHistogram kTestMenuScenario =
+    kMenuScenarioHistogramHistoryEntry;
 }  // namespace
 
 // Test fixture for the BrowserActionFactory.
diff --git a/ios/chrome/browser/ui/menu/menu_histograms.h b/ios/chrome/browser/ui/menu/menu_histograms.h
index 12cfad8c..555e0f9 100644
--- a/ios/chrome/browser/ui/menu/menu_histograms.h
+++ b/ios/chrome/browser/ui/menu/menu_histograms.h
@@ -8,30 +8,28 @@
 // Enum representing the existing set of menu scenarios. Current values should
 // not be renumbered. Please keep in sync with "IOSMenuScenario" in
 // src/tools/metrics/histograms/enums.xml.
-enum class MenuScenarioHistogram {
-  kBookmarkEntry = 0,
-  kBookmarkFolder = 1,
-  kReadingListEntry = 2,
-  kRecentTabsHeader = 3,
-  kRecentTabsEntry = 4,
-  kHistoryEntry = 5,
-  kMostVisitedEntry = 6,
-  kContextMenuImage = 7,
-  kContextMenuImageLink = 8,
-  kContextMenuLink = 9,
-  kTabGridEntry = 10,
-  kTabGridAddTo = 11,
-  kTabGridEdit = 12,
-  kToolbarMenu = 13,
-  kTabGridSearchResult = 14,
-  kThumbStrip = 15,
-  kOmniboxMostVisitedEntry = 16,
-  kPinnedTabsEntry = 17,
-  kTabStripEntry =
-      18,  // TODO(crbug.com/1428071): Currently not recorded. With the current
-           // tabStrip implementation we can't display context menus.
-  kInactiveTabsEntry = 19,
-  kMaxValue = kInactiveTabsEntry,
+enum MenuScenarioHistogram {
+  kMenuScenarioHistogramBookmarkEntry = 0,
+  kMenuScenarioHistogramBookmarkFolder = 1,
+  kMenuScenarioHistogramReadingListEntry = 2,
+  kMenuScenarioHistogramRecentTabsHeader = 3,
+  kMenuScenarioHistogramRecentTabsEntry = 4,
+  kMenuScenarioHistogramHistoryEntry = 5,
+  kMenuScenarioHistogramMostVisitedEntry = 6,
+  kMenuScenarioHistogramContextMenuImage = 7,
+  kMenuScenarioHistogramContextMenuImageLink = 8,
+  kMenuScenarioHistogramContextMenuLink = 9,
+  kMenuScenarioHistogramTabGridEntry = 10,
+  kMenuScenarioHistogramTabGridAddTo = 11,
+  kMenuScenarioHistogramTabGridEdit = 12,
+  kMenuScenarioHistogramToolbarMenu = 13,
+  kMenuScenarioHistogramTabGridSearchResult = 14,
+  kMenuScenarioHistogramThumbStrip = 15,
+  kMenuScenarioHistogramOmniboxMostVisitedEntry = 16,
+  kMenuScenarioHistogramPinnedTabsEntry = 17,
+  kMenuScenarioHistogramTabStripEntry = 18,
+  kMenuScenarioHistogramInactiveTabsEntry = 19,
+  kMenuScenarioHistogramCount,
 };
 
 // Records a menu shown histogram metric for the `scenario`.
diff --git a/ios/chrome/browser/ui/menu/menu_histograms.mm b/ios/chrome/browser/ui/menu/menu_histograms.mm
index 4488878..be0ddab 100644
--- a/ios/chrome/browser/ui/menu/menu_histograms.mm
+++ b/ios/chrome/browser/ui/menu/menu_histograms.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/ui/menu/menu_histograms.h"
 
 #import "base/metrics/histogram_functions.h"
+#import "base/notreached.h"
 
 namespace {
 // Histogram for tracking menu scenario started.
@@ -51,49 +52,52 @@
 }  // namespace
 
 void RecordMenuShown(MenuScenarioHistogram scenario) {
-  base::UmaHistogramEnumeration(kMenuEntryPointsHistogram, scenario);
+  base::UmaHistogramEnumeration(kMenuEntryPointsHistogram, scenario,
+                                kMenuScenarioHistogramCount);
 }
 
 const char* GetActionsHistogramName(MenuScenarioHistogram scenario) {
   switch (scenario) {
-    case MenuScenarioHistogram::kHistoryEntry:
+    case kMenuScenarioHistogramHistoryEntry:
       return kHistoryEntryActionsHistogram;
-    case MenuScenarioHistogram::kBookmarkEntry:
+    case kMenuScenarioHistogramBookmarkEntry:
       return kBookmarkEntryActionsHistogram;
-    case MenuScenarioHistogram::kReadingListEntry:
+    case kMenuScenarioHistogramReadingListEntry:
       return kReadingListEntryActionsHistogram;
-    case MenuScenarioHistogram::kRecentTabsEntry:
+    case kMenuScenarioHistogramRecentTabsEntry:
       return kRecentTabsEntryActionsHistogram;
-    case MenuScenarioHistogram::kRecentTabsHeader:
+    case kMenuScenarioHistogramRecentTabsHeader:
       return kRecentTabsHeaderActionsHistogram;
-    case MenuScenarioHistogram::kMostVisitedEntry:
+    case kMenuScenarioHistogramMostVisitedEntry:
       return kMostVisitedEntryActionsHistogram;
-    case MenuScenarioHistogram::kBookmarkFolder:
+    case kMenuScenarioHistogramBookmarkFolder:
       return kBookmarkFolderActionsHistogram;
-    case MenuScenarioHistogram::kContextMenuImage:
+    case kMenuScenarioHistogramContextMenuImage:
       return KContextMenuImageActionsHistogram;
-    case MenuScenarioHistogram::kContextMenuImageLink:
+    case kMenuScenarioHistogramContextMenuImageLink:
       return KContextMenuImageLinkActionsHistogram;
-    case MenuScenarioHistogram::kContextMenuLink:
+    case kMenuScenarioHistogramContextMenuLink:
       return KContextMenuLinkActionsHistogram;
-    case MenuScenarioHistogram::kTabGridEntry:
-    case MenuScenarioHistogram::kThumbStrip:
+    case kMenuScenarioHistogramTabGridEntry:
+    case kMenuScenarioHistogramThumbStrip:
       return kTabGridActionsHistogram;
-    case MenuScenarioHistogram::kTabGridAddTo:
+    case kMenuScenarioHistogramTabGridAddTo:
       return kTabGridAddToActionsHistogram;
-    case MenuScenarioHistogram::kTabGridEdit:
+    case kMenuScenarioHistogramTabGridEdit:
       return kTabGridEditActionsHistogram;
-    case MenuScenarioHistogram::kTabGridSearchResult:
+    case kMenuScenarioHistogramTabGridSearchResult:
       return kTabGridSearchResultHistogram;
-    case MenuScenarioHistogram::kToolbarMenu:
+    case kMenuScenarioHistogramToolbarMenu:
       return kToolbarMenuActionsHistogram;
-    case MenuScenarioHistogram::kOmniboxMostVisitedEntry:
+    case kMenuScenarioHistogramOmniboxMostVisitedEntry:
       return kOmniboxMostVisitedEntryActionsHistogram;
-    case MenuScenarioHistogram::kPinnedTabsEntry:
+    case kMenuScenarioHistogramPinnedTabsEntry:
       return kPinnedTabsEntryActionsHistogram;
-    case MenuScenarioHistogram::kTabStripEntry:
+    case kMenuScenarioHistogramTabStripEntry:
       return kTabStripEntryActionsHistogram;
-    case MenuScenarioHistogram::kInactiveTabsEntry:
+    case kMenuScenarioHistogramInactiveTabsEntry:
       return kInactiveTabsEntryActionsHistogram;
+    case kMenuScenarioHistogramCount:
+      NOTREACHED_NORETURN();
   }
 }
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
index c91a84d..42aa4bab 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
@@ -120,7 +120,7 @@
   self.mediator.sharingDelegate = self;
   BrowserActionFactory* actionFactory = [[BrowserActionFactory alloc]
       initWithBrowser:self.browser
-             scenario:MenuScenarioHistogram::kOmniboxMostVisitedEntry];
+             scenario:kMenuScenarioHistogramOmniboxMostVisitedEntry];
   self.mediator.mostVisitedActionFactory = actionFactory;
   self.popupViewController.imageRetriever = self.mediator;
   self.popupViewController.faviconRetriever = self.mediator;
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm
index 43b1977..269dde83 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm
@@ -631,7 +631,7 @@
             strongSelf.mostVisitedActionFactory;
 
         // Record that this context menu was shown to the user.
-        RecordMenuShown(MenuScenarioHistogram::kOmniboxMostVisitedEntry);
+        RecordMenuShown(kMenuScenarioHistogramOmniboxMostVisitedEntry);
 
         NSMutableArray<UIMenuElement*>* menuElements =
             [[NSMutableArray alloc] init];
@@ -660,7 +660,8 @@
           [menuElements addObject:newWindowAction];
         }
 
-        [menuElements addObject:[actionFactory actionToCopyURL:copyURL]];
+        CrURL* URL = [[CrURL alloc] initWithGURL:copyURL];
+        [menuElements addObject:[actionFactory actionToCopyURL:URL]];
 
         [menuElements addObject:[actionFactory actionToShareWithBlock:^{
                         [weakSelf.sharingDelegate
diff --git a/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_mediator.mm b/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_mediator.mm
index cce9663..bac7328 100644
--- a/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_mediator.mm
+++ b/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_mediator.mm
@@ -10,7 +10,7 @@
 #import "components/password_manager/core/browser/features/password_features.h"
 #import "components/password_manager/core/browser/password_form.h"
 #import "components/password_manager/core/browser/password_manager.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "components/password_manager/core/browser/password_ui_utils.h"
 #import "components/password_manager/core/browser/ui/credential_ui_entry.h"
 #import "components/password_manager/ios/ios_password_manager_driver_factory.h"
diff --git a/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator.mm b/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator.mm
index 7822744..61fd01b 100644
--- a/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator.mm
+++ b/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator.mm
@@ -588,8 +588,7 @@
   // Choice Promo handler
   if (ios::provider::IsChoiceEnabled()) {
     _displayHandlerPromos[promos_manager::Promo::Choice] =
-        ios::provider::CreateChoiceDisplayHandler(
-            self.browser->GetBrowserState());
+        ios::provider::CreateChoiceDisplayHandler();
   }
 }
 
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn
index 9746dfbd..124f20e 100644
--- a/ios/chrome/browser/ui/reading_list/BUILD.gn
+++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -40,6 +40,7 @@
     "//ios/chrome/browser/favicon",
     "//ios/chrome/browser/feature_engagement/model",
     "//ios/chrome/browser/metrics:metrics_internal",
+    "//ios/chrome/browser/net:crurl",
     "//ios/chrome/browser/policy:policy_util",
     "//ios/chrome/browser/reading_list/model",
     "//ios/chrome/browser/shared/coordinator/chrome_coordinator",
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
index f42909d..4d898f27 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
@@ -25,6 +25,7 @@
 #import "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h"
 #import "ios/chrome/browser/feature_engagement/model/tracker_factory.h"
 #import "ios/chrome/browser/metrics/new_tab_page_uma.h"
+#import "ios/chrome/browser/net/crurl.h"
 #import "ios/chrome/browser/policy/policy_util.h"
 #import "ios/chrome/browser/reading_list/model/offline_page_tab_helper.h"
 #import "ios/chrome/browser/reading_list/model/offline_url_utils.h"
@@ -467,11 +468,11 @@
         ReadingListCoordinator* strongSelf = weakSelf;
 
         // Record that this context menu was shown to the user.
-        RecordMenuShown(MenuScenarioHistogram::kReadingListEntry);
+        RecordMenuShown(kMenuScenarioHistogramReadingListEntry);
 
         BrowserActionFactory* actionFactory = [[BrowserActionFactory alloc]
             initWithBrowser:strongSelf.browser
-                   scenario:MenuScenarioHistogram::kReadingListEntry];
+                   scenario:kMenuScenarioHistogramReadingListEntry];
 
         NSMutableArray<UIMenuElement*>* menuElements =
             [[NSMutableArray alloc] init];
@@ -537,7 +538,8 @@
                         }]];
         }
 
-        [menuElements addObject:[actionFactory actionToCopyURL:item.entryURL]];
+        CrURL* URL = [[CrURL alloc] initWithGURL:item.entryURL];
+        [menuElements addObject:[actionFactory actionToCopyURL:URL]];
 
         [menuElements addObject:[actionFactory actionToShareWithBlock:^{
                         [weakSelf shareURL:item.entryURL
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_menu_helper.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_menu_helper.mm
index 6856014ce..cc8b9981 100644
--- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_menu_helper.mm
+++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_menu_helper.mm
@@ -61,11 +61,11 @@
     RecentTabsContextMenuHelper* strongSelf = weakSelf;
 
     // Record that this context menu was shown to the user.
-    RecordMenuShown(MenuScenarioHistogram::kRecentTabsEntry);
+    RecordMenuShown(kMenuScenarioHistogramRecentTabsEntry);
 
     BrowserActionFactory* actionFactory = [[BrowserActionFactory alloc]
         initWithBrowser:strongSelf.browser
-               scenario:MenuScenarioHistogram::kRecentTabsEntry];
+               scenario:kMenuScenarioHistogramRecentTabsEntry];
 
     NSMutableArray<UIMenuElement*>* menuElements =
         [[NSMutableArray alloc] init];
@@ -83,7 +83,8 @@
                                             WindowActivityRecentTabsOrigin]];
     }
 
-    [menuElements addObject:[actionFactory actionToCopyURL:gurl]];
+    CrURL* URL = [[CrURL alloc] initWithGURL:gurl];
+    [menuElements addObject:[actionFactory actionToCopyURL:URL]];
 
     [menuElements addObject:[actionFactory actionToShareWithBlock:^{
                     [weakSelf.contextMenuDelegate
@@ -117,10 +118,10 @@
         RecentTabsContextMenuHelper* strongSelf = weakSelf;
 
         // Record that this context menu was shown to the user.
-        RecordMenuShown(MenuScenarioHistogram::kRecentTabsHeader);
+        RecordMenuShown(kMenuScenarioHistogramRecentTabsHeader);
 
         ActionFactory* actionFactory = [[ActionFactory alloc]
-            initWithScenario:MenuScenarioHistogram::kRecentTabsHeader];
+            initWithScenario:kMenuScenarioHistogramRecentTabsHeader];
 
         NSMutableArray<UIMenuElement*>* menuElements =
             [[NSMutableArray alloc] init];
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_profile_table_view_controller.mm b/ios/chrome/browser/ui/settings/autofill/autofill_profile_table_view_controller.mm
index 3c9a8ad1..3ff10b2 100644
--- a/ios/chrome/browser/ui/settings/autofill/autofill_profile_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/autofill/autofill_profile_table_view_controller.mm
@@ -232,8 +232,6 @@
 
 - (TableViewItem*)itemForProfile:
     (const autofill::AutofillProfile&)autofillProfile {
-  assert(autofillProfile.record_type() ==
-         autofill::AutofillProfile::LOCAL_PROFILE);
   std::string guid(autofillProfile.guid());
   NSString* title = base::SysUTF16ToNSString(
       autofillProfile.GetInfo(autofill::AutofillType(autofill::NAME_FULL),
diff --git a/ios/chrome/browser/ui/settings/cells/sync_switch_item.mm b/ios/chrome/browser/ui/settings/cells/sync_switch_item.mm
index 1beaf6e..13597a2 100644
--- a/ios/chrome/browser/ui/settings/cells/sync_switch_item.mm
+++ b/ios/chrome/browser/ui/settings/cells/sync_switch_item.mm
@@ -22,13 +22,10 @@
 - (void)configureCell:(TableViewSwitchCell*)cell
            withStyler:(ChromeTableViewStyler*)styler {
   [super configureCell:cell withStyler:styler];
-  cell.textLabel.text = self.text;
-  cell.detailTextLabel.text = self.detailText;
-  cell.switchView.enabled = self.enabled;
-  cell.switchView.on = self.on;
-  cell.textLabel.textColor =
-      [TableViewSwitchCell defaultTextColorForState:cell.switchView.state];
-  cell.selectionStyle = UITableViewCellSelectionStyleNone;
+  [cell configureCellWithTitle:self.text
+                      subtitle:self.detailText
+                 switchEnabled:self.enabled
+                            on:self.on];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/settings/password/password_settings_app_interface.mm b/ios/chrome/browser/ui/settings/password/password_settings_app_interface.mm
index 83fcd75c..bdd7c28 100644
--- a/ios/chrome/browser/ui/settings/password/password_settings_app_interface.mm
+++ b/ios/chrome/browser/ui/settings/password/password_settings_app_interface.mm
@@ -13,8 +13,9 @@
 #import "base/test/ios/wait_util.h"
 #import "components/keyed_service/core/service_access_type.h"
 #import "components/password_manager/core/browser/password_form.h"
-#import "components/password_manager/core/browser/password_store_consumer.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
+#import "components/password_manager/core/common/password_manager_features.h"
 #import "components/password_manager/core/common/password_manager_pref_names.h"
 #import "components/password_manager/ios/fake_bulk_leak_check_service.h"
 #import "components/prefs/pref_service.h"
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
index 912696f..3d9920900 100644
--- a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
@@ -1178,13 +1178,6 @@
     return cell;
   NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath];
 
-  if ([cell isKindOfClass:[TableViewDetailIconCell class]]) {
-    TableViewDetailIconCell* detailCell =
-        base::apple::ObjCCastStrict<TableViewDetailIconCell>(cell);
-    [detailCell setUserInteractionEnabled:YES];
-    detailCell.textLabel.textColor = [UIColor colorNamed:kTextPrimaryColor];
-  }
-
   switch (itemType) {
     case SettingsItemTypeMemoryDebugging: {
       TableViewSwitchCell* switchCell =
diff --git a/ios/chrome/browser/ui/settings/voice_search_table_view_controller.mm b/ios/chrome/browser/ui/settings/voice_search_table_view_controller.mm
index 21391342..a7681ac 100644
--- a/ios/chrome/browser/ui/settings/voice_search_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/voice_search_table_view_controller.mm
@@ -291,29 +291,18 @@
   NSIndexPath* switchPath =
       [self.tableViewModel indexPathForItemType:ItemTypeTTSEnabled
                               sectionIdentifier:SectionIdentifierTTS];
-  TableViewSwitchCell* switchCell =
-      base::apple::ObjCCastStrict<TableViewSwitchCell>(
-          [self.tableView cellForRowAtIndexPath:switchPath]);
-
   // Some languages do not support TTS.  Disable the switch for those
   // languages.
   BOOL enabled = [self currentLanguageSupportsTTS];
   BOOL on = enabled && _ttsEnabled.GetValue();
 
-  UISwitch* switchView = switchCell.switchView;
-  switchView.enabled = enabled;
-  switchCell.textLabel.textColor =
-      [TableViewSwitchCell defaultTextColorForState:switchView.state];
-  if (on != switchView.isOn) {
-    [switchView setOn:on animated:YES];
-  }
-
-  // Also update the switch item.
   TableViewSwitchItem* switchItem =
       base::apple::ObjCCastStrict<TableViewSwitchItem>(
           [self.tableViewModel itemAtIndexPath:switchPath]);
   switchItem.enabled = enabled;
   switchItem.on = on;
+
+  [self reconfigureCellsForItems:@[ switchItem ]];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn
index e5e8df88..0d08e34 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn
@@ -72,6 +72,7 @@
     "//ios/chrome/browser/ui/tab_switcher:tab_utils",
     "//ios/chrome/browser/ui/tab_switcher/tab_grid/grid",
     "//ios/chrome/browser/ui/tab_switcher/tab_grid/grid:grid_mediator_delegate",
+    "//ios/chrome/browser/ui/tab_switcher/tab_grid/grid:grid_toolbars_mutator",
     "//ios/chrome/browser/ui/tab_switcher/tab_grid/grid:grid_ui",
     "//ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito",
     "//ios/chrome/browser/ui/tab_switcher/tab_grid/grid/regular",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator.mm
index a129956..52442e66a 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator.mm
@@ -256,34 +256,6 @@
   NOTREACHED_NORETURN() << "Should be implemented in a subclass.";
 }
 
-- (void)configureSelectionToolbarsButtons {
-  TabGridToolbarsConfiguration* toolbarsConfiguration =
-      [[TabGridToolbarsConfiguration alloc] init];
-
-  NSUInteger selectedItemsCount =
-      [self.itemProvider selectedItemIDsForEditing].size();
-  NSUInteger selectedShareableItemsCount =
-      [self.itemProvider selectedShareableItemIDsForEditing].size();
-  BOOL allItemsSelected =
-      static_cast<int>(selectedItemsCount) ==
-      (self.webStateList->count() - self.webStateList->pinned_tabs_count());
-
-  toolbarsConfiguration.selectAllButton = !allItemsSelected;
-  toolbarsConfiguration.deselectAllButton = allItemsSelected;
-  toolbarsConfiguration.doneButton = YES;
-  toolbarsConfiguration.closeSelectedTabsButton = selectedItemsCount > 0;
-  toolbarsConfiguration.shareButton = selectedShareableItemsCount > 0;
-  toolbarsConfiguration.addToButton = selectedShareableItemsCount > 0;
-  toolbarsConfiguration.selectedItemsCount = selectedItemsCount;
-
-  toolbarsConfiguration.addToButtonMenu = [UIMenu
-      menuWithChildren:[self addToButtonMenuElementsForItems:
-                                 [self.itemProvider
-                                         selectedShareableItemIDsForEditing]]];
-
-  [self.toolbarsMutator setToolbarConfiguration:toolbarsConfiguration];
-}
-
 #pragma mark - WebStateListObserving
 
 - (void)willChangeWebStateList:(WebStateList*)webStateList
@@ -697,7 +669,7 @@
   }
 
   ActionFactory* actionFactory = [[ActionFactory alloc]
-      initWithScenario:MenuScenarioHistogram::kTabGridAddTo];
+      initWithScenario:kMenuScenarioHistogramTabGridAddTo];
 
   __weak BaseGridMediator* weakSelf = self;
 
@@ -1104,6 +1076,36 @@
   }
 }
 
+// Called when user switched on selection mode and toolbars button needs to be
+// updated.
+- (void)configureSelectionToolbarsButtons {
+  TabGridToolbarsConfiguration* toolbarsConfiguration =
+      [[TabGridToolbarsConfiguration alloc] init];
+
+  NSUInteger selectedItemsCount =
+      [self.itemProvider selectedItemIDsForEditing].size();
+  NSUInteger selectedShareableItemsCount =
+      [self.itemProvider selectedShareableItemIDsForEditing].size();
+  BOOL allItemsSelected =
+      static_cast<int>(selectedItemsCount) ==
+      (self.webStateList->count() - self.webStateList->pinned_tabs_count());
+
+  toolbarsConfiguration.selectAllButton = !allItemsSelected;
+  toolbarsConfiguration.deselectAllButton = allItemsSelected;
+  toolbarsConfiguration.doneButton = YES;
+  toolbarsConfiguration.closeSelectedTabsButton = selectedItemsCount > 0;
+  toolbarsConfiguration.shareButton = selectedShareableItemsCount > 0;
+  toolbarsConfiguration.addToButton = selectedShareableItemsCount > 0;
+  toolbarsConfiguration.selectedItemsCount = selectedItemsCount;
+
+  toolbarsConfiguration.addToButtonMenu = [UIMenu
+      menuWithChildren:[self addToButtonMenuElementsForItems:
+                                 [self.itemProvider
+                                         selectedShareableItemIDsForEditing]]];
+
+  [self.toolbarsMutator setToolbarConfiguration:toolbarsConfiguration];
+}
+
 #pragma mark - TabGridPageMutator
 
 - (void)currentlySelectedGrid:(BOOL)selected {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_view_controller.mm
index 2542f2e..91092887 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_view_controller.mm
@@ -755,11 +755,11 @@
 
   MenuScenarioHistogram scenario;
   if (_mode == TabGridModeSearch) {
-    scenario = MenuScenarioHistogram::kTabGridSearchResult;
+    scenario = kMenuScenarioHistogramTabGridSearchResult;
   } else if (_mode == TabGridModeInactive) {
-    scenario = MenuScenarioHistogram::kInactiveTabsEntry;
+    scenario = kMenuScenarioHistogramInactiveTabsEntry;
   } else {
-    scenario = MenuScenarioHistogram::kTabGridEntry;
+    scenario = kMenuScenarioHistogramTabGridEntry;
   }
 
   return [self.menuProvider contextMenuConfigurationForTabCell:cell
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_toolbars_mutator.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_toolbars_mutator.h
index d28d7fc..e73058c 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_toolbars_mutator.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_toolbars_mutator.h
@@ -25,6 +25,10 @@
 // Sends to the model the current mode.
 - (void)setToolbarsMode:(TabGridMode)mode;
 
+// Sends NO to disable all buttons and save the current configuration or YES to
+// enable the saved configuration.
+- (void)setButtonsEnabled:(BOOL)enabled;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_GRID_TOOLBARS_MUTATOR_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.h
index de6d0f5..eb9dbc1 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.h
@@ -58,6 +58,10 @@
     (PinnedTabsViewController*)pinnedTabsViewController;
 
 // Tells the delegate that a drag session did end.
+- (void)pinnedViewControllerDragSessionWillBegin:
+    (PinnedTabsViewController*)pinnedTabsViewController;
+
+// Tells the delegate that a drag session did end.
 - (void)pinnedViewControllerDragSessionDidEnd:
     (PinnedTabsViewController*)pinnedTabsViewController;
 
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm
index 6c9ad4e..f312e7e3 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm
@@ -475,8 +475,7 @@
       [self.collectionView cellForItemAtIndexPath:indexPath]);
   return [self.menuProvider
       contextMenuConfigurationForTabCell:cell
-                            menuScenario:MenuScenarioHistogram::
-                                             kPinnedTabsEntry];
+                            menuScenario:kMenuScenarioHistogramPinnedTabsEntry];
 }
 
 - (void)collectionView:(UICollectionView*)collectionView
@@ -500,7 +499,7 @@
   _localDragActionInProgress = YES;
   base::UmaHistogramEnumeration(kUmaPinnedViewDragDropTabs,
                                 DragDropTabs::kDragBegin);
-
+  [self.delegate pinnedViewControllerDragSessionWillBegin:self];
   [self dragSessionEnabled:YES];
 }
 
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_context_menu/tab_context_menu_helper.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_context_menu/tab_context_menu_helper.mm
index 9073d03..eeb742a0 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_context_menu/tab_context_menu_helper.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_context_menu/tab_context_menu_helper.mm
@@ -85,8 +85,8 @@
   const BOOL pinned = IsPinnedTabsEnabled() &&
                       [self isTabPinnedForIdentifier:cell.itemIdentifier];
   const BOOL tabSearchScenario =
-      scenario == MenuScenarioHistogram::kTabGridSearchResult;
-  const BOOL inactive = scenario == MenuScenarioHistogram::kInactiveTabsEntry;
+      scenario == kMenuScenarioHistogramTabGridSearchResult;
+  const BOOL inactive = scenario == kMenuScenarioHistogramInactiveTabsEntry;
 
   TabItem* item = [self tabItemForIdentifier:cell.itemIdentifier];
 
@@ -157,9 +157,9 @@
   // Pinned tabs, inactive tabs and search results menus don't
   // support tab selection.
   BOOL scenarioDisablesSelection =
-      scenario == MenuScenarioHistogram::kTabGridSearchResult ||
-      scenario == MenuScenarioHistogram::kPinnedTabsEntry ||
-      scenario == MenuScenarioHistogram::kInactiveTabsEntry;
+      scenario == kMenuScenarioHistogramTabGridSearchResult ||
+      scenario == kMenuScenarioHistogramPinnedTabsEntry ||
+      scenario == kMenuScenarioHistogramInactiveTabsEntry;
   if (!scenarioDisablesSelection) {
     [menuElements addObject:[actionFactory actionToSelectTabsWithBlock:^{
                     [self.contextMenuDelegate selectTabs];
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
index 009104f7..96c284b 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
@@ -875,6 +875,7 @@
   _mediator.regularPageMutator = _regularGridCoordinator.regularGridMediator;
   _mediator.incognitoPageMutator = self.incognitoTabsMediator;
   _mediator.remotePageMutator = self.remoteTabsMediator;
+  _mediator.toolbarsMutator = _toolbarsCoordinator.toolbarsMutator;
 
   self.remoteTabsMediator.toolbarsMutator =
       _toolbarsCoordinator.toolbarsMutator;
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h
index e56d9ba..f83c9c4 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h
@@ -9,6 +9,7 @@
 
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mutator.h"
 
+@protocol GridToolbarsMutator;
 @protocol TabGridConsumer;
 @protocol TabGridPageMutator;
 
@@ -24,6 +25,9 @@
 // Mutator for remote Tabs.
 @property(nonatomic, weak) id<TabGridPageMutator> remotePageMutator;
 
+// Mutator to handle toolbars modification.
+@property(nonatomic, weak) id<GridToolbarsMutator> toolbarsMutator;
+
 // Consumer for state changes in tab grid.
 @property(nonatomic, weak) id<TabGridConsumer> consumer;
 
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
index 79637980..37d4a41 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
@@ -13,6 +13,7 @@
 #import "components/supervised_user/core/common/features.h"
 #import "components/supervised_user/core/common/pref_names.h"
 #import "ios/chrome/browser/policy/policy_util.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_toolbars_mutator.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_consumer.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_metrics.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_page_mutator.h"
@@ -119,4 +120,12 @@
   // notification.
 }
 
+- (void)dragAndDropSessionStarted {
+  [self.toolbarsMutator setButtonsEnabled:NO];
+}
+
+- (void)dragAndDropSessionEnded {
+  [self.toolbarsMutator setButtonsEnabled:YES];
+}
+
 @end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mutator.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mutator.h
index 9abcca7..1922109 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mutator.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mutator.h
@@ -18,6 +18,10 @@
 - (void)pageChanged:(TabGridPage)currentPage
         interaction:(TabSwitcherPageChangeInteraction)interaction;
 
+// Notify the model that a drag and drop session started or ended.
+- (void)dragAndDropSessionStarted;
+- (void)dragAndDropSessionEnded;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_TAB_GRID_MUTATOR_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm
index 4c7bf558..5f8d2de1 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm
@@ -1245,7 +1245,10 @@
   BOOL incognitoTabsNeedsAuth =
       (self.currentPage == TabGridPageIncognitoTabs &&
        self.incognitoTabsViewController.contentNeedsAuthentication);
-  BOOL doneEnabled = tabsPresent && !incognitoTabsNeedsAuth;
+  // Avoid drag and drop because you can switch grid while drag and drop
+  // session.
+  BOOL doneEnabled =
+      tabsPresent && !incognitoTabsNeedsAuth && !self.dragSessionInProgress;
   [self.topToolbar setDoneButtonEnabled:doneEnabled];
   [self.bottomToolbar setDoneButtonEnabled:doneEnabled];
 }
@@ -1868,15 +1871,16 @@
   self.regularTabsViewController.dropAnimationInProgress = NO;
 }
 
+- (void)pinnedViewControllerDragSessionWillBegin:
+    (PinnedTabsViewController*)pinnedTabsViewController {
+  self.dragSessionInProgress = YES;
+  [self.mutator dragAndDropSessionStarted];
+}
+
 - (void)pinnedViewControllerDragSessionDidEnd:
     (PinnedTabsViewController*)pinnedTabsViewController {
   self.dragSessionInProgress = NO;
-
-  [self.topToolbar setSearchButtonEnabled:YES];
-
-  [self configureDoneButtonBasedOnPage:self.currentPage];
-  [self configureCloseAllButtonForCurrentPageAndUndoAvailability];
-  [self configureNewTabButtonBasedOnContentPermissions];
+  [self.mutator dragAndDropSessionEnded];
 }
 
 #pragma mark - BaseGridViewControllerDelegate
@@ -2006,18 +2010,10 @@
 - (void)gridViewControllerDragSessionWillBegin:
     (BaseGridViewController*)gridViewController {
   self.dragSessionInProgress = YES;
+  [self.mutator dragAndDropSessionStarted];
 
   // Actions on both bars should be disabled during dragging.
-  [self.topToolbar setDoneButtonEnabled:NO];
   self.topToolbar.pageControl.userInteractionEnabled = NO;
-  [self.bottomToolbar setDoneButtonEnabled:NO];
-  [self.topToolbar setSelectAllButtonEnabled:NO];
-  [self.topToolbar setEditButtonEnabled:NO];
-  [self.topToolbar setSearchButtonEnabled:NO];
-  [self.bottomToolbar setEditButtonEnabled:NO];
-  [self.bottomToolbar setAddToButtonEnabled:NO];
-  [self.bottomToolbar setShareTabsButtonEnabled:NO];
-  [self.bottomToolbar setCloseTabsButtonEnabled:NO];
   if (IsPinnedTabsEnabled()) {
     [self.pinnedTabsViewController dragSessionEnabled:YES];
   }
@@ -2026,13 +2022,9 @@
 - (void)gridViewControllerDragSessionDidEnd:
     (BaseGridViewController*)gridViewController {
   self.dragSessionInProgress = NO;
+  [self.mutator dragAndDropSessionEnded];
+  self.topToolbar.pageControl.userInteractionEnabled = YES;
 
-  [self.topToolbar setSearchButtonEnabled:YES];
-
-  // -configureDoneButtonBasedOnPage will enable the page control.
-  [self configureDoneButtonBasedOnPage:self.currentPage];
-  [self configureCloseAllButtonForCurrentPageAndUndoAvailability];
-  [self configureNewTabButtonBasedOnContentPermissions];
   if (IsPinnedTabsEnabled()) {
     [self.pinnedTabsViewController dragSessionEnabled:NO];
   }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/tab_grid_toolbars_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/tab_grid_toolbars_mediator.mm
index 5718e07..0adb566 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/tab_grid_toolbars_mediator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/tab_grid_toolbars_mediator.mm
@@ -14,14 +14,22 @@
 @implementation TabGridToolbarsMediator {
   // Configuration that provides all buttons to display.
   TabGridToolbarsConfiguration* _configuration;
+  TabGridToolbarsConfiguration* _previousConfiguration;
   id<TabGridToolbarsButtonsDelegate> _buttonsDelegate;
 
   TabGridMode _currentMode;
+
+  // YES if buttons are disabled.
+  BOOL _isDisabled;
 }
 
 #pragma mark - GridToolbarsMutator
 
 - (void)setToolbarConfiguration:(TabGridToolbarsConfiguration*)configuration {
+  if (_isDisabled) {
+    return;
+  }
+
   _configuration = configuration;
 
   // TODO(crbug.com/1457146): Add all buttons management.
@@ -38,11 +46,14 @@
   }
 
   [self configureEditOrUndoButton];
+
   [self.bottomToolbarConsumer
       setNewTabButtonEnabled:_configuration.newTabButton];
 
   [self.topToolbarConsumer setDoneButtonEnabled:_configuration.doneButton];
   [self.bottomToolbarConsumer setDoneButtonEnabled:_configuration.doneButton];
+
+  [self.topToolbarConsumer setSearchButtonEnabled:_configuration.searchButton];
 }
 
 - (void)setToolbarsButtonsDelegate:
@@ -58,6 +69,25 @@
   self.topToolbarConsumer.mode = mode;
 }
 
+- (void)setButtonsEnabled:(BOOL)enabled {
+  if (enabled) {
+    // Set the disabled boolean before modifiying the toolbar configuration
+    // because the configuration setup is skipped when disabled.
+    _isDisabled = NO;
+    [self setToolbarConfiguration:_previousConfiguration];
+  } else {
+    if (_isDisabled) {
+      return;
+    }
+    _previousConfiguration = _configuration;
+    [self setToolbarConfiguration:[TabGridToolbarsConfiguration
+                                      disabledConfiguration]];
+    // Set the disabled boolean after modifiying the toolbar configuration
+    // because the configuration setup is skipped when disabled.
+    _isDisabled = YES;
+  }
+}
+
 #pragma mark - Private
 
 // Helpers to configure all selection mode buttons.
@@ -111,7 +141,7 @@
   UIMenu* menu = nil;
   if (shouldEnableEditButton) {
     ActionFactory* actionFactory = [[ActionFactory alloc]
-        initWithScenario:MenuScenarioHistogram::kTabGridEdit];
+        initWithScenario:kMenuScenarioHistogramTabGridEdit];
     __weak id<TabGridToolbarsButtonsDelegate> weakButtonDelegate =
         _buttonsDelegate;
     NSMutableArray<UIMenuElement*>* menuElements =
diff --git a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_coordinator.mm
index 1af467f..97845ef8 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_coordinator.mm
@@ -85,7 +85,7 @@
           browser->GetBrowserState());
   self.mediator.actionFactory = [[BrowserActionFactory alloc]
       initWithBrowser:browser
-             scenario:MenuScenarioHistogram::kToolbarMenu];
+             scenario:kMenuScenarioHistogramToolbarMenu];
 
   _fullscreenUIUpdater = std::make_unique<FullscreenUIUpdater>(
       FullscreenController::FromBrowser(browser), self.viewController);
diff --git a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_mediator_unittest.mm b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_mediator_unittest.mm
index d9098f4..9b705e5 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_mediator_unittest.mm
@@ -53,7 +53,7 @@
 
 namespace {
 
-MenuScenarioHistogram kTestMenuScenario = MenuScenarioHistogram::kHistoryEntry;
+MenuScenarioHistogram kTestMenuScenario = kMenuScenarioHistogramHistoryEntry;
 
 static const int kNumberOfWebStates = 3;
 static const char kTestUrl[] = "http://www.chromium.org";
diff --git a/ios/chrome/test/providers/signin/test_choice.mm b/ios/chrome/test/providers/signin/test_choice.mm
index a3aa6aa..35db75d3 100644
--- a/ios/chrome/test/providers/signin/test_choice.mm
+++ b/ios/chrome/test/providers/signin/test_choice.mm
@@ -24,19 +24,10 @@
   NOTREACHED_NORETURN();
 }
 
-id<StandardPromoDisplayHandler> CreateChoiceDisplayHandler(
-    ChromeBrowserState* browserState) {
-  NOTREACHED_NORETURN();
-}
-
 id<StandardPromoDisplayHandler> CreateChoiceDisplayHandler() {
   NOTREACHED_NORETURN();
 }
 
-id<SceneAgent> CreateChoiceSceneAgent(PromosManager* promosManager) {
-  NOTREACHED_NORETURN();
-}
-
 id<SceneAgent> CreateChoiceSceneAgent(PromosManager* promosManager,
                                       ChromeBrowserState* browserState) {
   NOTREACHED_NORETURN();
diff --git a/ios/public/provider/chrome/browser/signin/choice_api.h b/ios/public/provider/chrome/browser/signin/choice_api.h
index 04aa6d0..f46362a 100644
--- a/ios/public/provider/chrome/browser/signin/choice_api.h
+++ b/ios/public/provider/chrome/browser/signin/choice_api.h
@@ -33,16 +33,9 @@
     id<FirstRunScreenDelegate> first_run_delegate);
 
 // Creates a new ChoiceDisplayHandler instance.
-id<StandardPromoDisplayHandler> CreateChoiceDisplayHandler(
-    ChromeBrowserState* browserState);
-
-// Creates a new ChoiceDisplayHandler instance.
 id<StandardPromoDisplayHandler> CreateChoiceDisplayHandler();
 
 // Creates a new ChoiceSceneAgent instance.
-id<SceneAgent> CreateChoiceSceneAgent(PromosManager* promosManager);
-
-// Creates a new ChoiceSceneAgent instance.
 id<SceneAgent> CreateChoiceSceneAgent(PromosManager* promosManager,
                                       ChromeBrowserState* browserState);
 
diff --git a/ios/web_view/internal/autofill/cwv_autofill_data_manager.mm b/ios/web_view/internal/autofill/cwv_autofill_data_manager.mm
index 9747179..2a9cd90 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_data_manager.mm
+++ b/ios/web_view/internal/autofill/cwv_autofill_data_manager.mm
@@ -12,9 +12,9 @@
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
-#include "components/password_manager/core/browser/password_store_change.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_change.h"
+#import "components/password_manager/core/browser/password_store/password_store_consumer.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "ios/web/public/thread/web_task_traits.h"
 #include "ios/web/public/thread/web_thread.h"
 #import "ios/web_view/internal/autofill/cwv_autofill_profile_internal.h"
diff --git a/ios/web_view/internal/cwv_web_view_configuration.mm b/ios/web_view/internal/cwv_web_view_configuration.mm
index 323d254..56c8498 100644
--- a/ios/web_view/internal/cwv_web_view_configuration.mm
+++ b/ios/web_view/internal/cwv_web_view_configuration.mm
@@ -10,7 +10,7 @@
 #import "components/keyed_service/core/service_access_type.h"
 #import "components/password_manager/core/browser/affiliation/affiliations_prefetcher.h"
 #import "components/password_manager/core/browser/leak_detection/bulk_leak_check_service_interface.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "components/sync/service/sync_service.h"
 #import "ios/web_view/internal/app/application_context.h"
 #import "ios/web_view/internal/autofill/cwv_autofill_data_manager_internal.h"
diff --git a/ios/web_view/internal/passwords/web_view_account_password_store_factory.h b/ios/web_view/internal/passwords/web_view_account_password_store_factory.h
index cbc9ccea..3cc69198 100644
--- a/ios/web_view/internal/passwords/web_view_account_password_store_factory.h
+++ b/ios/web_view/internal/passwords/web_view_account_password_store_factory.h
@@ -9,7 +9,7 @@
 #include "base/no_destructor.h"
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "ios/web_view/internal/web_view_browser_state.h"
 
 namespace ios_web_view {
diff --git a/ios/web_view/internal/passwords/web_view_password_manager_client.h b/ios/web_view/internal/passwords/web_view_password_manager_client.h
index 1dc3d6e..9fb8ce5 100644
--- a/ios/web_view/internal/passwords/web_view_password_manager_client.h
+++ b/ios/web_view/internal/passwords/web_view_password_manager_client.h
@@ -19,7 +19,7 @@
 #include "components/password_manager/core/browser/password_manager_metrics_recorder.h"
 #include "components/password_manager/core/browser/password_requirements_service.h"
 #include "components/password_manager/core/browser/password_reuse_manager.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/browser/sync_credentials_filter.h"
 #include "components/password_manager/ios/password_manager_client_bridge.h"
 #include "components/prefs/pref_member.h"
diff --git a/ios/web_view/internal/passwords/web_view_password_reuse_manager_factory.mm b/ios/web_view/internal/passwords/web_view_password_reuse_manager_factory.mm
index 19c13fbb..be4634d 100644
--- a/ios/web_view/internal/passwords/web_view_password_reuse_manager_factory.mm
+++ b/ios/web_view/internal/passwords/web_view_password_reuse_manager_factory.mm
@@ -9,7 +9,7 @@
 #import "components/keyed_service/core/service_access_type.h"
 #import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "components/password_manager/core/browser/password_reuse_manager_impl.h"
-#import "components/password_manager/core/browser/password_store_interface.h"
+#import "components/password_manager/core/browser/password_store/password_store_interface.h"
 #import "components/password_manager/core/common/password_manager_features.h"
 #import "components/prefs/pref_service.h"
 #import "ios/web_view/internal/app/application_context.h"
diff --git a/ios/web_view/internal/sync/web_view_sync_client.h b/ios/web_view/internal/sync/web_view_sync_client.h
index af91938..a30d8b39 100644
--- a/ios/web_view/internal/sync/web_view_sync_client.h
+++ b/ios/web_view/internal/sync/web_view_sync_client.h
@@ -12,7 +12,7 @@
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/browser_sync/browser_sync_client.h"
 #include "components/browser_sync/sync_api_component_factory_impl.h"
-#include "components/password_manager/core/browser/password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "ios/web_view/internal/web_view_browser_state.h"
 
 namespace ios_web_view {
diff --git a/ios_internal b/ios_internal
index c1c113a..6fedcb8 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit c1c113a56121778292a433076521a87eb30a441d
+Subproject commit 6fedcb89fabbeccebd8c87753620098b0037fcfe
diff --git a/ipc/ipc_channel_mojo.cc b/ipc/ipc_channel_mojo.cc
index b984b1f..7f4f4f9 100644
--- a/ipc/ipc_channel_mojo.cc
+++ b/ipc/ipc_channel_mojo.cc
@@ -312,7 +312,7 @@
 // static
 MojoResult ChannelMojo::ReadFromMessageAttachmentSet(
     Message* message,
-    absl::optional<std::vector<mojo::native::SerializedHandlePtr>>* handles) {
+    std::optional<std::vector<mojo::native::SerializedHandlePtr>>* handles) {
   DCHECK(!*handles);
 
   MojoResult result = MOJO_RESULT_OK;
@@ -341,7 +341,7 @@
 
 // static
 MojoResult ChannelMojo::WriteToMessageAttachmentSet(
-    absl::optional<std::vector<mojo::native::SerializedHandlePtr>> handles,
+    std::optional<std::vector<mojo::native::SerializedHandlePtr>> handles,
     Message* message) {
   if (!handles)
     return MOJO_RESULT_OK;
diff --git a/ipc/ipc_channel_mojo.h b/ipc/ipc_channel_mojo.h
index 2b9c6e3..00a873ff 100644
--- a/ipc/ipc_channel_mojo.h
+++ b/ipc/ipc_channel_mojo.h
@@ -83,11 +83,11 @@
   // These access protected API of IPC::Message, which has ChannelMojo
   // as a friend class.
   static MojoResult WriteToMessageAttachmentSet(
-      absl::optional<std::vector<mojo::native::SerializedHandlePtr>> handles,
+      std::optional<std::vector<mojo::native::SerializedHandlePtr>> handles,
       Message* message);
   static MojoResult ReadFromMessageAttachmentSet(
       Message* message,
-      absl::optional<std::vector<mojo::native::SerializedHandlePtr>>* handles);
+      std::optional<std::vector<mojo::native::SerializedHandlePtr>>* handles);
 
   // MessagePipeReader::Delegate
   void OnPeerPidReceived(int32_t peer_pid) override;
diff --git a/ipc/ipc_channel_mojo_unittest.cc b/ipc/ipc_channel_mojo_unittest.cc
index b1731f3..02c80518 100644
--- a/ipc/ipc_channel_mojo_unittest.cc
+++ b/ipc/ipc_channel_mojo_unittest.cc
@@ -12,6 +12,7 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "base/base_paths.h"
 #include "base/containers/queue.h"
 #include "base/files/file.h"
@@ -59,7 +60,6 @@
 #include "mojo/public/cpp/system/functions.h"
 #include "mojo/public/cpp/system/wait.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
 #include "base/file_descriptor_posix.h"
@@ -349,8 +349,8 @@
 
   // NOTE: We can't create a RunLoop before Init() is called, but we have to set
   // the default ProcessErrorCallback (which we want to reference the RunLoop)
-  // before Init() launches a child process. Hence the absl::optional here.
-  absl::optional<base::RunLoop> wait_for_error_loop;
+  // before Init() launches a child process. Hence the std::optional here.
+  std::optional<base::RunLoop> wait_for_error_loop;
   bool process_error_received = false;
   mojo::SetDefaultProcessErrorHandler(
       base::BindLambdaForTesting([&](const std::string&) {
diff --git a/ipc/ipc_message_pipe_reader.cc b/ipc/ipc_message_pipe_reader.cc
index 7f30d677a..dc7f480 100644
--- a/ipc/ipc_message_pipe_reader.cc
+++ b/ipc/ipc_message_pipe_reader.cc
@@ -109,7 +109,7 @@
   CHECK(message->IsValid());
   TRACE_EVENT_WITH_FLOW0("toplevel.flow", "MessagePipeReader::Send",
                          message->flags(), TRACE_EVENT_FLAG_FLOW_OUT);
-  absl::optional<std::vector<mojo::native::SerializedHandlePtr>> handles;
+  std::optional<std::vector<mojo::native::SerializedHandlePtr>> handles;
   MojoResult result = MOJO_RESULT_OK;
   result = ChannelMojo::ReadFromMessageAttachmentSet(message.get(), &handles);
   if (result != MOJO_RESULT_OK)
diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc
index 81b77d3..c17f4dd 100644
--- a/ipc/ipc_message_utils.cc
+++ b/ipc/ipc_message_utils.cc
@@ -281,7 +281,7 @@
       break;
     }
     case base::Value::Type::BINARY: {
-      absl::optional<base::span<const uint8_t>> data = iter->ReadData();
+      std::optional<base::span<const uint8_t>> data = iter->ReadData();
       if (!data) {
         return false;
       }
@@ -1322,7 +1322,7 @@
   // This is not mapped as nullable_is_same_type, so any UnguessableToken
   // deserialized by the traits should always yield a non-empty token.
   // If deserialization results in an empty token, the data is malformed.
-  absl::optional<base::UnguessableToken> token =
+  std::optional<base::UnguessableToken> token =
       base::UnguessableToken::Deserialize(high, low);
   if (!token.has_value()) {
     return false;
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
index a85db9b8..8a2de76 100644
--- a/ipc/ipc_message_utils.h
+++ b/ipc/ipc_message_utils.h
@@ -17,6 +17,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include <optional>
 #include "base/check.h"
 #include "base/compiler_specific.h"
 #include "base/component_export.h"
@@ -34,7 +35,6 @@
 #include "ipc/ipc_buildflags.h"
 #include "ipc/ipc_param_traits.h"
 #include "third_party/abseil-cpp/absl/container/inlined_vector.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(IS_ANDROID)
 #include "base/android/scoped_hardware_buffer_handle.h"
@@ -973,8 +973,8 @@
 // absl types ParamTraits
 
 template <class P>
-struct ParamTraits<absl::optional<P>> {
-  typedef absl::optional<P> param_type;
+struct ParamTraits<std::optional<P>> {
+  typedef std::optional<P> param_type;
   static void Write(base::Pickle* m, const param_type& p) {
     const bool is_set = static_cast<bool>(p);
     WriteParam(m, is_set);
diff --git a/ipc/ipc_message_utils_unittest.cc b/ipc/ipc_message_utils_unittest.cc
index 5485c21..ec98f48 100644
--- a/ipc/ipc_message_utils_unittest.cc
+++ b/ipc/ipc_message_utils_unittest.cc
@@ -117,7 +117,7 @@
 }
 
 TEST(IPCMessageUtilsTest, OptionalUnset) {
-  absl::optional<int> opt;
+  std::optional<int> opt;
   base::Pickle pickle;
   IPC::WriteParam(&pickle, opt);
 
@@ -125,14 +125,14 @@
   IPC::LogParam(opt, &log);
   EXPECT_EQ("(unset)", log);
 
-  absl::optional<int> unserialized_opt;
+  std::optional<int> unserialized_opt;
   base::PickleIterator iter(pickle);
   EXPECT_TRUE(IPC::ReadParam(&pickle, &iter, &unserialized_opt));
   EXPECT_FALSE(unserialized_opt);
 }
 
 TEST(IPCMessageUtilsTest, OptionalSet) {
-  absl::optional<int> opt(10);
+  std::optional<int> opt(10);
   base::Pickle pickle;
   IPC::WriteParam(&pickle, opt);
 
@@ -140,7 +140,7 @@
   IPC::LogParam(opt, &log);
   EXPECT_EQ("10", log);
 
-  absl::optional<int> unserialized_opt;
+  std::optional<int> unserialized_opt;
   base::PickleIterator iter(pickle);
   EXPECT_TRUE(IPC::ReadParam(&pickle, &iter, &unserialized_opt));
   EXPECT_TRUE(unserialized_opt);
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
index 360901a..c394c62d 100644
--- a/ipc/ipc_mojo_bootstrap.cc
+++ b/ipc/ipc_mojo_bootstrap.cc
@@ -13,6 +13,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/check_op.h"
 #include "base/containers/circular_deque.h"
 #include "base/containers/contains.h"
@@ -50,7 +51,6 @@
 #include "mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h"
 #include "mojo/public/cpp/bindings/tracing_helpers.h"
 #include "third_party/abseil-cpp/absl/base/attributes.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace IPC {
 
@@ -363,7 +363,7 @@
 
   void CloseEndpointHandle(
       mojo::InterfaceId id,
-      const absl::optional<mojo::DisconnectReason>& reason) override {
+      const std::optional<mojo::DisconnectReason>& reason) override {
     if (!mojo::IsValidInterfaceId(id))
       return;
     {
@@ -539,12 +539,12 @@
       handle_created_ = true;
     }
 
-    const absl::optional<mojo::DisconnectReason>& disconnect_reason() const {
+    const std::optional<mojo::DisconnectReason>& disconnect_reason() const {
       return disconnect_reason_;
     }
 
     void set_disconnect_reason(
-        const absl::optional<mojo::DisconnectReason>& disconnect_reason) {
+        const std::optional<mojo::DisconnectReason>& disconnect_reason) {
       disconnect_reason_ = disconnect_reason;
     }
 
@@ -583,11 +583,11 @@
       sync_watcher_.reset();
     }
 
-    absl::optional<uint32_t> EnqueueSyncMessage(MessageWrapper message) {
+    std::optional<uint32_t> EnqueueSyncMessage(MessageWrapper message) {
       controller_->lock_.AssertAcquired();
       if (exclusive_wait_ && exclusive_wait_->TryFulfillingWith(message)) {
         exclusive_wait_ = nullptr;
-        return absl::nullopt;
+        return std::nullopt;
       }
 
       uint32_t id = GenerateSyncMessageId();
@@ -645,7 +645,7 @@
     }
 
     MessageWrapper WaitForIncomingSyncReply(uint64_t request_id) {
-      absl::optional<ExclusiveSyncWait> wait;
+      std::optional<ExclusiveSyncWait> wait;
       {
         base::AutoLock lock(controller_->lock_);
         for (auto& [id, message] : sync_messages_) {
@@ -785,7 +785,7 @@
     bool peer_closed_ = false;
     bool handle_created_ = false;
     bool was_bound_off_sequence_ = false;
-    absl::optional<mojo::DisconnectReason> disconnect_reason_;
+    std::optional<mojo::DisconnectReason> disconnect_reason_;
     raw_ptr<mojo::InterfaceEndpointClient> client_ = nullptr;
     scoped_refptr<base::SequencedTaskRunner> task_runner_;
     std::unique_ptr<mojo::SequenceLocalSyncEventWatcher> sync_watcher_;
@@ -909,7 +909,7 @@
     DCHECK(endpoint->task_runner() && endpoint->client());
     if (endpoint->task_runner()->RunsTasksInCurrentSequence() && !force_async) {
       mojo::InterfaceEndpointClient* client = endpoint->client();
-      absl::optional<mojo::DisconnectReason> reason(
+      std::optional<mojo::DisconnectReason> reason(
           endpoint->disconnect_reason());
 
       base::AutoUnlock unlocker(lock_);
@@ -1051,7 +1051,7 @@
         // sync message queue. If the endpoint was blocking, it will dequeue the
         // message and dispatch it. Otherwise the posted |AcceptSyncMessage()|
         // call will dequeue the message and dispatch it.
-        absl::optional<uint32_t> message_id =
+        std::optional<uint32_t> message_id =
             endpoint->EnqueueSyncMessage(std::move(message_wrapper));
         if (message_id) {
           task_runner->PostTask(
@@ -1189,7 +1189,7 @@
   // mojo::PipeControlMessageHandlerDelegate:
   bool OnPeerAssociatedEndpointClosed(
       mojo::InterfaceId id,
-      const absl::optional<mojo::DisconnectReason>& reason) override {
+      const std::optional<mojo::DisconnectReason>& reason) override {
     DCHECK(thread_checker_.CalledOnValidThread());
 
     scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
diff --git a/ipc/ipc_mojo_bootstrap_unittest.cc b/ipc/ipc_mojo_bootstrap_unittest.cc
index f7bd5f5c..1736067 100644
--- a/ipc/ipc_mojo_bootstrap_unittest.cc
+++ b/ipc/ipc_mojo_bootstrap_unittest.cc
@@ -206,8 +206,8 @@
   auto& sender = connection.GetSender();
 
   uint8_t data = 0;
-  sender->Receive(IPC::MessageView(base::make_span(&data, 0u),
-                                   absl::nullopt /* handles */));
+  sender->Receive(
+      IPC::MessageView(base::make_span(&data, 0u), std::nullopt /* handles */));
 
   base::RunLoop run_loop;
   PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
diff --git a/ipc/message_mojom_traits.cc b/ipc/message_mojom_traits.cc
index 8b94705..5a59b59 100644
--- a/ipc/message_mojom_traits.cc
+++ b/ipc/message_mojom_traits.cc
@@ -14,7 +14,7 @@
 }
 
 // static
-absl::optional<std::vector<mojo::native::SerializedHandlePtr>>
+std::optional<std::vector<mojo::native::SerializedHandlePtr>>
 StructTraits<IPC::mojom::MessageDataView, IPC::MessageView>::handles(
     IPC::MessageView& view) {
   return view.TakeHandles();
@@ -27,7 +27,7 @@
   mojo::ArrayDataView<uint8_t> bytes;
   data.GetBytesDataView(&bytes);
 
-  absl::optional<std::vector<mojo::native::SerializedHandlePtr>> handles;
+  std::optional<std::vector<mojo::native::SerializedHandlePtr>> handles;
   if (!data.ReadHandles(&handles))
     return false;
 
diff --git a/ipc/message_mojom_traits.h b/ipc/message_mojom_traits.h
index 4b5c671..0e71969 100644
--- a/ipc/message_mojom_traits.h
+++ b/ipc/message_mojom_traits.h
@@ -7,12 +7,12 @@
 
 #include <vector>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "ipc/ipc.mojom-shared.h"
 #include "ipc/message_view.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "mojo/public/interfaces/bindings/native_struct.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 
@@ -20,7 +20,7 @@
 class StructTraits<IPC::mojom::MessageDataView, IPC::MessageView> {
  public:
   static base::span<const uint8_t> bytes(IPC::MessageView& view);
-  static absl::optional<std::vector<mojo::native::SerializedHandlePtr>> handles(
+  static std::optional<std::vector<mojo::native::SerializedHandlePtr>> handles(
       IPC::MessageView& view);
 
   static bool Read(IPC::mojom::MessageDataView data, IPC::MessageView* out);
diff --git a/ipc/message_view.cc b/ipc/message_view.cc
index 7cb859a..7b38621 100644
--- a/ipc/message_view.cc
+++ b/ipc/message_view.cc
@@ -12,7 +12,7 @@
 
 MessageView::MessageView(
     base::span<const uint8_t> bytes,
-    absl::optional<std::vector<mojo::native::SerializedHandlePtr>> handles)
+    std::optional<std::vector<mojo::native::SerializedHandlePtr>> handles)
     : bytes_(bytes), handles_(std::move(handles)) {}
 
 MessageView::MessageView(MessageView&&) = default;
@@ -21,7 +21,7 @@
 
 MessageView& MessageView::operator=(MessageView&&) = default;
 
-absl::optional<std::vector<mojo::native::SerializedHandlePtr>>
+std::optional<std::vector<mojo::native::SerializedHandlePtr>>
 MessageView::TakeHandles() {
   return std::move(handles_);
 }
diff --git a/ipc/message_view.h b/ipc/message_view.h
index 55276b9..67f394f8 100644
--- a/ipc/message_view.h
+++ b/ipc/message_view.h
@@ -7,11 +7,11 @@
 
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/containers/span.h"
 #include "ipc/ipc_message.h"
 #include "mojo/public/interfaces/bindings/native_struct.mojom-forward.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace IPC {
 
@@ -20,7 +20,7 @@
   MessageView();
   MessageView(
       base::span<const uint8_t> bytes,
-      absl::optional<std::vector<mojo::native::SerializedHandlePtr>> handles);
+      std::optional<std::vector<mojo::native::SerializedHandlePtr>> handles);
   MessageView(MessageView&&);
 
   MessageView(const MessageView&) = delete;
@@ -31,11 +31,11 @@
   MessageView& operator=(MessageView&&);
 
   base::span<const uint8_t> bytes() const { return bytes_; }
-  absl::optional<std::vector<mojo::native::SerializedHandlePtr>> TakeHandles();
+  std::optional<std::vector<mojo::native::SerializedHandlePtr>> TakeHandles();
 
  private:
   base::span<const uint8_t> bytes_;
-  absl::optional<std::vector<mojo::native::SerializedHandlePtr>> handles_;
+  std::optional<std::vector<mojo::native::SerializedHandlePtr>> handles_;
 };
 
 }  // namespace IPC
diff --git a/mojo/core/broker_posix.cc b/mojo/core/broker_posix.cc
index 26c7c2d7..98713e4 100644
--- a/mojo/core/broker_posix.cc
+++ b/mojo/core/broker_posix.cc
@@ -133,7 +133,7 @@
     const BufferResponseData* data;
     if (!GetBrokerMessageData(message.get(), &data))
       return base::WritableSharedMemoryRegion();
-    absl::optional<base::UnguessableToken> guid =
+    std::optional<base::UnguessableToken> guid =
         base::UnguessableToken::Deserialize(data->guid_high, data->guid_low);
     if (!guid.has_value()) {
       return base::WritableSharedMemoryRegion();
diff --git a/mojo/core/broker_win.cc b/mojo/core/broker_win.cc
index f9e95020..be287e68 100644
--- a/mojo/core/broker_win.cc
+++ b/mojo/core/broker_win.cc
@@ -150,7 +150,7 @@
     BufferResponseData* data;
     if (!GetBrokerMessageData(response.get(), &data))
       return base::WritableSharedMemoryRegion();
-    absl::optional<base::UnguessableToken> guid =
+    std::optional<base::UnguessableToken> guid =
         base::UnguessableToken::Deserialize(data->guid_high, data->guid_low);
     if (!guid.has_value()) {
       return base::WritableSharedMemoryRegion();
diff --git a/mojo/core/channel_unittest.cc b/mojo/core/channel_unittest.cc
index 6bb1cd3..2384f4b 100644
--- a/mojo/core/channel_unittest.cc
+++ b/mojo/core/channel_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <atomic>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/memory/page_size.h"
 #include "base/memory/ptr_util.h"
@@ -22,7 +23,6 @@
 #include "mojo/public/cpp/platform/platform_channel.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace core {
@@ -320,7 +320,7 @@
 
  private:
   size_t num_messages_ = 0;
-  absl::optional<base::RunLoop> wait_for_error_loop_;
+  std::optional<base::RunLoop> wait_for_error_loop_;
 };
 
 TEST(ChannelTest, RejectHandles) {
diff --git a/mojo/core/core.cc b/mojo/core/core.cc
index f1ec7b9..cca2027 100644
--- a/mojo/core/core.cc
+++ b/mojo/core/core.cc
@@ -1047,7 +1047,7 @@
   if (!handles_ok)
     return MOJO_RESULT_INVALID_ARGUMENT;
 
-  absl::optional<base::UnguessableToken> token =
+  std::optional<base::UnguessableToken> token =
       mojo::internal::PlatformHandleInternal::UnmarshalUnguessableToken(guid);
   if (!token.has_value()) {
     return MOJO_RESULT_INVALID_ARGUMENT;
diff --git a/mojo/core/core_ipcz.cc b/mojo/core/core_ipcz.cc
index 17c02f9..7acd38a1 100644
--- a/mojo/core/core_ipcz.cc
+++ b/mojo/core/core_ipcz.cc
@@ -397,7 +397,7 @@
       config.byte_capacity < config.element_size) {
     return MOJO_RESULT_INVALID_ARGUMENT;
   }
-  absl::optional<DataPipe::Pair> pipe = DataPipe::CreatePair(config);
+  std::optional<DataPipe::Pair> pipe = DataPipe::CreatePair(config);
   if (!pipe) {
     // This result implies that we failed to allocate or map a new shared memory
     // region and therefore have no transfer buffer for the pipe.
diff --git a/mojo/core/data_pipe_consumer_dispatcher.cc b/mojo/core/data_pipe_consumer_dispatcher.cc
index ba0e8eed..2247436 100644
--- a/mojo/core/data_pipe_consumer_dispatcher.cc
+++ b/mojo/core/data_pipe_consumer_dispatcher.cc
@@ -390,7 +390,7 @@
     return nullptr;
   }
 
-  absl::optional<base::UnguessableToken> buffer_guid =
+  std::optional<base::UnguessableToken> buffer_guid =
       base::UnguessableToken::Deserialize(state->buffer_guid_high,
                                           state->buffer_guid_low);
   if (!buffer_guid.has_value()) {
diff --git a/mojo/core/data_pipe_producer_dispatcher.cc b/mojo/core/data_pipe_producer_dispatcher.cc
index 1a54b1a..398db64 100644
--- a/mojo/core/data_pipe_producer_dispatcher.cc
+++ b/mojo/core/data_pipe_producer_dispatcher.cc
@@ -351,7 +351,7 @@
     return nullptr;
   }
 
-  absl::optional<base::UnguessableToken> buffer_guid =
+  std::optional<base::UnguessableToken> buffer_guid =
       base::UnguessableToken::Deserialize(state->buffer_guid_high,
                                           state->buffer_guid_low);
   if (!buffer_guid.has_value()) {
diff --git a/mojo/core/invitation_unittest.cc b/mojo/core/invitation_unittest.cc
index 507de6bc..fab7e00 100644
--- a/mojo/core/invitation_unittest.cc
+++ b/mojo/core/invitation_unittest.cc
@@ -6,6 +6,7 @@
 #include <cstring>
 #include <string>
 
+#include <optional>
 #include "base/base_paths.h"
 #include "base/base_switches.h"
 #include "base/check_op.h"
@@ -42,7 +43,6 @@
 #include "mojo/public/cpp/system/invitation.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "mojo/public/cpp/system/platform_handle.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(MOJO_USE_APPLE_CHANNEL)
 #include "base/mac/mach_port_rendezvous.h"
diff --git a/mojo/core/ipcz_driver/data_pipe.cc b/mojo/core/ipcz_driver/data_pipe.cc
index 62f9196f..a4413a80 100644
--- a/mojo/core/ipcz_driver/data_pipe.cc
+++ b/mojo/core/ipcz_driver/data_pipe.cc
@@ -11,6 +11,7 @@
 #include <limits>
 #include <tuple>
 
+#include <optional>
 #include "base/check.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/unsafe_shared_memory_region.h"
@@ -18,7 +19,6 @@
 #include "base/synchronization/lock.h"
 #include "mojo/core/ipcz_api.h"
 #include "mojo/core/ipcz_driver/ring_buffer.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/ipcz/include/ipcz/ipcz.h"
 
 namespace mojo::core::ipcz_driver {
@@ -140,7 +140,7 @@
 }
 
 // static
-absl::optional<DataPipe::Pair> DataPipe::CreatePair(const Config& config) {
+std::optional<DataPipe::Pair> DataPipe::CreatePair(const Config& config) {
   ScopedIpczHandle producer;
   ScopedIpczHandle consumer;
   const IpczResult result =
@@ -152,12 +152,12 @@
   base::UnsafeSharedMemoryRegion consumer_region =
       base::UnsafeSharedMemoryRegion::Create(config.byte_capacity);
   if (!consumer_region.IsValid()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   base::UnsafeSharedMemoryRegion producer_region = consumer_region.Duplicate();
   if (!producer_region.IsValid()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   scoped_refptr<SharedBuffer> consumer_buffer =
@@ -169,7 +169,7 @@
   auto producer_mapping =
       SharedBufferMapping::Create(producer_buffer->region());
   if (!consumer_mapping || !producer_mapping) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   Pair pair;
diff --git a/mojo/core/ipcz_driver/data_pipe.h b/mojo/core/ipcz_driver/data_pipe.h
index c4a67eb0..389005b 100644
--- a/mojo/core/ipcz_driver/data_pipe.h
+++ b/mojo/core/ipcz_driver/data_pipe.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/synchronization/lock.h"
@@ -19,7 +20,6 @@
 #include "mojo/core/scoped_ipcz_handle.h"
 #include "mojo/public/c/system/data_pipe.h"
 #include "mojo/public/c/system/types.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/ipcz/include/ipcz/ipcz.h"
 
 namespace mojo::core::ipcz_driver {
@@ -103,7 +103,7 @@
     scoped_refptr<DataPipe> consumer;
     scoped_refptr<DataPipe> producer;
   };
-  static absl::optional<Pair> CreatePair(const Config& config);
+  static std::optional<Pair> CreatePair(const Config& config);
 
   bool is_producer() const { return endpoint_type_ == EndpointType::kProducer; }
   bool is_consumer() const { return endpoint_type_ == EndpointType::kConsumer; }
@@ -181,8 +181,8 @@
   // data pipe endpoint's local cache of the buffer state.
   scoped_refptr<SharedBuffer> buffer_ GUARDED_BY(lock_);
   RingBuffer data_ GUARDED_BY(lock_);
-  absl::optional<RingBuffer::DirectWriter> two_phase_writer_;
-  absl::optional<RingBuffer::DirectReader> two_phase_reader_;
+  std::optional<RingBuffer::DirectWriter> two_phase_writer_;
+  std::optional<RingBuffer::DirectReader> two_phase_reader_;
 
   // Indicates whether this endpoint is in the process of being serialized and
   // transmitted elsewhere.
diff --git a/mojo/core/ipcz_driver/driver_for_ipcz_tests.cc b/mojo/core/ipcz_driver/driver_for_ipcz_tests.cc
index cfe77d73..ba2d6a7 100644
--- a/mojo/core/ipcz_driver/driver_for_ipcz_tests.cc
+++ b/mojo/core/ipcz_driver/driver_for_ipcz_tests.cc
@@ -147,7 +147,7 @@
   const raw_ref<ipcz::test::TestNode> source_;
   const bool is_broker_;
   base::Process process_;
-  absl::optional<bool> result_;
+  std::optional<bool> result_;
 };
 
 // TestDriver implementation for the mojo-ipcz driver to have coverage in ipcz'
diff --git a/mojo/core/ipcz_driver/mojo_trap.cc b/mojo/core/ipcz_driver/mojo_trap.cc
index 7a5765a..1cc82ef 100644
--- a/mojo/core/ipcz_driver/mojo_trap.cc
+++ b/mojo/core/ipcz_driver/mojo_trap.cc
@@ -8,6 +8,7 @@
 #include <tuple>
 #include <utility>
 
+#include <optional>
 #include "base/check_op.h"
 #include "base/memory/ref_counted.h"
 #include "base/notreached.h"
@@ -15,7 +16,6 @@
 #include "base/threading/thread_restrictions.h"
 #include "mojo/core/ipcz_api.h"
 #include "mojo/core/ipcz_driver/data_pipe.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/ipcz/include/ipcz/ipcz.h"
 
 namespace mojo::core::ipcz_driver {
diff --git a/mojo/core/ipcz_driver/mojo_trap.h b/mojo/core/ipcz_driver/mojo_trap.h
index c800fecf..e226ae6 100644
--- a/mojo/core/ipcz_driver/mojo_trap.h
+++ b/mojo/core/ipcz_driver/mojo_trap.h
@@ -7,6 +7,7 @@
 
 #include <cstdint>
 
+#include <optional>
 #include "base/containers/flat_map.h"
 #include "base/containers/span.h"
 #include "base/memory/scoped_refptr.h"
@@ -17,7 +18,6 @@
 #include "mojo/public/c/system/trap.h"
 #include "mojo/public/c/system/types.h"
 #include "third_party/abseil-cpp/absl/container/inlined_vector.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/ipcz/include/ipcz/ipcz.h"
 
 namespace mojo::core::ipcz_driver {
@@ -89,7 +89,7 @@
 
   // A ref identifying the thread which is currently dispatching an event for
   // this trap, if any.
-  absl::optional<base::PlatformThreadRef> dispatching_thread_ GUARDED_BY(lock_);
+  std::optional<base::PlatformThreadRef> dispatching_thread_ GUARDED_BY(lock_);
 
   using TriggerMap = base::flat_map<uintptr_t, scoped_refptr<Trigger>>;
   TriggerMap triggers_ GUARDED_BY(lock_);
diff --git a/mojo/core/ipcz_driver/ring_buffer_test.cc b/mojo/core/ipcz_driver/ring_buffer_test.cc
index 6c91455..2ba6301 100644
--- a/mojo/core/ipcz_driver/ring_buffer_test.cc
+++ b/mojo/core/ipcz_driver/ring_buffer_test.cc
@@ -10,6 +10,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/memory/unsafe_shared_memory_region.h"
 #include "base/ranges/algorithm.h"
@@ -17,7 +18,6 @@
 #include "mojo/core/ipcz_driver/shared_buffer.h"
 #include "mojo/core/ipcz_driver/shared_buffer_mapping.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo::core::ipcz_driver {
 namespace {
@@ -53,10 +53,10 @@
     return std::string(AsString(bytes.first(size)));
   }
 
-  absl::optional<std::string> ReadAll(size_t n) {
+  std::optional<std::string> ReadAll(size_t n) {
     std::vector<uint8_t> data(n);
     if (!buffer_.ReadAll(base::make_span(data))) {
-      return absl::nullopt;
+      return std::nullopt;
     }
     return std::string(data.begin(), data.end());
   }
@@ -68,10 +68,10 @@
     return std::string(AsString(bytes.first(size)));
   }
 
-  absl::optional<std::string> PeekAll(size_t n) {
+  std::optional<std::string> PeekAll(size_t n) {
     std::vector<uint8_t> data(n);
     if (!buffer_.PeekAll(base::make_span(data))) {
-      return absl::nullopt;
+      return std::nullopt;
     }
     return std::string(data.begin(), data.end());
   }
diff --git a/mojo/core/ipcz_driver/shared_buffer.cc b/mojo/core/ipcz_driver/shared_buffer.cc
index 510a7f20..879fafd 100644
--- a/mojo/core/ipcz_driver/shared_buffer.cc
+++ b/mojo/core/ipcz_driver/shared_buffer.cc
@@ -136,7 +136,7 @@
       return nullptr;
   }
 
-  absl::optional<base::UnguessableToken> guid =
+  std::optional<base::UnguessableToken> guid =
       base::UnguessableToken::Deserialize(mojo_guid.high, mojo_guid.low);
   if (!guid.has_value()) {
     return nullptr;
@@ -261,7 +261,7 @@
       return nullptr;
   }
 
-  absl::optional<base::UnguessableToken> guid =
+  std::optional<base::UnguessableToken> guid =
       base::UnguessableToken::Deserialize(header.guid_high, header.guid_low);
   if (!guid.has_value()) {
     return nullptr;
diff --git a/mojo/core/message_pipe_dispatcher.cc b/mojo/core/message_pipe_dispatcher.cc
index 440903b..c74d8b08 100644
--- a/mojo/core/message_pipe_dispatcher.cc
+++ b/mojo/core/message_pipe_dispatcher.cc
@@ -202,7 +202,7 @@
 }
 
 MojoResult MessagePipeDispatcher::SetQuota(MojoQuotaType type, uint64_t limit) {
-  absl::optional<uint64_t> new_ack_request_interval;
+  std::optional<uint64_t> new_ack_request_interval;
   {
     base::AutoLock lock(signal_lock_);
     switch (type) {
diff --git a/mojo/core/message_pipe_dispatcher.h b/mojo/core/message_pipe_dispatcher.h
index 8a9a697..b171331 100644
--- a/mojo/core/message_pipe_dispatcher.h
+++ b/mojo/core/message_pipe_dispatcher.h
@@ -10,12 +10,12 @@
 #include <memory>
 #include <queue>
 
+#include <optional>
 #include "base/memory/raw_ptr_exclusion.h"
 #include "mojo/core/atomic_flag.h"
 #include "mojo/core/dispatcher.h"
 #include "mojo/core/ports/port_ref.h"
 #include "mojo/core/watcher_set.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace core {
@@ -110,9 +110,9 @@
   bool port_transferred_ = false;
   AtomicFlag port_closed_;
   WatcherSet watchers_;
-  absl::optional<uint64_t> receive_queue_length_limit_;
-  absl::optional<uint64_t> receive_queue_memory_size_limit_;
-  absl::optional<uint64_t> unread_message_count_limit_;
+  std::optional<uint64_t> receive_queue_length_limit_;
+  std::optional<uint64_t> receive_queue_memory_size_limit_;
+  std::optional<uint64_t> unread_message_count_limit_;
 };
 
 }  // namespace core
diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc
index 774a095..568df5a 100644
--- a/mojo/core/node_controller.cc
+++ b/mojo/core/node_controller.cc
@@ -7,6 +7,7 @@
 #include <limits>
 #include <vector>
 
+#include <optional>
 #include "base/containers/contains.h"
 #include "base/containers/queue.h"
 #include "base/functional/bind.h"
@@ -29,7 +30,6 @@
 #include "mojo/public/cpp/platform/named_platform_channel.h"
 #include "mojo/public/cpp/platform/platform_channel.h"
 #include "mojo/public/cpp/platform/platform_channel_server.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(IS_WIN)
 #include <windows.h>
@@ -151,7 +151,7 @@
 };
 
 #if !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_FUCHSIA)
-absl::optional<ConnectionParams> CreateSyncNodeConnectionParams(
+std::optional<ConnectionParams> CreateSyncNodeConnectionParams(
     const base::Process& target_process,
     ConnectionParams connection_params,
     const ProcessErrorCallback& process_error_callback,
@@ -172,7 +172,7 @@
   node_connection_params.set_is_untrusted_process(is_untrusted_process);
   if (!broker_host->SendChannel(
           node_channel.TakeRemoteEndpoint().TakePlatformHandle())) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return node_connection_params;
@@ -225,7 +225,7 @@
 
 void NodeController::AcceptBrokerClientInvitation(
     ConnectionParams connection_params) {
-  absl::optional<PlatformHandle> broker_host_handle;
+  std::optional<PlatformHandle> broker_host_handle;
   DCHECK(!GetConfiguration().is_broker_process);
 #if !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_FUCHSIA)
   if (!connection_params.is_async()) {
@@ -464,7 +464,7 @@
     }
 #endif
 
-    absl::optional<ConnectionParams> params = CreateSyncNodeConnectionParams(
+    std::optional<ConnectionParams> params = CreateSyncNodeConnectionParams(
         target_process, std::move(connection_params), process_error_callback,
         handle_policy);
     if (!params) {
@@ -514,7 +514,7 @@
 
 void NodeController::AcceptBrokerClientInvitationOnIOThread(
     ConnectionParams connection_params,
-    absl::optional<PlatformHandle> broker_host_handle) {
+    std::optional<PlatformHandle> broker_host_handle) {
   DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
 
   {
diff --git a/mojo/core/node_controller.h b/mojo/core/node_controller.h
index 70a914c..a8b6a8f 100644
--- a/mojo/core/node_controller.h
+++ b/mojo/core/node_controller.h
@@ -13,6 +13,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/containers/queue.h"
 #include "base/containers/span.h"
 #include "base/functional/callback.h"
@@ -29,7 +30,6 @@
 #include "mojo/core/ports/node_delegate.h"
 #include "mojo/core/system_impl_export.h"
 #include "mojo/public/cpp/platform/platform_handle.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace core {
@@ -199,7 +199,7 @@
 
   void AcceptBrokerClientInvitationOnIOThread(
       ConnectionParams connection_params,
-      absl::optional<PlatformHandle> broker_host_handle);
+      std::optional<PlatformHandle> broker_host_handle);
 
   void ConnectIsolatedOnIOThread(ConnectionParams connection_params,
                                  ports::PortRef port,
diff --git a/mojo/core/platform_wrapper_unittest.cc b/mojo/core/platform_wrapper_unittest.cc
index 82372876..34818e6 100644
--- a/mojo/core/platform_wrapper_unittest.cc
+++ b/mojo/core/platform_wrapper_unittest.cc
@@ -202,7 +202,7 @@
   EXPECT_EQ(MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_UNSAFE, access_mode);
 
   auto mode = base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe;
-  absl::optional<base::UnguessableToken> guid =
+  std::optional<base::UnguessableToken> guid =
       base::UnguessableToken::Deserialize(mojo_guid.high, mojo_guid.low);
   ASSERT_TRUE(guid.has_value());
 #if BUILDFLAG(IS_WIN)
diff --git a/mojo/core/ports/node.cc b/mojo/core/ports/node.cc
index 224cdfe..4e16b56 100644
--- a/mojo/core/ports/node.cc
+++ b/mojo/core/ports/node.cc
@@ -12,6 +12,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
@@ -23,7 +24,6 @@
 #include "mojo/core/ports/node_delegate.h"
 #include "mojo/core/ports/port_locker.h"
 #include "third_party/abseil-cpp/absl/container/inlined_vector.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if !BUILDFLAG(IS_NACL)
 #include "crypto/random.h"
@@ -1290,7 +1290,7 @@
     PortLocker::AssertNoPortsLockedOnCurrentThread();
     base::ReleasableAutoLock ports_locker(&ports_lock_);
 
-    absl::optional<PortLocker> locker(absl::in_place, port_refs, 2);
+    std::optional<PortLocker> locker(std::in_place, port_refs, 2);
     auto* port0 = locker->GetPort(port0_ref);
     auto* port1 = locker->GetPort(port1_ref);
 
diff --git a/mojo/core/run_all_core_unittests.cc b/mojo/core/run_all_core_unittests.cc
index 03ec406a..e5da67a1 100644
--- a/mojo/core/run_all_core_unittests.cc
+++ b/mojo/core/run_all_core_unittests.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <optional>
 #include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
@@ -15,7 +16,6 @@
 #include "mojo/core/mojo_core_unittest.h"
 #include "mojo/public/c/system/core.h"
 #include "mojo/public/cpp/system/dynamic_library_support.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 base::FilePath GetMojoCoreLibraryPath() {
 #if BUILDFLAG(IS_FUCHSIA)
@@ -48,7 +48,7 @@
   if (!command_line.HasSwitch(switches::kTestChildProcess))
     flags |= MOJO_INITIALIZE_FLAG_AS_BROKER;
 
-  absl::optional<base::FilePath> library_path;
+  std::optional<base::FilePath> library_path;
   if (command_line.HasSwitch(switches::kMojoUseExplicitLibraryPath))
     library_path = GetMojoCoreLibraryPath();
 
diff --git a/mojo/core/shared_buffer_dispatcher.cc b/mojo/core/shared_buffer_dispatcher.cc
index b1c2777..ab30a68 100644
--- a/mojo/core/shared_buffer_dispatcher.cc
+++ b/mojo/core/shared_buffer_dispatcher.cc
@@ -165,7 +165,7 @@
 #endif
   handles[0] = std::move(platform_handles[0]);
 
-  absl::optional<base::UnguessableToken> guid =
+  std::optional<base::UnguessableToken> guid =
       base::UnguessableToken::Deserialize(serialized_state->guid_high,
                                           serialized_state->guid_low);
   if (!guid.has_value()) {
diff --git a/mojo/core/watcher_set.h b/mojo/core/watcher_set.h
index 9af52e3..890c164 100644
--- a/mojo/core/watcher_set.h
+++ b/mojo/core/watcher_set.h
@@ -5,12 +5,12 @@
 #ifndef MOJO_CORE_WATCHER_SET_H_
 #define MOJO_CORE_WATCHER_SET_H_
 
+#include <optional>
 #include "base/containers/flat_map.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
 #include "mojo/core/handle_signals_state.h"
 #include "mojo/core/watcher_dispatcher.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace core {
@@ -65,7 +65,7 @@
 
   const raw_ptr<Dispatcher> owner_;
   base::flat_map<WatcherDispatcher*, Entry> watchers_;
-  absl::optional<HandleSignalsState> last_known_state_;
+  std::optional<HandleSignalsState> last_known_state_;
 };
 
 }  // namespace core
diff --git a/mojo/public/c/system/thunks.cc b/mojo/public/c/system/thunks.cc
index f0c568e1..30f8f9c 100644
--- a/mojo/public/c/system/thunks.cc
+++ b/mojo/public/c/system/thunks.cc
@@ -25,11 +25,11 @@
 
 #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || \
     BUILDFLAG(IS_FUCHSIA)
+#include <optional>
 #include "base/environment.h"
 #include "base/files/file_path.h"
 #include "base/scoped_native_library.h"
 #include "base/threading/thread_restrictions.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #endif
 
 namespace {
@@ -144,7 +144,7 @@
  private:
 #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || \
     BUILDFLAG(IS_FUCHSIA)
-  absl::optional<base::ScopedNativeLibrary> library_;
+  std::optional<base::ScopedNativeLibrary> library_;
 #endif
 };
 
diff --git a/mojo/public/cpp/base/big_buffer.cc b/mojo/public/cpp/base/big_buffer.cc
index 1e7a98a..e75caae 100644
--- a/mojo/public/cpp/base/big_buffer.cc
+++ b/mojo/public/cpp/base/big_buffer.cc
@@ -42,7 +42,7 @@
 void TryCreateSharedMemory(
     size_t size,
     BigBuffer::StorageType* storage_type,
-    absl::optional<internal::BigBufferSharedMemoryRegion>* shared_memory) {
+    std::optional<internal::BigBufferSharedMemoryRegion>* shared_memory) {
   if (size > BigBuffer::kMaxInlineBytes) {
     auto buffer = mojo::SharedBufferHandle::Create(size);
     if (buffer.is_valid()) {
diff --git a/mojo/public/cpp/base/big_buffer.h b/mojo/public/cpp/base/big_buffer.h
index bac0625..ec6b1cd 100644
--- a/mojo/public/cpp/base/big_buffer.h
+++ b/mojo/public/cpp/base/big_buffer.h
@@ -8,11 +8,11 @@
 #include <cstdint>
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/containers/span.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "mojo/public/cpp/system/buffer.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo_base {
 
@@ -135,7 +135,7 @@
   StorageType storage_type_;
   std::unique_ptr<uint8_t[]> bytes_;
   size_t bytes_size_;
-  absl::optional<internal::BigBufferSharedMemoryRegion> shared_memory_;
+  std::optional<internal::BigBufferSharedMemoryRegion> shared_memory_;
 };
 
 // Similar to BigBuffer, but doesn't *necessarily* own the buffer storage.
@@ -191,7 +191,7 @@
  private:
   BigBuffer::StorageType storage_type_ = BigBuffer::StorageType::kBytes;
   base::span<const uint8_t> bytes_;
-  absl::optional<internal::BigBufferSharedMemoryRegion> shared_memory_;
+  std::optional<internal::BigBufferSharedMemoryRegion> shared_memory_;
 };
 
 }  // namespace mojo_base
diff --git a/mojo/public/cpp/base/read_only_file_mojom_traits.cc b/mojo/public/cpp/base/read_only_file_mojom_traits.cc
index ccbf555..51aa7cd 100644
--- a/mojo/public/cpp/base/read_only_file_mojom_traits.cc
+++ b/mojo/public/cpp/base/read_only_file_mojom_traits.cc
@@ -29,7 +29,7 @@
 bool IsReadOnlyFile(base::File& file) {
   bool is_readonly = true;
 #if BUILDFLAG(IS_WIN)
-  absl::optional<ACCESS_MASK> flags =
+  std::optional<ACCESS_MASK> flags =
       base::win::GetGrantedAccess(file.GetPlatformFile());
   if (!flags.has_value()) {
     return false;
diff --git a/mojo/public/cpp/base/safe_base_name_unittest.cc b/mojo/public/cpp/base/safe_base_name_unittest.cc
index 939a01d..b1f26ef6 100644
--- a/mojo/public/cpp/base/safe_base_name_unittest.cc
+++ b/mojo/public/cpp/base/safe_base_name_unittest.cc
@@ -10,14 +10,14 @@
 namespace mojo_base {
 
 namespace {
-absl::optional<base::SafeBaseName> CreateSafeBaseName() {
+std::optional<base::SafeBaseName> CreateSafeBaseName() {
   return base::SafeBaseName::Create(base::FilePath());
 }
 }  // namespace
 
 TEST(SafeBaseNameTest, PathEmpty) {
-  absl::optional<base::SafeBaseName> basename = CreateSafeBaseName();
-  absl::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
+  std::optional<base::SafeBaseName> basename = CreateSafeBaseName();
+  std::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
 
   ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SafeBaseName>(
       *basename, *basename_out));
@@ -25,9 +25,9 @@
 }
 
 TEST(SafeBaseNameTest, PathContainsNoSeparators) {
-  absl::optional<base::SafeBaseName> basename(
+  std::optional<base::SafeBaseName> basename(
       base::SafeBaseName::Create(FILE_PATH_LITERAL("hello")));
-  absl::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
+  std::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
 
   ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SafeBaseName>(
       *basename, *basename_out));
@@ -37,8 +37,8 @@
 TEST(SafeBaseNameTest, PathContainsSeparators) {
   base::FilePath file = base::FilePath(FILE_PATH_LITERAL("hello"))
                             .Append(FILE_PATH_LITERAL("world"));
-  absl::optional<base::SafeBaseName> basename(base::SafeBaseName::Create(file));
-  absl::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
+  std::optional<base::SafeBaseName> basename(base::SafeBaseName::Create(file));
+  std::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
 
   ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SafeBaseName>(
       *basename, *basename_out));
@@ -49,8 +49,8 @@
   base::FilePath file = base::FilePath(FILE_PATH_LITERAL("hello"))
                             .Append(FILE_PATH_LITERAL("world"))
                             .AsEndingWithSeparator();
-  absl::optional<base::SafeBaseName> basename(base::SafeBaseName::Create(file));
-  absl::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
+  std::optional<base::SafeBaseName> basename(base::SafeBaseName::Create(file));
+  std::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
 
   ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SafeBaseName>(
       *basename, *basename_out));
@@ -62,7 +62,7 @@
   mojo_base::mojom::SafeBaseNamePtr mojom_basename =
       mojo_base::mojom::SafeBaseName::New();
   mojom_basename->path = base::FilePath(FILE_PATH_LITERAL("C:\\"));
-  absl::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
+  std::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
 
   // Expect deserialization to fail because "C:\\ is an absolute path. See
   // safe_base_name.h
@@ -74,7 +74,7 @@
   mojo_base::mojom::SafeBaseNamePtr mojom_basename =
       mojo_base::mojom::SafeBaseName::New();
   mojom_basename->path = base::FilePath(FILE_PATH_LITERAL("/"));
-  absl::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
+  std::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
 
   // Expect deserialization to fail because "/" is an absolute path. See
   // safe_base_name.h
@@ -85,9 +85,9 @@
 
 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
 TEST(SafeBaseNameTest, PathIsFileInRootWin) {
-  absl::optional<base::SafeBaseName> basename(
+  std::optional<base::SafeBaseName> basename(
       base::SafeBaseName::Create(FILE_PATH_LITERAL("C:\\foo.txt")));
-  absl::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
+  std::optional<base::SafeBaseName> basename_out = CreateSafeBaseName();
 
   ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SafeBaseName>(
       *basename, *basename_out));
diff --git a/mojo/public/cpp/base/unguessable_token_mojom_traits.cc b/mojo/public/cpp/base/unguessable_token_mojom_traits.cc
index ba96eeac..ac1abe25 100644
--- a/mojo/public/cpp/base/unguessable_token_mojom_traits.cc
+++ b/mojo/public/cpp/base/unguessable_token_mojom_traits.cc
@@ -17,7 +17,7 @@
   // This is not mapped as nullable_is_same_type, so any UnguessableToken
   // deserialized by the traits should always yield a non-empty token.
   // If deserialization results in an empty token, the data is malformed.
-  absl::optional<base::UnguessableToken> token =
+  std::optional<base::UnguessableToken> token =
       base::UnguessableToken::Deserialize(high, low);
   if (!token.has_value()) {
     return false;
diff --git a/mojo/public/cpp/bindings/associated_group_controller.h b/mojo/public/cpp/bindings/associated_group_controller.h
index bf2f3e79..c42aeb6 100644
--- a/mojo/public/cpp/bindings/associated_group_controller.h
+++ b/mojo/public/cpp/bindings/associated_group_controller.h
@@ -5,13 +5,13 @@
 #ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_CONTROLLER_H_
 #define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_CONTROLLER_H_
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/memory/ref_counted.h"
 #include "base/task/sequenced_task_runner.h"
 #include "mojo/public/cpp/bindings/disconnect_reason.h"
 #include "mojo/public/cpp/bindings/interface_id.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 
@@ -46,7 +46,7 @@
   // Closes an interface endpoint handle.
   virtual void CloseEndpointHandle(
       InterfaceId id,
-      const absl::optional<DisconnectReason>& reason) = 0;
+      const std::optional<DisconnectReason>& reason) = 0;
 
   // Attaches a client to the specified endpoint to send and receive messages.
   // The returned object is still owned by the controller. It must only be used
diff --git a/mojo/public/cpp/bindings/clone_traits.h b/mojo/public/cpp/bindings/clone_traits.h
index 7962ff7b..8e8c5129 100644
--- a/mojo/public/cpp/bindings/clone_traits.h
+++ b/mojo/public/cpp/bindings/clone_traits.h
@@ -9,9 +9,9 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/containers/flat_map.h"
 #include "mojo/public/cpp/bindings/lib/template_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 
@@ -40,12 +40,12 @@
 };
 
 template <typename T>
-struct CloneTraits<absl::optional<T>> {
-  static absl::optional<T> Clone(const absl::optional<T>& input) {
+struct CloneTraits<std::optional<T>> {
+  static std::optional<T> Clone(const std::optional<T>& input) {
     if (!input)
-      return absl::nullopt;
+      return std::nullopt;
 
-    return absl::optional<T>(mojo::Clone(*input));
+    return std::optional<T>(mojo::Clone(*input));
   }
 };
 
diff --git a/mojo/public/cpp/bindings/connector.h b/mojo/public/cpp/bindings/connector.h
index 72f8281b8..e3dd9e21 100644
--- a/mojo/public/cpp/bindings/connector.h
+++ b/mojo/public/cpp/bindings/connector.h
@@ -9,6 +9,7 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "base/compiler_specific.h"
 #include "base/component_export.h"
 #include "base/functional/callback.h"
@@ -23,7 +24,6 @@
 #include "mojo/public/cpp/system/handle_signal_tracker.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class Lock;
@@ -311,7 +311,7 @@
 
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   std::unique_ptr<SimpleWatcher> handle_watcher_;
-  absl::optional<HandleSignalTracker> peer_remoteness_tracker_;
+  std::optional<HandleSignalTracker> peer_remoteness_tracker_;
 
   std::atomic<bool> error_;
   bool drop_writes_ = false;
@@ -327,7 +327,7 @@
 
   // If sending messages is allowed from multiple sequences, |lock_| is used to
   // protect modifications to |message_pipe_| and |drop_writes_|.
-  absl::optional<base::Lock> lock_;
+  std::optional<base::Lock> lock_;
 
   std::unique_ptr<SyncHandleWatcher> sync_watcher_;
 
diff --git a/mojo/public/cpp/bindings/enum_utils.h b/mojo/public/cpp/bindings/enum_utils.h
index 1631f94..30172c1b 100644
--- a/mojo/public/cpp/bindings/enum_utils.h
+++ b/mojo/public/cpp/bindings/enum_utils.h
@@ -7,21 +7,21 @@
 
 #include <type_traits>
 
+#include <optional>
 #include "base/numerics/safe_conversions.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 
 // Converts |int_value| to |TMojoEnum|.  If |int_value| represents a known enum
 // value, then a corresponding |TMojoEnum| value will be returned.  Returns
-// |absl::nullopt| otherwise.
+// |std::nullopt| otherwise.
 //
 // Using base::StrictNumeric as the parameter type prevents callers from
 // accidentally using an implicit narrowing conversion when calling this
 // function (e.g. calling it with an int64_t argument, when the enum's
 // underlying type is int32_t).
 template <typename TMojoEnum>
-absl::optional<TMojoEnum> ConvertIntToMojoEnum(
+std::optional<TMojoEnum> ConvertIntToMojoEnum(
     base::StrictNumeric<int32_t> int_value) {
   // Today all mojo enums use |int32_t| as the underlying type, so the code
   // can simply use |int32_t| rather than |std::underlying_type_t<TMojoEnum>|.
@@ -56,7 +56,7 @@
   // TMojoEnum and |enum_value|) - we rely on ADL (argument-dependent lookup) to
   // find the right overload below.
   if (!IsKnownEnumValue(enum_value))
-    return absl::nullopt;
+    return std::nullopt;
 
   return enum_value;
 }
diff --git a/mojo/public/cpp/bindings/equals_traits.h b/mojo/public/cpp/bindings/equals_traits.h
index e0f15cd..73877e3 100644
--- a/mojo/public/cpp/bindings/equals_traits.h
+++ b/mojo/public/cpp/bindings/equals_traits.h
@@ -9,9 +9,9 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/containers/flat_map.h"
 #include "mojo/public/cpp/bindings/lib/template_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 
@@ -44,15 +44,15 @@
 };
 
 template <typename T>
-struct EqualsTraits<absl::optional<T>> {
-  static bool Equals(const absl::optional<T>& a, const absl::optional<T>& b) {
+struct EqualsTraits<std::optional<T>> {
+  static bool Equals(const std::optional<T>& a, const std::optional<T>& b) {
     if (!a && !b)
       return true;
     if (!a || !b)
       return false;
 
     // NOTE: Not just Equals() because that's EqualsTraits<>::Equals() and we
-    // want mojo::Equals() for things like absl::optional<std::vector<T>>.
+    // want mojo::Equals() for things like std::optional<std::vector<T>>.
     return mojo::Equals(*a, *b);
   }
 };
diff --git a/mojo/public/cpp/bindings/generic_pending_associated_receiver.h b/mojo/public/cpp/bindings/generic_pending_associated_receiver.h
index 7808d932..ebea14c 100644
--- a/mojo/public/cpp/bindings/generic_pending_associated_receiver.h
+++ b/mojo/public/cpp/bindings/generic_pending_associated_receiver.h
@@ -7,11 +7,11 @@
 
 #include <string>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/strings/string_piece.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 
@@ -54,7 +54,7 @@
 
   void reset();
 
-  const absl::optional<std::string>& interface_name() const {
+  const std::optional<std::string>& interface_name() const {
     return interface_name_;
   }
 
@@ -73,7 +73,7 @@
   mojo::ScopedInterfaceEndpointHandle PassHandleIfNameIs(
       const char* interface_name);
 
-  absl::optional<std::string> interface_name_;
+  std::optional<std::string> interface_name_;
   mojo::ScopedInterfaceEndpointHandle handle_;
 };
 
diff --git a/mojo/public/cpp/bindings/generic_pending_receiver.h b/mojo/public/cpp/bindings/generic_pending_receiver.h
index 985dd72f..1465d03 100644
--- a/mojo/public/cpp/bindings/generic_pending_receiver.h
+++ b/mojo/public/cpp/bindings/generic_pending_receiver.h
@@ -7,11 +7,11 @@
 
 #include <string>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/strings/string_piece.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/system/message_pipe.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"
 
 namespace mojo {
@@ -47,7 +47,7 @@
 
   void reset();
 
-  const absl::optional<std::string>& interface_name() const {
+  const std::optional<std::string>& interface_name() const {
     return interface_name_;
   }
 
@@ -69,7 +69,7 @@
  private:
   mojo::ScopedMessagePipeHandle PassPipeIfNameIs(const char* interface_name);
 
-  absl::optional<std::string> interface_name_;
+  std::optional<std::string> interface_name_;
   mojo::ScopedMessagePipeHandle pipe_;
 };
 
diff --git a/mojo/public/cpp/bindings/interface_endpoint_client.h b/mojo/public/cpp/bindings/interface_endpoint_client.h
index 6154a68..5abf7b2 100644
--- a/mojo/public/cpp/bindings/interface_endpoint_client.h
+++ b/mojo/public/cpp/bindings/interface_endpoint_client.h
@@ -11,6 +11,7 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/containers/span.h"
 #include "base/dcheck_is_on.h"
@@ -36,7 +37,6 @@
 #include "mojo/public/cpp/bindings/message_metadata_helpers.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 #include "mojo/public/cpp/bindings/thread_safe_proxy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 
@@ -153,7 +153,7 @@
 
   // NOTE: |message| must have passed message header validation.
   bool HandleIncomingMessage(Message* message);
-  void NotifyError(const absl::optional<DisconnectReason>& reason);
+  void NotifyError(const std::optional<DisconnectReason>& reason);
 
   // The following methods send interface control messages.
   // They must only be called when the handle is not in pending association
@@ -300,11 +300,11 @@
 
   // The timeout to wait for continuous idling before notiftying our peer that
   // we're idle.
-  absl::optional<base::TimeDelta> idle_timeout_;
+  std::optional<base::TimeDelta> idle_timeout_;
 
   // The current idle timer, valid only while we're idle. If this fires, we send
   // a NotifyIdle to our peer.
-  absl::optional<base::OneShotTimer> notify_idle_timer_;
+  std::optional<base::OneShotTimer> notify_idle_timer_;
 
   // A ref to a ConnectionGroup used to track the idle state of this endpoint,
   // if any. Only non-null if an EnableIdleTracking message has been received.
diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc
index c4d71cb5..f6babc4 100644
--- a/mojo/public/cpp/bindings/lib/connector.cc
+++ b/mojo/public/cpp/bindings/lib/connector.cc
@@ -521,7 +521,7 @@
   }
 
   base::WeakPtr<Connector> weak_self = weak_self_;
-  absl::optional<ActiveDispatchTracker> dispatch_tracker;
+  std::optional<ActiveDispatchTracker> dispatch_tracker;
   if (!is_dispatching_ && nesting_observer_) {
     is_dispatching_ = true;
     dispatch_tracker.emplace(weak_self);
diff --git a/mojo/public/cpp/bindings/lib/hash_util.h b/mojo/public/cpp/bindings/lib/hash_util.h
index 182bfbe..80805da 100644
--- a/mojo/public/cpp/bindings/lib/hash_util.h
+++ b/mojo/public/cpp/bindings/lib/hash_util.h
@@ -10,8 +10,8 @@
 #include <type_traits>
 #include <vector>
 
+#include <optional>
 #include "mojo/public/cpp/bindings/lib/template_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace internal {
@@ -62,8 +62,8 @@
 };
 
 template <typename T>
-struct HashTraits<absl::optional<std::vector<T>>, false> {
-  static size_t Hash(size_t seed, const absl::optional<std::vector<T>>& value) {
+struct HashTraits<std::optional<std::vector<T>>, false> {
+  static size_t Hash(size_t seed, const std::optional<std::vector<T>>& value) {
     if (!value)
       return HashCombine(seed, 0);
 
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
index 7e4d699..4608719 100644
--- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
+++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
@@ -8,6 +8,7 @@
 
 #include <tuple>
 
+#include <optional>
 #include "base/check.h"
 #include "base/containers/contains.h"
 #include "base/containers/cxx20_erase.h"
@@ -34,7 +35,6 @@
 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
 #include "mojo/public/cpp/bindings/sync_event_watcher.h"
 #include "mojo/public/cpp/bindings/thread_safe_proxy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.pbzero.h"
 
 namespace mojo {
@@ -708,7 +708,7 @@
 }
 
 void InterfaceEndpointClient::NotifyError(
-    const absl::optional<DisconnectReason>& reason) {
+    const std::optional<DisconnectReason>& reason) {
   TRACE_EVENT("toplevel", "Closed mojo endpoint",
               [&](perfetto::EventContext& ctx) {
                 auto* info = ctx.event()->set_chrome_mojo_event_info();
@@ -851,7 +851,7 @@
 }
 
 void InterfaceEndpointClient::ForgetAsyncRequest(uint64_t request_id) {
-  absl::optional<PendingAsyncResponse> response;
+  std::optional<PendingAsyncResponse> response;
   {
     base::AutoLock lock(async_responders_lock_);
     auto it = async_responders_.find(request_id);
@@ -914,7 +914,7 @@
                   info->set_ipc_hash((*method_info)());
                   const auto method_address =
                       reinterpret_cast<uintptr_t>(method_info);
-                  const absl::optional<size_t> location_iid =
+                  const std::optional<size_t> location_iid =
                       base::trace_event::InternedUnsymbolizedSourceLocation::
                           Get(&ctx, method_address);
                   if (location_iid) {
@@ -993,7 +993,7 @@
       sync_responses_.erase(it);
     }
 
-    absl::optional<PendingAsyncResponse> pending_response;
+    std::optional<PendingAsyncResponse> pending_response;
     {
       base::AutoLock lock(async_responders_lock_);
       auto it = async_responders_.find(request_id);
diff --git a/mojo/public/cpp/bindings/lib/may_auto_lock.h b/mojo/public/cpp/bindings/lib/may_auto_lock.h
index 63534d8..11be766 100644
--- a/mojo/public/cpp/bindings/lib/may_auto_lock.h
+++ b/mojo/public/cpp/bindings/lib/may_auto_lock.h
@@ -5,10 +5,10 @@
 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAY_AUTO_LOCK_H_
 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAY_AUTO_LOCK_H_
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/memory/raw_ptr_exclusion.h"
 #include "base/synchronization/lock.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace internal {
@@ -17,7 +17,7 @@
 // the constructor is null.
 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) MayAutoLock {
  public:
-  explicit MayAutoLock(absl::optional<base::Lock>* lock)
+  explicit MayAutoLock(std::optional<base::Lock>* lock)
       : lock_(lock->has_value() ? &lock->value() : nullptr) {
     if (lock_)
       lock_->Acquire();
@@ -43,7 +43,7 @@
 // into the constructor is null.
 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) MayAutoUnlock {
  public:
-  explicit MayAutoUnlock(absl::optional<base::Lock>* lock)
+  explicit MayAutoUnlock(std::optional<base::Lock>* lock)
       : lock_(lock->has_value() ? &lock->value() : nullptr) {
     if (lock_) {
       lock_->AssertAcquired();
diff --git a/mojo/public/cpp/bindings/lib/message_fragment.h b/mojo/public/cpp/bindings/lib/message_fragment.h
index 5b0809ab..21e59e4 100644
--- a/mojo/public/cpp/bindings/lib/message_fragment.h
+++ b/mojo/public/cpp/bindings/lib/message_fragment.h
@@ -20,7 +20,7 @@
 
 // Sentinel value used to denote an invalid index and thus a null fragment. Note
 // that we choose a sentinel value over something more explicit like
-// absl::optional because this is used heavily in generated code, so code size
+// std::optional because this is used heavily in generated code, so code size
 // is particularly relevant.
 constexpr size_t kInvalidFragmentIndex = std::numeric_limits<size_t>::max();
 
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc
index ed69861..90913f4 100644
--- a/mojo/public/cpp/bindings/lib/multiplex_router.cc
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
@@ -73,11 +73,11 @@
     handle_created_ = true;
   }
 
-  const absl::optional<DisconnectReason>& disconnect_reason() const {
+  const std::optional<DisconnectReason>& disconnect_reason() const {
     return disconnect_reason_;
   }
   void set_disconnect_reason(
-      const absl::optional<DisconnectReason>& disconnect_reason) {
+      const std::optional<DisconnectReason>& disconnect_reason) {
     router_->AssertLockAcquired();
     disconnect_reason_ = disconnect_reason;
   }
@@ -235,7 +235,7 @@
   // endpoint.
   bool handle_created_;
 
-  absl::optional<DisconnectReason> disconnect_reason_;
+  std::optional<DisconnectReason> disconnect_reason_;
 
   // The task runner on which |client_|'s methods can be called.
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
@@ -493,7 +493,7 @@
 
 void MultiplexRouter::CloseEndpointHandle(
     InterfaceId id,
-    const absl::optional<DisconnectReason>& reason) {
+    const std::optional<DisconnectReason>& reason) {
   if (!IsValidInterfaceId(id))
     return;
 
@@ -742,7 +742,7 @@
 
 bool MultiplexRouter::OnPeerAssociatedEndpointClosed(
     InterfaceId id,
-    const absl::optional<DisconnectReason>& reason) {
+    const std::optional<DisconnectReason>& reason) {
   MayAutoLock locker(&lock_);
   InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, nullptr);
 
@@ -997,7 +997,7 @@
   DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
 
   InterfaceEndpointClient* client = endpoint->client();
-  absl::optional<DisconnectReason> disconnect_reason(
+  std::optional<DisconnectReason> disconnect_reason(
       endpoint->disconnect_reason());
 
   {
@@ -1237,7 +1237,7 @@
 
     UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED);
     MayAutoUnlock unlocker(&lock_);
-    control_message_proxy_.NotifyPeerEndpointClosed(ids[i], absl::nullopt);
+    control_message_proxy_.NotifyPeerEndpointClosed(ids[i], std::nullopt);
   }
 
   ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr);
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h
index 8d66503..d1d0b94 100644
--- a/mojo/public/cpp/bindings/lib/multiplex_router.h
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.h
@@ -10,6 +10,7 @@
 #include <map>
 #include <memory>
 
+#include <optional>
 #include "base/check.h"
 #include "base/component_export.h"
 #include "base/containers/circular_deque.h"
@@ -28,7 +29,6 @@
 #include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h"
 #include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class SequencedTaskRunner;
@@ -131,7 +131,7 @@
       InterfaceId id) override;
   void CloseEndpointHandle(
       InterfaceId id,
-      const absl::optional<DisconnectReason>& reason) override;
+      const std::optional<DisconnectReason>& reason) override;
   InterfaceEndpointController* AttachEndpointClient(
       const ScopedInterfaceEndpointHandle& handle,
       InterfaceEndpointClient* endpoint_client,
@@ -221,7 +221,7 @@
   // PipeControlMessageHandlerDelegate implementation:
   bool OnPeerAssociatedEndpointClosed(
       InterfaceId id,
-      const absl::optional<DisconnectReason>& reason) override;
+      const std::optional<DisconnectReason>& reason) override;
   bool WaitForFlushToComplete(ScopedMessagePipeHandle flush_pipe) override;
 
   void OnPipeConnectionError(bool force_async_dispatch);
@@ -307,7 +307,7 @@
 
   // Active whenever dispatch is blocked by a pending remote flush.
   ScopedMessagePipeHandle active_flush_pipe_;
-  absl::optional<mojo::SimpleWatcher> flush_pipe_watcher_;
+  std::optional<mojo::SimpleWatcher> flush_pipe_watcher_;
 
   // Tracks information about the current exclusive sync wait, if any, on the
   // MultiplexRouter's primary thread. Note that exclusive off-thread sync waits
@@ -317,13 +317,13 @@
     uint64_t request_id = 0;
     bool finished = false;
   };
-  absl::optional<ExclusiveSyncWaitInfo> exclusive_sync_wait_;
+  std::optional<ExclusiveSyncWaitInfo> exclusive_sync_wait_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 
   // Protects the following members.
   // Not set in Config::SINGLE_INTERFACE* mode.
-  mutable absl::optional<base::Lock> lock_;
+  mutable std::optional<base::Lock> lock_;
   PipeControlMessageHandler control_message_handler_;
 
   // NOTE: It is unsafe to call into this object while holding |lock_|.
diff --git a/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc b/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc
index 54191c5..9cabdf3a 100644
--- a/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc
+++ b/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc
@@ -71,7 +71,7 @@
     const auto& event =
         params_ptr->input->get_peer_associated_endpoint_closed_event();
 
-    absl::optional<DisconnectReason> reason;
+    std::optional<DisconnectReason> reason;
     if (event->disconnect_reason) {
       reason.emplace(event->disconnect_reason->custom_reason,
                      event->disconnect_reason->description);
diff --git a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc b/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
index 42bcf32..b0e9dca0 100644
--- a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
+++ b/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
@@ -43,7 +43,7 @@
 
 void PipeControlMessageProxy::NotifyPeerEndpointClosed(
     InterfaceId id,
-    const absl::optional<DisconnectReason>& reason) {
+    const std::optional<DisconnectReason>& reason) {
   Message message(ConstructPeerEndpointClosedMessage(id, reason));
   message.set_heap_profiler_tag(kMessageTag);
   std::ignore = receiver_->Accept(&message);
@@ -66,7 +66,7 @@
 // static
 Message PipeControlMessageProxy::ConstructPeerEndpointClosedMessage(
     InterfaceId id,
-    const absl::optional<DisconnectReason>& reason) {
+    const std::optional<DisconnectReason>& reason) {
   auto event = pipe_control::PeerAssociatedEndpointClosedEvent::New();
   event->id = id;
   if (reason) {
diff --git a/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc b/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc
index a6838394..83b15f6b 100644
--- a/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc
+++ b/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc
@@ -39,7 +39,7 @@
     peer_state_ = std::move(peer);
   }
 
-  void Close(const absl::optional<DisconnectReason>& reason) {
+  void Close(const std::optional<DisconnectReason>& reason) {
     scoped_refptr<AssociatedGroupController> cached_group_controller;
     InterfaceId cached_id = kInvalidInterfaceId;
     scoped_refptr<State> cached_peer_state;
@@ -164,7 +164,7 @@
     return group_controller_.get();
   }
 
-  const absl::optional<DisconnectReason>& disconnect_reason() const {
+  const std::optional<DisconnectReason>& disconnect_reason() const {
     internal::MayAutoLock locker(&lock_);
     return disconnect_reason_;
   }
@@ -215,7 +215,7 @@
 
   // Called by the peer, maybe from a different sequence.
   void OnPeerClosedBeforeAssociation(
-      const absl::optional<DisconnectReason>& reason) {
+      const std::optional<DisconnectReason>& reason) {
     AssociationEventCallback handler;
     {
       internal::MayAutoLock locker(&lock_);
@@ -269,10 +269,10 @@
 
   // Protects the following members if the handle is initially set to pending
   // association.
-  mutable absl::optional<base::Lock> lock_;
+  mutable std::optional<base::Lock> lock_;
 
   bool pending_association_ = false;
-  absl::optional<DisconnectReason> disconnect_reason_;
+  std::optional<DisconnectReason> disconnect_reason_;
 
   scoped_refptr<State> peer_state_;
 
@@ -308,7 +308,7 @@
 }
 
 ScopedInterfaceEndpointHandle::~ScopedInterfaceEndpointHandle() {
-  state_->Close(absl::nullopt);
+  state_->Close(std::nullopt);
 }
 
 ScopedInterfaceEndpointHandle& ScopedInterfaceEndpointHandle::operator=(
@@ -335,7 +335,7 @@
   return state_->group_controller();
 }
 
-const absl::optional<DisconnectReason>&
+const std::optional<DisconnectReason>&
 ScopedInterfaceEndpointHandle::disconnect_reason() const {
   return state_->disconnect_reason();
 }
@@ -346,7 +346,7 @@
 }
 
 void ScopedInterfaceEndpointHandle::reset() {
-  ResetInternal(absl::nullopt);
+  ResetInternal(std::nullopt);
 }
 
 void ScopedInterfaceEndpointHandle::ResetWithReason(
@@ -369,7 +369,7 @@
 }
 
 void ScopedInterfaceEndpointHandle::ResetInternal(
-    const absl::optional<DisconnectReason>& reason) {
+    const std::optional<DisconnectReason>& reason) {
   auto new_state = base::MakeRefCounted<State>();
   state_->Close(reason);
   state_.swap(new_state);
diff --git a/mojo/public/cpp/bindings/lib/serialization_forward.h b/mojo/public/cpp/bindings/lib/serialization_forward.h
index fac9ba0..ce05a0e 100644
--- a/mojo/public/cpp/bindings/lib/serialization_forward.h
+++ b/mojo/public/cpp/bindings/lib/serialization_forward.h
@@ -7,6 +7,7 @@
 
 #include <type_traits>
 
+#include <optional>
 #include "mojo/public/cpp/bindings/array_traits.h"
 #include "mojo/public/cpp/bindings/enum_traits.h"
 #include "mojo/public/cpp/bindings/lib/buffer.h"
@@ -18,7 +19,6 @@
 #include "mojo/public/cpp/bindings/string_traits.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "mojo/public/cpp/bindings/union_traits.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // This file is included by serialization implementation files to avoid circular
 // includes.
@@ -32,7 +32,7 @@
 struct Serializer;
 
 template <typename T>
-using IsAbslOptional = IsSpecializationOf<absl::optional, std::decay_t<T>>;
+using IsAbslOptional = IsSpecializationOf<std::optional, std::decay_t<T>>;
 
 template <typename T>
 using IsOptionalAsPointer =
@@ -61,7 +61,7 @@
 bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) {
   if constexpr (IsAbslOptional<InputUserType>::value) {
     if (!input) {
-      *output = absl::nullopt;
+      *output = std::nullopt;
       return true;
     }
     if (!*output) {
diff --git a/mojo/public/cpp/bindings/optional_as_pointer.h b/mojo/public/cpp/bindings/optional_as_pointer.h
index ebeab30..5263f72 100644
--- a/mojo/public/cpp/bindings/optional_as_pointer.h
+++ b/mojo/public/cpp/bindings/optional_as_pointer.h
@@ -14,15 +14,15 @@
 // Simple wrapper around a pointer to allow zero-copy serialization of a
 // nullable type.
 //
-// Traits for nullable fields typically return `const absl::optional<T>&` or
-// `absl::optional<T>&`. However, if the field is not already an
-// `absl::optional`, this can be inefficient:
+// Traits for nullable fields typically return `const std::optional<T>&` or
+// `std::optional<T>&`. However, if the field is not already an
+// `std::optional`, this can be inefficient:
 //
-//   static absl::optional<std::string> nullable_field_getter(
+//   static std::optional<std::string> nullable_field_getter(
 //       const MyType& input) {
-//     // Bad: copies input.data() to populate `absl::optional`.
-//     return absl::make_optional(
-//         input.has_valid_data() ? input.data() : absl::nullopt);
+//     // Bad: copies input.data() to populate `std::optional`.
+//     return std::make_optional(
+//         input.has_valid_data() ? input.data() : std::nullopt);
 //   }
 //
 // Using this wrapper allows this to be serialized without additional copies:
diff --git a/mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h b/mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h
index 3c99c19..c092414 100644
--- a/mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h
+++ b/mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h
@@ -5,9 +5,9 @@
 #ifndef MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_HANDLER_DELEGATE_H_
 #define MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_HANDLER_DELEGATE_H_
 
+#include <optional>
 #include "mojo/public/cpp/bindings/disconnect_reason.h"
 #include "mojo/public/cpp/bindings/interface_id.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 
@@ -18,7 +18,7 @@
   // expected to close the message pipe.
   virtual bool OnPeerAssociatedEndpointClosed(
       InterfaceId id,
-      const absl::optional<DisconnectReason>& reason) = 0;
+      const std::optional<DisconnectReason>& reason) = 0;
 
   // The implementation should cease dispatching messages until the
   // |flush_pipe|'s peer is closed.
diff --git a/mojo/public/cpp/bindings/pipe_control_message_proxy.h b/mojo/public/cpp/bindings/pipe_control_message_proxy.h
index 66d2f1d..3266cf1e 100644
--- a/mojo/public/cpp/bindings/pipe_control_message_proxy.h
+++ b/mojo/public/cpp/bindings/pipe_control_message_proxy.h
@@ -5,6 +5,7 @@
 #ifndef MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_PROXY_H_
 #define MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_PROXY_H_
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "mojo/public/cpp/bindings/async_flusher.h"
@@ -12,7 +13,6 @@
 #include "mojo/public/cpp/bindings/interface_id.h"
 #include "mojo/public/cpp/bindings/message.h"
 #include "mojo/public/cpp/bindings/pending_flush.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 
@@ -31,13 +31,13 @@
   PipeControlMessageProxy& operator=(const PipeControlMessageProxy&) = delete;
 
   void NotifyPeerEndpointClosed(InterfaceId id,
-                                const absl::optional<DisconnectReason>& reason);
+                                const std::optional<DisconnectReason>& reason);
   void PausePeerUntilFlushCompletes(PendingFlush flush);
   void FlushAsync(AsyncFlusher flusher);
 
   static Message ConstructPeerEndpointClosedMessage(
       InterfaceId id,
-      const absl::optional<DisconnectReason>& reason);
+      const std::optional<DisconnectReason>& reason);
 
  private:
   // Not owned.
diff --git a/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h b/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h
index 9acfe5275..3939c20 100644
--- a/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h
+++ b/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h
@@ -5,13 +5,13 @@
 #ifndef MOJO_PUBLIC_CPP_BINDINGS_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_
 #define MOJO_PUBLIC_CPP_BINDINGS_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/functional/callback.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/strings/string_piece.h"
 #include "mojo/public/cpp/bindings/disconnect_reason.h"
 #include "mojo/public/cpp/bindings/interface_id.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 
@@ -57,7 +57,7 @@
 
   // Returns the disconnect reason if the peer handle is closed before
   // association and specifies a custom disconnect reason.
-  const absl::optional<DisconnectReason>& disconnect_reason() const;
+  const std::optional<DisconnectReason>& disconnect_reason() const;
 
   enum AssociationEvent {
     // The interface has been associated with a message pipe.
@@ -95,7 +95,7 @@
       InterfaceId id,
       scoped_refptr<AssociatedGroupController> peer_group_controller);
 
-  void ResetInternal(const absl::optional<DisconnectReason>& reason);
+  void ResetInternal(const std::optional<DisconnectReason>& reason);
 
   // Used by AssociatedGroup.
   // It is safe to run the returned callback on any sequence, or after this
diff --git a/mojo/public/cpp/bindings/struct_ptr.h b/mojo/public/cpp/bindings/struct_ptr.h
index f31236f..f3c1278 100644
--- a/mojo/public/cpp/bindings/struct_ptr.h
+++ b/mojo/public/cpp/bindings/struct_ptr.h
@@ -60,7 +60,7 @@
   }
 
   template <typename... Args>
-  StructPtr(absl::in_place_t, Args&&... args)
+  StructPtr(std::in_place_t, Args&&... args)
       : ptr_(new Struct(std::forward<Args>(args)...)) {}
 
   template <typename U>
@@ -159,7 +159,7 @@
   }
 
   template <typename... Args>
-  InlinedStructPtr(absl::in_place_t, Args&&... args)
+  InlinedStructPtr(std::in_place_t, Args&&... args)
       : value_(std::forward<Args>(args)...), state_(VALID) {}
 
   template <typename U>
diff --git a/mojo/public/cpp/bindings/struct_traits.h b/mojo/public/cpp/bindings/struct_traits.h
index e319728..13e5e86 100644
--- a/mojo/public/cpp/bindings/struct_traits.h
+++ b/mojo/public/cpp/bindings/struct_traits.h
@@ -49,7 +49,7 @@
 //          Value of any type that has an EnumTraits defined.
 //
 //      For any nullable string/struct/array/map/union field you could also
-//      return value or reference of absl::optional<T>, if T has the right
+//      return value or reference of std::optional<T>, if T has the right
 //      *Traits defined.
 //
 //      During serialization, getters for all fields are called exactly once. It
diff --git a/mojo/public/cpp/bindings/tests/connection_group_unittest.cc b/mojo/public/cpp/bindings/tests/connection_group_unittest.cc
index d97348f..11b5ad1b 100644
--- a/mojo/public/cpp/bindings/tests/connection_group_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/connection_group_unittest.cc
@@ -169,7 +169,7 @@
 }
 
 TEST_F(ConnectionGroupTest, NotifyOnDecrementToZeroMultipleTimes) {
-  absl::optional<base::RunLoop> loop;
+  std::optional<base::RunLoop> loop;
   ConnectionGroup::Ref ref =
       ConnectionGroup::Create(base::BindLambdaForTesting([&] {
                                 ASSERT_TRUE(loop.has_value());
diff --git a/mojo/public/cpp/bindings/tests/default_construct_unittest.cc b/mojo/public/cpp/bindings/tests/default_construct_unittest.cc
index e8ec529..f676c74 100644
--- a/mojo/public/cpp/bindings/tests/default_construct_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/default_construct_unittest.cc
@@ -125,7 +125,7 @@
 
 TEST(DefaultConstructOptionalTest, InitializedToNullopt) {
   auto container = mojom::OptionalTestStructContainer::New();
-  EXPECT_EQ(absl::nullopt, container->test_struct);
+  EXPECT_EQ(std::nullopt, container->test_struct);
 }
 
 }  // namespace mojo::test::default_construct
diff --git a/mojo/public/cpp/bindings/tests/equals_unittest.cc b/mojo/public/cpp/bindings/tests/equals_unittest.cc
index 963aac2..42ed5f8 100644
--- a/mojo/public/cpp/bindings/tests/equals_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/equals_unittest.cc
@@ -58,7 +58,7 @@
   NamedRegionPtr n2(n1.Clone());
   EXPECT_TRUE(n1.Equals(n2));
 
-  n2->rects = absl::nullopt;
+  n2->rects = std::nullopt;
   EXPECT_FALSE(n1.Equals(n2));
   n2->rects.emplace();
   EXPECT_FALSE(n1.Equals(n2));
diff --git a/mojo/public/cpp/bindings/tests/flush_async_unittest.cc b/mojo/public/cpp/bindings/tests/flush_async_unittest.cc
index 87f8480..d0a8370 100644
--- a/mojo/public/cpp/bindings/tests/flush_async_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/flush_async_unittest.cc
@@ -6,6 +6,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/barrier_closure.h"
 #include "base/containers/flat_map.h"
 #include "base/functional/bind.h"
@@ -25,7 +26,6 @@
 #include "mojo/public/cpp/bindings/tests/bindings_test_base.h"
 #include "mojo/public/cpp/bindings/tests/flush_async_unittest.test-mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace test {
@@ -262,7 +262,7 @@
   // corresponding AsyncFlusher. The call should eventually execute.
   base::RunLoop loop;
   base::flat_map<std::string, std::string> snapshot;
-  absl::optional<AsyncFlusher> flusher(absl::in_place);
+  std::optional<AsyncFlusher> flusher(std::in_place);
   key_value_store().PauseReceiverUntilFlushCompletes(
       PendingFlush(&flusher.value()));
   key_value_store()->GetSnapshot(base::BindLambdaForTesting(
@@ -300,7 +300,7 @@
   Remote<mojom::Pinger> pinger;
   PingerImpl impl(pinger.BindNewPipeAndPassReceiver());
 
-  absl::optional<AsyncFlusher> flusher(absl::in_place);
+  std::optional<AsyncFlusher> flusher(std::in_place);
   PendingFlush flush(&flusher.value());
   pinger.PauseReceiverUntilFlushCompletes(std::move(flush));
 
@@ -344,7 +344,7 @@
   Remote<mojom::Pinger> pinger;
   PingerImpl impl(pinger.BindNewPipeAndPassReceiver());
 
-  absl::optional<AsyncFlusher> flusher(absl::in_place);
+  std::optional<AsyncFlusher> flusher(std::in_place);
   PendingFlush flush(&flusher.value());
   pinger.PauseReceiverUntilFlushCompletes(std::move(flush));
 
diff --git a/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc b/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc
index 343a634..7fba344 100644
--- a/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc
@@ -212,7 +212,7 @@
                                       run_loop.QuitClosure());
 
   sample::RequestPtr request(sample::Request::New(
-      1, std::move(pipe1.handle0), absl::nullopt, std::move(imported)));
+      1, std::move(pipe1.handle0), std::nullopt, std::move(imported)));
   bool got_response = false;
   std::string got_text_reply;
   base::RunLoop run_loop2;
@@ -236,7 +236,7 @@
   SampleFactoryImpl factory_impl(factory.BindNewPipeAndPassReceiver());
 
   sample::RequestPtr request(sample::Request::New(1, ScopedMessagePipeHandle(),
-                                                  absl::nullopt, NullRemote()));
+                                                  std::nullopt, NullRemote()));
 
   bool got_response = false;
   std::string got_text_reply;
diff --git a/mojo/public/cpp/bindings/tests/new_endpoint_types_unittest.cc b/mojo/public/cpp/bindings/tests/new_endpoint_types_unittest.cc
index e15179755..dab12f6 100644
--- a/mojo/public/cpp/bindings/tests/new_endpoint_types_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/new_endpoint_types_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/run_loop.h"
@@ -19,7 +20,6 @@
 #include "mojo/public/cpp/bindings/unique_receiver_set.h"
 #include "mojo/public/interfaces/bindings/tests/new_endpoint_types.test-mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace test {
diff --git a/mojo/public/cpp/bindings/tests/nullable_value_types_unittest.cc b/mojo/public/cpp/bindings/tests/nullable_value_types_unittest.cc
index dadecde..39ddfc4 100644
--- a/mojo/public/cpp/bindings/tests/nullable_value_types_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/nullable_value_types_unittest.cc
@@ -4,6 +4,7 @@
 
 #include <utility>
 
+#include <optional>
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -13,7 +14,6 @@
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "mojo/public/interfaces/bindings/tests/nullable_value_types.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo::test::nullable_value_types {
 namespace {
@@ -30,20 +30,20 @@
     TypemappedEnum::kValueOne;
 
 template <typename T>
-std::pair<bool, T> FromOpt(const absl::optional<T>& opt) {
+std::pair<bool, T> FromOpt(const std::optional<T>& opt) {
   return opt.has_value() ? std::pair(true, opt.value())
                          : std::pair(false, kDefaultValue<T>);
 }
 
 template <typename T>
-absl::optional<T> ToOpt(bool has_value, T value) {
-  return has_value ? absl::make_optional(value) : absl::nullopt;
+std::optional<T> ToOpt(bool has_value, T value) {
+  return has_value ? std::make_optional(value) : std::nullopt;
 }
 
-absl::optional<mojom::RegularEnum> Transform(
-    absl::optional<mojom::RegularEnum> in) {
+std::optional<mojom::RegularEnum> Transform(
+    std::optional<mojom::RegularEnum> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   switch (in.value()) {
     case mojom::RegularEnum::kThisValue:
@@ -53,9 +53,9 @@
   }
 }
 
-absl::optional<TypemappedEnum> Transform(absl::optional<TypemappedEnum> in) {
+std::optional<TypemappedEnum> Transform(std::optional<TypemappedEnum> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   switch (in.value()) {
     case TypemappedEnum::kValueOne:
@@ -65,79 +65,79 @@
   }
 }
 
-absl::optional<bool> Transform(absl::optional<bool> in) {
+std::optional<bool> Transform(std::optional<bool> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return !in.value();
 }
 
-absl::optional<uint8_t> Transform(absl::optional<uint8_t> in) {
+std::optional<uint8_t> Transform(std::optional<uint8_t> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return ~in.value();
 }
 
-absl::optional<uint16_t> Transform(absl::optional<uint16_t> in) {
+std::optional<uint16_t> Transform(std::optional<uint16_t> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return ~in.value();
 }
 
-absl::optional<uint32_t> Transform(absl::optional<uint32_t> in) {
+std::optional<uint32_t> Transform(std::optional<uint32_t> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return ~in.value();
 }
 
-absl::optional<uint64_t> Transform(absl::optional<uint64_t> in) {
+std::optional<uint64_t> Transform(std::optional<uint64_t> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return ~in.value();
 }
 
-absl::optional<int8_t> Transform(absl::optional<int8_t> in) {
+std::optional<int8_t> Transform(std::optional<int8_t> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return -in.value();
 }
 
-absl::optional<int16_t> Transform(absl::optional<int16_t> in) {
+std::optional<int16_t> Transform(std::optional<int16_t> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return -in.value();
 }
 
-absl::optional<int32_t> Transform(absl::optional<int32_t> in) {
+std::optional<int32_t> Transform(std::optional<int32_t> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return -in.value();
 }
 
-absl::optional<int64_t> Transform(absl::optional<int64_t> in) {
+std::optional<int64_t> Transform(std::optional<int64_t> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return -in.value();
 }
 
-absl::optional<float> Transform(absl::optional<float> in) {
+std::optional<float> Transform(std::optional<float> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return -2 * in.value();
 }
 
-absl::optional<double> Transform(absl::optional<double> in) {
+std::optional<double> Transform(std::optional<double> in) {
   if (!in.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return -2 * in.value();
 }
@@ -285,13 +285,13 @@
  public:
   explicit InterfaceV2Impl(
       PendingReceiver<mojom::InterfaceV2> receiver,
-      absl::optional<CallerVersion> caller_version = absl::nullopt)
+      std::optional<CallerVersion> caller_version = std::nullopt)
       : receiver_(this, std::move(receiver)), caller_version_(caller_version) {}
 
  private:
   // mojom::InterfaceV2 implementation:
-  void MethodWithEnums(absl::optional<mojom::RegularEnum> enum_value,
-                       absl::optional<TypemappedEnum> mapped_enum_value,
+  void MethodWithEnums(std::optional<mojom::RegularEnum> enum_value,
+                       std::optional<TypemappedEnum> mapped_enum_value,
                        MethodWithEnumsCallback callback) override {
     std::move(callback).Run(Transform(enum_value),
                             Transform(mapped_enum_value));
@@ -304,17 +304,17 @@
         Transform(in->enum_value), Transform(in->mapped_enum_value)));
   }
 
-  void MethodWithNumerics(absl::optional<bool> bool_value,
-                          absl::optional<uint8_t> u8_value,
-                          absl::optional<uint16_t> u16_value,
-                          absl::optional<uint32_t> u32_value,
-                          absl::optional<uint64_t> u64_value,
-                          absl::optional<int8_t> i8_value,
-                          absl::optional<int16_t> i16_value,
-                          absl::optional<int32_t> i32_value,
-                          absl::optional<int64_t> i64_value,
-                          absl::optional<float> float_value,
-                          absl::optional<double> double_value,
+  void MethodWithNumerics(std::optional<bool> bool_value,
+                          std::optional<uint8_t> u8_value,
+                          std::optional<uint16_t> u16_value,
+                          std::optional<uint32_t> u32_value,
+                          std::optional<uint64_t> u64_value,
+                          std::optional<int8_t> i8_value,
+                          std::optional<int16_t> i16_value,
+                          std::optional<int32_t> i32_value,
+                          std::optional<int64_t> i64_value,
+                          std::optional<float> float_value,
+                          std::optional<double> double_value,
                           MethodWithNumericsCallback callback) override {
     std::move(callback).Run(
         Transform(bool_value), Transform(u8_value), Transform(u16_value),
@@ -336,37 +336,37 @@
   }
 
   void MethodWithVersionedArgs(
-      absl::optional<bool> bool_value,
-      absl::optional<uint8_t> u8_value,
-      absl::optional<uint16_t> u16_value,
-      absl::optional<uint32_t> u32_value,
-      absl::optional<uint64_t> u64_value,
-      absl::optional<int8_t> i8_value,
-      absl::optional<int16_t> i16_value,
-      absl::optional<int32_t> i32_value,
-      absl::optional<int64_t> i64_value,
-      absl::optional<float> float_value,
-      absl::optional<double> double_value,
-      absl::optional<mojom::RegularEnum> enum_value,
-      absl::optional<TypemappedEnum> mapped_enum_value,
+      std::optional<bool> bool_value,
+      std::optional<uint8_t> u8_value,
+      std::optional<uint16_t> u16_value,
+      std::optional<uint32_t> u32_value,
+      std::optional<uint64_t> u64_value,
+      std::optional<int8_t> i8_value,
+      std::optional<int16_t> i16_value,
+      std::optional<int32_t> i32_value,
+      std::optional<int64_t> i64_value,
+      std::optional<float> float_value,
+      std::optional<double> double_value,
+      std::optional<mojom::RegularEnum> enum_value,
+      std::optional<TypemappedEnum> mapped_enum_value,
       MethodWithVersionedArgsCallback callback) override {
     switch (*caller_version_) {
       case CallerVersion::kV1:
         // A caller using the V1 interface will not know about the new
-        // arguments, so they should all equal absl::nullopt.
-        EXPECT_EQ(absl::nullopt, bool_value);
-        EXPECT_EQ(absl::nullopt, u8_value);
-        EXPECT_EQ(absl::nullopt, u16_value);
-        EXPECT_EQ(absl::nullopt, u32_value);
-        EXPECT_EQ(absl::nullopt, u64_value);
-        EXPECT_EQ(absl::nullopt, i8_value);
-        EXPECT_EQ(absl::nullopt, i16_value);
-        EXPECT_EQ(absl::nullopt, i32_value);
-        EXPECT_EQ(absl::nullopt, i64_value);
-        EXPECT_EQ(absl::nullopt, float_value);
-        EXPECT_EQ(absl::nullopt, double_value);
-        EXPECT_EQ(absl::nullopt, enum_value);
-        EXPECT_EQ(absl::nullopt, mapped_enum_value);
+        // arguments, so they should all equal std::nullopt.
+        EXPECT_EQ(std::nullopt, bool_value);
+        EXPECT_EQ(std::nullopt, u8_value);
+        EXPECT_EQ(std::nullopt, u16_value);
+        EXPECT_EQ(std::nullopt, u32_value);
+        EXPECT_EQ(std::nullopt, u64_value);
+        EXPECT_EQ(std::nullopt, i8_value);
+        EXPECT_EQ(std::nullopt, i16_value);
+        EXPECT_EQ(std::nullopt, i32_value);
+        EXPECT_EQ(std::nullopt, i64_value);
+        EXPECT_EQ(std::nullopt, float_value);
+        EXPECT_EQ(std::nullopt, double_value);
+        EXPECT_EQ(std::nullopt, enum_value);
+        EXPECT_EQ(std::nullopt, mapped_enum_value);
         break;
       case CallerVersion::kV2:
         EXPECT_EQ(true, bool_value);
@@ -396,20 +396,20 @@
     switch (*caller_version_) {
       case CallerVersion::kV1:
         // A caller using the V1 interface will not know about the new
-        // arguments, so they should all equal absl::nullopt.
-        EXPECT_EQ(absl::nullopt, in->bool_value);
-        EXPECT_EQ(absl::nullopt, in->u8_value);
-        EXPECT_EQ(absl::nullopt, in->u16_value);
-        EXPECT_EQ(absl::nullopt, in->u32_value);
-        EXPECT_EQ(absl::nullopt, in->u64_value);
-        EXPECT_EQ(absl::nullopt, in->i8_value);
-        EXPECT_EQ(absl::nullopt, in->i16_value);
-        EXPECT_EQ(absl::nullopt, in->i32_value);
-        EXPECT_EQ(absl::nullopt, in->i64_value);
-        EXPECT_EQ(absl::nullopt, in->float_value);
-        EXPECT_EQ(absl::nullopt, in->double_value);
-        EXPECT_EQ(absl::nullopt, in->enum_value);
-        EXPECT_EQ(absl::nullopt, in->mapped_enum_value);
+        // arguments, so they should all equal std::nullopt.
+        EXPECT_EQ(std::nullopt, in->bool_value);
+        EXPECT_EQ(std::nullopt, in->u8_value);
+        EXPECT_EQ(std::nullopt, in->u16_value);
+        EXPECT_EQ(std::nullopt, in->u32_value);
+        EXPECT_EQ(std::nullopt, in->u64_value);
+        EXPECT_EQ(std::nullopt, in->i8_value);
+        EXPECT_EQ(std::nullopt, in->i16_value);
+        EXPECT_EQ(std::nullopt, in->i32_value);
+        EXPECT_EQ(std::nullopt, in->i64_value);
+        EXPECT_EQ(std::nullopt, in->float_value);
+        EXPECT_EQ(std::nullopt, in->double_value);
+        EXPECT_EQ(std::nullopt, in->enum_value);
+        EXPECT_EQ(std::nullopt, in->mapped_enum_value);
         break;
       case CallerVersion::kV2:
         EXPECT_EQ(true, in->bool_value);
@@ -434,7 +434,7 @@
   }
 
   const Receiver<mojom::InterfaceV2> receiver_;
-  const absl::optional<CallerVersion> caller_version_;
+  const std::optional<CallerVersion> caller_version_;
 };
 
 class NullableValueTypes : public ::testing::Test {
@@ -444,37 +444,37 @@
 TEST_F(NullableValueTypes, StructWithEnums) {
   {
     auto input = mojom::StructWithEnums::New();
-    input->enum_value = absl::nullopt;
-    input->mapped_enum_value = absl::nullopt;
+    input->enum_value = std::nullopt;
+    input->mapped_enum_value = std::nullopt;
 
     mojom::StructWithEnumsPtr output;
     ASSERT_TRUE(SerializeAndDeserialize<mojom::StructWithEnums>(input, output));
 
-    EXPECT_EQ(absl::nullopt, output->enum_value);
-    EXPECT_EQ(absl::nullopt, output->mapped_enum_value);
+    EXPECT_EQ(std::nullopt, output->enum_value);
+    EXPECT_EQ(std::nullopt, output->mapped_enum_value);
   }
 
   {
     auto input = mojom::StructWithEnums::New();
     input->enum_value = mojom::RegularEnum::kThisValue;
-    input->mapped_enum_value = absl::nullopt;
+    input->mapped_enum_value = std::nullopt;
 
     mojom::StructWithEnumsPtr output;
     ASSERT_TRUE(SerializeAndDeserialize<mojom::StructWithEnums>(input, output));
 
     EXPECT_EQ(mojom::RegularEnum::kThisValue, output->enum_value);
-    EXPECT_EQ(absl::nullopt, output->mapped_enum_value);
+    EXPECT_EQ(std::nullopt, output->mapped_enum_value);
   }
 
   {
     auto input = mojom::StructWithEnums::New();
-    input->enum_value = absl::nullopt;
+    input->enum_value = std::nullopt;
     input->mapped_enum_value = TypemappedEnum::kValueOne;
 
     mojom::StructWithEnumsPtr output;
     ASSERT_TRUE(SerializeAndDeserialize<mojom::StructWithEnums>(input, output));
 
-    EXPECT_EQ(absl::nullopt, output->enum_value);
+    EXPECT_EQ(std::nullopt, output->enum_value);
     EXPECT_EQ(TypemappedEnum::kValueOne, output->mapped_enum_value);
   }
 
@@ -577,12 +577,12 @@
     {
       base::RunLoop loop;
       remote->MethodWithEnums(
-          absl::nullopt, absl::nullopt,
+          std::nullopt, std::nullopt,
           base::BindLambdaForTesting(
-              [&](absl::optional<mojom::RegularEnum> enum_value,
-                  absl::optional<TypemappedEnum> mapped_enum_value) {
-                EXPECT_EQ(absl::nullopt, enum_value);
-                EXPECT_EQ(absl::nullopt, mapped_enum_value);
+              [&](std::optional<mojom::RegularEnum> enum_value,
+                  std::optional<TypemappedEnum> mapped_enum_value) {
+                EXPECT_EQ(std::nullopt, enum_value);
+                EXPECT_EQ(std::nullopt, mapped_enum_value);
                 loop.Quit();
               }));
       loop.Run();
@@ -591,12 +591,12 @@
     {
       base::RunLoop loop;
       remote->MethodWithEnums(
-          mojom::RegularEnum::kThisValue, absl::nullopt,
+          mojom::RegularEnum::kThisValue, std::nullopt,
           base::BindLambdaForTesting(
-              [&](absl::optional<mojom::RegularEnum> enum_value,
-                  absl::optional<TypemappedEnum> mapped_enum_value) {
+              [&](std::optional<mojom::RegularEnum> enum_value,
+                  std::optional<TypemappedEnum> mapped_enum_value) {
                 EXPECT_EQ(mojom::RegularEnum::kThatValue, enum_value);
-                EXPECT_EQ(absl::nullopt, mapped_enum_value);
+                EXPECT_EQ(std::nullopt, mapped_enum_value);
                 loop.Quit();
               }));
       loop.Run();
@@ -605,11 +605,11 @@
     {
       base::RunLoop loop;
       remote->MethodWithEnums(
-          absl::nullopt, TypemappedEnum::kValueOne,
+          std::nullopt, TypemappedEnum::kValueOne,
           base::BindLambdaForTesting(
-              [&](absl::optional<mojom::RegularEnum> enum_value,
-                  absl::optional<TypemappedEnum> mapped_enum_value) {
-                EXPECT_EQ(absl::nullopt, enum_value);
+              [&](std::optional<mojom::RegularEnum> enum_value,
+                  std::optional<TypemappedEnum> mapped_enum_value) {
+                EXPECT_EQ(std::nullopt, enum_value);
                 EXPECT_EQ(TypemappedEnum::kValueTwo, mapped_enum_value);
                 loop.Quit();
               }));
@@ -621,8 +621,8 @@
       remote->MethodWithEnums(
           mojom::RegularEnum::kThatValue, TypemappedEnum::kValueTwo,
           base::BindLambdaForTesting(
-              [&](absl::optional<mojom::RegularEnum> enum_value,
-                  absl::optional<TypemappedEnum> mapped_enum_value) {
+              [&](std::optional<mojom::RegularEnum> enum_value,
+                  std::optional<TypemappedEnum> mapped_enum_value) {
                 EXPECT_EQ(mojom::RegularEnum::kThisValue, enum_value);
                 EXPECT_EQ(TypemappedEnum::kValueOne, mapped_enum_value);
                 loop.Quit();
@@ -715,10 +715,10 @@
     {
       base::RunLoop loop;
       remote->MethodWithStructWithEnums(
-          mojom::StructWithEnums::New(absl::nullopt, absl::nullopt),
+          mojom::StructWithEnums::New(std::nullopt, std::nullopt),
           base::BindLambdaForTesting([&](mojom::StructWithEnumsPtr out) {
-            EXPECT_EQ(absl::nullopt, out->enum_value);
-            EXPECT_EQ(absl::nullopt, out->mapped_enum_value);
+            EXPECT_EQ(std::nullopt, out->enum_value);
+            EXPECT_EQ(std::nullopt, out->mapped_enum_value);
             loop.Quit();
           }));
       loop.Run();
@@ -728,10 +728,10 @@
       base::RunLoop loop;
       remote->MethodWithStructWithEnums(
           mojom::StructWithEnums::New(mojom::RegularEnum::kThisValue,
-                                      absl::nullopt),
+                                      std::nullopt),
           base::BindLambdaForTesting([&](mojom::StructWithEnumsPtr out) {
             EXPECT_EQ(mojom::RegularEnum::kThatValue, out->enum_value);
-            EXPECT_EQ(absl::nullopt, out->mapped_enum_value);
+            EXPECT_EQ(std::nullopt, out->mapped_enum_value);
             loop.Quit();
           }));
       loop.Run();
@@ -740,9 +740,9 @@
     {
       base::RunLoop loop;
       remote->MethodWithStructWithEnums(
-          mojom::StructWithEnums::New(absl::nullopt, TypemappedEnum::kValueOne),
+          mojom::StructWithEnums::New(std::nullopt, TypemappedEnum::kValueOne),
           base::BindLambdaForTesting([&](mojom::StructWithEnumsPtr out) {
-            EXPECT_EQ(absl::nullopt, out->enum_value);
+            EXPECT_EQ(std::nullopt, out->enum_value);
             EXPECT_EQ(TypemappedEnum::kValueTwo, out->mapped_enum_value);
             loop.Quit();
           }));
@@ -768,15 +768,15 @@
   {
     auto input = mojom::StructWithNumerics::New();
     input->bool_value = true;
-    input->u8_value = absl::nullopt;
+    input->u8_value = std::nullopt;
     input->u16_value = 16;
-    input->u32_value = absl::nullopt;
+    input->u32_value = std::nullopt;
     input->u64_value = 64;
     input->i8_value = -8;
-    input->i16_value = absl::nullopt;
+    input->i16_value = std::nullopt;
     input->i32_value = -32;
-    input->i64_value = absl::nullopt;
-    input->float_value = absl::nullopt;
+    input->i64_value = std::nullopt;
+    input->float_value = std::nullopt;
     input->double_value = -64.0;
 
     mojom::StructWithNumericsPtr output;
@@ -784,47 +784,47 @@
         SerializeAndDeserialize<mojom::StructWithNumerics>(input, output));
 
     EXPECT_EQ(true, output->bool_value);
-    EXPECT_EQ(absl::nullopt, output->u8_value);
+    EXPECT_EQ(std::nullopt, output->u8_value);
     EXPECT_EQ(16u, output->u16_value);
-    EXPECT_EQ(absl::nullopt, output->u32_value);
+    EXPECT_EQ(std::nullopt, output->u32_value);
     EXPECT_EQ(64u, output->u64_value);
     EXPECT_EQ(-8, output->i8_value);
-    EXPECT_EQ(absl::nullopt, output->i16_value);
+    EXPECT_EQ(std::nullopt, output->i16_value);
     EXPECT_EQ(-32, output->i32_value);
-    EXPECT_EQ(absl::nullopt, output->i64_value);
-    EXPECT_EQ(absl::nullopt, output->float_value);
+    EXPECT_EQ(std::nullopt, output->i64_value);
+    EXPECT_EQ(std::nullopt, output->float_value);
     EXPECT_EQ(-64.0, output->double_value);
   }
 
   {
     auto input = mojom::StructWithNumerics::New();
-    input->bool_value = absl::nullopt;
+    input->bool_value = std::nullopt;
     input->u8_value = 8;
-    input->u16_value = absl::nullopt;
+    input->u16_value = std::nullopt;
     input->u32_value = 32;
-    input->u64_value = absl::nullopt;
-    input->i8_value = absl::nullopt;
+    input->u64_value = std::nullopt;
+    input->i8_value = std::nullopt;
     input->i16_value = -16;
-    input->i32_value = absl::nullopt;
+    input->i32_value = std::nullopt;
     input->i64_value = -64;
     input->float_value = -32.0f;
-    input->double_value = absl::nullopt;
+    input->double_value = std::nullopt;
 
     mojom::StructWithNumericsPtr output;
     ASSERT_TRUE(
         SerializeAndDeserialize<mojom::StructWithNumerics>(input, output));
 
-    EXPECT_EQ(absl::nullopt, output->bool_value);
+    EXPECT_EQ(std::nullopt, output->bool_value);
     EXPECT_EQ(8u, output->u8_value);
-    EXPECT_EQ(absl::nullopt, output->u16_value);
+    EXPECT_EQ(std::nullopt, output->u16_value);
     EXPECT_EQ(32u, output->u32_value);
-    EXPECT_EQ(absl::nullopt, output->u64_value);
-    EXPECT_EQ(absl::nullopt, output->i8_value);
+    EXPECT_EQ(std::nullopt, output->u64_value);
+    EXPECT_EQ(std::nullopt, output->i8_value);
     EXPECT_EQ(-16, output->i16_value);
-    EXPECT_EQ(absl::nullopt, output->i32_value);
+    EXPECT_EQ(std::nullopt, output->i32_value);
     EXPECT_EQ(-64, output->i64_value);
     EXPECT_EQ(-32.0f, output->float_value);
-    EXPECT_EQ(absl::nullopt, output->double_value);
+    EXPECT_EQ(std::nullopt, output->double_value);
   }
 }
 
@@ -931,33 +931,33 @@
     {
       base::RunLoop loop;
       remote->MethodWithNumerics(
-          true, absl::nullopt, uint16_t{16}, absl::nullopt, uint64_t{64},
-          int8_t{-8}, absl::nullopt, int32_t{-32}, absl::nullopt, absl::nullopt,
+          true, std::nullopt, uint16_t{16}, std::nullopt, uint64_t{64},
+          int8_t{-8}, std::nullopt, int32_t{-32}, std::nullopt, std::nullopt,
           -64.0,
-          base::BindLambdaForTesting([&](absl::optional<bool> bool_value,
-                                         absl::optional<uint8_t> u8_value,
-                                         absl::optional<uint16_t> u16_value,
-                                         absl::optional<uint32_t> u32_value,
-                                         absl::optional<uint64_t> u64_value,
-                                         absl::optional<int8_t> i8_value,
-                                         absl::optional<int16_t> i16_value,
-                                         absl::optional<int32_t> i32_value,
-                                         absl::optional<int64_t> i64_value,
-                                         absl::optional<float> float_value,
-                                         absl::optional<double> double_value) {
+          base::BindLambdaForTesting([&](std::optional<bool> bool_value,
+                                         std::optional<uint8_t> u8_value,
+                                         std::optional<uint16_t> u16_value,
+                                         std::optional<uint32_t> u32_value,
+                                         std::optional<uint64_t> u64_value,
+                                         std::optional<int8_t> i8_value,
+                                         std::optional<int16_t> i16_value,
+                                         std::optional<int32_t> i32_value,
+                                         std::optional<int64_t> i64_value,
+                                         std::optional<float> float_value,
+                                         std::optional<double> double_value) {
             EXPECT_EQ(false, bool_value);
-            EXPECT_EQ(absl::nullopt, u8_value);
+            EXPECT_EQ(std::nullopt, u8_value);
             // Note: the seemingly more obvious ~uint16_t{16} is not used
             // here because using ~ when sizeof(integer) < sizeof(int)
             // automatically promotes to an int. 🙃
             EXPECT_EQ(uint16_t{0xffef}, u16_value);
-            EXPECT_EQ(absl::nullopt, u32_value);
+            EXPECT_EQ(std::nullopt, u32_value);
             EXPECT_EQ(~uint64_t{64}, u64_value);
             EXPECT_EQ(8, i8_value);
-            EXPECT_EQ(absl::nullopt, i16_value);
+            EXPECT_EQ(std::nullopt, i16_value);
             EXPECT_EQ(32, i32_value);
-            EXPECT_EQ(absl::nullopt, i64_value);
-            EXPECT_EQ(absl::nullopt, float_value);
+            EXPECT_EQ(std::nullopt, i64_value);
+            EXPECT_EQ(std::nullopt, float_value);
             EXPECT_EQ(128.0, double_value);
             loop.Quit();
           }));
@@ -967,34 +967,34 @@
     {
       base::RunLoop loop;
       remote->MethodWithNumerics(
-          absl::nullopt, uint8_t{8}, absl::nullopt, uint32_t{32}, absl::nullopt,
-          absl::nullopt, int16_t{-16}, absl::nullopt, int64_t{-64}, -32.0f,
-          absl::nullopt,
-          base::BindLambdaForTesting([&](absl::optional<bool> bool_value,
-                                         absl::optional<uint8_t> u8_value,
-                                         absl::optional<uint16_t> u16_value,
-                                         absl::optional<uint32_t> u32_value,
-                                         absl::optional<uint64_t> u64_value,
-                                         absl::optional<int8_t> i8_value,
-                                         absl::optional<int16_t> i16_value,
-                                         absl::optional<int32_t> i32_value,
-                                         absl::optional<int64_t> i64_value,
-                                         absl::optional<float> float_value,
-                                         absl::optional<double> double_value) {
-            EXPECT_EQ(absl::nullopt, bool_value);
+          std::nullopt, uint8_t{8}, std::nullopt, uint32_t{32}, std::nullopt,
+          std::nullopt, int16_t{-16}, std::nullopt, int64_t{-64}, -32.0f,
+          std::nullopt,
+          base::BindLambdaForTesting([&](std::optional<bool> bool_value,
+                                         std::optional<uint8_t> u8_value,
+                                         std::optional<uint16_t> u16_value,
+                                         std::optional<uint32_t> u32_value,
+                                         std::optional<uint64_t> u64_value,
+                                         std::optional<int8_t> i8_value,
+                                         std::optional<int16_t> i16_value,
+                                         std::optional<int32_t> i32_value,
+                                         std::optional<int64_t> i64_value,
+                                         std::optional<float> float_value,
+                                         std::optional<double> double_value) {
+            EXPECT_EQ(std::nullopt, bool_value);
             // Note: the seemingly more obvious ~uint8_t{8} is not used
             // here because using ~ when sizeof(integer) < sizeof(int)
             // automatically promotes to an int. 🙃
             EXPECT_EQ(uint8_t{0xf7}, u8_value);
-            EXPECT_EQ(absl::nullopt, u16_value);
+            EXPECT_EQ(std::nullopt, u16_value);
             EXPECT_EQ(~uint32_t{32}, u32_value);
-            EXPECT_EQ(absl::nullopt, u64_value);
-            EXPECT_EQ(absl::nullopt, i8_value);
+            EXPECT_EQ(std::nullopt, u64_value);
+            EXPECT_EQ(std::nullopt, i8_value);
             EXPECT_EQ(16, i16_value);
-            EXPECT_EQ(absl::nullopt, i32_value);
+            EXPECT_EQ(std::nullopt, i32_value);
             EXPECT_EQ(64, i64_value);
             EXPECT_EQ(64.0, float_value);
-            EXPECT_EQ(absl::nullopt, double_value);
+            EXPECT_EQ(std::nullopt, double_value);
             loop.Quit();
           }));
       loop.Run();
@@ -1093,24 +1093,24 @@
     {
       base::RunLoop loop;
       remote->MethodWithStructWithNumerics(
-          mojom::StructWithNumerics::New(
-              true, absl::nullopt, uint16_t{16}, absl::nullopt, uint64_t{64},
-              int8_t{-8}, absl::nullopt, int32_t{-32}, absl::nullopt,
-              absl::nullopt, -64.0),
+          mojom::StructWithNumerics::New(true, std::nullopt, uint16_t{16},
+                                         std::nullopt, uint64_t{64}, int8_t{-8},
+                                         std::nullopt, int32_t{-32},
+                                         std::nullopt, std::nullopt, -64.0),
           base::BindLambdaForTesting([&](mojom::StructWithNumericsPtr out) {
             EXPECT_EQ(false, out->bool_value);
-            EXPECT_EQ(absl::nullopt, out->u8_value);
+            EXPECT_EQ(std::nullopt, out->u8_value);
             // Note: the seemingly more obvious ~uint16_t{16} is not used
             // here because using ~ when sizeof(integer) < sizeof(int)
             // automatically promotes to an int. 🙃
             EXPECT_EQ(uint16_t{0xffef}, out->u16_value);
-            EXPECT_EQ(absl::nullopt, out->u32_value);
+            EXPECT_EQ(std::nullopt, out->u32_value);
             EXPECT_EQ(~uint64_t{64}, out->u64_value);
             EXPECT_EQ(8, out->i8_value);
-            EXPECT_EQ(absl::nullopt, out->i16_value);
+            EXPECT_EQ(std::nullopt, out->i16_value);
             EXPECT_EQ(32, out->i32_value);
-            EXPECT_EQ(absl::nullopt, out->i64_value);
-            EXPECT_EQ(absl::nullopt, out->float_value);
+            EXPECT_EQ(std::nullopt, out->i64_value);
+            EXPECT_EQ(std::nullopt, out->float_value);
             EXPECT_EQ(128.0, out->double_value);
             loop.Quit();
           }));
@@ -1121,24 +1121,24 @@
       base::RunLoop loop;
       remote->MethodWithStructWithNumerics(
           mojom::StructWithNumerics::New(
-              absl::nullopt, uint8_t{8}, absl::nullopt, uint32_t{32},
-              absl::nullopt, absl::nullopt, int16_t{-16}, absl::nullopt,
-              int64_t{-64}, -32.0f, absl::nullopt),
+              std::nullopt, uint8_t{8}, std::nullopt, uint32_t{32},
+              std::nullopt, std::nullopt, int16_t{-16}, std::nullopt,
+              int64_t{-64}, -32.0f, std::nullopt),
           base::BindLambdaForTesting([&](mojom::StructWithNumericsPtr out) {
-            EXPECT_EQ(absl::nullopt, out->bool_value);
+            EXPECT_EQ(std::nullopt, out->bool_value);
             // Note: the seemingly more obvious ~uint8_t{8} is not used
             // here because using ~ when sizeof(integer) < sizeof(int)
             // automatically promotes to an int. 🙃
             EXPECT_EQ(uint8_t{0xf7}, out->u8_value);
-            EXPECT_EQ(absl::nullopt, out->u16_value);
+            EXPECT_EQ(std::nullopt, out->u16_value);
             EXPECT_EQ(~uint32_t{32}, out->u32_value);
-            EXPECT_EQ(absl::nullopt, out->u64_value);
-            EXPECT_EQ(absl::nullopt, out->i8_value);
+            EXPECT_EQ(std::nullopt, out->u64_value);
+            EXPECT_EQ(std::nullopt, out->i8_value);
             EXPECT_EQ(16, out->i16_value);
-            EXPECT_EQ(absl::nullopt, out->i32_value);
+            EXPECT_EQ(std::nullopt, out->i32_value);
             EXPECT_EQ(64, out->i64_value);
             EXPECT_EQ(64.0, out->float_value);
-            EXPECT_EQ(absl::nullopt, out->double_value);
+            EXPECT_EQ(std::nullopt, out->double_value);
             loop.Quit();
           }));
       loop.Run();
@@ -1215,35 +1215,35 @@
           int16_t{-32}, int32_t{-64}, int64_t{-128}, 256.0f, -512.0,
           mojom::RegularEnum::kThisValue, TypemappedEnum::kValueTwo,
           base::BindLambdaForTesting(
-              [&](absl::optional<bool> out_bool_value,
-                  absl::optional<uint8_t> out_u8_value,
-                  absl::optional<uint16_t> out_u16_value,
-                  absl::optional<uint32_t> out_u32_value,
-                  absl::optional<uint64_t> out_u64_value,
-                  absl::optional<int8_t> out_i8_value,
-                  absl::optional<int16_t> out_i16_value,
-                  absl::optional<int32_t> out_i32_value,
-                  absl::optional<int64_t> out_i64_value,
-                  absl::optional<float> out_float_value,
-                  absl::optional<double> out_double_value,
-                  absl::optional<mojom::RegularEnum> out_enum_value,
-                  absl::optional<TypemappedEnum> out_mapped_enum_value) {
+              [&](std::optional<bool> out_bool_value,
+                  std::optional<uint8_t> out_u8_value,
+                  std::optional<uint16_t> out_u16_value,
+                  std::optional<uint32_t> out_u32_value,
+                  std::optional<uint64_t> out_u64_value,
+                  std::optional<int8_t> out_i8_value,
+                  std::optional<int16_t> out_i16_value,
+                  std::optional<int32_t> out_i32_value,
+                  std::optional<int64_t> out_i64_value,
+                  std::optional<float> out_float_value,
+                  std::optional<double> out_double_value,
+                  std::optional<mojom::RegularEnum> out_enum_value,
+                  std::optional<TypemappedEnum> out_mapped_enum_value) {
                 // An implementation based on the V1 interface will not know
                 // about the new arguments, so they should all equal
-                // absl::nullopt.
-                EXPECT_EQ(absl::nullopt, out_bool_value);
-                EXPECT_EQ(absl::nullopt, out_u8_value);
-                EXPECT_EQ(absl::nullopt, out_u16_value);
-                EXPECT_EQ(absl::nullopt, out_u32_value);
-                EXPECT_EQ(absl::nullopt, out_u64_value);
-                EXPECT_EQ(absl::nullopt, out_i8_value);
-                EXPECT_EQ(absl::nullopt, out_i16_value);
-                EXPECT_EQ(absl::nullopt, out_i32_value);
-                EXPECT_EQ(absl::nullopt, out_i64_value);
-                EXPECT_EQ(absl::nullopt, out_float_value);
-                EXPECT_EQ(absl::nullopt, out_double_value);
-                EXPECT_EQ(absl::nullopt, out_enum_value);
-                EXPECT_EQ(absl::nullopt, out_mapped_enum_value);
+                // std::nullopt.
+                EXPECT_EQ(std::nullopt, out_bool_value);
+                EXPECT_EQ(std::nullopt, out_u8_value);
+                EXPECT_EQ(std::nullopt, out_u16_value);
+                EXPECT_EQ(std::nullopt, out_u32_value);
+                EXPECT_EQ(std::nullopt, out_u64_value);
+                EXPECT_EQ(std::nullopt, out_i8_value);
+                EXPECT_EQ(std::nullopt, out_i16_value);
+                EXPECT_EQ(std::nullopt, out_i32_value);
+                EXPECT_EQ(std::nullopt, out_i64_value);
+                EXPECT_EQ(std::nullopt, out_float_value);
+                EXPECT_EQ(std::nullopt, out_double_value);
+                EXPECT_EQ(std::nullopt, out_enum_value);
+                EXPECT_EQ(std::nullopt, out_mapped_enum_value);
                 loop.Quit();
               }));
       loop.Run();
@@ -1260,20 +1260,20 @@
           base::BindLambdaForTesting([&](mojom::VersionedStructV2Ptr out) {
             // An implementation based on the V1 interface will not know
             // about the new arguments, so they should all equal
-            // absl::nullopt.
-            EXPECT_EQ(absl::nullopt, out->bool_value);
-            EXPECT_EQ(absl::nullopt, out->u8_value);
-            EXPECT_EQ(absl::nullopt, out->u16_value);
-            EXPECT_EQ(absl::nullopt, out->u32_value);
-            EXPECT_EQ(absl::nullopt, out->u64_value);
-            EXPECT_EQ(absl::nullopt, out->i8_value);
-            EXPECT_EQ(absl::nullopt, out->i16_value);
-            EXPECT_EQ(absl::nullopt, out->i32_value);
-            EXPECT_EQ(absl::nullopt, out->i64_value);
-            EXPECT_EQ(absl::nullopt, out->float_value);
-            EXPECT_EQ(absl::nullopt, out->double_value);
-            EXPECT_EQ(absl::nullopt, out->enum_value);
-            EXPECT_EQ(absl::nullopt, out->mapped_enum_value);
+            // std::nullopt.
+            EXPECT_EQ(std::nullopt, out->bool_value);
+            EXPECT_EQ(std::nullopt, out->u8_value);
+            EXPECT_EQ(std::nullopt, out->u16_value);
+            EXPECT_EQ(std::nullopt, out->u32_value);
+            EXPECT_EQ(std::nullopt, out->u64_value);
+            EXPECT_EQ(std::nullopt, out->i8_value);
+            EXPECT_EQ(std::nullopt, out->i16_value);
+            EXPECT_EQ(std::nullopt, out->i32_value);
+            EXPECT_EQ(std::nullopt, out->i64_value);
+            EXPECT_EQ(std::nullopt, out->float_value);
+            EXPECT_EQ(std::nullopt, out->double_value);
+            EXPECT_EQ(std::nullopt, out->enum_value);
+            EXPECT_EQ(std::nullopt, out->mapped_enum_value);
             loop.Quit();
           }));
       loop.Run();
@@ -1294,19 +1294,19 @@
           int16_t{-32}, int32_t{-64}, int64_t{-128}, 256.0f, -512.0,
           mojom::RegularEnum::kThisValue, TypemappedEnum::kValueTwo,
           base::BindLambdaForTesting(
-              [&](absl::optional<bool> out_bool_value,
-                  absl::optional<uint8_t> out_u8_value,
-                  absl::optional<uint16_t> out_u16_value,
-                  absl::optional<uint32_t> out_u32_value,
-                  absl::optional<uint64_t> out_u64_value,
-                  absl::optional<int8_t> out_i8_value,
-                  absl::optional<int16_t> out_i16_value,
-                  absl::optional<int32_t> out_i32_value,
-                  absl::optional<int64_t> out_i64_value,
-                  absl::optional<float> out_float_value,
-                  absl::optional<double> out_double_value,
-                  absl::optional<mojom::RegularEnum> out_enum_value,
-                  absl::optional<TypemappedEnum> out_mapped_enum_value) {
+              [&](std::optional<bool> out_bool_value,
+                  std::optional<uint8_t> out_u8_value,
+                  std::optional<uint16_t> out_u16_value,
+                  std::optional<uint32_t> out_u32_value,
+                  std::optional<uint64_t> out_u64_value,
+                  std::optional<int8_t> out_i8_value,
+                  std::optional<int16_t> out_i16_value,
+                  std::optional<int32_t> out_i32_value,
+                  std::optional<int64_t> out_i64_value,
+                  std::optional<float> out_float_value,
+                  std::optional<double> out_double_value,
+                  std::optional<mojom::RegularEnum> out_enum_value,
+                  std::optional<TypemappedEnum> out_mapped_enum_value) {
                 EXPECT_EQ(false, out_bool_value);
                 EXPECT_EQ(uint8_t{128}, out_u8_value);
                 EXPECT_EQ(uint16_t{64}, out_u16_value);
diff --git a/mojo/public/cpp/bindings/tests/receiver_unittest.cc b/mojo/public/cpp/bindings/tests/receiver_unittest.cc
index 34ffa853f..ac6a759 100644
--- a/mojo/public/cpp/bindings/tests/receiver_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/receiver_unittest.cc
@@ -5,6 +5,7 @@
 #include <stdint.h>
 #include <utility>
 
+#include <optional>
 #include "base/check_op.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
@@ -33,7 +34,6 @@
 #include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h"
 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace test {
@@ -768,7 +768,7 @@
 
   Receiver<mojom::TestGenericBinder> receiver_;
   bool connected_ = true;
-  absl::optional<base::RunLoop> wait_loop_;
+  std::optional<base::RunLoop> wait_loop_;
   raw_ptr<GenericPendingReceiver> next_receiver_storage_ = nullptr;
   raw_ptr<GenericPendingAssociatedReceiver> next_associated_receiver_storage_ =
       nullptr;
@@ -1013,7 +1013,7 @@
     constexpr size_t kNumIterations = 1000;
     constexpr size_t kNumReceiversPerIteration = 10;
     for (size_t i = 0; i < kNumIterations; ++i) {
-      std::vector<absl::optional<Receiver<mojom::TestInterface1>>> receivers(
+      std::vector<std::optional<Receiver<mojom::TestInterface1>>> receivers(
           kNumReceiversPerIteration);
       for (auto& receiver : receivers) {
         receiver.emplace(this);
diff --git a/mojo/public/cpp/bindings/tests/remote_unittest.cc b/mojo/public/cpp/bindings/tests/remote_unittest.cc
index 3801b5d..1df9c86 100644
--- a/mojo/public/cpp/bindings/tests/remote_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/remote_unittest.cc
@@ -7,6 +7,7 @@
 #include <tuple>
 #include <utility>
 
+#include <optional>
 #include "base/barrier_closure.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/functional/bind.h"
@@ -39,7 +40,6 @@
 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h"
 #include "mojo/public/interfaces/bindings/tests/scoping.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace test {
@@ -1307,7 +1307,7 @@
 }
 
 TEST_P(RemoteTest, RemoteSet) {
-  std::vector<absl::optional<MathCalculatorImpl>> impls(4);
+  std::vector<std::optional<MathCalculatorImpl>> impls(4);
 
   PendingRemote<math::Calculator> remote0;
   PendingRemote<math::Calculator> remote1;
diff --git a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
index d7d4919..5e93add 100644
--- a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
@@ -84,7 +84,7 @@
                   std::move(extra_bars), std::move(data),
                   std::move(pipe.handle1), std::move(input_streams),
                   std::move(output_streams), std::move(array_of_array_of_bools),
-                  absl::nullopt, absl::nullopt);
+                  std::nullopt, std::nullopt);
 }
 
 // Check that the given |Foo| is identical to the one made by |MakeFoo()|.
@@ -201,7 +201,7 @@
 template <typename T>
 void Print(int depth,
            const char* name,
-           const absl::optional<std::vector<T>>& array) {
+           const std::optional<std::vector<T>>& array) {
   if (array)
     Print(depth, name, *array);
   else
diff --git a/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc b/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
index 2a57ca4..4cabf95e 100644
--- a/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
@@ -27,9 +27,9 @@
 using mojo::internal::GetMapValidator;
 
 // Creates an array of arrays of handles (2 X 3) for testing.
-std::vector<absl::optional<std::vector<ScopedHandle>>>
+std::vector<std::optional<std::vector<ScopedHandle>>>
 CreateTestNestedHandleArray() {
-  std::vector<absl::optional<std::vector<ScopedHandle>>> array(2);
+  std::vector<std::optional<std::vector<ScopedHandle>>> array(2);
   for (size_t i = 0; i < array.size(); ++i) {
     std::vector<ScopedHandle> nested_array(3);
     for (size_t j = 0; j < nested_array.size(); ++j) {
@@ -159,7 +159,7 @@
 TEST_F(SerializationWarningTest, ArrayOfArraysOfHandles) {
   using MojomType = ArrayDataView<ArrayDataView<ScopedHandle>>;
   auto test_array = CreateTestNestedHandleArray();
-  test_array[0] = absl::nullopt;
+  test_array[0] = std::nullopt;
   (*test_array[1])[0] = ScopedHandle();
 
   constexpr const ContainerValidateParams& validate_params_0 =
@@ -169,7 +169,7 @@
                               &validate_params_0);
 
   test_array = CreateTestNestedHandleArray();
-  test_array[0] = absl::nullopt;
+  test_array[0] = std::nullopt;
   constexpr const ContainerValidateParams& validate_params_1 =
       GetArrayValidator<0, false, &GetArrayValidator<0, true, nullptr>()>();
   TestArrayWarning<MojomType>(
@@ -200,7 +200,7 @@
                               mojo::internal::VALIDATION_ERROR_NONE,
                               &validate_params_0);
 
-  std::vector<absl::optional<std::string>> optional_test_array(3);
+  std::vector<std::optional<std::string>> optional_test_array(3);
   constexpr const ContainerValidateParams& validate_params_1 =
       GetArrayValidator<0, false, &GetArrayValidator<0, false, nullptr>()>();
   TestArrayWarning<MojomType>(
diff --git a/mojo/public/cpp/bindings/tests/service_factory_unittest.cc b/mojo/public/cpp/bindings/tests/service_factory_unittest.cc
index 19393397..6fb7ffe 100644
--- a/mojo/public/cpp/bindings/tests/service_factory_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/service_factory_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "mojo/public/cpp/bindings/service_factory.h"
 
+#include <optional>
 #include "base/functional/callback.h"
 #include "base/functional/callback_helpers.h"
 #include "base/run_loop.h"
@@ -15,7 +16,6 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/bindings/tests/service_factory_unittest.test-mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace test {
@@ -170,7 +170,7 @@
 }
 
 TEST_F(ServiceFactoryTest, DestroyInstancesOnFactoryDestruction) {
-  absl::optional<ServiceFactory> factory{absl::in_place};
+  std::optional<ServiceFactory> factory{std::in_place};
   factory->Add(RunTestService1);
 
   Remote<mojom::TestService1> remote1;
diff --git a/mojo/public/cpp/bindings/tests/struct_traits_unittest.cc b/mojo/public/cpp/bindings/tests/struct_traits_unittest.cc
index 7395550..15d9853 100644
--- a/mojo/public/cpp/bindings/tests/struct_traits_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/struct_traits_unittest.cc
@@ -160,7 +160,7 @@
   }
 
   void EchoNullableMoveOnlyStructWithTraits(
-      absl::optional<MoveOnlyStructWithTraitsImpl> s,
+      std::optional<MoveOnlyStructWithTraitsImpl> s,
       EchoNullableMoveOnlyStructWithTraitsCallback callback) override {
     std::move(callback).Run(std::move(s));
   }
@@ -401,9 +401,9 @@
 }
 
 void CaptureNullableMoveOnlyStructWithTraitsImpl(
-    absl::optional<MoveOnlyStructWithTraitsImpl>* storage,
+    std::optional<MoveOnlyStructWithTraitsImpl>* storage,
     base::OnceClosure closure,
-    absl::optional<MoveOnlyStructWithTraitsImpl> passed) {
+    std::optional<MoveOnlyStructWithTraitsImpl> passed) {
   *storage = std::move(passed);
   std::move(closure).Run();
 }
@@ -412,11 +412,10 @@
   base::RunLoop loop;
   Remote<TraitsTestService> proxy = GetTraitsTestProxy();
 
-  absl::optional<MoveOnlyStructWithTraitsImpl> received;
+  std::optional<MoveOnlyStructWithTraitsImpl> received;
   proxy->EchoNullableMoveOnlyStructWithTraits(
-      absl::nullopt,
-      base::BindOnce(&CaptureNullableMoveOnlyStructWithTraitsImpl, &received,
-                     loop.QuitClosure()));
+      std::nullopt, base::BindOnce(&CaptureNullableMoveOnlyStructWithTraitsImpl,
+                                   &received, loop.QuitClosure()));
   loop.Run();
 
   EXPECT_FALSE(received);
diff --git a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
index 250e518e..d70117e 100644
--- a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
@@ -31,20 +31,20 @@
       : receiver_(this, std::move(receiver)) {}
 
   // mojo::test::TestWTF implementation:
-  void EchoString(const absl::optional<std::string>& str,
+  void EchoString(const std::optional<std::string>& str,
                   EchoStringCallback callback) override {
     std::move(callback).Run(str);
   }
 
   void EchoStringArray(
-      const absl::optional<std::vector<absl::optional<std::string>>>& arr,
+      const std::optional<std::vector<std::optional<std::string>>>& arr,
       EchoStringArrayCallback callback) override {
     std::move(callback).Run(std::move(arr));
   }
 
   void EchoStringMap(
-      const absl::optional<
-          base::flat_map<std::string, absl::optional<std::string>>>& str_map,
+      const std::optional<
+          base::flat_map<std::string, std::optional<std::string>>>& str_map,
       EchoStringMapCallback callback) override {
     std::move(callback).Run(std::move(str_map));
   }
@@ -89,17 +89,17 @@
   std::move(closure).Run();
 }
 
-void ExpectStringArray(absl::optional<WTF::Vector<WTF::String>>* expected_arr,
+void ExpectStringArray(std::optional<WTF::Vector<WTF::String>>* expected_arr,
                        base::OnceClosure closure,
-                       const absl::optional<WTF::Vector<WTF::String>>& arr) {
+                       const std::optional<WTF::Vector<WTF::String>>& arr) {
   EXPECT_EQ(*expected_arr, arr);
   std::move(closure).Run();
 }
 
 void ExpectStringMap(
-    absl::optional<WTF::HashMap<WTF::String, WTF::String>>* expected_map,
+    std::optional<WTF::HashMap<WTF::String, WTF::String>>* expected_map,
     base::OnceClosure closure,
-    const absl::optional<WTF::HashMap<WTF::String, WTF::String>>& map) {
+    const std::optional<WTF::HashMap<WTF::String, WTF::String>>& map) {
   EXPECT_EQ(*expected_map, map);
   std::move(closure).Run();
 }
@@ -168,7 +168,7 @@
           0, true, &mojo::internal::GetArrayValidator<0, false, nullptr>()>();
   mojo::internal::Serialize<MojomType>(cloned_strs, fragment, &validate_params);
 
-  std::vector<absl::optional<std::string>> strs2;
+  std::vector<std::optional<std::string>> strs2;
   mojo::internal::Deserialize<MojomType>(fragment.data(), &strs2, &message);
 
   ASSERT_EQ(4u, strs2.size());
@@ -201,7 +201,7 @@
     base::RunLoop loop;
     // Test that a WTF::String is unchanged after the following conversion:
     //   - serialized;
-    //   - deserialized as absl::optional<std::string>;
+    //   - deserialized as std::optional<std::string>;
     //   - serialized;
     //   - deserialized as WTF::String.
     remote->EchoString(
@@ -215,7 +215,7 @@
   TestWTFImpl impl(
       ConvertPendingReceiver<TestWTF>(remote.BindNewPipeAndPassReceiver()));
 
-  absl::optional<WTF::Vector<WTF::String>> arrs[3];
+  std::optional<WTF::Vector<WTF::String>> arrs[3];
   // arrs[0] is empty.
   arrs[0].emplace();
   // arrs[1] is null.
@@ -223,13 +223,13 @@
 
   for (size_t i = 0; i < std::size(arrs); ++i) {
     base::RunLoop loop;
-    // Test that a absl::optional<WTF::Vector<WTF::String>> is unchanged after
+    // Test that a std::optional<WTF::Vector<WTF::String>> is unchanged after
     // the following conversion:
     //   - serialized;
     //   - deserialized as
-    //     absl::optional<std::vector<absl::optional<std::string>>>;
+    //     std::optional<std::vector<std::optional<std::string>>>;
     //   - serialized;
-    //   - deserialized as absl::optional<WTF::Vector<WTF::String>>.
+    //   - deserialized as std::optional<WTF::Vector<WTF::String>>.
     remote->EchoStringArray(
         arrs[i], base::BindOnce(&ExpectStringArray, base::Unretained(&arrs[i]),
                                 loop.QuitClosure()));
@@ -242,7 +242,7 @@
   TestWTFImpl impl(
       ConvertPendingReceiver<TestWTF>(remote.BindNewPipeAndPassReceiver()));
 
-  absl::optional<WTF::HashMap<WTF::String, WTF::String>> maps[3];
+  std::optional<WTF::HashMap<WTF::String, WTF::String>> maps[3];
   // maps[0] is empty.
   maps[0].emplace();
   // maps[1] is null.
@@ -250,13 +250,13 @@
 
   for (size_t i = 0; i < std::size(maps); ++i) {
     base::RunLoop loop;
-    // Test that a absl::optional<WTF::HashMap<WTF::String, WTF::String>> is
+    // Test that a std::optional<WTF::HashMap<WTF::String, WTF::String>> is
     // unchanged after the following conversion:
     //   - serialized;
-    //   - deserialized as absl::optional<
-    //         base::flat_map<std::string, absl::optional<std::string>>>;
+    //   - deserialized as std::optional<
+    //         base::flat_map<std::string, std::optional<std::string>>>;
     //   - serialized;
-    //   - deserialized as absl::optional<WTF::HashMap<WTF::String,
+    //   - deserialized as std::optional<WTF::HashMap<WTF::String,
     //     WTF::String>>.
     remote->EchoStringMap(
         maps[i], base::BindOnce(&ExpectStringMap, base::Unretained(&maps[i]),
diff --git a/mojo/public/cpp/platform/platform_handle_internal.h b/mojo/public/cpp/platform/platform_handle_internal.h
index 5cc7b44..3bbad7e 100644
--- a/mojo/public/cpp/platform/platform_handle_internal.h
+++ b/mojo/public/cpp/platform/platform_handle_internal.h
@@ -22,7 +22,7 @@
     return {.high = token.GetHighForSerialization(),
             .low = token.GetLowForSerialization()};
   }
-  static absl::optional<base::UnguessableToken> UnmarshalUnguessableToken(
+  static std::optional<base::UnguessableToken> UnmarshalUnguessableToken(
       const MojoSharedBufferGuid* guid) {
     return base::UnguessableToken::Deserialize(guid->high, guid->low);
   }
diff --git a/mojo/public/cpp/platform/platform_handle_security_util_win.cc b/mojo/public/cpp/platform/platform_handle_security_util_win.cc
index 76ed1d3..c3bb4e3 100644
--- a/mojo/public/cpp/platform/platform_handle_security_util_win.cc
+++ b/mojo/public/cpp/platform/platform_handle_security_util_win.cc
@@ -6,6 +6,7 @@
 
 #include <windows.h>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/dcheck_is_on.h"
 #include "base/debug/stack_trace.h"
@@ -18,7 +19,6 @@
 #include "base/win/nt_status.h"
 #include "base/win/scoped_handle.h"
 #include "base/win/security_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 
@@ -47,10 +47,10 @@
   return full_path;
 }
 
-absl::optional<bool> IsReadOnlyHandle(HANDLE handle) {
-  absl::optional<ACCESS_MASK> flags = base::win::GetGrantedAccess(handle);
+std::optional<bool> IsReadOnlyHandle(HANDLE handle) {
+  std::optional<ACCESS_MASK> flags = base::win::GetGrantedAccess(handle);
   if (!flags.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   // Cannot use GENERIC_WRITE as that includes SYNCHRONIZE.
   // This is ~(all the writable permissions).
@@ -74,7 +74,7 @@
     return;
   }
 
-  absl::optional<bool> is_read_only = IsReadOnlyHandle(handle);
+  std::optional<bool> is_read_only = IsReadOnlyHandle(handle);
   if (!is_read_only.has_value()) {
     // If unable to obtain whether or not the handle is read-only, skip the rest
     // of the checks, since it's likely GetPathFromHandle below would fail
diff --git a/mojo/public/cpp/platform/tests/platform_channel_server_unittest.cc b/mojo/public/cpp/platform/tests/platform_channel_server_unittest.cc
index 3789ba8..3081e10 100644
--- a/mojo/public/cpp/platform/tests/platform_channel_server_unittest.cc
+++ b/mojo/public/cpp/platform/tests/platform_channel_server_unittest.cc
@@ -7,6 +7,7 @@
 #include <tuple>
 #include <utility>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/callback.h"
@@ -18,7 +19,6 @@
 #include "mojo/core/channel.h"
 #include "mojo/public/cpp/platform/named_platform_channel.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace {
@@ -99,7 +99,7 @@
   const scoped_refptr<core::Channel> channel_;
   base::RunLoop wait_for_message_;
   base::OnceClosure quit_{wait_for_message_.QuitClosure()};
-  absl::optional<std::string> received_message_;
+  std::optional<std::string> received_message_;
   bool stopped_ = false;
 };
 
diff --git a/mojo/public/cpp/system/dynamic_library_support.cc b/mojo/public/cpp/system/dynamic_library_support.cc
index 8e688b7..9a8cfac47 100644
--- a/mojo/public/cpp/system/dynamic_library_support.cc
+++ b/mojo/public/cpp/system/dynamic_library_support.cc
@@ -17,7 +17,7 @@
 
 // Helper for temporary storage related to |MojoInitialize()| calls.
 struct InitializationState {
-  InitializationState(const absl::optional<base::FilePath>& path,
+  InitializationState(const std::optional<base::FilePath>& path,
                       MojoInitializeFlags flags) {
     options.flags = flags;
 
@@ -44,18 +44,18 @@
 
 }  // namespace
 
-MojoResult LoadCoreLibrary(absl::optional<base::FilePath> path) {
+MojoResult LoadCoreLibrary(std::optional<base::FilePath> path) {
   InitializationState state(path, MOJO_INITIALIZE_FLAG_LOAD_ONLY);
   return MojoInitialize(&state.options);
 }
 
 MojoResult InitializeCoreLibrary(MojoInitializeFlags flags) {
   DCHECK_EQ(flags & MOJO_INITIALIZE_FLAG_LOAD_ONLY, 0u);
-  InitializationState state(absl::nullopt, flags);
+  InitializationState state(std::nullopt, flags);
   return MojoInitialize(&state.options);
 }
 
-MojoResult LoadAndInitializeCoreLibrary(absl::optional<base::FilePath> path,
+MojoResult LoadAndInitializeCoreLibrary(std::optional<base::FilePath> path,
                                         MojoInitializeFlags flags) {
   DCHECK_EQ(flags & MOJO_INITIALIZE_FLAG_LOAD_ONLY, 0u);
   InitializationState state(path, flags);
diff --git a/mojo/public/cpp/system/dynamic_library_support.h b/mojo/public/cpp/system/dynamic_library_support.h
index 745f65c6..bfec170 100644
--- a/mojo/public/cpp/system/dynamic_library_support.h
+++ b/mojo/public/cpp/system/dynamic_library_support.h
@@ -5,10 +5,10 @@
 #ifndef MOJO_PUBLIC_CPP_SYSTEM_DYNAMIC_LIBRARY_SUPPORT_H_
 #define MOJO_PUBLIC_CPP_SYSTEM_DYNAMIC_LIBRARY_SUPPORT_H_
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "mojo/public/c/system/types.h"
 #include "mojo/public/cpp/system/system_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 
@@ -23,7 +23,7 @@
 // cases where the client application must perform some work (e.g. sandbox
 // configuration, forking, etc) between the loading and initialization steps.
 MOJO_CPP_SYSTEM_EXPORT MojoResult
-LoadCoreLibrary(absl::optional<base::FilePath> path);
+LoadCoreLibrary(std::optional<base::FilePath> path);
 
 // Initializes the dynamic Mojo Core library previously loaded by
 // |LoadCoreLibrary()| above.
@@ -37,7 +37,7 @@
 // where they don't need to be performed at different times by the client
 // application.
 MOJO_CPP_SYSTEM_EXPORT MojoResult
-LoadAndInitializeCoreLibrary(absl::optional<base::FilePath> path,
+LoadAndInitializeCoreLibrary(std::optional<base::FilePath> path,
                              MojoInitializeFlags flags);
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/system/platform_handle.cc b/mojo/public/cpp/system/platform_handle.cc
index d6510a5..09e209d 100644
--- a/mojo/public/cpp/system/platform_handle.cc
+++ b/mojo/public/cpp/system/platform_handle.cc
@@ -173,7 +173,7 @@
       return base::subtle::PlatformSharedMemoryRegion();
   }
 
-  absl::optional<base::UnguessableToken> guid =
+  std::optional<base::UnguessableToken> guid =
       internal::PlatformHandleInternal::UnmarshalUnguessableToken(&mojo_guid);
   if (!guid.has_value()) {
     return base::subtle::PlatformSharedMemoryRegion();
diff --git a/mojo/public/cpp/system/tests/invitation_unittest.cc b/mojo/public/cpp/system/tests/invitation_unittest.cc
index f5f5c849..b7a8253b 100644
--- a/mojo/public/cpp/system/tests/invitation_unittest.cc
+++ b/mojo/public/cpp/system/tests/invitation_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include <optional>
 #include "base/base_paths.h"
 #include "base/base_switches.h"
 #include "base/check.h"
@@ -32,7 +33,6 @@
 #include "mojo/public/cpp/system/wait.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/multiprocess_func_list.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_IOS)
 #include "mojo/public/cpp/platform/named_platform_channel.h"
@@ -103,7 +103,7 @@
         base::GetMultiProcessTestChildBaseCommandLine());
 
     base::LaunchOptions launch_options;
-    absl::optional<PlatformChannel> channel;
+    std::optional<PlatformChannel> channel;
     PlatformChannelEndpoint channel_endpoint;
     PlatformChannelServerEndpoint server_endpoint;
     switch (transport_type) {
diff --git a/mojo/public/java/system/javatests/nullable_value_types_test_util.cc b/mojo/public/java/system/javatests/nullable_value_types_test_util.cc
index 81efdaf..9a8f602 100644
--- a/mojo/public/java/system/javatests/nullable_value_types_test_util.cc
+++ b/mojo/public/java/system/javatests/nullable_value_types_test_util.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include <optional>
 #include "base/android/jni_android.h"
 #include "base/notreached.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -14,15 +15,14 @@
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "mojo/public/interfaces/bindings/tests/nullable_value_types.mojom.h"
 #include "mojo/public/java/system/mojo_javatests_jni/NullableValueTypesTestUtil_jni.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
 namespace test::nullable_value_types {
 namespace {
 
 class InterfaceV2 : public mojom::InterfaceV2 {
-  void MethodWithEnums(absl::optional<mojom::RegularEnum> enum_value,
-                       absl::optional<TypemappedEnum> mapped_enum_value,
+  void MethodWithEnums(std::optional<mojom::RegularEnum> enum_value,
+                       std::optional<TypemappedEnum> mapped_enum_value,
                        MethodWithEnumsCallback reply) override {
     std::move(reply).Run(enum_value, mapped_enum_value);
   }
@@ -33,17 +33,17 @@
     std::move(reply).Run(std::move(in));
   }
 
-  void MethodWithNumerics(absl::optional<bool> bool_value,
-                          absl::optional<uint8_t> u8_value,
-                          absl::optional<uint16_t> u16_value,
-                          absl::optional<uint32_t> u32_value,
-                          absl::optional<uint64_t> u64_value,
-                          absl::optional<int8_t> i8_value,
-                          absl::optional<int16_t> i16_value,
-                          absl::optional<int32_t> i32_value,
-                          absl::optional<int64_t> i64_value,
-                          absl::optional<float> float_value,
-                          absl::optional<double> double_value,
+  void MethodWithNumerics(std::optional<bool> bool_value,
+                          std::optional<uint8_t> u8_value,
+                          std::optional<uint16_t> u16_value,
+                          std::optional<uint32_t> u32_value,
+                          std::optional<uint64_t> u64_value,
+                          std::optional<int8_t> i8_value,
+                          std::optional<int16_t> i16_value,
+                          std::optional<int32_t> i32_value,
+                          std::optional<int64_t> i64_value,
+                          std::optional<float> float_value,
+                          std::optional<double> double_value,
                           MethodWithNumericsCallback reply) override {
     std::move(reply).Run(bool_value, u8_value, u16_value, u32_value, u64_value,
                          i8_value, i16_value, i32_value, i64_value, float_value,
@@ -56,19 +56,19 @@
     std::move(reply).Run(std::move(in));
   }
 
-  void MethodWithVersionedArgs(absl::optional<bool> bool_value,
-                               absl::optional<uint8_t> u8_value,
-                               absl::optional<uint16_t> u16_value,
-                               absl::optional<uint32_t> u32_value,
-                               absl::optional<uint64_t> u64_value,
-                               absl::optional<int8_t> i8_value,
-                               absl::optional<int16_t> i16_value,
-                               absl::optional<int32_t> i32_value,
-                               absl::optional<int64_t> i64_value,
-                               absl::optional<float> float_value,
-                               absl::optional<double> double_value,
-                               absl::optional<mojom::RegularEnum> enum_value,
-                               absl::optional<TypemappedEnum> mapped_enum_value,
+  void MethodWithVersionedArgs(std::optional<bool> bool_value,
+                               std::optional<uint8_t> u8_value,
+                               std::optional<uint16_t> u16_value,
+                               std::optional<uint32_t> u32_value,
+                               std::optional<uint64_t> u64_value,
+                               std::optional<int8_t> i8_value,
+                               std::optional<int16_t> i16_value,
+                               std::optional<int32_t> i32_value,
+                               std::optional<int64_t> i64_value,
+                               std::optional<float> float_value,
+                               std::optional<double> double_value,
+                               std::optional<mojom::RegularEnum> enum_value,
+                               std::optional<TypemappedEnum> mapped_enum_value,
                                MethodWithVersionedArgsCallback reply) override {
     // Not currently exercised by tests.
     NOTREACHED_NORETURN();
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
index 9bfe902..10d1248 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
@@ -22,7 +22,7 @@
 #include <type_traits>
 #include <utility>
 
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include <optional>
 
 {%- if contains_only_enums %}
 #include "mojo/public/cpp/bindings/type_converter.h"
diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index 9b3b643..dd2ae5d 100644
--- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -666,7 +666,7 @@
 
   def _GetCppWrapperType(self, kind, add_same_module_namespaces=False):
     def _AddOptional(type_name):
-      return "absl::optional<%s>" % type_name
+      return "std::optional<%s>" % type_name
 
     if self._IsTypemappedKind(kind):
       type_name = self._GetNativeTypeName(kind)
@@ -1063,7 +1063,7 @@
 
     if mojom.IsEnumKind(kind):
       if kind.is_nullable:
-        return f"absl::optional<{_GetName(kind.MakeUnnullableKind())}>"
+        return f"std::optional<{_GetName(kind.MakeUnnullableKind())}>"
       return _GetName(kind)
     if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind):
       return "%sDataView" % _GetName(kind)
@@ -1106,7 +1106,7 @@
       return "mojo::PlatformHandle"
     assert isinstance(kind, mojom.ValueKind)
     if kind.is_nullable:
-      return f"absl::optional<{_kind_to_cpp_type[kind.MakeUnnullableKind()]}>"
+      return f"std::optional<{_kind_to_cpp_type[kind.MakeUnnullableKind()]}>"
     return _kind_to_cpp_type[kind]
 
   def _UnderToCamel(self, value, digits_split=False):
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index b750c06..e95c661 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -1233,8 +1233,10 @@
   // No need to explicitly handle ERR_CACHE_ENTRY_NOT_SUITABLE as the
   // ShouldOpenOnlyMethods() check will handle it.
 
-  // We were unable to open or create an entry.
-  DLOG(WARNING) << "Unable to open or create cache entry";
+  if (mode_ & WRITE) {
+    // We were unable to open or create an entry.
+    DLOG(WARNING) << "Unable to open or create cache entry";
+  }
 
   if (ShouldOpenOnlyMethods()) {
     // These methods, on failure, should bypass the cache.
diff --git a/pdf/accessibility.cc b/pdf/accessibility.cc
index e8a7197d..70b2c86 100644
--- a/pdf/accessibility.cc
+++ b/pdf/accessibility.cc
@@ -58,7 +58,7 @@
 
   int char_index = 0;
   while (char_index < char_count) {
-    absl::optional<AccessibilityTextRunInfo> text_run_info_result =
+    std::optional<AccessibilityTextRunInfo> text_run_info_result =
         engine->GetTextRunInfo(page_index, char_index);
     DCHECK(text_run_info_result.has_value());
     const auto& text_run_info = text_run_info_result.value();
diff --git a/pdf/accessibility_helper.cc b/pdf/accessibility_helper.cc
index 89f62c9..f7ac169 100644
--- a/pdf/accessibility_helper.cc
+++ b/pdf/accessibility_helper.cc
@@ -8,9 +8,9 @@
 
 #include <vector>
 
+#include <optional>
 #include "base/numerics/safe_math.h"
 #include "pdf/accessibility_structs.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chrome_pdf {
 
@@ -38,7 +38,7 @@
     return text_range;
   uint32_t end_char_index = checked_end_char_index.ValueOrDie();
   uint32_t current_char_index = 0;
-  absl::optional<size_t> start_text_run;
+  std::optional<size_t> start_text_run;
   for (size_t i = 0; i < text_runs.size(); ++i) {
     if (!start_text_run.has_value() &&
         IsCharWithinTextRun(text_runs[i], current_char_index,
diff --git a/pdf/parsed_params.cc b/pdf/parsed_params.cc
index 1e142613..d44711bc 100644
--- a/pdf/parsed_params.cc
+++ b/pdf/parsed_params.cc
@@ -24,7 +24,7 @@
 
 ParsedParams::~ParsedParams() = default;
 
-absl::optional<ParsedParams> ParseWebPluginParams(
+std::optional<ParsedParams> ParseWebPluginParams(
     const blink::WebPluginParams& params) {
   ParsedParams result;
   for (size_t i = 0; i < params.attribute_names.size(); ++i) {
@@ -39,7 +39,7 @@
     } else if (params.attribute_names[i] == "background-color") {
       if (!base::StringToUint(params.attribute_values[i].Utf8(),
                               &result.background_color)) {
-        return absl::nullopt;
+        return std::nullopt;
       }
     } else if (params.attribute_names[i] == "javascript") {
       if (params.attribute_values[i] != "allow")
@@ -52,7 +52,7 @@
   }
 
   if (result.src_url.empty())
-    return absl::nullopt;
+    return std::nullopt;
 
   if (result.original_url.empty())
     result.original_url = result.src_url;
diff --git a/pdf/parsed_params.h b/pdf/parsed_params.h
index 6ae4fddb..995dfe2 100644
--- a/pdf/parsed_params.h
+++ b/pdf/parsed_params.h
@@ -7,8 +7,8 @@
 
 #include <string>
 
+#include <optional>
 #include "pdf/pdfium/pdfium_form_filler.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 namespace blink {
@@ -53,8 +53,8 @@
 };
 
 // Creates an `ParsedParams` by parsing a `blink::WebPluginParams`. If
-// `blink::WebPluginParams` is invalid, returns absl::nullopt.
-absl::optional<ParsedParams> ParseWebPluginParams(
+// `blink::WebPluginParams` is invalid, returns std::nullopt.
+std::optional<ParsedParams> ParseWebPluginParams(
     const blink::WebPluginParams& params);
 
 }  // namespace chrome_pdf
diff --git a/pdf/parsed_params_unittest.cc b/pdf/parsed_params_unittest.cc
index 9d165c6..02e7b4d4 100644
--- a/pdf/parsed_params_unittest.cc
+++ b/pdf/parsed_params_unittest.cc
@@ -6,10 +6,10 @@
 
 #include <string>
 
+#include <optional>
 #include "pdf/pdfium/pdfium_form_filler.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_vector.h"
 #include "third_party/blink/public/web/web_plugin_params.h"
@@ -36,7 +36,7 @@
 TEST(ParsedParamsTest, ParseWebPluginParamsMinimal) {
   blink::WebPluginParams params = CreateMinimalWebPluginParams();
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_EQ(kFakeSrcUrl, result->src_url);
@@ -52,7 +52,7 @@
 TEST(ParsedParamsTest, ParseWebPluginParamsWithoutSourceUrl) {
   blink::WebPluginParams params;
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   EXPECT_FALSE(result.has_value());
 }
 
@@ -62,7 +62,7 @@
   params.attribute_values.push_back(
       blink::WebString("https://example.com/original.pdf"));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_EQ(kFakeSrcUrl, result->src_url);
@@ -75,7 +75,7 @@
   params.attribute_values.push_back(
       blink::WebString("https://example.net/top.html"));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_EQ("https://example.net/top.html", result->top_level_url);
@@ -86,7 +86,7 @@
   params.attribute_names.push_back(blink::WebString("full-frame"));
   params.attribute_values.push_back(blink::WebString(""));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_TRUE(result->full_frame);
@@ -97,7 +97,7 @@
   params.attribute_names.push_back(blink::WebString("full-frame"));
   params.attribute_values.push_back(blink::WebString("false"));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_TRUE(result->full_frame);
@@ -108,7 +108,7 @@
   params.attribute_names.push_back(blink::WebString("background-color"));
   params.attribute_values.push_back(blink::WebString("4283586137"));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_EQ(4283586137, result->background_color);
@@ -119,7 +119,7 @@
   params.attribute_names.push_back(blink::WebString("background-color"));
   params.attribute_values.push_back(blink::WebString("red"));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   EXPECT_FALSE(result.has_value());
 }
 
@@ -128,7 +128,7 @@
   params.attribute_names.push_back(blink::WebString("javascript"));
   params.attribute_values.push_back(blink::WebString("allow"));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_THAT(result->script_option,
@@ -141,7 +141,7 @@
   params.attribute_names.push_back(blink::WebString("javascript"));
   params.attribute_values.push_back(blink::WebString(""));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_EQ(PDFiumFormFiller::ScriptOption::kNoJavaScript,
@@ -153,7 +153,7 @@
   params.attribute_names.push_back(blink::WebString("javascript"));
   params.attribute_values.push_back(blink::WebString("true"));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_EQ(PDFiumFormFiller::ScriptOption::kNoJavaScript,
@@ -165,7 +165,7 @@
   params.attribute_names.push_back(blink::WebString("has-edits"));
   params.attribute_values.push_back(blink::WebString(""));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_TRUE(result->has_edits);
@@ -176,7 +176,7 @@
   params.attribute_names.push_back(blink::WebString("has-edits"));
   params.attribute_values.push_back(blink::WebString("false"));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_TRUE(result->has_edits);
@@ -187,7 +187,7 @@
   params.attribute_names.push_back(blink::WebString("use-skia"));
   params.attribute_values.push_back(blink::WebString(""));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_TRUE(result->use_skia);
@@ -198,7 +198,7 @@
   params.attribute_names.push_back(blink::WebString("use-skia"));
   params.attribute_values.push_back(blink::WebString("false"));
 
-  absl::optional<ParsedParams> result = ParseWebPluginParams(params);
+  std::optional<ParsedParams> result = ParseWebPluginParams(params);
   ASSERT_TRUE(result.has_value());
 
   EXPECT_TRUE(result->use_skia);
diff --git a/pdf/pdf.cc b/pdf/pdf.cc
index 9170b05..a3944f4 100644
--- a/pdf/pdf.cc
+++ b/pdf/pdf.cc
@@ -8,12 +8,12 @@
 
 #include <utility>
 
+#include <optional>
 #include "base/feature_list.h"
 #include "build/build_config.h"
 #include "pdf/pdf_engine.h"
 #include "pdf/pdf_features.h"
 #include "pdf/pdf_init.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size_f.h"
 
@@ -21,7 +21,7 @@
 
 namespace {
 
-absl::optional<bool> g_use_skia_renderer_enabled_by_policy;
+std::optional<bool> g_use_skia_renderer_enabled_by_policy;
 
 class ScopedSdkInitializer {
  public:
@@ -98,7 +98,7 @@
   return engine_exports->GetPDFDocInfo(pdf_buffer, page_count, max_page_width);
 }
 
-absl::optional<bool> IsPDFDocTagged(base::span<const uint8_t> pdf_buffer) {
+std::optional<bool> IsPDFDocTagged(base::span<const uint8_t> pdf_buffer) {
   ScopedSdkInitializer scoped_sdk_initializer(/*enable_v8=*/true);
   PDFEngineExports* engine_exports = PDFEngineExports::Get();
   return engine_exports->IsPDFDocTagged(pdf_buffer);
@@ -111,7 +111,7 @@
   return engine_exports->GetPDFStructTreeForPage(pdf_buffer, page_index);
 }
 
-absl::optional<gfx::SizeF> GetPDFPageSizeByIndex(
+std::optional<gfx::SizeF> GetPDFPageSizeByIndex(
     base::span<const uint8_t> pdf_buffer,
     int page_index) {
   ScopedSdkInitializer scoped_sdk_initializer(/*enable_v8=*/true);
diff --git a/pdf/pdf.h b/pdf/pdf.h
index f53e7ea..aa2de18c 100644
--- a/pdf/pdf.h
+++ b/pdf/pdf.h
@@ -102,7 +102,7 @@
 // Whether the PDF is Tagged (see 10.7 "Tagged PDF" in PDF Reference 1.7).
 // Returns true if it's a tagged (accessible) PDF, false if it's a valid
 // PDF but untagged, and nullopt if the PDF can't be parsed.
-absl::optional<bool> IsPDFDocTagged(base::span<const uint8_t> pdf_buffer);
+std::optional<bool> IsPDFDocTagged(base::span<const uint8_t> pdf_buffer);
 
 // Given a tagged PDF (see IsPDFDocTagged, above), return the portion of
 // the structure tree for a given page as a hierarchical tree of base::Values.
@@ -115,7 +115,7 @@
 // `page_index` is the page number that the function will get the dimensions of.
 // Returns the size of the page in points, or nullopt if the document or the
 // page number are not valid.
-absl::optional<gfx::SizeF> GetPDFPageSizeByIndex(
+std::optional<gfx::SizeF> GetPDFPageSizeByIndex(
     base::span<const uint8_t> pdf_buffer,
     int page_index);
 
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h
index 7e4868d..fcd9428 100644
--- a/pdf/pdf_engine.h
+++ b/pdf/pdf_engine.h
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/functional/callback.h"
 #include "base/time/time.h"
@@ -18,7 +19,6 @@
 #include "build/build_config.h"
 #include "pdf/document_layout.h"
 #include "printing/mojom/print.mojom-forward.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
 #include "ui/base/window_open_disposition.h"
@@ -366,7 +366,7 @@
   // Gets the number of pages in the document.
   virtual int GetNumberOfPages() const = 0;
   // Gets the named destination by name.
-  virtual absl::optional<PDFEngine::NamedDestination> GetNamedDestination(
+  virtual std::optional<PDFEngine::NamedDestination> GetNamedDestination(
       const std::string& destination) = 0;
   // Gets the index of the most visible page, or -1 if none are visible.
   virtual int GetMostVisiblePage() = 0;
@@ -390,9 +390,9 @@
   virtual uint32_t GetCharUnicode(int page_index, int char_index) = 0;
   // Given a start char index, find the longest continuous run of text that's
   // in a single direction and with the same text style. Return a filled out
-  // AccessibilityTextRunInfo on success or absl::nullopt on failure. e.g. When
+  // AccessibilityTextRunInfo on success or std::nullopt on failure. e.g. When
   // `start_char_index` is out of bounds.
-  virtual absl::optional<AccessibilityTextRunInfo> GetTextRunInfo(
+  virtual std::optional<AccessibilityTextRunInfo> GetTextRunInfo(
       int page_index,
       int start_char_index) = 0;
   // For all the links on page `page_index`, get their urls, underlying text
@@ -429,8 +429,8 @@
   // Returns the duplex setting.
   virtual printing::mojom::DuplexMode GetDuplexMode() = 0;
   // Returns the uniform page size of the document in points. Returns
-  // `absl::nullopt` if the document has more than one page size.
-  virtual absl::optional<gfx::Size> GetUniformPageSizePoints() = 0;
+  // `std::nullopt` if the document has more than one page size.
+  virtual std::optional<gfx::Size> GetUniformPageSizePoints() = 0;
 
   // Returns a list of Values of Bookmarks. Each Bookmark is a dictionary Value
   // which contains the following key/values:
@@ -551,7 +551,7 @@
   // Whether the PDF is Tagged (see 10.7 "Tagged PDF" in PDF Reference 1.7).
   // Returns true if it's a tagged (accessible) PDF, false if it's a valid
   // PDF but untagged, and nullopt if the PDF can't be parsed.
-  virtual absl::optional<bool> IsPDFDocTagged(
+  virtual std::optional<bool> IsPDFDocTagged(
       base::span<const uint8_t> pdf_buffer) = 0;
 
   // Given a tagged PDF (see IsPDFDocTagged, above), return the portion of
@@ -561,7 +561,7 @@
       int page_index) = 0;
 
   // See the definition of GetPDFPageSizeByIndex in pdf.cc for details.
-  virtual absl::optional<gfx::SizeF> GetPDFPageSizeByIndex(
+  virtual std::optional<gfx::SizeF> GetPDFPageSizeByIndex(
       base::span<const uint8_t> pdf_buffer,
       int page_index) = 0;
 };
diff --git a/pdf/pdf_utils/dates.cc b/pdf/pdf_utils/dates.cc
index 0b16fda..ed1cd04 100644
--- a/pdf/pdf_utils/dates.cc
+++ b/pdf/pdf_utils/dates.cc
@@ -6,11 +6,11 @@
 
 #include <stdint.h>
 
+#include <optional>
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chrome_pdf {
 
@@ -27,9 +27,9 @@
   // Pops the first `num_digits` characters from the string and converts them to
   // an int if possible. Popping too many characters or characters that cannot
   // be converted puts the deserializer in a stopped state.
-  absl::optional<int> PopDigits(size_t num_digits) {
+  std::optional<int> PopDigits(size_t num_digits) {
     if (stopped_)
-      return absl::nullopt;
+      return std::nullopt;
 
     // `base::StringToUint()` allows leading sign characters, so also verify
     // that the front character is a digit.
@@ -38,7 +38,7 @@
         !base::IsAsciiDigit(deserializing_.front()) ||
         !base::StringToUint(deserializing_.substr(0, num_digits), &value)) {
       stopped_ = true;
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     // Pop front characters.
@@ -47,14 +47,14 @@
   }
 
   // Pops the front character if it is not a digit. Otherwise, does not change
-  // the state of the deserializer and returns `absl::nullopt`.
-  absl::optional<char> TryPopNonDigit() {
+  // the state of the deserializer and returns `std::nullopt`.
+  std::optional<char> TryPopNonDigit() {
     if (stopped_ || deserializing_.empty())
-      return absl::nullopt;
+      return std::nullopt;
 
     const char front = deserializing_.front();
     if (base::IsAsciiDigit(front))
-      return absl::nullopt;
+      return std::nullopt;
 
     deserializing_ = deserializing_.substr(1);
     return front;
@@ -76,7 +76,7 @@
   base::TimeDelta offset;
 
   // UTC is assumed if no time zone information is provided.
-  const absl::optional<char> sign = deserializer.TryPopNonDigit();
+  const std::optional<char> sign = deserializer.TryPopNonDigit();
   if (!sign.has_value() || (sign.value() != '+' && sign.value() != '-'))
     return offset;
 
@@ -84,7 +84,7 @@
 
   // The spec requires that the hours offset be followed by an apostrophe, but
   // don't be strict about its presence.
-  const absl::optional<char> apostrophe = deserializer.TryPopNonDigit();
+  const std::optional<char> apostrophe = deserializer.TryPopNonDigit();
   if (apostrophe.has_value() && apostrophe.value() != '\'')
     return sign.value() == '+' ? offset : -offset;
 
@@ -108,7 +108,7 @@
   DateDeserializer deserializer(date);
 
   // Year is the only required part of a valid date.
-  const absl::optional<int> deserialized_year = deserializer.PopDigits(4);
+  const std::optional<int> deserialized_year = deserializer.PopDigits(4);
   if (!deserialized_year.has_value())
     return base::Time();
 
diff --git a/pdf/pdf_view_web_plugin.cc b/pdf/pdf_view_web_plugin.cc
index 55693fe..6055005 100644
--- a/pdf/pdf_view_web_plugin.cc
+++ b/pdf/pdf_view_web_plugin.cc
@@ -314,7 +314,7 @@
   // Allow the plugin to handle find requests.
   client_->UsePluginAsFindHandler();
 
-  absl::optional<ParsedParams> params = ParseWebPluginParams(initial_params_);
+  std::optional<ParsedParams> params = ParseWebPluginParams(initial_params_);
 
   // The contents of `initial_params_` are no longer needed.
   initial_params_ = {};
@@ -1342,7 +1342,7 @@
 
 void PdfViewWebPlugin::HandleGetNamedDestinationMessage(
     const base::Value::Dict& message) {
-  absl::optional<PDFEngine::NamedDestination> named_destination =
+  std::optional<PDFEngine::NamedDestination> named_destination =
       engine_->GetNamedDestination(*message.FindString("namedDestination"));
 
   const int page_number = named_destination.has_value()
diff --git a/pdf/pdf_view_web_plugin.h b/pdf/pdf_view_web_plugin.h
index e4a1818..11b8734 100644
--- a/pdf/pdf_view_web_plugin.h
+++ b/pdf/pdf_view_web_plugin.h
@@ -801,7 +801,7 @@
   std::vector<int> pages_to_print_;
 
   // Assigned a value only between `PrintBegin()` and `PrintEnd()` calls.
-  absl::optional<blink::WebPrintParams> print_params_;
+  std::optional<blink::WebPrintParams> print_params_;
 
   // For identifying actual print operations to avoid double logging of UMA.
   bool print_pages_called_;
diff --git a/pdf/pdf_view_web_plugin_unittest.cc b/pdf/pdf_view_web_plugin_unittest.cc
index 88739fc5..be70915 100644
--- a/pdf/pdf_view_web_plugin_unittest.cc
+++ b/pdf/pdf_view_web_plugin_unittest.cc
@@ -1771,7 +1771,7 @@
       return bookmarks;
     }
 
-    absl::optional<gfx::Size> GetUniformPageSizePoints() override {
+    std::optional<gfx::Size> GetUniformPageSizePoints() override {
       return gfx::Size(1000, 1200);
     }
 
diff --git a/pdf/pdfium/findtext_unittest.cc b/pdf/pdfium/findtext_unittest.cc
index 853d673..80b42ed 100644
--- a/pdf/pdfium/findtext_unittest.cc
+++ b/pdf/pdfium/findtext_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <optional>
 #include "base/check_op.h"
 #include "base/strings/utf_string_conversions.h"
 #include "pdf/document_layout.h"
@@ -9,7 +10,6 @@
 #include "pdf/pdfium/pdfium_test_base.h"
 #include "pdf/test/test_client.h"
 #include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 using testing::_;
 using testing::InSequence;
diff --git a/pdf/pdfium/pdfium_api_string_buffer_adapter.h b/pdf/pdfium/pdfium_api_string_buffer_adapter.h
index 34951266..90c1e26 100644
--- a/pdf/pdfium/pdfium_api_string_buffer_adapter.h
+++ b/pdf/pdfium/pdfium_api_string_buffer_adapter.h
@@ -9,10 +9,10 @@
 
 #include <string>
 
+#include <optional>
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "base/numerics/safe_math.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chrome_pdf {
 
@@ -104,12 +104,12 @@
           class StringType,
           typename BufferType,
           typename ReturnType>
-absl::optional<StringType> CallPDFiumStringBufferApiAndReturnOptional(
+std::optional<StringType> CallPDFiumStringBufferApiAndReturnOptional(
     base::RepeatingCallback<ReturnType(BufferType*, ReturnType)> api,
     bool check_expected_size) {
   ReturnType expected_size = api.Run(nullptr, 0);
   if (expected_size == 0)
-    return absl::nullopt;
+    return std::nullopt;
 
   StringType str;
   AdapterType api_string_adapter(&str, expected_size, check_expected_size);
@@ -125,7 +125,7 @@
 StringType CallPDFiumStringBufferApi(
     base::RepeatingCallback<ReturnType(BufferType*, ReturnType)> api,
     bool check_expected_size) {
-  absl::optional<StringType> result =
+  std::optional<StringType> result =
       CallPDFiumStringBufferApiAndReturnOptional<AdapterType, StringType>(
           api, check_expected_size);
   return result.value_or(StringType());
@@ -147,7 +147,7 @@
 // Variant of CallPDFiumWideStringBufferApi() that distinguishes between API
 // call failures and empty string return values.
 template <typename BufferType>
-absl::optional<std::u16string> CallPDFiumWideStringBufferApiAndReturnOptional(
+std::optional<std::u16string> CallPDFiumWideStringBufferApiAndReturnOptional(
     base::RepeatingCallback<unsigned long(BufferType*, unsigned long)> api,
     bool check_expected_size) {
   using adapter_type = internal::PDFiumAPIStringBufferSizeInBytesAdapter;
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 6eaee272..3d46297 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -2407,9 +2407,9 @@
     if (PageIndexInBounds(page_index)) {
       dict.Set("page", page_index);
 
-      absl::optional<float> x;
-      absl::optional<float> y;
-      absl::optional<float> zoom;
+      std::optional<float> x;
+      std::optional<float> y;
+      std::optional<float> zoom;
       pages_[page_index]->GetPageDestinationTarget(dest, &x, &y, &zoom);
 
       if (x)
@@ -2512,7 +2512,7 @@
   client_->ScrollBy(scroll_offset - global_point);
 }
 
-absl::optional<PDFEngine::NamedDestination> PDFiumEngine::GetNamedDestination(
+std::optional<PDFEngine::NamedDestination> PDFiumEngine::GetNamedDestination(
     const std::string& destination) {
   // Look for the destination.
   FPDF_DEST dest = FPDF_GetNamedDestByName(doc(), destination.c_str());
@@ -2607,7 +2607,7 @@
   return pages_[page_index]->GetCharUnicode(char_index);
 }
 
-absl::optional<AccessibilityTextRunInfo> PDFiumEngine::GetTextRunInfo(
+std::optional<AccessibilityTextRunInfo> PDFiumEngine::GetTextRunInfo(
     int page_index,
     int start_char_index) {
   DCHECK(PageIndexInBounds(page_index));
@@ -2668,14 +2668,14 @@
   }
 }
 
-absl::optional<gfx::Size> PDFiumEngine::GetUniformPageSizePoints() {
+std::optional<gfx::Size> PDFiumEngine::GetUniformPageSizePoints() {
   if (pages_.empty())
-    return absl::nullopt;
+    return std::nullopt;
 
   gfx::Size page_size = GetPageSize(0);
   for (size_t i = 1; i < pages_.size(); ++i) {
     if (page_size != GetPageSize(i))
-      return absl::nullopt;
+      return std::nullopt;
   }
 
   // Convert `page_size` back to points.
@@ -3140,19 +3140,19 @@
       static_cast<int>(ceil(inset_sizes.right * multiplier))));
 }
 
-absl::optional<size_t> PDFiumEngine::GetAdjacentPageIndexForTwoUpView(
+std::optional<size_t> PDFiumEngine::GetAdjacentPageIndexForTwoUpView(
     size_t page_index,
     size_t num_of_pages) const {
   DCHECK_LT(page_index, num_of_pages);
 
   if (layout_.options().page_spread() == DocumentLayout::PageSpread::kOneUp) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   int adjacent_page_offset = page_index % 2 ? -1 : 1;
   size_t adjacent_page_index = page_index + adjacent_page_offset;
   if (adjacent_page_index >= num_of_pages)
-    return absl::nullopt;
+    return std::nullopt;
 
   return adjacent_page_index;
 }
@@ -3337,7 +3337,7 @@
   int page_index = progressive_paints_[progressive_index].page_index();
   gfx::Rect dirty_in_screen = progressive_paints_[progressive_index].rect();
 
-  const absl::optional<RegionData> region =
+  const std::optional<RegionData> region =
       GetRegion(dirty_in_screen.origin(), image_data);
   if (!region.has_value()) {
     return;
@@ -3404,8 +3404,7 @@
 ScopedFPDFBitmap PDFiumEngine::CreateBitmap(const gfx::Rect& rect,
                                             bool has_alpha,
                                             SkBitmap& image_data) const {
-  const absl::optional<RegionData> region =
-      GetRegion(rect.origin(), image_data);
+  const std::optional<RegionData> region = GetRegion(rect.origin(), image_data);
   if (!region.has_value()) {
     return nullptr;
   }
@@ -3462,7 +3461,7 @@
       GetInsetSizes(layout_.options(), page_index, pages_.size());
 
   int max_page_height = page_rect.height();
-  absl::optional<size_t> adjacent_page_index =
+  std::optional<size_t> adjacent_page_index =
       GetAdjacentPageIndexForTwoUpView(page_index, pages_.size());
   if (adjacent_page_index.has_value()) {
     max_page_height = std::max(
@@ -3723,24 +3722,24 @@
   DrawShadow(image_data, shadow_rect, page_rect, clip_rect, *page_shadow_);
 }
 
-absl::optional<PDFiumEngine::RegionData> PDFiumEngine::GetRegion(
+std::optional<PDFiumEngine::RegionData> PDFiumEngine::GetRegion(
     const gfx::Point& location,
     SkBitmap& image_data) const {
   if (image_data.isNull()) {
     DCHECK(plugin_size().IsEmpty());
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   uint8_t* buffer = static_cast<uint8_t*>(image_data.getPixels());
   if (!buffer) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   gfx::Point offset_location = location + page_offset_;
   // TODO: update this when we support BIDI and scrollbars can be on the left.
   if (!gfx::Rect(gfx::PointAtOffsetFromOrigin(page_offset_), plugin_size())
            .Contains(offset_location)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   size_t stride = image_data.rowBytes();
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h
index 663d5c4f..b1740cd 100644
--- a/pdf/pdfium/pdfium_engine.h
+++ b/pdf/pdfium/pdfium_engine.h
@@ -13,6 +13,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/check.h"
 #include "base/containers/flat_map.h"
 #include "base/containers/span.h"
@@ -31,7 +32,6 @@
 #include "pdf/pdfium/pdfium_page.h"
 #include "pdf/pdfium/pdfium_print.h"
 #include "pdf/pdfium/pdfium_range.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/pdfium/public/cpp/fpdf_scopers.h"
 #include "third_party/pdfium/public/fpdf_formfill.h"
 #include "third_party/pdfium/public/fpdf_progressive.h"
@@ -140,7 +140,7 @@
   const DocumentMetadata& GetDocumentMetadata() const override;
   int GetNumberOfPages() const override;
   base::Value::List GetBookmarks() override;
-  absl::optional<PDFEngine::NamedDestination> GetNamedDestination(
+  std::optional<PDFEngine::NamedDestination> GetNamedDestination(
       const std::string& destination) override;
   int GetMostVisiblePage() override;
   gfx::Rect GetPageBoundsRect(int index) override;
@@ -151,7 +151,7 @@
   int GetCharCount(int page_index) override;
   gfx::RectF GetCharBounds(int page_index, int char_index) override;
   uint32_t GetCharUnicode(int page_index, int char_index) override;
-  absl::optional<AccessibilityTextRunInfo> GetTextRunInfo(
+  std::optional<AccessibilityTextRunInfo> GetTextRunInfo(
       int page_index,
       int start_char_index) override;
   std::vector<AccessibilityLinkInfo> GetLinkInfo(
@@ -170,7 +170,7 @@
   bool GetPrintScaling() override;
   int GetCopiesToPrint() override;
   printing::mojom::DuplexMode GetDuplexMode() override;
-  absl::optional<gfx::Size> GetUniformPageSizePoints() override;
+  std::optional<gfx::Size> GetUniformPageSizePoints() override;
   void AppendBlankPages(size_t num_pages) override;
   void AppendPage(PDFEngine* engine, int index) override;
   std::vector<uint8_t> GetSaveData() override;
@@ -393,9 +393,9 @@
                  gfx::Rect& rect) const;
 
   // If two-up view is enabled, returns the index of the page beside
-  // `page_index` page. Returns absl::nullopt if there is no adjacent page or
+  // `page_index` page. Returns std::nullopt if there is no adjacent page or
   // if two-up view is disabled.
-  absl::optional<size_t> GetAdjacentPageIndexForTwoUpView(
+  std::optional<size_t> GetAdjacentPageIndexForTwoUpView(
       size_t page_index,
       size_t num_of_pages) const;
 
@@ -558,8 +558,8 @@
                       const gfx::Rect& clip_rect,
                       SkBitmap& image_data);
 
-  absl::optional<RegionData> GetRegion(const gfx::Point& location,
-                                       SkBitmap& image_data) const;
+  std::optional<RegionData> GetRegion(const gfx::Point& location,
+                                      SkBitmap& image_data) const;
 
   // Called when the selection changes.
   void OnSelectionTextChanged();
@@ -680,7 +680,7 @@
   // The offset of the page into the viewport.
   gfx::Vector2d page_offset_;
   // The plugin size in screen coordinates.
-  absl::optional<gfx::Size> plugin_size_;
+  std::optional<gfx::Size> plugin_size_;
   double current_zoom_ = 1.0;
   // The caret position and bound in plugin viewport coordinates.
   gfx::Rect caret_rect_;
@@ -754,9 +754,9 @@
   int last_page_to_search_ = -1;
   int last_character_index_to_search_ = -1;  // -1 if search until end of page.
   // Which result the user has currently selected. (0-based)
-  absl::optional<size_t> current_find_index_;
+  std::optional<size_t> current_find_index_;
   // Where to resume searching. (0-based)
-  absl::optional<size_t> resume_find_index_;
+  std::optional<size_t> resume_find_index_;
 
   std::unique_ptr<PDFiumPermissions> permissions_;
 
@@ -797,7 +797,7 @@
 
   // Holds the page index requested by PDFium while the scroll operation
   // is being handled (asynchronously).
-  absl::optional<int> in_flight_visible_page_;
+  std::optional<int> in_flight_visible_page_;
 
   // Set to true after FORM_DoDocumentJSAction/FORM_DoDocumentOpenAction have
   // been called. Only after that can we call FORM_DoPageAAction.
diff --git a/pdf/pdfium/pdfium_engine_exports.cc b/pdf/pdfium/pdfium_engine_exports.cc
index 973241bc..94a3aa69 100644
--- a/pdf/pdfium/pdfium_engine_exports.cc
+++ b/pdf/pdfium/pdfium_engine_exports.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <utility>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/no_destructor.h"
 #include "build/build_config.h"
@@ -16,7 +17,6 @@
 #include "pdf/pdfium/pdfium_unsupported_features.h"
 #include "printing/nup_parameters.h"
 #include "printing/units.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/pdfium/public/cpp/fpdf_scopers.h"
 #include "third_party/pdfium/public/fpdf_catalog.h"
 #include "third_party/pdfium/public/fpdf_ppo.h"
@@ -151,7 +151,7 @@
   if (children_count <= 0)
     return base::Value();
 
-  absl::optional<std::u16string> opt_type =
+  std::optional<std::u16string> opt_type =
       CallPDFiumWideStringBufferApiAndReturnOptional(
           base::BindRepeating(FPDF_StructElement_GetType, struct_elem), true);
   if (!opt_type)
@@ -160,14 +160,14 @@
   base::Value::Dict result;
   result.Set("type", *opt_type);
 
-  absl::optional<std::u16string> opt_alt =
+  std::optional<std::u16string> opt_alt =
       CallPDFiumWideStringBufferApiAndReturnOptional(
           base::BindRepeating(FPDF_StructElement_GetAltText, struct_elem),
           true);
   if (opt_alt)
     result.Set("alt", *opt_alt);
 
-  absl::optional<std::u16string> opt_lang =
+  std::optional<std::u16string> opt_lang =
       CallPDFiumWideStringBufferApiAndReturnOptional(
           base::BindRepeating(FPDF_StructElement_GetLang, struct_elem), true);
   if (opt_lang)
@@ -411,13 +411,13 @@
   return true;
 }
 
-absl::optional<bool> PDFiumEngineExports::IsPDFDocTagged(
+std::optional<bool> PDFiumEngineExports::IsPDFDocTagged(
     base::span<const uint8_t> pdf_buffer) {
   ScopedUnsupportedFeature scoped_unsupported_feature(
       ScopedUnsupportedFeature::kNoEngine);
   ScopedFPDFDocument doc = LoadPdfData(pdf_buffer);
   if (!doc)
-    return absl::nullopt;
+    return std::nullopt;
 
   return FPDFCatalog_IsTagged(doc.get());
 }
@@ -452,18 +452,18 @@
   return RecursiveGetStructTree(struct_root_elem);
 }
 
-absl::optional<gfx::SizeF> PDFiumEngineExports::GetPDFPageSizeByIndex(
+std::optional<gfx::SizeF> PDFiumEngineExports::GetPDFPageSizeByIndex(
     base::span<const uint8_t> pdf_buffer,
     int page_index) {
   ScopedUnsupportedFeature scoped_unsupported_feature(
       ScopedUnsupportedFeature::kNoEngine);
   ScopedFPDFDocument doc = LoadPdfData(pdf_buffer);
   if (!doc)
-    return absl::nullopt;
+    return std::nullopt;
 
   FS_SIZEF size;
   if (!FPDF_GetPageSizeByIndexF(doc.get(), page_index, &size))
-    return absl::nullopt;
+    return std::nullopt;
 
   return gfx::SizeF(size.width, size.height);
 }
diff --git a/pdf/pdfium/pdfium_engine_exports.h b/pdf/pdfium/pdfium_engine_exports.h
index c6cc7f6..c7e72548 100644
--- a/pdf/pdfium/pdfium_engine_exports.h
+++ b/pdf/pdfium/pdfium_engine_exports.h
@@ -49,11 +49,11 @@
   bool GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
                      int* page_count,
                      float* max_page_width) override;
-  absl::optional<bool> IsPDFDocTagged(
+  std::optional<bool> IsPDFDocTagged(
       base::span<const uint8_t> pdf_buffer) override;
   base::Value GetPDFStructTreeForPage(base::span<const uint8_t> pdf_buffer,
                                       int page_index) override;
-  absl::optional<gfx::SizeF> GetPDFPageSizeByIndex(
+  std::optional<gfx::SizeF> GetPDFPageSizeByIndex(
       base::span<const uint8_t> pdf_buffer,
       int page_index) override;
 };
diff --git a/pdf/pdfium/pdfium_engine_exports_unittest.cc b/pdf/pdfium/pdfium_engine_exports_unittest.cc
index 09fd4866..926e9be0 100644
--- a/pdf/pdfium/pdfium_engine_exports_unittest.cc
+++ b/pdf/pdfium/pdfium_engine_exports_unittest.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <optional>
 #include "base/files/file_util.h"
 #include "base/path_service.h"
 #include "pdf/pdf.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/geometry/size_f.h"
@@ -67,7 +67,7 @@
   ASSERT_TRUE(GetPDFDocInfo(pdf_span, &page_count, nullptr));
   ASSERT_EQ(2, page_count);
   for (int page_index = 0; page_index < page_count; ++page_index) {
-    absl::optional<gfx::SizeF> page_size =
+    std::optional<gfx::SizeF> page_size =
         GetPDFPageSizeByIndex(pdf_span, page_index);
     ASSERT_TRUE(page_size.has_value());
     EXPECT_EQ(gfx::SizeF(200, 200), page_size.value());
@@ -109,7 +109,7 @@
   ASSERT_TRUE(GetPDFDocInfo(output_pdf_span, &page_count, nullptr));
   ASSERT_EQ(1, page_count);
 
-  absl::optional<gfx::SizeF> page_size =
+  std::optional<gfx::SizeF> page_size =
       GetPDFPageSizeByIndex(output_pdf_span, 0);
   ASSERT_TRUE(page_size.has_value());
   EXPECT_EQ(gfx::SizeF(792, 612), page_size.value());
@@ -137,7 +137,7 @@
   ASSERT_TRUE(GetPDFDocInfo(output_pdf_span, &page_count, nullptr));
   ASSERT_EQ(2, page_count);
   for (int page_index = 0; page_index < page_count; ++page_index) {
-    absl::optional<gfx::SizeF> page_size =
+    std::optional<gfx::SizeF> page_size =
         GetPDFPageSizeByIndex(output_pdf_span, page_index);
     ASSERT_TRUE(page_size.has_value());
     EXPECT_EQ(gfx::SizeF(612, 792), page_size.value());
diff --git a/pdf/pdfium/pdfium_engine_unittest.cc b/pdf/pdfium/pdfium_engine_unittest.cc
index c6bfc67c..972d23d1 100644
--- a/pdf/pdfium/pdfium_engine_unittest.cc
+++ b/pdf/pdfium/pdfium_engine_unittest.cc
@@ -523,7 +523,7 @@
   ASSERT_EQ(2, engine->GetNumberOfPages());
 
   // A destination with a valid page object
-  absl::optional<PDFEngine::NamedDestination> valid_page_obj =
+  std::optional<PDFEngine::NamedDestination> valid_page_obj =
       engine->GetNamedDestination("ValidPageObj");
   ASSERT_TRUE(valid_page_obj.has_value());
   EXPECT_EQ(0u, valid_page_obj->page);
@@ -532,18 +532,18 @@
   EXPECT_EQ(1.2f, valid_page_obj->params[2]);
 
   // A destination with an invalid page object
-  absl::optional<PDFEngine::NamedDestination> invalid_page_obj =
+  std::optional<PDFEngine::NamedDestination> invalid_page_obj =
       engine->GetNamedDestination("InvalidPageObj");
   ASSERT_FALSE(invalid_page_obj.has_value());
 
   // A destination with a valid page number
-  absl::optional<PDFEngine::NamedDestination> valid_page_number =
+  std::optional<PDFEngine::NamedDestination> valid_page_number =
       engine->GetNamedDestination("ValidPageNumber");
   ASSERT_TRUE(valid_page_number.has_value());
   EXPECT_EQ(1u, valid_page_number->page);
 
   // A destination with an out-of-range page number
-  absl::optional<PDFEngine::NamedDestination> invalid_page_number =
+  std::optional<PDFEngine::NamedDestination> invalid_page_number =
       engine->GetNamedDestination("OutOfRangePageNumber");
   EXPECT_FALSE(invalid_page_number.has_value());
 }
diff --git a/pdf/pdfium/pdfium_page.cc b/pdf/pdfium/pdfium_page.cc
index 18e0c52..5b840a7 100644
--- a/pdf/pdfium/pdfium_page.cc
+++ b/pdf/pdfium/pdfium_page.cc
@@ -459,14 +459,14 @@
   }
 }
 
-absl::optional<AccessibilityTextRunInfo> PDFiumPage::GetTextRunInfo(
+std::optional<AccessibilityTextRunInfo> PDFiumPage::GetTextRunInfo(
     int start_char_index) {
   FPDF_PAGE page = GetPage();
   FPDF_TEXTPAGE text_page = GetTextPage();
   int chars_count = FPDFText_CountChars(text_page);
   // Check to make sure `start_char_index` is within bounds.
   if (start_char_index < 0 || start_char_index >= chars_count)
-    return absl::nullopt;
+    return std::nullopt;
 
   int actual_start_char_index = GetFirstNonUnicodeWhiteSpaceCharIndex(
       text_page, start_char_index, chars_count);
@@ -1053,8 +1053,8 @@
 
   target->page = page_index;
 
-  absl::optional<float> x;
-  absl::optional<float> y;
+  std::optional<float> x;
+  std::optional<float> y;
   GetPageDestinationTarget(destination, &x, &y, &target->zoom);
 
   // The page where a destination exists can be different from the page that it
@@ -1077,12 +1077,12 @@
 }
 
 void PDFiumPage::GetPageDestinationTarget(FPDF_DEST destination,
-                                          absl::optional<float>* dest_x,
-                                          absl::optional<float>* dest_y,
-                                          absl::optional<float>* zoom_value) {
-  *dest_x = absl::nullopt;
-  *dest_y = absl::nullopt;
-  *zoom_value = absl::nullopt;
+                                          std::optional<float>* dest_x,
+                                          std::optional<float>* dest_y,
+                                          std::optional<float>* zoom_value) {
+  *dest_x = std::nullopt;
+  *dest_y = std::nullopt;
+  *zoom_value = std::nullopt;
   if (!available_)
     return;
 
diff --git a/pdf/pdfium/pdfium_page.h b/pdf/pdfium/pdfium_page.h
index 67fe82f..31c2ffef 100644
--- a/pdf/pdfium/pdfium_page.h
+++ b/pdf/pdfium/pdfium_page.h
@@ -10,13 +10,13 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/functional/callback.h"
 #include "base/functional/callback_forward.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/raw_ptr.h"
 #include "pdf/page_orientation.h"
 #include "pdf/pdf_engine.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/pdfium/public/cpp/fpdf_scopers.h"
 #include "third_party/pdfium/public/fpdf_doc.h"
 #include "third_party/pdfium/public/fpdf_formfill.h"
@@ -69,7 +69,7 @@
   FPDF_TEXTPAGE GetTextPage();
 
   // See definition of PDFEngine::GetTextRunInfo().
-  absl::optional<AccessibilityTextRunInfo> GetTextRunInfo(int start_char_index);
+  std::optional<AccessibilityTextRunInfo> GetTextRunInfo(int start_char_index);
 
   // Get a unicode character from the page.
   uint32_t GetCharUnicode(int char_index);
@@ -135,10 +135,10 @@
     // Valid for DOCLINK_AREA only.
     int page;
     // Valid for DOCLINK_AREA only. From the top-left of the page.
-    absl::optional<float> x_in_pixels;
-    absl::optional<float> y_in_pixels;
+    std::optional<float> x_in_pixels;
+    std::optional<float> y_in_pixels;
     // Valid for DOCLINK_AREA only.
-    absl::optional<float> zoom;
+    std::optional<float> zoom;
   };
 
   // Given a `link_index`, returns the type of underlying area and the link
@@ -153,9 +153,9 @@
   // Fills the output params with the in-page coordinates and the zoom value of
   // the destination.
   void GetPageDestinationTarget(FPDF_DEST destination,
-                                absl::optional<float>* dest_x,
-                                absl::optional<float>* dest_y,
-                                absl::optional<float>* zoom_value);
+                                std::optional<float>* dest_x,
+                                std::optional<float>* dest_y,
+                                std::optional<float>* zoom_value);
 
   // For a named destination with "XYZ" view fit type, pre-processes the in-page
   // x/y coordinate in case it's out of the range of the page dimension. Then
diff --git a/pdf/pdfium/pdfium_page_unittest.cc b/pdf/pdfium/pdfium_page_unittest.cc
index 7ecf983..bb2c7e6 100644
--- a/pdf/pdfium/pdfium_page_unittest.cc
+++ b/pdf/pdfium/pdfium_page_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/check.h"
 #include "base/files/file_path.h"
 #include "base/strings/string_util.h"
@@ -21,7 +22,6 @@
 #include "pdf/test/test_helpers.h"
 #include "pdf/ui/thumbnail.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/pdfium/public/fpdf_formfill.h"
 #include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkImageInfo.h"
@@ -631,7 +631,7 @@
   constexpr int kFirstRunStartIndex = 0;
   constexpr int kFirstRunEndIndex = 20;
   constexpr int kPageIndex = 0;
-  absl::optional<AccessibilityTextRunInfo> text_run_info_1 =
+  std::optional<AccessibilityTextRunInfo> text_run_info_1 =
       engine->GetTextRunInfo(kPageIndex, kFirstRunStartIndex);
   ASSERT_TRUE(text_run_info_1.has_value());
 
@@ -667,7 +667,7 @@
   // Test the properties of second text run.
   // Note: The leading spaces in second text run are accounted for in the end
   // of first text run. Hence we won't see a space leading the second text run.
-  absl::optional<AccessibilityTextRunInfo> text_run_info_2 =
+  std::optional<AccessibilityTextRunInfo> text_run_info_2 =
       engine->GetTextRunInfo(kPageIndex, kSecondRunStartIndex);
   ASSERT_TRUE(text_run_info_2.has_value());
 
@@ -748,7 +748,7 @@
   }
 
   // Test negative char index returns nullopt
-  absl::optional<AccessibilityTextRunInfo> text_run_info_result =
+  std::optional<AccessibilityTextRunInfo> text_run_info_result =
       engine->GetTextRunInfo(0, -1);
   ASSERT_FALSE(text_run_info_result.has_value());
 
@@ -802,7 +802,7 @@
 
   int current_char_index = 0;
   for (const auto& expected_text_run : expected_text_runs) {
-    absl::optional<AccessibilityTextRunInfo> text_run_info_result =
+    std::optional<AccessibilityTextRunInfo> text_run_info_result =
         engine->GetTextRunInfo(0, current_char_index);
     ASSERT_TRUE(text_run_info_result.has_value());
     const auto& actual_text_run = text_run_info_result.value();
diff --git a/pdf/pdfium/pdfium_print_unittest.cc b/pdf/pdfium/pdfium_print_unittest.cc
index 802d593..85c18ab 100644
--- a/pdf/pdfium/pdfium_print_unittest.cc
+++ b/pdf/pdfium/pdfium_print_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
@@ -17,7 +18,6 @@
 #include "printing/pdf_render_settings.h"
 #include "printing/units.h"
 #include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/web/web_print_params.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkImage.h"
@@ -69,7 +69,7 @@
   ASSERT_EQ(expected_dimensions.size(), static_cast<size_t>(page_count));
 
   for (int i = 0; i < page_count; ++i) {
-    absl::optional<gfx::SizeF> page_size =
+    std::optional<gfx::SizeF> page_size =
         exports.GetPDFPageSizeByIndex(pdf_data, i);
     ASSERT_TRUE(page_size.has_value());
     EXPECT_EQ(expected_dimensions[i], page_size.value());
diff --git a/pdf/ui/document_properties.cc b/pdf/ui/document_properties.cc
index 23ad0d0..8239d472 100644
--- a/pdf/ui/document_properties.cc
+++ b/pdf/ui/document_properties.cc
@@ -6,13 +6,13 @@
 
 #include <string>
 
+#include <optional>
 #include "base/i18n/number_formatting.h"
 #include "base/i18n/rtl.h"
 #include "base/strings/string_number_conversions.h"
 #include "components/strings/grit/components_strings.h"
 #include "pdf/document_metadata.h"
 #include "printing/units.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/icu/source/i18n/unicode/ulocdata.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/geometry/size.h"
@@ -75,7 +75,7 @@
 
 }  // namespace
 
-std::u16string FormatPageSize(const absl::optional<gfx::Size>& size_points) {
+std::u16string FormatPageSize(const std::optional<gfx::Size>& size_points) {
   if (!size_points.has_value())
     return l10n_util::GetStringUTF16(IDS_PDF_PROPERTIES_PAGE_SIZE_VARIABLE);
 
diff --git a/pdf/ui/document_properties.h b/pdf/ui/document_properties.h
index b9868ea..9214b4a 100644
--- a/pdf/ui/document_properties.h
+++ b/pdf/ui/document_properties.h
@@ -7,8 +7,8 @@
 
 #include <string>
 
+#include <optional>
 #include "pdf/document_metadata.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace gfx {
 class Size;
@@ -23,8 +23,8 @@
 // ->  210 x 297 mm (portrait)
 // ->  11.00 x 8.50 in (landscape)
 //
-// Returns the string "Varies" if `size_points` is `absl::nullopt`.
-std::u16string FormatPageSize(const absl::optional<gfx::Size>& size_points);
+// Returns the string "Varies" if `size_points` is `std::nullopt`.
+std::u16string FormatPageSize(const std::optional<gfx::Size>& size_points);
 
 // Formats `version` to a string suitable for display to a user. Version numbers
 // do not require localization.
diff --git a/pdf/ui/document_properties_unittest.cc b/pdf/ui/document_properties_unittest.cc
index 3b020a8..a26d56a3a 100644
--- a/pdf/ui/document_properties_unittest.cc
+++ b/pdf/ui/document_properties_unittest.cc
@@ -6,12 +6,12 @@
 
 #include <string>
 
+#include <optional>
 #include "base/i18n/number_formatting.h"
 #include "base/i18n/rtl.h"
 #include "pdf/document_metadata.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace chrome_pdf {
@@ -44,7 +44,7 @@
 }  // namespace
 
 TEST_F(FormatPageSizeTest, NoUniformSize) {
-  EXPECT_EQ(FormatPageSize(absl::nullopt), u"Varies");
+  EXPECT_EQ(FormatPageSize(std::nullopt), u"Varies");
 }
 
 class FormatPageSizeMillimetersTest : public FormatPageSizeTest {
diff --git a/printing/backend/cups_helper.cc b/printing/backend/cups_helper.cc
index 7d908c8..b9a407ae 100644
--- a/printing/backend/cups_helper.cc
+++ b/printing/backend/cups_helper.cc
@@ -13,6 +13,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
@@ -27,7 +28,6 @@
 #include "printing/print_job_constants_cups.h"
 #include "printing/printing_utils.h"
 #include "printing/units.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
@@ -115,11 +115,11 @@
   return std::make_pair(std::move(duplex_modes), duplex_default);
 }
 
-absl::optional<gfx::Size> ParseResolutionString(const char* input) {
+std::optional<gfx::Size> ParseResolutionString(const char* input) {
   int len = strlen(input);
   if (len == 0) {
     VLOG(1) << "Bad PPD resolution choice: null string";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   int n = 0;  // number of chars successfully parsed by sscanf()
@@ -132,12 +132,12 @@
     sscanf(input, "%dx%ddpi%n", &dpi_x, &dpi_y, &n);
     if (n != len) {
       VLOG(1) << "Bad PPD resolution choice: " << input;
-      return absl::nullopt;
+      return std::nullopt;
     }
   }
   if (dpi_x <= 0 || dpi_y <= 0) {
     VLOG(1) << "Invalid PPD resolution dimensions: " << dpi_x << " " << dpi_y;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return gfx::Size(dpi_x, dpi_y);
@@ -170,7 +170,7 @@
     for (int i = 0; i < res->num_choices; i++) {
       char* choice = res->choices[i].choice;
       CHECK(choice);
-      absl::optional<gfx::Size> parsed_size = ParseResolutionString(choice);
+      std::optional<gfx::Size> parsed_size = ParseResolutionString(choice);
       if (!parsed_size.has_value()) {
         continue;
       }
@@ -186,8 +186,7 @@
     ppd_attr_t* attr = ppdFindAttr(ppd, "DefaultResolution", nullptr);
     if (attr) {
       CHECK(attr->value);
-      absl::optional<gfx::Size> parsed_size =
-          ParseResolutionString(attr->value);
+      std::optional<gfx::Size> parsed_size = ParseResolutionString(attr->value);
       if (parsed_size.has_value()) {
         dpis.push_back(parsed_size.value());
         default_dpi = parsed_size.value();
diff --git a/printing/backend/cups_helper_unittest.cc b/printing/backend/cups_helper_unittest.cc
index 8b2774d5..a8d5864e 100644
--- a/printing/backend/cups_helper_unittest.cc
+++ b/printing/backend/cups_helper_unittest.cc
@@ -29,7 +29,7 @@
 }
 
 void VerifyCapabilityColorModels(const PrinterSemanticCapsAndDefaults& caps) {
-  absl::optional<bool> maybe_color = IsColorModelSelected(caps.color_model);
+  std::optional<bool> maybe_color = IsColorModelSelected(caps.color_model);
   ASSERT_TRUE(maybe_color.has_value());
   EXPECT_TRUE(maybe_color.value());
   maybe_color = IsColorModelSelected(caps.bw_model);
diff --git a/printing/backend/cups_ipp_helper.cc b/printing/backend/cups_ipp_helper.cc
index 92c0689..e2c1c28 100644
--- a/printing/backend/cups_ipp_helper.cc
+++ b/printing/backend/cups_ipp_helper.cc
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/containers/contains.h"
 #include "base/containers/fixed_flat_set.h"
 #include "base/containers/flat_map.h"
@@ -28,7 +29,6 @@
 #include "printing/mojom/print.mojom.h"
 #include "printing/printing_utils.h"
 #include "printing/units.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(IS_CHROMEOS)
 #include "base/functional/callback.h"
@@ -192,7 +192,7 @@
 }
 
 // Reads resolution from `attr` and puts into `size` in dots per inch.
-absl::optional<gfx::Size> GetResolution(ipp_attribute_t* attr, int i) {
+std::optional<gfx::Size> GetResolution(ipp_attribute_t* attr, int i) {
   ipp_res_t units;
   int yres;
   int xres = ippGetResolution(attr, i, &yres, &units);
@@ -229,12 +229,12 @@
 
   int num_options = ippGetCount(attr);
   for (int i = 0; i < num_options; i++) {
-    absl::optional<gfx::Size> size = GetResolution(attr, i);
+    std::optional<gfx::Size> size = GetResolution(attr, i);
     if (size)
       printer_info->dpis.push_back(size.value());
   }
   ipp_attribute_t* def_attr = printer.GetDefaultOptionValue(kIppResolution);
-  absl::optional<gfx::Size> size = GetResolution(def_attr, 0);
+  std::optional<gfx::Size> size = GetResolution(def_attr, 0);
   if (size) {
     printer_info->default_dpi = size.value();
   } else if (!printer_info->dpis.empty()) {
@@ -248,20 +248,20 @@
   }
 }
 
-absl::optional<PrinterSemanticCapsAndDefaults::Paper>
+std::optional<PrinterSemanticCapsAndDefaults::Paper>
 PaperFromMediaColDatabaseEntry(ipp_t* db_entry) {
   DCHECK(db_entry);
 
-  absl::optional<MediaColData> size = ExtractMediaColData(db_entry);
+  std::optional<MediaColData> size = ExtractMediaColData(db_entry);
   if (!size) {
     LOG(WARNING) << "Unable to create Paper from media-col-database";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (size->HasVariableWidth()) {
     LOG(WARNING) << "Invalid media-col-database entry:"
                  << " variable widths are not supported.";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Some PPDs (only ones with a custom height range) have a min height of 0,
@@ -290,7 +290,7 @@
                  << " media-left-margin=" << size->left_margin
                  << " media-right-margin=" << size->right_margin
                  << " media-top-margin=" << size->top_margin;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   gfx::Size size_um(size->min_width * kMicronsPerPwgUnit,
@@ -330,7 +330,7 @@
   int count = ippGetCount(attr);
 
   for (int i = 0; i < count; i++) {
-    absl::optional<PrinterSemanticCapsAndDefaults::Paper> paper_opt =
+    std::optional<PrinterSemanticCapsAndDefaults::Paper> paper_opt =
         PaperFromMediaColDatabaseEntry(ippGetCollection(attr, i));
     if (!paper_opt.has_value()) {
       continue;
@@ -552,7 +552,7 @@
   for (int i = 0; i < count; i++) {
     ipp_t* db_entry = ippGetCollection(attr, i);
 
-    absl::optional<PrinterSemanticCapsAndDefaults::Paper> paper_opt =
+    std::optional<PrinterSemanticCapsAndDefaults::Paper> paper_opt =
         PaperFromMediaColDatabaseEntry(db_entry);
     if (!paper_opt.has_value()) {
       continue;
@@ -582,16 +582,16 @@
   ippDelete(ipp);
 }
 
-absl::optional<MediaColData> ExtractMediaColData(ipp_t* db_entry) {
+std::optional<MediaColData> ExtractMediaColData(ipp_t* db_entry) {
   if (!db_entry) {
     LOG(WARNING) << "Invalid media-col-database entry: empty entry.";
-    return absl::nullopt;
+    return std::nullopt;
   }
   ipp_t* media_size = ippGetCollection(
       ippFindAttribute(db_entry, kIppMediaSize, IPP_TAG_BEGIN_COLLECTION), 0);
   if (!media_size) {
     LOG(WARNING) << "Invalid media-col-database entry: empty media_size.";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   ipp_attribute_t* bottom_attr =
@@ -605,7 +605,7 @@
   if (!bottom_attr || !left_attr || !right_attr || !top_attr) {
     LOG(WARNING) << "Invalid media-col-database entry:"
                  << " margins are not present.";
-    return absl::nullopt;
+    return std::nullopt;
   }
   int bottom_margin = ippGetInteger(bottom_attr, 0);
   int left_margin = ippGetInteger(left_attr, 0);
@@ -626,7 +626,7 @@
       (!height_attr && !height_range_attr)) {
     LOG(WARNING) << "Invalid media-col-database entry:"
                  << " media-size needs x and y (or x and y range).";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   int min_width = 0;
@@ -650,13 +650,13 @@
     LOG(WARNING) << "Invalid media-col-database entry:"
                  << " min_width (" << min_width << ") > max_width ("
                  << max_width << ").";
-    return absl::nullopt;
+    return std::nullopt;
   }
   if (min_height > max_height) {
     LOG(WARNING) << "Invalid media-col-database entry:"
                  << " min_height (" << min_height << ") > max_height ("
                  << max_height << ").";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
 #if BUILDFLAG(IS_MAC)
@@ -752,7 +752,7 @@
   // they can be added later (once all the fixed widths have been discovered).
   for (int i = 0; i < ippGetCount(media_col_db); i++) {
     ipp_t* db_entry = ippGetCollection(media_col_db, i);
-    absl::optional<MediaColData> size = ExtractMediaColData(db_entry);
+    std::optional<MediaColData> size = ExtractMediaColData(db_entry);
     if (!size.has_value()) {
       return;
     }
diff --git a/printing/backend/cups_ipp_helper.h b/printing/backend/cups_ipp_helper.h
index 753de6a..b7dc9644 100644
--- a/printing/backend/cups_ipp_helper.h
+++ b/printing/backend/cups_ipp_helper.h
@@ -61,7 +61,7 @@
 
 // Returns a MediaColData object by extracting necessary fields from `db_entry`.
 COMPONENT_EXPORT(PRINT_BACKEND)
-absl::optional<MediaColData> ExtractMediaColData(ipp_t* db_entry);
+std::optional<MediaColData> ExtractMediaColData(ipp_t* db_entry);
 
 // Creates a new media-col-database entry from `data`.  The caller is
 // responsible for the returned memory.
diff --git a/printing/backend/mojom/print_backend_mojom_traits.cc b/printing/backend/mojom/print_backend_mojom_traits.cc
index 25f55b0..3dcee639 100644
--- a/printing/backend/mojom/print_backend_mojom_traits.cc
+++ b/printing/backend/mojom/print_backend_mojom_traits.cc
@@ -116,7 +116,7 @@
   std::string display_name;
   std::string vendor_id;
   gfx::Size size_um;
-  absl::optional<gfx::Rect> maybe_printable_area_um;
+  std::optional<gfx::Rect> maybe_printable_area_um;
   if (!data.ReadDisplayName(&display_name) || !data.ReadVendorId(&vendor_id) ||
       !data.ReadSizeUm(&size_um) ||
       !data.ReadPrintableAreaUm(&maybe_printable_area_um)) {
@@ -253,9 +253,9 @@
                   printing::PrinterSemanticCapsAndDefaults>::
     Read(printing::mojom::PrinterSemanticCapsAndDefaultsDataView data,
          printing::PrinterSemanticCapsAndDefaults* out) {
-  absl::optional<printing::PrinterSemanticCapsAndDefaults::MediaTypes>
+  std::optional<printing::PrinterSemanticCapsAndDefaults::MediaTypes>
       media_types;
-  absl::optional<printing::PrinterSemanticCapsAndDefaults::MediaType>
+  std::optional<printing::PrinterSemanticCapsAndDefaults::MediaType>
       default_media_type;
 
   out->collate_capable = data.collate_capable();
@@ -322,7 +322,7 @@
   if (out->page_output_quality) {
     printing::PageOutputQualityAttributes qualities =
         out->page_output_quality->qualities;
-    absl::optional<std::string> default_quality =
+    std::optional<std::string> default_quality =
         out->page_output_quality->default_quality;
 
     // If non-null `default_quality`, there should be a matching element in
diff --git a/printing/backend/mojom/print_backend_mojom_traits.h b/printing/backend/mojom/print_backend_mojom_traits.h
index c128aaf..10fa830 100644
--- a/printing/backend/mojom/print_backend_mojom_traits.h
+++ b/printing/backend/mojom/print_backend_mojom_traits.h
@@ -172,7 +172,7 @@
     return p.qualities;
   }
 
-  static const absl::optional<std::string>& default_quality(
+  static const std::optional<std::string>& default_quality(
       const ::printing::PageOutputQuality& p) {
     return p.default_quality;
   }
@@ -259,7 +259,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_WIN)
-  static const absl::optional<printing::PageOutputQuality>& page_output_quality(
+  static const std::optional<printing::PageOutputQuality>& page_output_quality(
       const printing::PrinterSemanticCapsAndDefaults& p) {
     return p.page_output_quality;
   }
diff --git a/printing/backend/mojom/print_backend_mojom_traits_unittest.cc b/printing/backend/mojom/print_backend_mojom_traits_unittest.cc
index 2f9f7cd8..1c75c12e 100644
--- a/printing/backend/mojom/print_backend_mojom_traits_unittest.cc
+++ b/printing/backend/mojom/print_backend_mojom_traits_unittest.cc
@@ -445,7 +445,7 @@
     PrintBackendMojomTraitsTest,
     TestSerializeAndDeserializePrinterSemanticCapsAndDefaultsAllowableEmptyArraysXpsCapabilities) {
   const PageOutputQualityAttributes kEmptyQualities;
-  PageOutputQuality quality(kEmptyQualities, /*default_quality=*/absl::nullopt);
+  PageOutputQuality quality(kEmptyQualities, /*default_quality=*/std::nullopt);
   PrinterSemanticCapsAndDefaults input =
       GenerateSamplePrinterSemanticCapsAndDefaults({});
   input.page_output_quality = quality;
@@ -499,7 +499,7 @@
   PageOutputQuality page_output_quality(
       {kPageOutputQualityAttribute1, kPageOutputQualityAttributePrime,
        kPageOutputQualityAttribute2},
-      /*default_quality=*/absl::nullopt);
+      /*default_quality=*/std::nullopt);
   PrinterSemanticCapsAndDefaults input =
       GenerateSamplePrinterSemanticCapsAndDefaults({});
   input.page_output_quality = page_output_quality;
diff --git a/printing/backend/print_backend.cc b/printing/backend/print_backend.cc
index 99cbcc61..03268b02 100644
--- a/printing/backend/print_backend.cc
+++ b/printing/backend/print_backend.cc
@@ -120,9 +120,8 @@
 
 PageOutputQuality::PageOutputQuality() = default;
 
-PageOutputQuality::PageOutputQuality(
-    PageOutputQualityAttributes qualities,
-    absl::optional<std::string> default_quality)
+PageOutputQuality::PageOutputQuality(PageOutputQualityAttributes qualities,
+                                     std::optional<std::string> default_quality)
     : qualities(std::move(qualities)),
       default_quality(std::move(default_quality)) {}
 
diff --git a/printing/backend/print_backend.h b/printing/backend/print_backend.h
index defdcc5..21b9e43 100644
--- a/printing/backend/print_backend.h
+++ b/printing/backend/print_backend.h
@@ -11,12 +11,12 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_refptr.h"
 #include "build/build_config.h"
 #include "printing/mojom/print.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 
@@ -133,7 +133,7 @@
 struct COMPONENT_EXPORT(PRINT_BACKEND) PageOutputQuality {
   PageOutputQuality();
   PageOutputQuality(PageOutputQualityAttributes qualities,
-                    absl::optional<std::string> default_quality);
+                    std::optional<std::string> default_quality);
   PageOutputQuality(const PageOutputQuality& other);
   ~PageOutputQuality();
 
@@ -142,7 +142,7 @@
 
   // Default option of page output quality.
   // TODO(crbug.com/1291257): Need populate this option in the next CLs.
-  absl::optional<std::string> default_quality;
+  std::optional<std::string> default_quality;
 };
 
 #if defined(UNIT_TEST)
@@ -161,7 +161,7 @@
   XpsCapabilities& operator=(XpsCapabilities&& other) noexcept;
   ~XpsCapabilities();
 
-  absl::optional<PageOutputQuality> page_output_quality;
+  std::optional<PageOutputQuality> page_output_quality;
 };
 
 #endif  // BUILDFLAG(IS_WIN)
@@ -289,7 +289,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_WIN)
-  absl::optional<PageOutputQuality> page_output_quality;
+  std::optional<PageOutputQuality> page_output_quality;
 #endif  // BUILDFLAG(IS_WIN)
 };
 
@@ -365,7 +365,7 @@
   // there is any error in retrieving this data.
   // TODO(crbug.com/1424368):  Remove this if the printable areas can be made
   // fully available from `GetPrinterSemanticCapsAndDefaults()`.
-  virtual absl::optional<gfx::Rect> GetPaperPrintableArea(
+  virtual std::optional<gfx::Rect> GetPaperPrintableArea(
       const std::string& printer_name,
       const std::string& paper_vendor_id,
       const gfx::Size& paper_size_um) = 0;
diff --git a/printing/backend/print_backend_test_constants.cc b/printing/backend/print_backend_test_constants.cc
index c87954e..82d87c1 100644
--- a/printing/backend/print_backend_test_constants.cc
+++ b/printing/backend/print_backend_test_constants.cc
@@ -4,8 +4,8 @@
 
 #include "printing/backend/print_backend_test_constants.h"
 
+#include <optional>
 #include "printing/backend/print_backend.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace printing {
 
diff --git a/printing/backend/print_backend_test_constants.h b/printing/backend/print_backend_test_constants.h
index 2152b48..8e76e27 100644
--- a/printing/backend/print_backend_test_constants.h
+++ b/printing/backend/print_backend_test_constants.h
@@ -9,10 +9,10 @@
 
 #include <vector>
 
+#include <optional>
 #include "build/build_config.h"
 #include "printing/backend/mojom/print_backend.mojom-forward.h"
 #include "printing/backend/print_backend.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace printing {
@@ -34,7 +34,7 @@
   AdvancedCapabilities advanced_capabilities;
 #endif  // BUILDFLAG(IS_CHROMEOS)
 #if BUILDFLAG(IS_WIN)
-  absl::optional<PageOutputQuality> page_output_quality;
+  std::optional<PageOutputQuality> page_output_quality;
 #endif  // BUILDFLAG(IS_WIN)
 };
 
@@ -116,7 +116,7 @@
     kPageOutputQualityAttribute3};
 inline const PageOutputQuality kPageOutputQuality(
     kPageOutputQualityAttributes,
-    /*default_quality=*/absl::nullopt);
+    /*default_quality=*/std::nullopt);
 inline constexpr char kDefaultQuality[] = "ns000:Draft";
 #endif  // BUILDFLAG(IS_WIN)
 
diff --git a/printing/backend/print_backend_win.cc b/printing/backend/print_backend_win.cc
index b4259246..e8f6907e 100644
--- a/printing/backend/print_backend_win.cc
+++ b/printing/backend/print_backend_win.cc
@@ -304,7 +304,7 @@
   mojom::ResultCode GetPrinterCapsAndDefaults(
       const std::string& printer_name,
       PrinterCapsAndDefaults* printer_info) override;
-  absl::optional<gfx::Rect> GetPaperPrintableArea(
+  std::optional<gfx::Rect> GetPaperPrintableArea(
       const std::string& printer_name,
       const std::string& paper_vendor_id,
       const gfx::Size& paper_size_um) override;
@@ -555,19 +555,19 @@
   return mojom::ResultCode::kSuccess;
 }
 
-absl::optional<gfx::Rect> PrintBackendWin::GetPaperPrintableArea(
+std::optional<gfx::Rect> PrintBackendWin::GetPaperPrintableArea(
     const std::string& printer_name,
     const std::string& paper_vendor_id,
     const gfx::Size& paper_size_um) {
   ScopedPrinterHandle printer_handle = GetPrinterHandle(printer_name);
   if (!printer_handle.IsValid()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   std::unique_ptr<DEVMODE, base::FreeDeleter> devmode =
       CreateDevMode(printer_handle.Get(), nullptr);
   if (!devmode) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   unsigned id = 0;
diff --git a/printing/backend/test_print_backend.cc b/printing/backend/test_print_backend.cc
index 6eae2f6..4de96bc4 100644
--- a/printing/backend/test_print_backend.cc
+++ b/printing/backend/test_print_backend.cc
@@ -145,23 +145,23 @@
   return ReportErrorNotImplemented(FROM_HERE);
 }
 
-absl::optional<gfx::Rect> TestPrintBackend::GetPaperPrintableArea(
+std::optional<gfx::Rect> TestPrintBackend::GetPaperPrintableArea(
     const std::string& printer_name,
     const std::string& paper_vendor_id,
     const gfx::Size& paper_size_um) {
   auto found = printer_map_.find(printer_name);
   if (found == printer_map_.end()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   const std::unique_ptr<PrinterData>& data = found->second;
   if (data->blocked_by_permissions) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Capabilities might not have been provided.
   if (!data->caps) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Windows uses non-zero IDs to represent specific standard paper sizes.
@@ -175,7 +175,7 @@
     }
 
     // No match for the specified paper identification.
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Custom paper size.  For testing just treat as match to paper size.
diff --git a/printing/backend/test_print_backend.h b/printing/backend/test_print_backend.h
index e598e896..0b938f1 100644
--- a/printing/backend/test_print_backend.h
+++ b/printing/backend/test_print_backend.h
@@ -39,7 +39,7 @@
   mojom::ResultCode GetPrinterCapsAndDefaults(
       const std::string& printer_name,
       PrinterCapsAndDefaults* printer_info) override;
-  absl::optional<gfx::Rect> GetPaperPrintableArea(
+  std::optional<gfx::Rect> GetPaperPrintableArea(
       const std::string& printer_name,
       const std::string& paper_vendor_id,
       const gfx::Size& paper_size_um) override;
diff --git a/printing/backend/xps_utils_win_unittest.cc b/printing/backend/xps_utils_win_unittest.cc
index 8477679c..5dd65fb 100644
--- a/printing/backend/xps_utils_win_unittest.cc
+++ b/printing/backend/xps_utils_win_unittest.cc
@@ -293,7 +293,7 @@
             kPageOutputQuality);
 
   // Expect that non-XPS capabilities remain unmodified.
-  printer_capabilities.page_output_quality = absl::nullopt;
+  printer_capabilities.page_output_quality = std::nullopt;
   EXPECT_EQ(printer_capabilities,
             GenerateSamplePrinterSemanticCapsAndDefaults({}));
 }
diff --git a/printing/client_info_helpers_unittest.cc b/printing/client_info_helpers_unittest.cc
index 2f28fa3..552d77f 100644
--- a/printing/client_info_helpers_unittest.cc
+++ b/printing/client_info_helpers_unittest.cc
@@ -6,12 +6,12 @@
 
 #include <string>
 
+#include <optional>
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "printing/mojom/print.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace printing {
 
@@ -28,8 +28,8 @@
 TEST(ClientInfoHelpersTest, ValidateClientInfoItemValidWithMissingFields) {
   mojom::IppClientInfo::ClientType type =
       mojom::IppClientInfo::ClientType::kApplication;
-  mojom::IppClientInfo client_info(type, "a-", absl::nullopt, "1.",
-                                   absl::nullopt);
+  mojom::IppClientInfo client_info(type, "a-", std::nullopt, "1.",
+                                   std::nullopt);
 
   EXPECT_TRUE(ValidateClientInfoItem(client_info));
 }
@@ -37,7 +37,7 @@
 TEST(ClientInfoHelpersTest, ValidateClientInfoItemInvalidChars) {
   mojom::IppClientInfo valid_client_info(
       mojom::IppClientInfo::ClientType::kOther, "name", "patch", "version",
-      absl::nullopt);
+      std::nullopt);
 
   mojom::IppClientInfo client_info;
 
@@ -61,7 +61,7 @@
 TEST(ClientInfoHelpersTest, ValidateClientInfoItemInvalidRange) {
   mojom::IppClientInfo valid_client_info(
       mojom::IppClientInfo::ClientType::kOther, "name", "patch", "version",
-      absl::nullopt);
+      std::nullopt);
 
   mojom::IppClientInfo client_info;
 
diff --git a/printing/common/metafile_utils.cc b/printing/common/metafile_utils.cc
index e420456..d7a0c453 100644
--- a/printing/common/metafile_utils.cc
+++ b/printing/common/metafile_utils.cc
@@ -184,13 +184,13 @@
   }
 
   if (ui::IsCellOrTableHeader(ax_node->GetRole())) {
-    absl::optional<int> row_span = ax_node->GetTableCellRowSpan();
+    std::optional<int> row_span = ax_node->GetTableCellRowSpan();
     if (row_span.has_value()) {
       tag->fAttributes.appendInt(kPDFTableAttributeOwner,
                                  kPDFTableCellRowSpanAttribute,
                                  row_span.value());
     }
-    absl::optional<int> col_span = ax_node->GetTableCellColSpan();
+    std::optional<int> col_span = ax_node->GetTableCellColSpan();
     if (col_span.has_value()) {
       tag->fAttributes.appendInt(kPDFTableAttributeOwner,
                                  kPDFTableCellColSpanAttribute,
diff --git a/printing/mojom/printing_context_mojom_traits.cc b/printing/mojom/printing_context_mojom_traits.cc
index 42dea5f..f6c58fd 100644
--- a/printing/mojom/printing_context_mojom_traits.cc
+++ b/printing/mojom/printing_context_mojom_traits.cc
@@ -191,7 +191,7 @@
 #if BUILDFLAG(IS_MAC)
     // The dictionary must contain the destination type, page format, and
     // print settings.
-    absl::optional<int> destination_type = system_print_dialog_data.FindInt(
+    std::optional<int> destination_type = system_print_dialog_data.FindInt(
         printing::kMacSystemPrintDialogDataDestinationType);
     if (!destination_type.has_value()) {
       return false;
diff --git a/printing/print_settings.cc b/printing/print_settings.cc
index 3277874..d8599dd 100644
--- a/printing/print_settings.cc
+++ b/printing/print_settings.cc
@@ -219,7 +219,7 @@
 }
 #endif  // BUILDFLAG(USE_CUPS_IPP)
 
-absl::optional<bool> IsColorModelSelected(mojom::ColorModel color_model) {
+std::optional<bool> IsColorModelSelected(mojom::ColorModel color_model) {
   switch (color_model) {
     case mojom::ColorModel::kColor:
     case mojom::ColorModel::kCMYK:
@@ -267,7 +267,7 @@
       return false;
     case mojom::ColorModel::kUnknownColorModel:
       NOTREACHED();
-      return absl::nullopt;
+      return std::nullopt;
   }
   // The default case is excluded from the above switch statement to ensure that
   // all ColorModel values are determinantly handled.
diff --git a/printing/print_settings.h b/printing/print_settings.h
index 5e9cbf5a..bddd437 100644
--- a/printing/print_settings.h
+++ b/printing/print_settings.h
@@ -10,6 +10,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "build/build_config.h"
 #include "printing/buildflags/buildflags.h"
@@ -17,7 +18,6 @@
 #include "printing/page_range.h"
 #include "printing/page_setup.h"
 #include "printing/print_job_constants.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 
@@ -67,9 +67,9 @@
 
 // Returns true if `color_model` is color and false if it is B&W.  Callers
 // are not supposed to pass in `mojom::ColorModel::kUnknownColorModel`, but
-// if they do then the result will be absl::nullopt.
+// if they do then the result will be std::nullopt.
 COMPONENT_EXPORT(PRINTING)
-absl::optional<bool> IsColorModelSelected(mojom::ColorModel color_model);
+std::optional<bool> IsColorModelSelected(mojom::ColorModel color_model);
 
 #if BUILDFLAG(USE_CUPS)
 // Get the color model setting name and value for the `color_model`.
@@ -316,7 +316,7 @@
       crosapi::mojom::StatusReason::Reason printer_status_reason) {
     printer_status_reason_ = printer_status_reason;
   }
-  absl::optional<crosapi::mojom::StatusReason::Reason> printer_status_reason()
+  std::optional<crosapi::mojom::StatusReason::Reason> printer_status_reason()
       const {
     return printer_status_reason_;
   }
@@ -457,7 +457,7 @@
 
   // The printer status reason shown for the selected printer at the time print
   // is requested. Only local CrOS printers set printer statuses.
-  absl::optional<crosapi::mojom::StatusReason::Reason> printer_status_reason_;
+  std::optional<crosapi::mojom::StatusReason::Reason> printer_status_reason_;
 #endif  // BUILDFLAG(IS_CHROMEOS)
 };
 
diff --git a/printing/print_settings_conversion.cc b/printing/print_settings_conversion.cc
index 8e882f0..9878e55 100644
--- a/printing/print_settings_conversion.cc
+++ b/printing/print_settings_conversion.cc
@@ -12,6 +12,7 @@
 #include <string>
 #include <utility>
 
+#include <optional>
 #include "base/containers/contains.h"
 #include "base/containers/fixed_flat_set.h"
 #include "base/strings/string_number_conversions.h"
@@ -25,7 +26,6 @@
 #include "printing/print_job_constants.h"
 #include "printing/print_settings.h"
 #include "printing/units.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 
@@ -87,13 +87,13 @@
 void SetPrintableAreaIfValid(PrintSettings& settings,
                              const gfx::Size& size_microns,
                              const base::Value::Dict& media_size) {
-  absl::optional<int> left_microns =
+  std::optional<int> left_microns =
       media_size.FindInt(kSettingsImageableAreaLeftMicrons);
-  absl::optional<int> bottom_microns =
+  std::optional<int> bottom_microns =
       media_size.FindInt(kSettingsImageableAreaBottomMicrons);
-  absl::optional<int> right_microns =
+  std::optional<int> right_microns =
       media_size.FindInt(kSettingsImageableAreaRightMicrons);
-  absl::optional<int> top_microns =
+  std::optional<int> top_microns =
       media_size.FindInt(kSettingsImageableAreaTopMicrons);
   if (!bottom_microns.has_value() || !left_microns.has_value() ||
       !right_microns.has_value() || !top_microns.has_value()) {
@@ -140,8 +140,8 @@
     }
 
     const auto& dict = page_range.GetDict();
-    absl::optional<int> from = dict.FindInt(kSettingPageRangeFrom);
-    absl::optional<int> to = dict.FindInt(kSettingPageRangeTo);
+    std::optional<int> from = dict.FindInt(kSettingPageRangeFrom);
+    std::optional<int> to = dict.FindInt(kSettingPageRangeTo);
     if (!from.has_value() || !to.has_value()) {
       continue;
     }
@@ -157,7 +157,7 @@
 std::unique_ptr<PrintSettings> PrintSettingsFromJobSettings(
     const base::Value::Dict& job_settings) {
   auto settings = std::make_unique<PrintSettings>();
-  absl::optional<bool> display_header_footer =
+  std::optional<bool> display_header_footer =
       job_settings.FindBool(kSettingHeaderFooterEnabled);
   if (!display_header_footer.has_value()) {
     return nullptr;
@@ -176,9 +176,9 @@
     settings->set_url(base::UTF8ToUTF16(*url));
   }
 
-  absl::optional<bool> backgrounds =
+  std::optional<bool> backgrounds =
       job_settings.FindBool(kSettingShouldPrintBackgrounds);
-  absl::optional<bool> selection_only =
+  std::optional<bool> selection_only =
       job_settings.FindBool(kSettingShouldPrintSelectionOnly);
   if (!backgrounds.has_value() || !selection_only.has_value()) {
     return nullptr;
@@ -187,16 +187,16 @@
   settings->set_should_print_backgrounds(backgrounds.value());
   settings->set_selection_only(selection_only.value());
 
-  absl::optional<bool> collate = job_settings.FindBool(kSettingCollate);
-  absl::optional<int> copies = job_settings.FindInt(kSettingCopies);
-  absl::optional<int> color = job_settings.FindInt(kSettingColor);
-  absl::optional<int> duplex_mode = job_settings.FindInt(kSettingDuplexMode);
-  absl::optional<bool> landscape = job_settings.FindBool(kSettingLandscape);
+  std::optional<bool> collate = job_settings.FindBool(kSettingCollate);
+  std::optional<int> copies = job_settings.FindInt(kSettingCopies);
+  std::optional<int> color = job_settings.FindInt(kSettingColor);
+  std::optional<int> duplex_mode = job_settings.FindInt(kSettingDuplexMode);
+  std::optional<bool> landscape = job_settings.FindBool(kSettingLandscape);
   const std::string* device_name = job_settings.FindString(kSettingDeviceName);
-  absl::optional<int> scale_factor = job_settings.FindInt(kSettingScaleFactor);
-  absl::optional<bool> rasterize_pdf =
+  std::optional<int> scale_factor = job_settings.FindInt(kSettingScaleFactor);
+  std::optional<bool> rasterize_pdf =
       job_settings.FindBool(kSettingRasterizePdf);
-  absl::optional<int> pages_per_sheet =
+  std::optional<int> pages_per_sheet =
       job_settings.FindInt(kSettingPagesPerSheet);
   if (!collate.has_value() || !copies.has_value() || !color.has_value() ||
       !duplex_mode.has_value() || !landscape.has_value() || !device_name ||
@@ -215,16 +215,16 @@
   settings->set_rasterize_pdf(rasterize_pdf.value());
   settings->set_pages_per_sheet(pages_per_sheet.value());
 
-  absl::optional<int> dpi_horizontal =
+  std::optional<int> dpi_horizontal =
       job_settings.FindInt(kSettingDpiHorizontal);
-  absl::optional<int> dpi_vertical = job_settings.FindInt(kSettingDpiVertical);
+  std::optional<int> dpi_vertical = job_settings.FindInt(kSettingDpiVertical);
   if (!dpi_horizontal.has_value() || !dpi_vertical.has_value()) {
     return nullptr;
   }
 
   settings->set_dpi_xy(dpi_horizontal.value(), dpi_vertical.value());
 
-  absl::optional<int> rasterize_pdf_dpi =
+  std::optional<int> rasterize_pdf_dpi =
       job_settings.FindInt(kSettingRasterizePdfDpi);
   if (rasterize_pdf_dpi.has_value()) {
     settings->set_rasterize_pdf_dpi(rasterize_pdf_dpi.value());
@@ -250,9 +250,9 @@
   const base::Value::Dict* media_size_value =
       job_settings.FindDict(kSettingMediaSize);
   if (media_size_value) {
-    absl::optional<int> width_microns =
+    std::optional<int> width_microns =
         media_size_value->FindInt(kSettingMediaSizeWidthMicrons);
-    absl::optional<int> height_microns =
+    std::optional<int> height_microns =
         media_size_value->FindInt(kSettingMediaSizeHeightMicrons);
     if (width_microns.has_value() && height_microns.has_value()) {
       requested_media.size_microns =
@@ -269,7 +269,7 @@
   }
   settings->set_requested_media(requested_media);
 
-  absl::optional<bool> borderless = job_settings.FindBool(kSettingBorderless);
+  std::optional<bool> borderless = job_settings.FindBool(kSettingBorderless);
   if (borderless.has_value()) {
     settings->set_borderless(borderless.value());
   }
@@ -281,7 +281,7 @@
 
   settings->set_ranges(GetPageRangesFromJobSettings(job_settings));
 
-  absl::optional<bool> is_modifiable =
+  std::optional<bool> is_modifiable =
       job_settings.FindBool(kSettingPreviewModifiable);
   if (is_modifiable.has_value()) {
     settings->set_is_modifiable(is_modifiable.value());
@@ -335,8 +335,7 @@
   settings->set_printer_manually_selected(
       job_settings.FindBool(kSettingPrinterManuallySelected).value_or(false));
 
-  absl::optional<int> reason =
-      job_settings.FindInt(kSettingPrinterStatusReason);
+  std::optional<int> reason = job_settings.FindInt(kSettingPrinterStatusReason);
   if (reason.has_value()) {
     settings->set_printer_status_reason(
         static_cast<crosapi::mojom::StatusReason::Reason>(reason.value()));
diff --git a/printing/print_settings_conversion_chromeos_unittest.cc b/printing/print_settings_conversion_chromeos_unittest.cc
index 92c4a2e6..f7d2009 100644
--- a/printing/print_settings_conversion_chromeos_unittest.cc
+++ b/printing/print_settings_conversion_chromeos_unittest.cc
@@ -6,10 +6,10 @@
 
 #include <string>
 
+#include <optional>
 #include "base/test/values_test_util.h"
 #include "base/values.h"
 #include "printing/mojom/print.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace printing {
 
@@ -38,9 +38,9 @@
                          "version"),
     mojom::IppClientInfo(mojom::IppClientInfo::ClientType::kOther,
                          "chromebook-{DEVICE_ASSET_ID}",
-                         absl::nullopt,
+                         std::nullopt,
                          "",
-                         absl::nullopt)};
+                         std::nullopt)};
 
 TEST(PrintSettingsConversionChromeosTest, ConvertClientInfoToJobSetting) {
   base::Value::List job_setting = ConvertClientInfoToJobSetting(kClientInfo);
diff --git a/printing/printing_context_chromeos_unittest.cc b/printing/printing_context_chromeos_unittest.cc
index 2b74ba7..ef53af0 100644
--- a/printing/printing_context_chromeos_unittest.cc
+++ b/printing/printing_context_chromeos_unittest.cc
@@ -367,7 +367,7 @@
   EXPECT_FALSE(HasAttribute(kIppClientInfo));
 
   mojom::IppClientInfo invalid_client_info(
-      mojom::IppClientInfo::ClientType::kOther, "$", " ", "{}", absl::nullopt);
+      mojom::IppClientInfo::ClientType::kOther, "$", " ", "{}", std::nullopt);
 
   settings_.set_client_infos({invalid_client_info});
   EXPECT_FALSE(HasAttribute(kIppClientInfo));
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm
index b051381..f402566 100644
--- a/printing/printing_context_mac.mm
+++ b/printing/printing_context_mac.mm
@@ -293,7 +293,7 @@
                             const base::Value::Dict& system_print_dialog_data,
                             PMPrintSession& print_session,
                             PMPrintSettings& print_settings) {
-  absl::optional<int> destination_type = system_print_dialog_data.FindInt(
+  std::optional<int> destination_type = system_print_dialog_data.FindInt(
       kMacSystemPrintDialogDataDestinationType);
 
   CHECK(destination_type.has_value());
diff --git a/printing/test_printing_context.h b/printing/test_printing_context.h
index 494a45c7..108364b 100644
--- a/printing/test_printing_context.h
+++ b/printing/test_printing_context.h
@@ -16,7 +16,7 @@
 #include "printing/printing_context.h"
 
 #if BUILDFLAG(IS_WIN)
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include <optional>
 #endif
 
 namespace printing {
@@ -130,7 +130,7 @@
   base::flat_map<std::string, std::unique_ptr<PrintSettings>> device_settings_;
 
   // Settings to apply to mimic a user's choices in `AskUserForSettings()`.
-  absl::optional<PrintSettings> user_settings_;
+  std::optional<PrintSettings> user_settings_;
 
   // Platform implementations of `PrintingContext` apply PrintSettings to the
   // respective device contexts.  Once the upper printing layers call
@@ -155,7 +155,7 @@
   bool new_document_blocked_by_permissions_ = false;
 #if BUILDFLAG(IS_WIN)
   bool render_page_blocked_by_permissions_ = false;
-  absl::optional<uint32_t> render_page_fail_for_page_number_;
+  std::optional<uint32_t> render_page_fail_for_page_number_;
 #endif
   bool render_document_blocked_by_permissions_ = false;
   bool document_done_blocked_by_permissions_ = false;
diff --git a/remoting/base/chromoting_event.cc b/remoting/base/chromoting_event.cc
index e7a09f7..e0efc9bb 100644
--- a/remoting/base/chromoting_event.cc
+++ b/remoting/base/chromoting_event.cc
@@ -178,7 +178,7 @@
 }
 
 bool ChromotingEvent::IsDataValid() {
-  absl::optional<int> auth_method = values_map_->FindInt(kAuthMethodKey);
+  std::optional<int> auth_method = values_map_->FindInt(kAuthMethodKey);
   if (auth_method &&
       auth_method.value() == static_cast<int>(AuthMethod::NOT_SET)) {
     return false;
@@ -228,21 +228,21 @@
 apis::v1::ChromotingEvent ChromotingEvent::CreateProto() const {
   apis::v1::ChromotingEvent event_proto;
 
-  if (absl::optional<int> auth_method = values_map_->FindInt(kAuthMethodKey)) {
+  if (std::optional<int> auth_method = values_map_->FindInt(kAuthMethodKey)) {
     event_proto.set_auth_method(
         static_cast<apis::v1::ChromotingEvent_AuthMethod>(auth_method.value()));
   }
-  if (absl::optional<double> capture_latency =
+  if (std::optional<double> capture_latency =
           values_map_->FindDouble(kCaptureLatencyKey)) {
     event_proto.set_capture_latency(capture_latency.value());
   }
-  if (absl::optional<int> connection_error =
+  if (std::optional<int> connection_error =
           values_map_->FindInt(kConnectionErrorKey)) {
     event_proto.set_connection_error(
         static_cast<apis::v1::ChromotingEvent_ConnectionError>(
             connection_error.value()));
   }
-  if (absl::optional<int> connection_type =
+  if (std::optional<int> connection_type =
           values_map_->FindInt(kConnectionTypeKey)) {
     event_proto.set_connection_type(
         static_cast<apis::v1::ChromotingEvent_ConnectionType>(
@@ -251,15 +251,15 @@
   if (const std::string* cpu = values_map_->FindString(kCpuKey)) {
     event_proto.set_cpu(*cpu);
   }
-  if (absl::optional<double> decode_latency =
+  if (std::optional<double> decode_latency =
           values_map_->FindDouble(kDecodeLatencyKey)) {
     event_proto.set_decode_latency(decode_latency.value());
   }
-  if (absl::optional<double> encode_latency =
+  if (std::optional<double> encode_latency =
           values_map_->FindDouble(kEncodeLatencyKey)) {
     event_proto.set_encode_latency(encode_latency.value());
   }
-  if (absl::optional<int> host_os = values_map_->FindInt(kHostOsKey)) {
+  if (std::optional<int> host_os = values_map_->FindInt(kHostOsKey)) {
     event_proto.set_host_os(
         static_cast<apis::v1::ChromotingEvent_Os>(host_os.value()));
   }
@@ -271,59 +271,59 @@
           values_map_->FindString(kHostVersionKey)) {
     event_proto.set_host_version(*host_version);
   }
-  if (absl::optional<double> max_capture_latency =
+  if (std::optional<double> max_capture_latency =
           values_map_->FindDouble(kMaxCaptureLatencyKey)) {
     event_proto.set_max_capture_latency(max_capture_latency.value());
   }
-  if (absl::optional<double> max_decode_latency =
+  if (std::optional<double> max_decode_latency =
           values_map_->FindDouble(kMaxDecodeLatencyKey)) {
     event_proto.set_max_decode_latency(max_decode_latency.value());
   }
-  if (absl::optional<double> max_encode_latency =
+  if (std::optional<double> max_encode_latency =
           values_map_->FindDouble(kMaxEncodeLatencyKey)) {
     event_proto.set_max_encode_latency(max_encode_latency.value());
   }
-  if (absl::optional<double> max_render_latency =
+  if (std::optional<double> max_render_latency =
           values_map_->FindDouble(kMaxRenderLatencyKey)) {
     event_proto.set_max_render_latency(max_render_latency.value());
   }
-  if (absl::optional<double> max_roundtrip_latency =
+  if (std::optional<double> max_roundtrip_latency =
           values_map_->FindDouble(kMaxRoundtripLatencyKey)) {
     event_proto.set_max_roundtrip_latency(max_roundtrip_latency.value());
   }
-  if (absl::optional<int> mode = values_map_->FindInt(kModeKey)) {
+  if (std::optional<int> mode = values_map_->FindInt(kModeKey)) {
     event_proto.set_mode(
         static_cast<apis::v1::ChromotingEvent_Mode>(mode.value()));
   }
-  if (absl::optional<int> os = values_map_->FindInt(kOsKey)) {
+  if (std::optional<int> os = values_map_->FindInt(kOsKey)) {
     event_proto.set_os(static_cast<apis::v1::ChromotingEvent_Os>(os.value()));
   }
   if (const std::string* os_version = values_map_->FindString(kOsVersionKey)) {
     event_proto.set_os_version(*os_version);
   }
-  if (absl::optional<int> previous_session_state =
+  if (std::optional<int> previous_session_state =
           values_map_->FindInt(kPreviousSessionStateKey)) {
     event_proto.set_previous_session_state(
         static_cast<apis::v1::ChromotingEvent_SessionState>(
             previous_session_state.value()));
   }
-  if (absl::optional<double> render_latency =
+  if (std::optional<double> render_latency =
           values_map_->FindDouble(kRenderLatencyKey)) {
     event_proto.set_render_latency(render_latency.value());
   }
-  if (absl::optional<int> role = values_map_->FindInt(kRoleKey)) {
+  if (std::optional<int> role = values_map_->FindInt(kRoleKey)) {
     event_proto.set_role(
         static_cast<apis::v1::ChromotingEvent_Role>(role.value()));
   }
-  if (absl::optional<double> roundtrip_latency =
+  if (std::optional<double> roundtrip_latency =
           values_map_->FindDouble(kRoundtripLatencyKey)) {
     event_proto.set_roundtrip_latency(roundtrip_latency.value());
   }
-  if (absl::optional<double> session_duration =
+  if (std::optional<double> session_duration =
           values_map_->FindDouble(kSessionDurationKey)) {
     event_proto.set_session_duration(session_duration.value());
   }
-  if (absl::optional<int> session_entry_point =
+  if (std::optional<int> session_entry_point =
           values_map_->FindInt(kSessionEntryPointKey)) {
     event_proto.set_session_entry_point(
         static_cast<apis::v1::ChromotingEvent_SessionEntryPoint>(
@@ -332,23 +332,23 @@
   if (const std::string* session_id = values_map_->FindString(kSessionIdKey)) {
     event_proto.set_session_id(*session_id);
   }
-  if (absl::optional<int> session_state =
+  if (std::optional<int> session_state =
           values_map_->FindInt(kSessionStateKey)) {
     event_proto.set_session_state(
         static_cast<apis::v1::ChromotingEvent_SessionState>(
             session_state.value()));
   }
-  if (absl::optional<int> signal_strategy_type =
+  if (std::optional<int> signal_strategy_type =
           values_map_->FindInt(kSignalStrategyTypeKey)) {
     event_proto.set_signal_strategy_type(
         static_cast<apis::v1::ChromotingEvent_SignalStrategyType>(
             signal_strategy_type.value()));
   }
-  if (absl::optional<int> type = values_map_->FindInt(kTypeKey)) {
+  if (std::optional<int> type = values_map_->FindInt(kTypeKey)) {
     event_proto.set_type(
         static_cast<apis::v1::ChromotingEvent_Type>(type.value()));
   }
-  if (absl::optional<double> video_bandwidth =
+  if (std::optional<double> video_bandwidth =
           values_map_->FindDouble(kVideoBandwidthKey)) {
     event_proto.set_video_bandwidth(video_bandwidth.value());
   }
diff --git a/remoting/base/corp_service_client.cc b/remoting/base/corp_service_client.cc
index 930c5ee..0b23a44 100644
--- a/remoting/base/corp_service_client.cc
+++ b/remoting/base/corp_service_client.cc
@@ -40,7 +40,7 @@
     const std::string& owner_email,
     const std::string& fqdn,
     const std::string& public_key,
-    absl::optional<std::string> existing_host_id,
+    std::optional<std::string> existing_host_id,
     ProvisionCorpMachineCallback callback) {
   constexpr net::NetworkTrafficAnnotationTag traffic_annotation =
       net::DefineNetworkTrafficAnnotation("remoting_provision_corp_machine",
diff --git a/remoting/base/corp_service_client.h b/remoting/base/corp_service_client.h
index 9a073528..f4a6b57 100644
--- a/remoting/base/corp_service_client.h
+++ b/remoting/base/corp_service_client.h
@@ -8,12 +8,12 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/functional/callback_forward.h"
 #include "base/memory/scoped_refptr.h"
 #include "remoting/base/buildflags.h"
 #include "remoting/base/protobuf_http_client.h"
 #include "remoting/proto/empty.pb.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(REMOTING_INTERNAL)
 #include "remoting/internal/proto/helpers.h"
@@ -53,7 +53,7 @@
   void ProvisionCorpMachine(const std::string& owner_email,
                             const std::string& fqdn,
                             const std::string& public_key,
-                            absl::optional<std::string> existing_host_id,
+                            std::optional<std::string> existing_host_id,
                             ProvisionCorpMachineCallback callback);
 
   void ReportProvisioningError(const std::string& host_id,
diff --git a/remoting/base/file_host_settings.h b/remoting/base/file_host_settings.h
index 26cebb1..38b401a 100644
--- a/remoting/base/file_host_settings.h
+++ b/remoting/base/file_host_settings.h
@@ -42,7 +42,7 @@
 
   // TODO(yuweih): This needs to be guarded with a lock if we detect changes of
   // the settings file.
-  absl::optional<base::Value::Dict> settings_;
+  std::optional<base::Value::Dict> settings_;
 };
 
 }  // namespace remoting
diff --git a/remoting/base/protobuf_http_client.h b/remoting/base/protobuf_http_client.h
index b71965e..4db70f5 100644
--- a/remoting/base/protobuf_http_client.h
+++ b/remoting/base/protobuf_http_client.h
@@ -9,6 +9,7 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
@@ -16,7 +17,6 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "remoting/base/oauth_token_getter.h"
 #include "remoting/base/url_loader_network_service_observer.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace network {
 class SharedURLLoaderFactory;
@@ -67,7 +67,7 @@
 
   std::string server_endpoint_;
   raw_ptr<OAuthTokenGetter> token_getter_;
-  absl::optional<UrlLoaderNetworkServiceObserver> service_observer_;
+  std::optional<UrlLoaderNetworkServiceObserver> service_observer_;
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
   PendingRequestList pending_requests_;
 
diff --git a/remoting/base/result.h b/remoting/base/result.h
index 80a36d9..d9a5d67 100644
--- a/remoting/base/result.h
+++ b/remoting/base/result.h
@@ -8,8 +8,8 @@
 #include <type_traits>
 #include <utility>
 
+#include <optional>
 #include "base/check.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
 
 // Result<SuccessType, ErrorType> represents the success or failure of an
@@ -132,7 +132,7 @@
 class ErrorTag {};
 // absl::monostate can be used for SuccessType or ErrorType to indicate that
 // there is no data for that state. Thus, Result<SomeType, monostate> is
-// somewhat analogous to absl::optional<SomeType>, and Result<monostate,
+// somewhat analogous to std::optional<SomeType>, and Result<monostate,
 // monostate> is effectively a (2-byte) boolean. Result<monostate, ErrorType>
 // can be useful for cases where an operation can fail, but there is no return
 // value in the success case.
diff --git a/remoting/base/session_options.cc b/remoting/base/session_options.cc
index df2f649..7981ecd 100644
--- a/remoting/base/session_options.cc
+++ b/remoting/base/session_options.cc
@@ -53,18 +53,18 @@
   options_[key] = value;
 }
 
-absl::optional<std::string> SessionOptions::Get(const std::string& key) const {
+std::optional<std::string> SessionOptions::Get(const std::string& key) const {
   auto it = options_.find(key);
   if (it == options_.end()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return it->second;
 }
 
-absl::optional<bool> SessionOptions::GetBool(const std::string& key) const {
-  absl::optional<std::string> value = Get(key);
+std::optional<bool> SessionOptions::GetBool(const std::string& key) const {
+  std::optional<std::string> value = Get(key);
   if (!value) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   const std::string lowercase_value = base::ToLowerASCII(*value);
@@ -77,17 +77,17 @@
   }
   LOG(WARNING) << "Unexpected option received " << *value
                << " which cannot be converted to bool.";
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 bool SessionOptions::GetBoolValue(const std::string& key) const {
   return GetBool(key).value_or(false);
 }
 
-absl::optional<int> SessionOptions::GetInt(const std::string& key) const {
-  absl::optional<std::string> value = Get(key);
+std::optional<int> SessionOptions::GetInt(const std::string& key) const {
+  std::optional<std::string> value = Get(key);
   if (!value) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   int result;
@@ -96,7 +96,7 @@
   }
   LOG(WARNING) << "Unexpected option received " << *value
                << " which cannot be converted to integer.";
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 std::string SessionOptions::Export() const {
diff --git a/remoting/base/session_options.h b/remoting/base/session_options.h
index 99ee551..6d53993f 100644
--- a/remoting/base/session_options.h
+++ b/remoting/base/session_options.h
@@ -7,8 +7,8 @@
 
 #include <string>
 
+#include <optional>
 #include "base/containers/flat_map.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -32,20 +32,20 @@
 
   // Retrieves the value of |key|. Returns a true Optional if |key| has been
   // found, value of the Optional will be set to corresponding value.
-  absl::optional<std::string> Get(const std::string& key) const;
+  std::optional<std::string> Get(const std::string& key) const;
 
   // Retrieves the value of |key|. Returns a true Optional if |key| has been
   // found and the corresponding value can be converted to a boolean value.
   // "true", "1" or empty will be converted to true, "false" or "0" will be
   // converted to false.
-  absl::optional<bool> GetBool(const std::string& key) const;
+  std::optional<bool> GetBool(const std::string& key) const;
 
   // Equivalent to GetBool(key).value_or(false).
   bool GetBoolValue(const std::string& key) const;
 
   // Retrieves the value of |key|. Returns a true Optional if |key| has been
   // found and the corresponding value can be converted to an integer.
-  absl::optional<int> GetInt(const std::string& key) const;
+  std::optional<int> GetInt(const std::string& key) const;
 
   // Returns a string to represent current instance. Consumers can rebuild an
   // exactly same instance with Import() function.
diff --git a/remoting/base/url_loader_network_service_observer.cc b/remoting/base/url_loader_network_service_observer.cc
index 8913372..630b9e35 100644
--- a/remoting/base/url_loader_network_service_observer.cc
+++ b/remoting/base/url_loader_network_service_observer.cc
@@ -90,7 +90,7 @@
 }
 
 void UrlLoaderNetworkServiceObserver::OnCertificateRequested(
-    const absl::optional<base::UnguessableToken>& window_id,
+    const std::optional<base::UnguessableToken>& window_id,
     const scoped_refptr<net::SSLCertRequestInfo>& cert_info,
     mojo::PendingRemote<network::mojom::ClientCertificateResponder>
         client_cert_responder) {
@@ -110,7 +110,7 @@
 }
 
 void UrlLoaderNetworkServiceObserver::OnAuthRequired(
-    const absl::optional<base::UnguessableToken>& window_id,
+    const std::optional<base::UnguessableToken>& window_id,
     uint32_t request_id,
     const GURL& url,
     bool first_auth_attempt,
@@ -122,15 +122,15 @@
 void UrlLoaderNetworkServiceObserver::OnPrivateNetworkAccessPermissionRequired(
     const GURL& url,
     const net::IPAddress& ip_address,
-    const absl::optional<std::string>& private_network_device_id,
-    const absl::optional<std::string>& private_network_device_name,
+    const std::optional<std::string>& private_network_device_id,
+    const std::optional<std::string>& private_network_device_name,
     OnPrivateNetworkAccessPermissionRequiredCallback callback) {}
 
 void UrlLoaderNetworkServiceObserver::OnClearSiteData(
     const GURL& url,
     const std::string& header_value,
     int32_t load_flags,
-    const absl::optional<net::CookiePartitionKey>& cookie_partition_key,
+    const std::optional<net::CookiePartitionKey>& cookie_partition_key,
     bool partitioned_state_allowed_only,
     OnClearSiteDataCallback callback) {
   std::move(callback).Run();
diff --git a/remoting/base/url_loader_network_service_observer.h b/remoting/base/url_loader_network_service_observer.h
index 359a973..b8f27b5 100644
--- a/remoting/base/url_loader_network_service_observer.h
+++ b/remoting/base/url_loader_network_service_observer.h
@@ -43,12 +43,12 @@
                              bool fatal,
                              OnSSLCertificateErrorCallback response) override;
   void OnCertificateRequested(
-      const absl::optional<base::UnguessableToken>& window_id,
+      const std::optional<base::UnguessableToken>& window_id,
       const scoped_refptr<net::SSLCertRequestInfo>& cert_info,
       mojo::PendingRemote<network::mojom::ClientCertificateResponder>
           cert_responder) override;
   void OnAuthRequired(
-      const absl::optional<base::UnguessableToken>& window_id,
+      const std::optional<base::UnguessableToken>& window_id,
       uint32_t request_id,
       const GURL& url,
       bool first_auth_attempt,
@@ -59,14 +59,14 @@
   void OnPrivateNetworkAccessPermissionRequired(
       const GURL& url,
       const net::IPAddress& ip_address,
-      const absl::optional<std::string>& private_network_device_id,
-      const absl::optional<std::string>& private_network_device_name,
+      const std::optional<std::string>& private_network_device_id,
+      const std::optional<std::string>& private_network_device_name,
       OnPrivateNetworkAccessPermissionRequiredCallback callback) override;
   void OnClearSiteData(
       const GURL& url,
       const std::string& header_value,
       int load_flags,
-      const absl::optional<net::CookiePartitionKey>& cookie_partition_key,
+      const std::optional<net::CookiePartitionKey>& cookie_partition_key,
       bool partitioned_state_allowed_only,
       OnClearSiteDataCallback callback) override;
   void OnLoadingStateUpdate(network::mojom::LoadInfoPtr info,
diff --git a/remoting/client/display/gl_renderer.h b/remoting/client/display/gl_renderer.h
index 334e353..a6341d7a 100644
--- a/remoting/client/display/gl_renderer.h
+++ b/remoting/client/display/gl_renderer.h
@@ -7,6 +7,7 @@
 
 #include <vector>
 
+#include <optional>
 #include "base/containers/queue.h"
 #include "base/functional/callback.h"
 #include "base/memory/weak_ptr.h"
@@ -15,7 +16,6 @@
 #include "remoting/client/display/gl_cursor_feedback.h"
 #include "remoting/client/display/gl_desktop.h"
 #include "remoting/proto/control.pb.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace webrtc {
 class DesktopFrame;
@@ -139,7 +139,7 @@
   std::unique_ptr<Canvas> canvas_;
 
   // Used to recover the transformation matrix when the canvas is recreated.
-  absl::optional<std::array<float, 9>> transformation_matrix_;
+  std::optional<std::array<float, 9>> transformation_matrix_;
 
   GlCursor cursor_;
   GlCursorFeedback cursor_feedback_;
diff --git a/remoting/client/jni/jni_notification_presenter.cc b/remoting/client/jni/jni_notification_presenter.cc
index 87d8381..3ac3ef8 100644
--- a/remoting/client/jni/jni_notification_presenter.cc
+++ b/remoting/client/jni/jni_notification_presenter.cc
@@ -49,7 +49,7 @@
 }
 
 void JniNotificationPresenter::OnNotificationFetched(
-    absl::optional<NotificationMessage> notification) {
+    std::optional<NotificationMessage> notification) {
   DCHECK(sequence_->RunsTasksInCurrentSequence());
   JNIEnv* env = base::android::AttachCurrentThread();
   auto java_presenter = java_presenter_.get(env);
diff --git a/remoting/client/jni/jni_notification_presenter.h b/remoting/client/jni/jni_notification_presenter.h
index cfb35ddd..a30d3c0 100644
--- a/remoting/client/jni/jni_notification_presenter.h
+++ b/remoting/client/jni/jni_notification_presenter.h
@@ -7,11 +7,11 @@
 
 #include <jni.h>
 
+#include <optional>
 #include "base/android/jni_weak_ref.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/task/sequenced_task_runner.h"
 #include "remoting/client/notification/notification_client.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -31,7 +31,7 @@
   void Destroy(JNIEnv* env);
 
  private:
-  void OnNotificationFetched(absl::optional<NotificationMessage> notification);
+  void OnNotificationFetched(std::optional<NotificationMessage> notification);
 
   JavaObjectWeakGlobalRef java_presenter_;
   NotificationClient notification_client_;
diff --git a/remoting/client/notification/gstatic_json_fetcher.cc b/remoting/client/notification/gstatic_json_fetcher.cc
index 5213dd31..47c2bfe0 100644
--- a/remoting/client/notification/gstatic_json_fetcher.cc
+++ b/remoting/client/notification/gstatic_json_fetcher.cc
@@ -20,9 +20,9 @@
 
 constexpr char kGstaticUrlPrefix[] = "https://www.gstatic.com/chromoting/";
 
-absl::optional<base::Value> GetResponse(std::unique_ptr<std::string> body) {
+std::optional<base::Value> GetResponse(std::unique_ptr<std::string> body) {
   if (!body)
-    return absl::nullopt;
+    return std::nullopt;
 
   return base::JSONReader::Read(*body);
 }
diff --git a/remoting/client/notification/json_fetcher.h b/remoting/client/notification/json_fetcher.h
index 0475344..7dfbf86 100644
--- a/remoting/client/notification/json_fetcher.h
+++ b/remoting/client/notification/json_fetcher.h
@@ -7,8 +7,8 @@
 
 #include <string>
 
+#include <optional>
 #include "base/functional/callback_forward.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class Value;
@@ -24,14 +24,14 @@
 class JsonFetcher {
  public:
   using FetchJsonFileCallback =
-      base::OnceCallback<void(absl::optional<base::Value>)>;
+      base::OnceCallback<void(std::optional<base::Value>)>;
 
   JsonFetcher() = default;
   virtual ~JsonFetcher() = default;
 
   // |relative_path| is relative to https://www.gstatic.com/chromoting/.
   // Runs |done| with the decoded value if the file is successfully fetched,
-  // otherwise runs |done| with absl::nullopt.
+  // otherwise runs |done| with std::nullopt.
   //
   // Note that the implementation MUST be able to handle concurrent requests and
   // MUST NOT keep |done| after its destructor is called.
diff --git a/remoting/client/notification/notification_client.cc b/remoting/client/notification/notification_client.cc
index 94fbe60..5c9da0b04 100644
--- a/remoting/client/notification/notification_client.cc
+++ b/remoting/client/notification/notification_client.cc
@@ -151,12 +151,12 @@
         out_message_translation_(out_message_translation),
         out_link_translation_(out_link_translation) {}
 
-  void OnMessageTranslationsFetched(absl::optional<base::Value> translations) {
+  void OnMessageTranslationsFetched(std::optional<base::Value> translations) {
     is_message_translation_fetched_ = true;
     OnTranslationsFetched(std::move(translations), out_message_translation_);
   }
 
-  void OnLinkTranslationsFetched(absl::optional<base::Value> translations) {
+  void OnLinkTranslationsFetched(std::optional<base::Value> translations) {
     is_link_translation_fetched_ = true;
     OnTranslationsFetched(std::move(translations), out_link_translation_);
   }
@@ -166,7 +166,7 @@
 
   ~MessageAndLinkTextResults() = default;
 
-  void OnTranslationsFetched(absl::optional<base::Value> translations,
+  void OnTranslationsFetched(std::optional<base::Value> translations,
                              std::string* string_to_update) {
     if (!done_) {
       LOG(WARNING) << "Received new translations after some translations have "
@@ -287,16 +287,16 @@
 
 void NotificationClient::OnRulesFetched(const std::string& user_email,
                                         NotificationCallback callback,
-                                        absl::optional<base::Value> rules) {
+                                        std::optional<base::Value> rules) {
   if (!rules) {
     LOG(ERROR) << "Rules not found";
-    std::move(callback).Run(absl::nullopt);
+    std::move(callback).Run(std::nullopt);
     return;
   }
 
   if (!rules->is_list()) {
     LOG(ERROR) << "Rules should be list";
-    std::move(callback).Run(absl::nullopt);
+    std::move(callback).Run(std::nullopt);
     return;
   }
 
@@ -314,10 +314,10 @@
     }
   }
   // No matching rule is found.
-  std::move(callback).Run(absl::nullopt);
+  std::move(callback).Run(std::nullopt);
 }
 
-absl::optional<NotificationMessage> NotificationClient::ParseAndMatchRule(
+std::optional<NotificationMessage> NotificationClient::ParseAndMatchRule(
     const base::Value::Dict& rule,
     const std::string& user_email,
     std::string* out_message_text_filename,
@@ -336,32 +336,32 @@
       !FindKeyAndGet(rule, "link_text", &link_text_filename) ||
       !FindKeyAndGet(rule, "link_url", &link_url) ||
       !FindKeyAndGet(rule, "percent", &percent)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (should_ignore_dev_messages_) {
     bool is_dev_mode;
     if (FindKeyAndGet(rule, "dev_mode", &is_dev_mode) && is_dev_mode) {
-      return absl::nullopt;
+      return std::nullopt;
     }
   }
 
   if (target_platform != current_platform_) {
     VLOG(1) << "Notification ignored. Target platform: " << target_platform
             << "; current platform: " << current_platform_;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   VersionRange version_range(version_spec_string);
   if (!version_range.IsValid()) {
     LOG(ERROR) << "Invalid version range: " << version_spec_string;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (!version_range.ContainsVersion(current_version_)) {
     VLOG(1) << "Current version " << current_version_ << " not in range "
             << version_spec_string;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // OS version check is not performed if |os_version| is not specified.
@@ -370,21 +370,21 @@
     VersionRange os_version_range(os_version_spec_string);
     if (!os_version_range.IsValid()) {
       LOG(ERROR) << "Invalid OS version range: " << os_version_spec_string;
-      return absl::nullopt;
+      return std::nullopt;
     }
     if (!os_version_range.ContainsVersion(current_os_version_)) {
       VLOG(1) << "Current OS version " << current_os_version_
               << " not in range " << os_version_spec_string;
-      return absl::nullopt;
+      return std::nullopt;
     }
   }
 
   if (!ShouldShowNotificationForUser(user_email, percent)) {
     VLOG(1) << "User is not selected for notification";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
-  auto message = absl::make_optional<NotificationMessage>();
+  auto message = std::make_optional<NotificationMessage>();
   message->message_id = message_id;
   message->link_url = link_url;
   message->allow_silence = false;
@@ -397,9 +397,9 @@
 void NotificationClient::FetchTranslatedTexts(
     const std::string& message_text_filename,
     const std::string& link_text_filename,
-    absl::optional<NotificationMessage> partial_message,
+    std::optional<NotificationMessage> partial_message,
     NotificationCallback done) {
-  // Copy the message into a unique_ptr since moving absl::optional does not
+  // Copy the message into a unique_ptr since moving std::optional does not
   // move the internal storage.
   auto message_copy = std::make_unique<NotificationMessage>(*partial_message);
   std::string* message_text_ptr = &message_copy->message_text;
@@ -408,8 +408,8 @@
       [](std::unique_ptr<NotificationMessage> message,
          NotificationCallback done, bool is_successful) {
         std::move(done).Run(
-            is_successful ? absl::make_optional<NotificationMessage>(*message)
-                          : absl::nullopt);
+            is_successful ? std::make_optional<NotificationMessage>(*message)
+                          : std::nullopt);
       },
       std::move(message_copy), std::move(done));
   auto results = base::MakeRefCounted<MessageAndLinkTextResults>(
diff --git a/remoting/client/notification/notification_client.h b/remoting/client/notification/notification_client.h
index 6d334cd..149dd787 100644
--- a/remoting/client/notification/notification_client.h
+++ b/remoting/client/notification/notification_client.h
@@ -8,10 +8,10 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/functional/callback_forward.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -23,7 +23,7 @@
 class NotificationClient final {
  public:
   using NotificationCallback =
-      base::OnceCallback<void(absl::optional<NotificationMessage>)>;
+      base::OnceCallback<void(std::optional<NotificationMessage>)>;
 
   explicit NotificationClient(
       scoped_refptr<base::SingleThreadTaskRunner> network_task_runner);
@@ -35,7 +35,7 @@
 
   // Fetches notifications from the server and calls |callback| with the
   // best matched notification. If notifications failed to fetch or no matching
-  // notification is found then absl::nullopt will be returned. |callback| will
+  // notification is found then std::nullopt will be returned. |callback| will
   // be silently dropped if |this| is deleted before the notification is
   // fetched.
   // |user_email| is used to determine if the notification is available to the
@@ -58,12 +58,12 @@
 
   void OnRulesFetched(const std::string& user_email,
                       NotificationCallback callback,
-                      absl::optional<base::Value> rules);
+                      std::optional<base::Value> rules);
 
   // Returns non-empty NotificationMessage if the rule is parsed successfully
   // and the rule should apply to the user. |message_text| and |link_text| will
   // not be set and caller needs to call FetchTranslatedText to fill them up.
-  absl::optional<NotificationMessage> ParseAndMatchRule(
+  std::optional<NotificationMessage> ParseAndMatchRule(
       const base::Value::Dict& rule,
       const std::string& user_email,
       std::string* out_message_text_filename,
@@ -71,7 +71,7 @@
 
   void FetchTranslatedTexts(const std::string& message_text_filename,
                             const std::string& link_text_filename,
-                            absl::optional<NotificationMessage> partial_message,
+                            std::optional<NotificationMessage> partial_message,
                             NotificationCallback done);
 
   std::unique_ptr<JsonFetcher> fetcher_;
diff --git a/remoting/client/notification/notification_client_unittest.cc b/remoting/client/notification/notification_client_unittest.cc
index 671b2060..1013010ab 100644
--- a/remoting/client/notification/notification_client_unittest.cc
+++ b/remoting/client/notification/notification_client_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/memory/ptr_util.h"
 #include "base/memory/raw_ptr.h"
 #include "base/test/mock_callback.h"
@@ -14,7 +15,6 @@
 #include "remoting/client/notification/notification_message.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -33,7 +33,7 @@
  public:
   // GMock doesn't work with rvalue parameters. This works around it.
   MOCK_CONST_METHOD1(FetchJsonFile,
-                     absl::optional<base::Value>(const std::string&));
+                     std::optional<base::Value>(const std::string&));
   void FetchJsonFile(const std::string& relative_path,
                      FetchJsonFileCallback done,
                      const net::NetworkTrafficAnnotationTag&) override {
@@ -250,9 +250,9 @@
   base::Value translation = CreateDefaultTranslations("message");
 
   EXPECT_CALL(*fetcher_, FetchJsonFile("notification/message_text.json"))
-      .WillOnce(ReturnByMove(absl::nullopt));
+      .WillOnce(ReturnByMove(std::nullopt));
   EXPECT_CALL(*fetcher_, FetchJsonFile("notification/link_text.json"))
-      .WillOnce(ReturnByMove(absl::nullopt));
+      .WillOnce(ReturnByMove(std::nullopt));
 
   base::MockCallback<NotificationClient::NotificationCallback> callback;
   EXPECT_CALL(callback, Run(NoMessage()));
diff --git a/remoting/client/notification/version_range.cc b/remoting/client/notification/version_range.cc
index 00fd81e..efec5ac 100644
--- a/remoting/client/notification/version_range.cc
+++ b/remoting/client/notification/version_range.cc
@@ -30,8 +30,8 @@
   size_t dash_pos = range_spec.find('-');
   if (dash_pos == std::string::npos) {
     // May be a single version string.
-    min_version_ = absl::make_optional<base::Version>(range_spec);
-    max_version_ = absl::make_optional<base::Version>(*min_version_);
+    min_version_ = std::make_optional<base::Version>(range_spec);
+    max_version_ = std::make_optional<base::Version>(*min_version_);
     is_min_version_inclusive_ = true;
     is_max_version_inclusive_ = true;
     return;
@@ -60,9 +60,9 @@
     // Unbound min version.
     std::vector<uint32_t> version_components{kUnboundMinVersionNumber};
     min_version_ =
-        absl::make_optional<base::Version>(std::move(version_components));
+        std::make_optional<base::Version>(std::move(version_components));
   } else {
-    min_version_ = absl::make_optional<base::Version>(min_version_string);
+    min_version_ = std::make_optional<base::Version>(min_version_string);
   }
 
   std::string max_version_string = range_spec.substr(dash_pos + 1);
@@ -71,9 +71,9 @@
     // Unbound max version.
     std::vector<uint32_t> version_components{kUnboundMaxVersionNumber};
     max_version_ =
-        absl::make_optional<base::Version>(std::move(version_components));
+        std::make_optional<base::Version>(std::move(version_components));
   } else {
-    max_version_ = absl::make_optional<base::Version>(max_version_string);
+    max_version_ = std::make_optional<base::Version>(max_version_string);
   }
 }
 
diff --git a/remoting/client/notification/version_range.h b/remoting/client/notification/version_range.h
index e61f0f3..ab93fe9 100644
--- a/remoting/client/notification/version_range.h
+++ b/remoting/client/notification/version_range.h
@@ -7,8 +7,8 @@
 
 #include <string>
 
+#include <optional>
 #include "base/version.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -41,8 +41,8 @@
   bool ContainsVersion(const std::string& version_string) const;
 
  private:
-  absl::optional<base::Version> min_version_;
-  absl::optional<base::Version> max_version_;
+  std::optional<base::Version> min_version_;
+  std::optional<base::Version> max_version_;
 
   bool is_min_version_inclusive_ = false;
   bool is_max_version_inclusive_ = false;
diff --git a/remoting/host/base/desktop_environment_options.cc b/remoting/host/base/desktop_environment_options.cc
index 8cedf64..541ef0f 100644
--- a/remoting/host/base/desktop_environment_options.cc
+++ b/remoting/host/base/desktop_environment_options.cc
@@ -7,8 +7,8 @@
 #include <string>
 #include <utility>
 
+#include <optional>
 #include "build/build_config.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -105,13 +105,12 @@
   enable_remote_webauthn_ = enabled;
 }
 
-const absl::optional<size_t>& DesktopEnvironmentOptions::clipboard_size()
-    const {
+const std::optional<size_t>& DesktopEnvironmentOptions::clipboard_size() const {
   return clipboard_size_;
 }
 
 void DesktopEnvironmentOptions::set_clipboard_size(
-    absl::optional<size_t> clipboard_size) {
+    std::optional<size_t> clipboard_size) {
   clipboard_size_ = std::move(clipboard_size);
 }
 
@@ -134,12 +133,12 @@
 void DesktopEnvironmentOptions::ApplySessionOptions(
     const SessionOptions& options) {
   // This field is for test purpose. Usually it should not be set to false.
-  absl::optional<bool> detect_updated_region =
+  std::optional<bool> detect_updated_region =
       options.GetBool("Detect-Updated-Region");
   if (detect_updated_region.has_value()) {
     desktop_capture_options_.set_detect_updated_region(*detect_updated_region);
   }
-  absl::optional<bool> capture_video_on_dedicated_thread =
+  std::optional<bool> capture_video_on_dedicated_thread =
       options.GetBool("Capture-Video-On-Dedicated-Thread");
   if (capture_video_on_dedicated_thread.has_value()) {
     set_capture_video_on_dedicated_thread(*capture_video_on_dedicated_thread);
diff --git a/remoting/host/base/desktop_environment_options.h b/remoting/host/base/desktop_environment_options.h
index d695d1f6..3176586 100644
--- a/remoting/host/base/desktop_environment_options.h
+++ b/remoting/host/base/desktop_environment_options.h
@@ -5,9 +5,9 @@
 #ifndef REMOTING_HOST_BASE_DESKTOP_ENVIRONMENT_OPTIONS_H_
 #define REMOTING_HOST_BASE_DESKTOP_ENVIRONMENT_OPTIONS_H_
 
+#include <optional>
 #include "base/memory/weak_ptr.h"
 #include "remoting/base/session_options.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
 
 namespace remoting {
@@ -50,8 +50,8 @@
   bool enable_remote_webauthn() const;
   void set_enable_remote_webauthn(bool enabled);
 
-  const absl::optional<size_t>& clipboard_size() const;
-  void set_clipboard_size(absl::optional<size_t> clipboard_size);
+  const std::optional<size_t>& clipboard_size() const;
+  void set_clipboard_size(std::optional<size_t> clipboard_size);
 
   const webrtc::DesktopCaptureOptions* desktop_capture_options() const;
   webrtc::DesktopCaptureOptions* desktop_capture_options();
@@ -93,7 +93,7 @@
   // If set, this value is used to constrain the amount of data that can be
   // transferred using ClipboardEvents. A value of 0 will effectively disable
   // clipboard sharing.
-  absl::optional<size_t> clipboard_size_;
+  std::optional<size_t> clipboard_size_;
 
   // True if the video capturer should be run on a dedicated thread.
   bool capture_video_on_dedicated_thread_ = false;
diff --git a/remoting/host/base/screen_controls.h b/remoting/host/base/screen_controls.h
index e339093..4772bda1 100644
--- a/remoting/host/base/screen_controls.h
+++ b/remoting/host/base/screen_controls.h
@@ -5,7 +5,7 @@
 #ifndef REMOTING_HOST_BASE_SCREEN_CONTROLS_H_
 #define REMOTING_HOST_BASE_SCREEN_CONTROLS_H_
 
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include <optional>
 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h"
 
 namespace remoting {
@@ -34,7 +34,7 @@
   // resized).
   virtual void SetScreenResolution(
       const ScreenResolution& resolution,
-      absl::optional<webrtc::ScreenId> screen_id) = 0;
+      std::optional<webrtc::ScreenId> screen_id) = 0;
 
   virtual void SetVideoLayout(const protocol::VideoLayout& video_layout) = 0;
 };
diff --git a/remoting/host/chromeos/file_session_storage.cc b/remoting/host/chromeos/file_session_storage.cc
index 84c458e..4571641cb 100644
--- a/remoting/host/chromeos/file_session_storage.cc
+++ b/remoting/host/chromeos/file_session_storage.cc
@@ -4,6 +4,7 @@
 
 #include "remoting/host/chromeos/file_session_storage.h"
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/functional/callback.h"
@@ -15,7 +16,6 @@
 #include "base/task/thread_pool.h"
 #include "base/values.h"
 #include "chrome/common/chrome_paths.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -24,8 +24,8 @@
 constexpr char kStoredSessionFileName[] = "session";
 
 template <class T>
-absl::optional<T> make_nullopt() {
-  return absl::nullopt;
+std::optional<T> make_nullopt() {
+  return std::nullopt;
 }
 
 base::TaskTraits GetFileTaskTraits() {
@@ -61,19 +61,19 @@
 
 // Wrapper around base::ReadFileToString that returns the result as an optional
 // string.
-absl::optional<std::string> ReadFileToString(const base::FilePath& file) {
+std::optional<std::string> ReadFileToString(const base::FilePath& file) {
   std::string result;
   bool success = base::ReadFileToString(file, &result);
   if (success) {
     return result;
   } else {
-    return absl::nullopt;
+    return std::nullopt;
   }
 }
 
 void ReadFileAsync(
     const base::FilePath& file,
-    base::OnceCallback<void(absl::optional<std::string>)> on_done) {
+    base::OnceCallback<void(std::optional<std::string>)> on_done) {
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, GetFileTaskTraits(), base::BindOnce(&ReadFileToString, file),
       std::move(on_done));
@@ -111,9 +111,9 @@
 }
 
 void FileSessionStorage::RetrieveSession(
-    base::OnceCallback<void(absl::optional<base::Value::Dict>)> on_done) {
+    base::OnceCallback<void(std::optional<base::Value::Dict>)> on_done) {
   ReadFileAsync(session_file(),
-                base::BindOnce([](absl::optional<std::string> content) {
+                base::BindOnce([](std::optional<std::string> content) {
                   if (!content.has_value()) {
                     LOG(ERROR) << "Failed to read CRD session information file";
                     return make_nullopt<base::Value::Dict>();
diff --git a/remoting/host/chromeos/file_session_storage.h b/remoting/host/chromeos/file_session_storage.h
index 5fcafd8a..f04ccdc3 100644
--- a/remoting/host/chromeos/file_session_storage.h
+++ b/remoting/host/chromeos/file_session_storage.h
@@ -31,7 +31,7 @@
                     base::OnceClosure on_done) override;
   void DeleteSession(base::OnceClosure on_done) override;
   void RetrieveSession(
-      base::OnceCallback<void(absl::optional<base::Value::Dict>)> on_done)
+      base::OnceCallback<void(std::optional<base::Value::Dict>)> on_done)
       override;
   void HasSession(base::OnceCallback<void(bool)> on_done) const override;
 
diff --git a/remoting/host/chromeos/file_session_storage_unittest.cc b/remoting/host/chromeos/file_session_storage_unittest.cc
index 752e6e9..89be890a 100644
--- a/remoting/host/chromeos/file_session_storage_unittest.cc
+++ b/remoting/host/chromeos/file_session_storage_unittest.cc
@@ -4,12 +4,12 @@
 
 #include "remoting/host/chromeos/file_session_storage.h"
 
+#include <optional>
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_future.h"
 #include "base/test/values_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -44,8 +44,8 @@
     ASSERT_TRUE(done_signal.Wait());
   }
 
-  absl::optional<base::Value::Dict> RetrieveSession() {
-    TestFuture<absl::optional<base::Value::Dict>> done_signal;
+  std::optional<base::Value::Dict> RetrieveSession() {
+    TestFuture<std::optional<base::Value::Dict>> done_signal;
     storage().RetrieveSession(done_signal.GetCallback());
     return done_signal.Take();
   }
@@ -80,7 +80,7 @@
 
 TEST_F(FileSessionStorageTest,
        RetrieveSessionShouldReturnNullIfNoSessionIsStored) {
-  EXPECT_EQ(RetrieveSession(), absl::nullopt);
+  EXPECT_EQ(RetrieveSession(), std::nullopt);
 }
 
 TEST_F(FileSessionStorageTest,
@@ -90,7 +90,7 @@
 
   StoreSession(session_information);
 
-  absl::optional<base::Value::Dict> result = RetrieveSession();
+  std::optional<base::Value::Dict> result = RetrieveSession();
   ASSERT_TRUE(result.has_value());
   EXPECT_THAT(result.value(), base::test::IsJson(session_information));
 }
diff --git a/remoting/host/chromeos/frame_sink_desktop_capturer.h b/remoting/host/chromeos/frame_sink_desktop_capturer.h
index cedb3776..da59c5d 100644
--- a/remoting/host/chromeos/frame_sink_desktop_capturer.h
+++ b/remoting/host/chromeos/frame_sink_desktop_capturer.h
@@ -5,12 +5,12 @@
 #ifndef REMOTING_HOST_CHROMEOS_FRAME_SINK_DESKTOP_CAPTURER_H_
 #define REMOTING_HOST_CHROMEOS_FRAME_SINK_DESKTOP_CAPTURER_H_
 
+#include <optional>
 #include "base/memory/raw_ref.h"
 #include "base/memory/weak_ptr.h"
 #include "components/viz/host/client_frame_sink_video_capturer.h"
 #include "remoting/host/chromeos/ash_mojom_video_consumer.h"
 #include "remoting/host/chromeos/ash_proxy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
 #include "ui/aura/scoped_window_capture_request.h"
 #include "ui/display/display.h"
@@ -43,7 +43,7 @@
   const display::Display* GetSourceDisplay();
 
  private:
-  absl::optional<viz::ClientFrameSinkVideoCapturer> video_capturer_;
+  std::optional<viz::ClientFrameSinkVideoCapturer> video_capturer_;
   const raw_ref<AshProxy, ExperimentalAsh> ash_;
   AshMojomVideoConsumer video_consumer_;
   raw_ptr<DesktopCapturer::Callback> callback_ = nullptr;
diff --git a/remoting/host/chromeos/frame_sink_desktop_capturer_unittest.cc b/remoting/host/chromeos/frame_sink_desktop_capturer_unittest.cc
index f7a92eb..0d97f85 100644
--- a/remoting/host/chromeos/frame_sink_desktop_capturer_unittest.cc
+++ b/remoting/host/chromeos/frame_sink_desktop_capturer_unittest.cc
@@ -203,7 +203,7 @@
 
   MOCK_METHOD(void,
               ChangeTarget,
-              (const absl::optional<viz::VideoCaptureTarget>& target,
+              (const std::optional<viz::VideoCaptureTarget>& target,
                uint32_t sub_capture_target_version));
 
   MOCK_METHOD(void,
@@ -416,7 +416,7 @@
   AddMultipleDisplays();
 
   DisplayId primary_display_id = ash_proxy().GetPrimaryDisplayId();
-  const auto expected_target = absl::optional<viz::VideoCaptureTarget>(
+  const auto expected_target = std::optional<viz::VideoCaptureTarget>(
       ash_proxy().GetFrameSinkId(primary_display_id));
 
   EXPECT_CALL(video_capturer_, ChangeTarget(expected_target, 0));
@@ -574,7 +574,7 @@
   Size size(234, 56);
 
   StartCapturerForTesting();
-  const absl::optional<viz::VideoCaptureTarget> expected_target(
+  const std::optional<viz::VideoCaptureTarget> expected_target(
       ash_proxy().GetFrameSinkId(new_display_id));
 
   EXPECT_CALL(video_capturer_, ChangeTarget(expected_target, 0));
diff --git a/remoting/host/chromeos/mouse_cursor_monitor_aura.cc b/remoting/host/chromeos/mouse_cursor_monitor_aura.cc
index 14e2ea6..f52f463 100644
--- a/remoting/host/chromeos/mouse_cursor_monitor_aura.cc
+++ b/remoting/host/chromeos/mouse_cursor_monitor_aura.cc
@@ -6,12 +6,12 @@
 
 #include <utility>
 
+#include <optional>
 #include "ash/shell.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/location.h"
 #include "remoting/host/chromeos/skia_bitmap_desktop_frame.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
 #include "ui/aura/client/cursor_shape_client.h"
@@ -74,7 +74,7 @@
     return;
   }
 
-  absl::optional<ui::CursorData> cursor_data =
+  std::optional<ui::CursorData> cursor_data =
       aura::client::GetCursorShapeClient().GetCursorData(cursor);
   if (!cursor_data) {
     LOG(ERROR) << "Failed to load bitmap for cursor type: " << cursor.type();
diff --git a/remoting/host/chromeos/remote_support_host_ash.cc b/remoting/host/chromeos/remote_support_host_ash.cc
index 00787d55..7e61755 100644
--- a/remoting/host/chromeos/remote_support_host_ash.cc
+++ b/remoting/host/chromeos/remote_support_host_ash.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 #include <utility>
 
+#include <optional>
 #include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
@@ -24,7 +25,6 @@
 #include "remoting/host/it2me/it2me_native_messaging_host_ash.h"
 #include "remoting/host/it2me/reconnect_params.h"
 #include "remoting/host/policy_watcher.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -123,15 +123,15 @@
 
 void RemoteSupportHostAsh::StartSession(
     const mojom::SupportSessionParams& params,
-    const absl::optional<ChromeOsEnterpriseParams>& enterprise_params,
+    const std::optional<ChromeOsEnterpriseParams>& enterprise_params,
     StartSessionCallback callback) {
-  StartSession(params, enterprise_params, absl::nullopt, std::move(callback));
+  StartSession(params, enterprise_params, std::nullopt, std::move(callback));
 }
 
 void RemoteSupportHostAsh::StartSession(
     const mojom::SupportSessionParams& params,
-    const absl::optional<ChromeOsEnterpriseParams>& enterprise_params,
-    const absl::optional<ReconnectParams>& reconnect_params,
+    const std::optional<ChromeOsEnterpriseParams>& enterprise_params,
+    const std::optional<ReconnectParams>& reconnect_params,
     StartSessionCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -230,8 +230,8 @@
 
 void RemoteSupportHostAsh::OnHostStateConnected(
     mojom::SupportSessionParams session_params,
-    absl::optional<ChromeOsEnterpriseParams> enterprise_params,
-    absl::optional<ReconnectParams> reconnect_params) {
+    std::optional<ChromeOsEnterpriseParams> enterprise_params,
+    std::optional<ReconnectParams> reconnect_params) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!base::FeatureList::IsEnabled(kEnableCrdAdminRemoteAccessV2)) {
diff --git a/remoting/host/chromeos/remote_support_host_ash.h b/remoting/host/chromeos/remote_support_host_ash.h
index e56c507c..28fbe7e 100644
--- a/remoting/host/chromeos/remote_support_host_ash.h
+++ b/remoting/host/chromeos/remote_support_host_ash.h
@@ -6,6 +6,7 @@
 #define REMOTING_HOST_CHROMEOS_REMOTE_SUPPORT_HOST_ASH_H_
 
 #include <memory>
+#include <optional>
 #include "base/functional/callback.h"
 #include "base/memory/raw_ref.h"
 #include "base/memory/scoped_refptr.h"
@@ -14,7 +15,6 @@
 #include "remoting/host/chromeos/session_id.h"
 #include "remoting/host/it2me/it2me_native_messaging_host_ash.h"
 #include "remoting/host/mojom/remote_support.mojom-forward.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -56,7 +56,7 @@
   // called with the result.
   void StartSession(
       const mojom::SupportSessionParams& params,
-      const absl::optional<ChromeOsEnterpriseParams>& enterprise_params,
+      const std::optional<ChromeOsEnterpriseParams>& enterprise_params,
       StartSessionCallback callback);
 
   // Allows the caller to resume the given remote support session.
@@ -68,13 +68,13 @@
  private:
   void StartSession(
       const mojom::SupportSessionParams& params,
-      const absl::optional<ChromeOsEnterpriseParams>& enterprise_params,
-      const absl::optional<ReconnectParams>& reconnect_params,
+      const std::optional<ChromeOsEnterpriseParams>& enterprise_params,
+      const std::optional<ReconnectParams>& reconnect_params,
       StartSessionCallback callback);
 
   void OnHostStateConnected(mojom::SupportSessionParams,
-                            absl::optional<ChromeOsEnterpriseParams>,
-                            absl::optional<ReconnectParams>);
+                            std::optional<ChromeOsEnterpriseParams>,
+                            std::optional<ReconnectParams>);
   void OnHostStateDisconnected();
   void OnSessionDisconnected();
 
diff --git a/remoting/host/chromeos/remote_support_host_ash_unittest.cc b/remoting/host/chromeos/remote_support_host_ash_unittest.cc
index 76f9e59..8828101 100644
--- a/remoting/host/chromeos/remote_support_host_ash_unittest.cc
+++ b/remoting/host/chromeos/remote_support_host_ash_unittest.cc
@@ -188,12 +188,12 @@
     std::move(on_done).Run();
   }
   void RetrieveSession(
-      base::OnceCallback<void(absl::optional<base::Value::Dict>)> on_done)
+      base::OnceCallback<void(std::optional<base::Value::Dict>)> on_done)
       override {
     if (session_.has_value()) {
       std::move(on_done).Run(session_.value().Clone());
     } else {
-      std::move(on_done).Run(absl::nullopt);
+      std::move(on_done).Run(std::nullopt);
     }
   }
   void HasSession(base::OnceCallback<void(bool)> on_done) const override {
@@ -201,7 +201,7 @@
   }
 
  private:
-  absl::optional<base::Value::Dict> session_;
+  std::optional<base::Value::Dict> session_;
 };
 
 bool HasSession(SessionStorage& storage) {
@@ -231,13 +231,13 @@
   }
 
   mojom::StartSupportSessionResponsePtr StartSession(
-      absl::optional<ChromeOsEnterpriseParams> enterprise_params) {
+      std::optional<ChromeOsEnterpriseParams> enterprise_params) {
     return StartSession(GetSupportSessionParams(), enterprise_params);
   }
 
   mojom::StartSupportSessionResponsePtr StartSession(
       const mojom::SupportSessionParams& params,
-      absl::optional<ChromeOsEnterpriseParams> enterprise_params) {
+      std::optional<ChromeOsEnterpriseParams> enterprise_params) {
     TestFuture<mojom::StartSupportSessionResponsePtr> connect_result;
     support_host().StartSession(params, enterprise_params,
                                 connect_result.GetCallback());
@@ -468,7 +468,7 @@
        ShouldNotStoreSessionInfoIfEnterpriseParamsAreUnset) {
   EnableFeature(kEnableCrdAdminRemoteAccessV2);
 
-  StartSession(absl::nullopt);
+  StartSession(std::nullopt);
   SignalHostStateConnected();
 
   ASSERT_FALSE(HasSession(session_storage()));
@@ -681,7 +681,7 @@
   it2me_host().WaitForConnectCall();
   ASSERT_TRUE(HasSession(session_storage()));
 
-  StartSession(/*enterprise_params=*/absl::nullopt);
+  StartSession(/*enterprise_params=*/std::nullopt);
 
   EXPECT_FALSE(HasSession(session_storage()));
 }
diff --git a/remoting/host/chromeos/remoting_service.cc b/remoting/host/chromeos/remoting_service.cc
index 5d02251..72c2bbc 100644
--- a/remoting/host/chromeos/remoting_service.cc
+++ b/remoting/host/chromeos/remoting_service.cc
@@ -7,11 +7,11 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "base/no_destructor.h"
 #include "base/sequence_checker.h"
 #include "remoting/host/chromeos/file_session_storage.h"
 #include "remoting/host/chromeos/remote_support_host_ash.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -62,8 +62,8 @@
 
   session_storage_.HasSession(  //
       base::BindOnce([](bool has_session) {
-        return has_session ? absl::make_optional(kEnterpriseSessionId)
-                           : absl::nullopt;
+        return has_session ? std::make_optional(kEnterpriseSessionId)
+                           : std::nullopt;
       }).Then(std::move(callback)));
 }
 
diff --git a/remoting/host/chromeos/remoting_service.h b/remoting/host/chromeos/remoting_service.h
index 5ea9fc32..f5b0a28c 100644
--- a/remoting/host/chromeos/remoting_service.h
+++ b/remoting/host/chromeos/remoting_service.h
@@ -5,9 +5,9 @@
 #ifndef REMOTING_HOST_CHROMEOS_REMOTING_SERVICE_H_
 #define REMOTING_HOST_CHROMEOS_REMOTING_SERVICE_H_
 
+#include <optional>
 #include "base/functional/callback_forward.h"
 #include "remoting/host/chromeos/session_id.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class FilePath;
@@ -24,7 +24,7 @@
 // which is bound to the Main/UI sequence in production code.
 class RemotingService {
  public:
-  using SessionIdCallback = base::OnceCallback<void(absl::optional<SessionId>)>;
+  using SessionIdCallback = base::OnceCallback<void(std::optional<SessionId>)>;
 
   static RemotingService& Get();
   virtual ~RemotingService() = default;
@@ -33,7 +33,7 @@
   virtual RemoteSupportHostAsh& GetSupportHost() = 0;
 
   // Allows the caller to query if information about a reconnectable session is
-  // stored. Invokes `callback` with the id of this session (or absl::nullopt if
+  // stored. Invokes `callback` with the id of this session (or std::nullopt if
   // there is no reconnectable session).
   virtual void GetReconnectableEnterpriseSessionId(
       SessionIdCallback callback) = 0;
diff --git a/remoting/host/chromeos/remoting_service_unittest.cc b/remoting/host/chromeos/remoting_service_unittest.cc
index ac9b42dd..7f9b590a 100644
--- a/remoting/host/chromeos/remoting_service_unittest.cc
+++ b/remoting/host/chromeos/remoting_service_unittest.cc
@@ -57,19 +57,19 @@
        ShouldReturnNoSessionIdIdIfThereIsNoReconnectableSession) {
   EnsureNoReconnectableSession();
 
-  TestFuture<absl::optional<SessionId>> future;
+  TestFuture<std::optional<SessionId>> future;
   remoting_service().GetReconnectableEnterpriseSessionId(future.GetCallback());
-  absl::optional<SessionId> result = future.Take();
+  std::optional<SessionId> result = future.Take();
 
-  EXPECT_EQ(result, absl::nullopt);
+  EXPECT_EQ(result, std::nullopt);
 }
 
 TEST_F(RemotingServiceTest, ShouldReturnEnterpriseSessionIdIfSessionIsStored) {
   CreateReconnectableSession();
 
-  TestFuture<absl::optional<SessionId>> future;
+  TestFuture<std::optional<SessionId>> future;
   remoting_service().GetReconnectableEnterpriseSessionId(future.GetCallback());
-  absl::optional<SessionId> result = future.Take();
+  std::optional<SessionId> result = future.Take();
 
   EXPECT_EQ(result, kEnterpriseSessionId);
 }
diff --git a/remoting/host/chromeos/session_storage.h b/remoting/host/chromeos/session_storage.h
index 1bb84041..eb8492d 100644
--- a/remoting/host/chromeos/session_storage.h
+++ b/remoting/host/chromeos/session_storage.h
@@ -5,9 +5,9 @@
 #ifndef REMOTING_HOST_CHROMEOS_SESSION_STORAGE_H_
 #define REMOTING_HOST_CHROMEOS_SESSION_STORAGE_H_
 
+#include <optional>
 #include "base/functional/callback_forward.h"
 #include "base/values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -21,7 +21,7 @@
                             base::OnceClosure on_done) = 0;
   virtual void DeleteSession(base::OnceClosure on_done) = 0;
   virtual void RetrieveSession(
-      base::OnceCallback<void(absl::optional<base::Value::Dict>)> on_done) = 0;
+      base::OnceCallback<void(std::optional<base::Value::Dict>)> on_done) = 0;
 
   virtual void HasSession(base::OnceCallback<void(bool)> on_done) const = 0;
 };
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc
index a4036921..ed97e946 100644
--- a/remoting/host/client_session.cc
+++ b/remoting/host/client_session.cc
@@ -8,6 +8,7 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/containers/contains.h"
 #include "base/containers/cxx20_erase_map.h"
@@ -54,7 +55,6 @@
 #include "remoting/protocol/session.h"
 #include "remoting/protocol/session_config.h"
 #include "remoting/protocol/video_frame_pump.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
 
 #if defined(WEBRTC_USE_GIO)
@@ -165,7 +165,7 @@
 
   // Try to match the client's resolution.
   ScreenResolution screen_resolution(client_size, dpi_vector);
-  absl::optional<webrtc::ScreenId> screen_id;
+  std::optional<webrtc::ScreenId> screen_id;
   if (resolution.has_screen_id()) {
     screen_id = resolution.screen_id();
   }
@@ -462,8 +462,8 @@
   if (!connection_->peer_connection_controls()) {
     return;
   }
-  absl::optional<int> min_bitrate_bps;
-  absl::optional<int> max_bitrate_bps;
+  std::optional<int> min_bitrate_bps;
+  std::optional<int> max_bitrate_bps;
   bool set_preferred_bitrates = false;
   if (parameters.has_preferred_min_bitrate_bps()) {
     min_bitrate_bps = parameters.preferred_min_bitrate_bps();
diff --git a/remoting/host/crash/crash_file_uploader.cc b/remoting/host/crash/crash_file_uploader.cc
index f6af87d..5b7edc0 100644
--- a/remoting/host/crash/crash_file_uploader.cc
+++ b/remoting/host/crash/crash_file_uploader.cc
@@ -127,7 +127,7 @@
     return false;
   }
 
-  absl::optional<base::Value::Dict> opt_metadata =
+  std::optional<base::Value::Dict> opt_metadata =
       base::JSONReader::ReadDict(metadata_file_contents);
   if (!opt_metadata.has_value()) {
     error_reason = "Failed to parse metadata file contents";
diff --git a/remoting/host/daemon_process_win.cc b/remoting/host/daemon_process_win.cc
index 55a62c2..8208d1a 100644
--- a/remoting/host/daemon_process_win.cc
+++ b/remoting/host/daemon_process_win.cc
@@ -10,6 +10,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/functional/bind.h"
@@ -51,7 +52,6 @@
 #include "remoting/host/win/security_descriptor.h"
 #include "remoting/host/win/unprivileged_process_delegate.h"
 #include "remoting/host/win/worker_process_launcher.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 using base::win::ScopedHandle;
 
@@ -296,7 +296,7 @@
   LOG_IF(ERROR, !remoting_host_control_.is_connected())
       << "IPC channel not connected. HostConfig message will be dropped.";
 
-  absl::optional<base::Value::Dict> config(
+  std::optional<base::Value::Dict> config(
       HostConfigFromJson(serialized_config));
   if (!config.has_value()) {
     LOG(ERROR) << "Invalid host config, shutting down.";
diff --git a/remoting/host/desktop_display_layout_util_unittest.cc b/remoting/host/desktop_display_layout_util_unittest.cc
index a0ae4be..cc79480e3 100644
--- a/remoting/host/desktop_display_layout_util_unittest.cc
+++ b/remoting/host/desktop_display_layout_util_unittest.cc
@@ -6,10 +6,10 @@
 
 #include <vector>
 
+#include <optional>
 #include "build/build_config.h"
 #include "remoting/proto/control.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
 
@@ -49,7 +49,7 @@
     int height,
     int x_dpi,
     int y_dpi,
-    absl::optional<webrtc::ScreenId> screen_id) {
+    std::optional<webrtc::ScreenId> screen_id) {
   protocol::VideoTrackLayout layout;
   if (screen_id) {
     layout.set_screen_id(*screen_id);
diff --git a/remoting/host/desktop_session_agent.cc b/remoting/host/desktop_session_agent.cc
index 99534c2f..485e6b9 100644
--- a/remoting/host/desktop_session_agent.cc
+++ b/remoting/host/desktop_session_agent.cc
@@ -729,7 +729,7 @@
   CHECK(started_);
 
   if (screen_controls_) {
-    screen_controls_->SetScreenResolution(resolution, absl::nullopt);
+    screen_controls_->SetScreenResolution(resolution, std::nullopt);
   }
 }
 
diff --git a/remoting/host/desktop_session_agent.h b/remoting/host/desktop_session_agent.h
index bf71e19..f150027 100644
--- a/remoting/host/desktop_session_agent.h
+++ b/remoting/host/desktop_session_agent.h
@@ -11,6 +11,7 @@
 #include <map>
 #include <memory>
 
+#include <optional>
 #include "base/compiler_specific.h"
 #include "base/functional/callback.h"
 #include "base/memory/read_only_shared_memory_region.h"
@@ -30,7 +31,6 @@
 #include "remoting/host/mojom/remoting_mojom_traits.h"
 #include "remoting/proto/url_forwarder_control.pb.h"
 #include "remoting/protocol/clipboard_stub.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
 #include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
@@ -252,7 +252,7 @@
 
   // Routes file-transfer messages to the corresponding reader/writer to be
   // executed.
-  absl::optional<SessionFileOperationsHandler> session_file_operations_handler_;
+  std::optional<SessionFileOperationsHandler> session_file_operations_handler_;
 
   mojo::AssociatedRemote<mojom::DesktopSessionEventHandler>
       desktop_session_event_handler_;
diff --git a/remoting/host/desktop_session_proxy.cc b/remoting/host/desktop_session_proxy.cc
index be54372..caaffff 100644
--- a/remoting/host/desktop_session_proxy.cc
+++ b/remoting/host/desktop_session_proxy.cc
@@ -413,7 +413,7 @@
   keyboard_layout_monitor_ = std::move(keyboard_layout_monitor);
 }
 
-const absl::optional<protocol::KeyboardLayout>&
+const std::optional<protocol::KeyboardLayout>&
 DesktopSessionProxy::GetKeyboardCurrentLayout() const {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
diff --git a/remoting/host/desktop_session_proxy.h b/remoting/host/desktop_session_proxy.h
index a2a3a97..7705719 100644
--- a/remoting/host/desktop_session_proxy.h
+++ b/remoting/host/desktop_session_proxy.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/callback_list.h"
 #include "base/functional/callback.h"
 #include "base/memory/read_only_shared_memory_region.h"
@@ -36,7 +37,6 @@
 #include "remoting/protocol/clipboard_stub.h"
 #include "remoting/protocol/desktop_capturer.h"
 #include "remoting/protocol/errors.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
 
 namespace base {
@@ -155,7 +155,7 @@
   // changes. Called on the |caller_task_runner_| thread.
   void SetKeyboardLayoutMonitor(
       const base::WeakPtr<IpcKeyboardLayoutMonitor>& keyboard_layout_monitor);
-  const absl::optional<protocol::KeyboardLayout>& GetKeyboardCurrentLayout()
+  const std::optional<protocol::KeyboardLayout>& GetKeyboardCurrentLayout()
       const;
 
   // APIs used to implement the InputInjector interface.
@@ -302,7 +302,7 @@
 
   // Caches the last keyboard layout received so it can be provided when Start
   // is called on IpcKeyboardLayoutMonitor.
-  absl::optional<protocol::KeyboardLayout> keyboard_layout_;
+  std::optional<protocol::KeyboardLayout> keyboard_layout_;
 
   // Used to notify registered handlers when the IPC channel is disconnected.
   base::OnceClosureList disconnect_handlers_;
diff --git a/remoting/host/fake_desktop_environment.cc b/remoting/host/fake_desktop_environment.cc
index 246a4e99..af1e2dcc 100644
--- a/remoting/host/fake_desktop_environment.cc
+++ b/remoting/host/fake_desktop_environment.cc
@@ -65,7 +65,7 @@
 
 void FakeScreenControls::SetScreenResolution(
     const ScreenResolution& resolution,
-    absl::optional<webrtc::ScreenId> screen_id) {}
+    std::optional<webrtc::ScreenId> screen_id) {}
 
 void FakeScreenControls::SetVideoLayout(
     const protocol::VideoLayout& video_layout) {}
diff --git a/remoting/host/fake_desktop_environment.h b/remoting/host/fake_desktop_environment.h
index 5aa4012..8ef609af 100644
--- a/remoting/host/fake_desktop_environment.h
+++ b/remoting/host/fake_desktop_environment.h
@@ -76,7 +76,7 @@
 
   // ScreenControls implementation.
   void SetScreenResolution(const ScreenResolution& resolution,
-                           absl::optional<webrtc::ScreenId> screen_id) override;
+                           std::optional<webrtc::ScreenId> screen_id) override;
   void SetVideoLayout(const protocol::VideoLayout& video_layout) override;
 };
 
diff --git a/remoting/host/file_transfer/buffered_file_writer_unittest.cc b/remoting/host/file_transfer/buffered_file_writer_unittest.cc
index 0a269d1..9dce784 100644
--- a/remoting/host/file_transfer/buffered_file_writer_unittest.cc
+++ b/remoting/host/file_transfer/buffered_file_writer_unittest.cc
@@ -35,7 +35,7 @@
   void OnError(protocol::FileTransfer_Error error);
 
   bool complete_called_ = false;
-  absl::optional<protocol::FileTransfer_Error> error_ = absl::nullopt;
+  std::optional<protocol::FileTransfer_Error> error_ = std::nullopt;
 
   base::test::TaskEnvironment task_environment_;
 };
diff --git a/remoting/host/file_transfer/fake_file_operations.cc b/remoting/host/file_transfer/fake_file_operations.cc
index cbd2690..f3be31b 100644
--- a/remoting/host/file_transfer/fake_file_operations.cc
+++ b/remoting/host/file_transfer/fake_file_operations.cc
@@ -93,7 +93,7 @@
 FakeFileOperations::InputFile::InputFile(
     base::FilePath filename,
     std::vector<std::uint8_t> data,
-    absl::optional<protocol::FileTransfer_Error> io_error)
+    std::optional<protocol::FileTransfer_Error> io_error)
     : filename(std::move(filename)),
       data(std::move(data)),
       io_error(std::move(io_error)) {}
diff --git a/remoting/host/file_transfer/fake_file_operations.h b/remoting/host/file_transfer/fake_file_operations.h
index 024e3ee..e619060 100644
--- a/remoting/host/file_transfer/fake_file_operations.h
+++ b/remoting/host/file_transfer/fake_file_operations.h
@@ -9,11 +9,11 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/memory/raw_ptr.h"
 #include "remoting/host/file_transfer/file_operations.h"
 #include "remoting/proto/file_transfer.pb.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -46,7 +46,7 @@
     InputFile();
     InputFile(base::FilePath filename,
               std::vector<std::uint8_t> data,
-              absl::optional<protocol::FileTransfer_Error> io_error);
+              std::optional<protocol::FileTransfer_Error> io_error);
     InputFile(const InputFile& other);
     InputFile(InputFile&& other);
     InputFile& operator=(const InputFile&);
@@ -61,7 +61,7 @@
 
     // If set, this error will be returned instead of EOF once the provided data
     // has been read.
-    absl::optional<protocol::FileTransfer_Error> io_error;
+    std::optional<protocol::FileTransfer_Error> io_error;
   };
 
   // Used to interact with FakeFileOperations after ownership is passed
@@ -79,7 +79,7 @@
     std::vector<OutputFile> files_written;
 
     // If set, file operations will return this error.
-    absl::optional<protocol::FileTransfer_Error> io_error = absl::nullopt;
+    std::optional<protocol::FileTransfer_Error> io_error = std::nullopt;
   };
 
   explicit FakeFileOperations(TestIo* test_io);
diff --git a/remoting/host/file_transfer/file_transfer_message_handler.h b/remoting/host/file_transfer/file_transfer_message_handler.h
index 118a454..66356864 100644
--- a/remoting/host/file_transfer/file_transfer_message_handler.h
+++ b/remoting/host/file_transfer/file_transfer_message_handler.h
@@ -10,13 +10,13 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/containers/queue.h"
 #include "base/memory/weak_ptr.h"
 #include "remoting/host/file_transfer/buffered_file_writer.h"
 #include "remoting/host/file_transfer/file_operations.h"
 #include "remoting/protocol/file_transfer_helpers.h"
 #include "remoting/protocol/named_message_pipe_handler.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -84,7 +84,7 @@
 
   State state_ = kConnected;
   std::unique_ptr<FileOperations> file_operations_;
-  absl::optional<BufferedFileWriter> buffered_file_writer_;
+  std::optional<BufferedFileWriter> buffered_file_writer_;
   std::unique_ptr<FileOperations::Reader> file_reader_;
   std::size_t queued_chunks_ = 0;
   base::WeakPtrFactory<FileTransferMessageHandler> weak_ptr_factory_{this};
diff --git a/remoting/host/file_transfer/file_transfer_message_handler_unittest.cc b/remoting/host/file_transfer/file_transfer_message_handler_unittest.cc
index 6e8475f4..606223e6 100644
--- a/remoting/host/file_transfer/file_transfer_message_handler_unittest.cc
+++ b/remoting/host/file_transfer/file_transfer_message_handler_unittest.cc
@@ -350,7 +350,7 @@
 
   test_io.input_file = FakeFileOperations::InputFile(
       base::FilePath::FromASCII(kTestFilename),
-      ByteArrayFrom(kTestDataOne, kTestDataTwo, kTestDataThree), absl::nullopt);
+      ByteArrayFrom(kTestDataOne, kTestDataTwo, kTestDataThree), std::nullopt);
 
   // This will delete itself when fake_pipe_->ClosePipe() is called.
   new FileTransferMessageHandler(kTestDatachannelName, fake_pipe_->Wrap(),
diff --git a/remoting/host/file_transfer/ipc_file_operations.cc b/remoting/host/file_transfer/ipc_file_operations.cc
index 78f36ad..d2aa8ea 100644
--- a/remoting/host/file_transfer/ipc_file_operations.cc
+++ b/remoting/host/file_transfer/ipc_file_operations.cc
@@ -135,9 +135,9 @@
  private:
   void OnOpenResult(mojom::BeginFileWriteResultPtr result);
   void OnOperationResult(
-      const absl::optional<::remoting::protocol::FileTransfer_Error>& error);
+      const std::optional<::remoting::protocol::FileTransfer_Error>& error);
   void OnCloseResult(
-      const absl::optional<::remoting::protocol::FileTransfer_Error>& error);
+      const std::optional<::remoting::protocol::FileTransfer_Error>& error);
 
   State state_ GUARDED_BY_CONTEXT(sequence_checker_) = kCreated;
   Callback pending_callback_ GUARDED_BY_CONTEXT(sequence_checker_);
@@ -403,7 +403,7 @@
 }
 
 void IpcFileOperations::IpcWriter::OnOperationResult(
-    const absl::optional<::remoting::protocol::FileTransfer_Error>& error) {
+    const std::optional<::remoting::protocol::FileTransfer_Error>& error) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (error) {
@@ -418,7 +418,7 @@
 }
 
 void IpcFileOperations::IpcWriter::OnCloseResult(
-    const absl::optional<::remoting::protocol::FileTransfer_Error>& error) {
+    const std::optional<::remoting::protocol::FileTransfer_Error>& error) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // We're done with the remote regardless of the result.
diff --git a/remoting/host/file_transfer/ipc_file_operations_unittest.cc b/remoting/host/file_transfer/ipc_file_operations_unittest.cc
index a8527883..cb698f95f 100644
--- a/remoting/host/file_transfer/ipc_file_operations_unittest.cc
+++ b/remoting/host/file_transfer/ipc_file_operations_unittest.cc
@@ -72,7 +72,7 @@
   std::vector<base::CallbackListSubscription> disconnect_subscriptions_;
 
   // If set, this will be returned on the next file transfer operation request.
-  absl::optional<protocol::FileTransfer_Error> request_error_;
+  std::optional<protocol::FileTransfer_Error> request_error_;
 
   // Remote end of the DesktopSessionControl channel, the receiver is owned by
   // a FakeDesktopSessionAgent instance.
@@ -170,7 +170,7 @@
   bool disconnect_on_next_request_ = false;
 
   // If set, |response_error_| will be returned in the next IPC response.
-  absl::optional<protocol::FileTransfer_Error> response_error_;
+  std::optional<protocol::FileTransfer_Error> response_error_;
 
   // Handles file transfer requests over Mojo and manages receiver lifetimes.
   SessionFileOperationsHandler session_file_operations_handler_;
@@ -349,7 +349,7 @@
       file_operations_->CreateWriter();
   ASSERT_EQ(FileOperations::kCreated, writer->state());
 
-  absl::optional<FileOperations::Writer::Result> open_result;
+  std::optional<FileOperations::Writer::Result> open_result;
   writer->Open(kTestFilename, base::BindLambdaForTesting(
                                   [&](FileOperations::Writer::Result result) {
                                     open_result = std::move(result);
@@ -362,7 +362,7 @@
   ASSERT_EQ(session_file_writer_count(), size_t{1});
 
   for (const auto& chunk : {kTestDataOne, kTestDataTwo, kTestDataThree}) {
-    absl::optional<FileOperations::Writer::Result> write_result;
+    std::optional<FileOperations::Writer::Result> write_result;
     writer->WriteChunk(chunk, base::BindLambdaForTesting(
                                   [&](FileOperations::Writer::Result result) {
                                     write_result = std::move(result);
@@ -374,7 +374,7 @@
     ASSERT_TRUE(*write_result);
   }
 
-  absl::optional<FileOperations::Writer::Result> close_result;
+  std::optional<FileOperations::Writer::Result> close_result;
   writer->Close(
       base::BindLambdaForTesting([&](FileOperations::Writer::Result result) {
         close_result = std::move(result);
@@ -397,7 +397,7 @@
   std::unique_ptr<FileOperations::Writer> writer =
       file_operations_->CreateWriter();
 
-  absl::optional<FileOperations::Writer::Result> open_result;
+  std::optional<FileOperations::Writer::Result> open_result;
   writer->Open(kTestFilename, base::BindLambdaForTesting(
                                   [&](FileOperations::Writer::Result result) {
                                     open_result = std::move(result);
@@ -408,7 +408,7 @@
   ASSERT_EQ(session_file_writer_count(), size_t{1});
 
   for (const auto& chunk : {kTestDataOne, kTestDataTwo, kTestDataThree}) {
-    absl::optional<FileOperations::Writer::Result> write_result;
+    std::optional<FileOperations::Writer::Result> write_result;
     writer->WriteChunk(chunk, base::BindLambdaForTesting(
                                   [&](FileOperations::Writer::Result result) {
                                     write_result = std::move(result);
@@ -432,7 +432,7 @@
   std::unique_ptr<FileOperations::Writer> writer =
       file_operations_->CreateWriter();
 
-  absl::optional<FileOperations::Writer::Result> open_result;
+  std::optional<FileOperations::Writer::Result> open_result;
   writer->Open(kTestFilename, base::BindLambdaForTesting(
                                   [&](FileOperations::Writer::Result result) {
                                     open_result = std::move(result);
@@ -442,7 +442,7 @@
   ASSERT_TRUE(*open_result);
   ASSERT_EQ(session_file_writer_count(), size_t{1});
 
-  absl::optional<FileOperations::Writer::Result> write_result;
+  std::optional<FileOperations::Writer::Result> write_result;
   writer->WriteChunk(
       kTestDataOne,
       base::BindLambdaForTesting([&](FileOperations::Writer::Result result) {
@@ -472,7 +472,7 @@
   ASSERT_EQ(FileOperations::kCreated, reader->state());
 
   FakeFileChooser::SetResult(path);
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   reader->Open(base::BindLambdaForTesting(
       [&](FileOperations::Reader::OpenResult result) {
         open_result = std::move(result);
@@ -485,7 +485,7 @@
   ASSERT_EQ(session_file_reader_count(), size_t{1});
 
   for (const auto& chunk : {kTestDataOne, kTestDataTwo, kTestDataThree}) {
-    absl::optional<FileOperations::Reader::ReadResult> read_result;
+    std::optional<FileOperations::Reader::ReadResult> read_result;
     reader->ReadChunk(chunk.size(),
                       base::BindLambdaForTesting(
                           [&](FileOperations::Reader::ReadResult result) {
@@ -519,7 +519,7 @@
       file_operations_->CreateReader();
 
   FakeFileChooser::SetResult(path);
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   reader->Open(base::BindLambdaForTesting(
       [&](FileOperations::Reader::OpenResult result) {
         open_result = std::move(result);
@@ -529,7 +529,7 @@
   ASSERT_TRUE(*open_result);
   ASSERT_EQ(session_file_reader_count(), size_t{1});
 
-  absl::optional<FileOperations::Reader::ReadResult> read_result;
+  std::optional<FileOperations::Reader::ReadResult> read_result;
   reader->ReadChunk(
       contents.size() +
           kOverreadAmount,  // Attempt to read more than is in file.
@@ -570,7 +570,7 @@
       file_operations_->CreateReader();
 
   FakeFileChooser::SetResult(path);
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   reader->Open(base::BindLambdaForTesting(
       [&](FileOperations::Reader::OpenResult result) {
         open_result = std::move(result);
@@ -580,7 +580,7 @@
   ASSERT_TRUE(*open_result);
   ASSERT_EQ(session_file_reader_count(), size_t{1});
 
-  absl::optional<FileOperations::Reader::ReadResult> read_result;
+  std::optional<FileOperations::Reader::ReadResult> read_result;
   reader->ReadChunk(kChunkSize,
                     base::BindLambdaForTesting(
                         [&](FileOperations::Reader::ReadResult result) {
@@ -620,7 +620,7 @@
   int reader_count = static_cast<int>(readers.size());
   for (int i = 0; i < reader_count; i++) {
     FakeFileChooser::SetResult(paths[i]);
-    absl::optional<FileOperations::Reader::OpenResult> open_result;
+    std::optional<FileOperations::Reader::OpenResult> open_result;
     readers[i]->Open(base::BindLambdaForTesting(
         [&](FileOperations::Reader::OpenResult result) {
           open_result = std::move(result);
@@ -634,7 +634,7 @@
 
   for (int i = 0; i < reader_count; i++) {
     for (const auto& chunk : {kTestDataOne, kTestDataTwo, kTestDataThree}) {
-      absl::optional<FileOperations::Reader::ReadResult> read_result;
+      std::optional<FileOperations::Reader::ReadResult> read_result;
       readers[i]->ReadChunk(chunk.size(),
                             base::BindLambdaForTesting(
                                 [&](FileOperations::Reader::ReadResult result) {
@@ -651,7 +651,7 @@
   ASSERT_EQ(session_file_reader_count(), readers.size());
 
   for (int i = reader_count - 1; i >= 0; i--) {
-    absl::optional<FileOperations::Reader::ReadResult> read_result;
+    std::optional<FileOperations::Reader::ReadResult> read_result;
     // Simulate EOF by reading 1 additional byte.
     readers[i]->ReadChunk(1,
                           base::BindLambdaForTesting(
@@ -689,7 +689,7 @@
 
   int writer_count = static_cast<int>(writers.size());
   for (int i = 0; i < writer_count; i++) {
-    absl::optional<FileOperations::Writer::Result> open_result;
+    std::optional<FileOperations::Writer::Result> open_result;
     writers[i]->Open(paths[i], base::BindLambdaForTesting(
                                    [&](FileOperations::Writer::Result result) {
                                      open_result = std::move(result);
@@ -703,7 +703,7 @@
 
   for (const auto& chunk : {kTestDataOne, kTestDataTwo, kTestDataThree}) {
     for (int i = 0; i < writer_count; i++) {
-      absl::optional<FileOperations::Writer::Result> write_result;
+      std::optional<FileOperations::Writer::Result> write_result;
       writers[i]->WriteChunk(chunk,
                              base::BindLambdaForTesting(
                                  [&](FileOperations::Writer::Result result) {
@@ -720,7 +720,7 @@
   ASSERT_EQ(session_file_writer_count(), writers.size());
 
   for (int i = writer_count - 1; i >= 0; i--) {
-    absl::optional<FileOperations::Writer::Result> close_result;
+    std::optional<FileOperations::Writer::Result> close_result;
     writers[i]->Close(
         base::BindLambdaForTesting([&](FileOperations::Writer::Result result) {
           close_result = std::move(result);
@@ -757,14 +757,14 @@
   ASSERT_TRUE(base::WriteFile(read_path, contents));
 
   // Pending open file operations.
-  absl::optional<FileOperations::Writer::Result> open_for_write_result;
+  std::optional<FileOperations::Writer::Result> open_for_write_result;
   writer->Open(
       base_path.InsertBeforeExtension(FILE_PATH_LITERAL("(write)")),
       base::BindLambdaForTesting([&](FileOperations::Writer::Result result) {
         open_for_write_result = std::move(result);
       }));
   FakeFileChooser::SetResult(read_path);
-  absl::optional<FileOperations::Reader::OpenResult> open_for_read_result;
+  std::optional<FileOperations::Reader::OpenResult> open_for_read_result;
   reader->Open(base::BindLambdaForTesting(
       [&](FileOperations::Reader::OpenResult result) {
         open_for_read_result = std::move(result);
@@ -784,13 +784,13 @@
   ASSERT_EQ(session_file_reader_count(), size_t{1});
 
   // Pending write operation.
-  absl::optional<FileOperations::Writer::Result> write_result;
+  std::optional<FileOperations::Writer::Result> write_result;
   writer->WriteChunk(contents, base::BindLambdaForTesting(
                                    [&](FileOperations::Writer::Result result) {
                                      write_result = std::move(result);
                                    }));
   // Pending read operation.
-  absl::optional<FileOperations::Reader::ReadResult> read_result;
+  std::optional<FileOperations::Reader::ReadResult> read_result;
   reader->ReadChunk(contents.size(),
                     base::BindLambdaForTesting(
                         [&](FileOperations::Reader::ReadResult result) {
@@ -811,7 +811,7 @@
   ASSERT_EQ(session_file_reader_count(), size_t{1});
 
   // Close the writer.
-  absl::optional<FileOperations::Writer::Result> close_result;
+  std::optional<FileOperations::Writer::Result> close_result;
   writer->Close(
       base::BindLambdaForTesting([&](FileOperations::Writer::Result result) {
         close_result = std::move(result);
@@ -851,7 +851,7 @@
 
   // Currently non-existent file.
   FakeFileChooser::SetResult(TestDir().Append(kTestFilename));
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   reader->Open(base::BindLambdaForTesting(
       [&](FileOperations::Reader::OpenResult result) {
         open_result = std::move(result);
@@ -871,7 +871,7 @@
   fake_desktop_session_proxy_.SetErrorForNextRequest(
       protocol::MakeFileTransferError(
           FROM_HERE, protocol::FileTransfer_Error_Type_UNEXPECTED_ERROR));
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   reader->Open(base::BindLambdaForTesting(
       [&](FileOperations::Reader::OpenResult result) {
         open_result = std::move(result);
@@ -889,7 +889,7 @@
   fake_desktop_session_proxy_.SetErrorForNextRequest(
       protocol::MakeFileTransferError(
           FROM_HERE, protocol::FileTransfer_Error_Type_UNEXPECTED_ERROR));
-  absl::optional<FileOperations::Writer::Result> open_result;
+  std::optional<FileOperations::Writer::Result> open_result;
   writer->Open(
       TestDir().Append(kTestFilename),
       base::BindLambdaForTesting([&](FileOperations::Writer::Result result) {
@@ -909,7 +909,7 @@
   fake_desktop_session_agent_.SetErrorForNextResponse(
       protocol::MakeFileTransferError(
           FROM_HERE, protocol::FileTransfer_Error_Type_UNEXPECTED_ERROR));
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   reader->Open(base::BindLambdaForTesting(
       [&](FileOperations::Reader::OpenResult result) {
         open_result = std::move(result);
@@ -928,7 +928,7 @@
   fake_desktop_session_agent_.SetErrorForNextResponse(
       protocol::MakeFileTransferError(
           FROM_HERE, protocol::FileTransfer_Error_Type_UNEXPECTED_ERROR));
-  absl::optional<FileOperations::Writer::Result> open_result;
+  std::optional<FileOperations::Writer::Result> open_result;
   writer->Open(
       TestDir().Append(kTestFilename),
       base::BindLambdaForTesting([&](FileOperations::Writer::Result result) {
@@ -947,7 +947,7 @@
       file_operations_->CreateReader();
   // This will trigger the DesktopSessionControl remote disconnect handler.
   fake_desktop_session_agent_.DisconnectReceiverOnNextRequest();
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   reader->Open(base::BindLambdaForTesting(
       [&](FileOperations::Reader::OpenResult result) {
         open_result = std::move(result);
@@ -965,7 +965,7 @@
       file_operations_->CreateWriter();
   // This will trigger the DesktopSessionControl remote disconnect handler.
   fake_desktop_session_agent_.DisconnectReceiverOnNextRequest();
-  absl::optional<FileOperations::Writer::Result> open_result;
+  std::optional<FileOperations::Writer::Result> open_result;
   writer->Open(
       TestDir().Append(kTestFilename),
       base::BindLambdaForTesting([&](FileOperations::Writer::Result result) {
@@ -984,7 +984,7 @@
   constexpr std::size_t kChunkSize = 5;
   std::unique_ptr<FileOperations::Reader> reader =
       file_operations_->CreateReader();
-  absl::optional<FileOperations::Reader::ReadResult> read_result;
+  std::optional<FileOperations::Reader::ReadResult> read_result;
   reader->ReadChunk(kChunkSize,
                     base::BindLambdaForTesting(
                         [&](FileOperations::Reader::ReadResult result) {
@@ -1002,7 +1002,7 @@
 TEST_F(IpcFileOperationsTest, ErrorWhenWriteChunkCalledBeforeOpen) {
   std::unique_ptr<FileOperations::Writer> writer =
       file_operations_->CreateWriter();
-  absl::optional<FileOperations::Writer::Result> write_result;
+  std::optional<FileOperations::Writer::Result> write_result;
   writer->WriteChunk(
       std::vector<uint8_t>{16, 16, 16, 16, 16},
       base::BindLambdaForTesting([&](FileOperations::Writer::Result result) {
@@ -1020,7 +1020,7 @@
 TEST_F(IpcFileOperationsTest, ErrorWhenCloseCalledBeforeOpen) {
   std::unique_ptr<FileOperations::Writer> writer =
       file_operations_->CreateWriter();
-  absl::optional<FileOperations::Writer::Result> close_result;
+  std::optional<FileOperations::Writer::Result> close_result;
   writer->Close(
       base::BindLambdaForTesting([&](FileOperations::Writer::Result result) {
         close_result = std::move(result);
@@ -1043,7 +1043,7 @@
       file_operations_->CreateReader();
 
   FakeFileChooser::SetResult(path);
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   reader->Open(base::BindLambdaForTesting(
       [&](FileOperations::Reader::OpenResult result) {
         open_result = std::move(result);
@@ -1058,7 +1058,7 @@
   ASSERT_EQ(session_file_reader_count(), size_t{0});
   task_environment_.RunUntilIdle();
 
-  absl::optional<FileOperations::Reader::ReadResult> read_result;
+  std::optional<FileOperations::Reader::ReadResult> read_result;
   reader->ReadChunk(kChunkSize,
                     base::BindLambdaForTesting(
                         [&](FileOperations::Reader::ReadResult result) {
@@ -1076,7 +1076,7 @@
   std::unique_ptr<FileOperations::Writer> writer =
       file_operations_->CreateWriter();
 
-  absl::optional<FileOperations::Writer::Result> open_result;
+  std::optional<FileOperations::Writer::Result> open_result;
   writer->Open(kTestFilename, base::BindLambdaForTesting(
                                   [&](FileOperations::Writer::Result result) {
                                     open_result = std::move(result);
@@ -1090,7 +1090,7 @@
   ASSERT_EQ(session_file_writer_count(), size_t{0});
   task_environment_.RunUntilIdle();
 
-  absl::optional<FileOperations::Writer::Result> write_result;
+  std::optional<FileOperations::Writer::Result> write_result;
   writer->WriteChunk(
       std::vector<uint8_t>{16, 16, 16, 16, 16},
       base::BindLambdaForTesting([&](FileOperations::Writer::Result result) {
@@ -1108,7 +1108,7 @@
   std::unique_ptr<FileOperations::Writer> writer =
       file_operations_->CreateWriter();
 
-  absl::optional<FileOperations::Writer::Result> open_result;
+  std::optional<FileOperations::Writer::Result> open_result;
   writer->Open(kTestFilename, base::BindLambdaForTesting(
                                   [&](FileOperations::Writer::Result result) {
                                     open_result = std::move(result);
@@ -1122,7 +1122,7 @@
   ASSERT_EQ(session_file_writer_count(), size_t{0});
   task_environment_.RunUntilIdle();
 
-  absl::optional<FileOperations::Writer::Result> close_result;
+  std::optional<FileOperations::Writer::Result> close_result;
   writer->Close(
       base::BindLambdaForTesting([&](FileOperations::Writer::Result result) {
         close_result = std::move(result);
@@ -1149,7 +1149,7 @@
 
   ipc_file_operations_factory.reset();
 
-  absl::optional<FileOperations::Writer::Result> writer_open_result;
+  std::optional<FileOperations::Writer::Result> writer_open_result;
   writer->Open(kTestFilename, base::BindLambdaForTesting(
                                   [&](FileOperations::Writer::Result result) {
                                     writer_open_result = std::move(result);
@@ -1158,7 +1158,7 @@
   ASSERT_EQ(writer->state(), FileOperations::kFailed);
   ASSERT_TRUE(writer_open_result->is_error());
 
-  absl::optional<FileOperations::Reader::OpenResult> reader_open_result;
+  std::optional<FileOperations::Reader::OpenResult> reader_open_result;
   reader->Open(base::BindLambdaForTesting(
       [&](FileOperations::Reader::OpenResult result) {
         reader_open_result = std::move(result);
@@ -1182,7 +1182,7 @@
   std::unique_ptr<FileOperations::Reader> reader =
       file_operations->CreateReader();
 
-  absl::optional<FileOperations::Writer::Result> writer_open_result;
+  std::optional<FileOperations::Writer::Result> writer_open_result;
   writer->Open(kTestFilename, base::BindLambdaForTesting(
                                   [&](FileOperations::Writer::Result result) {
                                     writer_open_result = std::move(result);
@@ -1191,7 +1191,7 @@
   ASSERT_EQ(writer->state(), FileOperations::kFailed);
   ASSERT_TRUE(writer_open_result->is_error());
 
-  absl::optional<FileOperations::Reader::OpenResult> reader_open_result;
+  std::optional<FileOperations::Reader::OpenResult> reader_open_result;
   reader->Open(base::BindLambdaForTesting(
       [&](FileOperations::Reader::OpenResult result) {
         reader_open_result = std::move(result);
diff --git a/remoting/host/file_transfer/local_file_operations.cc b/remoting/host/file_transfer/local_file_operations.cc
index 5618379..2760e51d 100644
--- a/remoting/host/file_transfer/local_file_operations.cc
+++ b/remoting/host/file_transfer/local_file_operations.cc
@@ -6,6 +6,7 @@
 
 #include <cstdint>
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/files/file_proxy.h"
 #include "base/files/file_util.h"
@@ -22,7 +23,6 @@
 #include "remoting/host/file_transfer/ensure_user.h"
 #include "remoting/host/file_transfer/file_chooser.h"
 #include "remoting/protocol/file_transfer_helpers.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -97,7 +97,7 @@
   scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
   scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
   std::unique_ptr<FileChooser> file_chooser_;
-  absl::optional<base::FileProxy> file_proxy_;
+  std::optional<base::FileProxy> file_proxy_;
   SEQUENCE_CHECKER(sequence_checker_);
   base::WeakPtrFactory<LocalFileReader> weak_ptr_factory_{this};
 };
@@ -148,7 +148,7 @@
   std::uint64_t bytes_written_ = 0;
 
   scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
-  absl::optional<base::FileProxy> file_proxy_;
+  std::optional<base::FileProxy> file_proxy_;
   SEQUENCE_CHECKER(sequence_checker_);
   base::WeakPtrFactory<LocalFileWriter> weak_ptr_factory_{this};
 };
diff --git a/remoting/host/file_transfer/local_file_operations_unittest.cc b/remoting/host/file_transfer/local_file_operations_unittest.cc
index 7a915a7..ed5524f 100644
--- a/remoting/host/file_transfer/local_file_operations_unittest.cc
+++ b/remoting/host/file_transfer/local_file_operations_unittest.cc
@@ -245,7 +245,7 @@
       file_operations_->CreateReader();
 
   FakeFileChooser::SetResult(path);
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   ASSERT_EQ(FileOperations::kCreated, reader->state());
   reader->Open(BindLambda([&](FileOperations::Reader::OpenResult result) {
     open_result = std::move(result);
@@ -270,7 +270,7 @@
       file_operations_->CreateReader();
 
   FakeFileChooser::SetResult(path);
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   reader->Open(BindLambda([&](FileOperations::Reader::OpenResult result) {
     open_result = std::move(result);
   }));
@@ -278,7 +278,7 @@
   ASSERT_TRUE(open_result && *open_result);
 
   for (const auto& chunk : {kTestDataOne, kTestDataTwo, kTestDataThree}) {
-    absl::optional<FileOperations::Reader::ReadResult> read_result;
+    std::optional<FileOperations::Reader::ReadResult> read_result;
     reader->ReadChunk(
         chunk.size(),
         BindLambda([&](FileOperations::Reader::ReadResult result) {
@@ -304,14 +304,14 @@
       file_operations_->CreateReader();
 
   FakeFileChooser::SetResult(path);
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   reader->Open(BindLambda([&](FileOperations::Reader::OpenResult result) {
     open_result = std::move(result);
   }));
   task_environment_.RunUntilIdle();
   ASSERT_TRUE(open_result && *open_result);
 
-  absl::optional<FileOperations::Reader::ReadResult> read_result;
+  std::optional<FileOperations::Reader::ReadResult> read_result;
   reader->ReadChunk(
       contents.size() + 5,  // Attempt to read more than is in file.
       BindLambda([&](FileOperations::Reader::ReadResult result) {
@@ -340,7 +340,7 @@
 
   FakeFileChooser::SetResult(protocol::MakeFileTransferError(
       FROM_HERE, protocol::FileTransfer_Error_Type_CANCELED));
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   reader->Open(BindLambda([&](FileOperations::Reader::OpenResult result) {
     open_result = std::move(result);
   }));
@@ -359,7 +359,7 @@
 
   // Currently non-existent file.
   FakeFileChooser::SetResult(TestDir().Append(kTestFilename));
-  absl::optional<FileOperations::Reader::OpenResult> open_result;
+  std::optional<FileOperations::Reader::OpenResult> open_result;
   reader->Open(BindLambda([&](FileOperations::Reader::OpenResult result) {
     open_result = std::move(result);
   }));
diff --git a/remoting/host/file_transfer/rtc_log_file_operations_unittest.cc b/remoting/host/file_transfer/rtc_log_file_operations_unittest.cc
index ade7bd7..2e05dac 100644
--- a/remoting/host/file_transfer/rtc_log_file_operations_unittest.cc
+++ b/remoting/host/file_transfer/rtc_log_file_operations_unittest.cc
@@ -52,8 +52,8 @@
   std::unique_ptr<FileOperations::Reader> reader_;
 
   // These are the most-recent results from the callbacks.
-  absl::optional<FileOperations::Reader::OpenResult> open_result_;
-  absl::optional<FileOperations::Reader::ReadResult> read_result_;
+  std::optional<FileOperations::Reader::OpenResult> open_result_;
+  std::optional<FileOperations::Reader::ReadResult> read_result_;
 
   FileOperations::Reader::OpenCallback MakeOpenCallback() {
     return base::BindOnce(&RtcLogFileOperationsTest::OnOpenResult,
diff --git a/remoting/host/file_transfer/session_file_operations_handler.cc b/remoting/host/file_transfer/session_file_operations_handler.cc
index 1bc7b8a..44948d623 100644
--- a/remoting/host/file_transfer/session_file_operations_handler.cc
+++ b/remoting/host/file_transfer/session_file_operations_handler.cc
@@ -6,12 +6,12 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/functional/bind.h"
 #include "base/memory/weak_ptr.h"
 #include "remoting/host/mojom/desktop_session.mojom.h"
 #include "remoting/protocol/file_transfer_helpers.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -158,7 +158,7 @@
 // methods which expect a Writer::Callback.
 template <class T>
 void FileWriterCallbackWrapper(T callback, remoting::Writer::Result result) {
-  absl::optional<protocol::FileTransfer_Error> error;
+  std::optional<protocol::FileTransfer_Error> error;
   if (result.is_error()) {
     error = std::move(result.error());
   }
diff --git a/remoting/host/host_config.cc b/remoting/host/host_config.cc
index b99c9c0..26dfb75b 100644
--- a/remoting/host/host_config.cc
+++ b/remoting/host/host_config.cc
@@ -28,17 +28,17 @@
 const char kDeprecatedHostOwnerEmailConfigPath[] = "host_owner_email";
 const char kDeprecatedXmppLoginConfigPath[] = "xmpp_login";
 
-absl::optional<base::Value::Dict> HostConfigFromJson(const std::string& json) {
-  absl::optional<base::Value> value =
+std::optional<base::Value::Dict> HostConfigFromJson(const std::string& json) {
+  std::optional<base::Value> value =
       base::JSONReader::Read(json, base::JSON_ALLOW_TRAILING_COMMAS);
   if (!value.has_value()) {
     LOG(ERROR) << "Failed to parse host config from JSON";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (!value->is_dict()) {
     LOG(ERROR) << "Parsed host config returned was not a dictionary";
-    return absl::nullopt;
+    return std::nullopt;
   }
   auto config = std::move(value->GetDict());
 
@@ -76,12 +76,12 @@
   return data;
 }
 
-absl::optional<base::Value::Dict> HostConfigFromJsonFile(
+std::optional<base::Value::Dict> HostConfigFromJsonFile(
     const base::FilePath& config_file) {
   std::string serialized;
   if (!base::ReadFileToString(config_file, &serialized)) {
     LOG(ERROR) << "Failed to read " << config_file.value();
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return HostConfigFromJson(serialized);
diff --git a/remoting/host/host_config.h b/remoting/host/host_config.h
index 5c490e3..45339699 100644
--- a/remoting/host/host_config.h
+++ b/remoting/host/host_config.h
@@ -8,8 +8,8 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class FilePath;
@@ -59,12 +59,12 @@
 extern const char kDeprecatedXmppLoginConfigPath[];
 
 // Helpers for serializing/deserializing Host configuration dictionaries.
-absl::optional<base::Value::Dict> HostConfigFromJson(
+std::optional<base::Value::Dict> HostConfigFromJson(
     const std::string& serialized);
 std::string HostConfigToJson(const base::Value::Dict& host_config);
 
 // Helpers for loading/saving host configurations from/to files.
-absl::optional<base::Value::Dict> HostConfigFromJsonFile(
+std::optional<base::Value::Dict> HostConfigFromJsonFile(
     const base::FilePath& config_file);
 bool HostConfigToJsonFile(const base::Value::Dict& host_config,
                           const base::FilePath& config_file);
diff --git a/remoting/host/host_config_unittest.cc b/remoting/host/host_config_unittest.cc
index 3a4ebe0b..0e0631e5 100644
--- a/remoting/host/host_config_unittest.cc
+++ b/remoting/host/host_config_unittest.cc
@@ -4,13 +4,13 @@
 
 #include "remoting/host/host_config.h"
 
+#include <optional>
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/json/json_writer.h"
 #include "base/memory/ref_counted.h"
 #include "base/values.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
diff --git a/remoting/host/input_injector_win.cc b/remoting/host/input_injector_win.cc
index 4b4cfce8..52bcb8bc 100644
--- a/remoting/host/input_injector_win.cc
+++ b/remoting/host/input_injector_win.cc
@@ -12,6 +12,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/compiler_specific.h"
 #include "base/functional/bind.h"
 #include "base/location.h"
@@ -24,7 +25,6 @@
 #include "remoting/host/clipboard.h"
 #include "remoting/host/touch_injector_win.h"
 #include "remoting/proto/event.pb.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
 
 namespace remoting {
@@ -168,8 +168,8 @@
 }
 
 // Sets the keyboard lock states to those provided.
-void SetLockStates(absl::optional<bool> caps_lock,
-                   absl::optional<bool> num_lock) {
+void SetLockStates(std::optional<bool> caps_lock,
+                   std::optional<bool> num_lock) {
   if (caps_lock) {
     bool client_capslock_state = *caps_lock;
     bool host_capslock_state = (GetKeyState(VK_CAPITAL) & 1) != 0;
@@ -393,8 +393,8 @@
   }
 
   if (event.pressed() && !IsLockKey(scancode)) {
-    absl::optional<bool> caps_lock;
-    absl::optional<bool> num_lock;
+    std::optional<bool> caps_lock;
+    std::optional<bool> num_lock;
 
     // For caps lock, check both the new caps_lock field and the old lock_states
     // field.
diff --git a/remoting/host/input_injector_x11.cc b/remoting/host/input_injector_x11.cc
index c7de2a8..994a19d 100644
--- a/remoting/host/input_injector_x11.cc
+++ b/remoting/host/input_injector_x11.cc
@@ -8,6 +8,7 @@
 #include <set>
 #include <utility>
 
+#include <optional>
 #include "base/compiler_specific.h"
 #include "base/functional/bind.h"
 #include "base/location.h"
@@ -25,7 +26,6 @@
 #include "remoting/host/linux/x11_keyboard_impl.h"
 #include "remoting/host/linux/x11_util.h"
 #include "remoting/proto/internal.pb.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
@@ -172,8 +172,8 @@
     }
 
     if (!IsLockKey(static_cast<x11::KeyCode>(keycode))) {
-      absl::optional<bool> caps_lock;
-      absl::optional<bool> num_lock;
+      std::optional<bool> caps_lock;
+      std::optional<bool> num_lock;
 
       // For caps lock, check both the new caps_lock field and the old
       // lock_states field.
@@ -280,8 +280,8 @@
   }
 }
 
-void InputInjectorX11::Core::SetLockStates(absl::optional<bool> caps_lock,
-                                           absl::optional<bool> num_lock) {
+void InputInjectorX11::Core::SetLockStates(std::optional<bool> caps_lock,
+                                           std::optional<bool> num_lock) {
   // The lock bits associated with each lock key.
   auto caps_lock_mask = static_cast<unsigned int>(x11::ModMask::Lock);
   auto num_lock_mask = static_cast<unsigned int>(x11::ModMask::c_2);
diff --git a/remoting/host/input_injector_x11.h b/remoting/host/input_injector_x11.h
index 4d90e3b..58b05d4 100644
--- a/remoting/host/input_injector_x11.h
+++ b/remoting/host/input_injector_x11.h
@@ -11,6 +11,7 @@
 #include <set>
 #include <utility>
 
+#include <optional>
 #include "base/compiler_specific.h"
 #include "base/functional/bind.h"
 #include "base/location.h"
@@ -26,7 +27,6 @@
 #include "remoting/host/linux/x11_keyboard_impl.h"
 #include "remoting/host/linux/x11_util.h"
 #include "remoting/proto/internal.pb.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
 #include "ui/gfx/x/xproto.h"
 
@@ -99,8 +99,8 @@
     bool IsLockKey(x11::KeyCode keycode);
 
     // Sets the keyboard lock states to those provided.
-    void SetLockStates(absl::optional<bool> caps_lock,
-                       absl::optional<bool> num_lock);
+    void SetLockStates(std::optional<bool> caps_lock,
+                       std::optional<bool> num_lock);
 
     void InjectScrollWheelClicks(int button, int count);
 
diff --git a/remoting/host/ipc_desktop_environment_unittest.cc b/remoting/host/ipc_desktop_environment_unittest.cc
index 0617ba5..4b8b273 100644
--- a/remoting/host/ipc_desktop_environment_unittest.cc
+++ b/remoting/host/ipc_desktop_environment_unittest.cc
@@ -798,7 +798,7 @@
   screen_controls_->SetScreenResolution(
       ScreenResolution(webrtc::DesktopSize(100, 100),
                        webrtc::DesktopVector(96, 96)),
-      absl::nullopt);
+      std::nullopt);
 }
 
 TEST_F(IpcDesktopEnvironmentTest, CheckUrlForwarderState) {
diff --git a/remoting/host/ipc_screen_controls.cc b/remoting/host/ipc_screen_controls.cc
index 6a43236f..669e8f37 100644
--- a/remoting/host/ipc_screen_controls.cc
+++ b/remoting/host/ipc_screen_controls.cc
@@ -17,7 +17,7 @@
 
 void IpcScreenControls::SetScreenResolution(
     const ScreenResolution& resolution,
-    absl::optional<webrtc::ScreenId> screen_id) {
+    std::optional<webrtc::ScreenId> screen_id) {
   // TODO(crbug.com/1326339): Pass |screen_id| over IPC.
   desktop_session_proxy_->SetScreenResolution(resolution);
 }
diff --git a/remoting/host/ipc_screen_controls.h b/remoting/host/ipc_screen_controls.h
index 7ccaaeb..8ae1138 100644
--- a/remoting/host/ipc_screen_controls.h
+++ b/remoting/host/ipc_screen_controls.h
@@ -25,7 +25,7 @@
 
   // ScreenControls interface.
   void SetScreenResolution(const ScreenResolution& resolution,
-                           absl::optional<webrtc::ScreenId> screen_id) override;
+                           std::optional<webrtc::ScreenId> screen_id) override;
   void SetVideoLayout(const protocol::VideoLayout& video_layout) override;
 
  private:
diff --git a/remoting/host/it2me/it2me_confirmation_dialog_chromeos.cc b/remoting/host/it2me/it2me_confirmation_dialog_chromeos.cc
index 827f0bd8..dbe5fe762 100644
--- a/remoting/host/it2me/it2me_confirmation_dialog_chromeos.cc
+++ b/remoting/host/it2me/it2me_confirmation_dialog_chromeos.cc
@@ -63,7 +63,7 @@
  private:
   void ShowConfirmationNotification(const std::string& remote_user_email);
 
-  void OnConfirmationNotificationResult(absl::optional<int> button_index);
+  void OnConfirmationNotificationResult(std::optional<int> button_index);
 
   const gfx::VectorIcon& GetIcon() const {
     switch (style_) {
@@ -136,7 +136,7 @@
 }
 
 void It2MeConfirmationDialogChromeOS::OnConfirmationNotificationResult(
-    absl::optional<int> button_index) {
+    std::optional<int> button_index) {
   if (!button_index.has_value()) {
     return;  // This happens when the user clicks the notification itself.
   }
diff --git a/remoting/host/it2me/it2me_confirmation_dialog_chromeos_unittest.cc b/remoting/host/it2me/it2me_confirmation_dialog_chromeos_unittest.cc
index cc591e3..cf95286 100644
--- a/remoting/host/it2me/it2me_confirmation_dialog_chromeos_unittest.cc
+++ b/remoting/host/it2me/it2me_confirmation_dialog_chromeos_unittest.cc
@@ -8,6 +8,7 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/i18n/message_formatter.h"
 #include "base/ranges/algorithm.h"
 #include "base/strings/utf_string_conversions.h"
@@ -16,7 +17,6 @@
 #include "remoting/base/string_resources.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/message_center/lock_screen/fake_lock_screen_controller.h"
 #include "ui/message_center/message_center.h"
@@ -90,7 +90,7 @@
     ASSERT_NE(notification, nullptr);
     const int button_index = FindButtonIndex(*notification, button_title);
     ASSERT_GE(button_index, 0);
-    notification->delegate()->Click(button_index, absl::nullopt);
+    notification->delegate()->Click(button_index, std::nullopt);
   }
 
   std::u16string FormatMessage(const std::string& remote_user_email,
diff --git a/remoting/host/it2me/it2me_confirmation_dialog_win.cc b/remoting/host/it2me/it2me_confirmation_dialog_win.cc
index f4016ff..1e4748c 100644
--- a/remoting/host/it2me/it2me_confirmation_dialog_win.cc
+++ b/remoting/host/it2me/it2me_confirmation_dialog_win.cc
@@ -98,7 +98,7 @@
   task_dialog.set_message_text(message_text);
   task_dialog.set_default_button(IDNO);
   task_dialog.set_dialog_timeout(kDialogTimeout);
-  absl::optional<int> button_result = task_dialog.Show();
+  std::optional<int> button_result = task_dialog.Show();
 
   if (!button_result.has_value()) {
     std::move(callback).Run(result);
diff --git a/remoting/host/it2me/it2me_host.cc b/remoting/host/it2me/it2me_host.cc
index 7c37e0a..413e968 100644
--- a/remoting/host/it2me/it2me_host.cc
+++ b/remoting/host/it2me/it2me_host.cc
@@ -467,13 +467,13 @@
            << enterprise_file_transfer_allowed_;
 #endif
 
-  absl::optional<bool> nat_policy_value =
+  std::optional<bool> nat_policy_value =
       policies.FindBool(policy::key::kRemoteAccessHostFirewallTraversal);
   if (!nat_policy_value.has_value()) {
     HOST_LOG << "Failed to read kRemoteAccessHostFirewallTraversal policy";
     nat_policy_value = nat_traversal_enabled_;
   }
-  absl::optional<bool> relay_policy_value =
+  std::optional<bool> relay_policy_value =
       policies.FindBool(policy::key::kRemoteAccessHostAllowRelayedConnection);
   if (!relay_policy_value.has_value()) {
     HOST_LOG << "Failed to read kRemoteAccessHostAllowRelayedConnection policy";
@@ -507,7 +507,7 @@
     UpdateHostUdpPortRangePolicy(*port_range_string);
   }
 
-  absl::optional<int> max_clipboard_size =
+  std::optional<int> max_clipboard_size =
       policies.FindInt(policy::key::kRemoteAccessHostClipboardSizeBytes);
   if (max_clipboard_size.has_value()) {
     if (max_clipboard_size.value() >= 0) {
diff --git a/remoting/host/it2me/it2me_host.h b/remoting/host/it2me/it2me_host.h
index 60115b57..7210f6a 100644
--- a/remoting/host/it2me/it2me_host.h
+++ b/remoting/host/it2me/it2me_host.h
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/functional/callback_forward.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
@@ -25,7 +26,6 @@
 #include "remoting/protocol/port_range.h"
 #include "remoting/protocol/validating_authenticator.h"
 #include "remoting/signaling/signal_strategy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -251,7 +251,7 @@
 
   // Set when the session was initiated for a managed Chrome OS device by an
   // admin using the admin console.
-  absl::optional<ChromeOsEnterpriseParams> chrome_os_enterprise_params_;
+  std::optional<ChromeOsEnterpriseParams> chrome_os_enterprise_params_;
 
   // Only the username stored in |authorized_helper_| will be allowed to connect
   // to this host instance, if set. Note: setting this value does not override
@@ -266,7 +266,7 @@
   PortRange udp_port_range_;
 
   // Stores the clipboard size policy value.
-  absl::optional<size_t> max_clipboard_size_;
+  std::optional<size_t> max_clipboard_size_;
 
   // Stores the remote support connections allowed policy value.
   bool remote_support_connections_allowed_ = true;
diff --git a/remoting/host/it2me/it2me_host_unittest.cc b/remoting/host/it2me/it2me_host_unittest.cc
index e0ea8c01f..05b904f 100644
--- a/remoting/host/it2me/it2me_host_unittest.cc
+++ b/remoting/host/it2me/it2me_host_unittest.cc
@@ -8,6 +8,7 @@
 #include <string>
 #include <utility>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/location.h"
@@ -37,7 +38,6 @@
 #include "remoting/signaling/xmpp_log_to_server.h"
 #include "services/network/test/test_shared_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
 #include "base/linux_util.h"
@@ -228,7 +228,7 @@
   void RunValidationCallback(const std::string& remote_jid);
 
   void StartHost();
-  void StartHost(absl::optional<ChromeOsEnterpriseParams> enterprise_params);
+  void StartHost(std::optional<ChromeOsEnterpriseParams> enterprise_params);
   void ShutdownHost();
 
   static base::Value MakeList(std::initializer_list<base::StringPiece> values);
@@ -236,8 +236,8 @@
   ChromotingHost* GetHost() { return it2me_host_->host_.get(); }
 
   // Configuration values used by StartHost();
-  absl::optional<ChromeOsEnterpriseParams> enterprise_params_;
-  absl::optional<std::string> authorized_helper_;
+  std::optional<ChromeOsEnterpriseParams> enterprise_params_;
+  std::optional<std::string> authorized_helper_;
 
   // Stores the last nat traversal policy value received.
   bool last_nat_traversal_enabled_value_ = false;
@@ -256,7 +256,7 @@
   raw_ptr<FakeIt2MeDialogFactory, AcrossTasksDanglingUntriaged>
       dialog_factory_ = nullptr;
 
-  absl::optional<base::Value::Dict> policies_;
+  std::optional<base::Value::Dict> policies_;
 
   scoped_refptr<It2MeHost> it2me_host_;
 
@@ -417,7 +417,7 @@
 }
 
 void It2MeHostTest::StartHost(
-    absl::optional<ChromeOsEnterpriseParams> enterprise_params) {
+    std::optional<ChromeOsEnterpriseParams> enterprise_params) {
   enterprise_params_ = enterprise_params;
   StartHost();
 }
@@ -894,7 +894,7 @@
 }
 
 TEST_F(It2MeHostTest, TerminateUponInputDefaultsToFalse) {
-  StartHost(/*enterprise_params=*/absl::nullopt);
+  StartHost(/*enterprise_params=*/std::nullopt);
 
   EXPECT_FALSE(GetHost()->desktop_environment_options().terminate_upon_input());
 }
@@ -906,7 +906,7 @@
 }
 
 TEST_F(It2MeHostTest, EnableCurtainingDefaultsToFalse) {
-  StartHost(/*enterprise_params=*/absl::nullopt);
+  StartHost(/*enterprise_params=*/std::nullopt);
 
   EXPECT_FALSE(GetHost()->desktop_environment_options().enable_curtaining());
 }
@@ -934,7 +934,7 @@
   SetPolicies({{policy::key::kRemoteAccessHostAllowEnterpriseFileTransfer,
                 base::Value(true)}});
 
-  StartHost(/*enterprise_params=*/absl::nullopt);
+  StartHost(/*enterprise_params=*/std::nullopt);
 
   EXPECT_FALSE(GetHost()->desktop_environment_options().enable_file_transfer());
 }
@@ -959,7 +959,7 @@
 }
 
 TEST_F(It2MeHostTest, EnableFileTransferDefaultsToFalse) {
-  StartHost(/*enterprise_params=*/absl::nullopt);
+  StartHost(/*enterprise_params=*/std::nullopt);
 
   EXPECT_FALSE(GetHost()->desktop_environment_options().enable_file_transfer());
 }
@@ -1008,7 +1008,7 @@
       {{policy::key::kRemoteAccessHostAllowEnterpriseRemoteSupportConnections,
         base::Value(false)}});
 
-  StartHost(/*enterprise_params=*/absl::nullopt);
+  StartHost(/*enterprise_params=*/std::nullopt);
   ASSERT_EQ(It2MeHostState::kReceivedAccessCode, last_host_state_);
 }
 #endif
diff --git a/remoting/host/it2me/it2me_native_messaging_host.cc b/remoting/host/it2me/it2me_native_messaging_host.cc
index b55eef5..5a52541a 100644
--- a/remoting/host/it2me/it2me_native_messaging_host.cc
+++ b/remoting/host/it2me/it2me_native_messaging_host.cc
@@ -206,7 +206,7 @@
     return;
   }
 
-  absl::optional<base::Value::Dict> response =
+  std::optional<base::Value::Dict> response =
       CreateNativeMessageResponse(request);
   if (!response.has_value()) {
     SendErrorAndExit(base::Value::Dict(), ErrorCode::INCOMPATIBLE_PROTOCOL);
@@ -609,7 +609,7 @@
   }
 }
 
-absl::optional<bool>
+std::optional<bool>
 It2MeNativeMessagingHost::GetAllowElevatedHostPolicyValue() {
   DCHECK(policy_received_);
 #if BUILDFLAG(IS_WIN)
@@ -624,7 +624,7 @@
   }
 #endif  // BUILDFLAG(IS_WIN)
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 void It2MeNativeMessagingHost::OnPolicyError() {
diff --git a/remoting/host/it2me/it2me_native_messaging_host.h b/remoting/host/it2me/it2me_native_messaging_host.h
index b35936f..0fbeec8b 100644
--- a/remoting/host/it2me/it2me_native_messaging_host.h
+++ b/remoting/host/it2me/it2me_native_messaging_host.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
@@ -18,7 +19,6 @@
 #include "remoting/host/it2me/it2me_host.h"
 #include "remoting/protocol/errors.h"
 #include "remoting/signaling/delegating_signal_strategy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "remoting/host/native_messaging/log_message_handler.h"
@@ -101,7 +101,7 @@
   std::string ExtractAccessToken(const base::Value::Dict& message);
 
   // Returns the value of the 'allow_elevated_host' platform policy or empty.
-  absl::optional<bool> GetAllowElevatedHostPolicyValue();
+  std::optional<bool> GetAllowElevatedHostPolicyValue();
 
   // Indicates whether the current process is already elevated.
   bool is_process_elevated_ = false;
diff --git a/remoting/host/it2me/it2me_native_messaging_host_ash.cc b/remoting/host/it2me/it2me_native_messaging_host_ash.cc
index 8cd9948e..cb950139 100644
--- a/remoting/host/it2me/it2me_native_messaging_host_ash.cc
+++ b/remoting/host/it2me/it2me_native_messaging_host_ash.cc
@@ -27,7 +27,7 @@
 
 bool ShouldSuppressNotifications(
     const mojom::SupportSessionParams& params,
-    const absl::optional<ChromeOsEnterpriseParams>& enterprise_params) {
+    const std::optional<ChromeOsEnterpriseParams>& enterprise_params) {
   if (enterprise_params.has_value()) {
     return enterprise_params->suppress_notifications;
   }
@@ -42,7 +42,7 @@
 
 bool ShouldSuppressUserDialog(
     const mojom::SupportSessionParams& params,
-    const absl::optional<ChromeOsEnterpriseParams>& enterprise_params) {
+    const std::optional<ChromeOsEnterpriseParams>& enterprise_params) {
   if (enterprise_params.has_value()) {
     return enterprise_params->suppress_user_dialogs;
   }
@@ -57,7 +57,7 @@
 
 bool ShouldTerminateUponInput(
     const mojom::SupportSessionParams& params,
-    const absl::optional<ChromeOsEnterpriseParams>& enterprise_params) {
+    const std::optional<ChromeOsEnterpriseParams>& enterprise_params) {
   if (enterprise_params.has_value()) {
     return enterprise_params->terminate_upon_input;
   }
@@ -72,7 +72,7 @@
 
 bool ShouldCurtainLocalUserSession(
     const mojom::SupportSessionParams& params,
-    const absl::optional<ChromeOsEnterpriseParams>& enterprise_params) {
+    const std::optional<ChromeOsEnterpriseParams>& enterprise_params) {
   if (!base::FeatureList::IsEnabled(features::kEnableCrdAdminRemoteAccess)) {
     return false;
   }
@@ -90,7 +90,7 @@
 }
 
 bool ShouldShowTroubleshootingTools(
-    const absl::optional<ChromeOsEnterpriseParams>& enterprise_params) {
+    const std::optional<ChromeOsEnterpriseParams>& enterprise_params) {
   if (enterprise_params.has_value()) {
     return enterprise_params->show_troubleshooting_tools;
   }
@@ -98,7 +98,7 @@
 }
 
 bool ShouldAllowTroubleshootingTools(
-    const absl::optional<ChromeOsEnterpriseParams>& enterprise_params) {
+    const std::optional<ChromeOsEnterpriseParams>& enterprise_params) {
   if (enterprise_params.has_value()) {
     return enterprise_params->allow_troubleshooting_tools;
   }
@@ -106,7 +106,7 @@
 }
 
 bool ShouldAllowReconnections(
-    const absl::optional<ChromeOsEnterpriseParams>& enterprise_params) {
+    const std::optional<ChromeOsEnterpriseParams>& enterprise_params) {
   if (enterprise_params.has_value()) {
     return enterprise_params->allow_reconnections;
   }
@@ -114,7 +114,7 @@
 }
 
 bool ShouldAllowFileTransfer(
-    const absl::optional<ChromeOsEnterpriseParams>& enterprise_params) {
+    const std::optional<ChromeOsEnterpriseParams>& enterprise_params) {
   if (enterprise_params.has_value()) {
     return enterprise_params->allow_file_transfer;
   }
@@ -153,8 +153,8 @@
 
 void It2MeNativeMessageHostAsh::Connect(
     const mojom::SupportSessionParams& params,
-    const absl::optional<ChromeOsEnterpriseParams>& enterprise_params,
-    const absl::optional<ReconnectParams>& reconnect_params,
+    const std::optional<ChromeOsEnterpriseParams>& enterprise_params,
+    const std::optional<ReconnectParams>& reconnect_params,
     base::OnceClosure connected_callback,
     HostStateConnectedCallback host_state_connected_callback,
     base::OnceClosure host_state_disconnected_callback,
@@ -314,7 +314,7 @@
           ErrorCodeToString(protocol::ErrorCode::INCOMPATIBLE_PROTOCOL));
       return;
     }
-    absl::optional<int> access_code_lifetime =
+    std::optional<int> access_code_lifetime =
         message.FindInt(kAccessCodeLifetime);
     if (!access_code_lifetime) {
       LOG(ERROR) << "Missing |" << kAccessCodeLifetime << "| value in message.";
@@ -336,7 +336,7 @@
     }
     remote_->OnHostStateConnected(*remote_username);
 
-    absl::optional<ReconnectParams> reconnect_params;
+    std::optional<ReconnectParams> reconnect_params;
     const auto* reconnect_params_ptr = message.FindDict(kReconnectParamsDict);
     if (reconnect_params_ptr) {
       reconnect_params.emplace(
@@ -375,7 +375,7 @@
 void It2MeNativeMessageHostAsh::HandleNatPolicyChangedMessage(
     base::Value::Dict message) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<bool> nat_enabled =
+  std::optional<bool> nat_enabled =
       message.FindBool(kNatPolicyChangedMessageNatEnabled);
   if (!nat_enabled.has_value()) {
     LOG(ERROR) << "Missing |" << kNatPolicyChangedMessageNatEnabled
@@ -384,7 +384,7 @@
     return;
   }
 
-  absl::optional<bool> relay_enabled =
+  std::optional<bool> relay_enabled =
       message.FindBool(kNatPolicyChangedMessageRelayEnabled);
   if (!nat_enabled.has_value()) {
     LOG(ERROR) << "Missing |" << kNatPolicyChangedMessageRelayEnabled
diff --git a/remoting/host/it2me/it2me_native_messaging_host_ash.h b/remoting/host/it2me/it2me_native_messaging_host_ash.h
index 51cbf43..deb699ad 100644
--- a/remoting/host/it2me/it2me_native_messaging_host_ash.h
+++ b/remoting/host/it2me/it2me_native_messaging_host_ash.h
@@ -7,6 +7,7 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/sequence_checker.h"
 #include "base/thread_annotations.h"
 #include "base/values.h"
@@ -15,7 +16,6 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "remoting/host/chromeos/chromeos_enterprise_params.h"
 #include "remoting/host/mojom/remote_support.mojom.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace extensions {
 class NativeMessageHost;
@@ -45,7 +45,7 @@
   ~It2MeNativeMessageHostAsh() override;
 
   using HostStateConnectedCallback =
-      base::OnceCallback<void(absl::optional<ReconnectParams>)>;
+      base::OnceCallback<void(std::optional<ReconnectParams>)>;
 
   // Creates a new NMH instance, creates a new SupportHostObserver remote and
   // returns the pending_remote.  Start() must be called before the first call
@@ -62,14 +62,13 @@
   // |connected_callback| is run after the connection process has completed.
   // If `reconnect_params` is set then the new connection will allow a
   // previously connected client to reconnect.
-  void Connect(
-      const mojom::SupportSessionParams& params,
-      const absl::optional<ChromeOsEnterpriseParams>& enterprise_params,
-      const absl::optional<ReconnectParams>& reconnect_params,
-      base::OnceClosure connected_callback,
-      HostStateConnectedCallback host_state_connected_callback,
-      base::OnceClosure host_state_disconnected_callback,
-      base::OnceClosure disconnected_callback);
+  void Connect(const mojom::SupportSessionParams& params,
+               const std::optional<ChromeOsEnterpriseParams>& enterprise_params,
+               const std::optional<ReconnectParams>& reconnect_params,
+               base::OnceClosure connected_callback,
+               HostStateConnectedCallback host_state_connected_callback,
+               base::OnceClosure host_state_disconnected_callback,
+               base::OnceClosure disconnected_callback);
   // Disconnects an active session if one exists.
   void Disconnect();
 
diff --git a/remoting/host/it2me/it2me_native_messaging_host_lacros.cc b/remoting/host/it2me/it2me_native_messaging_host_lacros.cc
index e9a58ae2f..d503a06 100644
--- a/remoting/host/it2me/it2me_native_messaging_host_lacros.cc
+++ b/remoting/host/it2me/it2me_native_messaging_host_lacros.cc
@@ -41,7 +41,7 @@
 constexpr int kInvalidMessageId = -1;
 
 int GetMessageId(const base::Value::Dict& message) {
-  absl::optional<int> message_id = message.FindInt(kMessageId);
+  std::optional<int> message_id = message.FindInt(kMessageId);
   return message_id.value_or(kInvalidMessageId);
 }
 
@@ -89,7 +89,7 @@
   void OnHostStateConnecting() override;
   void OnHostStateConnected(const std::string& remote_username) override;
   void OnHostStateDisconnected(
-      const absl::optional<std::string>& disconnect_reason) override;
+      const std::optional<std::string>& disconnect_reason) override;
   void OnNatPolicyChanged(mojom::NatPolicyStatePtr policy_state) override;
   void OnHostStateError(int64_t error_code) override;
   void OnPolicyError() override;
@@ -219,7 +219,7 @@
 }
 
 void It2MeNativeMessagingHostLacros::OnHostStateDisconnected(
-    const absl::optional<std::string>& disconnect_reason) {
+    const std::optional<std::string>& disconnect_reason) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   base::Value::Dict message;
   if (disconnect_reason.has_value()) {
diff --git a/remoting/host/it2me/it2me_native_messaging_host_unittest.cc b/remoting/host/it2me/it2me_native_messaging_host_unittest.cc
index 22bdcc54..882785cc 100644
--- a/remoting/host/it2me/it2me_native_messaging_host_unittest.cc
+++ b/remoting/host/it2me/it2me_native_messaging_host_unittest.cc
@@ -51,7 +51,7 @@
 const char kTestStunServer[] = "test_relay_server.com";
 
 void VerifyId(const base::Value::Dict& response, int expected_value) {
-  absl::optional<int> value = response.FindInt(kMessageId);
+  std::optional<int> value = response.FindInt(kMessageId);
   ASSERT_TRUE(value);
   EXPECT_EQ(expected_value, *value);
 }
@@ -72,7 +72,7 @@
   ASSERT_TRUE(string_value);
   EXPECT_EQ(type, *string_value);
 
-  absl::optional<int> int_value = response.FindInt(kMessageId);
+  std::optional<int> int_value = response.FindInt(kMessageId);
   ASSERT_TRUE(int_value);
   EXPECT_EQ(id, *int_value);
 }
@@ -231,7 +231,7 @@
 
  protected:
   void SetPolicies(base::Value::Dict dict);
-  absl::optional<base::Value::Dict> ReadMessageFromOutputPipe();
+  std::optional<base::Value::Dict> ReadMessageFromOutputPipe();
   void WriteMessageToInputPipe(const base::Value::Dict& message);
 
   void VerifyHelloResponse(int request_id);
@@ -248,7 +248,7 @@
                       bool expect_error_response);
   void TestConnect();
 
-  const absl::optional<ChromeOsEnterpriseParams>
+  const std::optional<ChromeOsEnterpriseParams>
   get_chrome_os_enterprise_params() {
     return factory_raw_ptr_->host->chrome_os_enterprise_params_;
   }
@@ -330,7 +330,7 @@
   test_run_loop_->Run();
 
   // Verify there are no more message in the output pipe.
-  absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
+  std::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
   EXPECT_FALSE(response);
 
   // The It2MeNativeMessagingHost dtor closes the handles that are passed to it.
@@ -358,7 +358,7 @@
   policy_run_loop_.reset(nullptr);
 }
 
-absl::optional<base::Value::Dict>
+std::optional<base::Value::Dict>
 It2MeNativeMessagingHostTest::ReadMessageFromOutputPipe() {
   while (true) {
     uint32_t length;
@@ -366,7 +366,7 @@
         reinterpret_cast<char*>(&length), sizeof(length));
     if (read_result != sizeof(length)) {
       // The output pipe has been closed, return an empty message.
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     std::string message_json(length, '\0');
@@ -375,13 +375,13 @@
     if (read_result != static_cast<int>(length)) {
       LOG(ERROR) << "Message size (" << read_result
                  << ") doesn't match the header (" << length << ").";
-      return absl::nullopt;
+      return std::nullopt;
     }
 
-    absl::optional<base::Value> message = base::JSONReader::Read(message_json);
+    std::optional<base::Value> message = base::JSONReader::Read(message_json);
     if (!message || !message->is_dict()) {
       LOG(ERROR) << "Malformed message:" << message_json;
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     base::Value::Dict result = std::move(*message).TakeDict();
@@ -405,13 +405,13 @@
 }
 
 void It2MeNativeMessagingHostTest::VerifyHelloResponse(int request_id) {
-  absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
+  std::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
   ASSERT_TRUE(response);
   VerifyCommonProperties(*response, kHelloResponse, request_id);
 }
 
 void It2MeNativeMessagingHostTest::VerifyErrorResponse() {
-  absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
+  std::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
   ASSERT_TRUE(response);
   VerifyStringProperty(*response, kMessageType, kErrorMessage);
 }
@@ -428,7 +428,7 @@
   // We expect a total of 7 messages: 1 connectResponse, 1 natPolicyChanged,
   // and 5 hostStateChanged.
   for (int i = 0; i < 7; ++i) {
-    absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
+    std::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
     ASSERT_TRUE(response);
 
     const std::string* type = response->FindString(kMessageType);
@@ -461,7 +461,7 @@
         ASSERT_TRUE(value);
         EXPECT_EQ(kTestAccessCode, *value);
 
-        absl::optional<int> access_code_lifetime =
+        std::optional<int> access_code_lifetime =
             response->FindInt(kAccessCodeLifetime);
         ASSERT_TRUE(access_code_lifetime);
         EXPECT_EQ(kTestAccessCodeLifetime.InSeconds(), *access_code_lifetime);
@@ -491,7 +491,7 @@
 
   // We expect a total of 2 messages: disconnectResponse and hostStateChanged.
   for (int i = 0; i < 2; i++) {
-    absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
+    std::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
     ASSERT_TRUE(response);
 
     const std::string* type = response->FindString(kMessageType);
@@ -520,7 +520,7 @@
 }
 
 void It2MeNativeMessagingHostTest::VerifyPolicyErrorResponse() {
-  absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
+  std::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
   ASSERT_TRUE(response);
   const std::string* type = response->FindString(kMessageType);
   ASSERT_TRUE(type);
@@ -544,7 +544,7 @@
     VerifyErrorResponse();
   }
 
-  absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
+  std::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
   EXPECT_FALSE(response);
 }
 
@@ -639,7 +639,7 @@
   message.Set(kMessageId, "42");
   WriteMessageToInputPipe(message);
 
-  absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
+  std::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
   ASSERT_TRUE(response);
   const std::string* value = response->FindString(kMessageId);
   EXPECT_FALSE(value);
diff --git a/remoting/host/keyboard_layout_monitor_linux.cc b/remoting/host/keyboard_layout_monitor_linux.cc
index 87e13fa..f9f7d51 100644
--- a/remoting/host/keyboard_layout_monitor_linux.cc
+++ b/remoting/host/keyboard_layout_monitor_linux.cc
@@ -6,6 +6,7 @@
 
 #include <gdk/gdk.h>
 
+#include <optional>
 #include "base/files/file_descriptor_watcher_posix.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
@@ -19,7 +20,6 @@
 #include "remoting/host/linux/keyboard_layout_monitor_wayland.h"
 #include "remoting/host/linux/wayland_utils.h"
 #include "remoting/proto/control.pb.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/glib/scoped_gsignal.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
diff --git a/remoting/host/keyboard_layout_monitor_mac.cc b/remoting/host/keyboard_layout_monitor_mac.cc
index dea23f0..4cedac5 100644
--- a/remoting/host/keyboard_layout_monitor_mac.cc
+++ b/remoting/host/keyboard_layout_monitor_mac.cc
@@ -11,6 +11,7 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "base/apple/scoped_cftyperef.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
@@ -20,7 +21,6 @@
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/single_thread_task_runner.h"
 #include "remoting/proto/control.pb.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
 
@@ -59,9 +59,9 @@
   base::WeakPtrFactory<KeyboardLayoutMonitorMac> weak_ptr_factory_;
 };
 
-absl::optional<protocol::LayoutKeyFunction> GetFixedKeyFunction(int keycode);
-absl::optional<protocol::LayoutKeyFunction> GetCharFunction(UniChar char_code,
-                                                            int keycode);
+std::optional<protocol::LayoutKeyFunction> GetFixedKeyFunction(int keycode);
+std::optional<protocol::LayoutKeyFunction> GetCharFunction(UniChar char_code,
+                                                           int keycode);
 
 KeyboardLayoutMonitorMac::KeyboardLayoutMonitorMac(
     base::RepeatingCallback<void(const protocol::KeyboardLayout&)> callback)
@@ -169,7 +169,7 @@
         *(*layout_message.mutable_keys())[usb_code].mutable_actions();
 
     for (int shift_level = 0; shift_level < 4; ++shift_level) {
-      absl::optional<protocol::LayoutKeyFunction> fixed_function =
+      std::optional<protocol::LayoutKeyFunction> fixed_function =
           GetFixedKeyFunction(keycode);
       if (fixed_function) {
         key_actions[shift_level].set_function(*fixed_function);
@@ -198,7 +198,7 @@
       }
 
       if (result_length == 1) {
-        absl::optional<protocol::LayoutKeyFunction> char_function =
+        std::optional<protocol::LayoutKeyFunction> char_function =
             GetCharFunction(result_array[0], keycode);
         if (char_function) {
           key_actions[shift_level].set_function(*char_function);
@@ -222,7 +222,7 @@
                      callback_context->weak_ptr, std::move(layout_message)));
 }
 
-absl::optional<protocol::LayoutKeyFunction> GetFixedKeyFunction(int keycode) {
+std::optional<protocol::LayoutKeyFunction> GetFixedKeyFunction(int keycode) {
   // Some keys are not represented in the layout and always have the same
   // function.
   switch (keycode) {
@@ -283,12 +283,12 @@
     case kVK_JIS_Eisu:
       return protocol::LayoutKeyFunction::EISU;
     default:
-      return absl::nullopt;
+      return std::nullopt;
   }
 }
 
-absl::optional<protocol::LayoutKeyFunction> GetCharFunction(UniChar char_code,
-                                                            int keycode) {
+std::optional<protocol::LayoutKeyFunction> GetCharFunction(UniChar char_code,
+                                                           int keycode) {
   switch (char_code) {
     case kHomeCharCode:
       return protocol::LayoutKeyFunction::HOME;
@@ -333,7 +333,7 @@
     case kDeleteCharCode:
       return protocol::LayoutKeyFunction::DELETE_;
     default:
-      return absl::nullopt;
+      return std::nullopt;
   }
 }
 
diff --git a/remoting/host/linux/input_injector_wayland.cc b/remoting/host/linux/input_injector_wayland.cc
index 797d8b3..9be5cce7 100644
--- a/remoting/host/linux/input_injector_wayland.cc
+++ b/remoting/host/linux/input_injector_wayland.cc
@@ -11,6 +11,7 @@
 #include <set>
 #include <utility>
 
+#include <optional>
 #include "base/containers/contains.h"
 #include "base/containers/queue.h"
 #include "base/functional/bind.h"
@@ -32,7 +33,6 @@
 #include "remoting/host/linux/unicode_to_keysym.h"
 #include "remoting/host/linux/wayland_manager.h"
 #include "remoting/proto/internal.pb.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
 #include "third_party/webrtc/modules/desktop_capture/linux/wayland/scoped_glib.h"
 #include "third_party/webrtc/modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h"
@@ -240,7 +240,7 @@
     return;
   }
   if (!clipboard_initialized_) {
-    pending_clipboard_event_ = absl::make_optional(event);
+    pending_clipboard_event_ = std::make_optional(event);
     return;
   }
   clipboard_->InjectClipboardEvent(event);
diff --git a/remoting/host/linux/input_injector_wayland.h b/remoting/host/linux/input_injector_wayland.h
index 72b5cb59..c6a5d2c4 100644
--- a/remoting/host/linux/input_injector_wayland.h
+++ b/remoting/host/linux/input_injector_wayland.h
@@ -13,6 +13,7 @@
 #include <set>
 #include <utility>
 
+#include <optional>
 #include "base/containers/queue.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
@@ -32,7 +33,6 @@
 #include "remoting/host/linux/remote_desktop_portal_injector.h"
 #include "remoting/host/linux/wayland_manager.h"
 #include "remoting/proto/internal.pb.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "remoting/host/chromeos/point_transformer.h"
@@ -121,7 +121,7 @@
 
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
     std::set<int> pressed_keys_;
-    absl::optional<webrtc::DesktopVector> latest_mouse_position_;
+    std::optional<webrtc::DesktopVector> latest_mouse_position_;
     float wheel_ticks_x_ = 0;
     float wheel_ticks_y_ = 0;
     base::TimeTicks latest_tick_y_event_;
@@ -141,7 +141,7 @@
     // but separated so that the remote desktop isn't blocked waiting for the
     // clipboard.
     bool clipboard_initialized_ = false;
-    absl::optional<protocol::ClipboardEvent> pending_clipboard_event_;
+    std::optional<protocol::ClipboardEvent> pending_clipboard_event_;
 
     // Keeps track of whether or not the associated seat has keyboard
     // capability.
diff --git a/remoting/host/linux/remoting_user_session.cc b/remoting/host/linux/remoting_user_session.cc
index 88693c0..a27dedd 100644
--- a/remoting/host/linux/remoting_user_session.cc
+++ b/remoting/host/linux/remoting_user_session.cc
@@ -37,6 +37,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/environment.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -46,7 +47,6 @@
 #include "base/strings/strcat.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -99,13 +99,13 @@
 // Shell-escapes a single argument in a way that is compatible with various
 // different shells. Returns nullopt when argument contains a newline, which
 // can't be represented in a cross-shell fashion.
-absl::optional<std::string> ShellEscapeArgument(
+std::optional<std::string> ShellEscapeArgument(
     const base::StringPiece argument) {
   std::string result;
   for (char character : argument) {
     // csh in particular doesn't provide a good way to handle this
     if (character == '\n') {
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     // Some shells ascribe special meaning to some escape sequences such as \t,
@@ -231,12 +231,12 @@
 
   // Returns the current username according to PAM. It is possible for PAM
   // modules to change this from the initial value passed to the constructor.
-  absl::optional<std::string> GetUser() {
+  std::optional<std::string> GetUser() {
     const char* user;
     last_return_code_ = pam_get_item(pam_handle_, PAM_USER,
                                      reinterpret_cast<const void**>(&user));
     if (last_return_code_ != PAM_SUCCESS || user == nullptr) {
-      return absl::nullopt;
+      return std::nullopt;
     }
     return std::string(user);
   }
@@ -248,11 +248,11 @@
   }
 
   // Obtains the list of environment variables provided by PAM modules.
-  absl::optional<base::EnvironmentMap> GetEnvironment() {
+  std::optional<base::EnvironmentMap> GetEnvironment() {
     char** environment = pam_getenvlist(pam_handle_);
 
     if (environment == nullptr) {
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     base::EnvironmentMap environment_map;
@@ -323,14 +323,14 @@
   // argv[0] with a '-'.
   std::string shell_name = '-' + base::FilePath(login_shell).BaseName().value();
 
-  absl::optional<std::string> escaped_script_path =
+  std::optional<std::string> escaped_script_path =
       ShellEscapeArgument(FindScriptPath());
   CHECK(escaped_script_path) << "Could not escape script path";
 
   std::string shell_arg = *escaped_script_path + " --start --child-process";
 
   for (const std::string& arg : script_args) {
-    absl::optional<std::string> escaped_arg = ShellEscapeArgument(arg);
+    std::optional<std::string> escaped_arg = ShellEscapeArgument(arg);
     CHECK(escaped_arg) << "Could not escape script argument";
     shell_arg += " ";
     shell_arg += *escaped_arg;
@@ -369,7 +369,7 @@
 
 // Either |user| must be set when running as root, xor the real user ID must be
 // properly set when running as a user.
-void Relaunch(const absl::optional<std::string>& user,
+void Relaunch(const std::optional<std::string>& user,
               const std::vector<std::string>& script_args) {
   CHECK(user.has_value() == (getuid() == 0));
 
@@ -400,7 +400,7 @@
 // Returns: whether the session should be relaunched.
 bool ExecuteSession(std::string user,
                     bool chown_log,
-                    absl::optional<uid_t> match_uid,
+                    std::optional<uid_t> match_uid,
                     const std::vector<std::string>& script_args) {
   PamHandle pam_handle(kPamName, user.c_str(), &kPamConversation);
   CHECK(pam_handle.IsInitialized()) << "Failed to initialize PAM";
@@ -492,7 +492,7 @@
   if (child_pid == 0) {
     PCHECK(setuid(pwinfo->pw_uid) == 0) << "setuid failed";
     PCHECK(chdir(pwinfo->pw_dir) == 0) << "chdir to $HOME failed";
-    absl::optional<base::EnvironmentMap> pam_environment =
+    std::optional<base::EnvironmentMap> pam_environment =
         pam_handle.GetEnvironment();
     CHECK(pam_environment) << "Failed to get environment from PAM";
 
@@ -803,7 +803,7 @@
   argv += 2;
 
   bool foreground = false;
-  absl::optional<std::string> user;
+  std::optional<std::string> user;
   std::vector<std::string> script_args;
 
   while (argc > 0) {
@@ -855,8 +855,8 @@
   // Daemonizing redirects stdout to a log file, which we want to be owned by
   // the target user.
   bool chown_stdout = !foreground;
-  absl::optional<uid_t> match_uid =
-      real_uid != 0 ? absl::make_optional(real_uid) : absl::nullopt;
+  std::optional<uid_t> match_uid =
+      real_uid != 0 ? std::make_optional(real_uid) : std::nullopt;
 
   // Fork before opening PAM session so relaunches don't descend from the closed
   // PAM session.
@@ -885,7 +885,7 @@
       // If running as root, forward the username argument to the relaunched
       // process. Otherwise, it should be inferred from the user id and
       // environment.
-      Relaunch(real_uid == 0 ? user : absl::nullopt, script_args);
+      Relaunch(real_uid == 0 ? user : std::nullopt, script_args);
     }
   }
 
diff --git a/remoting/host/mojom/remoting_mojom_traits.cc b/remoting/host/mojom/remoting_mojom_traits.cc
index 7fbfe245..2ea9b8c 100644
--- a/remoting/host/mojom/remoting_mojom_traits.cc
+++ b/remoting/host/mojom/remoting_mojom_traits.cc
@@ -95,7 +95,7 @@
   out_options->set_enable_remote_open_url(data_view.enable_remote_open_url());
   out_options->set_enable_remote_webauthn(data_view.enable_remote_webauthn());
 
-  absl::optional<uint32_t> clipboard_size;
+  std::optional<uint32_t> clipboard_size;
   if (!data_view.ReadClipboardSize(&clipboard_size)) {
     return false;
   }
@@ -210,7 +210,7 @@
   }
   out_error->set_type(type);
 
-  absl::optional<int32_t> api_error_code;
+  std::optional<int32_t> api_error_code;
   if (!data_view.ReadApiErrorCode(&api_error_code)) {
     return false;
   }
@@ -283,7 +283,7 @@
   out_event->set_usb_keycode(data_view.usb_keycode());
   out_event->set_lock_states(data_view.lock_states());
 
-  absl::optional<bool> caps_lock_state;
+  std::optional<bool> caps_lock_state;
   if (!data_view.ReadCapsLockState(&caps_lock_state)) {
     return false;
   }
@@ -291,7 +291,7 @@
     out_event->set_caps_lock_state(*caps_lock_state);
   }
 
-  absl::optional<bool> num_lock_state;
+  std::optional<bool> num_lock_state;
   if (!data_view.ReadNumLockState(&num_lock_state)) {
     return false;
   }
@@ -349,7 +349,7 @@
                         ::remoting::protocol::MouseEvent>::
     Read(remoting::mojom::MouseEventDataView data_view,
          ::remoting::protocol::MouseEvent* out_event) {
-  absl::optional<int32_t> x;
+  std::optional<int32_t> x;
   if (!data_view.ReadX(&x)) {
     return false;
   }
@@ -357,7 +357,7 @@
     out_event->set_x(*x);
   }
 
-  absl::optional<int32_t> y;
+  std::optional<int32_t> y;
   if (!data_view.ReadY(&y)) {
     return false;
   }
@@ -373,7 +373,7 @@
     out_event->set_button(mouse_button);
   }
 
-  absl::optional<bool> button_down;
+  std::optional<bool> button_down;
   if (!data_view.ReadButtonDown(&button_down)) {
     return false;
   }
@@ -381,7 +381,7 @@
     out_event->set_button_down(*button_down);
   }
 
-  absl::optional<float> wheel_delta_x;
+  std::optional<float> wheel_delta_x;
   if (!data_view.ReadWheelDeltaX(&wheel_delta_x)) {
     return false;
   }
@@ -389,7 +389,7 @@
     out_event->set_wheel_delta_x(*wheel_delta_x);
   }
 
-  absl::optional<float> wheel_delta_y;
+  std::optional<float> wheel_delta_y;
   if (!data_view.ReadWheelDeltaY(&wheel_delta_y)) {
     return false;
   }
@@ -397,7 +397,7 @@
     out_event->set_wheel_delta_y(*wheel_delta_y);
   }
 
-  absl::optional<float> wheel_ticks_x;
+  std::optional<float> wheel_ticks_x;
   if (!data_view.ReadWheelTicksX(&wheel_ticks_x)) {
     return false;
   }
@@ -405,7 +405,7 @@
     out_event->set_wheel_ticks_x(*wheel_ticks_x);
   }
 
-  absl::optional<float> wheel_ticks_y;
+  std::optional<float> wheel_ticks_y;
   if (!data_view.ReadWheelTicksY(&wheel_ticks_y)) {
     return false;
   }
@@ -413,7 +413,7 @@
     out_event->set_wheel_ticks_y(*wheel_ticks_y);
   }
 
-  absl::optional<int32_t> delta_x;
+  std::optional<int32_t> delta_x;
   if (!data_view.ReadDeltaX(&delta_x)) {
     return false;
   }
@@ -421,7 +421,7 @@
     out_event->set_delta_x(*delta_x);
   }
 
-  absl::optional<int32_t> delta_y;
+  std::optional<int32_t> delta_y;
   if (!data_view.ReadDeltaY(&delta_y)) {
     return false;
   }
diff --git a/remoting/host/mojom/remoting_mojom_traits.h b/remoting/host/mojom/remoting_mojom_traits.h
index 4bc1e72..b89795d 100644
--- a/remoting/host/mojom/remoting_mojom_traits.h
+++ b/remoting/host/mojom/remoting_mojom_traits.h
@@ -9,6 +9,7 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/files/file_path.h"
 #include "base/numerics/safe_conversions.h"
@@ -35,7 +36,6 @@
 #include "remoting/protocol/file_transfer_helpers.h"
 #include "remoting/protocol/transport.h"
 #include "services/network/public/cpp/ip_endpoint_mojom_traits.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
 #include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
 #include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
@@ -152,10 +152,10 @@
     return options.enable_remote_webauthn();
   }
 
-  static absl::optional<uint32_t> clipboard_size(
+  static std::optional<uint32_t> clipboard_size(
       const ::remoting::DesktopEnvironmentOptions& options) {
     if (!options.clipboard_size().has_value()) {
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     size_t clipboard_size = options.clipboard_size().value();
@@ -618,12 +618,12 @@
     return error.type();
   }
 
-  static absl::optional<int32_t> api_error_code(
+  static std::optional<int32_t> api_error_code(
       const ::remoting::protocol::FileTransfer_Error& error) {
     if (error.has_api_error_code()) {
       return error.api_error_code();
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   static const std::string& function(
@@ -1169,20 +1169,20 @@
     return event.lock_states();
   }
 
-  static absl::optional<bool> caps_lock_state(
+  static std::optional<bool> caps_lock_state(
       const ::remoting::protocol::KeyEvent& event) {
     if (event.has_caps_lock_state()) {
       return event.caps_lock_state();
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
-  static absl::optional<bool> num_lock_state(
+  static std::optional<bool> num_lock_state(
       const ::remoting::protocol::KeyEvent& event) {
     if (event.has_num_lock_state()) {
       return event.num_lock_state();
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   static bool Read(remoting::mojom::KeyEventDataView data_view,
@@ -1193,20 +1193,20 @@
 class StructTraits<remoting::mojom::MouseEventDataView,
                    ::remoting::protocol::MouseEvent> {
  public:
-  static absl::optional<int32_t> x(
+  static std::optional<int32_t> x(
       const ::remoting::protocol::MouseEvent& event) {
     if (event.has_x()) {
       return event.x();
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
-  static absl::optional<int32_t> y(
+  static std::optional<int32_t> y(
       const ::remoting::protocol::MouseEvent& event) {
     if (event.has_y()) {
       return event.y();
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   static ::remoting::protocol::MouseEvent::MouseButton button(
@@ -1217,61 +1217,61 @@
     return ::remoting::protocol::MouseEvent::BUTTON_UNDEFINED;
   }
 
-  static absl::optional<bool> button_down(
+  static std::optional<bool> button_down(
       const ::remoting::protocol::MouseEvent& event) {
     if (event.has_button_down()) {
       DCHECK(event.has_button());
       return event.button_down();
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
-  static absl::optional<float> wheel_delta_x(
+  static std::optional<float> wheel_delta_x(
       const ::remoting::protocol::MouseEvent& event) {
     if (event.has_wheel_delta_x()) {
       return event.wheel_delta_x();
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
-  static absl::optional<float> wheel_delta_y(
+  static std::optional<float> wheel_delta_y(
       const ::remoting::protocol::MouseEvent& event) {
     if (event.has_wheel_delta_y()) {
       return event.wheel_delta_y();
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
-  static absl::optional<float> wheel_ticks_x(
+  static std::optional<float> wheel_ticks_x(
       const ::remoting::protocol::MouseEvent& event) {
     if (event.wheel_ticks_x()) {
       return event.wheel_ticks_x();
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
-  static absl::optional<float> wheel_ticks_y(
+  static std::optional<float> wheel_ticks_y(
       const ::remoting::protocol::MouseEvent& event) {
     if (event.wheel_ticks_y()) {
       return event.wheel_ticks_y();
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
-  static absl::optional<int32_t> delta_x(
+  static std::optional<int32_t> delta_x(
       const ::remoting::protocol::MouseEvent& event) {
     if (event.has_delta_x()) {
       return event.delta_x();
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
-  static absl::optional<int32_t> delta_y(
+  static std::optional<int32_t> delta_y(
       const ::remoting::protocol::MouseEvent& event) {
     if (event.has_delta_y()) {
       return event.delta_y();
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   static bool Read(remoting::mojom::MouseEventDataView data_view,
diff --git a/remoting/host/native_messaging/native_messaging_helpers.cc b/remoting/host/native_messaging/native_messaging_helpers.cc
index b434fa8..d1feaeb 100644
--- a/remoting/host/native_messaging/native_messaging_helpers.cc
+++ b/remoting/host/native_messaging/native_messaging_helpers.cc
@@ -37,12 +37,12 @@
   return true;
 }
 
-absl::optional<base::Value::Dict> CreateNativeMessageResponse(
+std::optional<base::Value::Dict> CreateNativeMessageResponse(
     const base::Value::Dict& request) {
   const std::string* type = request.FindString(kMessageType);
   if (!type) {
     LOG(ERROR) << "'" << kMessageType << "' not found in request.";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   base::Value::Dict response;
diff --git a/remoting/host/native_messaging/native_messaging_helpers.h b/remoting/host/native_messaging/native_messaging_helpers.h
index 7653245..c9853d4 100644
--- a/remoting/host/native_messaging/native_messaging_helpers.h
+++ b/remoting/host/native_messaging/native_messaging_helpers.h
@@ -7,8 +7,8 @@
 
 #include <string>
 
+#include <optional>
 #include "base/values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -23,7 +23,7 @@
 // is malformed.
 // For a request like this: {id: "abc", type: "hello"}, the response will be:
 // {id: "abc", type: "helloResponse"}.
-absl::optional<base::Value::Dict> CreateNativeMessageResponse(
+std::optional<base::Value::Dict> CreateNativeMessageResponse(
     const base::Value::Dict& request);
 
 // Adds hello response fields to |response|, which should be created by calling
diff --git a/remoting/host/native_messaging/native_messaging_pipe.cc b/remoting/host/native_messaging/native_messaging_pipe.cc
index 78332b4..bd6c5bf 100644
--- a/remoting/host/native_messaging/native_messaging_pipe.cc
+++ b/remoting/host/native_messaging/native_messaging_pipe.cc
@@ -37,7 +37,7 @@
 
 void NativeMessagingPipe::PostMessageFromNativeHost(
     const std::string& message) {
-  absl::optional<base::Value> json = base::JSONReader::Read(message);
+  std::optional<base::Value> json = base::JSONReader::Read(message);
   channel_->SendMessage(json);
 }
 
diff --git a/remoting/host/native_messaging/native_messaging_reader.cc b/remoting/host/native_messaging/native_messaging_reader.cc
index 6574cb3..e2f066af 100644
--- a/remoting/host/native_messaging/native_messaging_reader.cc
+++ b/remoting/host/native_messaging/native_messaging_reader.cc
@@ -121,7 +121,7 @@
       return;
     }
 
-    absl::optional<base::Value> message = base::JSONReader::Read(message_json);
+    std::optional<base::Value> message = base::JSONReader::Read(message_json);
     if (!message) {
       LOG(ERROR) << "Failed to parse JSON message: " << message_json;
       NotifyEof();
diff --git a/remoting/host/native_messaging/native_messaging_reader_unittest.cc b/remoting/host/native_messaging/native_messaging_reader_unittest.cc
index 8cda736a..6c0da95d 100644
--- a/remoting/host/native_messaging/native_messaging_reader_unittest.cc
+++ b/remoting/host/native_messaging/native_messaging_reader_unittest.cc
@@ -8,6 +8,7 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
@@ -15,7 +16,6 @@
 #include "build/build_config.h"
 #include "remoting/host/setup/test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -47,7 +47,7 @@
   base::File read_file_;
   base::File write_file_;
   bool on_error_signaled_ = false;
-  absl::optional<base::Value> message_;
+  std::optional<base::Value> message_;
 
  private:
   // MessageLoop declared here, since the NativeMessageReader ctor requires a
@@ -133,7 +133,7 @@
   ASSERT_TRUE(message_);
 
   ASSERT_TRUE(message_->is_dict());
-  absl::optional<int> result = message_->GetDict().FindInt("foo");
+  std::optional<int> result = message_->GetDict().FindInt("foo");
   ASSERT_TRUE(result.has_value());
   ASSERT_EQ(42, result);
 }
@@ -154,7 +154,7 @@
     ASSERT_FALSE(on_error_signaled_);
     ASSERT_TRUE(message_);
     ASSERT_TRUE(message_->is_dict());
-    absl::optional<int> result = message_->GetDict().FindInt("foo");
+    std::optional<int> result = message_->GetDict().FindInt("foo");
     ASSERT_TRUE(result.has_value());
     ASSERT_EQ(42, result);
   }
@@ -165,7 +165,7 @@
     ASSERT_FALSE(on_error_signaled_);
     ASSERT_TRUE(message_);
     ASSERT_TRUE(message_->is_dict());
-    absl::optional<int> result = message_->GetDict().FindInt("bar");
+    std::optional<int> result = message_->GetDict().FindInt("bar");
     ASSERT_TRUE(result.has_value());
     ASSERT_EQ(43, result);
   }
@@ -176,7 +176,7 @@
     ASSERT_FALSE(on_error_signaled_);
     ASSERT_TRUE(message_);
     ASSERT_TRUE(message_->is_dict());
-    absl::optional<int> result = message_->GetDict().FindInt("baz");
+    std::optional<int> result = message_->GetDict().FindInt("baz");
     ASSERT_TRUE(result.has_value());
     ASSERT_EQ(44, result);
   }
diff --git a/remoting/host/native_messaging/pipe_messaging_channel.cc b/remoting/host/native_messaging/pipe_messaging_channel.cc
index d0857acb..f7b73fb 100644
--- a/remoting/host/native_messaging/pipe_messaging_channel.cc
+++ b/remoting/host/native_messaging/pipe_messaging_channel.cc
@@ -63,8 +63,7 @@
   }
 }
 
-void PipeMessagingChannel::SendMessage(
-    absl::optional<base::ValueView> message) {
+void PipeMessagingChannel::SendMessage(std::optional<base::ValueView> message) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   bool success = message && native_messaging_writer_;
diff --git a/remoting/host/native_messaging/pipe_messaging_channel.h b/remoting/host/native_messaging/pipe_messaging_channel.h
index 5082601..ed75c206 100644
--- a/remoting/host/native_messaging/pipe_messaging_channel.h
+++ b/remoting/host/native_messaging/pipe_messaging_channel.h
@@ -49,7 +49,7 @@
 
   // extensions::NativeMessagingChannel implementation.
   void Start(EventHandler* event_handler) override;
-  void SendMessage(absl::optional<base::ValueView> message) override;
+  void SendMessage(std::optional<base::ValueView> message) override;
 
  private:
   // Processes a message received from the client app.
diff --git a/remoting/host/pairing_registry_delegate_win.cc b/remoting/host/pairing_registry_delegate_win.cc
index 7875e70..c4686c2 100644
--- a/remoting/host/pairing_registry_delegate_win.cc
+++ b/remoting/host/pairing_registry_delegate_win.cc
@@ -6,12 +6,12 @@
 
 #include <utility>
 
+#include <optional>
 #include "base/json/json_string_value_serializer.h"
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "base/win/registry.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #include <windows.h>
 
@@ -41,15 +41,15 @@
 
 // Reads value |value_name| from |key| as a JSON string and returns it as
 // |base::Value|.
-absl::optional<base::Value::Dict> ReadValue(const base::win::RegKey& key,
-                                            const wchar_t* value_name) {
+std::optional<base::Value::Dict> ReadValue(const base::win::RegKey& key,
+                                           const wchar_t* value_name) {
   // presubmit: allow wstring
   std::wstring value_json;
   LONG result = key.ReadValue(value_name, &value_json);
   if (result != ERROR_SUCCESS) {
     SetLastError(result);
     PLOG(ERROR) << "Cannot read value '" << value_name << "'";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Parse the value.
@@ -62,12 +62,12 @@
   if (!value) {
     LOG(ERROR) << "Failed to parse '" << value_name << "': " << error_message
                << " (" << error_code << ").";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (!value->is_dict()) {
     LOG(ERROR) << "Failed to parse '" << value_name << "': not a dictionary.";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return std::move(*value).TakeDict();
@@ -192,7 +192,7 @@
   std::wstring value_name = base::UTF8ToWide(client_id);
 
   // Read unprivileged fields first.
-  absl::optional<base::Value::Dict> pairing =
+  std::optional<base::Value::Dict> pairing =
       ReadValue(unprivileged_, value_name.c_str());
   if (!pairing) {
     return PairingRegistry::Pairing();
@@ -200,7 +200,7 @@
 
   // Read the shared secret.
   if (privileged_.Valid()) {
-    absl::optional<base::Value::Dict> secret =
+    std::optional<base::Value::Dict> secret =
         ReadValue(privileged_, value_name.c_str());
     if (!secret) {
       return PairingRegistry::Pairing();
@@ -224,7 +224,7 @@
   base::Value::Dict pairing_json = pairing.ToValue();
 
   // Extract the shared secret to a separate dictionary.
-  absl::optional<base::Value> secret_key =
+  std::optional<base::Value> secret_key =
       pairing_json.Extract(PairingRegistry::kSharedSecretKey);
   CHECK(secret_key.has_value());
   base::Value::Dict secret_json;
diff --git a/remoting/host/register_support_host_request.h b/remoting/host/register_support_host_request.h
index 16a7cee..711a4020 100644
--- a/remoting/host/register_support_host_request.h
+++ b/remoting/host/register_support_host_request.h
@@ -8,13 +8,13 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/functional/callback_forward.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/time/time.h"
 #include "remoting/base/rsa_key_pair.h"
 #include "remoting/host/chromeos/chromeos_enterprise_params.h"
 #include "remoting/protocol/errors.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -44,7 +44,7 @@
   virtual void StartRequest(SignalStrategy* signal_strategy,
                             scoped_refptr<RsaKeyPair> key_pair,
                             const std::string& authorized_helper,
-                            absl::optional<ChromeOsEnterpriseParams> params,
+                            std::optional<ChromeOsEnterpriseParams> params,
                             RegisterCallback callback) = 0;
 };
 
diff --git a/remoting/host/remote_open_url/remote_open_url_client_delegate_win.cc b/remoting/host/remote_open_url/remote_open_url_client_delegate_win.cc
index e455864..bde8b2f 100644
--- a/remoting/host/remote_open_url/remote_open_url_client_delegate_win.cc
+++ b/remoting/host/remote_open_url/remote_open_url_client_delegate_win.cc
@@ -54,7 +54,7 @@
   task_dialog.AppendButtonWithStringId(IDOK,
                                        IDS_OPEN_DEFAULT_APPS_SETTINGS_BUTTON);
   task_dialog.set_default_button(IDOK);
-  absl::optional<int> result = task_dialog.Show();
+  std::optional<int> result = task_dialog.Show();
   DCHECK_EQ(IDOK, *result);
   base::win::LaunchDefaultAppsSettingsModernDialog(/*protocol=*/std::wstring());
 }
diff --git a/remoting/host/remote_open_url/url_forwarder_configurator_main_win.cc b/remoting/host/remote_open_url/url_forwarder_configurator_main_win.cc
index fcc0376..10959ee 100644
--- a/remoting/host/remote_open_url/url_forwarder_configurator_main_win.cc
+++ b/remoting/host/remote_open_url/url_forwarder_configurator_main_win.cc
@@ -106,7 +106,7 @@
   }
   task_dialog.set_default_button(IDOK);
 
-  absl::optional<int> button_result = task_dialog.Show();
+  std::optional<int> button_result = task_dialog.Show();
   if (!button_result.has_value()) {
     LOG(ERROR) << "Failed to show the setup dialog.";
     return false;
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc
index cba37d0..f154a8bf 100644
--- a/remoting/host/remoting_me2me_host.cc
+++ b/remoting/host/remoting_me2me_host.cc
@@ -12,6 +12,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -109,7 +110,6 @@
 #include "remoting/signaling/ftl_signal_strategy.h"
 #include "remoting/signaling/remoting_log_to_server.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/rtc_base/event_tracer.h"
 
 #if BUILDFLAG(IS_POSIX)
@@ -417,7 +417,7 @@
   base::Value::Dict config_;
   std::string host_owner_;
   bool is_googler_ = false;
-  absl::optional<size_t> max_clipboard_size_;
+  std::optional<size_t> max_clipboard_size_;
 
   std::unique_ptr<PolicyWatcher> policy_watcher_;
   PolicyState policy_state_ = POLICY_INITIALIZING;
@@ -435,7 +435,7 @@
   ThirdPartyAuthConfig third_party_auth_config_;
   bool security_key_auth_policy_enabled_ = false;
   bool security_key_extension_supported_ = true;
-  absl::optional<int> max_session_duration_minutes_;
+  std::optional<int> max_session_duration_minutes_;
 
   // Allows us to override field trials which are causing issues for chromoting.
   std::unique_ptr<base::FieldTrialList> field_trial_list_;
@@ -642,7 +642,7 @@
 void HostProcess::OnConfigUpdated(const std::string& serialized_config) {
   HOST_LOG << "Parsing new host configuration.";
 
-  absl::optional<base::Value::Dict> config(
+  std::optional<base::Value::Dict> config(
       HostConfigFromJson(serialized_config));
   if (!config.has_value()) {
     LOG(ERROR) << "Invalid configuration.";
@@ -1392,7 +1392,7 @@
   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
-  absl::optional<bool> host_username_match_required =
+  std::optional<bool> host_username_match_required =
       policies.FindBool(policy::key::kRemoteAccessHostMatchUsername);
   if (!host_username_match_required.has_value()) {
     return false;
@@ -1408,7 +1408,7 @@
   // Returns true if the host has to be restarted after this policy update.
   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
 
-  absl::optional<bool> allow_nat_traversal =
+  std::optional<bool> allow_nat_traversal =
       policies.FindBool(policy::key::kRemoteAccessHostFirewallTraversal);
   if (!allow_nat_traversal.has_value()) {
     return false;
@@ -1427,7 +1427,7 @@
   // Returns true if the host has to be restarted after this policy update.
   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
 
-  absl::optional<bool> allow_relay =
+  std::optional<bool> allow_relay =
       policies.FindBool(policy::key::kRemoteAccessHostAllowRelayedConnection);
   if (!allow_relay.has_value()) {
     return false;
@@ -1464,7 +1464,7 @@
   // Returns true if the host has to be restarted after this policy update.
   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
 
-  absl::optional<bool> curtain_required =
+  std::optional<bool> curtain_required =
       policies.FindBool(policy::key::kRemoteAccessHostRequireCurtain);
   if (!curtain_required.has_value()) {
     return false;
@@ -1523,7 +1523,7 @@
 bool HostProcess::OnPairingPolicyUpdate(const base::Value::Dict& policies) {
   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
 
-  absl::optional<bool> allow_pairing =
+  std::optional<bool> allow_pairing =
       policies.FindBool(policy::key::kRemoteAccessHostAllowClientPairing);
   if (!allow_pairing.has_value()) {
     return false;
@@ -1541,7 +1541,7 @@
 bool HostProcess::OnGnubbyAuthPolicyUpdate(const base::Value::Dict& policies) {
   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
 
-  absl::optional<bool> security_key_auth_policy_enabled =
+  std::optional<bool> security_key_auth_policy_enabled =
       policies.FindBool(policy::key::kRemoteAccessHostAllowGnubbyAuth);
   if (!security_key_auth_policy_enabled.has_value()) {
     return false;
@@ -1561,7 +1561,7 @@
     const base::Value::Dict& policies) {
   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
 
-  absl::optional<bool> file_transfer_enabled =
+  std::optional<bool> file_transfer_enabled =
       policies.FindBool(policy::key::kRemoteAccessHostAllowFileTransfer);
   if (!file_transfer_enabled.has_value()) {
     return false;
@@ -1584,7 +1584,7 @@
     const base::Value::Dict& policies) {
   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
 
-  absl::optional<bool> enable_user_interface =
+  std::optional<bool> enable_user_interface =
       policies.FindBool(policy::key::kRemoteAccessHostEnableUserInterface);
   if (!enable_user_interface) {
     return false;
@@ -1607,7 +1607,7 @@
     const base::Value::Dict& policies) {
   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
 
-  absl::optional<int> value = policies.FindInt(
+  std::optional<int> value = policies.FindInt(
       policy::key::kRemoteAccessHostMaximumSessionDurationMinutes);
   if (!value) {
     return false;
@@ -1630,7 +1630,7 @@
     const base::Value::Dict& policies) {
   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
 
-  absl::optional<int> max_clipboard_size =
+  std::optional<int> max_clipboard_size =
       policies.FindInt(policy::key::kRemoteAccessHostClipboardSizeBytes);
   if (!max_clipboard_size) {
     return false;
@@ -1654,7 +1654,7 @@
   // Returns false: never restart the host after this policy update.
   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
 
-  absl::optional<bool> allow_remote_access_connections = policies.FindBool(
+  std::optional<bool> allow_remote_access_connections = policies.FindBool(
       policy::key::kRemoteAccessHostAllowRemoteAccessConnections);
   if (!allow_remote_access_connections.has_value()) {
     return false;
@@ -1810,7 +1810,7 @@
   } else if (desktop_environment_options_.clipboard_size().has_value()) {
     // If we've transitioned from having a policy value to no value then make
     // sure the value stored in desktop_environment_options has been cleared.
-    desktop_environment_options_.set_clipboard_size(absl::optional<size_t>());
+    desktop_environment_options_.set_clipboard_size(std::optional<size_t>());
   }
 
   host_ = std::make_unique<ChromotingHost>(
diff --git a/remoting/host/remoting_register_support_host_request.cc b/remoting/host/remoting_register_support_host_request.cc
index e23fa73..6283061 100644
--- a/remoting/host/remoting_register_support_host_request.cc
+++ b/remoting/host/remoting_register_support_host_request.cc
@@ -158,7 +158,7 @@
     SignalStrategy* signal_strategy,
     scoped_refptr<RsaKeyPair> key_pair,
     const std::string& authorized_helper,
-    absl::optional<ChromeOsEnterpriseParams> params,
+    std::optional<ChromeOsEnterpriseParams> params,
     RegisterCallback callback) {
   DCHECK_EQ(State::NOT_STARTED, state_);
   DCHECK(signal_strategy);
diff --git a/remoting/host/remoting_register_support_host_request.h b/remoting/host/remoting_register_support_host_request.h
index 835f6b0..e22af08 100644
--- a/remoting/host/remoting_register_support_host_request.h
+++ b/remoting/host/remoting_register_support_host_request.h
@@ -5,13 +5,13 @@
 #ifndef REMOTING_HOST_REMOTING_REGISTER_SUPPORT_HOST_REQUEST_H_
 #define REMOTING_HOST_REMOTING_REGISTER_SUPPORT_HOST_REQUEST_H_
 
+#include <optional>
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
 #include "remoting/host/chromeos/chromeos_enterprise_params.h"
 #include "remoting/host/register_support_host_request.h"
 #include "remoting/signaling/signal_strategy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace network {
 class SharedURLLoaderFactory;
@@ -52,7 +52,7 @@
   void StartRequest(SignalStrategy* signal_strategy,
                     scoped_refptr<RsaKeyPair> key_pair,
                     const std::string& authorized_helper,
-                    absl::optional<ChromeOsEnterpriseParams> params,
+                    std::optional<ChromeOsEnterpriseParams> params,
                     RegisterCallback callback) override;
 
  private:
@@ -98,7 +98,7 @@
   RegisterCallback callback_;
   std::unique_ptr<OAuthTokenGetter> token_getter_;
   std::unique_ptr<RegisterSupportHostClient> register_host_client_;
-  absl::optional<ChromeOsEnterpriseParams> enterprise_params_;
+  std::optional<ChromeOsEnterpriseParams> enterprise_params_;
   std::string authorized_helper_;
 
   State state_ = State::NOT_STARTED;
diff --git a/remoting/host/remoting_register_support_host_request_unittest.cc b/remoting/host/remoting_register_support_host_request_unittest.cc
index b6d9bcf..655f23f8 100644
--- a/remoting/host/remoting_register_support_host_request_unittest.cc
+++ b/remoting/host/remoting_register_support_host_request_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "remoting/host/remoting_register_support_host_request.h"
 
+#include <optional>
 #include "base/memory/raw_ptr.h"
 #include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
@@ -17,7 +18,6 @@
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -153,7 +153,7 @@
       .Times(1);
 
   register_host_request_->StartRequest(signal_strategy_.get(), key_pair_,
-                                       authorized_helper_, absl::nullopt,
+                                       authorized_helper_, std::nullopt,
                                        register_callback.Get());
   signal_strategy_->Connect();
 }
@@ -211,7 +211,7 @@
   authorized_helper_ = kTestAuthorizedHelper;
 
   register_host_request_->StartRequest(signal_strategy_.get(), key_pair_,
-                                       authorized_helper_, absl::nullopt,
+                                       authorized_helper_, std::nullopt,
                                        register_callback.Get());
   signal_strategy_->Connect();
 }
@@ -236,7 +236,7 @@
       .Times(1);
 
   register_host_request_->StartRequest(signal_strategy_.get(), key_pair_,
-                                       authorized_helper_, absl::nullopt,
+                                       authorized_helper_, std::nullopt,
                                        register_callback.Get());
   signal_strategy_->Connect();
 }
@@ -260,7 +260,7 @@
       .Times(1);
 
   register_host_request_->StartRequest(signal_strategy_.get(), key_pair_,
-                                       authorized_helper_, absl::nullopt,
+                                       authorized_helper_, std::nullopt,
                                        register_callback.Get());
   signal_strategy_->Connect();
   signal_strategy_->Disconnect();
diff --git a/remoting/host/resizing_host_observer.cc b/remoting/host/resizing_host_observer.cc
index a11cdf56..309b8f0 100644
--- a/remoting/host/resizing_host_observer.cc
+++ b/remoting/host/resizing_host_observer.cc
@@ -144,7 +144,7 @@
 
 void ResizingHostObserver::SetScreenResolution(
     const ScreenResolution& resolution,
-    absl::optional<webrtc::ScreenId> opt_screen_id) {
+    std::optional<webrtc::ScreenId> opt_screen_id) {
   // Get the current time. This function is called exactly once for each call
   // to SetScreenResolution to simplify the implementation of unit-tests.
   base::TimeTicks now = clock_->NowTicks();
@@ -302,7 +302,7 @@
   // If there was a pending resolution request for an unspecifed monitor, apply
   // it now.
   if (!pending_resolution_request_.IsEmpty()) {
-    SetScreenResolution(pending_resolution_request_, absl::nullopt);
+    SetScreenResolution(pending_resolution_request_, std::nullopt);
     pending_resolution_request_ = {};
   }
 }
diff --git a/remoting/host/resizing_host_observer.h b/remoting/host/resizing_host_observer.h
index 33066bc..db02bbb 100644
--- a/remoting/host/resizing_host_observer.h
+++ b/remoting/host/resizing_host_observer.h
@@ -48,7 +48,7 @@
 
   // ScreenControls interface.
   void SetScreenResolution(const ScreenResolution& resolution,
-                           absl::optional<webrtc::ScreenId> screen_id) override;
+                           std::optional<webrtc::ScreenId> screen_id) override;
   void SetVideoLayout(const protocol::VideoLayout& video_layout) override;
 
   // Allows tests to provide display-info updates.
diff --git a/remoting/host/resizing_host_observer_unittest.cc b/remoting/host/resizing_host_observer_unittest.cc
index 922cd506..159a062 100644
--- a/remoting/host/resizing_host_observer_unittest.cc
+++ b/remoting/host/resizing_host_observer_unittest.cc
@@ -157,7 +157,7 @@
   }
 
   void SetScreenResolution(const ScreenResolution& client_size) {
-    resizing_host_observer_->SetScreenResolution(client_size, absl::nullopt);
+    resizing_host_observer_->SetScreenResolution(client_size, std::nullopt);
     if (auto_advance_clock_) {
       clock_.Advance(base::Seconds(1));
     }
diff --git a/remoting/host/security_key/security_key_extension_session.cc b/remoting/host/security_key/security_key_extension_session.cc
index 24bba7c..6fd2c30 100644
--- a/remoting/host/security_key/security_key_extension_session.cc
+++ b/remoting/host/security_key/security_key_extension_session.cc
@@ -95,7 +95,7 @@
     return false;
   }
 
-  absl::optional<base::Value> value = base::JSONReader::Read(message.data());
+  std::optional<base::Value> value = base::JSONReader::Read(message.data());
   if (!value || !value->is_dict()) {
     LOG(WARNING) << "Failed to retrieve data from gnubby-auth message.";
     return true;
@@ -145,7 +145,7 @@
 
 void SecurityKeyExtensionSession::ProcessDataMessage(
     const base::Value::Dict& message_data) const {
-  absl::optional<int> connection_id_opt = message_data.FindInt(kConnectionId);
+  std::optional<int> connection_id_opt = message_data.FindInt(kConnectionId);
   if (!connection_id_opt.has_value()) {
     LOG(WARNING) << "Could not extract connection id from message.";
     return;
@@ -173,7 +173,7 @@
 
 void SecurityKeyExtensionSession::ProcessErrorMessage(
     const base::Value::Dict& message_data) const {
-  absl::optional<int> connection_id_opt = message_data.FindInt(kConnectionId);
+  std::optional<int> connection_id_opt = message_data.FindInt(kConnectionId);
   if (!connection_id_opt.has_value()) {
     LOG(WARNING) << "Could not extract connection id from message.";
     return;
diff --git a/remoting/host/setup/corp_host_starter.cc b/remoting/host/setup/corp_host_starter.cc
index f70b3ed..1adea603 100644
--- a/remoting/host/setup/corp_host_starter.cc
+++ b/remoting/host/setup/corp_host_starter.cc
@@ -73,7 +73,7 @@
  private:
   void StartHostProcess();
 
-  void OnExistingConfigLoaded(absl::optional<base::Value::Dict> config);
+  void OnExistingConfigLoaded(std::optional<base::Value::Dict> config);
 
   void OnProvisionCorpMachineResponse(
       const ProtobufHttpStatus& status,
@@ -136,8 +136,8 @@
 }
 
 void CorpHostStarter::OnExistingConfigLoaded(
-    absl::optional<base::Value::Dict> config) {
-  absl::optional<std::string> existing_host_id;
+    std::optional<base::Value::Dict> config) {
+  std::optional<std::string> existing_host_id;
   if (config.has_value()) {
     std::string* host_id = config->FindString("host_id");
     if (host_id) {
diff --git a/remoting/host/setup/daemon_controller.cc b/remoting/host/setup/daemon_controller.cc
index 69c69cb5..898395c2 100644
--- a/remoting/host/setup/daemon_controller.cc
+++ b/remoting/host/setup/daemon_controller.cc
@@ -118,7 +118,7 @@
 void DaemonController::DoGetConfig(GetConfigCallback done) {
   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
 
-  absl::optional<base::Value::Dict> config = delegate_->GetConfig();
+  std::optional<base::Value::Dict> config = delegate_->GetConfig();
   caller_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(std::move(done), std::move(config)));
 }
@@ -171,7 +171,7 @@
 
 void DaemonController::InvokeConfigCallbackAndScheduleNext(
     GetConfigCallback done,
-    absl::optional<base::Value::Dict> config) {
+    std::optional<base::Value::Dict> config) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
   std::move(done).Run(std::move(config));
diff --git a/remoting/host/setup/daemon_controller.h b/remoting/host/setup/daemon_controller.h
index 086fb40..b3048b4 100644
--- a/remoting/host/setup/daemon_controller.h
+++ b/remoting/host/setup/daemon_controller.h
@@ -8,11 +8,11 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/containers/queue.h"
 #include "base/functional/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class SingleThreadTaskRunner;
@@ -66,7 +66,7 @@
   // is returned containing host_id and service_account, with security-sensitive
   // fields filtered out. An empty dictionary is returned if the host is not
   // configured, and nullptr if the configuration is corrupt or cannot be read.
-  typedef base::OnceCallback<void(absl::optional<base::Value::Dict> config)>
+  typedef base::OnceCallback<void(std::optional<base::Value::Dict> config)>
       GetConfigCallback;
 
   // Callback used for asynchronous operations, e.g. when
@@ -110,7 +110,7 @@
 
     // Queries current host configuration. Any values that might be security
     // sensitive have been filtered out.
-    virtual absl::optional<base::Value::Dict> GetConfig() = 0;
+    virtual std::optional<base::Value::Dict> GetConfig() = 0;
 
     // Checks to verify that the required OS permissions have been granted to
     // the host process, querying the user if necessary. Notifies the callback
@@ -218,7 +218,7 @@
                                                AsyncResult result);
   void InvokeConfigCallbackAndScheduleNext(
       GetConfigCallback done,
-      absl::optional<base::Value::Dict> config);
+      std::optional<base::Value::Dict> config);
   void InvokeConsentCallbackAndScheduleNext(GetUsageStatsConsentCallback done,
                                             const UsageStatsConsent& consent);
 
diff --git a/remoting/host/setup/daemon_controller_delegate_linux.cc b/remoting/host/setup/daemon_controller_delegate_linux.cc
index 5ff1dc19..28fae20 100644
--- a/remoting/host/setup/daemon_controller_delegate_linux.cc
+++ b/remoting/host/setup/daemon_controller_delegate_linux.cc
@@ -7,6 +7,7 @@
 #include <unistd.h>
 #include <utility>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/environment.h"
@@ -27,7 +28,6 @@
 #include "remoting/base/file_path_util_linux.h"
 #include "remoting/host/host_config.h"
 #include "remoting/host/usage_stats_consent.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -144,11 +144,11 @@
   }
 }
 
-absl::optional<base::Value::Dict> DaemonControllerDelegateLinux::GetConfig() {
-  absl::optional<base::Value::Dict> host_config(
+std::optional<base::Value::Dict> DaemonControllerDelegateLinux::GetConfig() {
+  std::optional<base::Value::Dict> host_config(
       HostConfigFromJsonFile(GetConfigPath()));
   if (!host_config.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   base::Value::Dict result;
@@ -218,7 +218,7 @@
 void DaemonControllerDelegateLinux::UpdateConfig(
     base::Value::Dict config,
     DaemonController::CompletionCallback done) {
-  absl::optional<base::Value::Dict> new_config(
+  std::optional<base::Value::Dict> new_config(
       HostConfigFromJsonFile(GetConfigPath()));
   if (!new_config.has_value()) {
     LOG(ERROR) << "Failed to read existing config file.";
diff --git a/remoting/host/setup/daemon_controller_delegate_linux.h b/remoting/host/setup/daemon_controller_delegate_linux.h
index c099505..3e472e3 100644
--- a/remoting/host/setup/daemon_controller_delegate_linux.h
+++ b/remoting/host/setup/daemon_controller_delegate_linux.h
@@ -23,7 +23,7 @@
 
   // DaemonController::Delegate interface.
   DaemonController::State GetState() override;
-  absl::optional<base::Value::Dict> GetConfig() override;
+  std::optional<base::Value::Dict> GetConfig() override;
   void CheckPermission(bool it2me, DaemonController::BoolCallback) override;
   void SetConfigAndStart(base::Value::Dict config,
                          bool consent,
diff --git a/remoting/host/setup/daemon_controller_delegate_mac.h b/remoting/host/setup/daemon_controller_delegate_mac.h
index bcfde6f..c2b1480 100644
--- a/remoting/host/setup/daemon_controller_delegate_mac.h
+++ b/remoting/host/setup/daemon_controller_delegate_mac.h
@@ -30,7 +30,7 @@
 
   // DaemonController::Delegate interface.
   DaemonController::State GetState() override;
-  absl::optional<base::Value::Dict> GetConfig() override;
+  std::optional<base::Value::Dict> GetConfig() override;
   void CheckPermission(bool it2me, DaemonController::BoolCallback) override;
   void SetConfigAndStart(base::Value::Dict config,
                          bool consent,
diff --git a/remoting/host/setup/daemon_controller_delegate_mac.mm b/remoting/host/setup/daemon_controller_delegate_mac.mm
index 0b8e02a6..3fdc9d90 100644
--- a/remoting/host/setup/daemon_controller_delegate_mac.mm
+++ b/remoting/host/setup/daemon_controller_delegate_mac.mm
@@ -8,6 +8,7 @@
 #include <sys/types.h>
 #include <utility>
 
+#include <optional>
 #include "base/apple/bridging.h"
 #include "base/apple/foundation_util.h"
 #include "base/apple/osstatus_logging.h"
@@ -32,7 +33,6 @@
 #include "remoting/host/mac/permission_checker.h"
 #include "remoting/host/mac/permission_wizard.h"
 #include "remoting/host/resources.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
@@ -236,11 +236,11 @@
   }
 }
 
-absl::optional<base::Value::Dict> DaemonControllerDelegateMac::GetConfig() {
+std::optional<base::Value::Dict> DaemonControllerDelegateMac::GetConfig() {
   base::FilePath config_path(kHostConfigFilePath);
   auto host_config = HostConfigFromJsonFile(config_path);
   if (!host_config.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   base::Value::Dict config;
@@ -282,7 +282,7 @@
     base::Value::Dict config,
     DaemonController::CompletionCallback done) {
   base::FilePath config_file_path(kHostConfigFilePath);
-  absl::optional<base::Value::Dict> host_config(
+  std::optional<base::Value::Dict> host_config(
       HostConfigFromJsonFile(config_file_path));
   if (!host_config.has_value()) {
     std::move(done).Run(DaemonController::RESULT_FAILED);
@@ -307,10 +307,10 @@
   consent.set_by_policy = false;
 
   base::FilePath config_file_path(kHostConfigFilePath);
-  absl::optional<base::Value::Dict> host_config(
+  std::optional<base::Value::Dict> host_config(
       HostConfigFromJsonFile(config_file_path));
   if (host_config.has_value()) {
-    absl::optional<bool> host_config_value =
+    std::optional<bool> host_config_value =
         host_config->FindBool(kUsageStatsConsentConfigPath);
     if (host_config_value.has_value()) {
       consent.allowed = host_config_value.value();
diff --git a/remoting/host/setup/daemon_controller_delegate_win.cc b/remoting/host/setup/daemon_controller_delegate_win.cc
index b7dcbfb..2dcc98f4 100644
--- a/remoting/host/setup/daemon_controller_delegate_win.cc
+++ b/remoting/host/setup/daemon_controller_delegate_win.cc
@@ -83,7 +83,7 @@
     return false;
   }
 
-  absl::optional<base::Value::Dict> config = HostConfigFromJson(file_content);
+  std::optional<base::Value::Dict> config = HostConfigFromJson(file_content);
   if (!config.has_value()) {
     LOG(ERROR) << "Config file: '" << filename.value() << "' is empty.";
     return false;
@@ -351,13 +351,13 @@
   return ConvertToDaemonState(status.dwCurrentState);
 }
 
-absl::optional<base::Value::Dict> DaemonControllerDelegateWin::GetConfig() {
+std::optional<base::Value::Dict> DaemonControllerDelegateWin::GetConfig() {
   base::FilePath config_dir = remoting::GetConfigDir();
 
   // Read the unprivileged part of host configuration.
   base::Value::Dict config;
   if (!ReadConfig(config_dir.Append(kUnprivilegedConfigFileName), config)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return config;
diff --git a/remoting/host/setup/daemon_controller_delegate_win.h b/remoting/host/setup/daemon_controller_delegate_win.h
index aef2291..825d958 100644
--- a/remoting/host/setup/daemon_controller_delegate_win.h
+++ b/remoting/host/setup/daemon_controller_delegate_win.h
@@ -21,7 +21,7 @@
 
   // DaemonController::Delegate interface.
   DaemonController::State GetState() override;
-  absl::optional<base::Value::Dict> GetConfig() override;
+  std::optional<base::Value::Dict> GetConfig() override;
   void CheckPermission(bool it2me, DaemonController::BoolCallback) override;
   void SetConfigAndStart(base::Value::Dict config,
                          bool consent,
diff --git a/remoting/host/setup/host_stopper.cc b/remoting/host/setup/host_stopper.cc
index e2d1b297..a233bff 100644
--- a/remoting/host/setup/host_stopper.cc
+++ b/remoting/host/setup/host_stopper.cc
@@ -27,7 +27,7 @@
       base::BindOnce(&HostStopper::OnConfigLoaded, weak_ptr_));
 }
 
-void HostStopper::OnConfigLoaded(absl::optional<base::Value::Dict> config) {
+void HostStopper::OnConfigLoaded(std::optional<base::Value::Dict> config) {
   const std::string* hostId = nullptr;
   if (!config || !(hostId = config->FindString("host_id"))) {
     std::move(on_done_).Run();
diff --git a/remoting/host/setup/host_stopper.h b/remoting/host/setup/host_stopper.h
index dc54107..4bae6bd 100644
--- a/remoting/host/setup/host_stopper.h
+++ b/remoting/host/setup/host_stopper.h
@@ -5,12 +5,12 @@
 #ifndef REMOTING_HOST_SETUP_HOST_STOPPER_H_
 #define REMOTING_HOST_SETUP_HOST_STOPPER_H_
 
+#include <optional>
 #include "base/functional/callback.h"
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "remoting/host/setup/daemon_controller.h"
 #include "remoting/host/setup/service_client.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -27,7 +27,7 @@
   void StopLocalHost(std::string access_token, base::OnceClosure on_done);
 
  private:
-  void OnConfigLoaded(absl::optional<base::Value::Dict> config);
+  void OnConfigLoaded(std::optional<base::Value::Dict> config);
   void StopHost();
   void OnStopped(DaemonController::AsyncResult);
 
diff --git a/remoting/host/setup/me2me_native_messaging_host.cc b/remoting/host/setup/me2me_native_messaging_host.cc
index 8f8013a..8b1a6e4 100644
--- a/remoting/host/setup/me2me_native_messaging_host.cc
+++ b/remoting/host/setup/me2me_native_messaging_host.cc
@@ -9,6 +9,7 @@
 #include <string>
 #include <utility>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
@@ -30,7 +31,6 @@
 #include "remoting/host/native_messaging/log_message_handler.h"
 #include "remoting/host/pin_hash.h"
 #include "remoting/protocol/pairing_registry.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(IS_WIN)
 #include "remoting/host/win/elevated_native_messaging_host.h"
@@ -54,12 +54,12 @@
 
 // Helper to extract the "config" part of a message as a base::Value::Dict.
 // Returns nullptr on failure, and logs an error message.
-absl::optional<base::Value::Dict> ConfigDictionaryFromMessage(
+std::optional<base::Value::Dict> ConfigDictionaryFromMessage(
     base::Value::Dict message) {
   if (base::Value::Dict* config_dict = message.FindDict("config")) {
     return std::move(*config_dict);
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 }  // namespace
@@ -92,7 +92,7 @@
   DCHECK(task_runner()->BelongsToCurrentThread());
 
   base::Value::Dict response;
-  absl::optional<base::Value> message_value = base::JSONReader::Read(message);
+  std::optional<base::Value> message_value = base::JSONReader::Read(message);
   if (!message_value || !message_value->is_dict()) {
     OnError("Received a message that's not a dictionary.");
     return;
@@ -293,7 +293,7 @@
     }
   }
 
-  absl::optional<base::Value::Dict> config_dict =
+  std::optional<base::Value::Dict> config_dict =
       ConfigDictionaryFromMessage(std::move(message));
   if (!config_dict) {
     OnError("'config' dictionary not found");
@@ -360,13 +360,13 @@
     }
   }
 
-  absl::optional<bool> consent = message.FindBool("consent");
+  std::optional<bool> consent = message.FindBool("consent");
   if (!consent) {
     OnError("'consent' not found.");
     return;
   }
 
-  absl::optional<base::Value::Dict> config_dict =
+  std::optional<base::Value::Dict> config_dict =
       ConfigDictionaryFromMessage(std::move(message));
   if (!config_dict) {
     OnError("'config' dictionary not found");
@@ -481,7 +481,7 @@
 
 void Me2MeNativeMessagingHost::SendConfigResponse(
     base::Value::Dict response,
-    absl::optional<base::Value::Dict> config) {
+    std::optional<base::Value::Dict> config) {
   DCHECK(task_runner()->BelongsToCurrentThread());
 
   if (config) {
diff --git a/remoting/host/setup/me2me_native_messaging_host.h b/remoting/host/setup/me2me_native_messaging_host.h
index 5f2d5d7..eb44d6df 100644
--- a/remoting/host/setup/me2me_native_messaging_host.h
+++ b/remoting/host/setup/me2me_native_messaging_host.h
@@ -100,7 +100,7 @@
   // These methods fill in the |response| dictionary from the other parameters,
   // and pass it to SendResponse().
   void SendConfigResponse(base::Value::Dict response,
-                          absl::optional<base::Value::Dict> config);
+                          std::optional<base::Value::Dict> config);
   void SendPairedClientsResponse(base::Value::Dict response,
                                  base::Value::List pairings);
   void SendUsageStatsConsentResponse(
diff --git a/remoting/host/setup/me2me_native_messaging_host_unittest.cc b/remoting/host/setup/me2me_native_messaging_host_unittest.cc
index 61d9fc1..417c3ef 100644
--- a/remoting/host/setup/me2me_native_messaging_host_unittest.cc
+++ b/remoting/host/setup/me2me_native_messaging_host_unittest.cc
@@ -11,6 +11,7 @@
 #include <string>
 #include <utility>
 
+#include <optional>
 #include "base/compiler_specific.h"
 #include "base/functional/bind.h"
 #include "base/json/json_reader.h"
@@ -36,7 +37,6 @@
 #include "remoting/protocol/protocol_mock_objects.h"
 #include "services/network/test/test_shared_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -171,7 +171,7 @@
 
   // DaemonController::Delegate interface.
   DaemonController::State GetState() override;
-  absl::optional<base::Value::Dict> GetConfig() override;
+  std::optional<base::Value::Dict> GetConfig() override;
   void CheckPermission(bool it2me,
                        DaemonController::BoolCallback callback) override;
   void SetConfigAndStart(base::Value::Dict config,
@@ -191,7 +191,7 @@
   return DaemonController::STATE_STARTED;
 }
 
-absl::optional<base::Value::Dict> MockDaemonControllerDelegate::GetConfig() {
+std::optional<base::Value::Dict> MockDaemonControllerDelegate::GetConfig() {
   return base::Value::Dict();
 }
 
@@ -250,7 +250,7 @@
   void SetUp() override;
   void TearDown() override;
 
-  absl::optional<base::Value::Dict> ReadMessageFromOutputPipe();
+  std::optional<base::Value::Dict> ReadMessageFromOutputPipe();
 
   void WriteMessageToInputPipe(const base::ValueView& message);
 
@@ -409,7 +409,7 @@
   test_run_loop_->Run();
 
   // Verify there are no more message in the output pipe.
-  absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
+  std::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
   EXPECT_FALSE(response);
 
   // The It2MeMe2MeNativeMessagingHost dtor closes the handles that are passed
@@ -417,26 +417,26 @@
   output_read_file_.Close();
 }
 
-absl::optional<base::Value::Dict>
+std::optional<base::Value::Dict>
 Me2MeNativeMessagingHostTest::ReadMessageFromOutputPipe() {
   while (true) {
     uint32_t length;
     int read_result = output_read_file_.ReadAtCurrentPos(
         reinterpret_cast<char*>(&length), sizeof(length));
     if (read_result != sizeof(length)) {
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     std::string message_json(length, '\0');
     read_result =
         output_read_file_.ReadAtCurrentPos(std::data(message_json), length);
     if (read_result != static_cast<int>(length)) {
-      return absl::nullopt;
+      return std::nullopt;
     }
 
-    absl::optional<base::Value> message = base::JSONReader::Read(message_json);
+    std::optional<base::Value> message = base::JSONReader::Read(message_json);
     if (!message || !message->is_dict()) {
-      return absl::nullopt;
+      return std::nullopt;
     }
 
     base::Value::Dict& result = message->GetDict();
@@ -470,7 +470,7 @@
   WriteMessageToInputPipe(good_message);
 
   // Read from output pipe, and verify responses.
-  absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
+  std::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
   ASSERT_TRUE(response);
   VerifyHelloResponse(std::move(*response));
 
@@ -556,11 +556,11 @@
 
   // Read all responses from output pipe, and verify them.
   for (int i = 0; i < next_id; ++i) {
-    absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
+    std::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
     ASSERT_TRUE(response);
 
     // Make sure that id is available and is in the range.
-    absl::optional<int> id = response->FindInt("id");
+    std::optional<int> id = response->FindInt("id");
     ASSERT_TRUE(id);
     ASSERT_TRUE(0 <= *id && *id < next_id);
 
@@ -581,7 +581,7 @@
   message.Set("id", "42");
   WriteMessageToInputPipe(message);
 
-  absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
+  std::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
   EXPECT_TRUE(response);
   std::string* value = response->FindString("id");
   EXPECT_FALSE(value);
diff --git a/remoting/host/token_validator_base.cc b/remoting/host/token_validator_base.cc
index a94aa507..eb70427 100644
--- a/remoting/host/token_validator_base.cc
+++ b/remoting/host/token_validator_base.cc
@@ -246,7 +246,7 @@
           ? data_.substr(sizeof(kJsonSafetyPrefix) - 1)
           : data_;
 
-  absl::optional<base::Value> value = base::JSONReader::Read(responseData);
+  std::optional<base::Value> value = base::JSONReader::Read(responseData);
   if (!value || !value->is_dict()) {
     LOG(ERROR) << "Invalid token validation response: '" << data_ << "'";
     return RejectionReason::INVALID_CREDENTIALS;
diff --git a/remoting/host/usage_stats_consent_linux.cc b/remoting/host/usage_stats_consent_linux.cc
index 7fe00c1c..1e9b9033 100644
--- a/remoting/host/usage_stats_consent_linux.cc
+++ b/remoting/host/usage_stats_consent_linux.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
@@ -16,7 +17,6 @@
 #include "remoting/base/is_google_email.h"
 #include "remoting/host/config_file_watcher.h"
 #include "remoting/host/host_config.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -26,7 +26,7 @@
 
   std::string filename = GetHostHash() + ".json";
   base::FilePath config_path = GetConfigDirectoryPath().Append(filename);
-  absl::optional<base::Value::Dict> config(HostConfigFromJsonFile(config_path));
+  std::optional<base::Value::Dict> config(HostConfigFromJsonFile(config_path));
   if (!config.has_value()) {
     LOG(ERROR) << "No host config file found.";
     return false;
diff --git a/remoting/host/usage_stats_consent_mac.cc b/remoting/host/usage_stats_consent_mac.cc
index ce08666..21aea57 100644
--- a/remoting/host/usage_stats_consent_mac.cc
+++ b/remoting/host/usage_stats_consent_mac.cc
@@ -7,13 +7,13 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/notreached.h"
 #include "base/values.h"
 #include "remoting/host/config_file_watcher.h"
 #include "remoting/host/host_config.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -28,10 +28,10 @@
   if (command_line->HasSwitch(kHostConfigSwitchName)) {
     base::FilePath config_file_path =
         command_line->GetSwitchValuePath(kHostConfigSwitchName);
-    absl::optional<base::Value::Dict> host_config(
+    std::optional<base::Value::Dict> host_config(
         HostConfigFromJsonFile(config_file_path));
     if (host_config.has_value()) {
-      absl::optional<bool> host_config_value =
+      std::optional<bool> host_config_value =
           host_config->FindBool(kUsageStatsConsentConfigPath);
       if (host_config_value.has_value()) {
         allowed = host_config_value.value();
diff --git a/remoting/host/webauthn/remote_webauthn_native_messaging_host.cc b/remoting/host/webauthn/remote_webauthn_native_messaging_host.cc
index 1c1e7e41..4f84a4d 100644
--- a/remoting/host/webauthn/remote_webauthn_native_messaging_host.cc
+++ b/remoting/host/webauthn/remote_webauthn_native_messaging_host.cc
@@ -83,7 +83,7 @@
     return;
   }
 
-  absl::optional<base::Value::Dict> response =
+  std::optional<base::Value::Dict> response =
       CreateNativeMessageResponse(request);
   if (!response.has_value()) {
     return;
diff --git a/remoting/host/win/simple_task_dialog.cc b/remoting/host/win/simple_task_dialog.cc
index f4bb0425..24262fa 100644
--- a/remoting/host/win/simple_task_dialog.cc
+++ b/remoting/host/win/simple_task_dialog.cc
@@ -70,7 +70,7 @@
   return true;
 }
 
-absl::optional<int> SimpleTaskDialog::Show() {
+std::optional<int> SimpleTaskDialog::Show() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   std::vector<TASKDIALOG_BUTTON> taskdialog_buttons;
@@ -104,7 +104,7 @@
       LOG(ERROR) << "TaskDialogIndirect() Failed: 0x" << std::hex << hr;
     }
 
-    return absl::nullopt;
+    return std::nullopt;
   }
   return button_result;
 }
diff --git a/remoting/host/win/simple_task_dialog.h b/remoting/host/win/simple_task_dialog.h
index 01387e8..32aedf3 100644
--- a/remoting/host/win/simple_task_dialog.h
+++ b/remoting/host/win/simple_task_dialog.h
@@ -13,10 +13,10 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/sequence_checker.h"
 #include "base/thread_annotations.h"
 #include "base/time/time.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -62,7 +62,7 @@
 
   // Shows the dialog and returns the ID of the button that the user clicked.
   // Returns nullopt if the dialog fails to show or times out.
-  absl::optional<int> Show();
+  std::optional<int> Show();
 
   SimpleTaskDialog(const SimpleTaskDialog&) = delete;
   SimpleTaskDialog& operator=(const SimpleTaskDialog&) = delete;
diff --git a/remoting/host/win/unprivileged_process_delegate.cc b/remoting/host/win/unprivileged_process_delegate.cc
index 7be275b..8db2d793 100644
--- a/remoting/host/win/unprivileged_process_delegate.cc
+++ b/remoting/host/win/unprivileged_process_delegate.cc
@@ -14,6 +14,7 @@
 #include <string>
 #include <utility>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/files/file.h"
 #include "base/logging.h"
@@ -36,7 +37,6 @@
 #include "remoting/host/win/launch_process_with_token.h"
 #include "remoting/host/win/security_descriptor.h"
 #include "remoting/host/win/window_station_and_desktop.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 using base::win::ScopedHandle;
 using base::win::Sid;
@@ -107,7 +107,7 @@
   }
 
   ScopedHandle restricted_token(temp_handle);
-  absl::optional<Sid> sid = Sid::FromIntegrityLevel(SECURITY_MANDATORY_LOW_RID);
+  std::optional<Sid> sid = Sid::FromIntegrityLevel(SECURITY_MANDATORY_LOW_RID);
   if (!sid) {
     LOG(ERROR) << "Failed to get integrity level SID";
     return false;
diff --git a/remoting/host/xmpp_register_support_host_request.cc b/remoting/host/xmpp_register_support_host_request.cc
index 9ca135f..76aff317 100644
--- a/remoting/host/xmpp_register_support_host_request.cc
+++ b/remoting/host/xmpp_register_support_host_request.cc
@@ -66,7 +66,7 @@
     SignalStrategy* signal_strategy,
     scoped_refptr<RsaKeyPair> key_pair,
     const std::string& authorized_helper,
-    absl::optional<ChromeOsEnterpriseParams> params,
+    std::optional<ChromeOsEnterpriseParams> params,
     RegisterCallback callback) {
   DCHECK(signal_strategy);
   DCHECK(key_pair.get());
diff --git a/remoting/host/xmpp_register_support_host_request.h b/remoting/host/xmpp_register_support_host_request.h
index cdc7b1b..f604098 100644
--- a/remoting/host/xmpp_register_support_host_request.h
+++ b/remoting/host/xmpp_register_support_host_request.h
@@ -53,7 +53,7 @@
   void StartRequest(SignalStrategy* signal_strategy,
                     scoped_refptr<RsaKeyPair> key_pair,
                     const std::string& authorized_helper,
-                    absl::optional<ChromeOsEnterpriseParams> params,
+                    std::optional<ChromeOsEnterpriseParams> params,
                     RegisterCallback callback) override;
 
   // HostStatusObserver implementation.
diff --git a/remoting/host/xmpp_register_support_host_request_unittest.cc b/remoting/host/xmpp_register_support_host_request_unittest.cc
index db82fc391..6c8e22a5c 100644
--- a/remoting/host/xmpp_register_support_host_request_unittest.cc
+++ b/remoting/host/xmpp_register_support_host_request_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <stdint.h>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
@@ -24,7 +25,6 @@
 #include "remoting/signaling/xmpp_constants.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 using jingle_xmpp::QName;
@@ -88,7 +88,7 @@
 TEST_F(XmppRegisterSupportHostRequestTest, Timeout) {
   auto request = std::make_unique<XmppRegisterSupportHostRequest>(kTestBotJid);
   request->StartRequest(&signal_strategy_, key_pair_, authorized_helper_,
-                        absl::nullopt, callback_.Get());
+                        std::nullopt, callback_.Get());
   EXPECT_CALL(signal_strategy_, GetNextId()).WillOnce(Return(kStanzaId));
   EXPECT_CALL(signal_strategy_, SendStanzaPtr(NotNull()))
       .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
@@ -109,7 +109,7 @@
 
   auto request = std::make_unique<XmppRegisterSupportHostRequest>(kTestBotJid);
   request->StartRequest(&signal_strategy_, key_pair_, authorized_helper_,
-                        absl::nullopt, callback_.Get());
+                        std::nullopt, callback_.Get());
 
   XmlElement* sent_iq = nullptr;
   EXPECT_CALL(signal_strategy_, GetNextId()).WillOnce(Return(kStanzaId));
@@ -205,7 +205,7 @@
 
   auto request = std::make_unique<XmppRegisterSupportHostRequest>(kTestBotJid);
   request->StartRequest(&signal_strategy_, key_pair_, authorized_helper_,
-                        absl::nullopt, callback_.Get());
+                        std::nullopt, callback_.Get());
 
   XmlElement* sent_iq = nullptr;
   EXPECT_CALL(signal_strategy_, GetNextId()).WillOnce(Return(kStanzaId));
diff --git a/remoting/host/xsession_chooser_linux.cc b/remoting/host/xsession_chooser_linux.cc
index 7a23bb7..a80302b0 100644
--- a/remoting/host/xsession_chooser_linux.cc
+++ b/remoting/host/xsession_chooser_linux.cc
@@ -20,6 +20,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/environment.h"
 #include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
@@ -36,7 +37,6 @@
 #include "base/task/single_thread_task_executor.h"
 #include "remoting/base/logging.h"
 #include "remoting/base/string_resources.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/icu/source/common/unicode/unistr.h"
 #include "third_party/icu/source/i18n/unicode/coll.h"
 #include "ui/base/glib/scoped_gobject.h"
@@ -170,7 +170,7 @@
   return true;
 }
 
-absl::optional<XSession> TryLoadSession(base::FilePath path) {
+std::optional<XSession> TryLoadSession(base::FilePath path) {
   std::unique_ptr<GKeyFile, void (*)(GKeyFile*)> key_file(g_key_file_new(),
                                                           &g_key_file_free);
   GError* error;
@@ -179,14 +179,14 @@
                                  G_KEY_FILE_NONE, &error)) {
     LOG(WARNING) << "Failed to load " << path << ": " << error->message;
     g_error_free(error);
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Files without a "Desktop Entry" group can be ignored. (An empty file can be
   // put in a higher-priority directory to hide entries from a lower-priority
   // directory.)
   if (!g_key_file_has_group(key_file.get(), G_KEY_FILE_DESKTOP_GROUP)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Files with "NoDisplay" or "Hidden" set should be ignored.
@@ -194,7 +194,7 @@
        {G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, G_KEY_FILE_DESKTOP_KEY_HIDDEN}) {
     if (g_key_file_get_boolean(key_file.get(), G_KEY_FILE_DESKTOP_GROUP, key,
                                nullptr)) {
-      return absl::nullopt;
+      return std::nullopt;
     }
   }
 
@@ -213,7 +213,7 @@
             : !base::ExecutableExistsInPath(base::Environment::Create().get(),
                                             try_exec_path.value())) {
       LOG(INFO) << "Rejecting " << path << " due to TryExec=" << try_exec_path;
-      return absl::nullopt;
+      return std::nullopt;
     }
   }
 
@@ -227,7 +227,7 @@
   } else {
     LOG(WARNING) << "Failed to load value of " << G_KEY_FILE_DESKTOP_KEY_NAME
                  << " from " << path;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (gchar* exec =
@@ -238,7 +238,7 @@
   } else {
     LOG(WARNING) << "Failed to load value of " << G_KEY_FILE_DESKTOP_KEY_EXEC
                  << " from " << path;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Optional fields.
@@ -300,7 +300,7 @@
        "default"});
 
   for (const auto& session : session_files) {
-    absl::optional<XSession> loaded_session = TryLoadSession(session.second);
+    std::optional<XSession> loaded_session = TryLoadSession(session.second);
     if (loaded_session) {
       sessions.push_back(std::move(*loaded_session));
     }
diff --git a/remoting/ios/app/notification_presenter.h b/remoting/ios/app/notification_presenter.h
index a7f4911..8928ba2 100644
--- a/remoting/ios/app/notification_presenter.h
+++ b/remoting/ios/app/notification_presenter.h
@@ -7,13 +7,13 @@
 
 #import <Foundation/Foundation.h>
 
+#include <optional>
 #include "base/no_destructor.h"
 #include "base/sequence_checker.h"
 #include "base/threading/sequence_bound.h"
 #include "base/timer/timer.h"
 #include "remoting/client/notification/notification_client.h"
 #include "remoting/client/notification/notification_message.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting {
 
@@ -42,7 +42,7 @@
   ~NotificationPresenter() = delete;
 
   void FetchNotification();
-  void OnNotificationFetched(absl::optional<NotificationMessage> notification);
+  void OnNotificationFetched(std::optional<NotificationMessage> notification);
 
   NotificationClient notification_client_;
 
diff --git a/remoting/ios/app/notification_presenter.mm b/remoting/ios/app/notification_presenter.mm
index ff7da35..0be8e67 100644
--- a/remoting/ios/app/notification_presenter.mm
+++ b/remoting/ios/app/notification_presenter.mm
@@ -105,7 +105,7 @@
 }
 
 void NotificationPresenter::OnNotificationFetched(
-    absl::optional<NotificationMessage> notification) {
+    std::optional<NotificationMessage> notification) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_EQ(State::FETCHING, state_);
 
diff --git a/remoting/proto/internal_stubs.cc b/remoting/proto/internal_stubs.cc
index 1b90a425..d12a9f6 100644
--- a/remoting/proto/internal_stubs.cc
+++ b/remoting/proto/internal_stubs.cc
@@ -37,7 +37,7 @@
     const std::string& owner_email,
     const std::string& fqdn,
     const std::string& public_key,
-    absl::optional<std::string> existing_host_id) {
+    std::optional<std::string> existing_host_id) {
   return std::make_unique<RemoteAccessHostV1Proto>();
 }
 
diff --git a/remoting/proto/internal_stubs.h b/remoting/proto/internal_stubs.h
index eaffd5e..36dba4af 100644
--- a/remoting/proto/internal_stubs.h
+++ b/remoting/proto/internal_stubs.h
@@ -8,7 +8,7 @@
 #include <memory>
 #include <string>
 
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include <optional>
 #include "third_party/protobuf/src/google/protobuf/message_lite.h"
 
 // This file defines proto and function stubs for internal-only implementations.
@@ -48,7 +48,7 @@
     const std::string& owner_email,
     const std::string& fqdn,
     const std::string& public_key,
-    absl::optional<std::string> existing_host_id);
+    std::optional<std::string> existing_host_id);
 
 extern std::string GetReportProvisioningErrorRequestPath();
 extern std::unique_ptr<ReportProvisioningErrorRequest>
diff --git a/remoting/protocol/clipboard_filter.h b/remoting/protocol/clipboard_filter.h
index a2ebe82..829a462 100644
--- a/remoting/protocol/clipboard_filter.h
+++ b/remoting/protocol/clipboard_filter.h
@@ -5,10 +5,10 @@
 #ifndef REMOTING_PROTOCOL_CLIPBOARD_FILTER_H_
 #define REMOTING_PROTOCOL_CLIPBOARD_FILTER_H_
 
+#include <optional>
 #include "base/compiler_specific.h"
 #include "base/memory/raw_ptr.h"
 #include "remoting/protocol/clipboard_stub.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting::protocol {
 
@@ -42,7 +42,7 @@
  private:
   raw_ptr<ClipboardStub, DanglingUntriaged> clipboard_stub_ = nullptr;
   bool enabled_ = true;
-  absl::optional<size_t> max_size_;
+  std::optional<size_t> max_size_;
 };
 
 }  // namespace remoting::protocol
diff --git a/remoting/protocol/fake_stream_socket.h b/remoting/protocol/fake_stream_socket.h
index 1e90660..b8004f06 100644
--- a/remoting/protocol/fake_stream_socket.h
+++ b/remoting/protocol/fake_stream_socket.h
@@ -9,11 +9,11 @@
 #include <memory>
 #include <string>
 
+#include <optional>
 #include "base/memory/weak_ptr.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "remoting/protocol/p2p_stream_socket.h"
 #include "remoting/protocol/stream_channel_factory.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class SingleThreadTaskRunner;
@@ -93,7 +93,7 @@
   int write_limit_ = 0;
   int next_write_error_ = 0;
 
-  absl::optional<int> next_read_error_;
+  std::optional<int> next_read_error_;
   scoped_refptr<net::IOBuffer> read_buffer_;
   int read_buffer_size_ = 0;
   net::CompletionOnceCallback read_callback_;
diff --git a/remoting/protocol/file_transfer_helpers.cc b/remoting/protocol/file_transfer_helpers.cc
index 026e058e..1d5cec7b 100644
--- a/remoting/protocol/file_transfer_helpers.cc
+++ b/remoting/protocol/file_transfer_helpers.cc
@@ -9,7 +9,7 @@
 FileTransfer_Error MakeFileTransferError(
     base::Location location,
     FileTransfer_Error_Type type,
-    absl::optional<int32_t> api_error_code) {
+    std::optional<int32_t> api_error_code) {
   FileTransfer_Error error;
   error.set_type(type);
   if (api_error_code) {
diff --git a/remoting/protocol/file_transfer_helpers.h b/remoting/protocol/file_transfer_helpers.h
index fb7c19e5..1063a2e 100644
--- a/remoting/protocol/file_transfer_helpers.h
+++ b/remoting/protocol/file_transfer_helpers.h
@@ -8,10 +8,10 @@
 #include <cstdint>
 #include <ostream>
 
+#include <optional>
 #include "base/location.h"
 #include "remoting/base/result.h"
 #include "remoting/proto/file_transfer.pb.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace remoting::protocol {
 
@@ -21,7 +21,7 @@
 FileTransfer_Error MakeFileTransferError(
     base::Location location,
     FileTransfer_Error_Type type,
-    absl::optional<std::int32_t> api_error_code = absl::nullopt);
+    std::optional<std::int32_t> api_error_code = std::nullopt);
 
 std::ostream& operator<<(std::ostream& stream, const FileTransfer_Error& error);
 
diff --git a/remoting/protocol/ice_config.cc b/remoting/protocol/ice_config.cc
index 766e5e7b..6c56405 100644
--- a/remoting/protocol/ice_config.cc
+++ b/remoting/protocol/ice_config.cc
@@ -212,7 +212,7 @@
 
 // static
 IceConfig IceConfig::Parse(const std::string& config_json) {
-  absl::optional<base::Value> json = base::JSONReader::Read(config_json);
+  std::optional<base::Value> json = base::JSONReader::Read(config_json);
   if (!json) {
     return IceConfig();
   }
diff --git a/remoting/protocol/pairing_registry.cc b/remoting/protocol/pairing_registry.cc
index caa9a7b..462fa70 100644
--- a/remoting/protocol/pairing_registry.cc
+++ b/remoting/protocol/pairing_registry.cc
@@ -58,7 +58,7 @@
 
 PairingRegistry::Pairing PairingRegistry::Pairing::CreateFromValue(
     const base::Value::Dict& pairing) {
-  absl::optional<double> created_time_value =
+  std::optional<double> created_time_value =
       pairing.FindDouble(kCreatedTimeKey);
   const std::string* client_name = pairing.FindString(kClientNameKey);
   const std::string* client_id = pairing.FindString(kClientIdKey);
diff --git a/remoting/protocol/peer_connection_controls.h b/remoting/protocol/peer_connection_controls.h
index 94e3590..ec6e109c 100644
--- a/remoting/protocol/peer_connection_controls.h
+++ b/remoting/protocol/peer_connection_controls.h
@@ -5,7 +5,7 @@
 #ifndef REMOTING_PROTOCOL_PEER_CONNECTION_CONTROLS_H_
 #define REMOTING_PROTOCOL_PEER_CONNECTION_CONTROLS_H_
 
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include <optional>
 
 namespace remoting::protocol {
 
@@ -17,8 +17,8 @@
 
   // Sets preferred min and max bitrates for the peer connection. nullopt means
   // no preference.
-  virtual void SetPreferredBitrates(absl::optional<int> min_bitrate_bps,
-                                    absl::optional<int> max_bitrate_bps) = 0;
+  virtual void SetPreferredBitrates(std::optional<int> min_bitrate_bps,
+                                    std::optional<int> max_bitrate_bps) = 0;
 
   // Performs an ICE restart. This causes the host to initiate a new SDP
   // offer/answer exchange, and restarts the ICE gathering/connection sequence.
diff --git a/remoting/protocol/webrtc_connection_to_client.cc b/remoting/protocol/webrtc_connection_to_client.cc
index 32cd84e8..3f633bd 100644
--- a/remoting/protocol/webrtc_connection_to_client.cc
+++ b/remoting/protocol/webrtc_connection_to_client.cc
@@ -208,7 +208,7 @@
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   auto sctp_transport = transport_->peer_connection()->GetSctpTransport();
   if (sctp_transport) {
-    absl::optional<double> max_message_size =
+    std::optional<double> max_message_size =
         sctp_transport->Information().MaxMessageSize();
     if (max_message_size && *max_message_size > 0) {
       control_dispatcher_->set_max_message_size(*max_message_size);
diff --git a/remoting/protocol/webrtc_transport.cc b/remoting/protocol/webrtc_transport.cc
index 16cee7e..2f27815 100644
--- a/remoting/protocol/webrtc_transport.cc
+++ b/remoting/protocol/webrtc_transport.cc
@@ -113,7 +113,7 @@
 }
 
 // Returns true if the selected candidate-pair indicates a relay connection.
-absl::optional<bool> IsConnectionRelayed(
+std::optional<bool> IsConnectionRelayed(
     const cricket::CandidatePair& selected_candidate_pair) {
   const cricket::Candidate& local_candidate =
       selected_candidate_pair.local_candidate();
@@ -620,9 +620,8 @@
   return session_options_;
 }
 
-void WebrtcTransport::SetPreferredBitrates(
-    absl::optional<int> min_bitrate_bps,
-    absl::optional<int> max_bitrate_bps) {
+void WebrtcTransport::SetPreferredBitrates(std::optional<int> min_bitrate_bps,
+                                           std::optional<int> max_bitrate_bps) {
   preferred_min_bitrate_bps_ = min_bitrate_bps;
   preferred_max_bitrate_bps_ = max_bitrate_bps;
   if (connected_) {
@@ -741,7 +740,7 @@
 void WebrtcTransport::ApplySessionOptions(const SessionOptions& options) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   session_options_ = options;
-  absl::optional<std::string> video_codec = options.Get("Video-Codec");
+  std::optional<std::string> video_codec = options.Get("Video-Codec");
   if (video_codec) {
     preferred_video_codec_ = *video_codec;
   }
@@ -983,7 +982,7 @@
 
   // Unknown -> direct/relayed is treated as a
   // change, so the correct initial bitrate caps are set.
-  absl::optional<bool> connection_relayed =
+  std::optional<bool> connection_relayed =
       IsConnectionRelayed(event.selected_candidate_pair);
   if (connection_relayed != connection_relayed_) {
     connection_relayed_ = connection_relayed;
diff --git a/remoting/protocol/webrtc_transport.h b/remoting/protocol/webrtc_transport.h
index 94ff50d..d0ad0f1 100644
--- a/remoting/protocol/webrtc_transport.h
+++ b/remoting/protocol/webrtc_transport.h
@@ -10,6 +10,7 @@
 #include <tuple>
 #include <vector>
 
+#include <optional>
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
@@ -25,7 +26,6 @@
 #include "remoting/protocol/webrtc_data_stream_adapter.h"
 #include "remoting/protocol/webrtc_event_log_data.h"
 #include "remoting/signaling/signal_strategy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/api/peer_connection_interface.h"
 #include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
 
@@ -113,8 +113,8 @@
   const SessionOptions& session_options() const override;
 
   // PeerConnectionControls implementations.
-  void SetPreferredBitrates(absl::optional<int> min_bitrate_bps,
-                            absl::optional<int> max_bitrate_bps) override;
+  void SetPreferredBitrates(std::optional<int> min_bitrate_bps,
+                            std::optional<int> max_bitrate_bps) override;
   void RequestIceRestart() override;
   void RequestSdpRestart() override;
 
@@ -238,7 +238,7 @@
 
   bool connected_ = false;
 
-  absl::optional<bool> connection_relayed_;
+  std::optional<bool> connection_relayed_;
 
   std::string transport_protocol_;
 
@@ -262,8 +262,8 @@
 
   // Preferred bitrates set by the client. nullopt if the client has not
   // provided any preferred bitrates.
-  absl::optional<int> preferred_min_bitrate_bps_;
-  absl::optional<int> preferred_max_bitrate_bps_;
+  std::optional<int> preferred_min_bitrate_bps_;
+  std::optional<int> preferred_max_bitrate_bps_;
 
   // Stores event log data generated by WebRTC for the PeerConnection.
   WebrtcEventLogData rtc_event_log_;
diff --git a/remoting/protocol/webrtc_video_encoder_wrapper.cc b/remoting/protocol/webrtc_video_encoder_wrapper.cc
index 9932c261..5a38cdc 100644
--- a/remoting/protocol/webrtc_video_encoder_wrapper.cc
+++ b/remoting/protocol/webrtc_video_encoder_wrapper.cc
@@ -111,7 +111,7 @@
       encoder_ = WebrtcVideoEncoderVpx::CreateForVP8();
       break;
     case webrtc::kVideoCodecVP9: {
-      absl::optional<webrtc::VP9Profile> profile =
+      std::optional<webrtc::VP9Profile> profile =
           webrtc::ParseSdpForVP9Profile(format.parameters);
       bool lossless_color = profile.has_value() &&
                             profile.value() == webrtc::VP9Profile::kProfile1;
@@ -119,7 +119,7 @@
               << (lossless_color ? "true" : "false");
       encoder_ = WebrtcVideoEncoderVpx::CreateForVP9();
       encoder_->SetLosslessColor(lossless_color);
-      absl::optional<int> encoder_speed =
+      std::optional<int> encoder_speed =
           session_options.GetInt("Vp9-Encoder-Speed");
       if (encoder_speed) {
         VLOG(0) << "Setting VP9 encoder speed to " << encoder_speed.value();
@@ -128,7 +128,7 @@
       break;
     }
     case webrtc::kVideoCodecAV1: {
-      absl::optional<webrtc::AV1Profile> profile =
+      std::optional<webrtc::AV1Profile> profile =
           webrtc::ParseSdpForAV1Profile(format.parameters);
       bool lossless_color = profile.has_value() &&
                             profile.value() == webrtc::AV1Profile::kProfile1;
@@ -136,7 +136,7 @@
               << (lossless_color ? "true" : "false");
       encoder_ = std::make_unique<WebrtcVideoEncoderAV1>();
       encoder_->SetLosslessColor(lossless_color);
-      absl::optional<int> encoder_speed =
+      std::optional<int> encoder_speed =
           session_options.GetInt("Av1-Encoder-Speed");
       if (encoder_speed) {
         VLOG(0) << "Setting AV1 encoder speed to " << encoder_speed.value();
diff --git a/remoting/protocol/webrtc_video_encoder_wrapper.h b/remoting/protocol/webrtc_video_encoder_wrapper.h
index 29198da9..d999af83 100644
--- a/remoting/protocol/webrtc_video_encoder_wrapper.h
+++ b/remoting/protocol/webrtc_video_encoder_wrapper.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
@@ -16,7 +17,6 @@
 #include "remoting/base/running_samples.h"
 #include "remoting/base/session_options.h"
 #include "remoting/codec/webrtc_video_encoder.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/webrtc/api/video/video_codec_type.h"
 #include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
 #include "third_party/webrtc/api/video_codecs/video_encoder.h"
@@ -172,7 +172,7 @@
 
   // Represents the screen which is being encoded by this instance. Initialized
   // after the first captured frame has been received.
-  absl::optional<webrtc::ScreenId> screen_id_;
+  std::optional<webrtc::ScreenId> screen_id_;
 
   base::WeakPtr<VideoStreamEventRouter> video_stream_event_router_;
 
diff --git a/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc b/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc
index 7609e89e..980358a5 100644
--- a/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc
+++ b/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc
@@ -220,7 +220,7 @@
     expected_framerate_ = framerate;
   }
 
-  const absl::optional<int>& get_expected_framerate() const {
+  const std::optional<int>& get_expected_framerate() const {
     return expected_framerate_;
   }
 
@@ -229,7 +229,7 @@
 
   base::RunLoop run_loop_;
 
-  absl::optional<int> expected_framerate_;
+  std::optional<int> expected_framerate_;
 
   VideoStreamEventRouter video_stream_event_router_;
   NiceMock<MockVideoChannelStateObserver> observer_;
diff --git a/remoting/protocol/webrtc_video_track_source.cc b/remoting/protocol/webrtc_video_track_source.cc
index 16eceadc..bf12ed5 100644
--- a/remoting/protocol/webrtc_video_track_source.cc
+++ b/remoting/protocol/webrtc_video_track_source.cc
@@ -32,8 +32,8 @@
   return true;
 }
 
-absl::optional<bool> WebrtcVideoTrackSource::needs_denoising() const {
-  return absl::nullopt;
+std::optional<bool> WebrtcVideoTrackSource::needs_denoising() const {
+  return std::nullopt;
 }
 
 bool WebrtcVideoTrackSource::GetStats(
diff --git a/remoting/protocol/webrtc_video_track_source.h b/remoting/protocol/webrtc_video_track_source.h
index f71416e..53a6a764 100644
--- a/remoting/protocol/webrtc_video_track_source.h
+++ b/remoting/protocol/webrtc_video_track_source.h
@@ -36,7 +36,7 @@
   SourceState state() const override;
   bool remote() const override;
   bool is_screencast() const override;
-  absl::optional<bool> needs_denoising() const override;
+  std::optional<bool> needs_denoising() const override;
   bool GetStats(Stats* stats) override;
   void AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
                        const rtc::VideoSinkWants& wants) override;
diff --git a/remoting/test/it2me_cli_host.cc b/remoting/test/it2me_cli_host.cc
index fbfca23..b0e63b39 100644
--- a/remoting/test/it2me_cli_host.cc
+++ b/remoting/test/it2me_cli_host.cc
@@ -274,8 +274,7 @@
   }
 
   const std::string* code = message.FindString(kAccessCode);
-  const absl::optional<int> code_lifetime =
-      message.FindInt(kAccessCodeLifetime);
+  const std::optional<int> code_lifetime = message.FindInt(kAccessCodeLifetime);
   if (!code || !code_lifetime) {
     OnProtocolBroken("Can not obtain access code");
     return;
diff --git a/remoting/test/test_token_storage.cc b/remoting/test/test_token_storage.cc
index 690699b7..466d79e 100644
--- a/remoting/test/test_token_storage.cc
+++ b/remoting/test/test_token_storage.cc
@@ -4,6 +4,7 @@
 
 #include "remoting/test/test_token_storage.h"
 
+#include <optional>
 #include "base/files/file_util.h"
 #include "base/files/important_file_writer.h"
 #include "base/json/json_reader.h"
@@ -11,7 +12,6 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 const base::FilePath::CharType kTokenFileName[] =
@@ -123,7 +123,7 @@
     return std::string();
   }
 
-  absl::optional<base::Value> token_data(base::JSONReader::Read(file_contents));
+  std::optional<base::Value> token_data(base::JSONReader::Read(file_contents));
   if (!token_data.has_value() || !token_data->is_dict()) {
     LOG(ERROR) << "File contents were not valid JSON, "
                << "could not retrieve token.";
@@ -162,7 +162,7 @@
     }
   }
 
-  absl::optional<base::Value> token_data(base::JSONReader::Read(file_contents));
+  std::optional<base::Value> token_data(base::JSONReader::Read(file_contents));
   if (!token_data.has_value() || !token_data->is_dict()) {
     LOG(ERROR) << "Invalid token file format, could not store token.";
     return false;
diff --git a/rlz/chromeos/lib/rlz_value_store_chromeos.cc b/rlz/chromeos/lib/rlz_value_store_chromeos.cc
index 059ea75..d527ff1 100644
--- a/rlz/chromeos/lib/rlz_value_store_chromeos.cc
+++ b/rlz/chromeos/lib/rlz_value_store_chromeos.cc
@@ -158,21 +158,21 @@
 }
 
 // Copy |value| without empty children.
-absl::optional<base::Value> CopyWithoutEmptyChildren(const base::Value& value) {
+std::optional<base::Value> CopyWithoutEmptyChildren(const base::Value& value) {
   switch (value.type()) {
     case base::Value::Type::DICT: {
       base::Value::Dict dict;
       const base::Value::Dict& dict_in = value.GetDict();
 
       for (auto it = dict_in.begin(); it != dict_in.end(); ++it) {
-        absl::optional<base::Value> item_copy =
+        std::optional<base::Value> item_copy =
             CopyWithoutEmptyChildren(it->second);
         if (item_copy)
           dict.Set(it->first, std::move(*item_copy));
       }
 
       if (dict.empty())
-        return absl::nullopt;
+        return std::nullopt;
 
       return base::Value(std::move(dict));
     }
@@ -182,13 +182,13 @@
       list.reserve(value.GetList().size());
 
       for (const base::Value& item : value.GetList()) {
-        absl::optional<base::Value> item_copy = CopyWithoutEmptyChildren(item);
+        std::optional<base::Value> item_copy = CopyWithoutEmptyChildren(item);
         if (item_copy)
           list.Append(std::move(*item_copy));
       }
 
       if (list.empty())
-        return absl::nullopt;
+        return std::nullopt;
 
       return base::Value(std::move(list));
     }
@@ -379,7 +379,7 @@
   if (strcmp(event_rlz, "CAF") == 0) {
     ash::system::StatisticsProvider* stats =
         ash::system::StatisticsProvider::GetInstance();
-    if (const absl::optional<base::StringPiece> should_send_rlz_ping_value =
+    if (const std::optional<base::StringPiece> should_send_rlz_ping_value =
             stats->GetMachineStatistic(ash::system::kShouldSendRlzPingKey)) {
       if (should_send_rlz_ping_value ==
           ash::system::kShouldSendRlzPingValueFalse) {
diff --git a/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc b/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
index 967b507..d4838765 100644
--- a/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
+++ b/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
@@ -592,7 +592,7 @@
     BrokerTestDelegate::BrokerParams broker_params =
         broker_test_delegate_->ChildSetUpPreSandbox();
 
-    auto policy = absl::make_optional<syscall_broker::BrokerSandboxConfig>(
+    auto policy = std::make_optional<syscall_broker::BrokerSandboxConfig>(
         broker_params.allowed_command_set, broker_params.permissions,
         broker_params.denied_errno);
     broker_process_ = std::make_unique<BrokerProcess>(
diff --git a/sandbox/linux/syscall_broker/broker_host.cc b/sandbox/linux/syscall_broker/broker_host.cc
index 8447121..272dcbc 100644
--- a/sandbox/linux/syscall_broker/broker_host.cc
+++ b/sandbox/linux/syscall_broker/broker_host.cc
@@ -54,21 +54,21 @@
 
 // Applies a rewrite from /proc/self/ to /proc/[pid of sandboxed process]/.
 // Returns either a rewritten or the original pathname.
-absl::optional<std::string> BrokerHost::RewritePathname(const char* pathname) {
+std::optional<std::string> BrokerHost::RewritePathname(const char* pathname) {
   if (base::StartsWith(pathname, kProcSelf)) {
     return base::StringPrintf("/proc/%d/%s", sandboxed_process_pid_,
                               pathname + kProcSelfNumChars);
   }
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<std::pair<const char*, int>> BrokerHost::GetPathAndFlags(
+std::optional<std::pair<const char*, int>> BrokerHost::GetPathAndFlags(
     BrokerSimpleMessage* message) {
   const char* pathname;
   int flags;
   if (!message->ReadString(&pathname) || !message->ReadInt(&flags)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return {{pathname, flags}};
 }
@@ -87,7 +87,7 @@
     return;
   }
 
-  absl::optional<std::string> rewritten_filename =
+  std::optional<std::string> rewritten_filename =
       RewritePathname(file_to_access);
   if (rewritten_filename.has_value()) {
     file_to_access = rewritten_filename.value().c_str();
@@ -115,7 +115,7 @@
     return;
   }
 
-  absl::optional<std::string> rewritten_filename =
+  std::optional<std::string> rewritten_filename =
       RewritePathname(file_to_access);
   if (rewritten_filename.has_value()) {
     file_to_access = rewritten_filename.value().c_str();
@@ -146,8 +146,7 @@
     return;
   }
 
-  absl::optional<std::string> rewritten_filename =
-      RewritePathname(file_to_open);
+  std::optional<std::string> rewritten_filename = RewritePathname(file_to_open);
   if (rewritten_filename.has_value()) {
     file_to_open = rewritten_filename.value().c_str();
   }
@@ -180,13 +179,13 @@
     return;
   }
 
-  absl::optional<std::string> old_rewritten_filename =
+  std::optional<std::string> old_rewritten_filename =
       RewritePathname(old_file_to_access);
   if (old_rewritten_filename) {
     old_file_to_access = old_rewritten_filename.value().c_str();
   }
 
-  absl::optional<std::string> new_rewritten_filename =
+  std::optional<std::string> new_rewritten_filename =
       RewritePathname(new_file_to_access);
   if (new_rewritten_filename) {
     new_file_to_access = new_rewritten_filename.value().c_str();
@@ -211,7 +210,7 @@
     return;
   }
 
-  absl::optional<std::string> rewritten_filename =
+  std::optional<std::string> rewritten_filename =
       RewritePathname(file_to_access);
   if (rewritten_filename.has_value()) {
     file_to_access = rewritten_filename.value().c_str();
@@ -238,7 +237,7 @@
     return;
   }
 
-  absl::optional<std::string> rewritten_filename =
+  std::optional<std::string> rewritten_filename =
       RewritePathname(file_to_access);
   if (rewritten_filename.has_value()) {
     file_to_access = rewritten_filename.value().c_str();
@@ -267,7 +266,7 @@
     return;
   }
 
-  absl::optional<std::string> rewritten_filename =
+  std::optional<std::string> rewritten_filename =
       RewritePathname(file_to_access);
   if (rewritten_filename.has_value()) {
     file_to_access = rewritten_filename.value().c_str();
@@ -318,7 +317,7 @@
     return;
   }
 
-  absl::optional<std::string> rewritten_filename =
+  std::optional<std::string> rewritten_filename =
       RewritePathname(file_to_access);
   if (rewritten_filename.has_value()) {
     file_to_access = rewritten_filename.value().c_str();
@@ -344,7 +343,7 @@
     return;
   }
 
-  absl::optional<std::string> rewritten_filename =
+  std::optional<std::string> rewritten_filename =
       RewritePathname(file_to_access);
   if (rewritten_filename.has_value()) {
     file_to_access = rewritten_filename.value().c_str();
diff --git a/sandbox/linux/syscall_broker/broker_host.h b/sandbox/linux/syscall_broker/broker_host.h
index ca49cce..9a6131e 100644
--- a/sandbox/linux/syscall_broker/broker_host.h
+++ b/sandbox/linux/syscall_broker/broker_host.h
@@ -5,12 +5,12 @@
 #ifndef SANDBOX_LINUX_SYSCALL_BROKER_BROKER_HOST_H_
 #define SANDBOX_LINUX_SYSCALL_BROKER_BROKER_HOST_H_
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/memory/raw_ref.h"
 #include "sandbox/linux/syscall_broker/broker_channel.h"
 #include "sandbox/linux/syscall_broker/broker_command.h"
 #include "sandbox/linux/syscall_broker/broker_sandbox_config.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -36,9 +36,9 @@
   void LoopAndHandleRequests();
 
  private:
-  [[nodiscard]] absl::optional<std::string> RewritePathname(
+  [[nodiscard]] std::optional<std::string> RewritePathname(
       const char* pathname);
-  [[nodiscard]] absl::optional<std::pair<const char*, int>> GetPathAndFlags(
+  [[nodiscard]] std::optional<std::pair<const char*, int>> GetPathAndFlags(
       BrokerSimpleMessage* message);
 
   void AccessFileForIPC(const char* requested_filename,
diff --git a/sandbox/linux/syscall_broker/broker_process.cc b/sandbox/linux/syscall_broker/broker_process.cc
index a55b548..c6c1117 100644
--- a/sandbox/linux/syscall_broker/broker_process.cc
+++ b/sandbox/linux/syscall_broker/broker_process.cc
@@ -35,7 +35,7 @@
 
 namespace syscall_broker {
 
-BrokerProcess::BrokerProcess(absl::optional<BrokerSandboxConfig> policy,
+BrokerProcess::BrokerProcess(std::optional<BrokerSandboxConfig> policy,
                              BrokerType broker_type,
                              bool fast_check_in_client,
                              bool quiet_failures_for_tests)
diff --git a/sandbox/linux/syscall_broker/broker_process.h b/sandbox/linux/syscall_broker/broker_process.h
index 797ce6e5..4baaed1e 100644
--- a/sandbox/linux/syscall_broker/broker_process.h
+++ b/sandbox/linux/syscall_broker/broker_process.h
@@ -11,10 +11,10 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/functional/callback_forward.h"
 #include "sandbox/linux/syscall_broker/broker_sandbox_config.h"
 #include "sandbox/sandbox_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -54,7 +54,7 @@
   // pipeline to the broker process, and it is not multi-threaded.
   //
   // |quiet_failures_for_tests| is reserved for unit tests, don't use it.
-  BrokerProcess(absl::optional<BrokerSandboxConfig> policy,
+  BrokerProcess(std::optional<BrokerSandboxConfig> policy,
                 BrokerType broker_type,
                 bool fast_check_in_client = true,
                 bool quiet_failures_for_tests = false);
@@ -106,7 +106,7 @@
   bool ForkSignalBasedBroker(BrokerSideCallback broker_process_init_callback);
 
   // Variables initialized by the constructor.
-  absl::optional<BrokerSandboxConfig>
+  std::optional<BrokerSandboxConfig>
       policy_;  // Can also be created by SendPolicy().
   const BrokerType broker_type_;
   const bool fast_check_in_client_;
diff --git a/sandbox/linux/syscall_broker/broker_process_unittest.cc b/sandbox/linux/syscall_broker/broker_process_unittest.cc
index cb85c87..10e7621 100644
--- a/sandbox/linux/syscall_broker/broker_process_unittest.cc
+++ b/sandbox/linux/syscall_broker/broker_process_unittest.cc
@@ -67,7 +67,7 @@
   {
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadOnly("/proc/cpuinfo")};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         BrokerCommandSet(), permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED);
 
@@ -83,8 +83,8 @@
       MakeBrokerCommandSet({COMMAND_ACCESS, COMMAND_OPEN});
 
   std::vector<BrokerFilePermission> empty;
-  auto policy = absl::make_optional<BrokerSandboxConfig>(command_set, empty,
-                                                         kFakeErrnoSentinel);
+  auto policy = std::make_optional<BrokerSandboxConfig>(command_set, empty,
+                                                        kFakeErrnoSentinel);
   BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED);
 
   ASSERT_TRUE(open_broker.Fork(base::BindOnce(&NoOpCallback)));
@@ -113,7 +113,7 @@
       BrokerFilePermission::ReadOnly(kR_AllowListedButDenied),
       BrokerFilePermission::WriteOnly(kW_AllowListed),
       BrokerFilePermission::ReadWrite(kRW_AllowListed)};
-  auto policy = absl::make_optional<BrokerSandboxConfig>(
+  auto policy = std::make_optional<BrokerSandboxConfig>(
       command_set, permissions, denied_errno);
   BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                             fast_check_in_client);
@@ -302,7 +302,7 @@
 
   std::vector<BrokerFilePermission> permissions = {
       BrokerFilePermission::ReadOnlyRecursive("/proc/")};
-  auto policy = absl::make_optional<BrokerSandboxConfig>(
+  auto policy = std::make_optional<BrokerSandboxConfig>(
       command_set, permissions, kFakeErrnoSentinel);
   BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                             fast_check_in_client);
@@ -374,7 +374,7 @@
         recursive ? BrokerFilePermission::ReadOnlyRecursive(kDirProc)
                   : BrokerFilePermission::ReadOnly(kFileCpuInfo));
 
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -460,7 +460,7 @@
 
   std::vector<BrokerFilePermission> permissions = {
       BrokerFilePermission::ReadWrite(tempfile_name)};
-  auto policy = absl::make_optional<BrokerSandboxConfig>(
+  auto policy = std::make_optional<BrokerSandboxConfig>(
       command_set, permissions, kFakeErrnoSentinel);
   BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED);
 
@@ -502,7 +502,7 @@
 
   std::vector<BrokerFilePermission> permissions = {
       BrokerFilePermission::ReadOnly(kCpuInfo)};
-  auto policy = absl::make_optional<BrokerSandboxConfig>(
+  auto policy = std::make_optional<BrokerSandboxConfig>(
       command_set, permissions, kFakeErrnoSentinel);
   BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                             true /* fast_check_in_client */,
@@ -535,7 +535,7 @@
 
   std::vector<BrokerFilePermission> permissions = {
       BrokerFilePermission::ReadOnly(kCpuInfo)};
-  auto policy = absl::make_optional<BrokerSandboxConfig>(
+  auto policy = std::make_optional<BrokerSandboxConfig>(
       command_set, permissions, kFakeErrnoSentinel);
   BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                             fast_check_in_client);
@@ -635,7 +635,7 @@
 
   std::vector<BrokerFilePermission> permissions = {
       BrokerFilePermission::ReadOnly(kCpuInfo)};
-  auto policy = absl::make_optional<BrokerSandboxConfig>(
+  auto policy = std::make_optional<BrokerSandboxConfig>(
       command_set, permissions, kFakeErrnoSentinel);
   BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED);
 
@@ -691,7 +691,7 @@
 
   std::vector<BrokerFilePermission> permissions = {
       BrokerFilePermission::ReadOnly("/proc/cpuinfo")};
-  auto policy = absl::make_optional<BrokerSandboxConfig>(
+  auto policy = std::make_optional<BrokerSandboxConfig>(
       command_set, permissions, kFakeErrnoSentinel);
   BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                             true /* fast_check_in_client */,
@@ -730,7 +730,7 @@
 
   {
     // Nonexistent file with no permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, proc_status_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -800,7 +800,7 @@
       BrokerFilePermission::ReadWriteCreate(permfile_name),
   };
 
-  auto policy = absl::make_optional<BrokerSandboxConfig>(
+  auto policy = std::make_optional<BrokerSandboxConfig>(
       command_set, permissions, kFakeErrnoSentinel);
   BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED);
 
@@ -903,7 +903,7 @@
     // Actual file with permissions to see file but command not allowed.
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadOnly(tempfile_name)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         BrokerCommandSet(), permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -922,7 +922,7 @@
   {
     // Nonexistent file with no permissions to see file.
     std::vector<BrokerFilePermission> permissions;
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -937,7 +937,7 @@
   {
     // Actual file with no permission to see file.
     std::vector<BrokerFilePermission> permissions;
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -953,7 +953,7 @@
     // Nonexistent file with permissions to see file.
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadOnly(nonesuch_name)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1000,7 +1000,7 @@
     // Nonexistent file with permissions to create file.
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadWriteCreate(nonesuch_name)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1049,7 +1049,7 @@
     // Actual file with permissions to see file.
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadOnly(tempfile_name)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1119,7 +1119,7 @@
   {
     // Check rename fails with write permissions to both files but command
     // itself is not allowed.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         BrokerCommandSet(), rwc_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1140,7 +1140,7 @@
     // Check rename fails when no permission to new file.
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadWriteCreate(oldpath)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1158,7 +1158,7 @@
     // Check rename fails when no permission to old file.
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadWriteCreate(newpath)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1177,7 +1177,7 @@
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadOnly(oldpath),
         BrokerFilePermission::ReadWriteCreate(newpath)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1196,7 +1196,7 @@
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadWriteCreate(oldpath),
         BrokerFilePermission::ReadOnly(newpath)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1212,7 +1212,7 @@
   }
   {
     // Check rename passes with write permissions to both files.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rwc_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1260,7 +1260,7 @@
     // Actual file with permissions to see file but command itself not allowed.
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadOnly(newpath_name)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         BrokerCommandSet(), permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1277,7 +1277,7 @@
   {
     // Nonexistent file with no permissions to see file.
     std::vector<BrokerFilePermission> permissions;
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1290,7 +1290,7 @@
   {
     // Actual file with no permissions to see file.
     std::vector<BrokerFilePermission> permissions;
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1304,7 +1304,7 @@
     // Nonexistent file with permissions to see file.
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadOnly(nonesuch_name)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1317,7 +1317,7 @@
     // Actual file with permissions to see file.
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadOnly(newpath_name)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1332,7 +1332,7 @@
     // Actual file with permissions to see file, but too small a buffer.
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::ReadOnly(newpath_name)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1380,7 +1380,7 @@
 
   {
     // Actual file with permissions to use but command itself not allowed.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         BrokerCommandSet(), rw_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1394,7 +1394,7 @@
 
   {
     // Nonexistent file with no permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, no_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1406,7 +1406,7 @@
   }
   {
     // Actual file with no permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, no_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1417,7 +1417,7 @@
   }
   {
     // Nonexistent file with insufficient permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, ro_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1429,7 +1429,7 @@
   }
   {
     // Actual file with insufficient permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, ro_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1440,7 +1440,7 @@
   }
   {
     // Nonexistent file with insufficient permissions to see file, case 2.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rw_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1452,7 +1452,7 @@
   }
   {
     // Actual file with insufficient permissions to see file, case 2.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rw_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1463,7 +1463,7 @@
   }
   {
     // Nonexistent file with permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rwc_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1474,7 +1474,7 @@
   }
   {
     // Actual file with permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rwc_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1524,7 +1524,7 @@
 
   {
     // Actual dir with permissions to use but command itself not allowed.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         BrokerCommandSet(), rw_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1539,7 +1539,7 @@
 
   {
     // Nonexistent dir with no permissions to see dir.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, no_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1552,7 +1552,7 @@
 
   {
     // Actual dir with no permissions to see dir.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, no_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1565,7 +1565,7 @@
 
   {
     // Nonexistent dir with insufficient permissions to see dir.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, ro_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1578,7 +1578,7 @@
 
   {
     // Actual dir with insufficient permissions to see dir.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, ro_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1591,7 +1591,7 @@
 
   {
     // Nonexistent dir with insufficient permissions to see dir, case 2.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rw_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1604,7 +1604,7 @@
 
   {
     // Actual dir with insufficient permissions to see dir, case 2.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rw_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1617,7 +1617,7 @@
 
   {
     // Nonexistent dir with permissions to see dir.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rwc_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1630,7 +1630,7 @@
 
   {
     // Actual dir with permissions to see dir.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rwc_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1681,7 +1681,7 @@
 
   {
     // Actual file with permissions to use but command itself not allowed.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         BrokerCommandSet(), rwc_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1696,7 +1696,7 @@
 
   {
     // Nonexistent file with no permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, no_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1709,7 +1709,7 @@
 
   {
     // Actual file with no permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, no_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1722,7 +1722,7 @@
 
   {
     // Nonexistent file with insufficient permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, ro_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1735,7 +1735,7 @@
 
   {
     // Actual file with insufficient permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, ro_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1748,7 +1748,7 @@
 
   {
     // Nonexistent file with insufficient permissions to see file, case 2.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rw_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1761,7 +1761,7 @@
 
   {
     // Actual file with insufficient permissions to see file, case 2.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rw_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1774,7 +1774,7 @@
 
   {
     // Nonexistent file with permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rwc_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1787,7 +1787,7 @@
 
   {
     // Actual file with permissions to see file.
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, rwc_permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1834,7 +1834,7 @@
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::InotifyAddWatchWithIntermediateDirs(
             nested_temp_dir_str)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         BrokerCommandSet(), permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1855,7 +1855,7 @@
   {
     // Try to watch a directory with no permission.
     std::vector<BrokerFilePermission> permissions;
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1874,7 +1874,7 @@
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::InotifyAddWatchWithIntermediateDirs(
             nested_temp_dir_str)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1894,7 +1894,7 @@
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::InotifyAddWatchWithIntermediateDirs(
             nested_temp_dir_str)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -1926,7 +1926,7 @@
     std::vector<BrokerFilePermission> permissions = {
         BrokerFilePermission::InotifyAddWatchWithIntermediateDirs(
             nested_temp_dir_str)};
-    auto policy = absl::make_optional<BrokerSandboxConfig>(
+    auto policy = std::make_optional<BrokerSandboxConfig>(
         command_set, permissions, kFakeErrnoSentinel);
     BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED,
                               fast_check_in_client);
@@ -2058,7 +2058,7 @@
       BrokerCommand command = test.first;
       const base::flat_set<int>& sysnos = test.second;
       SCOPED_TRACE(base::StringPrintf("fast check, command=%d", command));
-      auto policy = absl::make_optional<BrokerSandboxConfig>(
+      auto policy = std::make_optional<BrokerSandboxConfig>(
           MakeBrokerCommandSet({command}), std::vector<BrokerFilePermission>(),
           ENOSYS);
       BrokerProcess process(std::move(policy), BrokerType::SIGNAL_BASED,
@@ -2075,7 +2075,7 @@
     {
       BrokerCommand command = test.first;
       SCOPED_TRACE(base::StringPrintf("no fast check, command=%d", command));
-      auto policy = absl::make_optional<BrokerSandboxConfig>(
+      auto policy = std::make_optional<BrokerSandboxConfig>(
           MakeBrokerCommandSet({command}), std::vector<BrokerFilePermission>(),
           ENOSYS);
       BrokerProcess process(std::move(policy), BrokerType::SIGNAL_BASED,
diff --git a/sandbox/mac/sandbox_test.h b/sandbox/mac/sandbox_test.h
index d74b68c2..fcac4be 100644
--- a/sandbox/mac/sandbox_test.h
+++ b/sandbox/mac/sandbox_test.h
@@ -7,11 +7,11 @@
 
 #include <string>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/functional/callback.h"
 #include "base/process/process.h"
 #include "base/test/multiprocess_test.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -20,7 +20,7 @@
 class SandboxTest : public base::MultiProcessTest {
  public:
   using CommandLineModifier =
-      absl::optional<base::RepeatingCallback<void(base::CommandLine&)>>;
+      std::optional<base::RepeatingCallback<void(base::CommandLine&)>>;
 
   SandboxTest();
   ~SandboxTest() override;
@@ -32,12 +32,12 @@
   base::Process SpawnChildWithOptions(
       const std::string& procname,
       const base::LaunchOptions& options,
-      CommandLineModifier command_line_modifier = absl::nullopt);
+      CommandLineModifier command_line_modifier = std::nullopt);
 
   // Same as SpawnChildWithOptions, but uses a default LaunchOptions value.
   base::Process SpawnChild(
       const std::string& procname,
-      CommandLineModifier command_line_modifier = absl::nullopt);
+      CommandLineModifier command_line_modifier = std::nullopt);
 };
 
 }  // namespace sandbox
diff --git a/sandbox/policy/linux/sandbox_linux.cc b/sandbox/policy/linux/sandbox_linux.cc
index e574b7b..0bb1294 100644
--- a/sandbox/policy/linux/sandbox_linux.cc
+++ b/sandbox/policy/linux/sandbox_linux.cc
@@ -536,7 +536,7 @@
   // other LSMs like AppArmor and Landlock. Some userspace code, such as
   // glibc's |dlopen|, expect to see EACCES rather than EPERM. See
   // crbug.com/1233028 for an example.
-  auto policy = absl::make_optional<syscall_broker::BrokerSandboxConfig>(
+  auto policy = std::make_optional<syscall_broker::BrokerSandboxConfig>(
       allowed_command_set, std::move(permissions), EACCES);
   // Leaked at shutdown, so use bare |new|.
   broker_process_ = new syscall_broker::BrokerProcess(
diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc
index 0aa0cdc4..5eb2c633 100644
--- a/sandbox/policy/win/sandbox_win.cc
+++ b/sandbox/policy/win/sandbox_win.cc
@@ -15,6 +15,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/command_line.h"
 #include "base/containers/contains.h"
 #include "base/feature_list.h"
@@ -62,7 +63,6 @@
 #include "sandbox/win/src/app_container.h"
 #include "sandbox/win/src/process_mitigations.h"
 #include "sandbox/win/src/sandbox.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 namespace policy {
@@ -369,7 +369,7 @@
   std::wstring_view type_name(type_info->TypeName.Buffer,
                               type_info->TypeName.Length / sizeof(wchar_t));
 
-  absl::optional<ACCESS_MASK> granted_access =
+  std::optional<ACCESS_MASK> granted_access =
       base::win::GetGrantedAccess(handle);
   CHECK(granted_access.has_value());
 
@@ -785,7 +785,7 @@
   if (ret != SBOX_ALL_OK)
     return ret;
 
-  absl::optional<size_t> memory_limit = GetJobMemoryLimit(sandbox_type);
+  std::optional<size_t> memory_limit = GetJobMemoryLimit(sandbox_type);
   if (memory_limit) {
     config->SetJobMemoryLimit(*memory_limit);
   }
@@ -1136,7 +1136,7 @@
 }
 
 // static
-absl::optional<size_t> SandboxWin::GetJobMemoryLimit(Sandbox sandbox_type) {
+std::optional<size_t> SandboxWin::GetJobMemoryLimit(Sandbox sandbox_type) {
   // Trigger feature list initialization here to ensure no population bias in
   // the experimental and control groups.
   [[maybe_unused]] const bool high_renderer_limits =
@@ -1171,7 +1171,7 @@
   }
   return memory_limit;
 #else
-  return absl::nullopt;
+  return std::nullopt;
 #endif
 }
 
diff --git a/sandbox/policy/win/sandbox_win.h b/sandbox/policy/win/sandbox_win.h
index f45b798..81698da 100644
--- a/sandbox/policy/win/sandbox_win.h
+++ b/sandbox/policy/win/sandbox_win.h
@@ -9,6 +9,7 @@
 
 #include <string>
 
+#include <optional>
 #include "base/functional/bind.h"
 #include "base/functional/callback_forward.h"
 #include "base/process/launch.h"
@@ -19,7 +20,6 @@
 #include "sandbox/policy/sandbox_type.h"
 #include "sandbox/win/src/sandbox_types.h"
 #include "sandbox/win/src/security_level.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class CommandLine;
@@ -125,7 +125,7 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(SandboxWinTest, GetJobMemoryLimit);
 
-  static absl::optional<size_t> GetJobMemoryLimit(
+  static std::optional<size_t> GetJobMemoryLimit(
       sandbox::mojom::Sandbox sandbox_type);
 };
 
diff --git a/sandbox/policy/win/sandbox_win_unittest.cc b/sandbox/policy/win/sandbox_win_unittest.cc
index 2c9cef97..cac37fd0 100644
--- a/sandbox/policy/win/sandbox_win_unittest.cc
+++ b/sandbox/policy/win/sandbox_win_unittest.cc
@@ -558,7 +558,7 @@
   // Test GPU with physical memory > 64GB.
   {
     base::test::ScopedAmountOfPhysicalMemoryOverride memory_override(k65GB);
-    absl::optional<size_t> memory_limit =
+    std::optional<size_t> memory_limit =
         SandboxWin::GetJobMemoryLimit(sandbox::mojom::Sandbox::kGpu);
     EXPECT_TRUE(memory_limit.has_value());
     EXPECT_EQ(memory_limit, 64 * kGB);
@@ -567,7 +567,7 @@
   // Test GPU with physical memory > 32GB
   {
     base::test::ScopedAmountOfPhysicalMemoryOverride memory_override(k33GB);
-    absl::optional<size_t> memory_limit =
+    std::optional<size_t> memory_limit =
         SandboxWin::GetJobMemoryLimit(sandbox::mojom::Sandbox::kGpu);
     EXPECT_TRUE(memory_limit.has_value());
     EXPECT_EQ(memory_limit, 32 * kGB);
@@ -576,7 +576,7 @@
   // Test GPU with physical memory > 16GB
   {
     base::test::ScopedAmountOfPhysicalMemoryOverride memory_override(k17GB);
-    absl::optional<size_t> memory_limit =
+    std::optional<size_t> memory_limit =
         SandboxWin::GetJobMemoryLimit(sandbox::mojom::Sandbox::kGpu);
     EXPECT_TRUE(memory_limit.has_value());
     EXPECT_EQ(memory_limit, 16 * kGB);
@@ -585,7 +585,7 @@
   // Test GPU with physical memory < 16GB
   {
     base::test::ScopedAmountOfPhysicalMemoryOverride memory_override(k8GB);
-    absl::optional<size_t> memory_limit =
+    std::optional<size_t> memory_limit =
         SandboxWin::GetJobMemoryLimit(sandbox::mojom::Sandbox::kGpu);
     EXPECT_TRUE(memory_limit.has_value());
     EXPECT_EQ(memory_limit, 8 * kGB);
@@ -597,7 +597,7 @@
     base::test::ScopedFeatureList scoped_feature_list;
     scoped_feature_list.InitAndDisableFeature(
         sandbox::policy::features::kWinSboxHighRendererJobMemoryLimits);
-    absl::optional<size_t> memory_limit =
+    std::optional<size_t> memory_limit =
         SandboxWin::GetJobMemoryLimit(sandbox::mojom::Sandbox::kRenderer);
     EXPECT_TRUE(memory_limit.has_value());
     EXPECT_EQ(memory_limit, 16 * kGB);
@@ -609,7 +609,7 @@
     base::test::ScopedFeatureList scoped_feature_list;
     scoped_feature_list.InitAndDisableFeature(
         sandbox::policy::features::kWinSboxHighRendererJobMemoryLimits);
-    absl::optional<size_t> memory_limit =
+    std::optional<size_t> memory_limit =
         SandboxWin::GetJobMemoryLimit(sandbox::mojom::Sandbox::kRenderer);
     EXPECT_TRUE(memory_limit.has_value());
     EXPECT_EQ(memory_limit, 8 * kGB);
@@ -621,7 +621,7 @@
     base::test::ScopedFeatureList scoped_feature_list;
     scoped_feature_list.InitAndEnableFeature(
         sandbox::policy::features::kWinSboxHighRendererJobMemoryLimits);
-    absl::optional<size_t> memory_limit =
+    std::optional<size_t> memory_limit =
         SandboxWin::GetJobMemoryLimit(sandbox::mojom::Sandbox::kRenderer);
     EXPECT_TRUE(memory_limit.has_value());
     EXPECT_EQ(memory_limit, 1024 * kGB);
@@ -630,7 +630,7 @@
   // Test 32-bit processes don't get a limit.
   {
     base::test::ScopedAmountOfPhysicalMemoryOverride memory_override(k8GB);
-    absl::optional<size_t> memory_limit =
+    std::optional<size_t> memory_limit =
         SandboxWin::GetJobMemoryLimit(sandbox::mojom::Sandbox::kRenderer);
     EXPECT_FALSE(memory_limit.has_value());
   }
diff --git a/sandbox/win/src/acl.cc b/sandbox/win/src/acl.cc
index a649d469..8c2c072 100644
--- a/sandbox/win/src/acl.cc
+++ b/sandbox/win/src/acl.cc
@@ -10,7 +10,7 @@
 
 namespace sandbox {
 
-absl::optional<DWORD> GetIntegrityLevelRid(IntegrityLevel integrity_level) {
+std::optional<DWORD> GetIntegrityLevelRid(IntegrityLevel integrity_level) {
   switch (integrity_level) {
     case INTEGRITY_LEVEL_SYSTEM:
       return DWORD{SECURITY_MANDATORY_SYSTEM_RID};
@@ -27,18 +27,18 @@
     case INTEGRITY_LEVEL_UNTRUSTED:
       return DWORD{SECURITY_MANDATORY_UNTRUSTED_RID};
     case INTEGRITY_LEVEL_LAST:
-      return absl::nullopt;
+      return std::nullopt;
   }
 
   NOTREACHED();
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 DWORD SetObjectIntegrityLabel(HANDLE handle,
                               base::win::SecurityObjectType object_type,
                               DWORD mandatory_policy,
                               IntegrityLevel integrity_level) {
-  absl::optional<DWORD> value = GetIntegrityLevelRid(integrity_level);
+  std::optional<DWORD> value = GetIntegrityLevelRid(integrity_level);
   if (!value) {
     return ERROR_INVALID_SID;
   }
diff --git a/sandbox/win/src/acl.h b/sandbox/win/src/acl.h
index 475e94428..59ce330 100644
--- a/sandbox/win/src/acl.h
+++ b/sandbox/win/src/acl.h
@@ -13,7 +13,7 @@
 
 // Returns the RID associated with a given IntegrityLevel value. This returns
 // an empty value if `integrity_level` is set to INTEGRITY_LEVEL_LAST.
-absl::optional<DWORD> GetIntegrityLevelRid(IntegrityLevel integrity_level);
+std::optional<DWORD> GetIntegrityLevelRid(IntegrityLevel integrity_level);
 
 // Sets the integrity label on a object.
 // `handle` should be an open handle with WRITE_OWNER access.
diff --git a/sandbox/win/src/acl_unittest.cc b/sandbox/win/src/acl_unittest.cc
index 7584624a..65042d6 100644
--- a/sandbox/win/src/acl_unittest.cc
+++ b/sandbox/win/src/acl_unittest.cc
@@ -16,10 +16,9 @@
 
 void CheckGetIntegrityLevelSid(IntegrityLevel integrity_level,
                                const wchar_t* sddl) {
-  absl::optional<base::win::Sid> sddl_sid =
-      base::win::Sid::FromSddlString(sddl);
+  std::optional<base::win::Sid> sddl_sid = base::win::Sid::FromSddlString(sddl);
   ASSERT_TRUE(sddl_sid);
-  absl::optional<DWORD> integrity_value = GetIntegrityLevelRid(integrity_level);
+  std::optional<DWORD> integrity_value = GetIntegrityLevelRid(integrity_level);
   ASSERT_TRUE(integrity_value);
   EXPECT_EQ(*sddl_sid, base::win::Sid::FromIntegrityLevel(*integrity_value));
 }
@@ -34,7 +33,7 @@
   EXPECT_EQ(result, expected_error);
   if (result != ERROR_SUCCESS)
     return;
-  absl::optional<base::win::SecurityDescriptor> sd =
+  std::optional<base::win::SecurityDescriptor> sd =
       base::win::SecurityDescriptor::FromHandle(
           job.get(), base::win::SecurityObjectType::kKernel,
           LABEL_SECURITY_INFORMATION);
@@ -48,7 +47,7 @@
   ASSERT_EQ(ace->Header.AceType, SYSTEM_MANDATORY_LABEL_ACE_TYPE);
   EXPECT_EQ(ace->Header.AceFlags, 0);
   EXPECT_EQ(ace->Mask, mandatory_policy);
-  absl::optional<DWORD> rid = GetIntegrityLevelRid(integrity_level);
+  std::optional<DWORD> rid = GetIntegrityLevelRid(integrity_level);
   base::win::Sid sid = base::win::Sid::FromIntegrityLevel(*rid);
   ASSERT_TRUE(::IsValidSid(&ace->SidStart));
   EXPECT_TRUE(sid.Equal(&ace->SidStart));
diff --git a/sandbox/win/src/app_container_base.cc b/sandbox/win/src/app_container_base.cc
index 37cc8fa8..8fd0b01 100644
--- a/sandbox/win/src/app_container_base.cc
+++ b/sandbox/win/src/app_container_base.cc
@@ -107,7 +107,7 @@
     return false;
   }
 
-  absl::optional<base::win::SecurityDescriptor> sd =
+  std::optional<base::win::SecurityDescriptor> sd =
       base::win::SecurityDescriptor::FromName(
           object_name, object_type,
           OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
@@ -125,24 +125,24 @@
     }
   }
 
-  absl::optional<base::win::AccessToken> primary =
+  std::optional<base::win::AccessToken> primary =
       base::win::AccessToken::FromCurrentProcess(
           /*impersonation=*/false, TOKEN_DUPLICATE);
   if (!primary.has_value()) {
     return false;
   }
-  absl::optional<base::win::AccessToken> lowbox = BuildPrimaryToken(*primary);
+  std::optional<base::win::AccessToken> lowbox = BuildPrimaryToken(*primary);
   if (!lowbox) {
     return false;
   }
-  absl::optional<base::win::AccessToken> token_query =
+  std::optional<base::win::AccessToken> token_query =
       lowbox->DuplicateImpersonation(
           base::win::SecurityImpersonationLevel::kIdentification);
   if (!token_query) {
     return false;
   }
 
-  absl::optional<base::win::AccessCheckResult> result =
+  std::optional<base::win::AccessCheckResult> result =
       sd->AccessCheck(*token_query, desired_access, object_type);
   if (!result) {
     return false;
@@ -166,7 +166,7 @@
 }
 
 bool AppContainerBase::AddCapability(
-    const absl::optional<base::win::Sid>& capability_sid,
+    const std::optional<base::win::Sid>& capability_sid,
     bool impersonation_only) {
   if (!capability_sid)
     return false;
@@ -220,38 +220,38 @@
   return std::make_unique<SecurityCapabilities>(package_sid_, capabilities_);
 }
 
-absl::optional<base::win::AccessToken>
-AppContainerBase::BuildImpersonationToken(const base::win::AccessToken& token) {
-  absl::optional<base::win::AccessToken> lowbox = token.CreateAppContainer(
+std::optional<base::win::AccessToken> AppContainerBase::BuildImpersonationToken(
+    const base::win::AccessToken& token) {
+  std::optional<base::win::AccessToken> lowbox = token.CreateAppContainer(
       package_sid_, impersonation_capabilities_, TOKEN_ALL_ACCESS);
   ;
   if (!lowbox.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
-  absl::optional<base::win::SecurityDescriptor> sd =
+  std::optional<base::win::SecurityDescriptor> sd =
       base::win::SecurityDescriptor::FromHandle(
           lowbox->get(), base::win::SecurityObjectType::kKernel,
           DACL_SECURITY_INFORMATION);
   if (!sd) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   lowbox = lowbox->DuplicateImpersonation(
       base::win::SecurityImpersonationLevel::kImpersonation, TOKEN_ALL_ACCESS);
   if (!lowbox.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (!sd->WriteToHandle(lowbox->get(), base::win::SecurityObjectType::kKernel,
                          DACL_SECURITY_INFORMATION)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return lowbox;
 }
 
-absl::optional<base::win::AccessToken> AppContainerBase::BuildPrimaryToken(
+std::optional<base::win::AccessToken> AppContainerBase::BuildPrimaryToken(
     const base::win::AccessToken& token) {
   return token.CreateAppContainer(package_sid_, capabilities_,
                                   TOKEN_ALL_ACCESS);
diff --git a/sandbox/win/src/app_container_base.h b/sandbox/win/src/app_container_base.h
index 73998cf..174f247 100644
--- a/sandbox/win/src/app_container_base.h
+++ b/sandbox/win/src/app_container_base.h
@@ -8,13 +8,13 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/win/access_token.h"
 #include "base/win/security_descriptor.h"
 #include "base/win/sid.h"
 #include "base/win/windows_types.h"
 #include "sandbox/win/src/app_container.h"
 #include "sandbox/win/src/sandbox_types.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -70,21 +70,21 @@
   // `token` specify the base token to create the new token from. Must have
   // TOKEN_DUPLICATE access. The token is created with the impersonation
   // capabilities list.
-  absl::optional<base::win::AccessToken> BuildImpersonationToken(
+  std::optional<base::win::AccessToken> BuildImpersonationToken(
       const base::win::AccessToken& token);
 
   // Build a primary token from an existing token.
   // `token` specify the base token to create the new token from. Must have
   // TOKEN_DUPLICATE access. The token is created with the normal capabilities
   // list.
-  absl::optional<base::win::AccessToken> BuildPrimaryToken(
+  std::optional<base::win::AccessToken> BuildPrimaryToken(
       const base::win::AccessToken& token);
 
  private:
   AppContainerBase(base::win::Sid& package_sid, AppContainerType type);
   ~AppContainerBase();
 
-  bool AddCapability(const absl::optional<base::win::Sid>& capability_sid,
+  bool AddCapability(const std::optional<base::win::Sid>& capability_sid,
                      bool impersonation_only);
 
   // Standard object-lifetime reference counter.
diff --git a/sandbox/win/src/app_container_test.cc b/sandbox/win/src/app_container_test.cc
index ed78a6d1..c1ca465 100644
--- a/sandbox/win/src/app_container_test.cc
+++ b/sandbox/win/src/app_container_test.cc
@@ -51,7 +51,7 @@
   return impersonation ? "Impersonation Token" : "Primary Token";
 }
 
-void CheckToken(const absl::optional<base::win::AccessToken>& token,
+void CheckToken(const std::optional<base::win::AccessToken>& token,
                 bool impersonation,
                 PSECURITY_CAPABILITIES security_capabilities,
                 bool restricted) {
@@ -65,7 +65,7 @@
     EXPECT_FALSE(token->IsIdentification()) << TokenTypeToName(impersonation);
   }
 
-  absl::optional<base::win::Sid> package_sid = token->AppContainerSid();
+  std::optional<base::win::Sid> package_sid = token->AppContainerSid();
   ASSERT_TRUE(package_sid) << TokenTypeToName(impersonation);
   EXPECT_TRUE(package_sid->Equal(security_capabilities->AppContainerSid))
       << TokenTypeToName(impersonation);
diff --git a/sandbox/win/src/app_container_unittest.cc b/sandbox/win/src/app_container_unittest.cc
index 34803f9..6ca40e91 100644
--- a/sandbox/win/src/app_container_unittest.cc
+++ b/sandbox/win/src/app_container_unittest.cc
@@ -179,7 +179,7 @@
                       const base::win::AccessToken& base_token,
                       bool impersonation,
                       size_t expected_cap_count) {
-  absl::optional<base::win::AccessToken> token =
+  std::optional<base::win::AccessToken> token =
       impersonation ? container->BuildImpersonationToken(base_token)
                     : container->BuildPrimaryToken(base_token);
   ASSERT_TRUE(token);
@@ -418,7 +418,7 @@
   if (!features::IsAppContainerSandboxSupported()) {
     return;
   }
-  absl::optional<base::win::AccessToken> base_token =
+  std::optional<base::win::AccessToken> base_token =
       base::win::AccessToken::FromCurrentProcess(
           /*impersonation=*/false, TOKEN_DUPLICATE);
   ASSERT_TRUE(base_token);
@@ -438,7 +438,7 @@
   if (!features::IsAppContainerSandboxSupported()) {
     return;
   }
-  absl::optional<base::win::AccessToken> base_token =
+  std::optional<base::win::AccessToken> base_token =
       base::win::AccessToken::FromCurrentProcess(
           /*impersonation=*/false, TOKEN_DUPLICATE);
   ASSERT_TRUE(base_token);
diff --git a/sandbox/win/src/broker_services.cc b/sandbox/win/src/broker_services.cc
index 9dfe4b3..95a6e5d3 100644
--- a/sandbox/win/src/broker_services.cc
+++ b/sandbox/win/src/broker_services.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include <optional>
 #include <utility>
 #include "base/check_op.h"
 #include "base/containers/contains.h"
@@ -27,7 +28,6 @@
 #include "sandbox/win/src/target_process.h"
 #include "sandbox/win/src/threadpool.h"
 #include "sandbox/win/src/win_utils.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
@@ -408,8 +408,8 @@
 
   // Construct the tokens and the job object that we are going to associate
   // with the soon to be created target process.
-  absl::optional<base::win::AccessToken> initial_token;
-  absl::optional<base::win::AccessToken> lockdown_token;
+  std::optional<base::win::AccessToken> initial_token;
+  std::optional<base::win::AccessToken> lockdown_token;
   ResultCode result = SBOX_ALL_OK;
 
   result = policy_base->MakeTokens(initial_token, lockdown_token);
diff --git a/sandbox/win/src/handle_closer_agent.cc b/sandbox/win/src/handle_closer_agent.cc
index 11f1950..98529e3 100644
--- a/sandbox/win/src/handle_closer_agent.cc
+++ b/sandbox/win/src/handle_closer_agent.cc
@@ -6,12 +6,12 @@
 
 #include <stddef.h>
 
+#include <optional>
 #include "base/check.h"
 #include "base/logging.h"
 #include "base/win/static_constants.h"
 #include "base/win/win_util.h"
 #include "sandbox/win/src/win_utils.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -148,7 +148,7 @@
   if (base::win::IsAppVerifierLoaded())
     return true;
 
-  absl::optional<ProcessHandleMap> handle_map = GetCurrentProcessHandles();
+  std::optional<ProcessHandleMap> handle_map = GetCurrentProcessHandles();
   if (!handle_map)
     return false;
 
diff --git a/sandbox/win/src/integrity_level_test.cc b/sandbox/win/src/integrity_level_test.cc
index 5f79e53..42e9871 100644
--- a/sandbox/win/src/integrity_level_test.cc
+++ b/sandbox/win/src/integrity_level_test.cc
@@ -6,6 +6,7 @@
 
 #include <atlsecurity.h>
 
+#include <optional>
 #include "base/process/process_info.h"
 #include "base/win/access_token.h"
 #include "sandbox/win/src/sandbox.h"
@@ -13,7 +14,6 @@
 #include "sandbox/win/src/sandbox_policy.h"
 #include "sandbox/win/tests/common/controller.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -30,7 +30,7 @@
 }
 
 SBOX_TESTS_COMMAND int CheckIntegrityLevel(int argc, wchar_t** argv) {
-  absl::optional<base::win::AccessToken> token =
+  std::optional<base::win::AccessToken> token =
       base::win::AccessToken::FromEffective();
   if (!token)
     return SBOX_TEST_FAILED;
diff --git a/sandbox/win/src/process_mitigations.cc b/sandbox/win/src/process_mitigations.cc
index 79ca46ee..2b870c0 100644
--- a/sandbox/win/src/process_mitigations.cc
+++ b/sandbox/win/src/process_mitigations.cc
@@ -127,7 +127,7 @@
   }
 
   if (flags & MITIGATION_HARDEN_TOKEN_IL_POLICY) {
-    absl::optional<base::win::AccessToken> token =
+    std::optional<base::win::AccessToken> token =
         base::win::AccessToken::FromCurrentProcess(/*impersonation=*/false,
                                                    READ_CONTROL | WRITE_OWNER);
     if (!token) {
diff --git a/sandbox/win/src/process_thread_interception.cc b/sandbox/win/src/process_thread_interception.cc
index 7ab4d37f..308a519 100644
--- a/sandbox/win/src/process_thread_interception.cc
+++ b/sandbox/win/src/process_thread_interception.cc
@@ -6,6 +6,7 @@
 
 #include <stdint.h>
 
+#include <optional>
 #include "sandbox/win/src/crosscall_client.h"
 #include "sandbox/win/src/ipc_tags.h"
 #include "sandbox/win/src/policy_params.h"
@@ -14,7 +15,6 @@
 #include "sandbox/win/src/sandbox_nt_util.h"
 #include "sandbox/win/src/sharedmem_ipc_client.h"
 #include "sandbox/win/src/target_services.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -33,21 +33,21 @@
 }
 
 template <typename T>
-absl::optional<T> CaptureParameter(const T* parameter) {
+std::optional<T> CaptureParameter(const T* parameter) {
   if (parameter) {
     __try {
       return *parameter;
     } __except (EXCEPTION_EXECUTE_HANDLER) {
     }
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 bool ValidObjectAttributes(const OBJECT_ATTRIBUTES* object_attributes) {
   if (!object_attributes) {
     return true;
   }
-  absl::optional<OBJECT_ATTRIBUTES> valid_obj_attr =
+  std::optional<OBJECT_ATTRIBUTES> valid_obj_attr =
       CaptureParameter(object_attributes);
   return valid_obj_attr.has_value() && !valid_obj_attr->Attributes &&
          !valid_obj_attr->ObjectName && !valid_obj_attr->RootDirectory &&
@@ -124,7 +124,7 @@
     return status;
   }
 
-  absl::optional<CLIENT_ID> valid_client_id = CaptureParameter(client_id);
+  std::optional<CLIENT_ID> valid_client_id = CaptureParameter(client_id);
   if (!valid_client_id.has_value() || valid_client_id->UniqueProcess) {
     return status;
   }
@@ -187,7 +187,7 @@
     return status;
   }
 
-  absl::optional<CLIENT_ID> valid_client_id = CaptureParameter(client_id);
+  std::optional<CLIENT_ID> valid_client_id = CaptureParameter(client_id);
   if (!valid_client_id.has_value() ||
       valid_client_id->UniqueProcess != GetCurrentClientId().UniqueProcess) {
     return status;
diff --git a/sandbox/win/src/restricted_token.cc b/sandbox/win/src/restricted_token.cc
index ffaa725..07c84b5 100644
--- a/sandbox/win/src/restricted_token.cc
+++ b/sandbox/win/src/restricted_token.cc
@@ -23,13 +23,13 @@
 RestrictedToken::RestrictedToken() = default;
 RestrictedToken::~RestrictedToken() = default;
 
-absl::optional<base::win::AccessToken> RestrictedToken::GetRestrictedToken()
+std::optional<base::win::AccessToken> RestrictedToken::GetRestrictedToken()
     const {
-  absl::optional<base::win::AccessToken> token =
+  std::optional<base::win::AccessToken> token =
       base::win::AccessToken::FromCurrentProcess(/*impersonation=*/false,
                                                  TOKEN_ALL_ACCESS);
   if (!token) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return CreateRestricted(*token);
 }
@@ -100,7 +100,7 @@
   sids_for_default_dacl_.emplace_back(known_sid, access_mode, access, 0);
 }
 
-absl::optional<base::win::AccessToken>
+std::optional<base::win::AccessToken>
 RestrictedToken::GetRestrictedTokenForTesting(base::win::AccessToken& token) {
   return CreateRestricted(token);
 }
@@ -143,7 +143,7 @@
     }
   }
   if (add_restricting_sid_logon_session_) {
-    absl::optional<base::win::Sid> logon_sid = token.LogonId();
+    std::optional<base::win::Sid> logon_sid = token.LogonId();
     if (logon_sid.has_value()) {
       sids.push_back(std::move(*logon_sid));
     }
@@ -151,9 +151,9 @@
   return sids;
 }
 
-absl::optional<base::win::AccessToken> RestrictedToken::CreateRestricted(
+std::optional<base::win::AccessToken> RestrictedToken::CreateRestricted(
     const base::win::AccessToken& token) const {
-  absl::optional<base::win::AccessToken> new_token;
+  std::optional<base::win::AccessToken> new_token;
 
   std::vector<base::win::Sid> deny_sids = BuildDenyOnlySids(token);
   std::vector<base::win::Sid> restrict_sids = BuildRestrictedSids(token);
@@ -169,31 +169,31 @@
   }
 
   if (!new_token) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (delete_all_privileges_ && remove_traversal_privilege_ &&
       !new_token->RemovePrivilege(SE_CHANGE_NOTIFY_NAME)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   std::vector<base::win::ExplicitAccessEntry> dacl_entries;
 
-  absl::optional<base::win::AccessControlList> dacl = new_token->DefaultDacl();
+  std::optional<base::win::AccessControlList> dacl = new_token->DefaultDacl();
   if (!dacl) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (lockdown_default_dacl_) {
     // Don't add Restricted sid and also remove logon sid access.
-    absl::optional<base::win::Sid> logon_sid = new_token->LogonId();
+    std::optional<base::win::Sid> logon_sid = new_token->LogonId();
     if (logon_sid.has_value()) {
       dacl_entries.emplace_back(*logon_sid,
                                 base::win::SecurityAccessMode::kRevoke, 0, 0);
     } else {
       DWORD last_error = ::GetLastError();
       if (last_error != ERROR_NOT_FOUND) {
-        return absl::nullopt;
+        return std::nullopt;
       }
     }
   } else {
@@ -210,16 +210,16 @@
       new_token->User(), base::win::SecurityAccessMode::kGrant, GENERIC_ALL, 0);
 
   if (!dacl->SetEntries(dacl_entries)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (!new_token->SetDefaultDacl(*dacl)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (integrity_rid_.has_value()) {
     if (!new_token->SetIntegrityLevel(*integrity_rid_)) {
-      return absl::nullopt;
+      return std::nullopt;
     }
   }
 
diff --git a/sandbox/win/src/restricted_token.h b/sandbox/win/src/restricted_token.h
index 5e0c70bf..1d7925eb 100644
--- a/sandbox/win/src/restricted_token.h
+++ b/sandbox/win/src/restricted_token.h
@@ -7,12 +7,12 @@
 
 #include <vector>
 
+#include <optional>
 #include "base/win/access_control_list.h"
 #include "base/win/access_token.h"
 #include "base/win/sid.h"
 #include "base/win/windows_types.h"
 #include "sandbox/win/src/security_level.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -38,7 +38,7 @@
 
   // Creates a restricted token. This creates a primary token for process
   // creation. If the function fails an empty value is returned.
-  absl::optional<base::win::AccessToken> GetRestrictedToken() const;
+  std::optional<base::win::AccessToken> GetRestrictedToken() const;
 
   // Lists all sids in the token and mark them as Deny Only except for those
   // present in the exceptions parameter. If there is no exception needed,
@@ -129,7 +129,7 @@
 
   // Creates a restricted token. This is only used for testing to change the
   // token used to build the restricted token.
-  absl::optional<base::win::AccessToken> GetRestrictedTokenForTesting(
+  std::optional<base::win::AccessToken> GetRestrictedTokenForTesting(
       base::win::AccessToken& token);
 
  private:
@@ -137,7 +137,7 @@
       const base::win::AccessToken& token) const;
   std::vector<base::win::Sid> BuildRestrictedSids(
       const base::win::AccessToken& token) const;
-  absl::optional<base::win::AccessToken> CreateRestricted(
+  std::optional<base::win::AccessToken> CreateRestricted(
       const base::win::AccessToken& token) const;
 
   // The list of restricting sids in the restricted token.
@@ -147,9 +147,9 @@
   // The list of sids to add to the default DACL of the restricted token.
   std::vector<base::win::ExplicitAccessEntry> sids_for_default_dacl_;
   // The token to restrict, this is only used for testing.
-  absl::optional<base::win::AccessToken> effective_token_;
+  std::optional<base::win::AccessToken> effective_token_;
   // The token integrity level RID.
-  absl::optional<DWORD> integrity_rid_;
+  std::optional<DWORD> integrity_rid_;
   // Lockdown the default DACL when creating new tokens.
   bool lockdown_default_dacl_ = false;
   // Delete all privileges except for SeChangeNotifyPrivilege.
diff --git a/sandbox/win/src/restricted_token_test.cc b/sandbox/win/src/restricted_token_test.cc
index 639dca6..c13b477 100644
--- a/sandbox/win/src/restricted_token_test.cc
+++ b/sandbox/win/src/restricted_token_test.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 #include <string>
 
+#include <optional>
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/access_token.h"
@@ -16,7 +17,6 @@
 #include "sandbox/win/src/target_services.h"
 #include "sandbox/win/tests/common/controller.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -156,7 +156,7 @@
 // Opens a the process token and checks if it's restricted.
 SBOX_TESTS_COMMAND int RestrictedTokenTest_IsRestricted(int argc,
                                                         wchar_t** argv) {
-  absl::optional<base::win::AccessToken> token =
+  std::optional<base::win::AccessToken> token =
       base::win::AccessToken::FromCurrentProcess();
   if (!token)
     return SBOX_TEST_FIRST_ERROR;
diff --git a/sandbox/win/src/restricted_token_unittest.cc b/sandbox/win/src/restricted_token_unittest.cc
index 7475cf2..29e679835 100644
--- a/sandbox/win/src/restricted_token_unittest.cc
+++ b/sandbox/win/src/restricted_token_unittest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/ranges/algorithm.h"
 #include "base/win/access_control_list.h"
 #include "base/win/access_token.h"
@@ -22,7 +23,6 @@
 #include "sandbox/win/src/restricted_token_utils.h"
 #include "sandbox/win/tests/common/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -56,7 +56,7 @@
   auto logon_sid = restricted_token.LogonId();
   if (logon_sid) {
     EXPECT_EQ(restricted_required,
-              IsSidInDacl(dacl, true, absl::nullopt, *logon_sid));
+              IsSidInDacl(dacl, true, std::nullopt, *logon_sid));
   }
 }
 
@@ -89,7 +89,7 @@
 }
 
 DWORD GetMandatoryPolicy(const base::win::AccessToken& token) {
-  absl::optional<base::win::SecurityDescriptor> sd =
+  std::optional<base::win::SecurityDescriptor> sd =
       base::win::SecurityDescriptor::FromHandle(
           token.get(), base::win::SecurityObjectType::kKernel,
           LABEL_SECURITY_INFORMATION);
@@ -112,7 +112,7 @@
 }
 
 void CheckUniqueSid(TokenLevel level, bool check_present) {
-  absl::optional<base::win::Sid> random_sid =
+  std::optional<base::win::Sid> random_sid =
       base::win::Sid::GenerateRandomSid();
   auto token = *CreateRestrictedToken(level, INTEGRITY_LEVEL_LAST,
                                       TokenType::kPrimary, false, random_sid);
@@ -125,11 +125,10 @@
 }
 
 void CheckIntegrityLevel(IntegrityLevel integrity_level) {
-  absl::optional<base::win::AccessToken> token =
-      CreateRestrictedToken(USER_LOCKDOWN, integrity_level, TokenType::kPrimary,
-                            false, absl::nullopt);
+  std::optional<base::win::AccessToken> token = CreateRestrictedToken(
+      USER_LOCKDOWN, integrity_level, TokenType::kPrimary, false, std::nullopt);
   ASSERT_TRUE(token);
-  absl::optional<DWORD> rid = GetIntegrityLevelRid(integrity_level);
+  std::optional<DWORD> rid = GetIntegrityLevelRid(integrity_level);
   if (rid) {
     EXPECT_EQ(token->IntegrityLevel(), *rid);
   } else {
@@ -138,8 +137,8 @@
 }
 
 void CheckPrivileges(TokenLevel level, bool delete_all, bool remove_traversal) {
-  absl::optional<base::win::AccessToken> token = CreateRestrictedToken(
-      level, INTEGRITY_LEVEL_LAST, TokenType::kPrimary, false, absl::nullopt);
+  std::optional<base::win::AccessToken> token = CreateRestrictedToken(
+      level, INTEGRITY_LEVEL_LAST, TokenType::kPrimary, false, std::nullopt);
   ASSERT_TRUE(token);
   std::vector<base::win::AccessToken::Privilege> privs = token->Privileges();
   if (remove_traversal) {
@@ -173,15 +172,15 @@
                      const std::vector<base::win::WellKnownSid>& known_sids,
                      bool user,
                      bool logon) {
-  absl::optional<base::win::AccessToken> token = CreateRestrictedToken(
-      level, INTEGRITY_LEVEL_LAST, TokenType::kPrimary, false, absl::nullopt);
+  std::optional<base::win::AccessToken> token = CreateRestrictedToken(
+      level, INTEGRITY_LEVEL_LAST, TokenType::kPrimary, false, std::nullopt);
   std::vector<base::win::Sid> sids =
       base::win::Sid::FromKnownSidVector(known_sids);
   if (user) {
     sids.push_back(token->User());
   }
   if (logon) {
-    absl::optional<base::win::Sid> logon_sid = token->LogonId();
+    std::optional<base::win::Sid> logon_sid = token->LogonId();
     if (logon_sid) {
       sids.push_back(logon_sid->Clone());
     }
@@ -194,8 +193,8 @@
     const std::vector<base::win::WellKnownSid>& known_exceptions,
     bool allow_all,
     bool user) {
-  absl::optional<base::win::AccessToken> token = CreateRestrictedToken(
-      level, INTEGRITY_LEVEL_LAST, TokenType::kPrimary, false, absl::nullopt);
+  std::optional<base::win::AccessToken> token = CreateRestrictedToken(
+      level, INTEGRITY_LEVEL_LAST, TokenType::kPrimary, false, std::nullopt);
   ASSERT_TRUE(token);
   std::vector<base::win::Sid> exceptions =
       base::win::Sid::FromKnownSidVector(known_exceptions);
@@ -220,12 +219,12 @@
 // Tests default initialization of the class.
 TEST(RestrictedTokenTest, DefaultInit) {
   RestrictedToken token_default;
-  absl::optional<base::win::AccessToken> restricted_token =
+  std::optional<base::win::AccessToken> restricted_token =
       token_default.GetRestrictedToken();
   ASSERT_TRUE(restricted_token);
 
   // Get the current process token.
-  absl::optional<base::win::AccessToken> access_token =
+  std::optional<base::win::AccessToken> access_token =
       base::win::AccessToken::FromCurrentProcess();
   ASSERT_TRUE(access_token);
   // Check if both token have the same owner and user.
@@ -242,7 +241,7 @@
   RestrictedToken token;
   token.AddRestrictingSid(base::win::WellKnownSid::kWorld);
 
-  absl::optional<base::win::AccessToken> restricted_token =
+  std::optional<base::win::AccessToken> restricted_token =
       token.GetRestrictedToken();
   ASSERT_TRUE(restricted_token);
   EXPECT_TRUE(restricted_token->IsRestricted());
@@ -276,7 +275,7 @@
   RestrictedToken token;
 
   token.AddSidForDenyOnly(base::win::WellKnownSid::kWorld);
-  absl::optional<base::win::AccessToken> restricted_token =
+  std::optional<base::win::AccessToken> restricted_token =
       token.GetRestrictedToken();
   ASSERT_TRUE(restricted_token);
   base::win::Sid sid(base::win::WellKnownSid::kWorld);
@@ -435,7 +434,7 @@
 
 TEST(RestrictedTokenTest, LockdownDefaultDaclNoLogonSid) {
   ASSERT_TRUE(::ImpersonateAnonymousToken(::GetCurrentThread()));
-  absl::optional<base::win::AccessToken> anonymous_token =
+  std::optional<base::win::AccessToken> anonymous_token =
       base::win::AccessToken::FromCurrentThread(/*open_as_self=*/true,
                                                 TOKEN_ALL_ACCESS);
   ::RevertToSelf();
@@ -461,15 +460,14 @@
 }
 
 TEST(RestrictedTokenTest, TokenType) {
-  absl::optional<base::win::AccessToken> token =
+  std::optional<base::win::AccessToken> token =
       CreateRestrictedToken(USER_LOCKDOWN, INTEGRITY_LEVEL_LAST,
-                            TokenType::kPrimary, false, absl::nullopt);
+                            TokenType::kPrimary, false, std::nullopt);
   ASSERT_TRUE(token);
   EXPECT_FALSE(token->IsImpersonation());
   EXPECT_EQ(DWORD{TOKEN_ALL_ACCESS}, base::win::GetGrantedAccess(token->get()));
-  token =
-      CreateRestrictedToken(USER_LOCKDOWN, INTEGRITY_LEVEL_LAST,
-                            TokenType::kImpersonation, false, absl::nullopt);
+  token = CreateRestrictedToken(USER_LOCKDOWN, INTEGRITY_LEVEL_LAST,
+                                TokenType::kImpersonation, false, std::nullopt);
   ASSERT_TRUE(token);
   EXPECT_TRUE(token->IsImpersonation());
   EXPECT_EQ(token->ImpersonationLevel(),
@@ -526,9 +524,9 @@
   CheckRestricted(USER_LOCKDOWN, {base::win::WellKnownSid::kNull}, false,
                   false);
 
-  absl::optional<base::win::AccessToken> token =
+  std::optional<base::win::AccessToken> token =
       CreateRestrictedToken(USER_RESTRICTED_SAME_ACCESS, INTEGRITY_LEVEL_LAST,
-                            TokenType::kPrimary, false, absl::nullopt);
+                            TokenType::kPrimary, false, std::nullopt);
   ASSERT_TRUE(token);
   std::vector<base::win::Sid> sids;
   sids.push_back(token->User());
diff --git a/sandbox/win/src/restricted_token_utils.cc b/sandbox/win/src/restricted_token_utils.cc
index 050d9d5..9cefa097 100644
--- a/sandbox/win/src/restricted_token_utils.cc
+++ b/sandbox/win/src/restricted_token_utils.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/check.h"
 #include "base/notreached.h"
 #include "base/win/access_token.h"
@@ -16,7 +17,6 @@
 #include "sandbox/win/src/sandbox_nt_util.h"
 #include "sandbox/win/src/security_level.h"
 #include "sandbox/win/src/win_utils.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -29,12 +29,12 @@
 
 }  // namespace
 
-absl::optional<base::win::AccessToken> CreateRestrictedToken(
+std::optional<base::win::AccessToken> CreateRestrictedToken(
     TokenLevel security_level,
     IntegrityLevel integrity_level,
     TokenType token_type,
     bool lockdown_default_dacl,
-    const absl::optional<base::win::Sid>& unique_restricted_sid) {
+    const std::optional<base::win::Sid>& unique_restricted_sid) {
   RestrictedToken restricted_token;
   if (lockdown_default_dacl) {
     restricted_token.SetLockdownDefaultDacl();
@@ -126,7 +126,7 @@
       }
       break;
     case USER_LAST:
-      return absl::nullopt;
+      return std::nullopt;
   }
 
   if (deny_sids) {
@@ -138,10 +138,10 @@
   }
 
   restricted_token.SetIntegrityLevel(integrity_level);
-  absl::optional<base::win::AccessToken> result =
+  std::optional<base::win::AccessToken> result =
       restricted_token.GetRestrictedToken();
   if (!result) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (token_type == TokenType::kPrimary) {
@@ -151,14 +151,14 @@
   result = result->DuplicateImpersonation(
       base::win::SecurityImpersonationLevel::kImpersonation, TOKEN_ALL_ACCESS);
   if (!result) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return result;
 }
 
 DWORD HardenTokenIntegrityLevelPolicy(const base::win::AccessToken& token) {
-  absl::optional<base::win::SecurityDescriptor> sd =
+  std::optional<base::win::SecurityDescriptor> sd =
       base::win::SecurityDescriptor::FromHandle(
           token.get(), base::win::SecurityObjectType::kKernel,
           LABEL_SECURITY_INFORMATION);
diff --git a/sandbox/win/src/restricted_token_utils.h b/sandbox/win/src/restricted_token_utils.h
index a3eb4b4..a638f772 100644
--- a/sandbox/win/src/restricted_token_utils.h
+++ b/sandbox/win/src/restricted_token_utils.h
@@ -5,12 +5,12 @@
 #ifndef SANDBOX_WIN_SRC_RESTRICTED_TOKEN_UTILS_H_
 #define SANDBOX_WIN_SRC_RESTRICTED_TOKEN_UTILS_H_
 
+#include <optional>
 #include "base/win/access_token.h"
 #include "base/win/sid.h"
 #include "base/win/windows_types.h"
 #include "sandbox/win/src/restricted_token.h"
 #include "sandbox/win/src/security_level.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // Contains the utility functions to be able to create restricted tokens based
 // on a security profiles.
@@ -34,12 +34,12 @@
 // other sandboxed processes at the same security level.
 // If the function succeeds, the return value is the restricted token. If it
 // fails then the return value is empty.
-absl::optional<base::win::AccessToken> CreateRestrictedToken(
+std::optional<base::win::AccessToken> CreateRestrictedToken(
     TokenLevel security_level,
     IntegrityLevel integrity_level,
     TokenType token_type,
     bool lockdown_default_dacl,
-    const absl::optional<base::win::Sid>& unique_restricted_sid);
+    const std::optional<base::win::Sid>& unique_restricted_sid);
 
 // Hardens the integrity level policy on a token. Specifically it sets the
 // policy to block read and execute so that a lower privileged process cannot
diff --git a/sandbox/win/src/sandbox.h b/sandbox/win/src/sandbox.h
index b73b7f0..41b70a0 100644
--- a/sandbox/win/src/sandbox.h
+++ b/sandbox/win/src/sandbox.h
@@ -23,12 +23,12 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/strings/string_piece.h"
 #include "base/win/windows_types.h"
 #include "sandbox/win/src/sandbox_policy.h"
 #include "sandbox/win/src/sandbox_types.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // sandbox: Google User-Land Application Sandbox
 namespace sandbox {
@@ -194,7 +194,7 @@
   // If no data was provided the span will have a size of zero. This method can
   // be called at any time after Init(), but it is intended to be used sparingly
   // prior to calling LowerToken().
-  virtual absl::optional<base::span<const uint8_t>> GetDelegateData() = 0;
+  virtual std::optional<base::span<const uint8_t>> GetDelegateData() = 0;
 
   // Discards the impersonation token and uses the lower token, call before
   // processing any untrusted data or running third-party code. If this call
diff --git a/sandbox/win/src/sandbox_nt_util.cc b/sandbox/win/src/sandbox_nt_util.cc
index 82e911d..27942c9 100644
--- a/sandbox/win/src/sandbox_nt_util.cc
+++ b/sandbox/win/src/sandbox_nt_util.cc
@@ -10,6 +10,7 @@
 
 #include <string>
 
+#include <optional>
 #include "base/compiler_specific.h"
 #include "base/containers/span.h"
 #include "base/win/pe_image.h"
@@ -17,7 +18,6 @@
 #include "sandbox/win/src/nt_internals.h"
 #include "sandbox/win/src/sandbox_factory.h"
 #include "sandbox/win/src/target_services.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -245,12 +245,12 @@
   return g_shared_policy_memory;
 }
 
-absl::optional<base::span<const uint8_t>> GetGlobalDelegateData() {
+std::optional<base::span<const uint8_t>> GetGlobalDelegateData() {
   if (!g_delegate_data_size) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   if (!MapGlobalMemory()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return base::make_span(
       reinterpret_cast<const uint8_t*>(g_shared_delegate_data),
diff --git a/sandbox/win/src/sandbox_nt_util.h b/sandbox/win/src/sandbox_nt_util.h
index 9a42aa9..999c989 100644
--- a/sandbox/win/src/sandbox_nt_util.h
+++ b/sandbox/win/src/sandbox_nt_util.h
@@ -10,11 +10,11 @@
 #include <stdint.h>
 #include <memory>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/memory/raw_ptr_exclusion.h"
 #include "sandbox/win/src/nt_internals.h"
 #include "sandbox/win/src/sandbox_nt_types.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // Placement new and delete to be used from ntdll interception code.
 void* __cdecl operator new(size_t size,
@@ -105,7 +105,7 @@
 void* GetGlobalPolicyMemoryForTesting();
 
 // Returns a view of the shared delegate data, or nullopt if none was provided.
-absl::optional<base::span<const uint8_t>> GetGlobalDelegateData();
+std::optional<base::span<const uint8_t>> GetGlobalDelegateData();
 
 // Returns a reference to imported NT functions.
 const NtExports* GetNtExports();
diff --git a/sandbox/win/src/sandbox_policy_base.cc b/sandbox/win/src/sandbox_policy_base.cc
index 4151077e..4e6c0f1 100644
--- a/sandbox/win/src/sandbox_policy_base.cc
+++ b/sandbox/win/src/sandbox_policy_base.cc
@@ -11,6 +11,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/functional/callback.h"
 #include "base/logging.h"
@@ -38,7 +39,6 @@
 #include "sandbox/win/src/signed_policy.h"
 #include "sandbox/win/src/target_process.h"
 #include "sandbox/win/src/top_level_dispatcher.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 namespace {
@@ -83,7 +83,7 @@
 bool ReplacePackageSidInDacl(HANDLE token,
                              const base::win::Sid& package_sid,
                              ACCESS_MASK access) {
-  absl::optional<base::win::SecurityDescriptor> sd =
+  std::optional<base::win::SecurityDescriptor> sd =
       base::win::SecurityDescriptor::FromHandle(
           token, base::win::SecurityObjectType::kKernel,
           DACL_SECURITY_INFORMATION);
@@ -190,14 +190,14 @@
   return policy_;
 }
 
-absl::optional<base::span<const uint8_t>> ConfigBase::policy_span() {
+std::optional<base::span<const uint8_t>> ConfigBase::policy_span() {
   if (policy_) {
     // Note: this is not policy().data_size as that relates to internal data,
     // not the entire allocated policy area.
     return base::span<const uint8_t>(reinterpret_cast<uint8_t*>(policy_.get()),
                                      kPolMemSize);
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 std::vector<std::wstring>& ConfigBase::blocklisted_dlls() {
@@ -565,9 +565,9 @@
 }
 
 ResultCode PolicyBase::MakeTokens(
-    absl::optional<base::win::AccessToken>& initial,
-    absl::optional<base::win::AccessToken>& lockdown) {
-  absl::optional<base::win::Sid> random_sid;
+    std::optional<base::win::AccessToken>& initial,
+    std::optional<base::win::AccessToken>& lockdown) {
+  std::optional<base::win::Sid> random_sid;
   if (config()->add_restricting_random_sid()) {
     random_sid = base::win::Sid::GenerateRandomSid();
   }
@@ -576,7 +576,7 @@
   bool lockdown_default_dacl = config()->lockdown_default_dacl();
   // Create the 'naked' token. This will be the permanent token associated
   // with the process and therefore with any thread that is not impersonating.
-  absl::optional<base::win::AccessToken> primary = CreateRestrictedToken(
+  std::optional<base::win::AccessToken> primary = CreateRestrictedToken(
       config()->GetLockdownTokenLevel(), integrity_level, TokenType::kPrimary,
       lockdown_default_dacl, random_sid);
   if (!primary) {
@@ -603,7 +603,7 @@
   // Create the 'better' token. We use this token as the one that the main
   // thread uses when booting up the process. It should contain most of
   // what we need (before reaching main( ))
-  absl::optional<base::win::AccessToken> impersonation = CreateRestrictedToken(
+  std::optional<base::win::AccessToken> impersonation = CreateRestrictedToken(
       config()->GetInitialTokenLevel(), integrity_level,
       TokenType::kImpersonation, lockdown_default_dacl, random_sid);
   if (!impersonation) {
@@ -760,11 +760,11 @@
   return handle_closer->InitializeTargetHandles(target);
 }
 
-absl::optional<base::span<const uint8_t>> PolicyBase::delegate_data_span() {
+std::optional<base::span<const uint8_t>> PolicyBase::delegate_data_span() {
   if (delegate_data_) {
     return base::make_span(*delegate_data_);
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 void PolicyBase::AddDelegateData(base::span<const uint8_t> data) {
diff --git a/sandbox/win/src/sandbox_policy_base.h b/sandbox/win/src/sandbox_policy_base.h
index 22f872d..4246a43 100644
--- a/sandbox/win/src/sandbox_policy_base.h
+++ b/sandbox/win/src/sandbox_policy_base.h
@@ -13,6 +13,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/compiler_specific.h"
 #include "base/containers/span.h"
 #include "base/dcheck_is_on.h"
@@ -30,7 +31,6 @@
 #include "sandbox/win/src/policy_engine_opcodes.h"
 #include "sandbox/win/src/policy_engine_params.h"
 #include "sandbox/win/src/sandbox_policy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -117,7 +117,7 @@
 
   // Should only be called once the object is configured.
   PolicyGlobal* policy();
-  absl::optional<base::span<const uint8_t>> policy_span();
+  std::optional<base::span<const uint8_t>> policy_span();
   std::vector<std::wstring>& blocklisted_dlls();
   AppContainerBase* app_container();
   IntegrityLevel integrity_level() { return integrity_level_; }
@@ -196,8 +196,8 @@
 
   // Creates the two tokens with the levels specified in a previous call to
   // SetTokenLevel().
-  ResultCode MakeTokens(absl::optional<base::win::AccessToken>& initial,
-                        absl::optional<base::win::AccessToken>& lockdown);
+  ResultCode MakeTokens(std::optional<base::win::AccessToken>& initial,
+                        std::optional<base::win::AccessToken>& lockdown);
 
   // Applies the sandbox to |target| and takes ownership. Internally a
   // call to TargetProcess::Init() is issued.
@@ -239,7 +239,7 @@
   // time.
 
   // Returns nullopt if no data has been set, or a view into the data.
-  absl::optional<base::span<const uint8_t>> delegate_data_span();
+  std::optional<base::span<const uint8_t>> delegate_data_span();
 
   // The user-defined global policy settings.
   HANDLE stdout_handle_;
diff --git a/sandbox/win/src/sandbox_policy_diagnostic.cc b/sandbox/win/src/sandbox_policy_diagnostic.cc
index 1b4c459..e9a52fb 100644
--- a/sandbox/win/src/sandbox_policy_diagnostic.cc
+++ b/sandbox/win/src/sandbox_policy_diagnostic.cc
@@ -108,7 +108,7 @@
 }
 
 std::wstring GetSidAsString(const base::win::Sid& sid) {
-  absl::optional<std::wstring> result = sid.ToSddlString();
+  std::optional<std::wstring> result = sid.ToSddlString();
   if (!result) {
     DCHECK(false) << "Failed to make sddl string";
     return L"";
diff --git a/sandbox/win/src/sandbox_policy_diagnostic.h b/sandbox/win/src/sandbox_policy_diagnostic.h
index 0277435..17564e8 100644
--- a/sandbox/win/src/sandbox_policy_diagnostic.h
+++ b/sandbox/win/src/sandbox_policy_diagnostic.h
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/win/sid.h"
 #include "sandbox/win/src/app_container.h"
 #include "sandbox/win/src/handle_closer.h"
@@ -18,7 +19,6 @@
 #include "sandbox/win/src/process_mitigations.h"
 #include "sandbox/win/src/sandbox.h"
 #include "sandbox/win/src/security_level.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -46,7 +46,7 @@
   JobLevel job_level_ = JobLevel::kUnprotected;
   IntegrityLevel desired_integrity_level_ = INTEGRITY_LEVEL_LAST;
   MitigationFlags desired_mitigations_ = 0;
-  absl::optional<base::win::Sid> app_container_sid_;
+  std::optional<base::win::Sid> app_container_sid_;
   // Only populated if |app_container_sid_| is present.
   std::vector<base::win::Sid> capabilities_;
   // Only populated if |app_container_sid_| is present.
diff --git a/sandbox/win/src/target_process.cc b/sandbox/win/src/target_process.cc
index d3c1324..d2172fe 100644
--- a/sandbox/win/src/target_process.cc
+++ b/sandbox/win/src/target_process.cc
@@ -79,7 +79,7 @@
 // Checks that the impersonation token was applied successfully and hasn't been
 // reverted to an identification level token.
 bool CheckImpersonationToken(HANDLE thread) {
-  absl::optional<base::win::AccessToken> token =
+  std::optional<base::win::AccessToken> token =
       base::win::AccessToken::FromThread(thread);
   if (!token.has_value()) {
     return false;
@@ -252,8 +252,8 @@
 // an IPC it will eventually call the dispatcher.
 ResultCode TargetProcess::Init(
     Dispatcher* ipc_dispatcher,
-    absl::optional<base::span<const uint8_t>> policy,
-    absl::optional<base::span<const uint8_t>> delegate_data,
+    std::optional<base::span<const uint8_t>> policy,
+    std::optional<base::span<const uint8_t>> delegate_data,
     uint32_t shared_IPC_size,
     DWORD* win_error) {
   ResultCode ret = VerifySentinels();
diff --git a/sandbox/win/src/target_process.h b/sandbox/win/src/target_process.h
index aea55b2..6b0efac 100644
--- a/sandbox/win/src/target_process.h
+++ b/sandbox/win/src/target_process.h
@@ -59,8 +59,8 @@
   // Creates the IPC objects such as the BrokerDispatcher and the
   // IPC server. The IPC server uses the services of the thread_pool.
   ResultCode Init(Dispatcher* ipc_dispatcher,
-                  absl::optional<base::span<const uint8_t>> policy,
-                  absl::optional<base::span<const uint8_t>> delegate_data,
+                  std::optional<base::span<const uint8_t>> policy,
+                  std::optional<base::span<const uint8_t>> delegate_data,
                   uint32_t shared_IPC_size,
                   DWORD* win_error);
 
diff --git a/sandbox/win/src/target_services.cc b/sandbox/win/src/target_services.cc
index 4429a2d5..603ed9b 100644
--- a/sandbox/win/src/target_services.cc
+++ b/sandbox/win/src/target_services.cc
@@ -12,6 +12,7 @@
 #include <process.h>
 #include <stdint.h>
 
+#include <optional>
 #include "base/containers/span.h"
 #include "base/logging.h"
 #include "base/win/access_token.h"
@@ -26,7 +27,6 @@
 #include "sandbox/win/src/sandbox_nt_util.h"
 #include "sandbox/win/src/sandbox_types.h"
 #include "sandbox/win/src/sharedmem_ipc_client.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 namespace {
@@ -115,13 +115,13 @@
 }
 
 bool SetProcessIntegrityLevel(IntegrityLevel integrity_level) {
-  absl::optional<DWORD> rid = GetIntegrityLevelRid(integrity_level);
+  std::optional<DWORD> rid = GetIntegrityLevelRid(integrity_level);
   if (!rid) {
     // No mandatory level specified, we don't change it.
     return true;
   }
 
-  absl::optional<base::win::AccessToken> token =
+  std::optional<base::win::AccessToken> token =
       base::win::AccessToken::FromCurrentProcess(/*impersonation=*/false,
                                                  TOKEN_ADJUST_DEFAULT);
   if (!token) {
@@ -149,8 +149,7 @@
   return SBOX_ALL_OK;
 }
 
-absl::optional<base::span<const uint8_t>>
-TargetServicesBase::GetDelegateData() {
+std::optional<base::span<const uint8_t>> TargetServicesBase::GetDelegateData() {
   CHECK(process_state_.InitCalled());
   return sandbox::GetGlobalDelegateData();
 }
diff --git a/sandbox/win/src/target_services.h b/sandbox/win/src/target_services.h
index 45b98fc2..a6c2bdede 100644
--- a/sandbox/win/src/target_services.h
+++ b/sandbox/win/src/target_services.h
@@ -5,10 +5,10 @@
 #ifndef SANDBOX_WIN_SRC_TARGET_SERVICES_H_
 #define SANDBOX_WIN_SRC_TARGET_SERVICES_H_
 
+#include <optional>
 #include "base/containers/span.h"
 #include "sandbox/win/src/sandbox.h"
 #include "sandbox/win/src/win_utils.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -50,7 +50,7 @@
 
   // Public interface of TargetServices. See comments in sandbox.h.
   ResultCode Init() override;
-  absl::optional<base::span<const uint8_t>> GetDelegateData() override;
+  std::optional<base::span<const uint8_t>> GetDelegateData() override;
   void LowerToken() override;
   ProcessState* GetState() override;
 
diff --git a/sandbox/win/src/win_utils.cc b/sandbox/win/src/win_utils.cc
index afdddac..9af6506d 100644
--- a/sandbox/win/src/win_utils.cc
+++ b/sandbox/win/src/win_utils.cc
@@ -205,7 +205,7 @@
   return EqualPath(path, start, kPipe, std::size(kPipe) - 1);
 }
 
-absl::optional<std::wstring> ResolveRegistryName(std::wstring name) {
+std::optional<std::wstring> ResolveRegistryName(std::wstring name) {
   for (size_t i = 0; i < std::size(kKnownKey); ++i) {
     if (name.find(kKnownKey[i].name) == 0) {
       HKEY key;
@@ -213,20 +213,20 @@
       if (ERROR_SUCCESS != ::RegCreateKeyEx(kKnownKey[i].key, L"", 0, nullptr,
                                             0, MAXIMUM_ALLOWED, nullptr, &key,
                                             &disposition)) {
-        return absl::nullopt;
+        return std::nullopt;
       }
 
       auto result = GetPathFromHandle(key);
       ::RegCloseKey(key);
 
       if (!result)
-        return absl::nullopt;
+        return std::nullopt;
 
       result->append(name.substr(wcslen(kKnownKey[i].name)));
       return result;
     }
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 // |full_path| can have any of the following forms:
@@ -442,19 +442,19 @@
   return false;
 }
 
-absl::optional<std::wstring> GetNtPathFromWin32Path(const std::wstring& path) {
+std::optional<std::wstring> GetNtPathFromWin32Path(const std::wstring& path) {
   base::win::ScopedHandle file(::CreateFileW(
       path.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
       nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr));
   if (!file.IsValid())
-    return absl::nullopt;
+    return std::nullopt;
   return GetPathFromHandle(file.Get());
 }
 
-absl::optional<std::wstring> GetPathFromHandle(HANDLE handle) {
+std::optional<std::wstring> GetPathFromHandle(HANDLE handle) {
   auto buffer = QueryObjectInformation(handle, ObjectNameInformation, 512);
   if (!buffer)
-    return absl::nullopt;
+    return std::nullopt;
   OBJECT_NAME_INFORMATION* name =
       reinterpret_cast<OBJECT_NAME_INFORMATION*>(buffer->data());
   return std::wstring(
@@ -462,12 +462,12 @@
       name->ObjectName.Length / sizeof(name->ObjectName.Buffer[0]));
 }
 
-absl::optional<std::wstring> GetTypeNameFromHandle(HANDLE handle) {
+std::optional<std::wstring> GetTypeNameFromHandle(HANDLE handle) {
   // No typename is currently longer than 32 characters on Windows 11, so use a
   // hint of 128 bytes.
   auto buffer = QueryObjectInformation(handle, ObjectTypeInformation, 128);
   if (!buffer)
-    return absl::nullopt;
+    return std::nullopt;
   OBJECT_TYPE_INFORMATION* name =
       reinterpret_cast<OBJECT_TYPE_INFORMATION*>(buffer->data());
   return std::wstring(name->Name.Buffer,
@@ -539,10 +539,10 @@
   return base_address;
 }
 
-absl::optional<ProcessHandleMap> GetCurrentProcessHandles() {
+std::optional<ProcessHandleMap> GetCurrentProcessHandles() {
   DWORD handle_count;
   if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count))
-    return absl::nullopt;
+    return std::nullopt;
 
   // The system call will return only handles up to the buffer size so add a
   // margin of error of an additional 1000 handles.
@@ -554,7 +554,7 @@
 
   if (!NT_SUCCESS(status)) {
     ::SetLastError(GetLastErrorFromNtStatus(status));
-    return absl::nullopt;
+    return std::nullopt;
   }
   DCHECK(buffer.size() >= return_length);
   DCHECK((buffer.size() % sizeof(uint32_t)) == 0);
diff --git a/sandbox/win/src/win_utils.h b/sandbox/win/src/win_utils.h
index e416d6c..0f62c236 100644
--- a/sandbox/win/src/win_utils.h
+++ b/sandbox/win/src/win_utils.h
@@ -12,8 +12,8 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/win/windows_types.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -71,20 +71,20 @@
 bool SameObject(HANDLE handle, const wchar_t* full_path);
 
 // Resolves a handle to an nt path or nullopt if the path cannot be resolved.
-absl::optional<std::wstring> GetPathFromHandle(HANDLE handle);
+std::optional<std::wstring> GetPathFromHandle(HANDLE handle);
 
 // Resolves a win32 path to an nt path using GetPathFromHandle. The path must
 // exist. Returns the path if the translation was successful.
-absl::optional<std::wstring> GetNtPathFromWin32Path(const std::wstring& path);
+std::optional<std::wstring> GetNtPathFromWin32Path(const std::wstring& path);
 
 // Resolves a handle to its type name. Returns the typename if successful.
-absl::optional<std::wstring> GetTypeNameFromHandle(HANDLE handle);
+std::optional<std::wstring> GetTypeNameFromHandle(HANDLE handle);
 
 // Resolves a user-readable registry path to a system-readable registry path.
 // For example, HKEY_LOCAL_MACHINE\\Software\\microsoft is translated to
 // \\registry\\machine\\software\\microsoft. Returns nullopt if the path
 // cannot be resolved.
-absl::optional<std::wstring> ResolveRegistryName(std::wstring name);
+std::optional<std::wstring> ResolveRegistryName(std::wstring name);
 
 // Allocates |buffer_bytes| in child (PAGE_READWRITE) and copies data
 // from |local_buffer| in this process into |child|. |remote_buffer|
@@ -113,7 +113,7 @@
 // value is returned. Note that unless all threads are suspended in the process
 // the valid handles could change between the return of the list and when you
 // use them.
-absl::optional<ProcessHandleMap> GetCurrentProcessHandles();
+std::optional<ProcessHandleMap> GetCurrentProcessHandles();
 
 }  // namespace sandbox
 
diff --git a/sandbox/win/src/win_utils_unittest.cc b/sandbox/win/src/win_utils_unittest.cc
index 400f09b..4ca9e3a 100644
--- a/sandbox/win/src/win_utils_unittest.cc
+++ b/sandbox/win/src/win_utils_unittest.cc
@@ -99,7 +99,7 @@
   EXPECT_TRUE(base::Contains(entry->second, handle.Get()));
 }
 
-void TestCurrentProcessHandles(absl::optional<ProcessHandleMap> (*func)()) {
+void TestCurrentProcessHandles(std::optional<ProcessHandleMap> (*func)()) {
   std::wstring random_name = GetRandomName();
   ASSERT_FALSE(random_name.empty());
   base::win::ScopedHandle event_handle(
@@ -111,7 +111,7 @@
       PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_USE_DEFAULT_WAIT, nullptr));
   ASSERT_TRUE(pipe_handle.IsValid());
 
-  absl::optional<ProcessHandleMap> handle_map = func();
+  std::optional<ProcessHandleMap> handle_map = func();
   ASSERT_TRUE(handle_map);
   EXPECT_LE(2U, handle_map->size());
   FindHandle(*handle_map, L"Event", event_handle);
diff --git a/sandbox/win/src/window.cc b/sandbox/win/src/window.cc
index ad552760..95a1f1c 100644
--- a/sandbox/win/src/window.cc
+++ b/sandbox/win/src/window.cc
@@ -6,11 +6,11 @@
 
 #include <windows.h>
 
+#include <optional>
 #include "base/notreached.h"
 #include "base/win/security_descriptor.h"
 #include "base/win/sid.h"
 #include "base/win/win_util.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -21,7 +21,7 @@
   if (!current_winsta)
     return SBOX_ERROR_CANNOT_GET_WINSTATION;
 
-  absl::optional<base::win::SecurityDescriptor> sd =
+  std::optional<base::win::SecurityDescriptor> sd =
       base::win::SecurityDescriptor::FromHandle(
           current_winsta, base::win::SecurityObjectType::kWindowStation,
           DACL_SECURITY_INFORMATION);
@@ -69,7 +69,7 @@
 
   // Get the security attributes from the current desktop, we will use this as
   // the base security attributes for the new desktop.
-  absl::optional<base::win::SecurityDescriptor> sd =
+  std::optional<base::win::SecurityDescriptor> sd =
       base::win::SecurityDescriptor::FromHandle(
           current_desktop, base::win::SecurityObjectType::kDesktop,
           DACL_SECURITY_INFORMATION);
diff --git a/sandbox/win/tests/common/test_utils.cc b/sandbox/win/tests/common/test_utils.cc
index 6adb1767..8df7b1d 100644
--- a/sandbox/win/tests/common/test_utils.cc
+++ b/sandbox/win/tests/common/test_utils.cc
@@ -80,7 +80,7 @@
 
 bool IsSidInDacl(const base::win::AccessControlList& dacl,
                  bool allowed,
-                 absl::optional<ACCESS_MASK> mask,
+                 std::optional<ACCESS_MASK> mask,
                  const base::win::Sid& sid) {
   DWORD ace_type = allowed ? ACCESS_ALLOWED_ACE_TYPE : ACCESS_DENIED_ACE_TYPE;
   PACL pacl = dacl.get();
diff --git a/sandbox/win/tests/common/test_utils.h b/sandbox/win/tests/common/test_utils.h
index 8560269..7788155 100644
--- a/sandbox/win/tests/common/test_utils.h
+++ b/sandbox/win/tests/common/test_utils.h
@@ -5,9 +5,9 @@
 #ifndef SANDBOX_WIN_TESTS_COMMON_TEST_UTILS_H_
 #define SANDBOX_WIN_TESTS_COMMON_TEST_UTILS_H_
 
+#include <optional>
 #include "base/win/access_control_list.h"
 #include "base/win/windows_types.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -27,7 +27,7 @@
 // Returns true if the SID and access mask is present.
 bool IsSidInDacl(const base::win::AccessControlList& dacl,
                  bool allowed,
-                 absl::optional<ACCESS_MASK> mask,
+                 std::optional<ACCESS_MASK> mask,
                  const base::win::Sid& sid);
 
 }  // namespace sandbox
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
index 2e0cc37..e7f761d 100644
--- a/services/network/cors/cors_url_loader.cc
+++ b/services/network/cors/cors_url_loader.cc
@@ -883,13 +883,14 @@
   const bool needs_pna_permission =
       state && PrivateNetworkAccessChecker::NeedPermission(
                    request_.url, state->is_web_secure_context,
-                   request_.target_address_space);
+                   request_.required_ip_address_space);
   if (needs_pna_permission &&
       url_loader_network_service_observer_->is_bound()) {
     // Fail the request if `targetAddressSpace` on fetch option is not the same
     // as the real target address space.
-    if (request_.target_address_space != mojom::IPAddressSpace::kUnknown &&
-        request_.target_address_space != request_.target_ip_address_space) {
+    if (request_.required_ip_address_space != mojom::IPAddressSpace::kUnknown &&
+        request_.required_ip_address_space !=
+            request_.target_ip_address_space) {
       HandleComplete(URLLoaderCompletionStatus(
           CorsErrorStatus(mojom::CorsError::kInvalidPrivateNetworkAccess)));
       return;
@@ -904,7 +905,8 @@
       PreflightController::WithTrustedHeaderClient(
           options_ & mojom::kURLLoadOptionUseHeaderClient),
       context_->cors_non_wildcard_request_headers_support(),
-      GetPrivateNetworkAccessPreflightBehavior(request_.target_address_space),
+      GetPrivateNetworkAccessPreflightBehavior(
+          request_.required_ip_address_space),
       tainted_, net::NetworkTrafficAnnotationTag(traffic_annotation_),
       network_loader_factory_, isolation_info_, CloneClientSecurityState(),
       weak_devtools_observer_factory_.GetWeakPtr(), net_log_,
@@ -963,8 +965,8 @@
 
   // Private Network Access warning: ignore net and CORS errors.
   if (net_error == net::OK || sending_pna_only_warning_preflight_) {
-    CHECK(
-        ShouldIgnorePrivateNetworkAccessErrors(request_.target_address_space));
+    CHECK(ShouldIgnorePrivateNetworkAccessErrors(
+        request_.required_ip_address_space));
     CHECK_EQ(*reason, PreflightRequiredReason::kPrivateNetworkAccess);
 
     // Record the existence of the warning so that we can report it to
@@ -1142,7 +1144,7 @@
       // PNA-specific preflight errors during this second preflight request.
       sending_pna_only_warning_preflight_ =
           ShouldIgnorePrivateNetworkAccessErrors(
-              request_.target_address_space) &&
+              request_.required_ip_address_space) &&
           !(NeedsPreflight(request_).has_value() && fetch_cors_flag_);
 
       network_client_receiver_.reset();
diff --git a/services/network/cors/cors_url_loader_factory.cc b/services/network/cors/cors_url_loader_factory.cc
index 349327d..0781bfc6 100644
--- a/services/network/cors/cors_url_loader_factory.cc
+++ b/services/network/cors/cors_url_loader_factory.cc
@@ -743,10 +743,10 @@
     if (client_security_state_ &&
         PrivateNetworkAccessChecker::NeedPermission(
             request.url, client_security_state_->is_web_secure_context,
-            request.target_address_space)) {
-      if (request.target_address_space == mojom::IPAddressSpace::kPublic) {
+            request.required_ip_address_space)) {
+      if (request.required_ip_address_space == mojom::IPAddressSpace::kPublic) {
         mojo::ReportBadMessage(
-            "CorsURLLoaderFactory: target_address_space "
+            "CorsURLLoaderFactory: required_ip_address_space "
             "is set to public.");
         return false;
       }
diff --git a/services/network/cors/cors_url_loader_unittest.cc b/services/network/cors/cors_url_loader_unittest.cc
index 02f7babf..8526016 100644
--- a/services/network/cors/cors_url_loader_unittest.cc
+++ b/services/network/cors/cors_url_loader_unittest.cc
@@ -2520,7 +2520,7 @@
 
   ResourceRequest request;
   request.mode = mojom::RequestMode::kCors;
-  request.target_address_space = mojom::IPAddressSpace::kPrivate;
+  request.required_ip_address_space = mojom::IPAddressSpace::kPrivate;
   request.target_ip_address_space = mojom::IPAddressSpace::kPrivate;
   request.url = GURL("http://foo.example/");
   request.request_initiator = initiator;
diff --git a/services/network/cors/preflight_controller.cc b/services/network/cors/preflight_controller.cc
index e0cfea9..2a10057fc 100644
--- a/services/network/cors/preflight_controller.cc
+++ b/services/network/cors/preflight_controller.cc
@@ -527,7 +527,7 @@
         PrivateNetworkAccessChecker::NeedPermission(
             original_request_.url,
             client_security_state_->is_web_secure_context,
-            original_request_.target_address_space);
+            original_request_.required_ip_address_space);
 
     if (!needs_permission) {
       FinishHandleResponseHeader(net_error, std::move(detected_error_status),
diff --git a/services/network/public/cpp/resource_request.cc b/services/network/public/cpp/resource_request.cc
index 2a309fe..39c9452 100644
--- a/services/network/public/cpp/resource_request.cc
+++ b/services/network/public/cpp/resource_request.cc
@@ -266,7 +266,7 @@
              request.originated_from_service_worker &&
          skip_service_worker == request.skip_service_worker &&
          corb_detachable == request.corb_detachable && mode == request.mode &&
-         target_address_space == request.target_address_space &&
+         required_ip_address_space == request.required_ip_address_space &&
          credentials_mode == request.credentials_mode &&
          redirect_mode == request.redirect_mode &&
          fetch_integrity == request.fetch_integrity &&
diff --git a/services/network/public/cpp/resource_request.h b/services/network/public/cpp/resource_request.h
index 2ce7143..b270a596a 100644
--- a/services/network/public/cpp/resource_request.h
+++ b/services/network/public/cpp/resource_request.h
@@ -164,7 +164,8 @@
   // `kNoCors` with strong rationale and approval from security experts. See
   // https://fetch.spec.whatwg.org/#concept-request-mode.
   mojom::RequestMode mode = mojom::RequestMode::kNoCors;
-  mojom::IPAddressSpace target_address_space = mojom::IPAddressSpace::kUnknown;
+  mojom::IPAddressSpace required_ip_address_space =
+      mojom::IPAddressSpace::kUnknown;
   mojom::CredentialsMode credentials_mode = mojom::CredentialsMode::kInclude;
   mojom::RedirectMode redirect_mode = mojom::RedirectMode::kFollow;
   std::string fetch_integrity;
diff --git a/services/network/public/cpp/url_request_mojom_traits.cc b/services/network/public/cpp/url_request_mojom_traits.cc
index 502a59b..0cc22ce 100644
--- a/services/network/public/cpp/url_request_mojom_traits.cc
+++ b/services/network/public/cpp/url_request_mojom_traits.cc
@@ -226,7 +226,7 @@
   out->is_ad_tagged = data.is_ad_tagged();
   out->shared_dictionary_writer_enabled =
       data.shared_dictionary_writer_enabled();
-  out->target_address_space = data.required_ip_address_space();
+  out->required_ip_address_space = data.required_ip_address_space();
 #if BUILDFLAG(IS_ANDROID)
   if (!data.ReadCreatedLocation(&out->created_location)) {
     return false;
diff --git a/services/network/public/cpp/url_request_mojom_traits.h b/services/network/public/cpp/url_request_mojom_traits.h
index 1831d5c..76450201c 100644
--- a/services/network/public/cpp/url_request_mojom_traits.h
+++ b/services/network/public/cpp/url_request_mojom_traits.h
@@ -405,7 +405,7 @@
   }
   static network::mojom::IPAddressSpace required_ip_address_space(
       const network::ResourceRequest& request) {
-    return request.target_address_space;
+    return request.required_ip_address_space;
   }
 
 #if BUILDFLAG(IS_ANDROID)
diff --git a/skia/public/mojom/image_info_mojom_traits.cc b/skia/public/mojom/image_info_mojom_traits.cc
index fe5a01a..25c8dab 100644
--- a/skia/public/mojom/image_info_mojom_traits.cc
+++ b/skia/public/mojom/image_info_mojom_traits.cc
@@ -4,11 +4,11 @@
 
 #include "skia/public/mojom/image_info_mojom_traits.h"
 
+#include <optional>
 #include "base/notreached.h"
 #include "base/numerics/checked_math.h"
 #include "base/numerics/safe_conversions.h"
 #include "mojo/public/cpp/bindings/array_data_view.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColorSpace.h"
 #include "third_party/skia/modules/skcms/skcms.h"
 
@@ -16,7 +16,7 @@
 
 namespace {
 
-absl::optional<SkImageInfo> MakeSkImageInfo(
+std::optional<SkImageInfo> MakeSkImageInfo(
     SkColorType color_type,
     SkAlphaType alpha_type,
     int width,
@@ -24,7 +24,7 @@
     mojo::ArrayDataView<float> color_transfer_function,
     mojo::ArrayDataView<float> color_to_xyz_matrix) {
   if (width < 0 || height < 0) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   sk_sp<SkColorSpace> color_space;
   if (!color_transfer_function.is_null() && !color_to_xyz_matrix.is_null()) {
@@ -33,7 +33,7 @@
     // TODO(crbug.com/1394542): Mojo should validate this array size. We can CHECK it instead
     // when it does.
     if (color_transfer_function.size() != 7u) {
-      return absl::nullopt;
+      return std::nullopt;
     }
     transfer_function.g = data[0];
     transfer_function.a = data[1];
@@ -47,7 +47,7 @@
     // TODO(crbug.com/1394542): Mojo should validate this array size. We can CHECK it instead
     // when it does.
     if (color_to_xyz_matrix.size() != 9u) {
-      return absl::nullopt;
+      return std::nullopt;
     }
     memcpy(to_xyz_matrix.vals, color_to_xyz_matrix.data(), 9 * sizeof(float));
     color_space = SkColorSpace::MakeRGB(transfer_function, to_xyz_matrix);
@@ -168,12 +168,12 @@
 }
 
 // static
-absl::optional<std::vector<float>>
+std::optional<std::vector<float>>
 StructTraits<skia::mojom::ImageInfoDataView,
              SkImageInfo>::color_transfer_function(const SkImageInfo& info) {
   SkColorSpace* color_space = info.colorSpace();
   if (!color_space) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   skcms_TransferFunction fn;
   color_space->transferFn(&fn);
@@ -181,12 +181,12 @@
 }
 
 // static
-absl::optional<std::vector<float>>
+std::optional<std::vector<float>>
 StructTraits<skia::mojom::ImageInfoDataView, SkImageInfo>::color_to_xyz_matrix(
     const SkImageInfo& info) {
   SkColorSpace* color_space = info.colorSpace();
   if (!color_space) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   skcms_Matrix3x3 to_xyz_matrix;
   CHECK(color_space->toXYZD50(&to_xyz_matrix));
@@ -222,7 +222,7 @@
     return false;
   }
 
-  absl::optional<SkImageInfo> maybe_info = MakeSkImageInfo(
+  std::optional<SkImageInfo> maybe_info = MakeSkImageInfo(
       color_type, alpha_type, width.ValueOrDie(), height.ValueOrDie(),
       std::move(color_transfer_function), std::move(color_to_xyz_matrix));
   if (!maybe_info.has_value()) {
@@ -254,7 +254,7 @@
     return false;
   }
 
-  absl::optional<SkImageInfo> maybe_info = MakeSkImageInfo(
+  std::optional<SkImageInfo> maybe_info = MakeSkImageInfo(
       kN32_SkColorType, alpha_type, width.ValueOrDie(), height.ValueOrDie(),
       std::move(color_transfer_function), std::move(color_to_xyz_matrix));
   if (!maybe_info.has_value()) {
diff --git a/skia/public/mojom/image_info_mojom_traits.h b/skia/public/mojom/image_info_mojom_traits.h
index 25f3f3a..e1269f9 100644
--- a/skia/public/mojom/image_info_mojom_traits.h
+++ b/skia/public/mojom/image_info_mojom_traits.h
@@ -7,9 +7,9 @@
 
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "skia/public/mojom/image_info.mojom-shared.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkImageInfo.h"
 
 namespace mojo {
@@ -39,9 +39,9 @@
   }
   static uint32_t width(const SkImageInfo& info);
   static uint32_t height(const SkImageInfo& info);
-  static absl::optional<std::vector<float>> color_transfer_function(
+  static std::optional<std::vector<float>> color_transfer_function(
       const SkImageInfo& info);
-  static absl::optional<std::vector<float>> color_to_xyz_matrix(
+  static std::optional<std::vector<float>> color_to_xyz_matrix(
       const SkImageInfo& info);
 
   static bool Read(skia::mojom::ImageInfoDataView data, SkImageInfo* info);
@@ -61,11 +61,11 @@
   static uint32_t height(const SkImageInfo& info) {
     return ImageInfoStructTraits::height(info);
   }
-  static absl::optional<std::vector<float>> color_transfer_function(
+  static std::optional<std::vector<float>> color_transfer_function(
       const SkImageInfo& info) {
     return ImageInfoStructTraits::color_transfer_function(info);
   }
-  static absl::optional<std::vector<float>> color_to_xyz_matrix(
+  static std::optional<std::vector<float>> color_to_xyz_matrix(
       const SkImageInfo& info) {
     return ImageInfoStructTraits::color_to_xyz_matrix(info);
   }
diff --git a/sql/database.cc b/sql/database.cc
index 2b71910..751dd17 100644
--- a/sql/database.cc
+++ b/sql/database.cc
@@ -254,7 +254,7 @@
     // allowing disk access.
     // TODO(paivanof@gmail.com): This should move to the beginning
     // of the function. http://crbug.com/136655.
-    absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+    std::optional<base::ScopedBlockingCall> scoped_blocking_call;
     InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
     // `stmt_` references memory loaned from the sqlite3 library. Stop
@@ -387,7 +387,7 @@
     // will happen on thread not allowing disk access.
     // TODO(paivanof@gmail.com): This should move to the beginning
     // of the function. http://crbug.com/136655.
-    absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+    std::optional<base::ScopedBlockingCall> scoped_blocking_call;
     InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
     // Resetting acquires a lock to ensure no dump is happening on the database
@@ -446,7 +446,7 @@
   CHECK(!options_.exclusive_database_file_lock)
       << "Cannot preload an exclusively locked database.";
 
-  absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+  std::optional<base::ScopedBlockingCall> scoped_blocking_call;
   InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   // Maximum number of bytes that will be prefetched from the database.
@@ -794,7 +794,7 @@
 size_t Database::ComputeMmapSizeForOpen() {
   TRACE_EVENT0("sql", "Database::ComputeMmapSizeForOpen");
 
-  absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+  std::optional<base::ScopedBlockingCall> scoped_blocking_call;
   InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   // How much to map if no errors are found.  50MB encompasses the 99th
@@ -974,7 +974,7 @@
 bool Database::Raze() {
   TRACE_EVENT0("sql", "Database::Raze");
 
-  absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+  std::optional<base::ScopedBlockingCall> scoped_blocking_call;
   InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   if (!db_) {
@@ -1324,7 +1324,7 @@
     return SqliteResultCode::kError;
   }
 
-  absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+  std::optional<base::ScopedBlockingCall> scoped_blocking_call;
   InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   SqliteResultCode sqlite_result_code = SqliteResultCode::kOk;
@@ -1442,7 +1442,7 @@
     return false;
   }
 
-  absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+  std::optional<base::ScopedBlockingCall> scoped_blocking_call;
   InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   while (*sql_script) {
@@ -1525,7 +1525,7 @@
   if (!db_)
     return base::MakeRefCounted<StatementRef>(nullptr, nullptr, poisoned_);
 
-  absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+  std::optional<base::ScopedBlockingCall> scoped_blocking_call;
   InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
 #if DCHECK_IS_ON()
@@ -1612,7 +1612,7 @@
 bool Database::IsSQLValid(const char* sql) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+  std::optional<base::ScopedBlockingCall> scoped_blocking_call;
   InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
   if (!db_) {
     DCHECK(poisoned_) << "Illegal use of Database without a db";
@@ -1807,7 +1807,7 @@
     return false;
   }
 
-  absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+  std::optional<base::ScopedBlockingCall> scoped_blocking_call;
   InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   EnsureSqliteInitialized();
@@ -2293,7 +2293,7 @@
 
 bool Database::CheckpointDatabase() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+  std::optional<base::ScopedBlockingCall> scoped_blocking_call;
   InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   auto sqlite_result_code = ToSqliteResultCode(sqlite3_wal_checkpoint_v2(
diff --git a/sql/database.h b/sql/database.h
index 7917287..ac4a920 100644
--- a/sql/database.h
+++ b/sql/database.h
@@ -14,6 +14,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/containers/flat_map.h"
 #include "base/dcheck_is_on.h"
@@ -33,7 +34,6 @@
 #include "sql/sqlite_result_code.h"
 #include "sql/sqlite_result_code_values.h"
 #include "sql/statement_id.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // Forward declaration for SQLite structures. Headers in the public sql:: API
 // must NOT include sqlite3.h.
@@ -764,7 +764,7 @@
   // declare its blocking execution scope (see https://www.crbug/934302).
   void InitScopedBlockingCall(
       const base::Location& from_here,
-      absl::optional<base::ScopedBlockingCall>* scoped_blocking_call) const {
+      std::optional<base::ScopedBlockingCall>* scoped_blocking_call) const {
     if (!in_memory_)
       scoped_blocking_call->emplace(from_here, base::BlockingType::MAY_BLOCK);
   }
@@ -831,7 +831,7 @@
     // declare its blocking execution scope (see https://www.crbug/934302).
     void InitScopedBlockingCall(
         const base::Location& from_here,
-        absl::optional<base::ScopedBlockingCall>* scoped_blocking_call) const {
+        std::optional<base::ScopedBlockingCall>* scoped_blocking_call) const {
       if (database_)
         database_->InitScopedBlockingCall(from_here, scoped_blocking_call);
     }
diff --git a/sql/database_options_unittest.cc b/sql/database_options_unittest.cc
index f90e9c9..932c4693 100644
--- a/sql/database_options_unittest.cc
+++ b/sql/database_options_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/callback_helpers.h"
@@ -12,7 +13,6 @@
 #include "sql/test/test_helpers.h"
 #include "sql/transaction.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/sqlite/sqlite3.h"
 
 namespace sql {
diff --git a/sql/database_unittest.cc b/sql/database_unittest.cc
index ee636091..a217d09 100644
--- a/sql/database_unittest.cc
+++ b/sql/database_unittest.cc
@@ -80,11 +80,6 @@
 };
 #endif  // BUILDFLAG(IS_POSIX)
 
-bool IsOpenedInCorrectJournalMode(Database* db, bool is_wal) {
-  std::string expected_mode = is_wal ? "wal" : "truncate";
-  return ExecuteWithResult(db, "PRAGMA journal_mode") == expected_mode;
-}
-
 }  // namespace
 
 // We use the parameter to run all tests with WAL mode on and off.
@@ -1920,73 +1915,6 @@
   EXPECT_TRUE(db_->Execute("DROP TRIGGER IF EXISTS trigger"));
 }
 
-// This test ensures that a database can be open/create with a journal mode and
-// can be re-open later with a different journal mode.
-TEST_P(SQLDatabaseTest, ReOpenWithDifferentJournalMode) {
-  const bool is_wal = IsWALEnabled();
-  const base::FilePath journal_path = Database::JournalPath(db_path_);
-  const base::FilePath wal_path = Database::WriteAheadLogPath(db_path_);
-
-  ASSERT_TRUE(db_->Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"));
-  ASSERT_TRUE(db_->Execute("INSERT INTO foo (value) VALUES (12)"));
-
-  // Last insert row ID should be valid.
-  int64_t row = db_->GetLastInsertRowId();
-  EXPECT_LT(0, row);
-
-  // It should be the primary key of the row we just inserted.
-  {
-    Statement s(db_->GetUniqueStatement("SELECT value FROM foo WHERE id=?"));
-    s.BindInt64(0, row);
-    ASSERT_TRUE(s.Step());
-    EXPECT_EQ(12, s.ColumnInt(0));
-  }
-
-  // Ensure appropriate journal mode and the journal file exists.
-  EXPECT_TRUE(IsOpenedInCorrectJournalMode(db_.get(), IsWALEnabled()));
-  EXPECT_EQ(base::PathExists(journal_path), !is_wal);
-  EXPECT_EQ(base::PathExists(wal_path), is_wal);
-
-  db_->Close();
-  if (IsWALEnabled()) {
-    // The WAL journal file is removed on database close. Database that enable
-    // WAL mode can use a different journal mode on a subsequent database open.
-    EXPECT_FALSE(base::PathExists(wal_path));
-  } else {
-    // The Rollback journal should have a zero size when pending operations
-    // are completed.
-    int64_t journal_size = 0;
-    base::GetFileSize(journal_path, &journal_size);
-    EXPECT_EQ(journal_size, 0);
-  }
-
-  // Re-open the database with a different mode (Rollback vs WAL).
-  DatabaseOptions options = GetDBOptions();
-  options.wal_mode = !is_wal;
-#if BUILDFLAG(IS_FUCHSIA)
-  // Exclusive mode needs to be enabled to enter WAL mode on Fuchsia.
-  if (options.wal_mode) {
-    options.exclusive_locking = true;
-  }
-#endif  // BUILDFLAG(IS_FUCHSIA)
-
-  db_ = std::make_unique<Database>(options);
-  ASSERT_TRUE(db_->Open(db_path_));
-
-  // The value for the last inserted row should be valid.
-  {
-    Statement s(db_->GetUniqueStatement("SELECT value FROM foo WHERE id=?"));
-    s.BindInt64(0, row);
-    ASSERT_TRUE(s.Step());
-    EXPECT_EQ(12, s.ColumnInt(0));
-  }
-
-  // Ensure appropriate journal file exists.
-  EXPECT_TRUE(IsOpenedInCorrectJournalMode(db_.get(), options.wal_mode));
-  EXPECT_EQ(base::PathExists(journal_path), is_wal);
-  EXPECT_EQ(base::PathExists(wal_path), !is_wal);
-}
-
 #if BUILDFLAG(IS_WIN)
 
 class SQLDatabaseTestExclusiveFileLockMode
@@ -2094,7 +2022,8 @@
 }
 
 TEST_P(SQLDatabaseTest, OpenedInCorrectMode) {
-  EXPECT_TRUE(IsOpenedInCorrectJournalMode(db_.get(), IsWALEnabled()));
+  std::string expected_mode = IsWALEnabled() ? "wal" : "truncate";
+  EXPECT_EQ(ExecuteWithResult(db_.get(), "PRAGMA journal_mode"), expected_mode);
 }
 
 TEST_P(SQLDatabaseTest, CheckpointDatabase) {
diff --git a/sql/recover_module/parsing.cc b/sql/recover_module/parsing.cc
index 5bc32a49..b1c7289 100644
--- a/sql/recover_module/parsing.cc
+++ b/sql/recover_module/parsing.cc
@@ -9,12 +9,12 @@
 #include <tuple>
 #include <utility>
 
+#include <optional>
 #include "base/check.h"
 #include "base/notreached.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_piece.h"
 #include "sql/recover_module/record.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sql {
 namespace recover {
@@ -63,7 +63,7 @@
 constexpr base::StringPiece kNonNullSql1("NOT");
 constexpr base::StringPiece kNonNullSql2("NULL");
 
-absl::optional<ModuleColumnType> ParseColumnType(
+std::optional<ModuleColumnType> ParseColumnType(
     base::StringPiece column_type_sql) {
   if (column_type_sql == kIntegerSql)
     return ModuleColumnType::kInteger;
@@ -80,7 +80,7 @@
   if (column_type_sql == kAnySql)
     return ModuleColumnType::kAny;
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 // Returns a view into a SQL string representing the column type.
@@ -151,7 +151,7 @@
 
   base::StringPiece column_type_sql;
   std::tie(column_type_sql, sql) = SplitToken(sql);
-  absl::optional<ModuleColumnType> column_type =
+  std::optional<ModuleColumnType> column_type =
       ParseColumnType(column_type_sql);
   if (!column_type.has_value()) {
     // Invalid column type.
diff --git a/sql/recover_module/table.cc b/sql/recover_module/table.cc
index fbd31a0..7e852bf2 100644
--- a/sql/recover_module/table.cc
+++ b/sql/recover_module/table.cc
@@ -4,6 +4,7 @@
 
 #include "sql/recover_module/table.h"
 
+#include <optional>
 #include "base/check_op.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_piece.h"
@@ -11,7 +12,6 @@
 #include "sql/recover_module/cursor.h"
 #include "sql/recover_module/integers.h"
 #include "sql/recover_module/pager.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sql {
 namespace recover {
@@ -21,12 +21,12 @@
 // Returns a null optional if the operation fails in any way. The failure is
 // most likely due to an incorrect table spec (missing attachment or table).
 // Corrupted SQLite metadata can cause failures here.
-absl::optional<int> GetTableRootPageId(sqlite3* sqlite_db,
-                                       const TargetTableSpec& table) {
+std::optional<int> GetTableRootPageId(sqlite3* sqlite_db,
+                                      const TargetTableSpec& table) {
   if (table.table_name == "sqlite_schema") {
     // The sqlite_schema table is always rooted at the first page.
     // SQLite page IDs use 1-based indexing.
-    return absl::optional<int64_t>(1);
+    return std::optional<int64_t>(1);
   }
 
   std::string select_sql =
@@ -37,7 +37,7 @@
                          SQLITE_PREPARE_NO_VTAB, &sqlite_statement,
                          nullptr) != SQLITE_OK) {
     // The sqlite_schema table is missing or its schema is corrupted.
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (sqlite3_bind_text(sqlite_statement, 1, table.table_name.c_str(),
@@ -45,13 +45,13 @@
                         SQLITE_STATIC) != SQLITE_OK) {
     // Binding the table name failed. This shouldn't happen.
     sqlite3_finalize(sqlite_statement);
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (sqlite3_step(sqlite_statement) != SQLITE_ROW) {
     // The database attachment point or table does not exist.
     sqlite3_finalize(sqlite_statement);
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   int64_t root_page = sqlite3_column_int64(sqlite_statement, 0);
@@ -59,13 +59,13 @@
 
   if (!DatabasePageReader::IsValidPageId(root_page)) {
     // Database corruption.
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   static_assert(
       DatabasePageReader::kMaxPageId <= std::numeric_limits<int>::max(),
       "Converting the page ID to int may overflow");
-  return absl::make_optional(static_cast<int>(root_page));
+  return std::make_optional(static_cast<int>(root_page));
 }
 
 // Returns (SQLite status, a SQLite database's page size).
@@ -126,7 +126,7 @@
     std::vector<RecoveredColumnSpec> column_specs) {
   DCHECK(backing_table_spec.IsValid());
 
-  absl::optional<int64_t> backing_table_root_page_id =
+  std::optional<int64_t> backing_table_root_page_id =
       GetTableRootPageId(sqlite_db, backing_table_spec);
   if (!backing_table_root_page_id.has_value()) {
     // Either the backing table specification is incorrect, or the database
diff --git a/sql/sandboxed_vfs.cc b/sql/sandboxed_vfs.cc
index d1fea53a..a0f850c 100644
--- a/sql/sandboxed_vfs.cc
+++ b/sql/sandboxed_vfs.cc
@@ -195,7 +195,7 @@
 
 int SandboxedVfs::Access(const char* full_path, int flags, int& result) {
   DCHECK(full_path);
-  absl::optional<PathAccessInfo> access =
+  std::optional<PathAccessInfo> access =
       delegate_->GetPathAccess(base::FilePath::FromUTF8Unsafe(full_path));
   if (!access) {
     result = 0;
diff --git a/sql/sandboxed_vfs.h b/sql/sandboxed_vfs.h
index 93ae6098..b454fb2 100644
--- a/sql/sandboxed_vfs.h
+++ b/sql/sandboxed_vfs.h
@@ -8,12 +8,13 @@
 #include <stdint.h>
 
 #include <memory>
+#include <optional>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/time/time.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/sqlite/sqlite3.h"
 
 namespace sql {
@@ -58,7 +59,7 @@
 
     // Queries path access information for `file_path`. Returns null if the
     // given path does not exist.
-    virtual absl::optional<PathAccessInfo> GetPathAccess(
+    virtual std::optional<PathAccessInfo> GetPathAccess(
         const base::FilePath& file_path) = 0;
 
     // Resizes a file.
diff --git a/sql/statement.cc b/sql/statement.cc
index 90c39b52..2dfb878e 100644
--- a/sql/statement.cc
+++ b/sql/statement.cc
@@ -72,7 +72,7 @@
   if (!CheckValid())
     return SqliteResultCode::kError;
 
-  absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+  std::optional<base::ScopedBlockingCall> scoped_blocking_call;
   ref_->InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   auto sqlite_result_code = ToSqliteResultCode(sqlite3_step(ref_->stmt()));
@@ -103,7 +103,7 @@
 void Statement::Reset(bool clear_bound_vars) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
+  std::optional<base::ScopedBlockingCall> scoped_blocking_call;
   ref_->InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
   if (is_valid()) {
     if (clear_bound_vars)
diff --git a/sql/test/test_helpers.cc b/sql/test/test_helpers.cc
index d8cddcb..7a1f781 100644
--- a/sql/test/test_helpers.cc
+++ b/sql/test/test_helpers.cc
@@ -12,6 +12,7 @@
 #include <string>
 #include <tuple>
 
+#include <optional>
 #include "base/big_endian.h"
 #include "base/check.h"
 #include "base/check_op.h"
@@ -24,7 +25,6 @@
 #include "sql/database.h"
 #include "sql/statement.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/sqlite/sqlite3.h"
 
 namespace sql::test {
@@ -43,17 +43,16 @@
 // Read the number of the root page of a B-tree (index/table).
 //
 // Returns a 0-indexed page number, not the raw SQLite page number.
-absl::optional<int> GetRootPage(sql::Database& db,
-                                base::StringPiece tree_name) {
+std::optional<int> GetRootPage(sql::Database& db, base::StringPiece tree_name) {
   sql::Statement select(
       db.GetUniqueStatement("SELECT rootpage FROM sqlite_schema WHERE name=?"));
   select.BindString(0, tree_name);
   if (!select.Step())
-    return absl::nullopt;
+    return std::nullopt;
 
   int sqlite_page_number = select.ColumnInt(0);
   if (!sqlite_page_number)
-    return absl::nullopt;
+    return std::nullopt;
 
   return sqlite_page_number - 1;
 }
@@ -117,15 +116,15 @@
 
 }  // namespace
 
-absl::optional<int> ReadDatabasePageSize(const base::FilePath& db_path) {
+std::optional<int> ReadDatabasePageSize(const base::FilePath& db_path) {
   // See https://www.sqlite.org/fileformat2.html#page_size
   constexpr size_t kPageSizeOffset = 16;
   uint8_t raw_page_size_bytes[2];
   base::File file(db_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
   if (!file.IsValid())
-    return absl::nullopt;
+    return std::nullopt;
   if (!file.ReadAndCheck(kPageSizeOffset, raw_page_size_bytes))
-    return absl::nullopt;
+    return std::nullopt;
 
   uint16_t raw_page_size;
   base::ReadBigEndian(raw_page_size_bytes, &raw_page_size);
@@ -142,7 +141,7 @@
   // Sanity-check that the page size is valid.
   constexpr uint16_t kMinPageSize = 512;
   if (page_size < kMinPageSize || (page_size & (page_size - 1)) != 0)
-    return absl::nullopt;
+    return std::nullopt;
 
   return page_size;
 }
@@ -209,7 +208,7 @@
 
 bool CorruptIndexRootPage(const base::FilePath& db_path,
                           base::StringPiece index_name) {
-  absl::optional<int> page_size = ReadDatabasePageSize(db_path);
+  std::optional<int> page_size = ReadDatabasePageSize(db_path);
   if (!page_size.has_value())
     return false;
 
@@ -217,7 +216,7 @@
   if (!db.Open(db_path))
     return false;
 
-  absl::optional<int> page_number = GetRootPage(db, index_name);
+  std::optional<int> page_number = GetRootPage(db, index_name);
   db.Close();
   if (!page_number.has_value())
     return false;
diff --git a/sql/test/test_helpers.h b/sql/test/test_helpers.h
index 459a9e2..32001967 100644
--- a/sql/test/test_helpers.h
+++ b/sql/test/test_helpers.h
@@ -7,11 +7,10 @@
 
 #include <stddef.h>
 #include <stdint.h>
-
+#include <optional>
 #include <string>
 
 #include "base/strings/string_piece.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // Collection of test-only convenience functions.
 
@@ -26,7 +25,7 @@
 namespace sql::test {
 
 // Read a database's page size. Returns nullopt in case of error.
-absl::optional<int> ReadDatabasePageSize(const base::FilePath& db_path);
+std::optional<int> ReadDatabasePageSize(const base::FilePath& db_path);
 
 // SQLite stores the database size in the header, and if the actual
 // OS-derived size is smaller, the database is considered corrupt.
diff --git a/storage/browser/blob/blob_impl.cc b/storage/browser/blob/blob_impl.cc
index ed96092..83dcaa50 100644
--- a/storage/browser/blob/blob_impl.cc
+++ b/storage/browser/blob/blob_impl.cc
@@ -146,7 +146,7 @@
          BlobStatus status) {
         if (status != BlobStatus::DONE) {
           DCHECK(BlobStatusIsError(status));
-          std::move(callback).Run(absl::nullopt);
+          std::move(callback).Run(std::nullopt);
           return;
         }
 
@@ -154,26 +154,26 @@
         // Currently side data is supported only for blobs with a single entry.
         const auto& items = snapshot->items();
         if (items.size() != 1) {
-          std::move(callback).Run(absl::nullopt);
+          std::move(callback).Run(std::nullopt);
           return;
         }
 
         const auto& item = items[0];
         if (item->type() != BlobDataItem::Type::kReadableDataHandle) {
-          std::move(callback).Run(absl::nullopt);
+          std::move(callback).Run(std::nullopt);
           return;
         }
 
         int32_t body_size = item->data_handle()->GetSideDataSize();
         if (body_size == 0) {
-          std::move(callback).Run(absl::nullopt);
+          std::move(callback).Run(std::nullopt);
           return;
         }
         item->data_handle()->ReadSideData(base::BindOnce(
             [](ReadSideDataCallback callback, int result,
                mojo_base::BigBuffer buffer) {
               if (result < 0) {
-                std::move(callback).Run(absl::nullopt);
+                std::move(callback).Run(std::nullopt);
                 return;
               }
               std::move(callback).Run(std::move(buffer));
@@ -197,7 +197,7 @@
 
         if (status != BlobStatus::DONE) {
           DCHECK(BlobStatusIsError(status));
-          std::move(callback).Run(0, absl::nullopt);
+          std::move(callback).Run(0, std::nullopt);
           return;
         }
 
@@ -206,13 +206,13 @@
         // time.
         const auto& items = snapshot->items();
         if (items.size() != 1) {
-          std::move(callback).Run(handle->size(), absl::nullopt);
+          std::move(callback).Run(handle->size(), std::nullopt);
           return;
         }
 
         const auto& item = items[0];
         if (item->type() != BlobDataItem::Type::kFile) {
-          std::move(callback).Run(handle->size(), absl::nullopt);
+          std::move(callback).Run(handle->size(), std::nullopt);
           return;
         }
 
@@ -225,7 +225,7 @@
 
         struct SizeAndTime {
           uint64_t size;
-          absl::optional<base::Time> time;
+          std::optional<base::Time> time;
         };
         base::ThreadPool::PostTaskAndReplyWithResult(
             FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
@@ -233,7 +233,7 @@
                 [](const base::FilePath& path) {
                   base::File::Info info;
                   if (!base::GetFileInfo(path, &info))
-                    return SizeAndTime{0, absl::nullopt};
+                    return SizeAndTime{0, std::nullopt};
                   return SizeAndTime{static_cast<uint64_t>(info.size),
                                      info.last_modified};
                 },
diff --git a/storage/browser/blob/blob_memory_controller.cc b/storage/browser/blob/blob_memory_controller.cc
index 714f8b5..c262aa06 100644
--- a/storage/browser/blob/blob_memory_controller.cc
+++ b/storage/browser/blob/blob_memory_controller.cc
@@ -75,7 +75,7 @@
 BlobStorageLimits CalculateBlobStorageLimitsImpl(
     const FilePath& storage_dir,
     bool disk_enabled,
-    absl::optional<uint64_t> optional_memory_size_for_testing) {
+    std::optional<uint64_t> optional_memory_size_for_testing) {
   int64_t disk_size = 0ull;
   uint64_t memory_size = optional_memory_size_for_testing
                              ? optional_memory_size_for_testing.value()
diff --git a/storage/browser/blob/blob_memory_controller.h b/storage/browser/blob/blob_memory_controller.h
index 3c15e0e..4f9ec4e 100644
--- a/storage/browser/blob/blob_memory_controller.h
+++ b/storage/browser/blob/blob_memory_controller.h
@@ -15,6 +15,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/containers/lru_cache.h"
 #include "base/feature_list.h"
@@ -28,7 +29,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "storage/browser/blob/blob_storage_constants.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class TaskRunner;
@@ -281,7 +281,7 @@
   bool did_calculate_storage_limits_ = false;
   std::vector<base::OnceClosure> on_calculate_limits_callbacks_;
 
-  absl::optional<uint64_t> amount_of_memory_for_testing_;
+  std::optional<uint64_t> amount_of_memory_for_testing_;
 
   // Memory bookkeeping. These numbers are all disjoint.
   // This is the amount of memory we're using for blobs in RAM, including the
diff --git a/storage/browser/blob/blob_memory_controller_unittest.cc b/storage/browser/blob/blob_memory_controller_unittest.cc
index 061ea14..2d60482 100644
--- a/storage/browser/blob/blob_memory_controller_unittest.cc
+++ b/storage/browser/blob/blob_memory_controller_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "storage/browser/blob/blob_memory_controller.h"
 
+#include <optional>
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/bind.h"
@@ -17,7 +18,6 @@
 #include "storage/browser/blob/blob_data_item.h"
 #include "storage/browser/blob/shareable_blob_data_item.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace storage {
 
@@ -163,7 +163,7 @@
 
   base::test::TaskEnvironment task_environment_;
 
-  absl::optional<base::ScopedDisallowBlocking> disallow_blocking_;
+  std::optional<base::ScopedDisallowBlocking> disallow_blocking_;
 };
 
 TEST_F(BlobMemoryControllerTest, Strategy) {
diff --git a/storage/browser/blob/blob_reader.cc b/storage/browser/blob/blob_reader.cc
index e9b8275..7bc8296 100644
--- a/storage/browser/blob/blob_reader.cc
+++ b/storage/browser/blob/blob_reader.cc
@@ -137,7 +137,7 @@
                      std::move(done), side_data_size));
 }
 
-absl::optional<mojo_base::BigBuffer> BlobReader::TakeSideData() {
+std::optional<mojo_base::BigBuffer> BlobReader::TakeSideData() {
   return std::move(side_data_);
 }
 
diff --git a/storage/browser/blob/blob_reader.h b/storage/browser/blob/blob_reader.h
index af034fea..1a396f38fe 100644
--- a/storage/browser/blob/blob_reader.h
+++ b/storage/browser/blob/blob_reader.h
@@ -12,6 +12,7 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/functional/callback_forward.h"
 #include "base/functional/callback_helpers.h"
@@ -25,7 +26,6 @@
 #include "net/base/completion_once_callback.h"
 #include "services/network/public/cpp/data_pipe_to_source_stream.h"
 #include "storage/browser/blob/blob_storage_constants.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class GURL;
 
@@ -110,7 +110,7 @@
   void ReadSideData(StatusCallback done);
 
   // Passes the side data (if any) from ReadSideData() to the caller.
-  absl::optional<mojo_base::BigBuffer> TakeSideData();
+  std::optional<mojo_base::BigBuffer> TakeSideData();
 
   // Used to set the read position.
   // * This should be called after CalculateSize and before Read.
@@ -256,7 +256,7 @@
   std::unique_ptr<BlobDataSnapshot> blob_data_;
   std::unique_ptr<FileStreamReaderProvider> file_stream_provider_for_testing_;
   scoped_refptr<base::TaskRunner> file_task_runner_;
-  absl::optional<mojo_base::BigBuffer> side_data_;
+  std::optional<mojo_base::BigBuffer> side_data_;
 
   int net_error_;
   bool item_list_populated_ = false;
diff --git a/storage/browser/blob/blob_registry_impl.cc b/storage/browser/blob/blob_registry_impl.cc
index a372aed..9f5959d 100644
--- a/storage/browser/blob/blob_registry_impl.cc
+++ b/storage/browser/blob/blob_registry_impl.cc
@@ -283,7 +283,7 @@
     // requested asynchronously later again anyway.
     for (auto& entry : elements_) {
       if (entry.element->is_bytes())
-        entry.element->get_bytes()->embedded_data = absl::nullopt;
+        entry.element->get_bytes()->embedded_data = std::nullopt;
     }
   }
 
diff --git a/storage/browser/blob/blob_registry_impl_unittest.cc b/storage/browser/blob/blob_registry_impl_unittest.cc
index 00652e0..307e7ae 100644
--- a/storage/browser/blob/blob_registry_impl_unittest.cc
+++ b/storage/browser/blob/blob_registry_impl_unittest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/feature_list.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/bind.h"
@@ -43,7 +44,6 @@
 #include "storage/browser/test/mock_bytes_provider.h"
 #include "storage/browser/test/mock_special_storage_policy.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/blob/data_element.mojom.h"
 #include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h"
 
@@ -194,7 +194,7 @@
  protected:
   base::ScopedTempDir data_dir_;
   base::test::TaskEnvironment task_environment_;
-  absl::optional<base::ScopedDisallowBlocking> disallow_blocking_;
+  std::optional<base::ScopedDisallowBlocking> disallow_blocking_;
   std::unique_ptr<BlobStorageContext> context_;
   BlobUrlRegistry url_registry_;
   std::unique_ptr<BlobRegistryImpl> registry_impl_;
@@ -307,7 +307,7 @@
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          0, absl::nullopt, CreateBytesProvider(""))));
+          0, std::nullopt, CreateBytesProvider(""))));
 
   mojo::Remote<blink::mojom::Blob> blob;
   EXPECT_TRUE(registry_->Register(blob.BindNewPipeAndPassReceiver(), kId,
@@ -587,7 +587,7 @@
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(
       blink::mojom::DataElement::NewFile(blink::mojom::DataElementFile::New(
-          base::FilePath(FILE_PATH_LITERAL("foobar")), 0, 16, absl::nullopt)));
+          base::FilePath(FILE_PATH_LITERAL("foobar")), 0, 16, std::nullopt)));
 
   mojo::PendingRemote<blink::mojom::Blob> blob;
   EXPECT_TRUE(registry_->Register(blob.InitWithNewPipeAndPassReceiver(), kId,
@@ -611,7 +611,7 @@
 
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(blink::mojom::DataElement::NewFile(
-      blink::mojom::DataElementFile::New(path, 0, 16, absl::nullopt)));
+      blink::mojom::DataElementFile::New(path, 0, 16, std::nullopt)));
 
   mojo::PendingRemote<blink::mojom::Blob> blob;
   EXPECT_TRUE(registry_->Register(blob.InitWithNewPipeAndPassReceiver(), kId,
@@ -667,10 +667,10 @@
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          8, absl::nullopt, CreateBytesProvider(""))));
+          8, std::nullopt, CreateBytesProvider(""))));
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          std::numeric_limits<uint64_t>::max() - 4, absl::nullopt,
+          std::numeric_limits<uint64_t>::max() - 4, std::nullopt,
           CreateBytesProvider(""))));
 
   mojo::PendingRemote<blink::mojom::Blob> blob;
@@ -701,11 +701,11 @@
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          kTestBlobStorageMaxDiskSpace, absl::nullopt,
+          kTestBlobStorageMaxDiskSpace, std::nullopt,
           CreateBytesProvider(""))));
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          kTestBlobStorageMaxDiskSpace, absl::nullopt,
+          kTestBlobStorageMaxDiskSpace, std::nullopt,
           CreateBytesProvider(""))));
 
   mojo::PendingRemote<blink::mojom::Blob> blob;
@@ -762,7 +762,7 @@
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          kData.size(), absl::nullopt, CreateBytesProvider(kData))));
+          kData.size(), std::nullopt, CreateBytesProvider(kData))));
 
   mojo::PendingRemote<blink::mojom::Blob> blob;
   EXPECT_TRUE(registry_->Register(blob.InitWithNewPipeAndPassReceiver(), kId,
@@ -792,7 +792,7 @@
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          kData.size(), absl::nullopt, CreateBytesProvider(""))));
+          kData.size(), std::nullopt, CreateBytesProvider(""))));
 
   mojo::PendingRemote<blink::mojom::Blob> blob;
   EXPECT_TRUE(registry_->Register(blob.InitWithNewPipeAndPassReceiver(), kId,
@@ -823,7 +823,7 @@
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          kData.size(), absl::nullopt, CreateBytesProvider(kData))));
+          kData.size(), std::nullopt, CreateBytesProvider(kData))));
 
   mojo::PendingRemote<blink::mojom::Blob> blob;
   EXPECT_TRUE(registry_->Register(blob.InitWithNewPipeAndPassReceiver(), kId,
@@ -859,7 +859,7 @@
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          kData.size(), absl::nullopt, CreateBytesProvider(kData))));
+          kData.size(), std::nullopt, CreateBytesProvider(kData))));
 
   mojo::PendingRemote<blink::mojom::Blob> blob;
   EXPECT_TRUE(registry_->Register(blob.InitWithNewPipeAndPassReceiver(), kId,
@@ -905,7 +905,7 @@
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          32, absl::nullopt, std::move(bytes_provider_remote))));
+          32, std::nullopt, std::move(bytes_provider_remote))));
 
   mojo::PendingRemote<blink::mojom::Blob> blob;
   EXPECT_TRUE(registry_->Register(blob.InitWithNewPipeAndPassReceiver(), kId,
@@ -930,7 +930,7 @@
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          32, absl::nullopt, std::move(bytes_provider_remote))));
+          32, std::nullopt, std::move(bytes_provider_remote))));
 
   mojo::PendingRemote<blink::mojom::Blob> blob;
   EXPECT_TRUE(registry_->Register(blob.InitWithNewPipeAndPassReceiver(), kId,
@@ -1009,7 +1009,7 @@
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          kData.size(), absl::nullopt, std::move(bytes_provider_remote))));
+          kData.size(), std::nullopt, std::move(bytes_provider_remote))));
 
   mojo::PendingRemote<blink::mojom::Blob> blob;
   EXPECT_TRUE(registry_->Register(blob.InitWithNewPipeAndPassReceiver(), kId,
@@ -1045,7 +1045,7 @@
   std::vector<blink::mojom::DataElementPtr> elements;
   elements.push_back(
       blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
-          kData.size(), absl::nullopt, std::move(bytes_provider_remote))));
+          kData.size(), std::nullopt, std::move(bytes_provider_remote))));
 
   mojo::PendingRemote<blink::mojom::Blob> blob;
   EXPECT_TRUE(registry_->Register(blob.InitWithNewPipeAndPassReceiver(), kId,
diff --git a/storage/browser/blob/blob_storage_context.cc b/storage/browser/blob/blob_storage_context.cc
index 2b781f2..140c04a 100644
--- a/storage/browser/blob/blob_storage_context.cc
+++ b/storage/browser/blob/blob_storage_context.cc
@@ -706,7 +706,7 @@
     mojo::PendingRemote<::blink::mojom::Blob> pending_blob,
     const base::FilePath& file_path,
     bool flush_on_write,
-    absl::optional<base::Time> last_modified,
+    std::optional<base::Time> last_modified,
     BlobStorageContext::WriteBlobToFileCallback callback) {
   DCHECK(!last_modified || !last_modified.value().is_null());
   if (profile_directory_.empty()) {
@@ -727,7 +727,7 @@
       base::BindOnce(
           [](base::WeakPtr<BlobStorageContext> blob_context,
              const base::FilePath& file_path, bool flush_on_write,
-             absl::optional<base::Time> last_modified,
+             std::optional<base::Time> last_modified,
              BlobStorageContext::WriteBlobToFileCallback callback,
              std::unique_ptr<BlobDataHandle> handle) {
             if (!handle || !blob_context) {
diff --git a/storage/browser/blob/blob_storage_context.h b/storage/browser/blob/blob_storage_context.h
index ae1d156..f6ce6740 100644
--- a/storage/browser/blob/blob_storage_context.h
+++ b/storage/browser/blob/blob_storage_context.h
@@ -254,7 +254,7 @@
   void WriteBlobToFile(mojo::PendingRemote<::blink::mojom::Blob> blob,
                        const base::FilePath& path,
                        bool flush_on_write,
-                       absl::optional<base::Time> last_modified,
+                       std::optional<base::Time> last_modified,
                        WriteBlobToFileCallback callback) override;
   void Clone(mojo::PendingReceiver<mojom::BlobStorageContext> cloned) override;
 
diff --git a/storage/browser/blob/blob_storage_context_mojo_unittest.cc b/storage/browser/blob/blob_storage_context_mojo_unittest.cc
index df94acb..c24836fc 100644
--- a/storage/browser/blob/blob_storage_context_mojo_unittest.cc
+++ b/storage/browser/blob/blob_storage_context_mojo_unittest.cc
@@ -122,7 +122,7 @@
 
   void CreateFile(base::FilePath path,
                   std::string data,
-                  absl::optional<base::Time> modification_time) {
+                  std::optional<base::Time> modification_time) {
     base::ScopedAllowBlockingForTesting allow_blocking;
     EXPECT_TRUE(base::WriteFile(path, data));
     if (modification_time) {
@@ -136,7 +136,7 @@
       base::test::TaskEnvironment::MainThreadType::IO};
   scoped_refptr<base::SequencedTaskRunner> file_runner_;
   std::unique_ptr<BlobStorageContext> context_;
-  absl::optional<base::ScopedDisallowBlocking> disallow_blocking_;
+  std::optional<base::ScopedDisallowBlocking> disallow_blocking_;
 };
 
 TEST_F(BlobStorageContextMojoTest, BasicBlobCreation) {
@@ -214,7 +214,7 @@
   base::RunLoop loop;
   base::FilePath file_path = temp_dir_.GetPath().AppendASCII("TestFile.txt");
   context->WriteBlobToFile(
-      blob.Unbind(), file_path, true, absl::nullopt,
+      blob.Unbind(), file_path, true, std::nullopt,
       base::BindLambdaForTesting([&](mojom::WriteBlobToFileResult result) {
         EXPECT_EQ(result, mojom::WriteBlobToFileResult::kSuccess);
         loop.Quit();
@@ -494,7 +494,7 @@
   base::FilePath file_path =
       temp_dir_.GetPath().AppendASCII("DestinationFile.txt");
   context->WriteBlobToFile(
-      blob.Unbind(), file_path, true, absl::nullopt,
+      blob.Unbind(), file_path, true, std::nullopt,
       base::BindLambdaForTesting([&loop](mojom::WriteBlobToFileResult result) {
         EXPECT_EQ(result, mojom::WriteBlobToFileResult::kInvalidBlob);
         loop.Quit();
@@ -519,7 +519,7 @@
   base::RunLoop loop;
   base::FilePath file_path = temp_dir_.GetPath().AppendASCII("TestFile.txt");
   context->WriteBlobToFile(
-      blob.Unbind(), file_path, true, absl::nullopt,
+      blob.Unbind(), file_path, true, std::nullopt,
       base::BindLambdaForTesting([&](mojom::WriteBlobToFileResult result) {
         EXPECT_EQ(result, mojom::WriteBlobToFileResult::kBadPath);
         loop.Quit();
@@ -541,7 +541,7 @@
   base::FilePath file_path =
       temp_dir_.GetPath().AppendASCII("..").AppendASCII("UnaccessibleFile.txt");
   context->WriteBlobToFile(
-      blob.Unbind(), file_path, true, absl::nullopt,
+      blob.Unbind(), file_path, true, std::nullopt,
       base::BindLambdaForTesting([&](mojom::WriteBlobToFileResult result) {
         EXPECT_EQ(result, mojom::WriteBlobToFileResult::kBadPath);
         loop.Quit();
@@ -562,7 +562,7 @@
   base::RunLoop loop;
   base::FilePath file_path = base::FilePath::FromUTF8Unsafe("/etc/passwd");
   context->WriteBlobToFile(
-      blob.Unbind(), file_path, true, absl::nullopt,
+      blob.Unbind(), file_path, true, std::nullopt,
       base::BindLambdaForTesting([&](mojom::WriteBlobToFileResult result) {
         EXPECT_EQ(result, mojom::WriteBlobToFileResult::kBadPath);
         loop.Quit();
@@ -609,7 +609,7 @@
       temp_dir_.GetPath().AppendASCII("SourceFile.txt");
 
   // Create a file to copy from.
-  CreateFile(copy_from_file, kData, absl::nullopt);
+  CreateFile(copy_from_file, kData, std::nullopt);
 
   std::unique_ptr<BlobDataBuilder> builder =
       std::make_unique<BlobDataBuilder>("1234");
@@ -628,7 +628,7 @@
                                  .AppendASCII("NotCreatedDirectory")
                                  .AppendASCII("TestFile.txt");
   context->WriteBlobToFile(
-      std::move(blob), file_path, true, absl::nullopt,
+      std::move(blob), file_path, true, std::nullopt,
       base::BindLambdaForTesting([&](mojom::WriteBlobToFileResult result) {
         EXPECT_EQ(result, mojom::WriteBlobToFileResult::kIOError);
         loop.Quit();
@@ -648,7 +648,7 @@
       temp_dir_.GetPath().AppendASCII("SourceFile.txt");
 
   // Create a file to copy from.
-  CreateFile(copy_from_file, kData, absl::nullopt);
+  CreateFile(copy_from_file, kData, std::nullopt);
 
   std::unique_ptr<BlobDataBuilder> builder =
       std::make_unique<BlobDataBuilder>("1234");
@@ -666,7 +666,7 @@
   base::RunLoop loop;
   base::FilePath file_path = temp_dir_.GetPath().AppendASCII("TestFile.txt");
   context->WriteBlobToFile(
-      std::move(blob), file_path, true, absl::nullopt,
+      std::move(blob), file_path, true, std::nullopt,
       base::BindLambdaForTesting([&](mojom::WriteBlobToFileResult result) {
         EXPECT_EQ(result, mojom::WriteBlobToFileResult::kSuccess);
         loop.Quit();
diff --git a/storage/browser/blob/blob_storage_context_unittest.cc b/storage/browser/blob/blob_storage_context_unittest.cc
index 67bbcee..f7df78a 100644
--- a/storage/browser/blob/blob_storage_context_unittest.cc
+++ b/storage/browser/blob/blob_storage_context_unittest.cc
@@ -11,6 +11,7 @@
 #include <string>
 #include <utility>
 
+#include <optional>
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -34,7 +35,6 @@
 #include "storage/browser/test/fake_blob_data_handle.h"
 #include "storage/browser/test/test_file_system_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace storage {
 namespace {
@@ -140,7 +140,7 @@
 
   std::vector<FileCreationInfo> files_;
   base::ScopedTempDir temp_dir_;
-  absl::optional<base::ScopedDisallowBlocking> disallow_blocking_;
+  std::optional<base::ScopedDisallowBlocking> disallow_blocking_;
   scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner();
   scoped_refptr<FileSystemContext> file_system_context_;
 
diff --git a/storage/browser/blob/blob_transport_strategy.cc b/storage/browser/blob/blob_transport_strategy.cc
index 3353d7fc..34911703 100644
--- a/storage/browser/blob/blob_transport_strategy.cc
+++ b/storage/browser/blob/blob_transport_strategy.cc
@@ -323,7 +323,7 @@
  private:
   void OnReply(BlobDataBuilder::FutureFile future_file,
                scoped_refptr<ShareableFileReference> file_reference,
-               absl::optional<base::Time> time_file_modified) {
+               std::optional<base::Time> time_file_modified) {
     if (!time_file_modified) {
       // Writing to the file failed in the renderer.
       std::move(result_callback_).Run(BlobStatus::ERR_FILE_WRITE_FAILED);
diff --git a/storage/browser/blob/blob_transport_strategy_unittest.cc b/storage/browser/blob/blob_transport_strategy_unittest.cc
index 41867d8..7283cd93 100644
--- a/storage/browser/blob/blob_transport_strategy_unittest.cc
+++ b/storage/browser/blob/blob_transport_strategy_unittest.cc
@@ -10,6 +10,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/bind.h"
@@ -27,7 +28,6 @@
 #include "storage/browser/blob/blob_data_builder.h"
 #include "storage/browser/test/mock_bytes_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/blob/data_element.mojom.h"
 
 namespace storage {
@@ -89,7 +89,7 @@
 
   mojo::PendingRemote<blink::mojom::BytesProvider> CreateBytesProvider(
       const std::string& bytes,
-      absl::optional<base::Time> time) {
+      std::optional<base::Time> time) {
     mojo::PendingRemote<blink::mojom::BytesProvider> result;
     auto provider = std::make_unique<MockBytesProvider>(
         std::vector<uint8_t>(bytes.begin(), bytes.end()), &reply_request_count_,
@@ -107,7 +107,7 @@
   base::Time mock_time_;
   BlobStorageLimits limits_;
 
-  absl::optional<base::ScopedDisallowBlocking> disallow_blocking_;
+  std::optional<base::ScopedDisallowBlocking> disallow_blocking_;
 
   std::vector<std::string> bad_messages_;
 
@@ -182,7 +182,7 @@
   expected.AppendData(data);
 
   data = base::RandBytesAsString(10);
-  blink::mojom::DataElementBytes bytes3(data.size(), absl::nullopt,
+  blink::mojom::DataElementBytes bytes3(data.size(), std::nullopt,
                                         mojo::NullRemote());
   mojo::Remote<blink::mojom::BytesProvider> bytes_provider3(
       CreateBytesProvider(data, mock_time_));
@@ -243,7 +243,7 @@
       limits_);
 
   std::string data = base::RandBytesAsString(7);
-  blink::mojom::DataElementBytes bytes(data.size(), absl::nullopt,
+  blink::mojom::DataElementBytes bytes(data.size(), std::nullopt,
                                        mojo::NullRemote());
   mojo::Remote<blink::mojom::BytesProvider> bytes_provider(
       CreateBytesProvider(data.substr(0, 4), mock_time_));
@@ -273,7 +273,7 @@
       limits_);
 
   std::string data = base::RandBytesAsString(4);
-  blink::mojom::DataElementBytes bytes(data.size(), absl::nullopt,
+  blink::mojom::DataElementBytes bytes(data.size(), std::nullopt,
                                        mojo::NullRemote());
   mojo::Remote<blink::mojom::BytesProvider> bytes_provider(
       CreateBytesProvider(data + "foobar", mock_time_));
@@ -315,7 +315,7 @@
 
   std::string data =
       base::RandBytesAsString(kTestBlobStorageMaxSharedMemoryBytes * 3 + 13);
-  blink::mojom::DataElementBytes bytes(data.size(), absl::nullopt,
+  blink::mojom::DataElementBytes bytes(data.size(), std::nullopt,
                                        mojo::NullRemote());
   mojo::Remote<blink::mojom::BytesProvider> bytes_provider(
       CreateBytesProvider(data, mock_time_));
@@ -371,12 +371,12 @@
 
   base::RunLoop loop;
   std::string data = base::RandBytesAsString(kTestBlobStorageMaxFileSizeBytes);
-  blink::mojom::DataElementBytes bytes(data.size(), absl::nullopt,
+  blink::mojom::DataElementBytes bytes(data.size(), std::nullopt,
                                        mojo::NullRemote());
 
   // Must outlive `strategy`.
   mojo::Remote<blink::mojom::BytesProvider> bytes_provider(
-      CreateBytesProvider(data, absl::nullopt));
+      CreateBytesProvider(data, std::nullopt));
 
   BlobStatus status = BlobStatus::PENDING_TRANSPORT;
   auto strategy = BlobTransportStrategy::Create(
@@ -419,7 +419,7 @@
   base::RunLoop loop;
   std::string data =
       base::RandBytesAsString(kTestBlobStorageMaxBlobMemorySize + 42);
-  blink::mojom::DataElementBytes bytes(data.size(), absl::nullopt,
+  blink::mojom::DataElementBytes bytes(data.size(), std::nullopt,
                                        mojo::NullRemote());
 
   // Must outlive `strategy`.
@@ -480,19 +480,19 @@
       base::RandBytesAsString(kTestBlobStorageMaxBlobMemorySize / 3);
 
   // These must outlive `strategy`.
-  blink::mojom::DataElementBytes bytes1(data.size(), absl::nullopt,
+  blink::mojom::DataElementBytes bytes1(data.size(), std::nullopt,
                                         mojo::NullRemote());
   mojo::Remote<blink::mojom::BytesProvider> bytes_provider1(
       CreateBytesProvider(data, mock_time_));
-  blink::mojom::DataElementBytes bytes2(data.size(), absl::nullopt,
+  blink::mojom::DataElementBytes bytes2(data.size(), std::nullopt,
                                         mojo::NullRemote());
   mojo::Remote<blink::mojom::BytesProvider> bytes_provider2(
       CreateBytesProvider(data, mock_time_));
-  blink::mojom::DataElementBytes bytes3(data.size(), absl::nullopt,
+  blink::mojom::DataElementBytes bytes3(data.size(), std::nullopt,
                                         mojo::NullRemote());
   mojo::Remote<blink::mojom::BytesProvider> bytes_provider3(
       CreateBytesProvider(data, mock_time_));
-  blink::mojom::DataElementBytes bytes4(data.size(), absl::nullopt,
+  blink::mojom::DataElementBytes bytes4(data.size(), std::nullopt,
                                         mojo::NullRemote());
   mojo::Remote<blink::mojom::BytesProvider> bytes_provider4(
       CreateBytesProvider(data, mock_time_));
diff --git a/storage/browser/blob/blob_url_loader.cc b/storage/browser/blob/blob_url_loader.cc
index aef3a1b..f011ae6 100644
--- a/storage/browser/blob/blob_url_loader.cc
+++ b/storage/browser/blob/blob_url_loader.cc
@@ -171,7 +171,7 @@
     const std::vector<std::string>& removed_headers,
     const net::HttpRequestHeaders& modified_headers,
     const net::HttpRequestHeaders& modified_cors_exempt_headers,
-    const absl::optional<GURL>& new_url) {
+    const std::optional<GURL>& new_url) {
   NOTREACHED();
 }
 
@@ -192,11 +192,11 @@
     return REQUEST_SIDE_DATA;
   }
 
-  HeadersCompleted(status_code, content_size, absl::nullopt);
+  HeadersCompleted(status_code, content_size, std::nullopt);
   return DONT_REQUEST_SIDE_DATA;
 }
 
-void BlobURLLoader::DidReadSideData(absl::optional<mojo_base::BigBuffer> data) {
+void BlobURLLoader::DidReadSideData(std::optional<mojo_base::BigBuffer> data) {
   HeadersCompleted(net::HTTP_OK, total_size_, std::move(data));
 }
 
@@ -210,7 +210,7 @@
 void BlobURLLoader::HeadersCompleted(
     net::HttpStatusCode status_code,
     uint64_t content_size,
-    absl::optional<mojo_base::BigBuffer> metadata) {
+    std::optional<mojo_base::BigBuffer> metadata) {
   auto response = network::mojom::URLResponseHead::New();
   response->content_length = 0;
   if (status_code == net::HTTP_OK || status_code == net::HTTP_PARTIAL_CONTENT)
diff --git a/storage/browser/blob/blob_url_loader.h b/storage/browser/blob/blob_url_loader.h
index 7cea56f..1021157 100644
--- a/storage/browser/blob/blob_url_loader.h
+++ b/storage/browser/blob/blob_url_loader.h
@@ -67,7 +67,7 @@
       const std::vector<std::string>& removed_headers,
       const net::HttpRequestHeaders& modified_request_headers,
       const net::HttpRequestHeaders& modified_cors_exempt_request_headers,
-      const absl::optional<GURL>& new_url) override;
+      const std::optional<GURL>& new_url) override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
   void PauseReadingBodyFromNet() override {}
@@ -76,12 +76,12 @@
   // MojoBlobReader::Delegate implementation:
   RequestSideData DidCalculateSize(uint64_t total_size,
                                    uint64_t content_size) override;
-  void DidReadSideData(absl::optional<mojo_base::BigBuffer> data) override;
+  void DidReadSideData(std::optional<mojo_base::BigBuffer> data) override;
   void OnComplete(net::Error error_code, uint64_t total_written_bytes) override;
 
   void HeadersCompleted(net::HttpStatusCode status_code,
                         uint64_t content_size,
-                        absl::optional<mojo_base::BigBuffer> metadata);
+                        std::optional<mojo_base::BigBuffer> metadata);
 
   mojo::Receiver<network::mojom::URLLoader> receiver_;
   mojo::Remote<network::mojom::URLLoaderClient> client_;
diff --git a/storage/browser/blob/blob_url_registry.cc b/storage/browser/blob/blob_url_registry.cc
index 0891432..6b8fee3 100644
--- a/storage/browser/blob/blob_url_registry.cc
+++ b/storage/browser/blob/blob_url_registry.cc
@@ -58,7 +58,7 @@
     const blink::StorageKey& storage_key,
     // TODO(https://crbug.com/1224926): Remove these once experiment is over.
     const base::UnguessableToken& unsafe_agent_cluster_id,
-    const absl::optional<net::SchemefulSite>& unsafe_top_level_site) {
+    const std::optional<net::SchemefulSite>& unsafe_top_level_site) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!BlobUrlUtils::UrlHasFragment(blob_url));
   if (IsUrlMapped(blob_url, storage_key)) {
@@ -113,7 +113,7 @@
 }
 
 // TODO(https://crbug.com/1224926): Remove this once experiment is over.
-absl::optional<base::UnguessableToken> BlobUrlRegistry::GetUnsafeAgentClusterID(
+std::optional<base::UnguessableToken> BlobUrlRegistry::GetUnsafeAgentClusterID(
     const GURL& blob_url) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   auto it = url_to_unsafe_agent_cluster_id_.find(blob_url);
@@ -121,10 +121,10 @@
     return it->second;
   if (fallback_)
     return fallback_->GetUnsafeAgentClusterID(blob_url);
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<net::SchemefulSite> BlobUrlRegistry::GetUnsafeTopLevelSite(
+std::optional<net::SchemefulSite> BlobUrlRegistry::GetUnsafeTopLevelSite(
     const GURL& blob_url) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   auto it = url_to_unsafe_top_level_site_.find(blob_url);
@@ -132,7 +132,7 @@
     return it->second;
   if (fallback_)
     return fallback_->GetUnsafeTopLevelSite(blob_url);
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 mojo::PendingRemote<blink::mojom::Blob> BlobUrlRegistry::GetBlobFromUrl(
diff --git a/storage/browser/blob/blob_url_registry.h b/storage/browser/blob/blob_url_registry.h
index 2c7d3fb..bfa492e 100644
--- a/storage/browser/blob/blob_url_registry.h
+++ b/storage/browser/blob/blob_url_registry.h
@@ -62,7 +62,7 @@
       const blink::StorageKey& storage_key,
       // TODO(https://crbug.com/1224926): Remove these once experiment is over.
       const base::UnguessableToken& unsafe_agent_cluster_id,
-      const absl::optional<net::SchemefulSite>& unsafe_top_level_site);
+      const std::optional<net::SchemefulSite>& unsafe_top_level_site);
 
   // Removes the given URL mapping associated with `storage_key` (unless the
   // kSupportPartitionedBlobUrl flag is disabled, in which case `storage_key` is
@@ -76,9 +76,9 @@
                    const blink::StorageKey& storage_key) const;
 
   // TODO(https://crbug.com/1224926): Remove this once experiment is over.
-  absl::optional<base::UnguessableToken> GetUnsafeAgentClusterID(
+  std::optional<base::UnguessableToken> GetUnsafeAgentClusterID(
       const GURL& blob_url) const;
-  absl::optional<net::SchemefulSite> GetUnsafeTopLevelSite(
+  std::optional<net::SchemefulSite> GetUnsafeTopLevelSite(
       const GURL& blob_url) const;
 
   // Returns the blob from the given url. Returns a null remote if the mapping
diff --git a/storage/browser/blob/blob_url_registry_unittest.cc b/storage/browser/blob/blob_url_registry_unittest.cc
index ec02da9..9480a32 100644
--- a/storage/browser/blob/blob_url_registry_unittest.cc
+++ b/storage/browser/blob/blob_url_registry_unittest.cc
@@ -142,8 +142,8 @@
   EXPECT_EQ(2u, registry.url_count());
   EXPECT_TRUE(registry.RemoveUrlMapping(kURL2, storageKey2));
   EXPECT_FALSE(registry.IsUrlMapped(kURL2, storageKey2));
-  EXPECT_EQ(absl::nullopt, registry.GetUnsafeAgentClusterID(kURL2));
-  EXPECT_EQ(absl::nullopt, registry.GetUnsafeTopLevelSite(kURL2));
+  EXPECT_EQ(std::nullopt, registry.GetUnsafeAgentClusterID(kURL2));
+  EXPECT_EQ(std::nullopt, registry.GetUnsafeTopLevelSite(kURL2));
 
   // Both urls point to the same blob.
   EXPECT_TRUE(registry.AddUrlMapping(kURL2, blob1.Clone(), storageKey2,
diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/blob_url_store_impl.cc
index 8b318b4..6253250 100644
--- a/storage/browser/blob/blob_url_store_impl.cc
+++ b/storage/browser/blob/blob_url_store_impl.cc
@@ -89,7 +89,7 @@
     const GURL& url,
     // TODO(https://crbug.com/1224926): Remove these once experiment is over.
     const base::UnguessableToken& unsafe_agent_cluster_id,
-    const absl::optional<net::SchemefulSite>& unsafe_top_level_site,
+    const std::optional<net::SchemefulSite>& unsafe_top_level_site,
     RegisterCallback callback) {
   // TODO(https://crbug.com/1376126): Generate blob URLs here, rather than
   // validating the URLs the renderer process generated.
@@ -116,7 +116,7 @@
 
 void BlobURLStoreImpl::Resolve(const GURL& url, ResolveCallback callback) {
   if (!registry_) {
-    std::move(callback).Run(mojo::NullRemote(), absl::nullopt);
+    std::move(callback).Run(mojo::NullRemote(), std::nullopt);
     return;
   }
   mojo::PendingRemote<blink::mojom::Blob> blob = registry_->GetBlobFromUrl(url);
@@ -130,7 +130,7 @@
     ResolveAsURLLoaderFactoryCallback callback) {
   if (!registry_) {
     BlobURLLoaderFactory::Create(mojo::NullRemote(), url, std::move(receiver));
-    std::move(callback).Run(absl::nullopt, absl::nullopt);
+    std::move(callback).Run(std::nullopt, std::nullopt);
     return;
   }
 
@@ -145,12 +145,12 @@
     mojo::PendingReceiver<blink::mojom::BlobURLToken> token,
     ResolveForNavigationCallback callback) {
   if (!registry_) {
-    std::move(callback).Run(absl::nullopt);
+    std::move(callback).Run(std::nullopt);
     return;
   }
   mojo::PendingRemote<blink::mojom::Blob> blob = registry_->GetBlobFromUrl(url);
   if (!blob) {
-    std::move(callback).Run(absl::nullopt);
+    std::move(callback).Run(std::nullopt);
     return;
   }
   new BlobURLTokenImpl(registry_, url, std::move(blob), std::move(token));
diff --git a/storage/browser/blob/blob_url_store_impl.h b/storage/browser/blob/blob_url_store_impl.h
index 76ff04c..a4a5129 100644
--- a/storage/browser/blob/blob_url_store_impl.h
+++ b/storage/browser/blob/blob_url_store_impl.h
@@ -39,7 +39,7 @@
       const GURL& url,
       // TODO(https://crbug.com/1224926): Remove these once experiment is over.
       const base::UnguessableToken& unsafe_agent_cluster_id,
-      const absl::optional<net::SchemefulSite>& unsafe_top_level_site,
+      const std::optional<net::SchemefulSite>& unsafe_top_level_site,
       RegisterCallback callback) override;
   void Revoke(const GURL& url) override;
   void Resolve(const GURL& url, ResolveCallback callback) override;
diff --git a/storage/browser/blob/blob_url_store_impl_unittest.cc b/storage/browser/blob/blob_url_store_impl_unittest.cc
index f2c4688e..f915522 100644
--- a/storage/browser/blob/blob_url_store_impl_unittest.cc
+++ b/storage/browser/blob/blob_url_store_impl_unittest.cc
@@ -158,7 +158,7 @@
                           mojo::PendingRemote<blink::mojom::Blob>* blob_out,
                           const base::UnguessableToken& agent_registered,
                           mojo::PendingRemote<blink::mojom::Blob> blob,
-                          const absl::optional<base::UnguessableToken>&
+                          const std::optional<base::UnguessableToken>&
                               unsafe_agent_cluster_id) {
                          if (blob)
                            EXPECT_EQ(agent_registered, unsafe_agent_cluster_id);
@@ -373,9 +373,9 @@
       base::BindOnce(
           [](base::OnceClosure done,
              const base::UnguessableToken& agent_registered,
-             const absl::optional<base::UnguessableToken>&
+             const std::optional<base::UnguessableToken>&
                  unsafe_agent_cluster_id,
-             const absl::optional<net::SchemefulSite>& unsafe_top_level_site) {
+             const std::optional<net::SchemefulSite>& unsafe_top_level_site) {
             EXPECT_EQ(agent_registered, unsafe_agent_cluster_id);
             std::move(done).Run();
           },
@@ -411,7 +411,7 @@
       base::BindOnce(
           [](base::OnceClosure done,
              const base::UnguessableToken& agent_registered,
-             const absl::optional<base::UnguessableToken>&
+             const std::optional<base::UnguessableToken>&
                  unsafe_agent_cluster_id) {
             EXPECT_EQ(agent_registered, unsafe_agent_cluster_id);
             std::move(done).Run();
diff --git a/storage/browser/blob/mojo_blob_reader.h b/storage/browser/blob/mojo_blob_reader.h
index f64ca6b7..3dc68b1 100644
--- a/storage/browser/blob/mojo_blob_reader.h
+++ b/storage/browser/blob/mojo_blob_reader.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/sequence_checker.h"
@@ -15,7 +16,6 @@
 #include "net/base/net_errors.h"
 #include "net/http/http_byte_range.h"
 #include "storage/browser/blob/blob_reader.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace network {
 class NetToMojoPendingBuffer;
@@ -53,7 +53,7 @@
 
     // Called if DidCalculateSize returned |REQUEST_SIDE_DATA|, with the side
     // data associated with the blob being read, if any.
-    virtual void DidReadSideData(absl::optional<mojo_base::BigBuffer> data) {}
+    virtual void DidReadSideData(std::optional<mojo_base::BigBuffer> data) {}
 
     // Called whenever some amount of data is read from the blob and about to be
     // written to the data pipe.
diff --git a/storage/browser/blob/write_blob_to_file.cc b/storage/browser/blob/write_blob_to_file.cc
index 2d02d6d..9e9ff28 100644
--- a/storage/browser/blob/write_blob_to_file.cc
+++ b/storage/browser/blob/write_blob_to_file.cc
@@ -144,8 +144,8 @@
     base::Time expected_last_modified_copy_from,
     const base::FilePath& copy_to,
     int64_t offset,
-    absl::optional<int64_t> size,
-    absl::optional<base::Time> last_modified,
+    std::optional<int64_t> size,
+    std::optional<base::Time> last_modified,
     bool flush_on_close,
     file_access::ScopedFileAccess) {
   // Do a full file copy if the sizes match and there is no offset.
@@ -207,7 +207,7 @@
 
 mojom::WriteBlobToFileResult CreateEmptyFileAndMaybeSetModifiedTime(
     base::FilePath file_path,
-    absl::optional<base::Time> last_modified,
+    std::optional<base::Time> last_modified,
     bool flush_on_write) {
   base::File file(file_path,
                   base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
@@ -230,7 +230,7 @@
 
 void HandleModifiedTimeOnBlobFileWriteComplete(
     base::FilePath file_path,
-    absl::optional<base::Time> last_modified,
+    std::optional<base::Time> last_modified,
     bool flush_on_write,
     mojom::BlobStorageContext::WriteBlobToFileCallback callback,
     base::File::Error rv,
@@ -258,7 +258,7 @@
         FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
         base::BindOnce(
             [](int64_t bytes_written, base::FilePath file_path,
-               absl::optional<base::Time> last_modified) {
+               std::optional<base::Time> last_modified) {
               if (!base::TouchFile(file_path, last_modified.value(),
                                    last_modified.value())) {
                 // If the file modification time isn't set correctly, then
@@ -293,7 +293,7 @@
     std::unique_ptr<BlobDataHandle> blob_handle,
     const base::FilePath& file_path,
     bool flush_on_write,
-    absl::optional<base::Time> last_modified,
+    std::optional<base::Time> last_modified,
     mojom::BlobStorageContext::WriteBlobToFileCallback callback,
     BlobStatus status) {
   DCHECK(!last_modified || !last_modified.value().is_null());
@@ -311,11 +311,11 @@
     const BlobDataItem& item = *items[0];
     if (item.type() == BlobDataItem::Type::kFile) {
       // The File API cannot handle uint64_t.
-      absl::optional<int64_t> optional_size = item.length();
+      std::optional<int64_t> optional_size = item.length();
       if (item.length() == blink::BlobUtils::kUnknownSize) {
         // The blob system uses a special value (max uint64_t) to denote an
         // unknown file size. This means the whole file should be copied.
-        optional_size = absl::nullopt;
+        optional_size = std::nullopt;
       } else if (item.length() > std::numeric_limits<int64_t>::max()) {
         std::move(callback).Run(mojom::WriteBlobToFileResult::kError);
         return;
@@ -373,7 +373,7 @@
     std::unique_ptr<BlobDataHandle> blob_handle,
     const base::FilePath& file_path,
     bool flush_on_write,
-    absl::optional<base::Time> last_modified,
+    std::optional<base::Time> last_modified,
     mojom::BlobStorageContext::WriteBlobToFileCallback callback) {
   auto* blob_handle_ptr = blob_handle.get();
   blob_handle_ptr->RunOnConstructionComplete(base::BindOnce(
diff --git a/storage/browser/blob/write_blob_to_file.h b/storage/browser/blob/write_blob_to_file.h
index b787552..e643c0c 100644
--- a/storage/browser/blob/write_blob_to_file.h
+++ b/storage/browser/blob/write_blob_to_file.h
@@ -5,13 +5,13 @@
 #ifndef STORAGE_BROWSER_BLOB_WRITE_BLOB_TO_FILE_H_
 #define STORAGE_BROWSER_BLOB_WRITE_BLOB_TO_FILE_H_
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/time/time.h"
 #include "components/services/storage/public/mojom/blob_storage_context.mojom.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "storage/browser/blob/blob_data_handle.h"
 #include "storage/browser/blob/blob_entry.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace storage {
 
@@ -26,7 +26,7 @@
     std::unique_ptr<BlobDataHandle> blob_handle,
     const base::FilePath& file_path,
     bool flush_on_write,
-    absl::optional<base::Time> last_modified,
+    std::optional<base::Time> last_modified,
     mojom::BlobStorageContext::WriteBlobToFileCallback callback);
 
 }  // namespace storage
diff --git a/storage/browser/database/database_tracker_unittest.cc b/storage/browser/database/database_tracker_unittest.cc
index 5b44ef6..2255d13 100644
--- a/storage/browser/database/database_tracker_unittest.cc
+++ b/storage/browser/database/database_tracker_unittest.cc
@@ -122,7 +122,7 @@
   void NotifyBucketModified(
       QuotaClientType client_id,
       const BucketLocator& bucket,
-      absl::optional<int64_t> delta,
+      std::optional<int64_t> delta,
       base::Time modification_time,
       scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
       base::OnceClosure callback) override {
diff --git a/storage/browser/file_system/file_system_context.cc b/storage/browser/file_system/file_system_context.cc
index 863d9f4..0ed3d82 100644
--- a/storage/browser/file_system/file_system_context.cc
+++ b/storage/browser/file_system/file_system_context.cc
@@ -424,7 +424,7 @@
 
 void FileSystemContext::OpenFileSystem(
     const blink::StorageKey& storage_key,
-    const absl::optional<storage::BucketLocator>& bucket,
+    const std::optional<storage::BucketLocator>& bucket,
     FileSystemType type,
     OpenFileSystemMode mode,
     OpenFileSystemCallback callback) {
@@ -485,7 +485,7 @@
 
 void FileSystemContext::ResolveURLOnOpenFileSystem(
     const blink::StorageKey& storage_key,
-    const absl::optional<storage::BucketLocator>& bucket,
+    const std::optional<storage::BucketLocator>& bucket,
     FileSystemType type,
     OpenFileSystemMode mode,
     OpenFileSystemCallback callback) {
diff --git a/storage/browser/file_system/file_system_context.h b/storage/browser/file_system/file_system_context.h
index f3cd9e48..4ea496b0 100644
--- a/storage/browser/file_system/file_system_context.h
+++ b/storage/browser/file_system/file_system_context.h
@@ -240,7 +240,7 @@
   // Provide a non-null BucketLocator to override the default storage bucket
   // for the root URL (which will be propagated to child URLs).
   void OpenFileSystem(const blink::StorageKey& storage_key,
-                      const absl::optional<storage::BucketLocator>& bucket,
+                      const std::optional<storage::BucketLocator>& bucket,
                       FileSystemType type,
                       OpenFileSystemMode mode,
                       OpenFileSystemCallback callback);
@@ -339,7 +339,7 @@
 
   void ResolveURLOnOpenFileSystemForTesting(
       const blink::StorageKey& storage_key,
-      const absl::optional<storage::BucketLocator>& bucket,
+      const std::optional<storage::BucketLocator>& bucket,
       FileSystemType type,
       OpenFileSystemMode mode,
       OpenFileSystemCallback callback) {
@@ -416,7 +416,7 @@
   // `bucket` will be populated if the non-default storage bucket was used.
   void ResolveURLOnOpenFileSystem(
       const blink::StorageKey& storage_key,
-      const absl::optional<storage::BucketLocator>& bucket,
+      const std::optional<storage::BucketLocator>& bucket,
       FileSystemType type,
       OpenFileSystemMode mode,
       OpenFileSystemCallback callback);
diff --git a/storage/browser/file_system/file_system_context_unittest.cc b/storage/browser/file_system/file_system_context_unittest.cc
index 140d1941..016eb6b 100644
--- a/storage/browser/file_system/file_system_context_unittest.cc
+++ b/storage/browser/file_system/file_system_context_unittest.cc
@@ -103,8 +103,7 @@
     EXPECT_EQ(expect_filesystem_id, url.filesystem_id());
   }
 
-  inline static absl::optional<FileSystemURL> last_resolved_url_ =
-      absl::nullopt;
+  inline static std::optional<FileSystemURL> last_resolved_url_ = std::nullopt;
 
  private:
   base::ScopedTempDir data_dir_;
diff --git a/storage/browser/file_system/file_system_url.h b/storage/browser/file_system/file_system_url.h
index df45f494..d7bef429 100644
--- a/storage/browser/file_system/file_system_url.h
+++ b/storage/browser/file_system/file_system_url.h
@@ -8,12 +8,12 @@
 #include <set>
 #include <string>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/files/file_path.h"
 #include "components/services/storage/public/cpp/buckets/bucket_locator.h"
 #include "storage/common/file_system/file_system_mount_option.h"
 #include "storage/common/file_system/file_system_types.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
 #include "url/gurl.h"
 
@@ -241,7 +241,7 @@
   // Returns the `BucketLocator` for this URL's partitioned file location. In
   // the majority of cases, this will not be populated and the default storage
   // bucket will be used.
-  const absl::optional<BucketLocator>& bucket() const { return bucket_; }
+  const std::optional<BucketLocator>& bucket() const { return bucket_; }
   void SetBucket(const BucketLocator& bucket) { bucket_ = bucket; }
 
   // Returns either `bucket_` or a `BucketLocator` corresponding to the default
@@ -308,7 +308,7 @@
   FileSystemMountOption mount_option_;
 
   // Fields that must be explicitly set separately.
-  absl::optional<BucketLocator> bucket_;
+  std::optional<BucketLocator> bucket_;
 };
 
 using FileSystemURLSet = std::set<FileSystemURL, FileSystemURL::Comparator>;
diff --git a/storage/browser/file_system/file_system_url_unittest.cc b/storage/browser/file_system/file_system_url_unittest.cc
index b6132de..09ce663 100644
--- a/storage/browser/file_system/file_system_url_unittest.cc
+++ b/storage/browser/file_system/file_system_url_unittest.cc
@@ -216,7 +216,7 @@
       no_bucket.CreateSibling(*base::SafeBaseName::Create(FPL("without")));
 
   EXPECT_EQ(with.bucket(), bucket);
-  EXPECT_EQ(without.bucket(), absl::nullopt);
+  EXPECT_EQ(without.bucket(), std::nullopt);
 }
 
 TEST(FileSystemURLTest, EnsureFilePathIsRelative) {
diff --git a/storage/browser/file_system/obfuscated_file_util.cc b/storage/browser/file_system/obfuscated_file_util.cc
index 1e84d35..ffae7d4 100644
--- a/storage/browser/file_system/obfuscated_file_util.cc
+++ b/storage/browser/file_system/obfuscated_file_util.cc
@@ -125,7 +125,7 @@
 DatabaseKey& DatabaseKey::operator=(DatabaseKey&& other) = default;
 
 DatabaseKey::DatabaseKey(const blink::StorageKey& storage_key,
-                         const absl::optional<BucketLocator>& bucket,
+                         const std::optional<BucketLocator>& bucket,
                          const std::string& type) {
   storage_key_ = storage_key;
   bucket_ = bucket;
@@ -272,11 +272,11 @@
 
   // Returns the next StorageKey. Returns empty if there are no more
   // StorageKeys.
-  absl::optional<blink::StorageKey> Next() override {
+  std::optional<blink::StorageKey> Next() override {
     OriginRecord record;
     if (origin_records_.empty()) {
       current_ = record;
-      return absl::nullopt;
+      return std::nullopt;
     }
     record = origin_records_.back();
     origin_records_.pop_back();
@@ -924,7 +924,7 @@
 base::FileErrorOr<base::FilePath>
 ObfuscatedFileUtil::GetDirectoryForBucketAndType(
     const BucketLocator& bucket,
-    const absl::optional<FileSystemType>& type,
+    const std::optional<FileSystemType>& type,
     bool create) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // A default bucket in a first-party context uses
@@ -954,7 +954,7 @@
 base::FileErrorOr<base::FilePath>
 ObfuscatedFileUtil::GetDirectoryForStorageKeyAndType(
     const blink::StorageKey& storage_key,
-    const absl::optional<FileSystemType>& type,
+    const std::optional<FileSystemType>& type,
     bool create) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   ASSIGN_OR_RETURN(base::FilePath path,
@@ -974,13 +974,13 @@
 
 bool ObfuscatedFileUtil::DeleteDirectoryForBucketAndType(
     const BucketLocator& bucket_locator,
-    const absl::optional<FileSystemType>& type) {
+    const std::optional<FileSystemType>& type) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DestroyDirectoryDatabaseForBucket(bucket_locator, type);
 
   // Get the base path for the bucket without the type string appended.
   base::FileErrorOr<base::FilePath> path_without_type =
-      GetDirectoryForBucketAndType(bucket_locator, /*type=*/absl::nullopt,
+      GetDirectoryForBucketAndType(bucket_locator, /*type=*/std::nullopt,
                                    /*create=*/false);
   if (!path_without_type.has_value() || path_without_type->empty()) {
     return true;
@@ -1048,30 +1048,30 @@
 
 void ObfuscatedFileUtil::DestroyDirectoryDatabaseForBucket(
     const BucketLocator& bucket_locator,
-    const absl::optional<FileSystemType>& type) {
+    const std::optional<FileSystemType>& type) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   DatabaseKey key_prefix;
   const std::string type_string =
       type ? SandboxFileSystemBackendDelegate::GetTypeString(type.value())
            : std::string();
-  // `key.bucket()` is absl::nullopt for all non-kTemporary types.
+  // `key.bucket()` is std::nullopt for all non-kTemporary types.
   if (type && (FileSystemTypeToQuotaStorageType(type.value()) ==
                ::blink::mojom::StorageType::kTemporary)) {
     key_prefix =
         DatabaseKey(bucket_locator.storage_key, bucket_locator, type_string);
   } else {  // All other storage types.
     key_prefix =
-        DatabaseKey(bucket_locator.storage_key, absl::nullopt, type_string);
+        DatabaseKey(bucket_locator.storage_key, std::nullopt, type_string);
   }
 
   // If `type` is empty, delete all filesystem types under `storage_key`.
   for (auto iter = directories_.lower_bound(key_prefix);
        iter != directories_.end();) {
-    // If the key matches exactly or `type` is absl::nullopt and just the
+    // If the key matches exactly or `type` is std::nullopt and just the
     // StorageKey and BucketLocator match exactly, delete the database.
     if (iter->first == key_prefix ||
-        (type == absl::nullopt &&
+        (type == std::nullopt &&
          iter->first.storage_key() == key_prefix.storage_key() &&
          iter->first.bucket() == key_prefix.bucket())) {
       std::unique_ptr<SandboxDirectoryDatabase> database =
@@ -1307,7 +1307,7 @@
   DatabaseKey key;
   const std::string type_string =
       SandboxFileSystemBackendDelegate::GetTypeString(url.type());
-  // `key.bucket()` is absl::nullopt for all non-kTemporary types.
+  // `key.bucket()` is std::nullopt for all non-kTemporary types.
   if (FileSystemTypeToQuotaStorageType(url.type()) ==
       ::blink::mojom::StorageType::kTemporary) {
     if (url.bucket().has_value()) {
@@ -1322,7 +1322,7 @@
                         type_string);
     }
   } else {  // All other storage types.
-    key = DatabaseKey(url.storage_key(), absl::nullopt, type_string);
+    key = DatabaseKey(url.storage_key(), std::nullopt, type_string);
   }
 
   auto iter = directories_.find(key);
diff --git a/storage/browser/file_system/obfuscated_file_util.h b/storage/browser/file_system/obfuscated_file_util.h
index e51b9813..eeaee161 100644
--- a/storage/browser/file_system/obfuscated_file_util.h
+++ b/storage/browser/file_system/obfuscated_file_util.h
@@ -45,7 +45,7 @@
 // Class representing the key for directories_. NOTE: The `bucket` value is
 // optional due to usage of ObfuscatedFileUtil where the type is not kTemporary
 // (i.e. kPersistent or kSyncable). For all non-temporary types, expect the
-// bucket member value to be absl::nullopt. The class is implemented as such to
+// bucket member value to be std::nullopt. The class is implemented as such to
 // avoid mapping the same StorageKey to potentially different bucket values,
 // which would cause directories_ lookup errors. NOTE: The `type_string` value
 // is empty when designating a "top-level directory" or a directory that
@@ -66,11 +66,11 @@
   DatabaseKey& operator=(DatabaseKey&& other);
 
   DatabaseKey(const blink::StorageKey& storage_key,
-              const absl::optional<BucketLocator>& bucket,
+              const std::optional<BucketLocator>& bucket,
               const std::string& type_string);
 
   const blink::StorageKey& storage_key() const { return storage_key_; }
-  const absl::optional<BucketLocator>& bucket() const { return bucket_; }
+  const std::optional<BucketLocator>& bucket() const { return bucket_; }
   const std::string& type() const { return type_; }
 
   bool operator==(const DatabaseKey& other) const;
@@ -79,7 +79,7 @@
 
  private:
   blink::StorageKey storage_key_;
-  absl::optional<BucketLocator> bucket_;
+  std::optional<BucketLocator> bucket_;
   std::string type_;
 };
 
@@ -127,9 +127,9 @@
    public:
     virtual ~AbstractStorageKeyEnumerator() = default;
 
-    // Returns the next StorageKey. Returns absl::nullopt if there are no more
+    // Returns the next StorageKey. Returns std::nullopt if there are no more
     // StorageKeys.
-    virtual absl::optional<blink::StorageKey> Next() = 0;
+    virtual std::optional<blink::StorageKey> Next() = 0;
 
     // Returns the current StorageKey's information.
     // `type_string` must be ascii string.
@@ -218,7 +218,7 @@
   // Returns a base::FileError if the directory is undefined.
   base::FileErrorOr<base::FilePath> GetDirectoryForBucketAndType(
       const BucketLocator& bucket_locator,
-      const absl::optional<FileSystemType>& type,
+      const std::optional<FileSystemType>& type,
       bool create);
 
   // Gets the topmost directory specific to this StorageKey and type.  This will
@@ -231,15 +231,15 @@
   // `create` is false).
   base::FileErrorOr<base::FilePath> GetDirectoryForStorageKeyAndType(
       const blink::StorageKey& storage_key,
-      const absl::optional<FileSystemType>& type,
+      const std::optional<FileSystemType>& type,
       bool create);
 
   // Deletes the topmost directory specific to this BucketLocator and type. This
   // will delete its directory database. Deletes the topmost bucket
-  // directory if `type` is absl::nullopt.
+  // directory if `type` is std::nullopt.
   bool DeleteDirectoryForBucketAndType(
       const BucketLocator& bucket_locator,
-      const absl::optional<FileSystemType>& type);
+      const std::optional<FileSystemType>& type);
 
   // This method and all methods of its returned class must be called only on
   // the FILE thread.  The caller is responsible for deleting the returned
@@ -250,7 +250,7 @@
   // database on the disk corresponding to the provided bucket locator and type.
   void DestroyDirectoryDatabaseForBucket(
       const BucketLocator& bucket_locator,
-      const absl::optional<FileSystemType>& type);
+      const std::optional<FileSystemType>& type);
 
   // Computes a cost for storing a given file in the obfuscated FSFU.
   // As the cost of a file is independent of the cost of its parent directories,
diff --git a/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc b/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
index 5d54bc9a..cb7da7c 100644
--- a/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
+++ b/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
@@ -101,7 +101,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-absl::optional<ObfuscatedFileUtilMemoryDelegate::DecomposedPath>
+std::optional<ObfuscatedFileUtilMemoryDelegate::DecomposedPath>
 ObfuscatedFileUtilMemoryDelegate::ParsePath(const base::FilePath& path) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DecomposedPath dp;
@@ -109,11 +109,11 @@
 
   // Ensure |path| is under |root_|.
   if (dp.components.size() < root_path_components_.size())
-    return absl::nullopt;
+    return std::nullopt;
 
   for (size_t i = 0; i < root_path_components_.size(); i++)
     if (dp.components[i] != root_path_components_[i])
-      return absl::nullopt;
+      return std::nullopt;
 
   dp.components.erase(dp.components.begin(),
                       dp.components.begin() + root_path_components_.size());
@@ -126,7 +126,7 @@
     } else if (dp.components[i] == base::FilePath::kParentDirectory) {
       // Beyond |root|?
       if (!i)
-        return absl::nullopt;
+        return std::nullopt;
       dp.components.erase(dp.components.begin() + i - 1,
                           dp.components.begin() + i + 1);
       i -= 2;
@@ -159,7 +159,7 @@
 bool ObfuscatedFileUtilMemoryDelegate::DirectoryExists(
     const base::FilePath& path) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
   return dp && dp->entry && dp->entry->type == Entry::kDirectory;
 }
 
@@ -168,7 +168,7 @@
     bool exclusive,
     bool recursive) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
   if (!dp)
     return base::File::FILE_ERROR_NOT_FOUND;
 
@@ -212,7 +212,7 @@
     const base::FilePath& path,
     bool recursive) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
   if (!dp)
     return false;
 
@@ -235,7 +235,7 @@
 
 bool ObfuscatedFileUtilMemoryDelegate::PathExists(const base::FilePath& path) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
   return dp && dp->entry;
 }
 
@@ -269,7 +269,7 @@
 base::File::Error ObfuscatedFileUtilMemoryDelegate::DeleteFile(
     const base::FilePath& path) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
   if (!dp || !dp->entry)
     return base::File::FILE_ERROR_NOT_FOUND;
 
@@ -284,7 +284,7 @@
     const base::FilePath& path,
     bool* created) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
   *created = false;
   if (!dp || !dp->parent)
     return base::File::FILE_ERROR_NOT_FOUND;
@@ -303,7 +303,7 @@
     const base::FilePath& path,
     base::File::Info* file_info) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
   if (!dp || !dp->entry)
     return base::File::FILE_ERROR_NOT_FOUND;
 
@@ -323,7 +323,7 @@
     const base::Time& last_access_time,
     const base::Time& last_modified_time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
   if (!dp || !dp->entry)
     return base::File::FILE_ERROR_FAILED;
 
@@ -337,7 +337,7 @@
     const base::FilePath& path,
     int64_t length) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
   if (!dp || !dp->entry || dp->entry->type != Entry::kFile)
     return base::File::FILE_ERROR_NOT_FOUND;
 
@@ -367,8 +367,8 @@
     FileSystemOperation::CopyOrMoveOptionSet options,
     NativeFileUtil::CopyOrMoveMode mode) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> src_dp = ParsePath(src_path);
-  absl::optional<DecomposedPath> dest_dp = ParsePath(dest_path);
+  std::optional<DecomposedPath> src_dp = ParsePath(src_path);
+  std::optional<DecomposedPath> dest_dp = ParsePath(dest_path);
 
   if (!src_dp || !src_dp->entry || !dest_dp || !dest_dp->parent)
     return base::File::FILE_ERROR_NOT_FOUND;
@@ -477,7 +477,7 @@
 size_t ObfuscatedFileUtilMemoryDelegate::ComputeDirectorySize(
     const base::FilePath& path) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
   if (!dp || !dp->entry || dp->entry->type != Entry::kDirectory)
     return 0;
 
@@ -503,7 +503,7 @@
                                                scoped_refptr<net::IOBuffer> buf,
                                                int buf_len) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
   if (!dp || dp->entry->type != Entry::kFile)
     return net::ERR_FILE_NOT_FOUND;
 
@@ -532,7 +532,7 @@
     scoped_refptr<net::IOBuffer> buf,
     int buf_len) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
 
   if (!dp || !dp->entry || dp->entry->type != Entry::kFile)
     return net::ERR_FILE_NOT_FOUND;
@@ -595,7 +595,7 @@
   if (result != base::File::FILE_OK)
     return result;
 
-  absl::optional<DecomposedPath> dp = ParsePath(path);
+  std::optional<DecomposedPath> dp = ParsePath(path);
   DCHECK(dp && dp->entry->type == Entry::kFile);
 
   dp->entry->file_content =
@@ -610,7 +610,7 @@
     FileSystemOperation::CopyOrMoveOptionSet /* options */,
     NativeFileUtil::CopyOrMoveMode /* mode */) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  absl::optional<DecomposedPath> dest_dp = ParsePath(dest_path);
+  std::optional<DecomposedPath> dest_dp = ParsePath(dest_path);
 
   if (!dest_dp || !dest_dp->parent)
     return base::File::FILE_ERROR_NOT_FOUND;
diff --git a/storage/browser/file_system/obfuscated_file_util_memory_delegate.h b/storage/browser/file_system/obfuscated_file_util_memory_delegate.h
index 0c6c5e8..e2bd64e8 100644
--- a/storage/browser/file_system/obfuscated_file_util_memory_delegate.h
+++ b/storage/browser/file_system/obfuscated_file_util_memory_delegate.h
@@ -118,7 +118,7 @@
 
   // Parses the given path into a decomposed path and performs validity checks
   // and normalization. Returns an empty value if checks fail.
-  absl::optional<DecomposedPath> ParsePath(const base::FilePath& path);
+  std::optional<DecomposedPath> ParsePath(const base::FilePath& path);
 
   // Creates or opens a file specified in |dp|.
   void CreateOrOpenInternal(const DecomposedPath& dp, uint32_t file_flags);
diff --git a/storage/browser/file_system/obfuscated_file_util_unittest.cc b/storage/browser/file_system/obfuscated_file_util_unittest.cc
index 0c153b4..428978b 100644
--- a/storage/browser/file_system/obfuscated_file_util_unittest.cc
+++ b/storage/browser/file_system/obfuscated_file_util_unittest.cc
@@ -1735,7 +1735,7 @@
   // populates the enumerator being tested. So in a test environment, this
   // enumerator should not have any additional StorageKeys to access via Next().
   if (is_third_party_context() || is_non_default_bucket()) {
-    EXPECT_EQ(absl::nullopt, enumerator->Next());
+    EXPECT_EQ(std::nullopt, enumerator->Next());
     return;
   }
   EXPECT_EQ(storage_key(), enumerator->Next());
@@ -1785,7 +1785,7 @@
   enumerator = ofu()->CreateStorageKeyEnumerator();
   EXPECT_TRUE(enumerator.get());
   std::set<blink::StorageKey> storage_keys_found;
-  absl::optional<blink::StorageKey> enumerator_storage_key;
+  std::optional<blink::StorageKey> enumerator_storage_key;
   while ((enumerator_storage_key = enumerator->Next()).has_value()) {
     storage_keys_found.insert(enumerator_storage_key.value());
     SCOPED_TRACE(testing::Message()
@@ -2667,7 +2667,7 @@
                   .has_value());
 
   // Delete all directories for default_bucket_.
-  ofu()->DeleteDirectoryForBucketAndType(default_bucket_, absl::nullopt);
+  ofu()->DeleteDirectoryForBucketAndType(default_bucket_, std::nullopt);
 
   // The directories for default_bucket_ should be removed.
   ASSERT_THAT(ofu()->GetDirectoryForBucketAndType(default_bucket_,
diff --git a/storage/browser/file_system/quota/quota_backend_impl_unittest.cc b/storage/browser/file_system/quota/quota_backend_impl_unittest.cc
index 10f7f6c7..3d0de9a7 100644
--- a/storage/browser/file_system/quota/quota_backend_impl_unittest.cc
+++ b/storage/browser/file_system/quota/quota_backend_impl_unittest.cc
@@ -62,7 +62,7 @@
   void NotifyBucketModified(
       QuotaClientType client_id,
       const BucketLocator& bucket,
-      absl::optional<int64_t> delta,
+      std::optional<int64_t> delta,
       base::Time modification_time,
       scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
       base::OnceClosure callback) override {
diff --git a/storage/browser/file_system/sandbox_file_stream_reader_unittest.cc b/storage/browser/file_system/sandbox_file_stream_reader_unittest.cc
index 1211c75..be5b4a9 100644
--- a/storage/browser/file_system/sandbox_file_stream_reader_unittest.cc
+++ b/storage/browser/file_system/sandbox_file_stream_reader_unittest.cc
@@ -62,7 +62,7 @@
 
     file_system_context_->OpenFileSystem(
         blink::StorageKey::CreateFromStringForTesting(kURLOrigin),
-        /*bucket=*/absl::nullopt, kFileSystemTypeTemporary,
+        /*bucket=*/std::nullopt, kFileSystemTypeTemporary,
         OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
         base::BindOnce([](const FileSystemURL& root_url,
                           const std::string& name, base::File::Error result) {
diff --git a/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc b/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc
index ac8af87..4378ea7 100644
--- a/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc
+++ b/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc
@@ -65,7 +65,7 @@
 
     file_system_context_->OpenFileSystem(
         blink::StorageKey::CreateFromStringForTesting(kURLOrigin),
-        /*bucket=*/absl::nullopt, kFileSystemTypeTemporary,
+        /*bucket=*/std::nullopt, kFileSystemTypeTemporary,
         OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
         base::BindOnce([](const FileSystemURL& root_url,
                           const std::string& name, base::File::Error result) {
diff --git a/storage/browser/file_system/sandbox_file_system_backend_delegate.cc b/storage/browser/file_system/sandbox_file_system_backend_delegate.cc
index 09a4290..7a832de 100644
--- a/storage/browser/file_system/sandbox_file_system_backend_delegate.cc
+++ b/storage/browser/file_system/sandbox_file_system_backend_delegate.cc
@@ -83,7 +83,7 @@
   }
   ~SandboxObfuscatedStorageKeyEnumerator() override = default;
 
-  absl::optional<blink::StorageKey> Next() override { return enum_->Next(); }
+  std::optional<blink::StorageKey> Next() override { return enum_->Next(); }
 
   bool HasFileSystemType(FileSystemType type) const override {
     return enum_->HasTypeDirectory(
@@ -355,7 +355,7 @@
   std::unique_ptr<StorageKeyEnumerator> enumerator(
       CreateStorageKeyEnumerator());
   std::vector<blink::StorageKey> storage_keys;
-  absl::optional<blink::StorageKey> storage_key;
+  std::optional<blink::StorageKey> storage_key;
   while ((storage_key = enumerator->Next()).has_value()) {
     if (enumerator->HasFileSystemType(type))
       storage_keys.push_back(std::move(storage_key).value());
@@ -369,7 +369,7 @@
     FileSystemType type) {
   DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
   return GetUsageOnFileTaskRunner(file_system_context, storage_key,
-                                  /*bucket_locator=*/absl::nullopt, type);
+                                  /*bucket_locator=*/std::nullopt, type);
 }
 
 int64_t SandboxFileSystemBackendDelegate::GetBucketUsageOnFileTaskRunner(
@@ -384,7 +384,7 @@
 int64_t SandboxFileSystemBackendDelegate::GetUsageOnFileTaskRunner(
     FileSystemContext* file_system_context,
     const blink::StorageKey& storage_key,
-    const absl::optional<BucketLocator>& bucket_locator,
+    const std::optional<BucketLocator>& bucket_locator,
     FileSystemType type) {
   DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
   DCHECK(!bucket_locator.has_value() ||
@@ -623,7 +623,7 @@
 int64_t SandboxFileSystemBackendDelegate::RecalculateUsage(
     FileSystemContext* context,
     const blink::StorageKey& storage_key,
-    const absl::optional<BucketLocator>& bucket_locator,
+    const std::optional<BucketLocator>& bucket_locator,
     FileSystemType type) {
   FileSystemOperationContext operation_context(context);
   FileSystemURL url =
diff --git a/storage/browser/file_system/sandbox_file_system_backend_delegate.h b/storage/browser/file_system/sandbox_file_system_backend_delegate.h
index 90ca94f..2bf20a5 100644
--- a/storage/browser/file_system/sandbox_file_system_backend_delegate.h
+++ b/storage/browser/file_system/sandbox_file_system_backend_delegate.h
@@ -14,6 +14,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/files/file_error_or.h"
 #include "base/files/file_path.h"
@@ -26,7 +27,6 @@
 #include "storage/browser/file_system/file_system_quota_util.h"
 #include "storage/browser/file_system/task_runner_bound_observer_list.h"
 #include "storage/browser/quota/quota_manager_proxy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class SequencedTaskRunner;
@@ -81,9 +81,9 @@
     StorageKeyEnumerator& operator=(const StorageKeyEnumerator&) = delete;
     virtual ~StorageKeyEnumerator() = default;
 
-    // Returns the next StorageKey.  Returns absl::nullopt if there are no more
+    // Returns the next StorageKey.  Returns std::nullopt if there are no more
     // StorageKey.
-    virtual absl::optional<blink::StorageKey> Next() = 0;
+    virtual std::optional<blink::StorageKey> Next() = 0;
 
     // Returns the current StorageKey's information.
     virtual bool HasFileSystemType(FileSystemType type) const = 0;
@@ -273,14 +273,14 @@
   int64_t GetUsageOnFileTaskRunner(
       FileSystemContext* context,
       const blink::StorageKey& storage_key,
-      const absl::optional<BucketLocator>& bucket_locator,
+      const std::optional<BucketLocator>& bucket_locator,
       FileSystemType type);
 
   // If no bucket value is provided, usage will be recalculated for the default
   // bucket for the provided StorageKey value.
   int64_t RecalculateUsage(FileSystemContext* context,
                            const blink::StorageKey& storage_key,
-                           const absl::optional<BucketLocator>& bucket_locator,
+                           const std::optional<BucketLocator>& bucket_locator,
                            FileSystemType type);
 
   ObfuscatedFileUtil* obfuscated_file_util();
diff --git a/storage/browser/file_system/sandbox_file_system_backend_unittest.cc b/storage/browser/file_system/sandbox_file_system_backend_unittest.cc
index 48da87ad..8eb9eeb 100644
--- a/storage/browser/file_system/sandbox_file_system_backend_unittest.cc
+++ b/storage/browser/file_system/sandbox_file_system_backend_unittest.cc
@@ -266,7 +266,7 @@
   size_t temporary_actual_size = 0;
   size_t persistent_actual_size = 0;
 
-  absl::optional<blink::StorageKey> current;
+  std::optional<blink::StorageKey> current;
   while ((current = enumerator->Next()).has_value()) {
     SCOPED_TRACE(testing::Message()
                  << "EnumerateOrigin " << current->origin().Serialize());
diff --git a/storage/browser/quota/client_usage_tracker.cc b/storage/browser/quota/client_usage_tracker.cc
index d2fc7d7..aee894b3 100644
--- a/storage/browser/quota/client_usage_tracker.cc
+++ b/storage/browser/quota/client_usage_tracker.cc
@@ -97,7 +97,7 @@
 }
 
 void ClientUsageTracker::UpdateBucketUsageCache(const BucketLocator& bucket,
-                                                absl::optional<int64_t> delta) {
+                                                std::optional<int64_t> delta) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!IsUsageCacheEnabledForStorageKey(bucket.storage_key)) {
     return;
diff --git a/storage/browser/quota/client_usage_tracker.h b/storage/browser/quota/client_usage_tracker.h
index 5b60bcd..20ce524e 100644
--- a/storage/browser/quota/client_usage_tracker.h
+++ b/storage/browser/quota/client_usage_tracker.h
@@ -75,7 +75,7 @@
   // reduction in quota usage. Negative `delta` values are clamped to ensure the
   // total cached usage never goes below zero (crbug.com/463729).
   void UpdateBucketUsageCache(const BucketLocator& bucket,
-                              absl::optional<int64_t> delta);
+                              std::optional<int64_t> delta);
 
   // Deletes `bucket` from the cache if it exists. Called either for bucket
   // deletion or disabling cache for `bucket`'s Storage Key.
diff --git a/storage/browser/quota/quota_callbacks.h b/storage/browser/quota/quota_callbacks.h
index cebb7e1..aa60c0dc 100644
--- a/storage/browser/quota/quota_callbacks.h
+++ b/storage/browser/quota/quota_callbacks.h
@@ -13,10 +13,10 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/containers/contains.h"
 #include "base/functional/callback.h"
 #include "components/services/storage/public/cpp/buckets/bucket_locator.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h"
 
 namespace blink {
@@ -44,7 +44,7 @@
     base::OnceCallback<void(const std::set<blink::StorageKey>& storage_keys)>;
 using GetUsageInfoCallback = base::OnceCallback<void(UsageInfoEntries)>;
 using GetBucketCallback =
-    base::OnceCallback<void(const absl::optional<BucketLocator>& bucket_info)>;
+    base::OnceCallback<void(const std::optional<BucketLocator>& bucket_info)>;
 
 // Simple template wrapper for a callback queue.
 template <typename CallbackType, typename... Args>
diff --git a/storage/browser/quota/quota_database.cc b/storage/browser/quota/quota_database.cc
index 815b7b02..7c86bfd 100644
--- a/storage/browser/quota/quota_database.cc
+++ b/storage/browser/quota/quota_database.cc
@@ -135,7 +135,7 @@
                                                   : QuotaError::kDatabaseError);
   }
 
-  absl::optional<StorageKey> storage_key =
+  std::optional<StorageKey> storage_key =
       StorageKey::Deserialize(statement.ColumnString(1));
   if (!storage_key.has_value()) {
     return base::unexpected(QuotaError::kStorageKeyError);
@@ -582,7 +582,7 @@
                                                   : QuotaError::kDatabaseError);
   }
 
-  absl::optional<StorageKey> storage_key =
+  std::optional<StorageKey> storage_key =
       StorageKey::Deserialize(statement.ColumnString(1));
   if (!storage_key.has_value()) {
     return base::unexpected(QuotaError::kStorageKeyError);
@@ -668,7 +668,7 @@
   int64_t total_usage = 0;
 
   while (statement.Step()) {
-    absl::optional<StorageKey> read_storage_key =
+    std::optional<StorageKey> read_storage_key =
         StorageKey::Deserialize(statement.ColumnString(1));
     if (!read_storage_key.has_value()) {
       // TODO(estade): this row needs to be deleted.
@@ -721,7 +721,7 @@
 
   std::set<StorageKey> storage_keys;
   while (statement.Step()) {
-    absl::optional<StorageKey> read_storage_key =
+    std::optional<StorageKey> read_storage_key =
         StorageKey::Deserialize(statement.ColumnString(0));
     if (!read_storage_key.has_value()) {
       continue;
@@ -757,7 +757,7 @@
 
   std::set<BucketLocator> buckets;
   while (statement.Step()) {
-    absl::optional<StorageKey> read_storage_key =
+    std::optional<StorageKey> read_storage_key =
         StorageKey::Deserialize(statement.ColumnString(1));
     if (!read_storage_key.has_value()) {
       continue;
@@ -1190,7 +1190,7 @@
   sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
 
   while (statement.Step()) {
-    absl::optional<StorageKey> storage_key =
+    std::optional<StorageKey> storage_key =
         StorageKey::Deserialize(statement.ColumnString(1));
     if (!storage_key.has_value()) {
       continue;
diff --git a/storage/browser/quota/quota_database.h b/storage/browser/quota/quota_database.h
index 1a460253..cc0fd37 100644
--- a/storage/browser/quota/quota_database.h
+++ b/storage/browser/quota/quota_database.h
@@ -12,6 +12,7 @@
 #include <set>
 #include <string>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/files/file_path.h"
 #include "base/functional/callback.h"
@@ -28,7 +29,6 @@
 #include "components/services/storage/public/cpp/quota_error_or.h"
 #include "storage/browser/quota/quota_internals.mojom-forward.h"
 #include "storage/browser/quota/storage_directory.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
 #include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
 
@@ -319,7 +319,7 @@
   static const size_t kIndexCount;
 
   // A descriptor of the last SQL statement that was executed, used for metrics.
-  absl::optional<std::string> last_operation_;
+  std::optional<std::string> last_operation_;
 
   base::RepeatingCallback<void(int)> db_error_callback_;
 };
diff --git a/storage/browser/quota/quota_database_migrations.cc b/storage/browser/quota/quota_database_migrations.cc
index 05715f4..ff85a1e 100644
--- a/storage/browser/quota/quota_database_migrations.cc
+++ b/storage/browser/quota/quota_database_migrations.cc
@@ -184,7 +184,7 @@
     std::string storage_key_string = select_statement.ColumnString(1);
     insert_statement.BindString(1, storage_key_string);
 
-    absl::optional<blink::StorageKey> storage_key =
+    std::optional<blink::StorageKey> storage_key =
         blink::StorageKey::Deserialize(storage_key_string);
     const std::string& host = storage_key.has_value()
                                   ? storage_key.value().origin().host()
diff --git a/storage/browser/quota/quota_database_unittest.cc b/storage/browser/quota/quota_database_unittest.cc
index 84a3473..9aee0ef 100644
--- a/storage/browser/quota/quota_database_unittest.cc
+++ b/storage/browser/quota/quota_database_unittest.cc
@@ -151,7 +151,7 @@
           quota_database->db_->GetCachedStatement(SQL_FROM_HERE, kSql));
       ASSERT_TRUE(statement.is_valid());
 
-      absl::optional<StorageKey> storage_key =
+      std::optional<StorageKey> storage_key =
           StorageKey::Deserialize(entry->storage_key);
       ASSERT_TRUE(storage_key.has_value());
 
diff --git a/storage/browser/quota/quota_manager_impl.cc b/storage/browser/quota/quota_manager_impl.cc
index f1f1e979..bd426a1 100644
--- a/storage/browser/quota/quota_manager_impl.cc
+++ b/storage/browser/quota/quota_manager_impl.cc
@@ -241,7 +241,7 @@
     weak_factory_.InvalidateWeakPtrs();
 
     int64_t quota = desired_storage_key_quota_;
-    absl::optional<int64_t> quota_override_size =
+    std::optional<int64_t> quota_override_size =
         manager()->GetQuotaOverrideForStorageKey(storage_key_);
     if (quota_override_size) {
       quota = *quota_override_size;
@@ -346,7 +346,7 @@
   const StorageKey storage_key_;
   // Non-null iff usage info is to be gathered for an individual bucket. If
   // null, usage is gathered for all buckets in the given host/StorageKey.
-  absl::optional<BucketInfo> bucket_info_;
+  std::optional<BucketInfo> bucket_info_;
   QuotaManagerImpl::UsageAndQuotaForDevtoolsCallback callback_;
   const StorageType type_;
   const bool is_unlimited_;
@@ -2020,7 +2020,7 @@
 
 void QuotaManagerImpl::NotifyBucketModified(QuotaClientType client_id,
                                             const BucketLocator& bucket,
-                                            absl::optional<int64_t> delta,
+                                            std::optional<int64_t> delta,
                                             base::Time modification_time,
                                             base::OnceClosure callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -2104,7 +2104,7 @@
       continue;
     }
 
-    absl::optional<StorageKey> storage_key =
+    std::optional<StorageKey> storage_key =
         StorageKey::Deserialize(entry->storage_key);
     // If the serialization format changes keys may not deserialize.
     if (!storage_key) {
@@ -2144,7 +2144,7 @@
   // Start the storage eviction routine on a full disk error.
   if (static_cast<sql::SqliteErrorCode>(error_code) ==
       sql::SqliteErrorCode::kFullDisk) {
-    OnFullDiskError(absl::nullopt);
+    OnFullDiskError(std::nullopt);
     return;
   }
 
@@ -2183,7 +2183,7 @@
                      weak_factory_.GetWeakPtr()));
 }
 
-void QuotaManagerImpl::OnFullDiskError(absl::optional<StorageKey> storage_key) {
+void QuotaManagerImpl::OnFullDiskError(std::optional<StorageKey> storage_key) {
   if ((base::TimeTicks::Now() - last_full_disk_eviction_time_) >
       base::Minutes(15)) {
     last_full_disk_eviction_time_ = base::TimeTicks::Now();
@@ -2417,7 +2417,7 @@
   if (storage_key_for_pending_storage_pressure_callback_.has_value()) {
     storage_pressure_callback_.Run(
         std::move(storage_key_for_pending_storage_pressure_callback_.value()));
-    storage_key_for_pending_storage_pressure_callback_ = absl::nullopt;
+    storage_key_for_pending_storage_pressure_callback_ = std::nullopt;
   }
 }
 
@@ -2429,7 +2429,7 @@
 void QuotaManagerImpl::OverrideQuotaForStorageKey(
     int handle_id,
     const StorageKey& storage_key,
-    absl::optional<int64_t> quota_size) {
+    std::optional<int64_t> quota_size) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_GE(quota_size.value_or(0), 0)
       << "negative quota override: " << quota_size.value_or(0);
@@ -2465,11 +2465,11 @@
   }
 }
 
-absl::optional<int64_t> QuotaManagerImpl::GetQuotaOverrideForStorageKey(
+std::optional<int64_t> QuotaManagerImpl::GetQuotaOverrideForStorageKey(
     const StorageKey& storage_key) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!base::Contains(devtools_overrides_, storage_key)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return devtools_overrides_[storage_key].quota_size;
 }
@@ -2555,7 +2555,7 @@
       continue;
     }
 
-    absl::optional<StorageKey> storage_key =
+    std::optional<StorageKey> storage_key =
         StorageKey::Deserialize(info->storage_key);
     if (!storage_key.has_value()) {
       continue;
@@ -2778,7 +2778,7 @@
                                             weak_factory_.GetWeakPtr()))));
 }
 
-void QuotaManagerImpl::DidGetSettings(absl::optional<QuotaSettings> settings) {
+void QuotaManagerImpl::DidGetSettings(std::optional<QuotaSettings> settings) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!settings) {
diff --git a/storage/browser/quota/quota_manager_impl.h b/storage/browser/quota/quota_manager_impl.h
index 82476fc..7b0a55a 100644
--- a/storage/browser/quota/quota_manager_impl.h
+++ b/storage/browser/quota/quota_manager_impl.h
@@ -15,6 +15,7 @@
 #include <utility>
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/files/file_path.h"
 #include "base/functional/callback.h"
@@ -45,7 +46,6 @@
 #include "storage/browser/quota/quota_settings.h"
 #include "storage/browser/quota/quota_task.h"
 #include "storage/browser/quota/special_storage_policy.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
 #include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h"
 #include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
@@ -320,7 +320,7 @@
   // cache to instead be discarded, after which it will be lazily recalculated.
   void NotifyBucketModified(QuotaClientType client_id,
                             const BucketLocator& bucket,
-                            absl::optional<int64_t> delta,
+                            std::optional<int64_t> delta,
                             base::Time modification_time,
                             base::OnceClosure callback);
 
@@ -452,7 +452,7 @@
   int GetOverrideHandleId();
   void OverrideQuotaForStorageKey(int handle_id,
                                   const blink::StorageKey& storage_key,
-                                  absl::optional<int64_t> quota_size);
+                                  std::optional<int64_t> quota_size);
   // Called when a DevTools client releases all overrides, however, overrides
   // will not be disabled for any storage keys for which there are other
   // DevTools clients/QuotaOverrideHandle with an active override.
@@ -653,7 +653,7 @@
 
   // Called when the quota database or a quota client run into low disk space
   // errors.
-  void OnFullDiskError(absl::optional<blink::StorageKey> storage_key);
+  void OnFullDiskError(std::optional<blink::StorageKey> storage_key);
 
   // Notifies the embedder that space is too low. This ends up showing a
   // user-facing dialog in Chrome.
@@ -698,7 +698,7 @@
       GetBucketsCallback callback,
       QuotaErrorOr<std::set<BucketLocator>> result);
   void GetQuotaSettings(QuotaSettingsCallback callback);
-  void DidGetSettings(absl::optional<QuotaSettings> settings);
+  void DidGetSettings(std::optional<QuotaSettings> settings);
   void GetStorageCapacity(StorageCapacityCallback callback);
   void ContinueIncognitoGetStorageCapacity(const QuotaSettings& settings);
   void DidGetStorageCapacity(const QuotaAvailability& total_and_available);
@@ -748,7 +748,7 @@
   // to use DetermineStoragePressure().
   void DetermineStoragePressure(int64_t free_space, int64_t total_space);
 
-  absl::optional<int64_t> GetQuotaOverrideForStorageKey(
+  std::optional<int64_t> GetQuotaOverrideForStorageKey(
       const blink::StorageKey&);
 
   template <typename ValueType>
@@ -779,7 +779,7 @@
   bool eviction_disabled_ = false;
   bool bootstrap_disabled_for_testing_ = false;
 
-  absl::optional<blink::StorageKey>
+  std::optional<blink::StorageKey>
       storage_key_for_pending_storage_pressure_callback_;
   scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
   scoped_refptr<base::SequencedTaskRunner> db_runner_;
@@ -810,7 +810,7 @@
   // The storage key for the last time a bucket was opened. This is used as an
   // imperfect estimate of which site may have encountered the last quota
   // database full disk error.
-  absl::optional<blink::StorageKey> last_opened_bucket_site_;
+  std::optional<blink::StorageKey> last_opened_bucket_site_;
 
   // The last time that an eviction round was started due to a full disk error.
   base::TimeTicks last_full_disk_eviction_time_;
diff --git a/storage/browser/quota/quota_manager_proxy.cc b/storage/browser/quota/quota_manager_proxy.cc
index 90242649..6b3f46d 100644
--- a/storage/browser/quota/quota_manager_proxy.cc
+++ b/storage/browser/quota/quota_manager_proxy.cc
@@ -440,7 +440,7 @@
 void QuotaManagerProxy::NotifyBucketModified(
     QuotaClientType client_id,
     const BucketLocator& bucket,
-    absl::optional<int64_t> delta,
+    std::optional<int64_t> delta,
     base::Time modification_time,
     scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
     base::OnceClosure callback) {
@@ -650,7 +650,7 @@
 void QuotaManagerProxy::OverrideQuotaForStorageKey(
     int handle_id,
     const StorageKey& storage_key,
-    absl::optional<int64_t> quota_size,
+    std::optional<int64_t> quota_size,
     scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
     base::OnceClosure callback) {
   DCHECK(callback_task_runner);
diff --git a/storage/browser/quota/quota_manager_proxy.h b/storage/browser/quota/quota_manager_proxy.h
index f15517c..7446b10c 100644
--- a/storage/browser/quota/quota_manager_proxy.h
+++ b/storage/browser/quota/quota_manager_proxy.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <vector>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
@@ -26,7 +27,6 @@
 #include "storage/browser/quota/quota_callbacks.h"
 #include "storage/browser/quota/quota_client_type.h"
 #include "storage/browser/quota/quota_manager_impl.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
 
 namespace blink {
@@ -195,7 +195,7 @@
   virtual void NotifyBucketModified(
       QuotaClientType client_id,
       const BucketLocator& bucket,
-      absl::optional<int64_t> delta,
+      std::optional<int64_t> delta,
       base::Time modification_time,
       scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
       base::OnceClosure callback);
@@ -248,7 +248,7 @@
   void OverrideQuotaForStorageKey(
       int handle_id,
       const blink::StorageKey& storage_key,
-      absl::optional<int64_t> quota_size,
+      std::optional<int64_t> quota_size,
       scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
       base::OnceClosure callback);
   void WithdrawOverridesForHandle(int handle_id);
diff --git a/storage/browser/quota/quota_manager_unittest.cc b/storage/browser/quota/quota_manager_unittest.cc
index c027aeb..7909d2f 100644
--- a/storage/browser/quota/quota_manager_unittest.cc
+++ b/storage/browser/quota/quota_manager_unittest.cc
@@ -596,7 +596,7 @@
   int64_t quota() const { return quota_; }
   int64_t total_space() const { return total_space_; }
   int64_t available_space() const { return available_space_; }
-  const absl::optional<BucketLocator>& eviction_bucket() const {
+  const std::optional<BucketLocator>& eviction_bucket() const {
     return eviction_bucket_;
   }
   const QuotaSettings& settings() const { return settings_; }
@@ -623,8 +623,8 @@
     explicit ObserverNotification(BucketLocator locator)
         : type(ObserverNotifyType::kDelete), bucket_locator(locator) {}
     ObserverNotifyType type;
-    absl::optional<BucketInfo> bucket_info;
-    absl::optional<BucketLocator> bucket_locator;
+    std::optional<BucketInfo> bucket_info;
+    std::optional<BucketLocator> bucket_locator;
   };
 
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -681,7 +681,7 @@
   int64_t quota_;
   int64_t total_space_;
   int64_t available_space_;
-  absl::optional<BucketLocator> eviction_bucket_;
+  std::optional<BucketLocator> eviction_bucket_;
   QuotaSettings settings_;
   std::unique_ptr<QuotaManagerObserverTest> quota_manager_observer_test_;
   std::unique_ptr<base::RunLoop> quota_manager_observer_run_loop_;
@@ -869,7 +869,7 @@
   // Dirty the cache by passing a null delta.
   quota_manager_impl()->NotifyBucketModified(
       QuotaClientType::kFileSystem, first_bucket_locator,
-      /*delta=*/absl::nullopt, base::Time::Now(), base::DoNothing());
+      /*delta=*/std::nullopt, base::Time::Now(), base::DoNothing());
 
   {
     base::test::TestFuture<UsageInfoEntries> future;
@@ -2515,7 +2515,7 @@
       continue;
     }
 
-    absl::optional<StorageKey> storage_key =
+    std::optional<StorageKey> storage_key =
         StorageKey::Deserialize(entry->storage_key);
     ASSERT_TRUE(storage_key.has_value());
 
@@ -2612,7 +2612,7 @@
       continue;
     }
 
-    absl::optional<StorageKey> storage_key =
+    std::optional<StorageKey> storage_key =
         StorageKey::Deserialize(entry->storage_key);
     ASSERT_TRUE(storage_key.has_value());
 
@@ -3442,7 +3442,7 @@
 
   base::RunLoop run_loop3;
   handle2->OverrideQuotaForStorageKey(
-      storage_key, absl::nullopt,
+      storage_key, std::nullopt,
       base::BindLambdaForTesting([&]() { run_loop3.Quit(); }));
   run_loop3.Run();
 
diff --git a/storage/browser/quota/quota_override_handle.cc b/storage/browser/quota/quota_override_handle.cc
index 85cb288..e9d90bd 100644
--- a/storage/browser/quota/quota_override_handle.cc
+++ b/storage/browser/quota/quota_override_handle.cc
@@ -31,7 +31,7 @@
 
 void QuotaOverrideHandle::OverrideQuotaForStorageKey(
     const blink::StorageKey& storage_key,
-    absl::optional<int64_t> quota_size,
+    std::optional<int64_t> quota_size,
     base::OnceClosure callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!id_.has_value()) {
@@ -51,7 +51,7 @@
 void QuotaOverrideHandle::DidGetOverrideHandleId(int id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!id_.has_value());
-  id_ = absl::make_optional(id);
+  id_ = std::make_optional(id);
 
   for (auto& callback : override_callback_queue_) {
     std::move(callback).Run();
diff --git a/storage/browser/quota/quota_override_handle.h b/storage/browser/quota/quota_override_handle.h
index 834eeeee..d9cbf8a5 100644
--- a/storage/browser/quota/quota_override_handle.h
+++ b/storage/browser/quota/quota_override_handle.h
@@ -31,7 +31,7 @@
   QuotaOverrideHandle(const QuotaOverrideHandle&) = delete;
 
   void OverrideQuotaForStorageKey(const blink::StorageKey& storage_key,
-                                  absl::optional<int64_t> quota_size,
+                                  std::optional<int64_t> quota_size,
                                   base::OnceClosure callback);
 
  private:
@@ -43,7 +43,7 @@
 
   const scoped_refptr<QuotaManagerProxy> quota_manager_proxy_
       GUARDED_BY_CONTEXT(sequence_checker_);
-  absl::optional<int> id_ GUARDED_BY_CONTEXT(sequence_checker_);
+  std::optional<int> id_ GUARDED_BY_CONTEXT(sequence_checker_);
   std::vector<base::OnceClosure> override_callback_queue_
       GUARDED_BY_CONTEXT(sequence_checker_);
 
diff --git a/storage/browser/quota/quota_settings.cc b/storage/browser/quota/quota_settings.cc
index b90b655..e530531 100644
--- a/storage/browser/quota/quota_settings.cc
+++ b/storage/browser/quota/quota_settings.cc
@@ -53,7 +53,7 @@
   return settings;
 }
 
-absl::optional<QuotaSettings> CalculateNominalDynamicSettings(
+std::optional<QuotaSettings> CalculateNominalDynamicSettings(
     const base::FilePath& partition_path,
     bool is_incognito,
     QuotaDeviceInfoHelper* device_info_helper) {
@@ -124,7 +124,7 @@
   int64_t total = device_info_helper->AmountOfTotalDiskSpace(partition_path);
   if (total == -1) {
     LOG(ERROR) << "Unable to compute QuotaSettings.";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Pool size calculated by ratio.
diff --git a/storage/browser/quota/quota_settings.h b/storage/browser/quota/quota_settings.h
index 41b41a07..9fd8a98 100644
--- a/storage/browser/quota/quota_settings.h
+++ b/storage/browser/quota/quota_settings.h
@@ -7,12 +7,12 @@
 
 #include <stdint.h>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/files/file_path.h"
 #include "base/functional/callback.h"
 #include "base/time/time.h"
 #include "storage/browser/quota/quota_device_info_helper.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace storage {
 
@@ -60,9 +60,9 @@
 
 // Function type used to return the settings in response to a
 // GetQuotaSettingsFunc invocation. If the embedder cannot
-// produce a settings values, absl::nullopt can be returned.
+// produce a settings values, std::nullopt can be returned.
 using OptionalQuotaSettingsCallback =
-    base::OnceCallback<void(absl::optional<QuotaSettings>)>;
+    base::OnceCallback<void(std::optional<QuotaSettings>)>;
 
 // Function type used to query the embedder about the quota manager settings.
 // This function is invoked on the UI thread.
diff --git a/storage/browser/quota/quota_settings_unittest.cc b/storage/browser/quota/quota_settings_unittest.cc
index 97e6088..55764e8 100644
--- a/storage/browser/quota/quota_settings_unittest.cc
+++ b/storage/browser/quota/quota_settings_unittest.cc
@@ -5,6 +5,7 @@
 #include <memory>
 #include <utility>
 
+#include <optional>
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
@@ -17,7 +18,6 @@
 #include "storage/browser/quota/quota_features.h"
 #include "storage/browser/quota/quota_settings.h"
 #include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 using ::testing::_;
 
@@ -43,14 +43,14 @@
   void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); }
 
   // Synchronous proxy to GetNominalDynamicSettings().
-  absl::optional<QuotaSettings> GetSettings(
+  std::optional<QuotaSettings> GetSettings(
       bool is_incognito,
       QuotaDeviceInfoHelper* device_info_helper) {
-    absl::optional<QuotaSettings> quota_settings;
+    std::optional<QuotaSettings> quota_settings;
     base::RunLoop run_loop;
     GetNominalDynamicSettings(
         profile_path(), is_incognito, device_info_helper,
-        base::BindLambdaForTesting([&](absl::optional<QuotaSettings> settings) {
+        base::BindLambdaForTesting([&](std::optional<QuotaSettings> settings) {
           quota_settings = std::move(settings);
           run_loop.Quit();
         }));
@@ -80,7 +80,7 @@
   }
 
   void GetAndTestSettings(const uint64_t physical_memory_amount) {
-    absl::optional<QuotaSettings> settings =
+    std::optional<QuotaSettings> settings =
         GetSettings(true, &device_info_helper_);
     ASSERT_TRUE(settings.has_value());
     const uint64_t pool_size =
@@ -102,7 +102,7 @@
   ON_CALL(device_info_helper, AmountOfTotalDiskSpace(_))
       .WillByDefault(::testing::Return(2000));
 
-  absl::optional<QuotaSettings> settings =
+  std::optional<QuotaSettings> settings =
       GetSettings(false, &device_info_helper);
   ASSERT_TRUE(settings.has_value());
   // 1600 = 2000 * default PoolSizeRatio (0.8)
@@ -124,7 +124,7 @@
   ON_CALL(device_info_helper, AmountOfTotalDiskSpace(_))
       .WillByDefault(::testing::Return(2000));
 
-  absl::optional<QuotaSettings> settings =
+  std::optional<QuotaSettings> settings =
       GetSettings(false, &device_info_helper);
   ASSERT_TRUE(settings.has_value());
 
@@ -146,7 +146,7 @@
   ON_CALL(device_info_helper, AmountOfTotalDiskSpace(_))
       .WillByDefault(::testing::Return(2000));
 
-  absl::optional<QuotaSettings> settings =
+  std::optional<QuotaSettings> settings =
       GetSettings(false, &device_info_helper);
   ASSERT_TRUE(settings.has_value());
 
@@ -165,7 +165,7 @@
   ON_CALL(device_info_helper, AmountOfTotalDiskSpace(_))
       .WillByDefault(::testing::Return(2000));
 
-  absl::optional<QuotaSettings> settings =
+  std::optional<QuotaSettings> settings =
       GetSettings(false, &device_info_helper);
   ASSERT_TRUE(settings.has_value());
 
diff --git a/storage/browser/quota/quota_temporary_storage_evictor.h b/storage/browser/quota/quota_temporary_storage_evictor.h
index 4e3d4e4..c700540 100644
--- a/storage/browser/quota/quota_temporary_storage_evictor.h
+++ b/storage/browser/quota/quota_temporary_storage_evictor.h
@@ -11,6 +11,7 @@
 #include <set>
 #include <string>
 
+#include <optional>
 #include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
@@ -18,7 +19,6 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "components/services/storage/public/cpp/buckets/bucket_locator.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
 
 namespace storage {
diff --git a/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc b/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc
index 8f4b15c7..43e059be 100644
--- a/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc
+++ b/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc
@@ -177,9 +177,9 @@
   }
 
   void TaskForRepeatedEvictionTest(
-      const std::pair<absl::optional<BucketLocator>, int64_t>&
+      const std::pair<std::optional<BucketLocator>, int64_t>&
           bucket_to_be_added,
-      const absl::optional<BucketLocator> bucket_to_be_accessed,
+      const std::optional<BucketLocator> bucket_to_be_accessed,
       int expected_usage_after_first,
       int expected_usage_after_second) {
     EXPECT_GE(4, num_get_usage_and_quota_for_eviction_);
@@ -370,7 +370,7 @@
           weak_factory_.GetWeakPtr(),
           std::make_pair(CreateBucket("http://www.e.com", /*is_default=*/false),
                          e_size),
-          absl::nullopt,
+          std::nullopt,
           // First round evicts d.
           initial_total_size - d_size,
           // Second round evicts c and b.
@@ -409,8 +409,8 @@
   quota_eviction_handler()->set_task_for_get_usage_and_quota(
       base::BindRepeating(
           &QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest,
-          weak_factory_.GetWeakPtr(), std::make_pair(absl::nullopt, 0),
-          absl::nullopt, initial_total_size - d_size,
+          weak_factory_.GetWeakPtr(), std::make_pair(std::nullopt, 0),
+          std::nullopt, initial_total_size - d_size,
           initial_total_size - d_size));
   EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage());
   temporary_storage_evictor()->Start();
@@ -453,7 +453,7 @@
           weak_factory_.GetWeakPtr(),
           std::make_pair(CreateBucket("http://www.e.com", /*is_default=*/false),
                          e_size),
-          absl::nullopt, initial_total_size - d_size,
+          std::nullopt, initial_total_size - d_size,
           initial_total_size - d_size + e_size - c_size));
   EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage());
   temporary_storage_evictor()->Start();
@@ -494,8 +494,8 @@
   quota_eviction_handler()->set_task_for_get_usage_and_quota(
       base::BindRepeating(
           &QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest,
-          weak_factory_.GetWeakPtr(), std::make_pair(absl::nullopt, 0),
-          absl::nullopt, initial_total_size - d_size,
+          weak_factory_.GetWeakPtr(), std::make_pair(std::nullopt, 0),
+          std::nullopt, initial_total_size - d_size,
           initial_total_size - d_size));
   EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage());
   // disable_timer_for_testing();
diff --git a/storage/browser/quota/usage_tracker.cc b/storage/browser/quota/usage_tracker.cc
index b8e4dd06..5f02aab7 100644
--- a/storage/browser/quota/usage_tracker.cc
+++ b/storage/browser/quota/usage_tracker.cc
@@ -107,7 +107,7 @@
 
 void UsageTracker::UpdateBucketUsageCache(QuotaClientType client_type,
                                           const BucketLocator& bucket,
-                                          absl::optional<int64_t> delta) {
+                                          std::optional<int64_t> delta) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   GetClient(client_type).UpdateBucketUsageCache(bucket, delta);
diff --git a/storage/browser/quota/usage_tracker.h b/storage/browser/quota/usage_tracker.h
index 96e2619..57697800 100644
--- a/storage/browser/quota/usage_tracker.h
+++ b/storage/browser/quota/usage_tracker.h
@@ -78,7 +78,7 @@
   // Updates usage for `bucket` in the ClientUsageTracker for `client_type`.
   void UpdateBucketUsageCache(QuotaClientType client_type,
                               const BucketLocator& bucket,
-                              absl::optional<int64_t> delta);
+                              std::optional<int64_t> delta);
 
   // Deletes `bucket` from the cache for `client_type` if it exists.
   // Called by QuotaManagerImpl::BucketDataDeleter.
diff --git a/storage/browser/test/mock_bytes_provider.cc b/storage/browser/test/mock_bytes_provider.cc
index 8441556..f2c2c7d 100644
--- a/storage/browser/test/mock_bytes_provider.cc
+++ b/storage/browser/test/mock_bytes_provider.cc
@@ -15,7 +15,7 @@
     size_t* reply_request_count,
     size_t* stream_request_count,
     size_t* file_request_count,
-    absl::optional<base::Time> file_modification_time)
+    std::optional<base::Time> file_modification_time)
     : data_(std::move(data)),
       reply_request_count_(reply_request_count),
       stream_request_count_(stream_request_count),
diff --git a/storage/browser/test/mock_bytes_provider.h b/storage/browser/test/mock_bytes_provider.h
index 98d30db..ae27962 100644
--- a/storage/browser/test/mock_bytes_provider.h
+++ b/storage/browser/test/mock_bytes_provider.h
@@ -22,7 +22,7 @@
       size_t* reply_request_count = nullptr,
       size_t* stream_request_count = nullptr,
       size_t* file_request_count = nullptr,
-      absl::optional<base::Time> file_modification_time = base::Time());
+      std::optional<base::Time> file_modification_time = base::Time());
   ~MockBytesProvider() override;
 
   // BytesProvider implementation:
@@ -39,7 +39,7 @@
   raw_ptr<size_t> reply_request_count_;
   raw_ptr<size_t> stream_request_count_;
   raw_ptr<size_t> file_request_count_;
-  absl::optional<base::Time> file_modification_time_;
+  std::optional<base::Time> file_modification_time_;
 };
 
 }  // namespace storage
diff --git a/storage/browser/test/mock_quota_manager.cc b/storage/browser/test/mock_quota_manager.cc
index c6718ca..ae95b90 100644
--- a/storage/browser/test/mock_quota_manager.cc
+++ b/storage/browser/test/mock_quota_manager.cc
@@ -391,7 +391,7 @@
 }
 
 void MockQuotaManager::UpdateUsage(const BucketLocator& bucket,
-                                   absl::optional<int64_t> delta) {
+                                   std::optional<int64_t> delta) {
   if (delta) {
     usage_map_[bucket].usage += *delta;
   } else {
diff --git a/storage/browser/test/mock_quota_manager.h b/storage/browser/test/mock_quota_manager.h
index 87be449..fcf8608e 100644
--- a/storage/browser/test/mock_quota_manager.h
+++ b/storage/browser/test/mock_quota_manager.h
@@ -228,7 +228,7 @@
       blink::mojom::StorageType type);
 
   // This must be called via MockQuotaManagerProxy.
-  void UpdateUsage(const BucketLocator& bucket, absl::optional<int64_t> delta);
+  void UpdateUsage(const BucketLocator& bucket, std::optional<int64_t> delta);
 
   void DidGetBucket(base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback,
                     QuotaErrorOr<BucketInfo> result);
diff --git a/storage/browser/test/mock_quota_manager_proxy.cc b/storage/browser/test/mock_quota_manager_proxy.cc
index dd6bffd..2295ebd8 100644
--- a/storage/browser/test/mock_quota_manager_proxy.cc
+++ b/storage/browser/test/mock_quota_manager_proxy.cc
@@ -109,7 +109,7 @@
 void MockQuotaManagerProxy::NotifyBucketModified(
     QuotaClientType client_id,
     const BucketLocator& bucket,
-    absl::optional<int64_t> delta,
+    std::optional<int64_t> delta,
     base::Time modification_time,
     scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
     base::OnceClosure callback) {
diff --git a/storage/browser/test/mock_quota_manager_proxy.h b/storage/browser/test/mock_quota_manager_proxy.h
index b0728fd..7dcf57f 100644
--- a/storage/browser/test/mock_quota_manager_proxy.h
+++ b/storage/browser/test/mock_quota_manager_proxy.h
@@ -95,7 +95,7 @@
   void NotifyBucketModified(
       QuotaClientType client_id,
       const BucketLocator& bucket,
-      absl::optional<int64_t> delta,
+      std::optional<int64_t> delta,
       base::Time modification_time,
       scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
       base::OnceClosure callback) override;
@@ -117,7 +117,7 @@
   int notify_bucket_accessed_count() const { return bucket_accessed_count_; }
   int notify_bucket_modified_count() const { return bucket_modified_count_; }
   BucketId last_notified_bucket_id() const { return last_notified_bucket_id_; }
-  absl::optional<int64_t> last_notified_bucket_delta() const {
+  std::optional<int64_t> last_notified_bucket_delta() const {
     return last_notified_bucket_delta_;
   }
 
@@ -135,7 +135,7 @@
   int bucket_accessed_count_ = 0;
   int bucket_modified_count_ = 0;
   BucketId last_notified_bucket_id_ = BucketId::FromUnsafeValue(-1);
-  absl::optional<int64_t> last_notified_bucket_delta_;
+  std::optional<int64_t> last_notified_bucket_delta_;
 };
 
 }  // namespace storage
diff --git a/storage/browser/test/sandbox_file_system_test_helper.h b/storage/browser/test/sandbox_file_system_test_helper.h
index e12b66b..9ec8d3b 100644
--- a/storage/browser/test/sandbox_file_system_test_helper.h
+++ b/storage/browser/test/sandbox_file_system_test_helper.h
@@ -109,7 +109,7 @@
   void SetUpFileSystem();
 
   scoped_refptr<FileSystemContext> file_system_context_;
-  absl::optional<BucketLocator> bucket_locator_;
+  std::optional<BucketLocator> bucket_locator_;
 
   blink::StorageKey storage_key_;
   const FileSystemType type_;
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index edc38375..877a121 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1722,7 +1722,7 @@
       {
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "brya",
-        "cros_img": "brya-release/R120-15662.4.0",
+        "cros_img": "brya-release/R120-15662.9.0",
         "dut_pool": "chrome",
         "experiment_percentage": 100,
         "name": "lacros_all_tast_tests BRYA_RELEASE_DEV",
@@ -1796,7 +1796,7 @@
       {
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "dedede",
-        "cros_img": "dedede-release/R120-15656.0.0",
+        "cros_img": "dedede-release/R120-15662.9.0",
         "experiment_percentage": 100,
         "name": "lacros_all_tast_tests DEDEDE_RELEASE_DEV",
         "resultdb": {
@@ -1868,7 +1868,7 @@
       {
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "fizz",
-        "cros_img": "fizz-release/R120-15662.4.0",
+        "cros_img": "fizz-release/R120-15662.9.0",
         "dut_pool": "chrome",
         "experiment_percentage": 100,
         "name": "lacros_all_tast_tests FIZZ_RELEASE_DEV",
@@ -1943,7 +1943,7 @@
       {
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "guybrush",
-        "cros_img": "guybrush-release/R120-15662.4.0",
+        "cros_img": "guybrush-release/R120-15662.9.0",
         "dut_pool": "chrome",
         "experiment_percentage": 100,
         "name": "lacros_all_tast_tests GUYBRUSH_RELEASE_DEV",
@@ -2018,7 +2018,7 @@
       {
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "puff",
-        "cros_img": "puff-release/R120-15662.4.0",
+        "cros_img": "puff-release/R120-15662.9.0",
         "dut_pool": "chrome",
         "experiment_percentage": 100,
         "name": "lacros_all_tast_tests PUFF_RELEASE_DEV",
@@ -2124,7 +2124,7 @@
       {
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R120-15662.4.0",
+        "cros_img": "jacuzzi-release/R120-15662.9.0",
         "experiment_percentage": 100,
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_DEV",
         "resultdb": {
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index f8b9889..8948663a 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1296,7 +1296,7 @@
       {
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R120-15662.4.0",
+        "cros_img": "octopus-release/R120-15662.9.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_DEV",
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
         "test": "lacros_fyi_tast_tests",
@@ -1339,7 +1339,7 @@
       {
         "autotest_name": "chromium",
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R120-15662.4.0",
+        "cros_img": "octopus-release/R120-15662.9.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_DEV",
         "test": "ozone_unittests",
         "test_id_prefix": "ninja://ui/ozone:ozone_unittests/",
@@ -1387,7 +1387,7 @@
       {
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "hana",
-        "cros_img": "hana-release/R120-15662.4.0",
+        "cros_img": "hana-release/R120-15662.9.0",
         "name": "lacros_all_tast_tests HANA_RELEASE_DEV",
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
         "test": "lacros_all_tast_tests",
@@ -1453,7 +1453,7 @@
       {
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R120-15662.4.0",
+        "cros_img": "strongbad-release/R120-15662.9.0",
         "name": "lacros_all_tast_tests strongbad_RELEASE_DEV",
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
         "test": "lacros_all_tast_tests",
@@ -1474,7 +1474,7 @@
       {
         "autotest_name": "chromium",
         "cros_board": "hana",
-        "cros_img": "hana-release/R120-15662.4.0",
+        "cros_img": "hana-release/R120-15662.9.0",
         "name": "ozone_unittests HANA_RELEASE_DEV",
         "test": "ozone_unittests",
         "test_id_prefix": "ninja://ui/ozone:ozone_unittests/",
@@ -1534,7 +1534,7 @@
       {
         "autotest_name": "chromium",
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R120-15662.4.0",
+        "cros_img": "strongbad-release/R120-15662.9.0",
         "name": "ozone_unittests strongbad_RELEASE_DEV",
         "test": "ozone_unittests",
         "test_id_prefix": "ninja://ui/ozone:ozone_unittests/",
@@ -1554,7 +1554,7 @@
       {
         "autotest_name": "chromium",
         "cros_board": "hana",
-        "cros_img": "hana-release/R120-15662.4.0",
+        "cros_img": "hana-release/R120-15662.9.0",
         "name": "viz_unittests HANA_RELEASE_DEV",
         "test": "viz_unittests",
         "test_id_prefix": "ninja://components/viz:viz_unittests/",
@@ -1614,7 +1614,7 @@
       {
         "autotest_name": "chromium",
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R120-15662.4.0",
+        "cros_img": "strongbad-release/R120-15662.9.0",
         "name": "viz_unittests strongbad_RELEASE_DEV",
         "test": "viz_unittests",
         "test_id_prefix": "ninja://components/viz:viz_unittests/",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 7021c96..82b9733 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -472,7 +472,7 @@
     'identifier': 'BRYA_RELEASE_DEV',
     'skylab': {
       'cros_board': 'brya',
-      'cros_img': 'brya-release/R120-15662.4.0',
+      'cros_img': 'brya-release/R120-15662.9.0',
       'dut_pool': 'chrome',
     },
   },
@@ -503,7 +503,7 @@
     'identifier': 'DEDEDE_RELEASE_DEV',
     'skylab': {
       'cros_board': 'dedede',
-      'cros_img': 'dedede-release/R120-15656.0.0',
+      'cros_img': 'dedede-release/R120-15662.9.0',
     },
   },
   'CROS_DEDEDE_RELEASE_BETA': {
@@ -532,7 +532,7 @@
     'identifier': 'FIZZ_RELEASE_DEV',
     'skylab': {
       'cros_board': 'fizz',
-      'cros_img': 'fizz-release/R120-15662.4.0',
+      'cros_img': 'fizz-release/R120-15662.9.0',
       'dut_pool': 'chrome',
     },
   },
@@ -564,7 +564,7 @@
     'identifier': 'GUYBRUSH_RELEASE_DEV',
     'skylab': {
       'cros_board': 'guybrush',
-      'cros_img': 'guybrush-release/R120-15662.4.0',
+      'cros_img': 'guybrush-release/R120-15662.9.0',
       'dut_pool': 'chrome',
     },
   },
@@ -596,7 +596,7 @@
     'identifier': 'PUFF_RELEASE_DEV',
     'skylab': {
       'cros_board': 'puff',
-      'cros_img': 'puff-release/R120-15662.4.0',
+      'cros_img': 'puff-release/R120-15662.9.0',
       'dut_pool': 'chrome',
     },
   },
@@ -638,7 +638,7 @@
     'identifier': 'HANA_RELEASE_DEV',
     'skylab': {
       'cros_board': 'hana',
-      'cros_img': 'hana-release/R120-15662.4.0',
+      'cros_img': 'hana-release/R120-15662.9.0',
     },
   },
   'CROS_HANA_RELEASE_BETA': {
@@ -666,7 +666,7 @@
     'identifier': 'JACUZZI_RELEASE_DEV',
     'skylab': {
       'cros_board': 'jacuzzi',
-      'cros_img': 'jacuzzi-release/R120-15662.4.0',
+      'cros_img': 'jacuzzi-release/R120-15662.9.0',
     },
   },
   'CROS_JACUZZI_RELEASE_BETA': {
@@ -742,7 +742,7 @@
     'identifier': 'OCTOPUS_RELEASE_DEV',
     'skylab': {
       'cros_board': 'octopus',
-      'cros_img': 'octopus-release/R120-15662.4.0',
+      'cros_img': 'octopus-release/R120-15662.9.0',
     },
   },
   'CROS_OCTOPUS_RELEASE_BETA': {
@@ -770,7 +770,7 @@
     'identifier': 'strongbad_RELEASE_DEV',
     'skylab': {
       'cros_board': 'strongbad',
-      'cros_img': 'strongbad-release/R120-15662.4.0',
+      'cros_img': 'strongbad-release/R120-15662.9.0',
     },
   },
   'CROS_STRONGBAD_RELEASE_BETA': {
diff --git a/testing/perf/luci_test_result.h b/testing/perf/luci_test_result.h
index 9e0496c..172c4df9 100644
--- a/testing/perf/luci_test_result.h
+++ b/testing/perf/luci_test_result.h
@@ -8,10 +8,10 @@
 #include <string>
 #include <vector>
 
+#include <optional>
 #include "base/containers/flat_map.h"
 #include "base/files/file_path.h"
 #include "base/time/time.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace perf_test {
 
@@ -47,9 +47,9 @@
 
     // Use only one of the two fields below.
     // Absolute path on the same machine running the test.
-    absl::optional<base::FilePath> file_path;
+    std::optional<base::FilePath> file_path;
     // The data of the artifact.
-    absl::optional<std::string> contents;
+    std::optional<std::string> contents;
 
     std::string content_type;
   };
diff --git a/testing/perf/luci_test_result_unittest.cc b/testing/perf/luci_test_result_unittest.cc
index cff07b9..f0068182 100644
--- a/testing/perf/luci_test_result_unittest.cc
+++ b/testing/perf/luci_test_result_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "testing/perf/luci_test_result.h"
 
+#include <optional>
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
@@ -11,7 +12,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace perf_test {
 
@@ -43,10 +43,10 @@
 
     std::string json;
     ASSERT_TRUE(ReadFileToString(GetResultFilePath(), &json));
-    absl::optional<base::Value> value = base::JSONReader::Read(json);
+    std::optional<base::Value> value = base::JSONReader::Read(json);
     ASSERT_TRUE(value.has_value());
 
-    absl::optional<base::Value> expected_value =
+    std::optional<base::Value> expected_value =
         base::JSONReader::Read(expected_json);
     ASSERT_TRUE(expected_value.has_value());
 
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index c1c8183de..e06849c3 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -592,6 +592,8 @@
          "first_paint_or_finished_parsing"},
         {DelayAsyncScriptDelayType::kEachLcpCandidate, "each_lcp_candidate"},
         {DelayAsyncScriptDelayType::kEachPaint, "each_paint"},
+        {DelayAsyncScriptDelayType::kTillFirstLcpCandidate,
+         "till_first_lcp_candidate"},
 };
 
 const base::FeatureParam<DelayAsyncScriptDelayType>
@@ -633,9 +635,16 @@
 const base::FeatureParam<std::string> kDelayAsyncScriptAllowList{
     &kDelayAsyncScriptExecution, "delay_async_exec_allow_list", ""};
 
+const base::FeatureParam<bool> kDelayAsyncScriptExecutionDelayByDefaultParam{
+    &kDelayAsyncScriptExecution, "delay_async_exec_delay_by_default", true};
+
 const base::FeatureParam<bool> kDelayAsyncScriptExecutionMainFrameOnlyParam{
     &kDelayAsyncScriptExecution, "delay_async_exec_main_frame_only", false};
 
+const base::FeatureParam<bool> kDelayAsyncScriptExecutionWhenLcpFoundInHtml{
+    &kDelayAsyncScriptExecution, "delay_async_exec_when_lcp_found_in_html",
+    false};
+
 BASE_FEATURE(kDelayLowPriorityRequestsAccordingToNetworkState,
              "DelayLowPriorityRequestsAccordingToNetworkState",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 3030ca70..c61f1fb 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -285,6 +285,7 @@
   kFirstPaintOrFinishedParsing,
   kEachLcpCandidate,
   kEachPaint,
+  kTillFirstLcpCandidate,
 };
 BLINK_COMMON_EXPORT extern const base::FeatureParam<DelayAsyncScriptDelayType>
     kDelayAsyncScriptExecutionDelayParam;
@@ -307,6 +308,10 @@
     kDelayAsyncScriptAllowList;
 BLINK_COMMON_EXPORT extern const base::FeatureParam<bool>
     kDelayAsyncScriptExecutionMainFrameOnlyParam;
+BLINK_COMMON_EXPORT extern const base::FeatureParam<bool>
+    kDelayAsyncScriptExecutionWhenLcpFoundInHtml;
+BLINK_COMMON_EXPORT extern const base::FeatureParam<bool>
+    kDelayAsyncScriptExecutionDelayByDefaultParam;
 
 // If enabled, the ResourceLoadScheculer will take the current network state
 // into consideration, when it plans to delay a low-priority throttleable
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
index 76fb2aa5..0e430e28 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
@@ -94,17 +94,6 @@
     TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
                          "v8.wasm.compiledModule", TRACE_EVENT_SCOPE_THREAD,
                          "url", response_url_.Utf8());
-    v8::MemorySpan<const uint8_t> wire_bytes =
-        compiled_module.GetWireBytesRef();
-    // Our heuristic for whether it's worthwhile to cache is that the module
-    // was fully compiled and the size is such that loading from the cache will
-    // improve startup time. Use wire bytes size since it should be correlated
-    // with module size.
-    // TODO(bbudge) This is set very low to compare performance of caching with
-    // baseline compilation. Adjust this test once we know which sizes benefit.
-    const size_t kWireBytesSizeThresholdBytes = 1UL << 10;  // 1 KB.
-    if (wire_bytes.size() < kWireBytesSizeThresholdBytes)
-      return;
     v8::OwnedBuffer serialized_module;
     {
       // Use a standard milliseconds based timer (up to 10 seconds, 50 buckets),
@@ -120,6 +109,8 @@
                          "v8.wasm.cachedModule", TRACE_EVENT_SCOPE_THREAD,
                          "producedCacheSize", serialized_module.size);
 
+    v8::MemorySpan<const uint8_t> wire_bytes =
+        compiled_module.GetWireBytesRef();
     DigestValue wire_bytes_digest;
     {
       TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
diff --git a/third_party/blink/renderer/core/css/css_image_value.cc b/third_party/blink/renderer/core/css/css_image_value.cc
index 926c2e93..04fa2c2 100644
--- a/third_party/blink/renderer/core/css/css_image_value.cc
+++ b/third_party/blink/renderer/core/css/css_image_value.cc
@@ -30,6 +30,7 @@
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
 #include "third_party/blink/renderer/core/style/style_fetched_image.h"
+#include "third_party/blink/renderer/core/svg/svg_resource.h"
 #include "third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
@@ -124,6 +125,14 @@
                               : initiator_name_);
 }
 
+SVGResource* CSSImageValue::EnsureSVGResource() const {
+  if (!svg_resource_) {
+    svg_resource_ = MakeGarbageCollected<ExternalSVGResourceImageContent>(
+        cached_image_->CachedImage(), NormalizedFragmentIdentifier());
+  }
+  return svg_resource_.Get();
+}
+
 bool CSSImageValue::HasFailedOrCanceledSubresources() const {
   if (!cached_image_) {
     return false;
@@ -144,6 +153,7 @@
 
 void CSSImageValue::TraceAfterDispatch(blink::Visitor* visitor) const {
   visitor->Trace(cached_image_);
+  visitor->Trace(svg_resource_);
   CSSValue::TraceAfterDispatch(visitor);
 }
 
@@ -169,6 +179,7 @@
 void CSSImageValue::ReResolveURL(const Document& document) const {
   if (url_data_.ReResolveUrl(document)) {
     cached_image_.Clear();
+    svg_resource_.Clear();
   }
 }
 
diff --git a/third_party/blink/renderer/core/css/css_image_value.h b/third_party/blink/renderer/core/css/css_image_value.h
index ace0c6a..c9d85b6a 100644
--- a/third_party/blink/renderer/core/css/css_image_value.h
+++ b/third_party/blink/renderer/core/css/css_image_value.h
@@ -33,6 +33,7 @@
 
 class Document;
 class StyleImage;
+class SVGResource;
 
 class CORE_EXPORT CSSImageValue : public CSSValue {
  public:
@@ -81,6 +82,7 @@
 
   void TraceAfterDispatch(blink::Visitor*) const;
   void RestoreCachedResourceIfNeeded(const Document&) const;
+  SVGResource* EnsureSVGResource() const;
 
  private:
   CSSUrlData url_data_;
@@ -88,6 +90,7 @@
 
   // Cached image data.
   mutable Member<StyleImage> cached_image_;
+  mutable Member<SVGResource> svg_resource_;
 };
 
 template <>
diff --git a/third_party/blink/renderer/core/css/resolver/element_style_resources.cc b/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
index 8983406..259528f 100644
--- a/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
+++ b/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
@@ -48,9 +48,8 @@
 #include "third_party/blink/renderer/core/style/style_generated_image.h"
 #include "third_party/blink/renderer/core/style/style_image.h"
 #include "third_party/blink/renderer/core/style/style_image_set.h"
+#include "third_party/blink/renderer/core/style/style_mask_source_image.h"
 #include "third_party/blink/renderer/core/style/style_pending_image.h"
-#include "third_party/blink/renderer/core/style/style_svg_mask_reference_image.h"
-#include "third_party/blink/renderer/core/svg/svg_resource.h"
 #include "third_party/blink/renderer/core/svg/svg_tree_scope_resources.h"
 #include "third_party/blink/renderer/platform/geometry/length.h"
 #include "third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h"
@@ -340,10 +339,14 @@
         element_.OriginatingTreeScope().EnsureSVGTreeScopedResources();
     SVGResource* resource = tree_scope_resources.ResourceForId(
         image_value->NormalizedFragmentIdentifier());
-    return MakeGarbageCollected<StyleSVGMaskReferenceImage>(resource,
-                                                            image_value);
+    return MakeGarbageCollected<StyleMaskSourceImage>(resource, image_value);
   }
-  return nullptr;
+  StyleImage* image = image_value->CacheImage(
+      element_.GetDocument(), FetchParameters::ImageRequestBehavior::kNone,
+      kCrossOriginAttributeAnonymous);
+  return MakeGarbageCollected<StyleMaskSourceImage>(
+      To<StyleFetchedImage>(image), image_value->EnsureSVGResource(),
+      image_value);
 }
 
 void ElementStyleResources::LoadPendingImages(ComputedStyleBuilder& builder) {
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index fe4be9d..12723b6 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -846,8 +846,10 @@
               : nullptr),
       data_(MakeGarbageCollected<DocumentData>(GetExecutionContext())) {
   DCHECK(agent_);
-  if (base::FeatureList::IsEnabled(features::kDelayAsyncScriptExecution))
+  if (base::FeatureList::IsEnabled(features::kDelayAsyncScriptExecution) &&
+      features::kDelayAsyncScriptExecutionDelayByDefaultParam.Get()) {
     script_runner_delayer_->Activate();
+  }
 
   if (GetFrame()) {
     DCHECK(GetFrame()->GetPage());
@@ -7406,6 +7408,14 @@
         script_runner_delayer_->Activate();
       }
       break;
+    case features::DelayAsyncScriptDelayType::kTillFirstLcpCandidate:
+      // Notify the ScriptRunner if a LCP candidate is reported.
+      if (milestone == MilestoneForDelayedAsyncScript::kLcpCandidate) {
+        // Flush all async scripts that are already prepared but forced to be
+        // delayed.
+        script_runner_delayer_->Deactivate();
+      }
+      break;
   }
 }
 
@@ -8750,6 +8760,14 @@
   return element_computed_style_map_.Take(element);
 }
 
+void Document::DelayAsyncScriptExecution() {
+  script_runner_delayer_->Activate();
+}
+
+void Document::ResumeAsyncScriptExecution() {
+  script_runner_delayer_->Deactivate();
+}
+
 void Document::Trace(Visitor* visitor) const {
   visitor->Trace(doc_type_);
   visitor->Trace(implementation_);
@@ -9272,6 +9290,14 @@
   return nullptr;
 }
 
+void Document::SetLcpElementFoundInHtml(bool found) {
+  data_->lcpp_encountered_lcp_in_html = found;
+}
+
+bool Document::IsLcpElementFoundInHtml() {
+  return data_->lcpp_encountered_lcp_in_html;
+}
+
 // static
 Document* Document::parseHTMLUnsafe(ExecutionContext* context,
                                     const String& html) {
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index fd9df47..8c5fa2c6 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -1994,10 +1994,20 @@
   static Document* parseHTMLUnsafe(ExecutionContext* context,
                                    const String& html);
 
+  // Delays execution of pending async scripts until a milestone is reached.
+  // Used in conjunction with kDelayAsyncScriptExecution experiment.
+  void DelayAsyncScriptExecution();
+  void ResumeAsyncScriptExecution();
+
   // This method should only be called when the document is top-level and it is
   // rendering static media like video or images.
   void SetOverrideSiteForCookiesForCSPMedia(bool value);
 
+  // Flags to determine if LCPP ElementLocator matched during
+  // HTML preload scanning.
+  void SetLcpElementFoundInHtml(bool found);
+  bool IsLcpElementFoundInHtml();
+
  protected:
   void ClearXMLVersion() { xml_version_ = String(); }
 
diff --git a/third_party/blink/renderer/core/dom/document_data.h b/third_party/blink/renderer/core/dom/document_data.h
index 168d94c..14fb914 100644
--- a/third_party/blink/renderer/core/dom/document_data.h
+++ b/third_party/blink/renderer/core/dom/document_data.h
@@ -73,6 +73,10 @@
   // This count doesn't include this document's frame nor descendant frames.
   int immediate_child_frame_creation_count_ = 0;
 
+  // LCPP's LCP ElementLocator was matched against a tag against html
+  // during preload scanning.
+  bool lcpp_encountered_lcp_in_html = false;
+
   friend class Document;
 };
 
diff --git a/third_party/blink/renderer/core/exported/web_element.cc b/third_party/blink/renderer/core/exported/web_element.cc
index 214c3196..959c6f9 100644
--- a/third_party/blink/renderer/core/exported/web_element.cc
+++ b/third_party/blink/renderer/core/exported/web_element.cc
@@ -41,6 +41,7 @@
 #include "third_party/blink/renderer/core/dom/focus_params.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/frame_selection.h"
+#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
 #include "third_party/blink/renderer/core/editing/selection_template.h"
 #include "third_party/blink/renderer/core/editing/visible_selection.h"
 #include "third_party/blink/renderer/core/events/clipboard_event.h"
@@ -195,29 +196,31 @@
   // of ClipboardCommands::Paste() that's limited to pasting plain text.
   Element* target = FindEventTargetFrom(
       *frame, frame->Selection().ComputeVisibleSelectionInDOMTree());
-  auto create_data_transfer = [&text]() {
+  auto create_data_transfer = [](const WebString& text) {
     return DataTransfer::Create(DataTransfer::kCopyAndPaste,
                                 DataTransferAccessPolicy::kReadable,
                                 DataObject::CreateFromString(text));
   };
   // Fires "paste" event.
-  target->DispatchEvent(*ClipboardEvent::Create(event_type_names::kPaste,
-                                                create_data_transfer()));
+  if (target->DispatchEvent(*ClipboardEvent::Create(
+          event_type_names::kPaste, create_data_transfer(text))) !=
+      DispatchEventResult::kNotCanceled) {
+    return;
+  }
   // Fires "beforeinput" event.
   if (DispatchBeforeInputDataTransfer(
           target, InputEvent::InputType::kInsertFromPaste,
-          create_data_transfer()) == DispatchEventResult::kNotCanceled) {
-    // Fires "textInput" and "input" events.
-    target->DispatchEvent(
-        *TextEvent::CreateForPlainTextPaste(frame->DomWindow(), text,
-                                            /*should_smart_replace=*/true));
-  }
-
-  if (is_destroyed(*frame)) {
+          create_data_transfer(text)) != DispatchEventResult::kNotCanceled) {
     return;
   }
-  // Revealing the selection currently doesn't work on contenteditables.
-  frame->Selection().RevealSelection();
+  // No DOM mutation if EditContext is active.
+  if (frame->GetInputMethodController().GetActiveEditContext()) {
+    return;
+  }
+  // Fires "textInput" and "input".
+  target->DispatchEvent(
+      *TextEvent::CreateForPlainTextPaste(frame->DomWindow(), text,
+                                          /*should_smart_replace=*/true));
 }
 
 WebVector<WebLabelElement> WebElement::Labels() const {
diff --git a/third_party/blink/renderer/core/exported/web_element_test.cc b/third_party/blink/renderer/core/exported/web_element_test.cc
index ceb9d79..11d5074 100644
--- a/third_party/blink/renderer/core/exported/web_element_test.cc
+++ b/third_party/blink/renderer/core/exported/web_element_test.cc
@@ -26,6 +26,7 @@
 class WebElementTest : public PageTestBase {
  protected:
   void InsertHTML(String html);
+  void AddScript(String script);
   WebElement TestElement();
 };
 
@@ -33,6 +34,14 @@
   GetDocument().documentElement()->setInnerHTML(html);
 }
 
+void WebElementTest::AddScript(String js) {
+  GetDocument().GetSettings()->SetScriptEnabled(true);
+  Element* script = GetDocument().CreateRawElement(html_names::kScriptTag);
+  script->setInnerHTML(js);
+  GetDocument().body()->AppendChild(script);
+  GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
+}
+
 WebElement WebElementTest::TestElement() {
   Element* element = GetDocument().getElementById(AtomicString("testElement"));
   DCHECK(element);
@@ -106,7 +115,7 @@
   GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
   Selection().SelectSubString(*element->firstElementChild(), 0, 9);
   ASSERT_EQ(Selection().SelectedText(), String("rich text"));
-  // Paste and append.
+  // Paste and replace selection.
   TestElement().PasteText("fancy text", /*replace_all=*/false);
   EXPECT_EQ(element->innerHTML(), "Some <b>fancy text</b>&nbsp;here.");
   // Paste and replace all.
@@ -132,7 +141,7 @@
                 element->selectionStart(),
                 element->selectionEnd() - element->selectionStart()),
             String("plain text"));
-  // Paste and append.
+  // Paste and replace selection.
   TestElement().PasteText("boring text", /*replace_all=*/false);
   EXPECT_EQ(element->Value(), "Some boring text here.");
   // Paste and replace all.
@@ -144,6 +153,45 @@
   EXPECT_EQ(element->Value(), "Hello world");
 }
 
+// Tests that PasteText() aborts when the JavaScript handler of the 'paste'
+// event prevents the default handling.
+TEST_F(WebElementTest, PasteTextIsNoOpWhenPasteIsCancelled) {
+  InsertHTML(
+      "<div id=testElement contenteditable>Some <b>rich text</b> here.</div>");
+  AddScript(R"(
+      document.getElementById('testElement').addEventListener('paste', e => {
+        e.target.textContent = 'UPPERCASE TEXT';
+        e.preventDefault();
+      }))");
+  auto* element = GetDocument().getElementById(AtomicString("testElement"));
+  GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
+  Selection().SelectSubString(*element->firstElementChild(), 0, 9);
+  ASSERT_EQ(Selection().SelectedText(), String("rich text"));
+  // Paste and replace selection.
+  TestElement().PasteText("fancy text", /*replace_all=*/false);
+  EXPECT_EQ(element->innerHTML(), "Some <b>UPPERCASE TEXT</b> here.");
+}
+
+// Tests that PasteText() aborts when the JavaScript handler of the
+// 'beforeinput' event prevents the default handling.
+TEST_F(WebElementTest, PasteTextIsNoOpWhenBeforeInputIsCancelled) {
+  InsertHTML(
+      "<div id=testElement contenteditable>Some <b>rich text</b> here.</div>");
+  AddScript(R"(
+      document.getElementById('testElement').addEventListener('beforeinput',
+                                                              e => {
+        e.target.textContent = 'UPPERCASE TEXT';
+        e.preventDefault();
+      }))");
+  auto* element = GetDocument().getElementById(AtomicString("testElement"));
+  GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
+  Selection().SelectSubString(*element->firstElementChild(), 0, 9);
+  ASSERT_EQ(Selection().SelectedText(), String("rich text"));
+  // Paste and replace selection.
+  TestElement().PasteText("fancy text", /*replace_all=*/false);
+  EXPECT_EQ(element->innerHTML(), "Some <b>UPPERCASE TEXT</b> here.");
+}
+
 TEST_F(WebElementTest, ShadowRoot) {
   InsertHTML("<input id=testElement>");
   EXPECT_TRUE(TestElement().ShadowRoot().IsNull())
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
index 03e1d47..ba976d37 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser.cc
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -491,6 +491,16 @@
     PumpTokenizerIfPossible();
   }
 
+  if (base::FeatureList::IsEnabled(features::kDelayAsyncScriptExecution) &&
+      features::kDelayAsyncScriptExecutionWhenLcpFoundInHtml.Get()) {
+    // If kDelayAsyncScriptExecutionWhenLcpFoundInHtml flag is turned on, and an
+    // LCP element wasn't found during Preload scan, there is no need to delay
+    // async scripts further.
+    if (!GetDocument()->IsLcpElementFoundInHtml()) {
+      GetDocument()->ResumeAsyncScriptExecution();
+    }
+  }
+
   if (IsStopped())
     return;
 
@@ -1394,6 +1404,19 @@
   for (auto& request : preload_data->requests) {
     queued_preloads_.push_back(std::move(request));
   }
+
+  if (base::FeatureList::IsEnabled(features::kDelayAsyncScriptExecution) &&
+      features::kDelayAsyncScriptExecutionWhenLcpFoundInHtml.Get()) {
+    // If kDelayAsyncScriptExecutionWhenLcpFoundInHtml flag is turned on,
+    // check if HTML has LCP element present.
+    //  If found, start/continue delaying async script execution on the document
+    //  until the configured  milestone.
+    if (preload_data->has_located_potential_lcp_element) {
+      GetDocument()->SetLcpElementFoundInHtml(true);
+      GetDocument()->DelayAsyncScriptExecution();
+    }
+  }
+
   FetchQueuedPreloads();
 }
 
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
index 9d09143..31c5cb1 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -826,6 +826,7 @@
       in_script_web_bundle_(false),
       seen_body_(false),
       seen_img_(false),
+      seen_potential_lcp_element_(false),
       template_count_(0),
       document_parameters_(std::move(document_parameters)),
       media_values_cached_data_(std::move(media_values_cached_data)),
@@ -958,6 +959,11 @@
       const StringImpl* tag_impl = TagImplFor(token.Data());
       const bool potentially_lcp_element =
           lcp_element_matcher_.ObserveStartTagAndReportMatch(tag_impl, token);
+
+      if (potentially_lcp_element) {
+        seen_potential_lcp_element_ = true;
+      }
+
       if (Match(tag_impl, html_names::kTemplateTag)) {
         bool is_declarative_shadow_root = false;
         const HTMLToken::Attribute* shadowrootmode_attribute =
@@ -1220,6 +1226,10 @@
       pending_data = std::make_unique<PendingPreloadData>();
     }
   }
+
+  pending_data->has_located_potential_lcp_element =
+      scanner_.HasLocatedPotentialLcpElement();
+
   return pending_data;
 }
 
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
index 2579d4f..dc3b195 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
@@ -74,6 +74,7 @@
   MetaCHValues meta_ch_values;
   absl::optional<ViewportDescription> viewport;
   bool has_csp_meta_tag = false;
+  bool has_located_potential_lcp_element = false;
   PreloadRequestStream requests;
 };
 
@@ -127,6 +128,8 @@
     predicted_base_element_url_ = url;
   }
 
+  bool HasLocatedPotentialLcpElement() { return seen_potential_lcp_element_; }
+
  private:
   class StartTagScanner;
 
@@ -169,6 +172,7 @@
   bool in_script_web_bundle_;
   bool seen_body_;
   bool seen_img_;
+  bool seen_potential_lcp_element_;
   PictureData picture_data_;
   size_t template_count_;
   std::unique_ptr<CachedDocumentParameters> document_parameters_;
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index 4708bb16..3e8e41c4 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -2185,7 +2185,7 @@
       if (layer->GetImage() && image == layer->GetImage()->Data()) {
         SetShouldDoFullPaintInvalidationWithoutLayoutChange(
             PaintInvalidationReason::kImage);
-        if (layer->GetImage()->IsSVGMaskReference() && IsSVGChild()) {
+        if (layer->GetImage()->IsMaskSource() && IsSVGChild()) {
           // Since an invalid <mask> reference does not yield a paint property
           // on SVG content (see CSSMaskPainter), we need to update paint
           // properties when such a reference changes.
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
index d9b295f..443e11e 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
@@ -135,7 +135,7 @@
     if (style_image && image == style_image->Data()) {
       SetShouldDoFullPaintInvalidationWithoutLayoutChange(
           PaintInvalidationReason::kImage);
-      if (style_image->IsSVGMaskReference()) {
+      if (style_image->IsMaskSource()) {
         // Since an invalid <mask> reference does not yield a paint property on
         // SVG content (see CSSMaskPainter), we need to update paint properties
         // when such a reference changes.
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc
index a473564b..f906fed 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc
@@ -21,7 +21,7 @@
 
 #include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
 #include "third_party/blink/renderer/core/style/reference_clip_path_operation.h"
-#include "third_party/blink/renderer/core/style/style_svg_mask_reference_image.h"
+#include "third_party/blink/renderer/core/style/style_mask_source_image.h"
 #include "third_party/blink/renderer/core/svg/svg_element.h"
 #include "third_party/blink/renderer/core/svg/svg_length.h"
 #include "third_party/blink/renderer/core/svg/svg_length_context.h"
@@ -242,14 +242,14 @@
   if (RuntimeEnabledFeatures::CSSMaskingInteropEnabled()) {
     for (const FillLayer* layer = &layout_object.StyleRef().MaskLayers(); layer;
          layer = layer->Next()) {
-      const auto* svg_mask_reference =
-          DynamicTo<StyleSVGMaskReferenceImage>(layer->GetImage());
-      if (!svg_mask_reference) {
+      const auto* mask_source =
+          DynamicTo<StyleMaskSourceImage>(layer->GetImage());
+      if (!mask_source) {
         continue;
       }
-      const SVGResource* svg_resource = svg_mask_reference->GetSVGResource();
+      const SVGResource* svg_resource = mask_source->GetSVGResource();
       SVGResourceClient* client =
-          svg_mask_reference->GetSVGResourceClient(layout_object);
+          mask_source->GetSVGResourceClient(layout_object);
       if (svg_resource && svg_resource->FindCycle(*client)) {
         return true;
       }
diff --git a/third_party/blink/renderer/core/layout/svg/svg_content_container.cc b/third_party/blink/renderer/core/layout/svg/svg_content_container.cc
index a72c5722..188d41a 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_content_container.cc
+++ b/third_party/blink/renderer/core/layout/svg/svg_content_container.cc
@@ -224,7 +224,8 @@
     if (!HasValidBoundingBoxForContainer(*child)) {
       continue;
     }
-    stroke_bbox.Union(child->StrokeBoundingBox());
+    const AffineTransform& transform = child->LocalToSVGParentTransform();
+    stroke_bbox.Union(transform.MapRect(child->StrokeBoundingBox()));
   }
   return stroke_bbox;
 }
diff --git a/third_party/blink/renderer/core/paint/box_painter_base.cc b/third_party/blink/renderer/core/paint/box_painter_base.cc
index fa6786c..d05437b 100644
--- a/third_party/blink/renderer/core/paint/box_painter_base.cc
+++ b/third_party/blink/renderer/core/paint/box_painter_base.cc
@@ -28,7 +28,7 @@
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/style/shadow_list.h"
 #include "third_party/blink/renderer/core/style/style_fetched_image.h"
-#include "third_party/blink/renderer/core/style/style_svg_mask_reference_image.h"
+#include "third_party/blink/renderer/core/style/style_mask_source_image.h"
 #include "third_party/blink/renderer/platform/geometry/layout_rect.h"
 #include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
@@ -1090,6 +1090,15 @@
   return layer.MaskMode() == EFillMaskMode::kLuminance;
 }
 
+const StyleMaskSourceImage* ToMaskSourceIfSVGMask(
+    const StyleImage& style_image) {
+  const auto* mask_source = DynamicTo<StyleMaskSourceImage>(style_image);
+  if (!mask_source || !mask_source->HasSVGMask()) {
+    return nullptr;
+  }
+  return mask_source;
+}
+
 class ScopedMaskLuminanceLayer {
   STACK_ALLOCATED();
 
@@ -1168,22 +1177,23 @@
     // If the "image" referenced by the FillLayer is an SVG <mask> reference
     // (and this is a layer for a mask), then repeat, position, clip, origin and
     // size should have no effect.
-    if (bg_layer.GetType() == EFillLayerType::kMask &&
-        fill_layer_info.image->IsSVGMaskReference()) {
-      const PhysicalRect positioning_area = geometry.ComputePositioningArea(
-          paint_info, bg_layer, scrolled_paint_rect);
-      const gfx::RectF reference_box(gfx::SizeF(positioning_area.size));
-      const float zoom = image_style.EffectiveZoom();
+    if (bg_layer.GetType() == EFillLayerType::kMask) {
+      if (const auto* mask_source =
+              ToMaskSourceIfSVGMask(*fill_layer_info.image)) {
+        const PhysicalRect positioning_area = geometry.ComputePositioningArea(
+            paint_info, bg_layer, scrolled_paint_rect);
+        const gfx::RectF reference_box(gfx::SizeF(positioning_area.size));
+        const float zoom = image_style.EffectiveZoom();
 
-      clip_with_scrolling_state_saver.SaveIfNeeded();
-      // Move the origin to the upper-left corner of the positioning area.
-      context.Translate(positioning_area.X().ToFloat(),
-                        positioning_area.Y().ToFloat());
-      SVGMaskPainter::PaintSVGMaskLayer(
-          context, To<StyleSVGMaskReferenceImage>(*fill_layer_info.image),
-          geometry.ImageClient(), reference_box, zoom, composite_op,
-          bg_layer.MaskMode() == EFillMaskMode::kMatchSource);
-      return;
+        clip_with_scrolling_state_saver.SaveIfNeeded();
+        // Move the origin to the upper-left corner of the positioning area.
+        context.Translate(positioning_area.X().ToFloat(),
+                          positioning_area.Y().ToFloat());
+        SVGMaskPainter::PaintSVGMaskLayer(
+            context, *mask_source, geometry.ImageClient(), reference_box, zoom,
+            composite_op, bg_layer.MaskMode() == EFillMaskMode::kMatchSource);
+        return;
+      }
     }
     geometry.Calculate(paint_info, bg_layer, scrolled_paint_rect);
 
diff --git a/third_party/blink/renderer/core/paint/css_mask_painter.cc b/third_party/blink/renderer/core/paint/css_mask_painter.cc
index c3cbe34..1e46208 100644
--- a/third_party/blink/renderer/core/paint/css_mask_painter.cc
+++ b/third_party/blink/renderer/core/paint/css_mask_painter.cc
@@ -11,7 +11,7 @@
 #include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/paint/svg_mask_painter.h"
-#include "third_party/blink/renderer/core/style/style_svg_mask_reference_image.h"
+#include "third_party/blink/renderer/core/style/style_mask_source_image.h"
 
 namespace blink {
 
@@ -22,14 +22,12 @@
   if (first_layer.Next()) {
     return false;
   }
-  const auto* svg_mask_reference =
-      DynamicTo<StyleSVGMaskReferenceImage>(first_layer.GetImage());
-  if (!svg_mask_reference) {
+  const auto* mask_source =
+      DynamicTo<StyleMaskSourceImage>(first_layer.GetImage());
+  if (!mask_source || !mask_source->HasSVGMask()) {
     return false;
   }
-  return !SVGMaskPainter::MaskIsValid(
-      svg_mask_reference->GetSVGResource(),
-      svg_mask_reference->GetSVGResourceClient(object));
+  return !SVGMaskPainter::MaskIsValid(*mask_source, object);
 }
 
 }  // namespace
diff --git a/third_party/blink/renderer/core/paint/svg_mask_painter.cc b/third_party/blink/renderer/core/paint/svg_mask_painter.cc
index 6e19eda..1d0a4232 100644
--- a/third_party/blink/renderer/core/paint/svg_mask_painter.cc
+++ b/third_party/blink/renderer/core/paint/svg_mask_painter.cc
@@ -12,7 +12,7 @@
 #include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
 #include "third_party/blink/renderer/core/paint/object_paint_properties.h"
 #include "third_party/blink/renderer/core/paint/paint_auto_dark_mode.h"
-#include "third_party/blink/renderer/core/style/style_svg_mask_reference_image.h"
+#include "third_party/blink/renderer/core/style/style_mask_source_image.h"
 #include "third_party/blink/renderer/core/svg/svg_length_functions.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
@@ -57,11 +57,18 @@
   if (DisplayLockUtilities::LockedAncestorPreventingLayout(*masker)) {
     return nullptr;
   }
-  SECURITY_DCHECK(!masker->SelfNeedsFullLayout());
+  SECURITY_CHECK(!masker->SelfNeedsFullLayout());
   masker->ClearInvalidationMask();
   return masker;
 }
 
+LayoutSVGResourceMasker* ResolveElementReference(
+    const StyleMaskSourceImage& mask_source,
+    const ImageResourceObserver& observer) {
+  return ResolveElementReference(mask_source.GetSVGResource(),
+                                 mask_source.GetSVGResourceClient(observer));
+}
+
 class SVGMaskGeometry {
   STACK_ALLOCATED();
 
@@ -418,6 +425,15 @@
   GraphicsContext& context_;
 };
 
+const StyleMaskSourceImage* ToMaskSourceIfSVGMask(
+    const StyleImage& style_image) {
+  const auto* mask_source = DynamicTo<StyleMaskSourceImage>(style_image);
+  if (!mask_source || !mask_source->HasSVGMask()) {
+    return nullptr;
+  }
+  return mask_source;
+}
+
 void PaintMaskLayer(const FillLayer& layer,
                     const FillInfo& info,
                     SVGMaskGeometry& geometry,
@@ -445,8 +461,7 @@
   // If the "image" referenced by the FillLayer is an SVG <mask> reference (and
   // this is a layer for a mask), then repeat, position, clip, origin and size
   // should have no effect.
-  if (const auto* svg_reference =
-          DynamicTo<StyleSVGMaskReferenceImage>(*style_image)) {
+  if (const auto* mask_source = ToMaskSourceIfSVGMask(*style_image)) {
     const ComputedStyle& style = info.object.StyleRef();
     const gfx::RectF reference_box = SVGResources::ReferenceBoxForEffects(
         info.object, GeometryBox::kFillBox,
@@ -456,7 +471,7 @@
 
     saver.Save();
     SVGMaskPainter::PaintSVGMaskLayer(
-        context, *svg_reference, info.object, reference_box, zoom, composite_op,
+        context, *mask_source, info.object, reference_box, zoom, composite_op,
         layer.MaskMode() == EFillMaskMode::kMatchSource);
     return;
   }
@@ -589,17 +604,15 @@
   context.Restore();
 }
 
-void SVGMaskPainter::PaintSVGMaskLayer(
-    GraphicsContext& context,
-    const StyleSVGMaskReferenceImage& svg_reference,
-    const ImageResourceObserver& observer,
-    const gfx::RectF& reference_box,
-    const float zoom,
-    const SkBlendMode composite_op,
-    const bool apply_mask_type) {
+void SVGMaskPainter::PaintSVGMaskLayer(GraphicsContext& context,
+                                       const StyleMaskSourceImage& mask_source,
+                                       const ImageResourceObserver& observer,
+                                       const gfx::RectF& reference_box,
+                                       const float zoom,
+                                       const SkBlendMode composite_op,
+                                       const bool apply_mask_type) {
   LayoutSVGResourceMasker* masker =
-      ResolveElementReference(svg_reference.GetSVGResource(),
-                              svg_reference.GetSVGResourceClient(observer));
+      ResolveElementReference(mask_source, observer);
   if (!masker) {
     return;
   }
@@ -608,9 +621,9 @@
                apply_mask_type);
 }
 
-bool SVGMaskPainter::MaskIsValid(SVGResource* mask_resource,
-                                 SVGResourceClient* client) {
-  return ResolveElementReference(mask_resource, client);
+bool SVGMaskPainter::MaskIsValid(const StyleMaskSourceImage& mask_source,
+                                 const ImageResourceObserver& observer) {
+  return ResolveElementReference(mask_source, observer);
 }
 
 gfx::RectF SVGMaskPainter::ResourceBoundsForSVGChild(
@@ -624,14 +637,13 @@
   gfx::RectF bounds;
   for (const FillLayer* layer = &style.MaskLayers(); layer;
        layer = layer->Next()) {
-    const auto* svg_mask_reference =
-        DynamicTo<StyleSVGMaskReferenceImage>(layer->GetImage());
-    if (!svg_mask_reference) {
+    const auto* mask_source =
+        DynamicTo<StyleMaskSourceImage>(layer->GetImage());
+    if (!mask_source) {
       continue;
     }
-    LayoutSVGResourceMasker* masker = ResolveElementReference(
-        svg_mask_reference->GetSVGResource(),
-        svg_mask_reference->GetSVGResourceClient(object));
+    LayoutSVGResourceMasker* masker =
+        ResolveElementReference(*mask_source, object);
     if (!masker) {
       continue;
     }
diff --git a/third_party/blink/renderer/core/paint/svg_mask_painter.h b/third_party/blink/renderer/core/paint/svg_mask_painter.h
index ced28d2..d6688a8 100644
--- a/third_party/blink/renderer/core/paint/svg_mask_painter.h
+++ b/third_party/blink/renderer/core/paint/svg_mask_painter.h
@@ -18,9 +18,7 @@
 class GraphicsContext;
 class ImageResourceObserver;
 class LayoutObject;
-class SVGResource;
-class SVGResourceClient;
-class StyleSVGMaskReferenceImage;
+class StyleMaskSourceImage;
 
 class SVGMaskPainter {
   STATIC_ONLY(SVGMaskPainter);
@@ -30,7 +28,7 @@
                     const LayoutObject& layout_object,
                     const DisplayItemClient& display_item_client);
   static void PaintSVGMaskLayer(GraphicsContext&,
-                                const StyleSVGMaskReferenceImage&,
+                                const StyleMaskSourceImage&,
                                 const ImageResourceObserver&,
                                 const gfx::RectF& reference_box,
                                 const float zoom,
@@ -38,8 +36,8 @@
                                 const bool apply_mask_type);
   static gfx::RectF ResourceBoundsForSVGChild(
       const LayoutObject& layout_object);
-  static bool MaskIsValid(SVGResource* mask_resource,
-                          SVGResourceClient* client);
+  static bool MaskIsValid(const StyleMaskSourceImage&,
+                          const ImageResourceObserver&);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/style/build.gni b/third_party/blink/renderer/core/style/build.gni
index fb5d927..4379c2d 100644
--- a/third_party/blink/renderer/core/style/build.gni
+++ b/third_party/blink/renderer/core/style/build.gni
@@ -97,6 +97,8 @@
   "style_initial_letter.cc",
   "style_initial_letter.h",
   "style_intrinsic_length.h",
+  "style_mask_source_image.cc",
+  "style_mask_source_image.h",
   "style_name.h",
   "style_name_or_keyword.h",
   "style_non_inherited_variables.h",
@@ -112,8 +114,6 @@
   "style_scrollbar_color.cc",
   "style_scrollbar_color.h",
   "style_self_alignment_data.h",
-  "style_svg_mask_reference_image.cc",
-  "style_svg_mask_reference_image.h",
   "style_svg_resource.cc",
   "style_svg_resource.h",
   "style_timeline.h",
diff --git a/third_party/blink/renderer/core/style/fill_layer.cc b/third_party/blink/renderer/core/style/fill_layer.cc
index f725e1b7..00b8399 100644
--- a/third_party/blink/renderer/core/style/fill_layer.cc
+++ b/third_party/blink/renderer/core/style/fill_layer.cc
@@ -25,6 +25,7 @@
 #include "third_party/blink/renderer/core/css/css_value.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/style/style_generated_image.h"
+#include "third_party/blink/renderer/core/style/style_mask_source_image.h"
 #include "third_party/blink/renderer/platform/wtf/size_assertions.h"
 
 namespace blink {
@@ -367,8 +368,8 @@
   // When the layer is for a mask and the image is an SVG <mask> reference, the
   // effective clip value is no-clip.
   if (GetType() == EFillLayerType::kMask) {
-    auto* image = GetImage();
-    if (image && image->IsSVGMaskReference()) {
+    const auto* mask_source = DynamicTo<StyleMaskSourceImage>(GetImage());
+    if (mask_source && mask_source->HasSVGMask()) {
       return EFillBox::kNoClip;
     }
   }
diff --git a/third_party/blink/renderer/core/style/style_image.h b/third_party/blink/renderer/core/style/style_image.h
index 22185dc..499afa9c 100644
--- a/third_party/blink/renderer/core/style/style_image.h
+++ b/third_party/blink/renderer/core/style/style_image.h
@@ -172,9 +172,7 @@
   ALWAYS_INLINE bool IsImageResourceSet() const {
     return is_image_resource_set_;
   }
-  ALWAYS_INLINE bool IsSVGMaskReference() const {
-    return is_svg_mask_reference_;
-  }
+  ALWAYS_INLINE bool IsMaskSource() const { return is_mask_source_; }
   ALWAYS_INLINE bool IsPaintImage() const { return is_paint_image_; }
   ALWAYS_INLINE bool IsCrossfadeImage() const { return is_crossfade_; }
 
@@ -191,7 +189,7 @@
         is_generated_image_(false),
         is_image_resource_set_(false),
         is_crossfade_(false),
-        is_svg_mask_reference_(false),
+        is_mask_source_(false),
         is_paint_image_(false),
         is_lazyload_possibly_deferred_(false) {}
   bool is_image_resource_ : 1;
@@ -199,7 +197,7 @@
   bool is_generated_image_ : 1;
   bool is_image_resource_set_ : 1;
   bool is_crossfade_ : 1;
-  bool is_svg_mask_reference_ : 1;
+  bool is_mask_source_ : 1;
   bool is_paint_image_ : 1;
   bool is_lazyload_possibly_deferred_ : 1;
 
diff --git a/third_party/blink/renderer/core/style/style_mask_source_image.cc b/third_party/blink/renderer/core/style/style_mask_source_image.cc
new file mode 100644
index 0000000..7b0db26d
--- /dev/null
+++ b/third_party/blink/renderer/core/style/style_mask_source_image.cc
@@ -0,0 +1,172 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/style/style_mask_source_image.h"
+
+#include "third_party/blink/renderer/core/css/css_image_value.h"
+#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/style/style_fetched_image.h"
+#include "third_party/blink/renderer/core/svg/svg_resource.h"
+#include "third_party/blink/renderer/platform/graphics/image.h"
+
+namespace blink {
+
+StyleMaskSourceImage::StyleMaskSourceImage(StyleFetchedImage* image,
+                                           SVGResource* resource,
+                                           CSSImageValue* resource_css_value)
+    : image_(image),
+      resource_(resource),
+      resource_css_value_(resource_css_value) {
+  is_mask_source_ = true;
+}
+
+StyleMaskSourceImage::StyleMaskSourceImage(SVGResource* resource,
+                                           CSSImageValue* resource_css_value)
+    : StyleMaskSourceImage(nullptr, resource, resource_css_value) {}
+
+StyleMaskSourceImage::~StyleMaskSourceImage() = default;
+
+CSSValue* StyleMaskSourceImage::CssValue() const {
+  return resource_css_value_.Get();
+}
+
+CSSValue* StyleMaskSourceImage::ComputedCSSValue(
+    const ComputedStyle& style,
+    bool allow_visited_style) const {
+  return resource_css_value_->ComputedCSSValueMaybeLocal();
+}
+
+bool StyleMaskSourceImage::CanRender() const {
+  return !image_ || image_->CanRender();
+}
+
+bool StyleMaskSourceImage::IsLoaded() const {
+  return !image_ || image_->IsLoaded();
+}
+
+bool StyleMaskSourceImage::IsLoading() const {
+  return image_ && image_->IsLoading();
+}
+
+bool StyleMaskSourceImage::ErrorOccurred() const {
+  return image_ && image_->ErrorOccurred();
+}
+
+bool StyleMaskSourceImage::IsAccessAllowed(String& failing_url) const {
+  return !image_ || image_->IsAccessAllowed(failing_url);
+}
+
+IntrinsicSizingInfo StyleMaskSourceImage::GetNaturalSizingInfo(
+    float multiplier,
+    RespectImageOrientationEnum respect_orientation) const {
+  if (!image_) {
+    return IntrinsicSizingInfo::None();
+  }
+  return image_->GetNaturalSizingInfo(multiplier, respect_orientation);
+}
+
+gfx::SizeF StyleMaskSourceImage::ImageSize(
+    float multiplier,
+    const gfx::SizeF& default_object_size,
+    RespectImageOrientationEnum respect_orientation) const {
+  if (!image_) {
+    return gfx::SizeF();
+  }
+  return image_->ImageSize(multiplier, default_object_size,
+                           respect_orientation);
+}
+
+bool StyleMaskSourceImage::HasIntrinsicSize() const {
+  return image_ && image_->HasIntrinsicSize();
+}
+
+SVGResource* StyleMaskSourceImage::GetSVGResource() const {
+  return resource_.Get();
+}
+
+SVGResourceClient* StyleMaskSourceImage::GetSVGResourceClient(
+    const ImageResourceObserver& observer) const {
+  return resource_ ? resource_->GetObserverResourceClient(
+                         const_cast<ImageResourceObserver&>(observer))
+                   : nullptr;
+}
+
+void StyleMaskSourceImage::AddClient(ImageResourceObserver* observer) {
+  if (image_) {
+    image_->AddClient(observer);
+  }
+  if (resource_) {
+    resource_->AddObserver(*observer);
+  }
+}
+
+void StyleMaskSourceImage::RemoveClient(ImageResourceObserver* observer) {
+  if (image_) {
+    image_->RemoveClient(observer);
+  }
+  if (resource_) {
+    resource_->RemoveObserver(*observer);
+  }
+}
+
+scoped_refptr<Image> StyleMaskSourceImage::GetImage(
+    const ImageResourceObserver& observer,
+    const Document& document,
+    const ComputedStyle& style,
+    const gfx::SizeF& target_size) const {
+  if (!image_) {
+    return Image::NullImage();
+  }
+  return image_->GetImage(observer, document, style, target_size);
+}
+
+float StyleMaskSourceImage::ImageScaleFactor() const {
+  return image_ ? image_->ImageScaleFactor() : 1;
+}
+
+WrappedImagePtr StyleMaskSourceImage::Data() const {
+  return image_ ? image_->Data() : resource_.Get();
+}
+
+bool StyleMaskSourceImage::KnownToBeOpaque(const Document& document,
+                                           const ComputedStyle& style) const {
+  return image_ && image_->KnownToBeOpaque(document, style);
+}
+
+ImageResourceContent* StyleMaskSourceImage::CachedImage() const {
+  return image_ ? image_->CachedImage() : nullptr;
+}
+
+bool StyleMaskSourceImage::HasSVGMask() const {
+  // If `image_` is null then this has to be an SVG <mask> reference.
+  if (!image_) {
+    return true;
+  }
+  CHECK(resource_);
+  LayoutSVGResourceContainer* container =
+      resource_->ResourceContainerNoCycleCheck();
+  return IsA<LayoutSVGResourceMasker>(container);
+}
+
+bool StyleMaskSourceImage::IsEqual(const StyleImage& other) const {
+  if (other.IsPendingImage()) {
+    // Ignore pending status when comparing; as long as the values are
+    // equal, the images should be considered equal, too.
+    return base::ValuesEquivalent(CssValue(), other.CssValue());
+  }
+  const auto* other_mask_ref = DynamicTo<StyleMaskSourceImage>(other);
+  return other_mask_ref &&
+         base::ValuesEquivalent(image_, other_mask_ref->image_) &&
+         resource_ == other_mask_ref->resource_;
+}
+
+void StyleMaskSourceImage::Trace(Visitor* visitor) const {
+  visitor->Trace(image_);
+  visitor->Trace(resource_);
+  visitor->Trace(resource_css_value_);
+  StyleImage::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/style/style_mask_source_image.h b/third_party/blink/renderer/core/style/style_mask_source_image.h
new file mode 100644
index 0000000..4b1575d
--- /dev/null
+++ b/third_party/blink/renderer/core/style/style_mask_source_image.h
@@ -0,0 +1,102 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_MASK_SOURCE_IMAGE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_MASK_SOURCE_IMAGE_H_
+
+#include "third_party/blink/renderer/core/style/style_image.h"
+
+#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+
+class CSSImageValue;
+class StyleFetchedImage;
+class SVGResource;
+class SVGResourceClient;
+
+// A pseudo-<image> representing the <mask-source> production described in
+// [1]. It's a url() <image> that can either be a regular image, or an SVG
+// <mask> reference.
+//
+// If the reference is non-local this wraps an StyleFetchedImage, and a
+// corresponding SVGResource that wraps the same ImageResourceContent as the
+// StyleFetchedImage. If the url() has fragment that in turn references an SVG
+// <mask> element this can be used to paint/generate a mask from that source.
+//
+// If the reference is local an SVGResource is wrapped.
+//
+// [1] https://drafts.fxtf.org/css-masking/#the-mask-image
+class StyleMaskSourceImage : public StyleImage {
+ public:
+  StyleMaskSourceImage(StyleFetchedImage*, SVGResource*, CSSImageValue*);
+  StyleMaskSourceImage(SVGResource*, CSSImageValue*);
+  ~StyleMaskSourceImage() override;
+
+  CSSValue* CssValue() const override;
+  CSSValue* ComputedCSSValue(const ComputedStyle&,
+                             bool allow_visited_style) const override;
+
+  bool CanRender() const override;
+  bool IsLoaded() const override;
+  bool IsLoading() const override;
+  bool ErrorOccurred() const override;
+  bool IsAccessAllowed(String& failing_url) const override;
+
+  IntrinsicSizingInfo GetNaturalSizingInfo(
+      float multiplier,
+      RespectImageOrientationEnum) const override;
+
+  gfx::SizeF ImageSize(float multiplier,
+                       const gfx::SizeF& default_object_size,
+                       RespectImageOrientationEnum) const override;
+
+  bool HasIntrinsicSize() const override;
+
+  void AddClient(ImageResourceObserver*) override;
+  void RemoveClient(ImageResourceObserver*) override;
+
+  scoped_refptr<Image> GetImage(const ImageResourceObserver&,
+                                const Document&,
+                                const ComputedStyle&,
+                                const gfx::SizeF& target_size) const override;
+  float ImageScaleFactor() const override;
+
+  WrappedImagePtr Data() const override;
+
+  bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
+  ImageResourceContent* CachedImage() const override;
+
+  bool HasSVGMask() const;
+  SVGResource* GetSVGResource() const;
+  SVGResourceClient* GetSVGResourceClient(const ImageResourceObserver&) const;
+
+  void Trace(Visitor* visitor) const override;
+
+ private:
+  bool IsEqual(const StyleImage&) const override;
+
+  // url() <image> being wrapped. Will be null if keeping a document-local
+  // resource.
+  Member<StyleFetchedImage> image_;
+
+  // SVG resource. Can be null if keeping a document-local resource for an
+  // empty fragment.
+  Member<SVGResource> resource_;
+
+  // Original CSS value.
+  Member<CSSImageValue> resource_css_value_;
+};
+
+template <>
+struct DowncastTraits<StyleMaskSourceImage> {
+  static bool AllowFrom(const StyleImage& style_image) {
+    return style_image.IsMaskSource();
+  }
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_MASK_SOURCE_IMAGE_H_
diff --git a/third_party/blink/renderer/core/style/style_svg_mask_reference_image.cc b/third_party/blink/renderer/core/style/style_svg_mask_reference_image.cc
deleted file mode 100644
index 291c464..0000000
--- a/third_party/blink/renderer/core/style/style_svg_mask_reference_image.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/style/style_svg_mask_reference_image.h"
-
-#include "third_party/blink/renderer/core/css/css_image_value.h"
-#include "third_party/blink/renderer/core/style/computed_style.h"
-#include "third_party/blink/renderer/core/svg/svg_resource.h"
-#include "third_party/blink/renderer/platform/graphics/image.h"
-
-namespace blink {
-
-StyleSVGMaskReferenceImage::StyleSVGMaskReferenceImage(
-    SVGResource* resource,
-    CSSImageValue* resource_css_value)
-    : resource_(resource), resource_css_value_(resource_css_value) {
-  is_svg_mask_reference_ = true;
-}
-
-StyleSVGMaskReferenceImage::~StyleSVGMaskReferenceImage() = default;
-
-CSSValue* StyleSVGMaskReferenceImage::CssValue() const {
-  return resource_css_value_.Get();
-}
-
-CSSValue* StyleSVGMaskReferenceImage::ComputedCSSValue(
-    const ComputedStyle& style,
-    bool allow_visited_style) const {
-  return resource_css_value_->ComputedCSSValueMaybeLocal();
-}
-
-bool StyleSVGMaskReferenceImage::IsAccessAllowed(String& failing_url) const {
-  return true;
-}
-
-IntrinsicSizingInfo StyleSVGMaskReferenceImage::GetNaturalSizingInfo(
-    float multiplier,
-    RespectImageOrientationEnum respect_orientation) const {
-  return IntrinsicSizingInfo::None();
-}
-
-gfx::SizeF StyleSVGMaskReferenceImage::ImageSize(
-    float multiplier,
-    const gfx::SizeF& default_object_size,
-    RespectImageOrientationEnum respect_orientation) const {
-  return default_object_size;
-}
-
-bool StyleSVGMaskReferenceImage::HasIntrinsicSize() const {
-  return false;
-}
-
-SVGResource* StyleSVGMaskReferenceImage::GetSVGResource() const {
-  return resource_.Get();
-}
-
-SVGResourceClient* StyleSVGMaskReferenceImage::GetSVGResourceClient(
-    const ImageResourceObserver& observer) const {
-  return resource_ ? resource_->GetObserverResourceClient(
-                         const_cast<ImageResourceObserver&>(observer))
-                   : nullptr;
-}
-
-void StyleSVGMaskReferenceImage::AddClient(ImageResourceObserver* observer) {
-  if (!resource_) {
-    return;
-  }
-  resource_->AddObserver(*observer);
-}
-
-void StyleSVGMaskReferenceImage::RemoveClient(ImageResourceObserver* observer) {
-  if (!resource_) {
-    return;
-  }
-  resource_->RemoveObserver(*observer);
-}
-
-scoped_refptr<Image> StyleSVGMaskReferenceImage::GetImage(
-    const ImageResourceObserver& observer,
-    const Document& document,
-    const ComputedStyle& style,
-    const gfx::SizeF& target_size) const {
-  return Image::NullImage();
-}
-
-WrappedImagePtr StyleSVGMaskReferenceImage::Data() const {
-  return resource_.Get();
-}
-
-bool StyleSVGMaskReferenceImage::KnownToBeOpaque(
-    const Document& document,
-    const ComputedStyle& style) const {
-  return false;
-}
-
-bool StyleSVGMaskReferenceImage::IsEqual(const StyleImage& other) const {
-  if (other.IsPendingImage()) {
-    // Ignore pending status when comparing; as long as the values are
-    // equal, the same, the images should be considered equal, too.
-    return base::ValuesEquivalent(CssValue(), other.CssValue());
-  }
-  const auto* other_mask_ref = DynamicTo<StyleSVGMaskReferenceImage>(other);
-  return other_mask_ref && resource_ == other_mask_ref->resource_;
-}
-
-void StyleSVGMaskReferenceImage::Trace(Visitor* visitor) const {
-  visitor->Trace(resource_);
-  visitor->Trace(resource_css_value_);
-  StyleImage::Trace(visitor);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/style/style_svg_mask_reference_image.h b/third_party/blink/renderer/core/style/style_svg_mask_reference_image.h
deleted file mode 100644
index dd8248f..0000000
--- a/third_party/blink/renderer/core/style/style_svg_mask_reference_image.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_SVG_MASK_REFERENCE_IMAGE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_SVG_MASK_REFERENCE_IMAGE_H_
-
-#include "third_party/blink/renderer/core/style/style_image.h"
-
-#include "third_party/blink/renderer/platform/heap/member.h"
-#include "third_party/blink/renderer/platform/wtf/casting.h"
-
-namespace blink {
-
-class CSSImageValue;
-class SVGResource;
-class SVGResourceClient;
-
-class StyleSVGMaskReferenceImage : public StyleImage {
- public:
-  StyleSVGMaskReferenceImage(SVGResource* resource,
-                             CSSImageValue* resource_css_value);
-  ~StyleSVGMaskReferenceImage() override;
-
-  CSSValue* CssValue() const override;
-  CSSValue* ComputedCSSValue(const ComputedStyle&,
-                             bool allow_visited_style) const override;
-
-  bool IsAccessAllowed(String& failing_url) const override;
-
-  IntrinsicSizingInfo GetNaturalSizingInfo(
-      float multiplier,
-      RespectImageOrientationEnum) const override;
-
-  gfx::SizeF ImageSize(float multiplier,
-                       const gfx::SizeF& default_object_size,
-                       RespectImageOrientationEnum) const override;
-
-  bool HasIntrinsicSize() const override;
-
-  void AddClient(ImageResourceObserver*) override;
-  void RemoveClient(ImageResourceObserver*) override;
-
-  scoped_refptr<Image> GetImage(const ImageResourceObserver&,
-                                const Document&,
-                                const ComputedStyle&,
-                                const gfx::SizeF& target_size) const override;
-
-  WrappedImagePtr Data() const override;
-
-  bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
-
-  SVGResource* GetSVGResource() const;
-  SVGResourceClient* GetSVGResourceClient(const ImageResourceObserver&) const;
-
-  void Trace(Visitor* visitor) const override;
-
- private:
-  bool IsEqual(const StyleImage&) const override;
-
-  Member<SVGResource> resource_;
-  Member<CSSImageValue> resource_css_value_;
-};
-
-template <>
-struct DowncastTraits<StyleSVGMaskReferenceImage> {
-  static bool AllowFrom(const StyleImage& style_image) {
-    return style_image.IsSVGMaskReference();
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_SVG_MASK_REFERENCE_IMAGE_H_
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image.cc b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
index 46b5777..57d3d9c5 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image.cc
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
@@ -675,6 +675,13 @@
   }
 }
 
+Element* SVGImage::GetResourceElement(const AtomicString& id) const {
+  if (!page_) {
+    return nullptr;
+  }
+  return GetFrame()->GetDocument()->getElementById(id);
+}
+
 void SVGImage::LoadCompleted() {
   switch (load_state_) {
     case kInDataChanged:
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image.h b/third_party/blink/renderer/core/svg/graphics/svg_image.h
index 6f51b11..d852c2a 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image.h
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image.h
@@ -44,6 +44,7 @@
 namespace blink {
 
 class Document;
+class Element;
 class LayoutSVGRoot;
 class LocalFrame;
 class Node;
@@ -117,6 +118,9 @@
   void SetPreferredColorScheme(
       mojom::blink::PreferredColorScheme preferred_color_scheme);
 
+  // Introspective service hatch for mask-image. Don't abuse for anything else.
+  Element* GetResourceElement(const AtomicString& id) const;
+
  protected:
   // Whether or not size is available yet.
   bool IsSizeAvailable() override;
diff --git a/third_party/blink/renderer/core/svg/svg_resource.cc b/third_party/blink/renderer/core/svg/svg_resource.cc
index 7eba7ccc..0b0eade 100644
--- a/third_party/blink/renderer/core/svg/svg_resource.cc
+++ b/third_party/blink/renderer/core/svg/svg_resource.cc
@@ -11,6 +11,8 @@
 #include "third_party/blink/renderer/core/dom/tree_scope.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h"
+#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
+#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
 #include "third_party/blink/renderer/core/svg/svg_resource_client.h"
 #include "third_party/blink/renderer/core/svg/svg_resource_document_content.h"
 #include "third_party/blink/renderer/core/svg/svg_uri_reference.h"
@@ -291,4 +293,52 @@
   ResourceClient::Trace(visitor);
 }
 
+ExternalSVGResourceImageContent::ExternalSVGResourceImageContent(
+    ImageResourceContent* image_content,
+    const AtomicString& fragment)
+    : image_content_(image_content), fragment_(fragment) {
+  image_content_->AddObserver(this);
+}
+
+void ExternalSVGResourceImageContent::Prefinalize() {
+  image_content_->DidRemoveObserver();
+  image_content_ = nullptr;
+}
+
+Element* ExternalSVGResourceImageContent::ResolveTarget() {
+  if (!image_content_->IsLoaded() || image_content_->ErrorOccurred()) {
+    return nullptr;
+  }
+  if (!fragment_) {
+    return nullptr;
+  }
+  auto* svg_image = DynamicTo<SVGImage>(image_content_->GetImage());
+  if (!svg_image) {
+    return nullptr;
+  }
+  AtomicString decoded_fragment(
+      DecodeURLEscapeSequences(fragment_, DecodeURLMode::kUTF8OrIsomorphic));
+  return svg_image->GetResourceElement(decoded_fragment);
+}
+
+void ExternalSVGResourceImageContent::ImageNotifyFinished(
+    ImageResourceContent*) {
+  Element* new_target = ResolveTarget();
+  if (new_target == target_) {
+    return;
+  }
+  target_ = new_target;
+  NotifyContentChanged();
+}
+
+String ExternalSVGResourceImageContent::DebugName() const {
+  return "ExternalSVGResourceImageContent";
+}
+
+void ExternalSVGResourceImageContent::Trace(Visitor* visitor) const {
+  visitor->Trace(image_content_);
+  SVGResource::Trace(visitor);
+  ImageResourceObserver::Trace(visitor);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/svg/svg_resource.h b/third_party/blink/renderer/core/svg/svg_resource.h
index a1950e5..2b9a7d8 100644
--- a/third_party/blink/renderer/core/svg/svg_resource.h
+++ b/third_party/blink/renderer/core/svg/svg_resource.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_RESOURCE_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_RESOURCE_H_
 
+#include "third_party/blink/renderer/core/loader/resource/image_resource_observer.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
@@ -142,7 +143,7 @@
   Member<IdTargetObserver> id_observer_;
 };
 
-// External resource reference (see SVGResource.)
+// External resource reference (see SVGResource).
 class ExternalSVGResource final : public SVGResource, public ResourceClient {
  public:
   explicit ExternalSVGResource(const KURL&);
@@ -163,6 +164,31 @@
   KURL url_;
 };
 
+// External resource reference (see SVGResource) with an ImageResourceContent
+// as the "data source".
+class ExternalSVGResourceImageContent final : public SVGResource,
+                                              public ImageResourceObserver {
+  USING_PRE_FINALIZER(ExternalSVGResourceImageContent, Prefinalize);
+
+ public:
+  ExternalSVGResourceImageContent(ImageResourceContent* image_content,
+                                  const AtomicString& fragment);
+
+  void Trace(Visitor*) const override;
+
+ private:
+  void Prefinalize();
+
+  Element* ResolveTarget();
+
+  // ImageResourceObserver overrides
+  void ImageNotifyFinished(ImageResourceContent*) override;
+  String DebugName() const override;
+
+  Member<ImageResourceContent> image_content_;
+  AtomicString fragment_;
+};
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_RESOURCE_H_
diff --git a/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_delegate.cc b/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_delegate.cc
index ca95bbb..4b61f2b 100644
--- a/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_delegate.cc
+++ b/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_delegate.cc
@@ -55,7 +55,7 @@
       StringFromFullPath(file_path), sync_dir);
 }
 
-absl::optional<sql::SandboxedVfs::PathAccessInfo>
+std::optional<sql::SandboxedVfs::PathAccessInfo>
 SandboxedVfsDelegate::GetPathAccess(const base::FilePath& file_path) {
   int32_t attributes = WebDatabaseHost::GetInstance().GetFileAttributes(
       StringFromFullPath(file_path));
@@ -71,7 +71,7 @@
 #endif  // BUILDFLAG(IS_WIN)
 
   if (!file_exists)
-    return absl::nullopt;
+    return std::nullopt;
 
   sql::SandboxedVfs::PathAccessInfo access;
 #if BUILDFLAG(IS_WIN)
diff --git a/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_delegate.h b/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_delegate.h
index 150941ff..06101e1 100644
--- a/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_delegate.h
+++ b/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_delegate.h
@@ -18,7 +18,7 @@
   base::File OpenFile(const base::FilePath& file_path,
                       int sqlite_requested_flags) override;
   int DeleteFile(const base::FilePath& file_path, bool sync_dir) override;
-  absl::optional<sql::SandboxedVfs::PathAccessInfo> GetPathAccess(
+  std::optional<sql::SandboxedVfs::PathAccessInfo> GetPathAccess(
       const base::FilePath& file_path) override;
   bool SetFileLength(const base::FilePath& file_path,
                      base::File& file,
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm b/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
index 7bb505b3..27bf305 100644
--- a/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
+++ b/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
@@ -267,6 +267,11 @@
       RuntimeEnabledFeatures::FontSrcLocalMatchingEnabled()) {
     matched_font = base::apple::CFToNSOwnershipCast(
         MatchUniqueFont(creation_params.Family(), size).release());
+  } else if (creation_params.Family() == font_family_names::kSystemUi) {
+    matched_font = base::apple::CFToNSOwnershipCast(
+        MatchSystemUIFont(font_description.Weight(), font_description.Style(),
+                          font_description.Stretch(), size)
+            .release());
   } else {
     matched_font = MatchNSFontFamily(creation_params.Family(), traits,
                                      font_description.Weight(), size);
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.h b/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.h
index b66f734..2345ef0 100644
--- a/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.h
+++ b/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.h
@@ -46,6 +46,13 @@
     const AtomicString& unique_font_name,
     float size);
 
+PLATFORM_EXPORT
+base::apple::ScopedCFTypeRef<CTFontRef> MatchSystemUIFont(
+    FontSelectionValue desired_weight,
+    FontSelectionValue desired_slant,
+    FontSelectionValue desired_width,
+    float size);
+
 // Converts a blink::FontSelectionValue to the nearest AppKit font weight if
 // possible, otherwise returns the default font weight.
 int ToAppKitFontWeight(FontSelectionValue);
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm b/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
index 582ab9b6..3ef2b51e 100644
--- a/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
+++ b/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
@@ -37,16 +37,22 @@
 #include "base/apple/foundation_util.h"
 #include "base/apple/scoped_cftyperef.h"
 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
+#include "third_party/blink/renderer/platform/fonts/font_selection_types.h"
 #import "third_party/blink/renderer/platform/wtf/hash_set.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 #import "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
 #import "third_party/blink/renderer/platform/wtf/text/string_impl.h"
 
+using base::apple::GetValueFromDictionary;
 using base::apple::ScopedCFTypeRef;
 
 namespace blink {
 
 namespace {
 
+const FourCharCode kWeightTag = 'wght';
+const FourCharCode kWidthTag = 'wdth';
+
 const NSFontTraitMask SYNTHESIZED_FONT_TRAITS =
     (NSBoldFontMask | NSItalicFontMask);
 
@@ -102,21 +108,6 @@
   return candidate_weight_delta_magnitude < chosen_weight_delta_magnitude;
 }
 
-NSFontWeight ToFontWeight(blink::FontSelectionValue font_weight) {
-  if (font_weight <= 50 || font_weight >= 950)
-    return NSFontWeightRegular;
-
-  const NSFontWeight ns_font_weights[] = {
-      NSFontWeightUltraLight, NSFontWeightThin,   NSFontWeightLight,
-      NSFontWeightRegular,    NSFontWeightMedium, NSFontWeightSemibold,
-      NSFontWeightBold,       NSFontWeightHeavy,  NSFontWeightBlack,
-  };
-  size_t select_weight = roundf(font_weight / 100) - 1;
-  DCHECK_GE(select_weight, 0ul);
-  DCHECK_LE(select_weight, std::size(ns_font_weights));
-  return ns_font_weights[select_weight];
-}
-
 }  // namespace
 
 ScopedCFTypeRef<CTFontRef> MatchUniqueFont(const AtomicString& unique_font_name,
@@ -149,6 +140,110 @@
   return matched_font;
 }
 
+void ClampVariationValuesToFontAcceptableRange(
+    ScopedCFTypeRef<CTFontRef> ct_font,
+    FontSelectionValue& weight,
+    FontSelectionValue& width) {
+  ScopedCFTypeRef<CFArrayRef> all_axes(CTFontCopyVariationAxes(ct_font.get()));
+  for (CFIndex i = 0; i < CFArrayGetCount(all_axes.get()); ++i) {
+    CFDictionaryRef axis = base::apple::CFCast<CFDictionaryRef>(
+        CFArrayGetValueAtIndex(all_axes.get(), i));
+    if (!axis) {
+      continue;
+    }
+
+    CFNumberRef axis_id = GetValueFromDictionary<CFNumberRef>(
+        axis, kCTFontVariationAxisIdentifierKey);
+    if (!axis_id) {
+      continue;
+    }
+    int axis_id_value;
+    if (!CFNumberGetValue(axis_id, kCFNumberIntType, &axis_id_value)) {
+      continue;
+    }
+
+    CFNumberRef axis_min_number = GetValueFromDictionary<CFNumberRef>(
+        axis, kCTFontVariationAxisMinimumValueKey);
+    double axis_min_value = 0.0;
+    if (!axis_min_number ||
+        !CFNumberGetValue(axis_min_number, kCFNumberDoubleType,
+                          &axis_min_value)) {
+      continue;
+    }
+
+    CFNumberRef axis_max_number = GetValueFromDictionary<CFNumberRef>(
+        axis, kCTFontVariationAxisMaximumValueKey);
+    double axis_max_value = 0.0;
+    if (!axis_max_number ||
+        !CFNumberGetValue(axis_max_number, kCFNumberDoubleType,
+                          &axis_max_value)) {
+      continue;
+    }
+
+    FontSelectionRange capabilities_range({FontSelectionValue(axis_min_value),
+                                           FontSelectionValue(axis_max_value)});
+
+    if (axis_id_value == kWeightTag && weight != kNormalWeightValue) {
+      weight = capabilities_range.clampToRange(weight);
+    }
+    if (axis_id_value == kWidthTag && width != kNormalWidthValue) {
+      width = capabilities_range.clampToRange(width);
+    }
+  }
+}
+
+ScopedCFTypeRef<CTFontRef> MatchSystemUIFont(FontSelectionValue desired_weight,
+                                             FontSelectionValue desired_slant,
+                                             FontSelectionValue desired_width,
+                                             float size) {
+  ScopedCFTypeRef<CTFontRef> ct_font(
+      CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, size, nullptr));
+
+  if (desired_slant != kNormalSlopeValue) {
+    ct_font.reset(CTFontCreateCopyWithSymbolicTraits(
+        ct_font.get(), size, nullptr, kCTFontItalicTrait, kCTFontItalicTrait));
+  }
+
+  if (desired_weight == kNormalWeightValue &&
+      desired_width == kNormalWidthValue) {
+    return ct_font;
+  }
+
+  ClampVariationValuesToFontAcceptableRange(ct_font, desired_weight,
+                                            desired_width);
+
+  ScopedCFTypeRef<CFMutableDictionaryRef> variations(CFDictionaryCreateMutable(
+      kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks,
+      &kCFTypeDictionaryValueCallBacks));
+
+  auto add_axis_to_variations = [&variations](const FourCharCode tag,
+                                              float desired_value,
+                                              float normal_value) {
+    if (desired_value != normal_value) {
+      ScopedCFTypeRef<CFNumberRef> tag_number(
+          CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &tag));
+      ScopedCFTypeRef<CFNumberRef> value_number(CFNumberCreate(
+          kCFAllocatorDefault, kCFNumberFloatType, &desired_value));
+      CFDictionarySetValue(variations.get(), tag_number.get(),
+                           value_number.get());
+    }
+  };
+  add_axis_to_variations(kWeightTag, desired_weight, kNormalWeightValue);
+  add_axis_to_variations(kWidthTag, desired_width, kNormalWidthValue);
+
+  ScopedCFTypeRef<CFMutableDictionaryRef> attributes(CFDictionaryCreateMutable(
+      kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks,
+      &kCFTypeDictionaryValueCallBacks));
+  CFDictionarySetValue(attributes.get(), kCTFontVariationAttribute,
+                       variations.get());
+
+  ScopedCFTypeRef<CTFontDescriptorRef> var_font_desc(
+      CTFontDescriptorCreateWithAttributes(attributes.get()));
+
+  return ScopedCFTypeRef<CTFontRef>(CTFontCreateCopyWithAttributes(
+      ct_font.get(), size, nullptr, var_font_desc.get()));
+}
+
 // Family name is somewhat of a misnomer here.  We first attempt to find an
 // exact match comparing the desiredFamily to the PostScript name of the
 // installed fonts.  If that fails we then do a search based on the family
@@ -159,15 +254,6 @@
                           float size) {
   DCHECK_NE(desired_family_string, FontCache::LegacySystemFontFamily());
 
-  if (desired_family_string == font_family_names::kSystemUi) {
-    NSFont* font = [NSFont systemFontOfSize:size
-                                     weight:ToFontWeight(desired_weight)];
-    if (desired_traits & IMPORTANT_FONT_TRAITS)
-      font = [NSFontManager.sharedFontManager convertFont:font
-                                              toHaveTrait:desired_traits];
-    return font;
-  }
-
   NSString* desired_family = desired_family_string;
   NSFontManager* font_manager = NSFontManager.sharedFontManager;
 
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm b/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm
index 07068ca..01b9f5a 100644
--- a/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm
+++ b/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm
@@ -7,13 +7,14 @@
 #import <AppKit/AppKit.h>
 #import <CoreText/CoreText.h>
 
-#include "base/apple/foundation_util.h"
+#import "base/apple/foundation_util.h"
 #include "base/apple/scoped_cftyperef.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/font_family_names.h"
 #include "third_party/blink/renderer/platform/fonts/font_selection_types.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 
+using base::apple::CFCast;
 using base::apple::NSToCFPtrCast;
 using base::apple::ScopedCFTypeRef;
 
@@ -61,38 +62,6 @@
 const char* FamiliesWithBoldItalicFaces[] = {"Baskerville", "Cochin", "Georgia",
                                              "GillSans"};
 
-void TestFontWithWeights(const AtomicString& font_name) {
-  float ns_weights[] = {
-      -0.80,  // NSFontWeightUltraLight
-      -0.60,  // NSFontWeightThin
-      -0.40,  // NSFontWeightLight
-      0.0,    // NSFontWeightRegular
-      0.23,   // NSFontWeightMedium
-      0.30,   // NSFontWeightSemibold
-      0.40,   // NSFontWeightBold
-      0.56,   // NSFontWeightHeavy
-      0.62,   // NSFontWeightBlack
-  };
-  for (size_t i = 0; i < 9; i++) {
-    @autoreleasepool {
-      int weight = (i + 1) * 100;
-      NSFont* font =
-          MatchNSFontFamily(font_name, 0, FontSelectionValue(weight), 11);
-      EXPECT_TRUE(font);
-
-      ScopedCFTypeRef<CFDictionaryRef> traits(
-          CTFontCopyTraits(NSToCFPtrCast(font)));
-      CFNumberRef actual_weight_cf_num =
-          base::apple::GetValueFromDictionary<CFNumberRef>(traits.get(),
-                                                           kCTFontWeightTrait);
-      float actual_weight = 0.0;
-      CFNumberGetValue(actual_weight_cf_num, kCFNumberFloatType,
-                       &actual_weight);
-      EXPECT_EQ(actual_weight, ns_weights[i]);
-    }
-  }
-}
-
 void TestFontWithBoldAndItalicTraits(const AtomicString& font_name) {
   NSFont* font_italic =
       MatchNSFontFamily(font_name, NSFontItalicTrait, kNormalWeightValue, 11);
@@ -143,8 +112,75 @@
 }  // namespace
 
 TEST(FontMatcherMacTest, MatchSystemFont) {
-  TestFontWithWeights(font_family_names::kSystemUi);
-  TestFontWithBoldAndItalicTraits(font_family_names::kSystemUi);
+  ScopedCFTypeRef<CTFontRef> font = MatchSystemUIFont(
+      kNormalWeightValue, kNormalSlopeValue, kNormalWidthValue, 11);
+  EXPECT_TRUE(font);
+}
+
+TEST(FontMatcherMacTest, MatchSystemFontItalic) {
+  ScopedCFTypeRef<CTFontRef> font = MatchSystemUIFont(
+      kNormalWeightValue, kItalicSlopeValue, kNormalWidthValue, 11);
+  EXPECT_TRUE(font);
+  ScopedCFTypeRef<CFDictionaryRef> traits(CTFontCopyTraits(font.get()));
+  CFNumberRef slant_num = base::apple::GetValueFromDictionary<CFNumberRef>(
+      traits.get(), kCTFontSlantTrait);
+  float slant;
+  CFNumberGetValue(slant_num, kCFNumberFloatType, &slant);
+  EXPECT_NE(slant, 0.0);
+}
+
+TEST(FontMatcherMacTest, MatchSystemFontWithWeightVariations) {
+  // Mac SystemUI font supports weight variations between 1 and 1000.
+  int min_weight = 1;
+  int max_weight = 1000;
+  FourCharCode wght_tag = 'wght';
+  ScopedCFTypeRef<CFNumberRef> wght_tag_num(
+      CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &wght_tag));
+  for (int weight = min_weight - 1; weight <= max_weight + 1; weight += 50) {
+    if (weight != kNormalWeightValue) {
+      ScopedCFTypeRef<CTFontRef> font = MatchSystemUIFont(
+          FontSelectionValue(weight), kNormalSlopeValue, kNormalWidthValue, 11);
+      EXPECT_TRUE(font);
+      ScopedCFTypeRef<CFDictionaryRef> variations(
+          CTFontCopyVariation(font.get()));
+      CFNumberRef actual_weight_cf_num = CFCast<CFNumberRef>(
+          CFDictionaryGetValue(variations.get(), wght_tag_num.get()));
+      EXPECT_TRUE(actual_weight_cf_num);
+      float actual_weight = 0.0;
+      CFNumberGetValue(actual_weight_cf_num, kCFNumberFloatType,
+                       &actual_weight);
+      float expected_weight =
+          std::max(min_weight, std::min(max_weight, weight));
+      EXPECT_EQ(actual_weight, expected_weight);
+    }
+  }
+}
+
+TEST(FontMatcherMacTest, MatchSystemFontWithWidthVariations) {
+  // Mac SystemUI font supports width variations between 30 and 150.
+  int min_width = 30;
+  int max_width = 150;
+  FourCharCode wdth_tag = 'wdth';
+  ScopedCFTypeRef<CFNumberRef> wdth_tag_num(
+      CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &wdth_tag));
+  for (int width = min_width - 10; width <= max_width + 10; width += 10) {
+    if (width != kNormalWidthValue) {
+      ScopedCFTypeRef<CTFontRef> font = MatchSystemUIFont(
+          kNormalWidthValue, kNormalSlopeValue, FontSelectionValue(width), 11);
+      EXPECT_TRUE(font);
+
+      ScopedCFTypeRef<CFDictionaryRef> variations(
+          CTFontCopyVariation(font.get()));
+      CFNumberRef actual_width_cf_num = CFCast<CFNumberRef>(
+          CFDictionaryGetValue(variations.get(), wdth_tag_num.get()));
+      EXPECT_TRUE(actual_width_cf_num);
+
+      float actual_width = 0.0;
+      CFNumberGetValue(actual_width_cf_num, kCFNumberFloatType, &actual_width);
+      float expected_width = std::max(min_width, std::min(max_width, width));
+      EXPECT_EQ(actual_width, expected_width);
+    }
+  }
 }
 
 TEST(FontMatcherMacTest, FontFamilyMatchingUnavailableFont) {
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac_test.mm b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac_test.mm
index 14ef1119..ca612e3 100644
--- a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac_test.mm
+++ b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac_test.mm
@@ -8,6 +8,7 @@
 #include "base/apple/foundation_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/font_family_names.h"
+#include "third_party/blink/renderer/platform/fonts/font_selection_types.h"
 #include "third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.h"
 #include "third_party/skia/include/core/SkTypeface.h"
 #include "third_party/skia/include/ports/SkTypeface_mac.h"
@@ -15,14 +16,18 @@
 namespace blink {
 
 namespace {
+
 constexpr SkFourByteTag kOpszTag = SkSetFourByteTag('o', 'p', 's', 'z');
 constexpr SkFourByteTag kWghtTag = SkSetFourByteTag('w', 'g', 'h', 't');
 
 sk_sp<SkTypeface> MakeSystemFontOfSize(float size) {
-  return SkMakeTypefaceFromCTFont(base::apple::NSToCFPtrCast(MatchNSFontFamily(
-      font_family_names::kSystemUi, 0, FontSelectionValue(400), size)));
+  return SkMakeTypefaceFromCTFont(MatchSystemUIFont(kNormalWeightValue,
+                                                    kNormalSlopeValue,
+                                                    kNormalWidthValue, size)
+                                      .release());
 }
-}
+
+}  // namespace
 
 TEST(FontPlatformDataMacTest, VariableOpticalSizingThreshold) {
   // Before macOS 10.15, the system font did not have variable optical sizing.
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
index b236cbb..3db15cd 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -501,6 +501,7 @@
   SkAlphaType surface_alpha_type = GetSkColorInfo().alphaType();
   gpu::Mailbox shared_image_mailbox;
 
+  scoped_refptr<gpu::ClientSharedImage> client_shared_image;
   if (!is_accelerated_ &&
       base::FeatureList::IsEnabled(kAlwaysUseMappableSIForSoftwareCanvas)) {
     CHECK(!gpu_memory_buffer_);
@@ -512,7 +513,7 @@
     // TODO(crbug.com/1478238): Add that usage flag back here once the issue is
     // resolved.
 
-    auto client_shared_image = shared_image_interface->CreateSharedImage(
+    client_shared_image = shared_image_interface->CreateSharedImage(
         GetSharedImageFormat(), Size(), GetColorSpace(), surface_origin,
         surface_alpha_type, shared_image_usage_flags, "CanvasResourceRasterGmb",
         gpu::kNullSurfaceHandle, gfx::BufferUsage::SCANOUT_CPU_READ_WRITE);
@@ -521,14 +522,14 @@
     }
     shared_image_mailbox = client_shared_image->mailbox();
   } else if (gpu_memory_buffer_) {
-    auto client_shared_image = shared_image_interface->CreateSharedImage(
+    client_shared_image = shared_image_interface->CreateSharedImage(
         GetSharedImageFormat(), Size(), GetColorSpace(), surface_origin,
         surface_alpha_type, shared_image_usage_flags, "CanvasResourceRasterGmb",
         gpu_memory_buffer_->CloneHandle());
     CHECK(client_shared_image);
     shared_image_mailbox = client_shared_image->mailbox();
   } else {
-    auto client_shared_image = shared_image_interface->CreateSharedImage(
+    client_shared_image = shared_image_interface->CreateSharedImage(
         GetSharedImageFormat(), Size(), GetColorSpace(), surface_origin,
         surface_alpha_type, shared_image_usage_flags, "CanvasResourceRaster",
         gpu::kNullSurfaceHandle);
@@ -541,7 +542,7 @@
 
   auto* raster_interface = RasterInterface();
   DCHECK(raster_interface);
-  owning_thread_data().shared_image_mailbox = shared_image_mailbox;
+  owning_thread_data().client_shared_image = client_shared_image;
 
   if (use_oop_rasterization_)
     return;
@@ -582,7 +583,7 @@
 }
 
 bool CanvasResourceRasterSharedImage::IsValid() const {
-  return !mailbox().IsZero();
+  return client_shared_image() != nullptr;
 }
 
 void CanvasResourceRasterSharedImage::BeginReadAccess() {
@@ -634,8 +635,9 @@
       gpu::SyncToken shared_image_sync_token;
       raster_interface->GenUnverifiedSyncTokenCHROMIUM(
           shared_image_sync_token.GetData());
-      shared_image_interface->DestroySharedImage(shared_image_sync_token,
-                                                 mailbox());
+      shared_image_interface->DestroySharedImage(
+          shared_image_sync_token,
+          std::move(owning_thread_data().client_shared_image));
     }
     if (raster_interface) {
       if (owning_thread_data().texture_id_for_read_access) {
@@ -722,7 +724,7 @@
       // non-owning thread in order to avoid modifying the mailbox on non
       // owning thread by mistake.
       CHECK(sii_);
-      mapping = sii_->MapSharedImage(mailbox());
+      mapping = sii_->MapSharedImage(client_shared_image()->mailbox());
       if (!mapping) {
         LOG(ERROR) << "MapSharedImage Failed.";
         return nullptr;
@@ -787,9 +789,9 @@
     owning_thread_data().mailbox_sync_mode = kUnverifiedSyncToken;
   }
   image = AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
-      mailbox(), GetSyncToken(), texture_id_for_image, image_info,
-      texture_target_, is_origin_top_left_, context_provider_wrapper_,
-      owning_thread_ref_, owning_thread_task_runner_,
+      client_shared_image()->mailbox(), GetSyncToken(), texture_id_for_image,
+      image_info, texture_target_, is_origin_top_left_,
+      context_provider_wrapper_, owning_thread_ref_, owning_thread_task_runner_,
       std::move(release_callback), supports_display_compositing_,
       is_overlay_candidate_);
 
@@ -810,7 +812,7 @@
   void* memory = nullptr;
   size_t stride = 0;
   if (base::FeatureList::IsEnabled(kAlwaysUseMappableSIForSoftwareCanvas)) {
-    mapping = sii->MapSharedImage(mailbox());
+    mapping = sii->MapSharedImage(client_shared_image()->mailbox());
     if (!mapping) {
       LOG(ERROR) << "MapSharedImage failed.";
       return;
@@ -835,7 +837,7 @@
   base::FeatureList::IsEnabled(kAlwaysUseMappableSIForSoftwareCanvas)
       ? mapping.reset()
       : gpu_memory_buffer_->Unmap();
-  sii->UpdateSharedImage(gpu::SyncToken(), mailbox());
+  sii->UpdateSharedImage(gpu::SyncToken(), client_shared_image()->mailbox());
   owning_thread_data().sync_token = sii->GenUnverifiedSyncToken();
 }
 
@@ -844,11 +846,17 @@
   if (!is_cross_thread()) {
     owning_thread_data().mailbox_sync_mode = sync_mode;
   }
-  return mailbox();
+
+  // NOTE: Return gpu::Mailbox() here does not build due to this function
+  // returning a reference.
+  // TODO(crbug.com/1494911): Remove `empty_mailbox_` entirely once
+  // GetOrCreateGpuMailbox() is converted to return ClientSharedImage.
+  return client_shared_image() ? client_shared_image()->mailbox()
+                               : empty_mailbox_;
 }
 
 bool CanvasResourceRasterSharedImage::HasGpuMailbox() const {
-  return !mailbox().IsZero();
+  return client_shared_image() != nullptr;
 }
 
 const gpu::SyncToken CanvasResourceRasterSharedImage::GetSyncToken() {
@@ -912,7 +920,7 @@
                   base::trace_event::MemoryAllocatorDump::kUnitsBytes,
                   memory_size);
 
-  auto guid = gpu::GetSharedImageGUIDForTracing(mailbox());
+  auto guid = client_shared_image()->GetGUIDForTracing();
   pmd->CreateSharedGlobalAllocatorDump(guid);
   pmd->AddOwnershipEdge(dump->guid(), guid,
                         static_cast<int>(gpu::TracingImportance::kClientOwner));
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.h b/third_party/blink/renderer/platform/graphics/canvas_resource.h
index 012ff322..06bc6de 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -13,6 +13,7 @@
 #include "components/viz/common/resources/shared_bitmap.h"
 #include "components/viz/common/resources/shared_image_format.h"
 #include "components/viz/common/resources/transferable_resource.h"
+#include "gpu/command_buffer/client/client_shared_image.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/shared_image_interface.h"
 #include "gpu/command_buffer/common/mailbox.h"
@@ -394,7 +395,7 @@
   // before a resource is used on a different thread.
   struct OwningThreadData {
     bool mailbox_needs_new_sync_token = true;
-    gpu::Mailbox shared_image_mailbox;
+    scoped_refptr<gpu::ClientSharedImage> client_shared_image;
     gpu::SyncToken sync_token;
     size_t bitmap_image_read_refs = 0u;
     MailboxSyncMode mailbox_sync_mode = kUnverifiedSyncToken;
@@ -441,9 +442,9 @@
     return owning_thread_data_;
   }
 
-  // Can be read on any thread but updated only on the owning thread.
-  const gpu::Mailbox& mailbox() const {
-    return owning_thread_data_.shared_image_mailbox;
+  // Can be read on any thread.
+  gpu::ClientSharedImage* client_shared_image() const {
+    return owning_thread_data_.client_shared_image.get();
   }
   bool mailbox_needs_new_sync_token() const {
     return owning_thread_data_.mailbox_needs_new_sync_token;
@@ -472,6 +473,9 @@
   const bool supports_display_compositing_;
   const GLenum texture_target_;
   const bool use_oop_rasterization_;
+  // TODO(crbug.com/1494911): Remove this field once GetOrCreateGpuMailbox() is
+  // converted to return ClientSharedImage.
+  const gpu::Mailbox empty_mailbox_;
 
   // Note that SharedImageInterface is supposed to be used via
   // |context_provider_wrapper_| to ensure that only owning thread can access
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
index 9d6771c..602ff2e 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/numerics/safe_conversions.h"
 #include "cc/input/layer_selection_bound.h"
 #include "cc/layers/layer.h"
@@ -234,13 +235,15 @@
     bool IsEffect() const { return type_ == kEffect; }
     bool NeedsRestore() const { return type_ != kClipOmitted; }
 
-    // These fields are neve nullptr.
-    raw_ptr<const TransformPaintPropertyNode, ExperimentalRenderer> transform;
-    raw_ptr<const ClipPaintPropertyNode, ExperimentalRenderer> clip;
-    raw_ptr<const EffectPaintPropertyNode, ExperimentalRenderer> effect;
+    // These fields are never nullptr.
+    //
+    // Excluded from being `raw_ptr` for visible regressions in
+    // MotionMark (crbug.com/1495275#c116).
+    RAW_PTR_EXCLUSION const TransformPaintPropertyNode* transform;
+    RAW_PTR_EXCLUSION const ClipPaintPropertyNode* clip;
+    RAW_PTR_EXCLUSION const EffectPaintPropertyNode* effect;
     // See ConversionContext<Result>::previous_transform_.
-    raw_ptr<const TransformPaintPropertyNode, ExperimentalRenderer>
-        previous_transform;
+    RAW_PTR_EXCLUSION const TransformPaintPropertyNode* previous_transform;
 #if DCHECK_IS_ON()
     bool has_pre_cap_effect_hierarchy_issue = false;
 #endif
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
index 1629dd3..24f959ad 100644
--- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
+++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
@@ -7,7 +7,7 @@
 
 #include "base/check_op.h"
 #include "base/dcheck_is_on.h"
-#include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -149,8 +149,10 @@
   // The parent of the root of consecutive identity or 2d translations from the
   // transform node, or the root of the tree if the whole path from the
   // transform node to the root contains identity or 2d translations only.
-  raw_ptr<const TransformPaintPropertyNode, ExperimentalRenderer>
-      root_of_2d_translation_;
+  //
+  // Excluded from being a `raw_ptr` for visible regression in
+  // MotionMark (crbug.com/1495275#c116).
+  RAW_PTR_EXCLUSION const TransformPaintPropertyNode* root_of_2d_translation_;
 
   // The cached values here can be categorized in two logical groups:
   //
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
index dfee073..7593d8e3 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
@@ -354,7 +354,7 @@
   dest->enable_upload_progress = src.ReportUploadProgress();
   dest->throttling_profile_id = src.GetDevToolsToken();
   dest->trust_token_params = ConvertTrustTokenParams(src.TrustTokenParams());
-  dest->target_address_space = src.GetTargetAddressSpace();
+  dest->required_ip_address_space = src.GetTargetAddressSpace();
 
   if (base::UnguessableToken window_id = src.GetFetchWindowId())
     dest->fetch_window_id = absl::make_optional(window_id);
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index b643a87..7cc53395 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -66,6 +66,15 @@
 [ Linux ] virtual/text-antialias/mac-system-ui-weight.html [ Skip ]
 [ Win ] virtual/text-antialias/mac-system-ui-weight.html [ Skip ]
 
+# Tests Mac system font specific width variations.
+[ Linux ] virtual/text-antialias/mac-system-ui-width.html [ Skip ]
+[ Win ] virtual/text-antialias/mac-system-ui-width.html [ Skip ]
+[ Mac10.15 ] virtual/text-antialias/mac-system-ui-width.html [ Skip ]
+
+# Tests Mac system font oblique faces.
+[ Linux ] virtual/text-antialias/mac-system-ui-slant.html [ Skip ]
+[ Win ] virtual/text-antialias/mac-system-ui-slant.html [ Skip ]
+
  # Mac's popup behavior is different.
 [ Mac ] fast/forms/select/menulist-onchange-fired-with-key-up-down.html [ Skip ]
 [ Mac ] fast/forms/select/popup-with-display-none-optgroup.html [ Skip ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 2821b28..92cec56 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -498,10 +498,6 @@
 crbug.com/367737 external/wpt/svg/painting/reftests/paint-context-001.svg [ Failure ]
 crbug.com/367737 external/wpt/svg/painting/reftests/paint-context-002.svg [ Failure ]
 
-# Need to support remote SVG mask references.
-crbug.com/1496470 external/wpt/css/css-masking/mask-image/mask-image-url-remote-mask.html [ Failure ]
-crbug.com/1496470 external/wpt/css/css-masking/mask-image/mask-image-1c.html [ Failure ]
-
 # See: https://bugzilla.mozilla.org/show_bug.cgi?id=1834644
 crbug.com/843084 external/wpt/css/css-masking/clip-path/clip-path-element-userSpaceOnUse-003.html [ Failure ]
 crbug.com/843084 external/wpt/css/css-masking/clip-path/clip-path-element-userSpaceOnUse-004.html [ Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index e6c8206..1b614ed8 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -2662,5 +2662,16 @@
     "args": ["--use-gpu-in-tests", "--enable-features=MachineLearningNeuralNetworkService"],
     "expires": "Jun 1, 2024",
     "owners": ["rafael.cintron@microsoft.com", "ningxin.hu@intel.com", "kbr@chromium.org"]
+  },
+  {
+    "prefix": "deprecate-unload",
+    "platforms": ["Linux", "Mac", "Win"],
+    "bases": [
+      "external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window.js",
+      "external/wpt/permissions-policy/experimental-features/unload-disallowed-subframe.tentative.window.js"
+     ],
+    "args": ["--enable-features=DeprecateUnload"],
+    "expires": "Jun 1, 2024",
+    "owners": ["fergal@chromium.org", "rakina@chromium.org"]
   }
 ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-strokeBox-1c.html b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-strokeBox-1c.html
new file mode 100644
index 0000000..577e6d0a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-strokeBox-1c.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path stroke-box with transform</title>
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="fuzzy" content="maxDifference=0-64; totalPixels=0-260">
+    <meta name="assert" content="Test checks whether clip-path stroke-box works correctly or not.">
+  </head>
+  <body>
+    <svg width="200" height="200" style="position: absolute; left: 0px; top: 0px;">
+      <g clip-path="circle(50%) stroke-box">
+        <rect x="0" y="60" width="80" height="80" fill="blue" stroke="blue" stroke-width="20" transform="translate(60,0)"/>
+      </g>
+    </svg>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-keepalive.any.js b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-keepalive.any.js
index f68d90ef..08229f9 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-keepalive.any.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-keepalive.any.js
@@ -75,10 +75,10 @@
 function keepaliveCorsInUnloadTest(description, origin, method) {
   const evt = 'unload';
   for (const mode of ['no-cors', 'cors']) {
-    for (const disallowOrigin of [false, true]) {
+    for (const disallowCrossOrigin of [false, true]) {
       const desc = `${description} ${method} request in ${evt} [${mode} mode` +
-          (disallowOrigin ? `, server forbid CORS]` : `]`);
-      const shouldPass = !disallowOrigin || mode === 'no-cors';
+          (disallowCrossOrigin ? ']' : ', server forbid CORS]');
+      const expectTokenExist = !disallowCrossOrigin || mode === 'no-cors';
       promise_test(async (test) => {
         const token1 = token();
         const iframe = document.createElement('iframe');
@@ -87,14 +87,14 @@
           requestOrigin: origin,
           sendOn: evt,
           mode: mode,
-          disallowOrigin
+          disallowCrossOrigin
         });
         document.body.appendChild(iframe);
         await iframeLoaded(iframe);
         iframe.remove();
         assert_equals(await getTokenFromMessage(), token1);
 
-        assertStashedTokenAsync(desc, token1, {shouldPass});
+        assertStashedTokenAsync(desc, token1, {expectTokenExist});
       }, `${desc}; setting up`);
     }
   }
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-keepalive.any.js b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-keepalive.any.js
index bcfc444..1cdec79 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-keepalive.any.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-keepalive.any.js
@@ -15,12 +15,23 @@
 } = get_host_info();
 
 /**
- * In an iframe, test to fetch a keepalive URL that involves in redirect to
- * another URL.
+ * In an iframe, and in `load` event handler, test to fetch a keepalive URL that
+ * involves in redirect to another URL.
+ *
+ * `unloadIframe` to unload the iframe before verifying stashed token to
+ * simulate the situation that unloads after fetching. Note that this test is
+ * different from `keepaliveRedirectInUnloadTest()` in that the the latter
+ * performs fetch() call directly in `unload` event handler, while this test
+ * does it in `load`.
  */
 function keepaliveRedirectTest(
-    desc, {origin1 = '', origin2 = '', withPreflight = false} = {}) {
-  desc = `[keepalive] ${desc}`;
+    desc,
+    {origin1 = '',
+     origin2 = '',
+     withPreflight = false,
+     unloadIframe = false} = {}) {
+  desc = `[keepalive][iframe][load] ${desc}` +
+      (unloadIframe ? ' [unload at end]' : '');
   promise_test(async (test) => {
     const tokenToStash = token();
     const iframe = document.createElement('iframe');
@@ -29,7 +40,9 @@
     document.body.appendChild(iframe);
     await iframeLoaded(iframe);
     assert_equals(await getTokenFromMessage(), tokenToStash);
-    iframe.remove();
+    if (unloadIframe) {
+      iframe.remove();
+    }
 
     assertStashedTokenAsync(desc, tokenToStash);
   }, `${desc}; setting up`);
@@ -44,7 +57,7 @@
   origin2 = '',
   url2 = '',
   withPreflight = false,
-  shouldPass = true
+  expectFetchSucceed = true
 } = {}) {
   desc = `[keepalive][new window][unload] ${desc}`;
 
@@ -58,22 +71,27 @@
     const token = await getTokenFromMessage();
     w.close();
 
-    assertStashedTokenAsync(desc, token, {shouldPass});
+    assertStashedTokenAsync(
+        desc, token, {expectTokenExist: expectFetchSucceed});
   }, `${desc}; setting up`);
 }
 
-keepaliveRedirectTest(`same-origin redirect`);
-keepaliveRedirectTest(
-    `same-origin redirect + preflight`, {withPreflight: true});
-keepaliveRedirectTest(`cross-origin redirect`, {
-  origin1: HTTP_REMOTE_ORIGIN,
-  origin2: HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT
-});
-keepaliveRedirectTest(`cross-origin redirect + preflight`, {
-  origin1: HTTP_REMOTE_ORIGIN,
-  origin2: HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT,
-  withPreflight: true
-});
+for (const unloadIframe of [false, true]) {
+  keepaliveRedirectTest(`same-origin redirect`, {unloadIframe});
+  keepaliveRedirectTest(
+      `same-origin redirect + preflight`, {withPreflight: true, unloadIframe});
+  keepaliveRedirectTest(`cross-origin redirect`, {
+    origin1: HTTP_REMOTE_ORIGIN,
+    origin2: HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT,
+    unloadIframe
+  });
+  keepaliveRedirectTest(`cross-origin redirect + preflight`, {
+    origin1: HTTP_REMOTE_ORIGIN,
+    origin2: HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT,
+    withPreflight: true,
+    unloadIframe
+  });
+}
 
 keepaliveRedirectInUnloadTest('same-origin redirect');
 keepaliveRedirectInUnloadTest(
@@ -88,7 +106,9 @@
   withPreflight: true
 });
 keepaliveRedirectInUnloadTest(
-    'redirect to file URL', {url2: 'file://tmp/bar.txt', shouldPass: false});
-keepaliveRedirectInUnloadTest(
-    'redirect to data URL',
-    {url2: 'data:text/plain;base64,cmVzcG9uc2UncyBib2R5', shouldPass: false});
+    'redirect to file URL',
+    {url2: 'file://tmp/bar.txt', expectFetchSucceed: false});
+keepaliveRedirectInUnloadTest('redirect to data URL', {
+  url2: 'data:text/plain;base64,cmVzcG9uc2UncyBib2R5',
+  expectFetchSucceed: false
+});
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/resources/keepalive-helper.js b/third_party/blink/web_tests/external/wpt/fetch/api/resources/keepalive-helper.js
index ad1d4b2..b70e22fc 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/resources/keepalive-helper.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/resources/keepalive-helper.js
@@ -11,14 +11,14 @@
 // `sendOn` to specify the name of the event when the keepalive request should
 // be sent instead of the default 'load'.
 // `mode` to specify the fetch request's CORS mode.
-// `disallowOrigin` to ask the iframe to set up a server that forbids CORS
-// requests.
+// `disallowCrossOrigin` to ask the iframe to set up a server that disallows
+// cross origin requests.
 function getKeepAliveIframeUrl(token, method, {
   frameOrigin = 'DEFAULT',
   requestOrigin = '',
   sendOn = 'load',
   mode = 'cors',
-  disallowOrigin = false
+  disallowCrossOrigin = false
 } = {}) {
   const https = location.protocol.startsWith('https');
   frameOrigin = frameOrigin === 'DEFAULT' ?
@@ -28,7 +28,7 @@
       `token=${token}&` +
       `method=${method}&` +
       `sendOn=${sendOn}&` +
-      `mode=${mode}&` + (disallowOrigin ? `disallowOrigin=1&` : ``) +
+      `mode=${mode}&` + (disallowCrossOrigin ? `disallowCrossOrigin=1&` : ``) +
       `origin=${requestOrigin}`;
 }
 
@@ -72,25 +72,40 @@
   return json;
 }
 
+// A helper to assert the existence of `token` that should have been stored in
+// the server by fetching ../resources/stash-put.py.
+//
+// This function simply wait for a custom amount of time before trying to
+// retrieve `token` from the server.
+// `expectTokenExist` tells if `token` should be present or not.
+//
+// NOTE:
 // In order to parallelize the work, we are going to have an async_test
 // for the rest of the work. Note that we want the serialized behavior
 // for the steps so far, so we don't want to make the entire test case
 // an async_test.
-function assertStashedTokenAsync(testName, token, {shouldPass = true} = {}) {
-  async_test((test) => {
-    new Promise((resolve) => test.step_timeout(resolve, 3000))
-        .then(() => {
+function assertStashedTokenAsync(
+    testName, token, {expectTokenExist = true} = {}) {
+  async_test(test => {
+    new Promise(resolve => test.step_timeout(resolve, 3000 /*ms*/))
+        .then(test.step_func(() => {
           return queryToken(token);
-        })
-        .then((result) => {
-          assert_equals(result, 'on');
-        })
-        .then(() => {
-          test.done();
-        })
-        .catch(test.step_func((e) => {
-          if (shouldPass) {
-            assert_unreached(e);
+        }))
+        .then(test.step_func(result => {
+          if (expectTokenExist) {
+            assert_equals(
+                result, 'on', `token [${token}] should be on (stashed).`);
+            test.done();
+          } else {
+            assert_not_equals(
+                result, 'on', `token [${token}] should not be on (stashed).`);
+            return Promise.reject(
+                `Failed to retrieve token [${token}] from server`);
+          }
+        }))
+        .catch(test.step_func(e => {
+          if (expectTokenExist) {
+            test.unreached_func(e);
           } else {
             test.done();
           }
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/resources/keepalive-iframe.html b/third_party/blink/web_tests/external/wpt/fetch/api/resources/keepalive-iframe.html
index 335a1f8..f9dae5a 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/resources/keepalive-iframe.html
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/resources/keepalive-iframe.html
@@ -4,14 +4,15 @@
 <script>
 const SEARCH_PARAMS = new URL(location.href).searchParams;
 const ORIGIN = SEARCH_PARAMS.get('origin') || '';
+const FRAME_ORIGIN = new URL(location.href).origin;
 const TOKEN = SEARCH_PARAMS.get('token') || '';
 const METHOD = SEARCH_PARAMS.get('method') || 'GET';
 const SEND_ON_EVENT = SEARCH_PARAMS.get('sendOn') || 'load';
 const MODE = SEARCH_PARAMS.get('mode') || 'cors';
-const DISALLOW_ORIGIN = SEARCH_PARAMS.get('disallow_origin') || '';
+const DISALLOW_CROSS_ORIGIN = SEARCH_PARAMS.get('disallowCrossOrigin') || '';
 // CORS requests are allowed by this URL by default.
-const url = `${ORIGIN}/fetch/api/resources/stash-put.py?key=${TOKEN}&value=on` +
-(DISALLOW_ORIGIN ? `&disallow_origin=1` : '');
+const url = `${ORIGIN}/fetch/api/resources/stash-put.py?key=${TOKEN}&value=on&mode=${MODE}`
+    + `&frame_origin=${FRAME_ORIGIN}` + (DISALLOW_CROSS_ORIGIN ? `&disallow_cross_origin=1` : '');
 
 addEventListener(SEND_ON_EVENT, () => {
   let p = fetch(url, {keepalive: true, method: METHOD, mode: MODE});
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/resources/stash-put.py b/third_party/blink/web_tests/external/wpt/fetch/api/resources/stash-put.py
index 0530e1b..91c198a 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/resources/stash-put.py
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/resources/stash-put.py
@@ -1,5 +1,20 @@
 from wptserve.utils import isomorphic_decode
 
+def should_be_treated_as_same_origin_request(request):
+  """Tells whether request should be treated as same-origin request."""
+  # In both of the following cases, allow to proceed with handling to simulate
+  # 'no-cors' mode: response is sent, but browser will make it opaque.
+  if request.GET.first(b'mode') == b'no-cors':
+    return True
+
+  # We can't rely on the Origin header field of a fetch request, as it is only
+  # present for 'cors' mode or methods other than 'GET'/'HEAD' (i.e. present for
+  # 'POST'). See https://fetch.spec.whatwg.org/#http-origin
+  assert 'frame_origin ' in request.GET
+  frame_origin = request.GET.first(b'frame_origin').decode('utf-8')
+  host_origin = request.url_parts.scheme + '://' + request.url_parts.netloc
+  return frame_origin == host_origin
+
 def main(request, response):
   if request.method == u'OPTIONS':
     # CORS preflight
@@ -8,12 +23,19 @@
     response.headers.set(b'Access-Control-Allow-Headers', b'*')
     return 'done'
 
+  if b'disallow_cross_origin' not in request.GET:
+    response.headers.set(b'Access-Control-Allow-Origin', b'*')
+  elif not should_be_treated_as_same_origin_request(request):
+    # As simple requests will not trigger preflight, we have to manually block
+    # cors requests before making any changes to storage.
+    # https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests
+    # https://fetch.spec.whatwg.org/#cors-preflight-fetch
+    return 'not stashing for cors request'
+
   url_dir = u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/'
   key = request.GET.first(b'key')
   value = request.GET.first(b'value')
   # value here must be a text string. It will be json.dump()'ed in stash-take.py.
   request.server.stash.put(key, isomorphic_decode(value), url_dir)
 
-  if b'disallow_origin' not in request.GET:
-    response.headers.set(b'Access-Control-Allow-Origin', b'*')
   return 'done'
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/iframe.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/iframe.tentative.https.window.js
index bf16b6c..1e00c0a 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/iframe.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/iframe.tentative.https.window.js
@@ -11,8 +11,9 @@
 //
 // Spec: https://wicg.github.io/private-network-access/#integration-fetch
 //
-// These tests verify that contexts can navigate iframes to less-public address
-// spaces iff the target server responds affirmatively to preflight requests.
+// These tests verify that secure contexts can navigate iframes to less-public
+// address spaces iff the target server responds affirmatively to preflight
+// requests.
 //
 // This file covers only those tests that must execute in a secure context.
 // Other tests are defined in: iframe.tentative.window.js
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/iframe.tentative.window.js b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/iframe.tentative.window.js
index c0770df..441e0884d 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/iframe.tentative.window.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/iframe.tentative.window.js
@@ -8,7 +8,7 @@
 // less-public address spaces, and can navigate them otherwise.
 //
 // This file covers only those tests that must execute in a non secure context.
-// Other tests are defined in: iframe.https.window.js
+// Other tests are defined in: iframe.tentative.https.window.js
 
 setup(() => {
   // Making sure we are in a non secure context, as expected.
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/opener.html b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/opener.html
new file mode 100644
index 0000000..40e3b60
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/opener.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Opener</title>
+<body></body>
+<script>
+  window.onmessage = (event) => {
+    const { url } = event.data;
+    const popup = window.open(url);
+    parent.postMessage(popup ? "success" : "failure", "*");
+  };
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/support.sub.js b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/support.sub.js
index 0cb757c..c3bdb81 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/support.sub.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/support.sub.js
@@ -470,6 +470,26 @@
   assert_equals(result, expected);
 }
 
+const WindowOpenTestResult = {
+  SUCCESS: "success",
+  FAILURE: "failure",
+};
+
+async function windowOpenTest(t, { source, target, expected }) {
+  const targetUrl = preflightUrl(target);
+
+  const sourceUrl =
+      resolveUrl("resources/opener.html", sourceResolveOptions(source));
+  sourceUrl.searchParams.set("url", targetUrl);
+
+  const iframe = await appendIframe(t, document, sourceUrl);
+  const reply = futureMessage({ source: iframe.contentWindow });
+
+  iframe.contentWindow.postMessage({ url: targetUrl.href }, "*");
+
+  assert_equals(await reply, expected);
+}
+
 // Similar to `iframeTest`, but replaced iframes with fenced frames.
 async function fencedFrameTest(t, { source, target, expected }) {
   // Allows running tests in parallel.
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/window-open.tentative.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/window-open.tentative.https.window-expected.txt
new file mode 100644
index 0000000..a908ea02
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/window-open.tentative.https.window-expected.txt
@@ -0,0 +1,47 @@
+This is a testharness.js-based test.
+[PASS] local to local: no preflight required.
+[PASS] local to private: no preflight required.
+[PASS] local to public: no preflight required.
+[FAIL] private to local: failed preflight.
+  assert_equals: expected "failure" but got "success"
+[FAIL] private to local: missing CORS headers.
+  assert_equals: expected "failure" but got "success"
+[FAIL] private to local: missing PNA header.
+  assert_equals: expected "failure" but got "success"
+[PASS] private to local: success.
+[PASS] private to private: no preflight required.
+[PASS] private to public: no preflight required.
+[FAIL] public to local: failed preflight.
+  assert_equals: expected "failure" but got "success"
+[FAIL] public to local: missing CORS headers.
+  assert_equals: expected "failure" but got "success"
+[FAIL] public to local: missing PNA header.
+  assert_equals: expected "failure" but got "success"
+[PASS] public to local: success.
+[FAIL] public to private: failed preflight.
+  assert_equals: expected "failure" but got "success"
+[FAIL] public to private: missing CORS headers.
+  assert_equals: expected "failure" but got "success"
+[FAIL] public to private: missing PNA header.
+  assert_equals: expected "failure" but got "success"
+[PASS] public to private: success.
+[PASS] public to public: no preflight required.
+[FAIL] treat-as-public-address to local: failed preflight.
+  assert_equals: expected "failure" but got "success"
+[FAIL] treat-as-public-address to local: missing CORS headers.
+  assert_equals: expected "failure" but got "success"
+[FAIL] treat-as-public-address to local: missing PNA header.
+  assert_equals: expected "failure" but got "success"
+[PASS] treat-as-public-address to local: success.
+[PASS] treat-as-public-address to local (same-origin): no preflight required.
+[FAIL] treat-as-public-address to private: failed preflight.
+  assert_equals: expected "failure" but got "success"
+[FAIL] treat-as-public-address to private: missing CORS headers.
+  assert_equals: expected "failure" but got "success"
+[FAIL] treat-as-public-address to private: missing PNA header.
+  assert_equals: expected "failure" but got "success"
+[PASS] treat-as-public-address to private: success.
+[PASS] treat-as-public-address to public: no preflight required.
+[PASS] treat-as-public-address to local: optional preflight
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/window-open.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/window-open.tentative.https.window.js
new file mode 100644
index 0000000..85b929f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/window-open.tentative.https.window.js
@@ -0,0 +1,200 @@
+// META: script=/common/dispatcher/dispatcher.js
+// META: script=/common/utils.js
+// META: script=resources/support.sub.js
+//
+// These tests verify that secure contexts can navigate iframes to less-public
+// address spaces iff the target server responds affirmatively to preflight
+// requests.
+
+setup(() => {
+  assert_true(window.isSecureContext);
+});
+
+// Source: secure local context.
+//
+// All fetches unaffected by Private Network Access.
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTPS_LOCAL },
+  target: { server: Server.HTTPS_LOCAL },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "local to local: no preflight required.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTPS_LOCAL },
+  target: { server: Server.HTTPS_PRIVATE },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "local to private: no preflight required.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTPS_LOCAL },
+  target: { server: Server.HTTPS_PUBLIC },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "local to public: no preflight required.");
+
+// Generates tests of preflight behavior for a single (source, target) pair.
+//
+// Scenarios:
+//
+// - parent navigates child:
+//   - preflight response has non-2xx HTTP code
+//   - preflight response is missing CORS headers
+//   - preflight response is missing the PNA-specific `Access-Control` header
+//   - success
+//
+function makePreflightTests({
+  key,
+  sourceName,
+  sourceServer,
+  sourceTreatAsPublic,
+  targetName,
+  targetServer,
+}) {
+  const prefix =
+      `${sourceName} to ${targetName}: `;
+
+  const source = {
+    server: sourceServer,
+    treatAsPublic: sourceTreatAsPublic,
+  };
+
+  promise_test_parallel(t => windowOpenTest(t, {
+    source,
+    target: {
+      server: targetServer,
+      behavior: { preflight: PreflightBehavior.failure() },
+    },
+    expected: WindowOpenTestResult.FAILURE,
+  }), prefix + "failed preflight.");
+
+  promise_test_parallel(t => windowOpenTest(t, {
+    source,
+    target: {
+      server: targetServer,
+      behavior: { preflight: PreflightBehavior.noCorsHeader(token()) },
+    },
+    expected: WindowOpenTestResult.FAILURE,
+  }), prefix + "missing CORS headers.");
+
+  promise_test_parallel(t => windowOpenTest(t, {
+    source,
+    target: {
+      server: targetServer,
+      behavior: { preflight: PreflightBehavior.noPnaHeader(token()) },
+    },
+    expected: WindowOpenTestResult.FAILURE,
+  }), prefix + "missing PNA header.");
+
+  promise_test_parallel(t => windowOpenTest(t, {
+    source,
+    target: {
+      server: targetServer,
+      behavior: { preflight: PreflightBehavior.success(token()) },
+    },
+    expected: WindowOpenTestResult.SUCCESS,
+  }), prefix + "success.");
+}
+
+// Source: private secure context.
+//
+// Fetches to the local address space require a successful preflight response
+// carrying a PNA-specific header.
+
+makePreflightTests({
+  sourceServer: Server.HTTPS_PRIVATE,
+  sourceName: 'private',
+  targetServer: Server.HTTPS_LOCAL,
+  targetName: 'local',
+});
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTPS_PRIVATE },
+  target: { server: Server.HTTPS_PRIVATE },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "private to private: no preflight required.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTPS_PRIVATE },
+  target: { server: Server.HTTPS_PUBLIC },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "private to public: no preflight required.");
+
+// Source: public secure context.
+//
+// Fetches to the local and private address spaces require a successful
+// preflight response carrying a PNA-specific header.
+
+makePreflightTests({
+  sourceServer: Server.HTTPS_PUBLIC,
+  sourceName: "public",
+  targetServer: Server.HTTPS_LOCAL,
+  targetName: "local",
+});
+
+makePreflightTests({
+  sourceServer: Server.HTTPS_PUBLIC,
+  sourceName: "public",
+  targetServer: Server.HTTPS_PRIVATE,
+  targetName: "private",
+});
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTPS_PUBLIC },
+  target: { server: Server.HTTPS_PUBLIC },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "public to public: no preflight required.");
+
+// The following tests verify that `CSP: treat-as-public-address` makes
+// documents behave as if they had been served from a public IP address.
+
+makePreflightTests({
+  sourceServer: Server.HTTPS_LOCAL,
+  sourceTreatAsPublic: true,
+  sourceName: "treat-as-public-address",
+  targetServer: Server.OTHER_HTTPS_LOCAL,
+  targetName: "local",
+});
+
+promise_test_parallel(
+    t => windowOpenTest(t, {
+      source: {
+        server: Server.HTTPS_LOCAL,
+        treatAsPublic: true,
+      },
+      target: {server: Server.HTTPS_LOCAL},
+      expected: WindowOpenTestResult.SUCCESS,
+    }),
+    'treat-as-public-address to local (same-origin): no preflight required.');
+
+makePreflightTests({
+  sourceServer: Server.HTTPS_LOCAL,
+  sourceTreatAsPublic: true,
+  sourceName: 'treat-as-public-address',
+  targetServer: Server.HTTPS_PRIVATE,
+  targetName: 'private',
+});
+
+promise_test_parallel(
+    t => windowOpenTest(t, {
+      source: {
+        server: Server.HTTPS_LOCAL,
+        treatAsPublic: true,
+      },
+      target: {server: Server.HTTPS_PUBLIC},
+      expected: WindowOpenTestResult.SUCCESS,
+    }),
+    'treat-as-public-address to public: no preflight required.');
+
+promise_test_parallel(
+    t => windowOpenTest(t, {
+      source: {
+        server: Server.HTTPS_LOCAL,
+        treatAsPublic: true,
+      },
+      target: {
+        server: Server.HTTPS_PUBLIC,
+        behavior: {preflight: PreflightBehavior.optionalSuccess(token())}
+      },
+      expected: WindowOpenTestResult.SUCCESS,
+    }),
+    'treat-as-public-address to local: optional preflight');
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/window-open.tentative.window-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/window-open.tentative.window-expected.txt
new file mode 100644
index 0000000..8140164
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/window-open.tentative.window-expected.txt
@@ -0,0 +1,20 @@
+This is a testharness.js-based test.
+[PASS] local to local: no preflight required.
+[PASS] local to private: no preflight required.
+[PASS] local to public: no preflight required.
+[FAIL] private to local: failure.
+  assert_equals: expected "failure" but got "success"
+[PASS] private to private: no preflight required.
+[PASS] private to public: no preflight required.
+[FAIL] public to local: failure.
+  assert_equals: expected "failure" but got "success"
+[FAIL] public to private: failure.
+  assert_equals: expected "failure" but got "success"
+[PASS] public to public: no preflight required.
+[FAIL] treat-as-public-address to local: failure.
+  assert_equals: expected "failure" but got "success"
+[FAIL] treat-as-public-address to private: failure.
+  assert_equals: expected "failure" but got "success"
+[PASS] treat-as-public-address to public: no preflight required.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/window-open.tentative.window.js b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/window-open.tentative.window.js
new file mode 100644
index 0000000..8d023775
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/window-open.tentative.window.js
@@ -0,0 +1,94 @@
+// META: script=/common/dispatcher/dispatcher.js
+// META: script=/common/utils.js
+// META: script=resources/support.sub.js
+//
+// Spec: https://wicg.github.io/private-network-access/
+//
+// These tests verify that non-secure contexts cannot open a new window to
+// less-public address spaces.
+
+setup(() => {
+  // Making sure we are in a non secure context, as expected.
+  assert_false(window.isSecureContext);
+});
+
+promise_test(t => windowOpenTest(t, {
+  source: { server: Server.HTTP_LOCAL },
+  target: { server: Server.HTTP_LOCAL },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "local to local: no preflight required.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTP_LOCAL },
+  target: { server: Server.HTTP_PRIVATE },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "local to private: no preflight required.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTP_LOCAL },
+  target: { server: Server.HTTP_PUBLIC },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "local to public: no preflight required.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTP_PRIVATE },
+  target: { server: Server.HTTP_LOCAL },
+  expected: WindowOpenTestResult.FAILURE,
+}), "private to local: failure.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTP_PRIVATE },
+  target: { server: Server.HTTP_PRIVATE },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "private to private: no preflight required.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTP_PRIVATE },
+  target: { server: Server.HTTP_PUBLIC },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "private to public: no preflight required.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTP_PUBLIC },
+  target: { server: Server.HTTP_LOCAL },
+  expected: WindowOpenTestResult.FAILURE,
+}), "public to local: failure.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTP_PUBLIC },
+  target: { server: Server.HTTP_PRIVATE },
+  expected: WindowOpenTestResult.FAILURE,
+}), "public to private: failure.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: { server: Server.HTTP_PUBLIC },
+  target: { server: Server.HTTP_PUBLIC },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "public to public: no preflight required.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: {
+    server: Server.HTTP_LOCAL,
+    treatAsPublic: true,
+  },
+  target: { server: Server.HTTP_LOCAL },
+  expected: WindowOpenTestResult.FAILURE,
+}), "treat-as-public-address to local: failure.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: {
+    server: Server.HTTP_LOCAL,
+    treatAsPublic: true,
+  },
+  target: { server: Server.HTTP_PRIVATE },
+  expected: WindowOpenTestResult.FAILURE,
+}), "treat-as-public-address to private: failure.");
+
+promise_test_parallel(t => windowOpenTest(t, {
+  source: {
+    server: Server.HTTP_LOCAL,
+    treatAsPublic: true,
+  },
+  target: { server: Server.HTTP_PUBLIC },
+  expected: WindowOpenTestResult.SUCCESS,
+}), "treat-as-public-address to public: no preflight required.");
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/protocol/transceiver-mline-recycling.html b/third_party/blink/web_tests/external/wpt/webrtc/protocol/transceiver-mline-recycling.html
new file mode 100644
index 0000000..068c5ac
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webrtc/protocol/transceiver-mline-recycling.html
@@ -0,0 +1,87 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>payload type handling (assuming rtcp-mux)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../third_party/sdp/sdp.js"></script>
+<script>
+promise_test(async t => {
+  const pc1 = new RTCPeerConnection();
+  t.add_cleanup(() => pc1.close());
+  const pc2 = new RTCPeerConnection();
+  t.add_cleanup(() => pc2.close());
+  const negotiate = async () => {
+    await pc1.setLocalDescription();
+    await pc2.setRemoteDescription(pc1.localDescription);
+    await pc2.setLocalDescription();
+    await pc1.setRemoteDescription(pc2.localDescription);
+  };
+
+  // Add audio, negotiate, stop the transceiver, negotiate again,
+  // add another audio transceiver and negotiate. This should re-use the m-line.
+  pc1.addTransceiver('audio');
+  await negotiate();
+  pc1.getTransceivers()[0].stop();
+  await negotiate();
+  pc1.addTransceiver('audio');
+  await negotiate();
+  let numberOfMediaSections = SDPUtils.splitSections(pc1.localDescription.sdp).length - 1;
+  assert_equals(numberOfMediaSections, 1, 'Audio m-line gets reused for audio transceiver');
+
+  // Stop the audio transceiver, negotiate, add a video transceiver, negotiate.
+  // This should reuse the m-line.
+  pc1.getTransceivers()[0].stop();
+  await negotiate();
+  pc1.addTransceiver('video');
+  await negotiate();
+  numberOfMediaSections = SDPUtils.splitSections(pc1.localDescription.sdp).length - 1;
+  assert_equals(numberOfMediaSections, 1, 'Audio m-line gets reused for video transceiver');
+
+  // Add another video transceiver after stopping the current one.
+  // This should re-use the m-line.
+  pc1.getTransceivers()[0].stop();
+  await negotiate();
+  pc1.addTransceiver('video');
+  await negotiate();
+  numberOfMediaSections = SDPUtils.splitSections(pc1.localDescription.sdp).length - 1;
+  assert_equals(numberOfMediaSections, 1, 'Video m-line gets reused for video transceiver');
+}, 'Reuses m-lines in local negotiation');
+
+promise_test(async t => {
+  // SDP with a rejected video m-line.
+  const sdp = `v=0
+o=- 0 3 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=fingerprint:sha-256 A7:24:72:CA:6E:02:55:39:BA:66:DF:6E:CC:4C:D8:B0:1A:BF:1A:56:65:7D:F4:03:AD:7E:77:43:2A:29:EC:93
+m=video 0 UDP/TLS/RTP/SAVPF 100
+c=IN IP4 0.0.0.0
+a=rtcp-mux
+a=sendonly
+a=mid:video
+a=rtpmap:100 VP8/90000
+a=setup:actpass
+a=ice-ufrag:ETEn
+a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l
+`;
+  const pc1 = new RTCPeerConnection();
+  t.add_cleanup(() => pc1.close());
+  await pc1.setRemoteDescription({type: 'offer', sdp});
+  await pc1.setLocalDescription();
+  assert_equals(pc1.getTransceivers().length, 0);
+  pc1.addTransceiver('audio');
+  let offer = await pc1.createOffer();
+  let numberOfMediaSections = SDPUtils.splitSections(offer.sdp).length - 1;
+  assert_equals(numberOfMediaSections, 1, 'Remote video m-line gets reused for audio transceiver');
+
+  const pc2 = new RTCPeerConnection();
+  t.add_cleanup(() => pc2.close());
+  await pc2.setRemoteDescription({type: 'offer', sdp});
+  await pc2.setLocalDescription();
+  assert_equals(pc2.getTransceivers().length, 0);
+  pc1.addTransceiver('video');
+  offer = await pc2.createOffer();
+  numberOfMediaSections = SDPUtils.splitSections(offer.sdp).length - 1;
+  assert_equals(numberOfMediaSections, 1, 'Remote video m-line gets reused for video transceiver');
+}, 'Reuses m-lines in remote negotiation');
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/platform/mac-mac11/virtual/text-antialias/mac-system-ui-slant-expected.png b/third_party/blink/web_tests/platform/mac-mac11/virtual/text-antialias/mac-system-ui-slant-expected.png
new file mode 100644
index 0000000..04876fd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11/virtual/text-antialias/mac-system-ui-slant-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/virtual/text-antialias/mac-system-ui-weight-expected.png b/third_party/blink/web_tests/platform/mac-mac11/virtual/text-antialias/mac-system-ui-weight-expected.png
index fae40c2a..02131eb 100644
--- a/third_party/blink/web_tests/platform/mac-mac11/virtual/text-antialias/mac-system-ui-weight-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac11/virtual/text-antialias/mac-system-ui-weight-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/virtual/text-antialias/mac-system-ui-width-expected.png b/third_party/blink/web_tests/platform/mac-mac11/virtual/text-antialias/mac-system-ui-width-expected.png
new file mode 100644
index 0000000..d9f2af2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11/virtual/text-antialias/mac-system-ui-width-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12/virtual/text-antialias/mac-system-ui-weight-expected.png b/third_party/blink/web_tests/platform/mac-mac12/virtual/text-antialias/mac-system-ui-weight-expected.png
index 9ac00b9..3cd5b9a13 100644
--- a/third_party/blink/web_tests/platform/mac-mac12/virtual/text-antialias/mac-system-ui-weight-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac12/virtual/text-antialias/mac-system-ui-weight-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12/virtual/text-antialias/mac-system-ui-width-expected.png b/third_party/blink/web_tests/platform/mac-mac12/virtual/text-antialias/mac-system-ui-width-expected.png
new file mode 100644
index 0000000..db14ef5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac12/virtual/text-antialias/mac-system-ui-width-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/text-antialias/mac-system-ui-weight-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/text-antialias/mac-system-ui-weight-expected.png
new file mode 100644
index 0000000..8460af0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/text-antialias/mac-system-ui-weight-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/text-antialias/mac-system-ui-width-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/text-antialias/mac-system-ui-width-expected.png
new file mode 100644
index 0000000..3b4d73b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/text-antialias/mac-system-ui-width-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/mac-system-ui-slant-expected.png b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/mac-system-ui-slant-expected.png
new file mode 100644
index 0000000..63fb8838
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/mac-system-ui-slant-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/mac-system-ui-weight-expected.png b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/mac-system-ui-weight-expected.png
new file mode 100644
index 0000000..8460af0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/mac-system-ui-weight-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/README.md b/third_party/blink/web_tests/virtual/deprecate-unload/README.md
new file mode 100644
index 0000000..4be2473
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/deprecate-unload/README.md
@@ -0,0 +1,7 @@
+Tests that fail when unload is deprecated (--enable-features=DeprecateUnload).
+See https://crbug.com/1488371. Eventually DeprecateUnload will be on by default
+for tests, the expectations here will be moved into main suite and we will
+replace this suite with one that disables the deprecation.
+
+This should only contain tests that truly depend on unload. Tests that fail but
+can be rewritten not to use unload should not be included here.
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window-expected.txt b/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window-expected.txt
new file mode 100644
index 0000000..756a0f55
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] 'unload' Policy : allowed by default
+  assert_equals: sameOriginSubframe: unload in sameOriginSubframe should be allowed expected true but got false
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/permissions-policy/experimental-features/unload-disallowed-subframe.tentative.window-expected.txt b/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/permissions-policy/experimental-features/unload-disallowed-subframe.tentative.window-expected.txt
new file mode 100644
index 0000000..d66d4bf
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/permissions-policy/experimental-features/unload-disallowed-subframe.tentative.window-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] 'unload' Policy : allowed in main frame but disallowed in subframe
+  assert_equals: main: unload in main should be allowed expected true but got false
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-slant.html b/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-slant.html
new file mode 100644
index 0000000..14de4f6
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-slant.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<style>
+  .system-ui-font {
+    font-family: system-ui, cursive;
+  }
+</style>
+<div style="display: flex;">
+  <div style="flex: 1; font-size: 12px;">
+    <div class="system-ui-font" style="font-style: italic;">System italic font</div>
+    <div class="system-ui-font" style="font-style: oblique 5deg;">System font oblique 5deg</div>
+    <div class="system-ui-font" style="font-style: oblique 14deg;">System font oblique 14deg</div>
+    <div class="system-ui-font" style="font-style: oblique 20deg;">System font oblique 20deg</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 100;">System italic font at weight 100</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 200;">System italic font at weight 200</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 300;">System italic font at weight 300</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 400;">System italic font at weight 400</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 500;">System italic font at weight 500</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 600;">System italic font at weight 600</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 700;">System italic font at weight 700</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 800;">System italic font at weight 800</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 900;">System italic font at weight 900</div>
+  </div>
+  <div style="flex: 1; font-size: 20px;">
+    <div class="system-ui-font" style="font-style: italic;">System italic font</div>
+    <div class="system-ui-font" style="font-style: oblique 5deg;">System font oblique 5deg</div>
+    <div class="system-ui-font" style="font-style: oblique 14deg;">System font oblique 14deg</div>
+    <div class="system-ui-font" style="font-style: oblique 20deg;">System font oblique 20deg</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 100;">System italic font at weight 100</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 200;">System italic font at weight 200</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 300;">System italic font at weight 300</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 400;">System italic font at weight 400</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 500;">System italic font at weight 500</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 600;">System italic font at weight 600</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 700;">System italic font at weight 700</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 800;">System italic font at weight 800</div>
+    <div class="system-ui-font" style="font-style: italic; font-weight: 900;">System italic font at weight 900</div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-weight-expected.png b/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-weight-expected.png
index 01d40120..8460af0 100644
--- a/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-weight-expected.png
+++ b/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-weight-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-width-expected.png b/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-width-expected.png
new file mode 100644
index 0000000..3b4d73b
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-width-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-width.html b/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-width.html
new file mode 100644
index 0000000..9ac0767
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/text-antialias/mac-system-ui-width.html
@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<style>
+  .system-ui-font {
+    font-family: system-ui, cursive;
+  }
+</style>
+<div style="display: flex;">
+  <div style="flex: 1; font-size: 12px;">
+    <div class="system-ui-font" style="font-stretch: 10%;">System font at width 10</div>
+    <div class="system-ui-font" style="font-stretch: 30%;">System font at width 30</div>
+    <div class="system-ui-font" style="font-stretch: 40%;">System font at width 40</div>
+    <div class="system-ui-font" style="font-stretch: 50%;">System font at width 50</div>
+    <div class="system-ui-font" style="font-stretch: 60%;">System font at width 60</div>
+    <div class="system-ui-font" style="font-stretch: 70%;">System font at width 70</div>
+    <div class="system-ui-font" style="font-stretch: 80%;">System font at width 80</div>
+    <div class="system-ui-font" style="font-stretch: 90%;">System font at width 90</div>
+    <div class="system-ui-font" style="font-stretch: 100%;">System font at width 100</div>
+    <div class="system-ui-font" style="font-stretch: 110%;">System font at width 110</div>
+    <div class="system-ui-font" style="font-stretch: 120%;">System font at width 120</div>
+    <div class="system-ui-font" style="font-stretch: 130%;">System font at width 130</div>
+    <div class="system-ui-font" style="font-stretch: 140%;">System font at width 140</div>
+    <div class="system-ui-font" style="font-stretch: 150%;">System font at width 150</div>
+    <div class="system-ui-font" style="font-stretch: 200%;">System font at width 200</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 10;">Variable system font at width 10</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 30;">Variable system font at width 30</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 40;">Variable system font at width 40</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 50;">Variable system font at width 50</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 60;">Variable system font at width 60</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 70;">Variable system font at width 70</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 80;">Variable system font at width 80</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 90;">Variable system font at width 90</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 100;">Variable system font at width 100</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 110;">Variable system font at width 110</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 120;">Variable system font at width 120</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 130;">Variable system font at width 130</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 140;">Variable system font at width 140</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 150;">Variable system font at width 150</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 200;">Variable system font at width 200</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 10;">Variable system font at
+      width 10 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 30;">Variable system font at
+      width 30 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 40;">Variable system font at
+      width 40 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 50;">Variable system font at
+      width 50 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 60;">Variable system font at
+      width 60 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 70;">Variable system font at
+      width 70 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 80;">Variable system font at
+      width 80 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 90;">Variable system font at
+      width 90 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 100;">Variable system font at
+      width 100 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 110;">Variable system font at
+      width 110 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 120;">Variable system font at
+      width 120 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 130;">Variable system font at
+      width 130 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 140;">Variable system font at
+      width 140 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 150;">Variable system font at
+      width 150 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 200;">Variable system font at
+      width 200 overriden</div>
+  </div>
+  <div style="flex: 1; font-size: 20px;">
+    <div class="system-ui-font" style="font-stretch: 10%;">System font at width 10</div>
+    <div class="system-ui-font" style="font-stretch: 30%;">System font at width 30</div>
+    <div class="system-ui-font" style="font-stretch: 40%;">System font at width 40</div>
+    <div class="system-ui-font" style="font-stretch: 50%;">System font at width 50</div>
+    <div class="system-ui-font" style="font-stretch: 60%;">System font at width 60</div>
+    <div class="system-ui-font" style="font-stretch: 70%;">System font at width 70</div>
+    <div class="system-ui-font" style="font-stretch: 80%;">System font at width 80</div>
+    <div class="system-ui-font" style="font-stretch: 90%;">System font at width 90</div>
+    <div class="system-ui-font" style="font-stretch: 100%;">System font at width 100</div>
+    <div class="system-ui-font" style="font-stretch: 110%;">System font at width 110</div>
+    <div class="system-ui-font" style="font-stretch: 120%;">System font at width 120</div>
+    <div class="system-ui-font" style="font-stretch: 130%;">System font at width 130</div>
+    <div class="system-ui-font" style="font-stretch: 140%;">System font at width 140</div>
+    <div class="system-ui-font" style="font-stretch: 150%;">System font at width 150</div>
+    <div class="system-ui-font" style="font-stretch: 200%;">System font at width 200</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 10;">Variable system font at width 10</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 30;">Variable system font at width 30</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 40;">Variable system font at width 40</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 50;">Variable system font at width 50</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 60;">Variable system font at width 60</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 70;">Variable system font at width 70</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 80;">Variable system font at width 80</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 90;">Variable system font at width 90</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 100;">Variable system font at width 100</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 110;">Variable system font at width 110</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 120;">Variable system font at width 120</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 130;">Variable system font at width 130</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 140;">Variable system font at width 140</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 150;">Variable system font at width 150</div>
+    <div class="system-ui-font" style="font-variation-settings: 'wdth' 200;">Variable system font at width 200</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 10;">Variable system font at
+      width 10 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 30;">Variable system font at
+      width 30 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 40;">Variable system font at
+      width 40 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 50;">Variable system font at
+      width 50 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 60;">Variable system font at
+      width 60 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 70;">Variable system font at
+      width 70 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 80;">Variable system font at
+      width 80 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 90;">Variable system font at
+      width 90 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 100;">Variable system font at
+      width 100 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 110;">Variable system font at
+      width 110 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 120;">Variable system font at
+      width 120 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 130;">Variable system font at
+      width 130 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 140;">Variable system font at
+      width 140 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 150;">Variable system font at
+      width 150 overriden</div>
+    <div class="system-ui-font" style="font-stretch: 110%; font-variation-settings: 'wdth' 200;">Variable system font at
+      width 200 overriden</div>
+  </div>
+</div>
diff --git a/third_party/chromium-variations b/third_party/chromium-variations
index fa82e3f..eb76055 160000
--- a/third_party/chromium-variations
+++ b/third_party/chromium-variations
@@ -1 +1 @@
-Subproject commit fa82e3ff298620455f9e159f8571a89bee79de72
+Subproject commit eb760559fcf0a51cdfaf7e67f219a28d979ad2ef
diff --git a/third_party/cros-components/src b/third_party/cros-components/src
index ccadd23..e764932 160000
--- a/third_party/cros-components/src
+++ b/third_party/cros-components/src
@@ -1 +1 @@
-Subproject commit ccadd234bf9dfa004a69560ed58874a857541e19
+Subproject commit e7649321f6608d790eb2421a8bada54d2d559ac4
diff --git a/third_party/dawn b/third_party/dawn
index d3e897d..c36093e 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit d3e897d992221ddddce7a9a7893fa66db8559c52
+Subproject commit c36093e932c33b6269204461ebbf864bd7e717de
diff --git a/third_party/depot_tools b/third_party/depot_tools
index dbd2967..ea9bf7f 160000
--- a/third_party/depot_tools
+++ b/third_party/depot_tools
@@ -1 +1 @@
-Subproject commit dbd29671bd11c2d59fa898722bdbbcb7d48b8f8b
+Subproject commit ea9bf7f343d3510746a51313a20fb596cd7a6d58
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal
index 34951c1..b32c6af 160000
--- a/third_party/devtools-frontend-internal
+++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@
-Subproject commit 34951c1d294f6e511c2ce3ecb17973a3a37cc1af
+Subproject commit b32c6af7c0da8b57e81dd7217f1a519e3b8805e0
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index cef1d4d..c3e6c9a 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit cef1d4d47c8c59859778863f2ab83b7b9db68aa3
+Subproject commit c3e6c9af4f1260fce7879783b5fb8bbcf0b273bd
diff --git a/third_party/lzma_sdk/C/CpuArch.h b/third_party/lzma_sdk/C/CpuArch.h
index 4856fbb1..8cd55be 100644
--- a/third_party/lzma_sdk/C/CpuArch.h
+++ b/third_party/lzma_sdk/C/CpuArch.h
@@ -253,6 +253,12 @@
 
 
 
+// Disable MY_CPU_LE_UNALIGN. Although the underlying ISA may be able to load
+// unaligned words, doing so via pointer casts is undefined behavior in C and
+// C++, under both strict aliasing and because it is invalid to construct
+// unaligned pointers. Instead, load the bytes generically and leave optimizing
+// this to the compiler.
+#if 0
 #ifdef MY_CPU_LE
   #if defined(MY_CPU_X86_OR_AMD64) \
       || defined(MY_CPU_ARM64)
@@ -264,6 +270,7 @@
     #define MY_CPU_LE_UNALIGN
   #endif
 #endif
+#endif
 
 
 #ifdef MY_CPU_LE_UNALIGN
diff --git a/third_party/lzma_sdk/README.chromium b/third_party/lzma_sdk/README.chromium
index e13b763..7458450 100644
--- a/third_party/lzma_sdk/README.chromium
+++ b/third_party/lzma_sdk/README.chromium
@@ -50,6 +50,9 @@
 bti. Shortened segment names in Asm/x86/*.asm files to make the builds
 deterministic. Resolved include paths as well.
 
+The patch in chromium_ubsan.patch fixes some undefined behavior, flagged by
+UBSan, caused by invalid pointer casts in LZMA SDK.
+
 The patch in Util/SfxSetup/chromium.patch was applied so that:
 
 1/ Fix for includes file names, since the original code causes an include
diff --git a/third_party/lzma_sdk/chromium_ubsan.patch b/third_party/lzma_sdk/chromium_ubsan.patch
new file mode 100644
index 0000000..42bb013f
--- /dev/null
+++ b/third_party/lzma_sdk/chromium_ubsan.patch
@@ -0,0 +1,25 @@
+diff --git a/third_party/lzma_sdk/C/CpuArch.h b/third_party/lzma_sdk/C/CpuArch.h
+index 4856fbb12a256..8cd55bea48dc6 100644
+--- a/third_party/lzma_sdk/C/CpuArch.h
++++ b/third_party/lzma_sdk/C/CpuArch.h
+@@ -253,6 +253,12 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
+ 
+ 
+ 
++// Disable MY_CPU_LE_UNALIGN. Although the underlying ISA may be able to load
++// unaligned words, doing so via pointer casts is undefined behavior in C and
++// C++, under both strict aliasing and because it is invalid to construct
++// unaligned pointers. Instead, load the bytes generically and leave optimizing
++// this to the compiler.
++#if 0
+ #ifdef MY_CPU_LE
+   #if defined(MY_CPU_X86_OR_AMD64) \
+       || defined(MY_CPU_ARM64)
+@@ -264,6 +270,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
+     #define MY_CPU_LE_UNALIGN
+   #endif
+ #endif
++#endif
+ 
+ 
+ #ifdef MY_CPU_LE_UNALIGN
diff --git a/third_party/perfetto b/third_party/perfetto
index 8dc60d8..9c4d509 160000
--- a/third_party/perfetto
+++ b/third_party/perfetto
@@ -1 +1 @@
-Subproject commit 8dc60d8a5484638134420511e0f54415853621c9
+Subproject commit 9c4d5090f6a29c785d4e2a1a1f577bcc17eeb648
diff --git a/third_party/webgpu-cts/src b/third_party/webgpu-cts/src
index 8eee61b..4e27db8 160000
--- a/third_party/webgpu-cts/src
+++ b/third_party/webgpu-cts/src
@@ -1 +1 @@
-Subproject commit 8eee61b66c5987e48fed3fc362910a52f91eb1ca
+Subproject commit 4e27db8161aec185923afa024f62870ef5a6442c
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 76185d9..d53b7b3 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -10331,6 +10331,59 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="GetDisplayMedia.Cancel">
+  <owner>eladalon@chromium.org</owner>
+  <owner>tovep@chromium.org</owner>
+  <owner>kron@chromium.org</owner>
+  <description>User cancelled the getDisplayMedia dialog.</description>
+</action>
+
+<action name="GetDisplayMedia.SelectCurrentTab">
+  <owner>eladalon@chromium.org</owner>
+  <owner>tovep@chromium.org</owner>
+  <owner>kron@chromium.org</owner>
+  <description>
+    User selected to share the current tab in the getDisplayMedia dialog.
+  </description>
+</action>
+
+<action name="GetDisplayMedia.SelectScreen">
+  <owner>eladalon@chromium.org</owner>
+  <owner>tovep@chromium.org</owner>
+  <owner>kron@chromium.org</owner>
+  <description>
+    User selected to share a screen in the getDisplayMedia dialog.
+  </description>
+</action>
+
+<action name="GetDisplayMedia.SelectWebContents">
+  <owner>eladalon@chromium.org</owner>
+  <owner>tovep@chromium.org</owner>
+  <owner>kron@chromium.org</owner>
+  <description>
+    User selected to share web contents in the getDisplayMedia dialog.
+  </description>
+</action>
+
+<action name="GetDisplayMedia.SelectWindow">
+  <owner>eladalon@chromium.org</owner>
+  <owner>tovep@chromium.org</owner>
+  <owner>kron@chromium.org</owner>
+  <description>
+    User selected to share a window in the getDisplayMedia dialog.
+  </description>
+</action>
+
+<action name="GetDisplayMedia.ShowDialog">
+  <owner>eladalon@chromium.org</owner>
+  <owner>tovep@chromium.org</owner>
+  <owner>kron@chromium.org</owner>
+  <description>
+    The getDisplayMedia dialog was shown to the user. In the majority of cases
+    this is triggered by the user in the web application.
+  </description>
+</action>
+
 <action name="Glanceables_Classroom_AssignmentPressed">
   <owner>mmourgos@chromium.org</owner>
   <owner>tbarzic@chromium.org</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 3040c323..3830d95 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -1974,6 +1974,35 @@
   <int value="2" label="RemoteException"/>
 </enum>
 
+<enum name="AndroidWebViewMediaIntegrityInvalidInteraction">
+  <int value="0" label="INVALID_PROVIDER_REQUEST"/>
+  <int value="1" label="INVALID_TOKEN_REQUEST"/>
+  <int value="2" label="CLOSED_PROVIDER_RESPONSE_PORT"/>
+  <int value="3" label="CLOUD_PROJECT_NUMBER_PARSE_ERROR"/>
+  <int value="4" label="TOKEN_REQUEST_MISSING_RESPONSE_PORT"/>
+</enum>
+
+<enum name="AndroidWebViewMediaIntegrityStatus">
+  <int value="0" label="NO_ERROR"/>
+  <int value="1" label="UNKNOWN_ERROR"/>
+  <int value="2" label="API_NOT_AVAILABLE"/>
+  <int value="3" label="PLAY_STORE_NOT_FOUND"/>
+  <int value="4" label="NETWORK_ERROR"/>
+  <int value="5" label="APP_NOT_INSTALLED"/>
+  <int value="6" label="PLAY_SERVICES_NOT_FOUND"/>
+  <int value="7" label="APP_UID_MISMATCH"/>
+  <int value="8" label="TOO_MANY_REQUESTS"/>
+  <int value="9" label="CANNOT_BIND_TO_SERVICE"/>
+  <int value="10" label="GOOGLE_SERVER_UNAVAILABLE"/>
+  <int value="11" label="PLAY_STORE_VERSION_OUTDATED"/>
+  <int value="12" label="PLAY_SERVICES_VERSION_OUTDATED"/>
+  <int value="13" label="CLOUD_PROJECT_NUMBER_IS_INVALID"/>
+  <int value="14" label="REQUEST_HASH_TOO_LONG"/>
+  <int value="15" label="CLIENT_TRANSIENT_ERROR"/>
+  <int value="16" label="INTEGRITY_TOKEN_PROVIDER_INVALID"/>
+  <int value="17" label="INTERNAL_ERROR"/>
+</enum>
+
 <enum name="AndroidWebViewNonEmbeddedMetricsParsingLogResult">
   <int value="0" label="Success"/>
   <int value="1" label="Malformed protobuf"/>
@@ -20172,14 +20201,6 @@
   <int value="29" label="FAILURE_UNKNOWN_ERROR"/>
 </enum>
 
-<enum name="EnterpriseCrdUserType">
-  <summary>Types of enterprise user connections.</summary>
-  <int value="0" label="kAutoLaunchedKiosk"/>
-  <int value="1" label="kAffiliatedUser"/>
-  <int value="2" label="kManagedGuestSession"/>
-  <int value="3" label="kManuallyLaunchedKiosk"/>
-</enum>
-
 <enum name="EnterpriseDeviceManagementStatus">
   <summary>
     Status codes produced by DeviceManagementService for requests made to the
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index 2053211..4a5e698 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -4868,6 +4868,202 @@
   </summary>
 </histogram>
 
+<histogram name="Android.WebView.MediaIntegrity.GetTokenCumulative"
+    units="calls" expires_after="2024-11-01">
+  <owner>pbirk@chromium.org</owner>
+  <owner>src/android_webview/OWNERS</owner>
+  <summary>
+    Counts the number of calls to 'requestToken' for a token provider. This
+    metric is counted individually for each token provider, and is emitted when
+    the request for a token is made.
+
+    The metric will show the usage pattern of token providers by individual
+    clients, by showing how many times they are used by the client
+
+    As a cumulative value, this value is incremented and logged for each
+    successive call. This means that when this histogram is logged for the Nth
+    time, it will already have been emitted for all values [1 ... N-1]. Before
+    analysing the histogram, it should be normalised by subtracting the raw
+    count of the next higher bucket from the bucket count. The interesting value
+    is &quot;how far did the app get&quot;. By subtracting the raw count of N+1
+    from bucket N, you remove all the counts where the app continued to emit the
+    next value in the sequence.
+  </summary>
+</histogram>
+
+<histogram name="Android.WebView.MediaIntegrity.GetTokenProviderCumulative"
+    units="calls" expires_after="2024-11-01">
+  <owner>pbirk@chromium.org</owner>
+  <owner>src/android_webview/OWNERS</owner>
+  <summary>
+    Counts the number of times the WebView Media Integrity GetTokenProvider
+    method has been called by web content since the app loaded.
+
+    This metric will be used to analyse the usage pattern of the Media Integrity
+    API in apps, specifically to understand if apps are causing multiple
+    sessions to be created, or if apps are instead creating a single webpage
+    that loads a single resource which instantiates the API once.
+
+    The metric is logged whenever a valid request is made from Web Content.
+
+    As a cumulative value, this value is incremented and logged for each
+    successive call. This means that when this histogram is logged for the Nth
+    time, it will already have been emitted for all values [1 ... N-1]. Before
+    analysing the histogram, it should be normalised by subtracting the raw
+    count of the next higher bucket from the bucket count. The interesting value
+    is &quot;how far did the app get&quot;. By subtracting the raw count of N+1
+    from bucket N, you remove all the counts where the app continued to emit the
+    next value in the sequence.
+  </summary>
+</histogram>
+
+<histogram name="Android.WebView.MediaIntegrity.GetTokenProviderStatus"
+    enum="AndroidWebViewMediaIntegrityStatus" expires_after="2024-11-01">
+  <owner>pbirk@chromium.org</owner>
+  <owner>src/android_webview/OWNERS</owner>
+  <summary>
+    Logs the status of calling the Play getTokenProvider API.
+
+    This histogram is logged on both successful responses and error responses.
+
+    The error enum corresponds to the StandardIntegrityErrorCode, but introduces
+    an UNKNOWN_ERROR code to catch situations where the Play client library
+    introduces a new error code.
+  </summary>
+</histogram>
+
+<histogram name="Android.WebView.MediaIntegrity.GetTokenStatus"
+    enum="AndroidWebViewMediaIntegrityStatus" expires_after="2024-11-01">
+  <owner>pbirk@chromium.org</owner>
+  <owner>src/android_webview/OWNERS</owner>
+  <summary>
+    Logs the status of calling the Play request token API on the
+    StandardIntegrityTokenProvider.
+
+    This histogram is logged on both successful responses and error responses.
+
+    The error enum corresponds to the StandardIntegrityErrorCode, but introduces
+    an UNKNOWN_ERROR code to catch situations where the Play client library
+    introduces a new error code.
+  </summary>
+</histogram>
+
+<histogram name="Android.WebView.MediaIntegrity.InvalidInteraction"
+    enum="AndroidWebViewMediaIntegrityInvalidInteraction"
+    expires_after="2024-11-01">
+  <owner>pbirk@chromium.org</owner>
+  <owner>src/android_webview/OWNERS</owner>
+  <summary>
+    Logs invalid calls from JavaScript to the Media Integrity API Java
+    implementation.
+
+    This histogram will be used to understand the extend to which clients are
+    bypassing the JavaScript client API and sending unexpected requests to Java.
+  </summary>
+</histogram>
+
+<histogram
+    name="Android.WebView.MediaIntegrity.TokenProviderCacheEvictionsCumulative"
+    units="evictions" expires_after="2024-11-01">
+  <owner>pbirk@chromium.org</owner>
+  <owner>src/android_webview/OWNERS</owner>
+  <summary>
+    Counts the number of times the token provider cache size has been exceeded,
+    or in other words how many times an existing token provider was evicted from
+    the cache in order to make room for a new one. The purpose of this histogram
+    is to measure the effectiveness of the current cache size parameter, and
+    will help inform if it should be changed, by giving us a histogram of how
+    much larger it should have been to avoid evictions.
+
+    This metric is logged every time a token provider is evicted.
+
+    As a cumulative value, this value is incremented and logged for each
+    successive call. This means that when this histogram is logged for the Nth
+    time, it will already have been emitted for all values [1 ... N-1]. Before
+    analysing the histogram, it should be normalised by subtracting the raw
+    count of the next higher bucket from the bucket count. The interesting value
+    is &quot;how far did the app get&quot;. By subtracting the raw count of N+1
+    from bucket N, you remove all the counts where the app continued to emit the
+    next value in the sequence.
+  </summary>
+</histogram>
+
+<histogram
+    name="Android.WebView.MediaIntegrity.TokenProviderCacheHitsCumulative"
+    units="hits" expires_after="2024-11-01">
+  <owner>pbirk@chromium.org</owner>
+  <owner>src/android_webview/OWNERS</owner>
+  <summary>
+    Counts the number of times a cached token provider is returned in response
+    to a request from web content.
+
+    This metric will help gauge the effectiveness of the token provider cache,
+    especially if the cache size is changed in the future. It serves as a way to
+    measure the savings on requests to Play caused by the cache.
+
+    The metric is logged when a cached token provider is found in the cache.
+
+    As a cumulative value, this value is incremented and logged for each
+    successive call. This means that when this histogram is logged for the Nth
+    time, it will already have been emitted for all values [1 ... N-1]. Before
+    analysing the histogram, it should be normalised by subtracting the raw
+    count of the next higher bucket from the bucket count. The interesting value
+    is &quot;how far did the app get&quot;. By subtracting the raw count of N+1
+    from bucket N, you remove all the counts where the app continued to emit the
+    next value in the sequence.
+  </summary>
+</histogram>
+
+<histogram
+    name="Android.WebView.MediaIntegrity.TokenProviderCacheMissesCumulative"
+    units="misses" expires_after="2024-11-01">
+  <owner>pbirk@chromium.org</owner>
+  <owner>src/android_webview/OWNERS</owner>
+  <summary>
+    Counts the number of cache misses for the token provider cache in an
+    application.
+
+    This metric will help gauge the effectiveness of the token provider cache,
+    especially if the cache size is changed in the future. It serves as a way to
+    measure the savings on requests to Play caused by the cache.
+
+    The metric is logged when a cached token provider is not found the cache.
+
+    As a cumulative value, this value is incremented and logged for each
+    successive call. This means that when this histogram is logged for the Nth
+    time, it will already have been emitted for all values [1 ... N-1]. Before
+    analysing the histogram, it should be normalised by subtracting the raw
+    count of the next higher bucket from the bucket count. The interesting value
+    is &quot;how far did the app get&quot;. By subtracting the raw count of N+1
+    from bucket N, you remove all the counts where the app continued to emit the
+    next value in the sequence.
+  </summary>
+</histogram>
+
+<histogram name="Android.WebView.MediaIntegrity.TokenProviderCreatedCumulative"
+    units="providers" expires_after="2024-11-01">
+  <owner>pbirk@chromium.org</owner>
+  <owner>src/android_webview/OWNERS</owner>
+  <summary>
+    Logs how many times a new TokenProvider is created by Play.
+
+    This metric will show how many different token providers are requested from
+    Play. With the token provider cache in place, this count is expected to be
+    lower than GetTokenProviderCumulative.
+
+    This metric is logged when a provider is returned from Play.
+
+    As a cumulative value, this value is incremented and logged for each
+    successive call. This means that when this histogram is logged for the Nth
+    time, it will already have been emitted for all values [1 ... N-1]. Before
+    analysing the histogram, it should be normalised by subtracting the raw
+    count of the next higher bucket from the bucket count. The interesting value
+    is &quot;how far did the app get&quot;. By subtracting the raw count of N+1
+    from bucket N, you remove all the counts where the app continued to emit the
+    next value in the sequence.
+  </summary>
+</histogram>
+
 <histogram name="Android.WebView.Memory.FunctorReclaim.OtherPrivateDirty"
     units="MB" expires_after="2024-04-28">
   <owner>lizeb@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml
index 2553d3b..0f0c36c 100644
--- a/tools/metrics/histograms/metadata/enterprise/histograms.xml
+++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -597,16 +597,6 @@
   <summary>Reports success/failure when a session is attempted.</summary>
 </histogram>
 
-<histogram name="Enterprise.DeviceRemoteCommand.Crd.SessionType"
-    enum="EnterpriseCrdUserType" expires_after="2024-04-28">
-  <owner>macinashutosh@google.com</owner>
-  <owner>chromeos-commercial-crd@google.com</owner>
-  <summary>
-    Reports the user type for the attempted session only when the result is
-    EnterpriseCrdSessionResultCode::SUCCESS.
-  </summary>
-</histogram>
-
 <histogram
     name="Enterprise.DeviceRemoteCommand.Crd.{Enterprise_CrdSessionType}.{Enterprise_UserSessionType}.Result"
     enum="EnterpriseCrdSessionResultCode" expires_after="2024-03-10">
diff --git a/tools/metrics/histograms/metadata/signin/histograms.xml b/tools/metrics/histograms/metadata/signin/histograms.xml
index 047b6edd..3379ca4 100644
--- a/tools/metrics/histograms/metadata/signin/histograms.xml
+++ b/tools/metrics/histograms/metadata/signin/histograms.xml
@@ -1429,7 +1429,7 @@
 </histogram>
 
 <histogram name="Signin.SignIn.Offered" enum="SigninAccessPoint"
-    expires_after="2023-12-19">
+    expires_after="2024-12-19">
   <owner>bsazonov@chromium.org</owner>
   <owner>dgn@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index c68d305..d2a74a70 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -21,8 +21,8 @@
             "full_remote_path": "perfetto-luci-artifacts/v38.0/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "51e7392dace538c5b7de551653e23b341ad2f723",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/8dc60d8a5484638134420511e0f54415853621c9/trace_processor_shell"
+            "hash": "a0a5e35797a177ab001400797a487094caacf872",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/9c4d5090f6a29c785d4e2a1a1f577bcc17eeb648/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/win/chromeexts/commands/view_command.cc b/tools/win/chromeexts/commands/view_command.cc
index b1ebd33..b1b3f0a 100644
--- a/tools/win/chromeexts/commands/view_command.cc
+++ b/tools/win/chromeexts/commands/view_command.cc
@@ -157,7 +157,7 @@
     return buffer;
   }
 
-  absl::optional<intptr_t> GetAddress() override {
+  std::optional<intptr_t> GetAddress() override {
     return view_block_.address();
   }
 
diff --git a/ui/gfx/mac/color_space_util.mm b/ui/gfx/mac/color_space_util.mm
index c31cb93a..2e396bb8 100644
--- a/ui/gfx/mac/color_space_util.mm
+++ b/ui/gfx/mac/color_space_util.mm
@@ -6,6 +6,7 @@
 
 #include <CoreMedia/CoreMedia.h>
 #include <CoreVideo/CoreVideo.h>
+#include <optional>
 
 #include "base/apple/foundation_util.h"
 #include "base/apple/scoped_cftyperef.h"
diff --git a/ui/webui/resources/cr_elements/cr_input/cr_input_style.css b/ui/webui/resources/cr_elements/cr_input/cr_input_style.css
index d8cf3a5..25bfbbf 100644
--- a/ui/webui/resources/cr_elements/cr_input/cr_input_style.css
+++ b/ui/webui/resources/cr_elements/cr_input/cr_input_style.css
@@ -5,6 +5,7 @@
 /* #css_wrapper_metadata_start
  * #type=style
  * #import=../cr_shared_vars.css.js
+ * #scheme=relative
  * #css_wrapper_metadata_end */
 
       :host {