Change net::CookieStore::SetCookiesCallback to return CookieInclusionStatus

Part of an effort to send better cookie information, and more specifically information as to *when* any *why* a cookie has been blocked from sending or storing.

Matt: //net
Maks: //service
Elly: //ios
Jochen: //chrome and //content
Torne: //android_webview


Bug: 856777
Change-Id: Ide937b3d00e0d1aca2d5155c21310fa072b022df
Reviewed-on: https://chromium-review.googlesource.com/c/1470931
Reviewed-by: Matt Menke <[email protected]>
Reviewed-by: Jochen Eisinger <[email protected]>
Reviewed-by: Richard Coles <[email protected]>
Reviewed-by: Maks Orlovich <[email protected]>
Reviewed-by: Elly Fong-Jones <[email protected]>
Commit-Queue: Aaron Tagliaboschi <[email protected]>
Cr-Commit-Position: refs/heads/master@{#634238}
diff --git a/android_webview/browser/cookie_manager.cc b/android_webview/browser/cookie_manager.cc
index cd5de81..04fb57a 100644
--- a/android_webview/browser/cookie_manager.cc
+++ b/android_webview/browser/cookie_manager.cc
@@ -129,6 +129,18 @@
   }
 }
 
+net::CookieStore::SetCookiesCallback StatusToBool(
+    base::OnceCallback<void(bool)> callback) {
+  return base::BindOnce(
+      [](base::OnceCallback<void(bool)> callback,
+         const net::CanonicalCookie::CookieInclusionStatus status) {
+        bool success =
+            (status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+        std::move(callback).Run(success);
+      },
+      std::move(callback));
+}
+
 }  // namespace
 
 namespace {
@@ -309,12 +321,13 @@
       replace_host.SetSchemeStr("https");
       GURL new_host = host.ReplaceComponents(replace_host);
       GetCookieStore()->SetCookieWithOptionsAsync(new_host, value, options,
-                                                  callback);
+                                                  StatusToBool(callback));
       return;
     }
   }
 
-  GetCookieStore()->SetCookieWithOptionsAsync(host, value, options, callback);
+  GetCookieStore()->SetCookieWithOptionsAsync(host, value, options,
+                                              StatusToBool(callback));
 }
 
 std::string CookieManager::GetCookie(const GURL& host) {
diff --git a/android_webview/browser/net/aw_cookie_store_wrapper.cc b/android_webview/browser/net/aw_cookie_store_wrapper.cc
index afa6edb..33fc9ac 100644
--- a/android_webview/browser/net/aw_cookie_store_wrapper.cc
+++ b/android_webview/browser/net/aw_cookie_store_wrapper.cc
@@ -96,7 +96,8 @@
   DCHECK(client_task_runner_->RunsTasksInCurrentSequence());
   PostTaskToCookieStoreTaskRunner(base::BindOnce(
       &SetCookieWithOptionsAsyncOnCookieThread, url, cookie_line, options,
-      CreateWrappedCallback<bool>(std::move(callback))));
+      CreateWrappedCallback<net::CanonicalCookie::CookieInclusionStatus>(
+          std::move(callback))));
 }
 
 void AwCookieStoreWrapper::SetCanonicalCookieAsync(
@@ -107,7 +108,9 @@
   DCHECK(client_task_runner_->RunsTasksInCurrentSequence());
   PostTaskToCookieStoreTaskRunner(base::BindOnce(
       &SetCanonicalCookieAsyncOnCookieThread, std::move(cookie), secure_source,
-      modify_http_only, CreateWrappedCallback<bool>(std::move(callback))));
+      modify_http_only,
+      CreateWrappedCallback<net::CanonicalCookie::CookieInclusionStatus>(
+          std::move(callback))));
 }
 
 void AwCookieStoreWrapper::GetCookieListWithOptionsAsync(
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 9cda7e1..a70122e 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -4805,8 +4805,8 @@
  public:
   ExtensionCookieCallback() : result_(false) {}
 
-  void SetCookieCallback(bool result) {
-    result_ = result;
+  void SetCookieCallback(net::CanonicalCookie::CookieInclusionStatus result) {
+    result_ = (result == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
   }
 
   void GetAllCookiesCallback(const net::CookieList& list,
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index 8abb1b1..483ad51 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -371,11 +371,14 @@
       normalized_domain, path, std::move(callback)));
 }
 
-void CookieSetOnIO(std::unique_ptr<SetCookieCallback> callback, bool success) {
+void CookieSetOnIO(std::unique_ptr<SetCookieCallback> callback,
+                   net::CanonicalCookie::CookieInclusionStatus status) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                           base::BindOnce(&SetCookieCallback::sendSuccess,
-                                          std::move(callback), success));
+  base::PostTaskWithTraits(
+      FROM_HERE, {BrowserThread::UI},
+      base::BindOnce(
+          &SetCookieCallback::sendSuccess, std::move(callback),
+          (status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE)));
 }
 
 void DeleteFilteredCookies(network::mojom::CookieManager* cookie_manager,
@@ -445,9 +448,11 @@
       base::Time(), secure, http_only, css, net::COOKIE_PRIORITY_DEFAULT);
 }
 
-void SetCookieOnIO(net::URLRequestContextGetter* context_getter,
-                   std::unique_ptr<net::CanonicalCookie> cookie,
-                   base::OnceCallback<void(bool)> callback) {
+void SetCookieOnIO(
+    net::URLRequestContextGetter* context_getter,
+    std::unique_ptr<net::CanonicalCookie> cookie,
+    base::OnceCallback<void(net::CanonicalCookie::CookieInclusionStatus)>
+        callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
   net::URLRequestContext* request_context =
@@ -474,10 +479,12 @@
   base::RepeatingClosure barrier_closure =
       base::BarrierClosure(cookies.size(), std::move(callback));
   for (auto& cookie : cookies) {
-    SetCookieOnIO(context_getter, std::move(cookie),
-                  base::BindOnce([](base::RepeatingClosure callback,
-                                    bool) { callback.Run(); },
-                                 barrier_closure));
+    SetCookieOnIO(
+        context_getter, std::move(cookie),
+        base::BindOnce(
+            [](base::RepeatingClosure callback,
+               net::CanonicalCookie::CookieInclusionStatus) { callback.Run(); },
+            barrier_closure));
   }
 }
 
diff --git a/content/browser/frame_host/render_frame_message_filter.cc b/content/browser/frame_host/render_frame_message_filter.cc
index 52596270..62f00997 100644
--- a/content/browser/frame_host/render_frame_message_filter.cc
+++ b/content/browser/frame_host/render_frame_message_filter.cc
@@ -620,7 +620,7 @@
 
   // |callback| needs to be fired even if network process crashes as it's for
   // sync IPC.
-  net::CookieStore::SetCookiesCallback net_callback =
+  base::OnceCallback<void(bool)> net_callback =
       mojo::WrapCallbackWithDefaultInvokeIfNotRun(
           base::BindOnce([](SetCookieCallback callback,
                             bool success) { std::move(callback).Run(); },
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index ba78ffd..41a5dcf 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -176,8 +176,8 @@
     await_completion_.Notify();
   }
 
-  void SetCookieCallback(bool result) {
-    ASSERT_TRUE(result);
+  void SetCookieCallback(CanonicalCookie::CookieInclusionStatus result) {
+    ASSERT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, result);
     await_completion_.Notify();
   }
 
diff --git a/ios/net/cookies/cookie_store_ios.h b/ios/net/cookies/cookie_store_ios.h
index e7bb38f..9cf07461 100644
--- a/ios/net/cookies/cookie_store_ios.h
+++ b/ios/net/cookies/cookie_store_ios.h
@@ -267,7 +267,8 @@
   // asynchronous cache update (using UpdateCachesFromCookieMonster()) and
   // calling the provided callback.
 
-  void UpdateCachesAfterSet(SetCookiesCallback callback, bool success);
+  void UpdateCachesAfterSet(SetCookiesCallback callback,
+                            net::CanonicalCookie::CookieInclusionStatus status);
   void UpdateCachesAfterDelete(DeleteCallback callback, uint32_t num_deleted);
   void UpdateCachesAfterClosure(base::OnceClosure callback);
 
diff --git a/ios/net/cookies/cookie_store_ios.mm b/ios/net/cookies/cookie_store_ios.mm
index 3cbabb6..d2d85815 100644
--- a/ios/net/cookies/cookie_store_ios.mm
+++ b/ios/net/cookies/cookie_store_ios.mm
@@ -136,13 +136,13 @@
 }
 
 // Returns an empty closure if |callback| is null callback or binds the
-// callback to |success|.
+// callback to |status|.
 base::OnceClosure BindSetCookiesCallback(
     CookieStoreIOS::SetCookiesCallback* callback,
-    bool success) {
+    net::CanonicalCookie::CookieInclusionStatus status) {
   base::OnceClosure set_callback;
   if (!callback->is_null()) {
-    set_callback = base::BindOnce(std::move(*callback), success);
+    set_callback = base::BindOnce(std::move(*callback), status);
   }
   return set_callback;
 }
@@ -298,7 +298,10 @@
   bool has_explicit_domain = HasExplicitDomain(cookie_line);
   bool has_valid_domain =
       net::cookie_util::GetCookieDomainWithString(url, domain_string, &dummy);
-  // A cookie can be set if all of:
+  net::CanonicalCookie::CookieInclusionStatus status =
+      net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+
+  // A cookie can be set if all of the following conditions are met:
   //   a) The cookie line is well-formed
   //   b) The Domain attribute, if present, was not malformed
   //   c) At least one of:
@@ -306,17 +309,33 @@
   //          from the URL, or
   //       2) The cookie had an explicit Domain for which the URL is allowed
   //          to set cookies.
-  bool success = (cookie != nil) && !domain_string.empty() &&
-                 (!has_explicit_domain || has_valid_domain);
 
-  if (success) {
-    system_store_->SetCookieAsync(cookie,
-                                  BindSetCookiesCallback(&callback, true));
+  // If |cookie| is nil, the cookie line was not well-formed.
+  if (cookie == nil)
+    status =
+        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE;
+
+  // If |domain_string| is empty, the domain was not well-formed.
+  if (domain_string.empty())
+    status =
+        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN;
+
+  // If the cookie had an explicit domain and it's not a domain it's allowed to
+  // set cookies to.
+  if (has_explicit_domain && !has_valid_domain)
+    status =
+        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN;
+
+  if (status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE) {
+    system_store_->SetCookieAsync(
+        cookie,
+        BindSetCookiesCallback(
+            &callback, net::CanonicalCookie::CookieInclusionStatus::INCLUDE));
     return;
   }
 
   if (!callback.is_null())
-    std::move(callback).Run(false);
+    std::move(callback).Run(status);
 }
 
 void CookieStoreIOS::SetCanonicalCookieAsync(
@@ -337,20 +356,24 @@
 
   if (cookie->IsSecure() && !secure_source) {
     if (!callback.is_null())
-      std::move(callback).Run(false);
+      std::move(callback).Run(
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY);
     return;
   }
 
   NSHTTPCookie* ns_cookie = SystemCookieFromCanonicalCookie(*cookie.get());
 
   if (ns_cookie != nil) {
-    system_store_->SetCookieAsync(ns_cookie, &cookie->CreationDate(),
-                                  BindSetCookiesCallback(&callback, true));
+    system_store_->SetCookieAsync(
+        ns_cookie, &cookie->CreationDate(),
+        BindSetCookiesCallback(
+            &callback, net::CanonicalCookie::CookieInclusionStatus::INCLUDE));
     return;
   }
 
   if (!callback.is_null())
-    std::move(callback).Run(false);
+    std::move(callback).Run(
+        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
 }
 
 void CookieStoreIOS::GetCookieListWithOptionsAsync(
@@ -721,13 +744,14 @@
   }
 }
 
-void CookieStoreIOS::UpdateCachesAfterSet(SetCookiesCallback callback,
-                                          bool success) {
+void CookieStoreIOS::UpdateCachesAfterSet(
+    SetCookiesCallback callback,
+    net::CanonicalCookie::CookieInclusionStatus status) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  if (success)
+  if (status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE)
     UpdateCachesFromCookieMonster();
   if (!callback.is_null())
-    std::move(callback).Run(success);
+    std::move(callback).Run(status);
 }
 
 void CookieStoreIOS::UpdateCachesAfterDelete(DeleteCallback callback,
diff --git a/ios/net/cookies/cookie_store_ios_test_util.mm b/ios/net/cookies/cookie_store_ios_test_util.mm
index 4994b8f..426c0527 100644
--- a/ios/net/cookies/cookie_store_ios_test_util.mm
+++ b/ios/net/cookies/cookie_store_ios_test_util.mm
@@ -9,6 +9,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -23,12 +24,6 @@
 
 namespace net {
 
-namespace {
-
-void IgnoreBoolean(bool not_used) {}
-
-}  // namespace
-
 #pragma mark -
 #pragma mark TestPersistentCookieStore
 
@@ -141,7 +136,7 @@
   net::CookieOptions options;
   options.set_include_httponly();
   store->SetCookieWithOptionsAsync(url, cookie_line, options,
-                                   base::Bind(&IgnoreBoolean));
+                                   base::DoNothing());
   net::CookieStoreIOS::NotifySystemCookiesChanged();
   // Wait until the flush is posted.
   base::RunLoop().RunUntilIdle();
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc
index 91611ac..aaa27709 100644
--- a/net/cookies/canonical_cookie.cc
+++ b/net/cookies/canonical_cookie.cc
@@ -189,17 +189,27 @@
     const GURL& url,
     const std::string& cookie_line,
     const base::Time& creation_time,
-    const CookieOptions& options) {
+    const CookieOptions& options,
+    CookieInclusionStatus* status) {
+  // Put a pointer on the stack so the rest of the function can assign to it if
+  // the default nullptr is passed in.
+  CookieInclusionStatus blank_status;
+  if (status == nullptr) {
+    status = &blank_status;
+  }
+
   ParsedCookie parsed_cookie(cookie_line);
 
   if (!parsed_cookie.IsValid()) {
     VLOG(net::cookie_util::kVlogSetCookies) << "WARNING: Couldn't parse cookie";
+    *status = CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE;
     return nullptr;
   }
 
   if (options.exclude_httponly() && parsed_cookie.IsHttpOnly()) {
     VLOG(net::cookie_util::kVlogSetCookies)
         << "Create() is not creating a httponly cookie";
+    *status = CookieInclusionStatus::EXCLUDE_HTTP_ONLY;
     return nullptr;
   }
 
@@ -207,6 +217,7 @@
   if (!GetCookieDomain(url, parsed_cookie, &cookie_domain)) {
     VLOG(net::cookie_util::kVlogSetCookies)
         << "Create() failed to get a cookie domain";
+    *status = CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN;
     return nullptr;
   }
 
@@ -217,6 +228,7 @@
   if (parsed_cookie.IsSecure() && !url.SchemeIsCryptographic()) {
     VLOG(net::cookie_util::kVlogSetCookies)
         << "Create() is trying to create a secure cookie from an insecure URL";
+    *status = CookieInclusionStatus::EXCLUDE_SECURE_ONLY;
     return nullptr;
   }
 
@@ -238,6 +250,7 @@
   if (!is_cookie_valid) {
     VLOG(net::cookie_util::kVlogSetCookies)
         << "Create() failed because the cookie violated prefix rules.";
+    *status = CookieInclusionStatus::EXCLUDE_INVALID_PREFIX;
     return nullptr;
   }
 
@@ -247,6 +260,7 @@
       parsed_cookie.IsHttpOnly(), parsed_cookie.SameSite(),
       parsed_cookie.Priority()));
   DCHECK(cc->IsCanonical());
+  *status = CookieInclusionStatus::INCLUDE;
   return cc;
 }
 
diff --git a/net/cookies/canonical_cookie.h b/net/cookies/canonical_cookie.h
index 39413d78..2fca15f 100644
--- a/net/cookies/canonical_cookie.h
+++ b/net/cookies/canonical_cookie.h
@@ -22,6 +22,8 @@
 
 class ParsedCookie;
 
+struct CookieWithStatus;
+
 class NET_EXPORT CanonicalCookie {
  public:
   CanonicalCookie();
@@ -47,14 +49,36 @@
 
   // Supports the default copy constructor.
 
+  // This enum represents if a cookie was included or excluded, and if excluded
+  // why.
+  enum class CookieInclusionStatus {
+    INCLUDE = 0,
+    EXCLUDE_HTTP_ONLY,
+    EXCLUDE_SECURE_ONLY,
+    EXCLUDE_DOMAIN_MISMATCH,
+    EXCLUDE_NOT_ON_PATH,
+    EXCLUDE_SAMESITE_STRICT,
+    EXCLUDE_SAMESITE_LAX,
+
+    // Statuses specific to setting cookies
+    EXCLUDE_FAILURE_TO_STORE,
+    EXCLUDE_NONCOOKIEABLE_SCHEME,
+    EXCLUDE_OVERWRITE_SECURE,
+    EXCLUDE_OVERWRITE_HTTP_ONLY,
+    EXCLUDE_INVALID_DOMAIN,
+    EXCLUDE_INVALID_PREFIX
+  };
+
   // Creates a new |CanonicalCookie| from the |cookie_line| and the
   // |creation_time|.  Canonicalizes and validates inputs. May return NULL if
-  // an attribute value is invalid.  |creation_time| may not be null.
+  // an attribute value is invalid.  |creation_time| may not be null. Sets
+  // optional |status| to the relevent CookieInclusionStatus if provided
   static std::unique_ptr<CanonicalCookie> Create(
       const GURL& url,
       const std::string& cookie_line,
       const base::Time& creation_time,
-      const CookieOptions& options);
+      const CookieOptions& options,
+      CookieInclusionStatus* status = nullptr);
 
   // Create a canonical cookie based on sanitizing the passed inputs in the
   // context of the passed URL.  Returns a null unique pointer if the inputs
@@ -141,18 +165,6 @@
   // section 5.1.3 of RFC 6265.
   bool IsDomainMatch(const std::string& host) const;
 
-  // This enum represents if a cookie was included or excluded, and if excluded
-  // why.
-  enum class CookieInclusionStatus {
-    INCLUDE = 0,
-    EXCLUDE_HTTP_ONLY,
-    EXCLUDE_SECURE_ONLY,
-    EXCLUDE_DOMAIN_MISMATCH,
-    EXCLUDE_NOT_ON_PATH,
-    EXCLUDE_SAMESITE_STRICT,
-    EXCLUDE_SAMESITE_LAX
-  };
-
   // Returns if the cookie should be included (and if not, why) for the given
   // request |url| using the CookieInclusionStatus enum. HTTP only cookies can
   // be filter by using appropriate cookie |options|. PLEASE NOTE that this
@@ -246,8 +258,6 @@
   CookiePriority priority_;
 };
 
-typedef std::vector<CanonicalCookie> CookieList;
-
 // These enable us to pass along a list of excluded cookie with the reason they
 // were excluded
 struct CookieWithStatus {
@@ -255,6 +265,8 @@
   CanonicalCookie::CookieInclusionStatus status;
 };
 
+typedef std::vector<CanonicalCookie> CookieList;
+
 typedef std::vector<CookieWithStatus> CookieStatusList;
 
 }  // namespace net
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc
index 87a47908..0b2420fe 100644
--- a/net/cookies/canonical_cookie_unittest.cc
+++ b/net/cookies/canonical_cookie_unittest.cc
@@ -97,13 +97,19 @@
   // Test creating secure cookies.
   // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone disallows
   // insecure URLs from setting secure cookies.
-  cookie = CanonicalCookie::Create(url, "A=2; Secure", creation_time, options);
+  CanonicalCookie::CookieInclusionStatus status;
+  cookie = CanonicalCookie::Create(url, "A=2; Secure", creation_time, options,
+                                   &status);
   EXPECT_FALSE(cookie.get());
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
+            status);
 
   // Test creating http only cookies.
-  cookie =
-      CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options);
+  cookie = CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options,
+                                   &status);
   EXPECT_FALSE(cookie.get());
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY, status);
+
   CookieOptions httponly_options;
   httponly_options.set_include_httponly();
   cookie = CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time,
@@ -173,21 +179,26 @@
   GURL url("http://www.example.com/test/foo.html");
   base::Time now = base::Time::Now();
   CookieOptions options;
+  CanonicalCookie::CookieInclusionStatus status;
 
   options.set_exclude_httponly();
   std::unique_ptr<CanonicalCookie> cookie =
-      CanonicalCookie::Create(url, "A=2; HttpOnly", now, options);
+      CanonicalCookie::Create(url, "A=2; HttpOnly", now, options, &status);
   EXPECT_EQ(nullptr, cookie.get());
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY, status);
 }
 
 TEST(CanonicalCookieTest, CreateWithInvalidDomain) {
   GURL url("http://www.example.com/test/foo.html");
   base::Time now = base::Time::Now();
   CookieOptions options;
+  CanonicalCookie::CookieInclusionStatus status;
 
-  std::unique_ptr<CanonicalCookie> cookie =
-      CanonicalCookie::Create(url, "A=2; Domain=wrongdomain.com", now, options);
+  std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
+      url, "A=2; Domain=wrongdomain.com", now, options, &status);
   EXPECT_EQ(nullptr, cookie.get());
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN,
+            status);
 }
 
 TEST(CanonicalCookieTest, EmptyExpiry) {
@@ -575,12 +586,16 @@
   GURL http_url("http://www.example.test");
   base::Time creation_time = base::Time::Now();
   CookieOptions options;
+  CanonicalCookie::CookieInclusionStatus status;
 
   // A __Secure- cookie must be Secure.
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B", creation_time,
-                                       options));
+                                       options, &status));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+            status);
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B; httponly",
-                                       creation_time, options));
+                                       creation_time, options, &status));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY, status);
 
   // A typoed prefix does not have to be Secure.
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__secure-A=B; Secure",
@@ -594,7 +609,9 @@
 
   // A __Secure- cookie can't be set on a non-secure origin.
   EXPECT_FALSE(CanonicalCookie::Create(http_url, "__Secure-A=B; Secure",
-                                       creation_time, options));
+                                       creation_time, options, &status));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
+            status);
 }
 
 TEST(CanonicalCookieTest, HostCookiePrefix) {
@@ -603,36 +620,52 @@
   base::Time creation_time = base::Time::Now();
   CookieOptions options;
   std::string domain = https_url.host();
+  CanonicalCookie::CookieInclusionStatus status;
 
   // A __Host- cookie must be Secure.
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B;", creation_time,
-                                       options));
+                                       options, &status));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+            status);
   EXPECT_FALSE(CanonicalCookie::Create(
       https_url, "__Host-A=B; Domain=" + domain + "; Path=/;", creation_time,
-      options));
+      options, &status));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+            status);
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure;",
                                       creation_time, options));
 
   // A __Host- cookie must be set from a secure scheme.
   EXPECT_FALSE(CanonicalCookie::Create(
       http_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
-      creation_time, options));
+      creation_time, options, &status));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
+            status);
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure;",
                                       creation_time, options));
 
   // A __Host- cookie can't have a Domain.
   EXPECT_FALSE(CanonicalCookie::Create(
       https_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
-      creation_time, options));
+      creation_time, options, &status));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+            status);
   EXPECT_FALSE(CanonicalCookie::Create(
       https_url, "__Host-A=B; Domain=" + domain + "; Secure;", creation_time,
-      options));
+      options, &status));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+            status);
 
   // A __Host- cookie must have a Path of "/".
-  EXPECT_FALSE(CanonicalCookie::Create(
-      https_url, "__Host-A=B; Path=/foo; Secure;", creation_time, options));
+  EXPECT_FALSE(CanonicalCookie::Create(https_url,
+                                       "__Host-A=B; Path=/foo; Secure;",
+                                       creation_time, options, &status));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+            status);
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B; Secure;",
-                                       creation_time, options));
+                                       creation_time, options, &status));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+            status);
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Secure; Path=/;",
                                       creation_time, options));
 
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index ba98b04..2152392 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -705,22 +705,29 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 
   if (!HasCookieableScheme(url)) {
-    MaybeRunCookieCallback(std::move(callback), false);
+    MaybeRunCookieCallback(
+        std::move(callback),
+        CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME);
     return;
   }
 
   VLOG(net::cookie_util::kVlogSetCookies)
       << "SetCookie() line: " << cookie_line;
 
-  std::unique_ptr<CanonicalCookie> cc(
-      CanonicalCookie::Create(url, cookie_line, Time::Now(), options));
+  CanonicalCookie::CookieInclusionStatus status;
 
-  if (!cc.get()) {
+  std::unique_ptr<CanonicalCookie> cc(
+      CanonicalCookie::Create(url, cookie_line, Time::Now(), options, &status));
+
+  if (status != CanonicalCookie::CookieInclusionStatus::INCLUDE) {
+    DCHECK(!cc);
     VLOG(net::cookie_util::kVlogSetCookies)
         << "WARNING: Failed to allocate CanonicalCookie";
-    MaybeRunCookieCallback(std::move(callback), false);
+    MaybeRunCookieCallback(std::move(callback), status);
     return;
   }
+
+  DCHECK(cc);
   SetCanonicalCookie(std::move(cc), url.SchemeIsCryptographic(),
                      !options.exclude_httponly(), std::move(callback));
 }
@@ -1059,7 +1066,7 @@
   }
 }
 
-bool CookieMonster::DeleteAnyEquivalentCookie(
+CanonicalCookie::CookieInclusionStatus CookieMonster::DeleteAnyEquivalentCookie(
     const std::string& key,
     const CanonicalCookie& ecc,
     bool source_secure,
@@ -1156,7 +1163,13 @@
     }
   }
 
-  return skipped_httponly || skipped_secure_cookie;
+  if (skipped_httponly)
+    return CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY;
+
+  if (skipped_secure_cookie)
+    return CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE;
+
+  return CanonicalCookie::CookieInclusionStatus::INCLUDE;
 }
 
 CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
@@ -1194,9 +1207,17 @@
                                        SetCookiesCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  if ((cc->IsSecure() && !secure_source) ||
-      (cc->IsHttpOnly() && !modify_http_only)) {
-    MaybeRunCookieCallback(std::move(callback), false);
+  if ((cc->IsSecure() && !secure_source)) {
+    MaybeRunCookieCallback(
+        std::move(callback),
+        CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY);
+    return;
+  }
+
+  if ((cc->IsHttpOnly() && !modify_http_only)) {
+    MaybeRunCookieCallback(
+        std::move(callback),
+        CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY);
     return;
   }
 
@@ -1210,15 +1231,19 @@
   bool already_expired = cc->IsExpired(creation_date);
 
   base::Time creation_date_to_inherit;
-  if (DeleteAnyEquivalentCookie(key, *cc, secure_source, !modify_http_only,
-                                already_expired, &creation_date_to_inherit)) {
+
+  CanonicalCookie::CookieInclusionStatus status =
+      DeleteAnyEquivalentCookie(key, *cc, secure_source, !modify_http_only,
+                                already_expired, &creation_date_to_inherit);
+
+  if (status != CanonicalCookie::CookieInclusionStatus::INCLUDE) {
     std::string error;
     error =
         "SetCookie() not clobbering httponly cookie or secure cookie for "
         "insecure scheme";
 
     VLOG(net::cookie_util::kVlogSetCookies) << error;
-    MaybeRunCookieCallback(std::move(callback), false);
+    MaybeRunCookieCallback(std::move(callback), status);
     return;
   }
 
@@ -1266,7 +1291,8 @@
   // and we will purge the expired cookies in GetCookies().
   GarbageCollect(creation_date, key);
 
-  MaybeRunCookieCallback(std::move(callback), true);
+  MaybeRunCookieCallback(std::move(callback),
+                         CanonicalCookie::CookieInclusionStatus::INCLUDE);
 }
 
 void CookieMonster::SetAllCookies(CookieList list,
@@ -1299,7 +1325,8 @@
   // shouldn't have a return value.  But it should also be deleted (see
   // https://codereview.chromium.org/2882063002/#msg64), which would
   // solve the return value problem.
-  MaybeRunCookieCallback(std::move(callback), true);
+  MaybeRunCookieCallback(std::move(callback),
+                         CanonicalCookie::CookieInclusionStatus::INCLUDE);
 }
 
 void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc,
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h
index 151511f5..680df39 100644
--- a/net/cookies/cookie_monster.h
+++ b/net/cookies/cookie_monster.h
@@ -463,12 +463,13 @@
   // |creation_date_to_inherit| will be set to that cookie's creation date.
   //
   // NOTE: There should never be more than a single matching equivalent cookie.
-  bool DeleteAnyEquivalentCookie(const std::string& key,
-                                 const CanonicalCookie& ecc,
-                                 bool source_secure,
-                                 bool skip_httponly,
-                                 bool already_expired,
-                                 base::Time* creation_date_to_inherit);
+  CanonicalCookie::CookieInclusionStatus DeleteAnyEquivalentCookie(
+      const std::string& key,
+      const CanonicalCookie& ecc,
+      bool source_secure,
+      bool skip_httponly,
+      bool already_expired,
+      base::Time* creation_date_to_inherit);
 
   // Inserts |cc| into cookies_. Returns an iterator that points to the inserted
   // cookie in cookies_. Guarantee: all iterators to cookies_ remain valid.
diff --git a/net/cookies/cookie_monster_perftest.cc b/net/cookies/cookie_monster_perftest.cc
index 9636629..b7c90ec 100644
--- a/net/cookies/cookie_monster_perftest.cc
+++ b/net/cookies/cookie_monster_perftest.cc
@@ -68,8 +68,8 @@
   }
 
  private:
-  void Run(bool success) {
-    EXPECT_TRUE(success);
+  void Run(CanonicalCookie::CookieInclusionStatus status) {
+    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
     CookieTestCallback::Run();
   }
   CookieOptions options_;
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc
index ad22e87e..e20ef24 100644
--- a/net/cookies/cookie_monster_unittest.cc
+++ b/net/cookies/cookie_monster_unittest.cc
@@ -147,7 +147,8 @@
     GetCookieListCallback callback;
     cm->GetCookieListWithOptionsAsync(
         url, options,
-        base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
+        base::BindOnce(&GetCookieListCallback::Run,
+                       base::Unretained(&callback)));
     callback.WaitUntilDone();
     return callback.cookies();
   }
@@ -168,12 +169,13 @@
 
   bool SetAllCookies(CookieMonster* cm, const CookieList& list) {
     DCHECK(cm);
-    ResultSavingCookieCallback<bool> callback;
-    cm->SetAllCookiesAsync(list,
-                           base::Bind(&ResultSavingCookieCallback<bool>::Run,
-                                      base::Unretained(&callback)));
+    ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback;
+    cm->SetAllCookiesAsync(
+        list, base::BindOnce(&ResultSavingCookieCallback<
+                                 CanonicalCookie::CookieInclusionStatus>::Run,
+                             base::Unretained(&callback)));
     callback.WaitUntilDone();
-    return callback.result();
+    return callback.result() == CanonicalCookie::CookieInclusionStatus::INCLUDE;
   }
 
   bool SetCookieWithCreationTime(CookieMonster* cm,
@@ -182,15 +184,16 @@
                                  base::Time creation_time) {
     DCHECK(cm);
     DCHECK(!creation_time.is_null());
-    ResultSavingCookieCallback<bool> callback;
+    ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback;
     cm->SetCanonicalCookieAsync(
         CanonicalCookie::Create(url, cookie_line, creation_time,
                                 CookieOptions()),
         url.SchemeIsCryptographic(), /* modify_httponly = */ false,
-        base::BindOnce(&ResultSavingCookieCallback<bool>::Run,
+        base::BindOnce(&ResultSavingCookieCallback<
+                           CanonicalCookie::CookieInclusionStatus>::Run,
                        base::Unretained(&callback)));
     callback.WaitUntilDone();
-    return callback.result();
+    return callback.result() == CanonicalCookie::CookieInclusionStatus::INCLUDE;
   }
 
   uint32_t DeleteAllCreatedInTimeRange(CookieMonster* cm,
@@ -211,8 +214,8 @@
     ResultSavingCookieCallback<uint32_t> callback;
     cm->DeleteAllMatchingInfoAsync(
         std::move(delete_info),
-        base::Bind(&ResultSavingCookieCallback<uint32_t>::Run,
-                   base::Unretained(&callback)));
+        base::BindOnce(&ResultSavingCookieCallback<uint32_t>::Run,
+                       base::Unretained(&callback)));
     callback.WaitUntilDone();
     return callback.result();
   }
@@ -1096,11 +1099,14 @@
 
   WaitForLoadCall();
 
-  EXPECT_CALL(set_cookies_callback, Run(true))
+  EXPECT_CALL(set_cookies_callback,
+              Run(CanonicalCookie::CookieInclusionStatus::INCLUDE))
       .WillOnce(SetCookieAction(&cookie_monster(), http_www_foo_.url(), "X=Y",
                                 &set_cookies_callback));
   base::RunLoop loop;
-  EXPECT_CALL(set_cookies_callback, Run(true)).WillOnce(QuitRunLoop(&loop));
+  EXPECT_CALL(set_cookies_callback,
+              Run(CanonicalCookie::CookieInclusionStatus::INCLUDE))
+      .WillOnce(QuitRunLoop(&loop));
 
   CompleteLoading();
   loop.Run();
@@ -1123,11 +1129,14 @@
 
   WaitForLoadCall();
 
-  EXPECT_CALL(set_cookies_callback, Run(true))
+  EXPECT_CALL(set_cookies_callback,
+              Run(CanonicalCookie::CookieInclusionStatus::INCLUDE))
       .WillOnce(
           SetAllCookiesAction(&cookie_monster(), list, &set_cookies_callback));
   base::RunLoop loop;
-  EXPECT_CALL(set_cookies_callback, Run(true)).WillOnce(QuitRunLoop(&loop));
+  EXPECT_CALL(set_cookies_callback,
+              Run(CanonicalCookie::CookieInclusionStatus::INCLUDE))
+      .WillOnce(QuitRunLoop(&loop));
 
   CompleteLoading();
   loop.Run();
@@ -1330,7 +1339,8 @@
       .WillOnce(GetCookieListForUrlWithOptionsAction(
           &cookie_monster(), http_www_foo_.url(),
           &get_cookie_list_callback_deferred));
-  EXPECT_CALL(set_cookies_callback, Run(true));
+  EXPECT_CALL(set_cookies_callback,
+              Run(CanonicalCookie::CookieInclusionStatus::INCLUDE));
   base::RunLoop loop;
   EXPECT_CALL(get_cookie_list_callback_deferred,
               Run(MatchesCookieLine("A=B; X=1"), testing::_))
@@ -1546,10 +1556,16 @@
   GURL foo_url("foo://host/path");
   GURL http_url("http://host/path");
 
-  EXPECT_TRUE(SetCookie(cm.get(), http_url, "x=1"));
-  EXPECT_FALSE(SetCookie(cm.get(), foo_url, "x=1"));
-  EXPECT_TRUE(SetCookie(cm_foo.get(), foo_url, "x=1"));
-  EXPECT_FALSE(SetCookie(cm_foo.get(), http_url, "x=1"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), http_url, "x=1"));
+  EXPECT_EQ(
+      CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
+      SetCookieReturnStatus(cm.get(), foo_url, "x=1"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm_foo.get(), foo_url, "x=1"));
+  EXPECT_EQ(
+      CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
+      SetCookieReturnStatus(cm_foo.get(), http_url, "x=1"));
 }
 
 TEST_F(CookieMonsterTest, GetAllCookiesForURL) {
@@ -2267,16 +2283,18 @@
       new CookieMonster(store.get(), nullptr, &net_log_));
 
   // Get all cookies task that queues a task to set a cookie when executed.
-  ResultSavingCookieCallback<bool> set_cookie_callback;
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
+      set_cookie_callback;
   cm->SetCookieWithOptionsAsync(
       kUrl, "a=b", CookieOptions(),
-      base::Bind(&ResultSavingCookieCallback<bool>::Run,
-                 base::Unretained(&set_cookie_callback)));
+      base::BindOnce(&ResultSavingCookieCallback<
+                         CanonicalCookie::CookieInclusionStatus>::Run,
+                     base::Unretained(&set_cookie_callback)));
 
   GetCookieListCallback get_cookie_list_callback1;
   cm->GetAllCookiesAsync(
-      base::Bind(&GetCookieListCallback::Run,
-                 base::Unretained(&get_cookie_list_callback1)));
+      base::BindOnce(&GetCookieListCallback::Run,
+                     base::Unretained(&get_cookie_list_callback1)));
 
   // Two load events should have been queued.
   ASSERT_EQ(2u, store->commands().size());
@@ -2291,7 +2309,8 @@
   // The tasks should run in order, and the get should see the cookies.
 
   set_cookie_callback.WaitUntilDone();
-  EXPECT_TRUE(set_cookie_callback.result());
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            set_cookie_callback.result());
 
   get_cookie_list_callback1.WaitUntilDone();
   EXPECT_EQ(1u, get_cookie_list_callback1.cookies().size());
@@ -2304,8 +2323,8 @@
   // The just set cookie should still be in the store.
   GetCookieListCallback get_cookie_list_callback2;
   cm->GetAllCookiesAsync(
-      base::Bind(&GetCookieListCallback::Run,
-                 base::Unretained(&get_cookie_list_callback2)));
+      base::BindOnce(&GetCookieListCallback::Run,
+                     base::Unretained(&get_cookie_list_callback2)));
   get_cookie_list_callback2.WaitUntilDone();
   EXPECT_EQ(1u, get_cookie_list_callback2.cookies().size());
 }
@@ -2322,14 +2341,14 @@
       new CookieMonster(store.get(), nullptr, &net_log_));
 
   ResultSavingCookieCallback<uint32_t> delete_callback;
-  cm->DeleteAllAsync(base::Bind(&ResultSavingCookieCallback<uint32_t>::Run,
-                                base::Unretained(&delete_callback)));
+  cm->DeleteAllAsync(base::BindOnce(&ResultSavingCookieCallback<uint32_t>::Run,
+                                    base::Unretained(&delete_callback)));
 
   GetCookieListCallback get_cookie_list_callback;
   cm->GetCookieListWithOptionsAsync(
       kUrl, CookieOptions(),
-      base::Bind(&GetCookieListCallback::Run,
-                 base::Unretained(&get_cookie_list_callback)));
+      base::BindOnce(&GetCookieListCallback::Run,
+                     base::Unretained(&get_cookie_list_callback)));
 
   // Only the main load should have been queued.
   ASSERT_EQ(1u, store->commands().size());
@@ -2364,19 +2383,21 @@
 
   GetCookieListCallback get_cookie_list_callback1;
   cm->GetAllCookiesAsync(
-      base::Bind(&GetCookieListCallback::Run,
-                 base::Unretained(&get_cookie_list_callback1)));
+      base::BindOnce(&GetCookieListCallback::Run,
+                     base::Unretained(&get_cookie_list_callback1)));
 
-  ResultSavingCookieCallback<bool> set_cookie_callback;
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
+      set_cookie_callback;
   cm->SetCookieWithOptionsAsync(
       kUrl, "a=b", CookieOptions(),
-      base::Bind(&ResultSavingCookieCallback<bool>::Run,
-                 base::Unretained(&set_cookie_callback)));
+      base::BindOnce(&ResultSavingCookieCallback<
+                         CanonicalCookie::CookieInclusionStatus>::Run,
+                     base::Unretained(&set_cookie_callback)));
 
   GetCookieListCallback get_cookie_list_callback2;
   cm->GetAllCookiesAsync(
-      base::Bind(&GetCookieListCallback::Run,
-                 base::Unretained(&get_cookie_list_callback2)));
+      base::BindOnce(&GetCookieListCallback::Run,
+                     base::Unretained(&get_cookie_list_callback2)));
 
   // Only the main load should have been queued.
   ASSERT_EQ(1u, store->commands().size());
@@ -2390,7 +2411,8 @@
   EXPECT_EQ(0u, get_cookie_list_callback1.cookies().size());
 
   set_cookie_callback.WaitUntilDone();
-  EXPECT_TRUE(set_cookie_callback.result());
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            set_cookie_callback.result());
 
   get_cookie_list_callback2.WaitUntilDone();
   EXPECT_EQ(1u, get_cookie_list_callback2.cookies().size());
@@ -2398,10 +2420,10 @@
 
 namespace {
 
-void RunClosureOnCookieListReceived(const base::Closure& closure,
+void RunClosureOnCookieListReceived(base::OnceClosure closure,
                                     const CookieList& cookie_list,
                                     const CookieStatusList& excluded_cookies) {
-  closure.Run();
+  std::move(closure).Run();
 }
 
 }  // namespace
@@ -2418,20 +2440,23 @@
       new CookieMonster(store.get(), nullptr, &net_log_));
 
   // Get all cookies task that queues a task to set a cookie when executed.
-  ResultSavingCookieCallback<bool> set_cookie_callback;
-  cm->GetAllCookiesAsync(base::Bind(
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
+      set_cookie_callback;
+  cm->GetAllCookiesAsync(base::BindOnce(
       &RunClosureOnCookieListReceived,
-      base::Bind(&CookieStore::SetCookieWithOptionsAsync,
-                 base::Unretained(cm.get()), kUrl, "a=b", CookieOptions(),
-                 base::Bind(&ResultSavingCookieCallback<bool>::Run,
-                            base::Unretained(&set_cookie_callback)))));
+      base::BindOnce(
+          &CookieStore::SetCookieWithOptionsAsync, base::Unretained(cm.get()),
+          kUrl, "a=b", CookieOptions(),
+          base::BindOnce(&ResultSavingCookieCallback<
+                             CanonicalCookie::CookieInclusionStatus>::Run,
+                         base::Unretained(&set_cookie_callback)))));
 
   // Get cookie task. Queued before the delete task is executed, so should not
   // see the set cookie.
   GetCookieListCallback get_cookie_list_callback1;
   cm->GetAllCookiesAsync(
-      base::Bind(&GetCookieListCallback::Run,
-                 base::Unretained(&get_cookie_list_callback1)));
+      base::BindOnce(&GetCookieListCallback::Run,
+                     base::Unretained(&get_cookie_list_callback1)));
 
   // Only the main load should have been queued.
   ASSERT_EQ(1u, store->commands().size());
@@ -2446,13 +2471,14 @@
   EXPECT_EQ(0u, get_cookie_list_callback1.cookies().size());
 
   set_cookie_callback.WaitUntilDone();
-  EXPECT_TRUE(set_cookie_callback.result());
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            set_cookie_callback.result());
 
   // A subsequent get cookies call should see the new cookie.
   GetCookieListCallback get_cookie_list_callback2;
   cm->GetAllCookiesAsync(
-      base::Bind(&GetCookieListCallback::Run,
-                 base::Unretained(&get_cookie_list_callback2)));
+      base::BindOnce(&GetCookieListCallback::Run,
+                     base::Unretained(&get_cookie_list_callback2)));
   get_cookie_list_callback2.WaitUntilDone();
   EXPECT_EQ(1u, get_cookie_list_callback2.cookies().size());
 }
@@ -2467,7 +2493,7 @@
   ASSERT_EQ(0, counter->callback_count());
 
   // Before initialization, FlushStore() should just run the callback.
-  cm->FlushStore(base::Bind(&CallbackCounter::Callback, counter));
+  cm->FlushStore(base::BindOnce(&CallbackCounter::Callback, counter));
   base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(0, store->flush_count());
@@ -2482,7 +2508,7 @@
 
   // After initialization, FlushStore() should delegate to the store.
   GetAllCookies(cm.get());  // Force init.
-  cm->FlushStore(base::Bind(&CallbackCounter::Callback, counter));
+  cm->FlushStore(base::BindOnce(&CallbackCounter::Callback, counter));
   base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(1, store->flush_count());
@@ -2503,7 +2529,7 @@
 
   ASSERT_EQ(2, counter->callback_count());
 
-  cm->FlushStore(base::Bind(&CallbackCounter::Callback, counter));
+  cm->FlushStore(base::BindOnce(&CallbackCounter::Callback, counter));
   base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(3, counter->callback_count());
@@ -2951,24 +2977,32 @@
 
   // A non-secure cookie can be created from either a URL with a secure or
   // insecure scheme.
-  EXPECT_TRUE(SetCookie(cm.get(), http_url, "A=C;"));
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B;"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), http_url, "A=C;"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), https_url, "A=B;"));
 
   // A secure cookie cannot be created from a URL with an insecure scheme.
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=B; Secure"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
+            SetCookieReturnStatus(cm.get(), http_url, "A=B; Secure"));
 
   // A secure cookie can be created from a URL with a secure scheme.
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
 
   // If a non-secure cookie is created from a URL with an insecure scheme, and a
   // secure cookie with the same name already exists, do not update the cookie.
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C;"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+            SetCookieReturnStatus(cm.get(), http_url, "A=C;"));
 
   // If a non-secure cookie is created from a URL with an secure scheme, and a
   // secure cookie with the same name already exists, update the cookie.
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=C;"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), https_url, "A=C;"));
 
   // If a non-secure cookie is created from a URL with an insecure scheme, and
   // a secure cookie with the same name already exists, do not update the cookie
@@ -2976,27 +3010,40 @@
   //
   // With an existing cookie whose path is '/', a cookie with the same name
   // cannot be set on the same domain, regardless of path:
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; path=/"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; path=/my/path"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+            SetCookieReturnStatus(cm.get(), http_url, "A=C; path=/"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+            SetCookieReturnStatus(cm.get(), http_url, "A=C; path=/my/path"));
 
   // But if the existing cookie has a path somewhere under the root, cookies
   // with the same name may be set for paths which don't overlap the existing
   // cookie.
   EXPECT_TRUE(
       SetCookie(cm.get(), https_url, "WITH_PATH=B; Secure; path=/my/path"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_url, "WITH_PATH=C"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_url, "WITH_PATH=C; path=/"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_url, "WITH_PATH=C; path=/your/path"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "WITH_PATH=C; path=/my/path"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "WITH_PATH=C; path=/my/path/sub"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), http_url, "WITH_PATH=C"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), http_url, "WITH_PATH=C; path=/"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), http_url,
+                                  "WITH_PATH=C; path=/your/path"));
+  EXPECT_EQ(
+      CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+      SetCookieReturnStatus(cm.get(), http_url, "WITH_PATH=C; path=/my/path"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+            SetCookieReturnStatus(cm.get(), http_url,
+                                  "WITH_PATH=C; path=/my/path/sub"));
 
   DeleteAll(cm.get());
 
   // If a secure cookie is set on top of an existing insecure cookie but with a
   // different path, both are retained.
-  EXPECT_TRUE(SetCookie(cm.get(), http_url, "A=B; path=/foo"));
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=C; Secure; path=/"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), http_url, "A=B; path=/foo"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), https_url, "A=C; Secure; path=/"));
 
   // Querying from an insecure url gets only the insecure cookie, but querying
   // from a secure url returns both.
@@ -3007,8 +3054,10 @@
   // Attempting to set an insecure cookie (from an insecure scheme) that domain-
   // matches and path-matches the secure cookie fails i.e. the secure cookie is
   // left alone...
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=D; path=/foo"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=D; path=/"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+            SetCookieReturnStatus(cm.get(), http_url, "A=D; path=/foo"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+            SetCookieReturnStatus(cm.get(), http_url, "A=D; path=/"));
   EXPECT_THAT(GetCookies(cm.get(), https_foo_url), testing::HasSubstr("A=C"));
 
   // ...but the original insecure cookie is still retained.
@@ -3017,23 +3066,34 @@
               testing::Not(testing::HasSubstr("A=D")));
 
   // Deleting the secure cookie leaves only the original insecure cookie.
-  EXPECT_TRUE(SetCookie(cm.get(), https_url,
-                        "A=C; path=/; Expires=Thu, 01-Jan-1970 00:00:01 GMT"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(
+                cm.get(), https_url,
+                "A=C; path=/; Expires=Thu, 01-Jan-1970 00:00:01 GMT"));
   EXPECT_EQ("A=B", GetCookies(cm.get(), https_foo_url));
 
   // If a non-secure cookie is created from a URL with an insecure scheme, and
   // a secure cookie with the same name already exists, if the domain strings
   // domain-match, do not update the cookie.
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; domain=foo.com"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; domain=www.foo.com"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+            SetCookieReturnStatus(cm.get(), http_url, "A=C; domain=foo.com"));
+  EXPECT_EQ(
+      CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+      SetCookieReturnStatus(cm.get(), http_url, "A=C; domain=www.foo.com"));
 
   // Since A=B was set above with no domain string, set a different cookie here
   // so the insecure examples aren't trying to overwrite the one above.
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "B=C; Secure; domain=foo.com"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "B=D; domain=foo.com"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "B=D"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_superdomain_url, "B=D"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), https_url,
+                                  "B=C; Secure; domain=foo.com"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+            SetCookieReturnStatus(cm.get(), http_url, "B=D; domain=foo.com"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+            SetCookieReturnStatus(cm.get(), http_url, "B=D"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+            SetCookieReturnStatus(cm.get(), http_superdomain_url, "B=D"));
 
   // Verify that if an httponly version of the cookie exists, adding a Secure
   // version of the cookie still does not overwrite it.
@@ -3043,7 +3103,8 @@
                                    include_httponly));
   // Note that the lack of an explicit options object below uses the default,
   // which in this case includes "exclude_httponly = true".
-  EXPECT_FALSE(SetCookie(cm.get(), https_url, "C=E; Secure"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY,
+            SetCookieReturnStatus(cm.get(), https_url, "C=E; Secure"));
 
   TestNetLogEntry::List entries;
   net_log_.GetEntries(&entries);
@@ -3185,14 +3246,19 @@
 
   // Tests that non-equivalent cookies because of the path attribute can be set
   // successfully.
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=C; path=/some/other/path"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
+  EXPECT_EQ(
+      CanonicalCookie::CookieInclusionStatus::INCLUDE,
+      SetCookieReturnStatus(cm.get(), https_url, "A=C; path=/some/other/path"));
   EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=D; path=/some/other/path"));
 
   // Tests that non-equivalent cookies because of the domain attribute can be
   // set successfully.
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=C; domain=foo.com"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            SetCookieReturnStatus(cm.get(), https_url, "A=C; domain=foo.com"));
   EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=D; domain=foo.com"));
 }
 
@@ -3204,12 +3270,14 @@
   CookieMonster cm(persistent_store.get(), nullptr, nullptr);
 
   // Start of a canonical cookie set.
-  ResultSavingCookieCallback<bool> callback_set;
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
+      callback_set;
   cm.SetCanonicalCookieAsync(
       CanonicalCookie::Create(GURL("http://a.com/"), "A=B", base::Time::Now(),
                               CookieOptions()),
       false /* secure_source */, false /* modify_httponly */,
-      base::BindOnce(&ResultSavingCookieCallback<bool>::Run,
+      base::BindOnce(&ResultSavingCookieCallback<
+                         CanonicalCookie::CookieInclusionStatus>::Run,
                      base::Unretained(&callback_set)));
 
   // Get cookies for a different URL.
@@ -3288,21 +3356,25 @@
 
   // Write a cookie created at |t1|.
   auto cookie = CanonicalCookie::Create(url, cookie_line, t1, options);
-  ResultSavingCookieCallback<bool> set_callback_1;
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
+      set_callback_1;
   cm.SetCanonicalCookieAsync(
       std::move(cookie), url.SchemeIsCryptographic(),
       !options.exclude_httponly(),
-      base::BindOnce(&ResultSavingCookieCallback<bool>::Run,
+      base::BindOnce(&ResultSavingCookieCallback<
+                         CanonicalCookie::CookieInclusionStatus>::Run,
                      base::Unretained(&set_callback_1)));
   set_callback_1.WaitUntilDone();
 
   // Overwrite the cookie at |t2|.
   cookie = CanonicalCookie::Create(url, cookie_line, t2, options);
-  ResultSavingCookieCallback<bool> set_callback_2;
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
+      set_callback_2;
   cm.SetCanonicalCookieAsync(
       std::move(cookie), url.SchemeIsCryptographic(),
       !options.exclude_httponly(),
-      base::BindOnce(&ResultSavingCookieCallback<bool>::Run,
+      base::BindOnce(&ResultSavingCookieCallback<
+                         CanonicalCookie::CookieInclusionStatus>::Run,
                      base::Unretained(&set_callback_2)));
   set_callback_2.WaitUntilDone();
 
diff --git a/net/cookies/cookie_store.h b/net/cookies/cookie_store.h
index b4b4ce4f..086115f3 100644
--- a/net/cookies/cookie_store.h
+++ b/net/cookies/cookie_store.h
@@ -45,7 +45,9 @@
   typedef base::OnceCallback<void(const CookieList& cookies,
                                   const CookieStatusList& excluded_list)>
       GetCookieListCallback;
-  typedef base::OnceCallback<void(bool success)> SetCookiesCallback;
+  typedef base::OnceCallback<void(
+      CanonicalCookie::CookieInclusionStatus status)>
+      SetCookiesCallback;
   typedef base::OnceCallback<void(uint32_t num_deleted)> DeleteCallback;
 
   virtual ~CookieStore();
diff --git a/net/cookies/cookie_store_test_helpers.cc b/net/cookies/cookie_store_test_helpers.cc
index 7261c7c..022b73a 100644
--- a/net/cookies/cookie_store_test_helpers.cc
+++ b/net/cookies/cookie_store_test_helpers.cc
@@ -68,11 +68,13 @@
                                         nullptr /* channel_id_service */,
                                         nullptr /* netlog */)),
       did_run_(false),
-      result_(false) {}
+      result_(
+          CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE) {}
 
 DelayedCookieMonster::~DelayedCookieMonster() = default;
 
-void DelayedCookieMonster::SetCookiesInternalCallback(bool result) {
+void DelayedCookieMonster::SetCookiesInternalCallback(
+    CanonicalCookie::CookieInclusionStatus result) {
   result_ = result;
   did_run_ = true;
 }
diff --git a/net/cookies/cookie_store_test_helpers.h b/net/cookies/cookie_store_test_helpers.h
index 293425e3..eb7934cee 100644
--- a/net/cookies/cookie_store_test_helpers.h
+++ b/net/cookies/cookie_store_test_helpers.h
@@ -93,7 +93,8 @@
  private:
   // Be called immediately from CookieMonster.
 
-  void SetCookiesInternalCallback(bool result);
+  void SetCookiesInternalCallback(
+      CanonicalCookie::CookieInclusionStatus result);
 
   void GetCookiesWithOptionsInternalCallback(const std::string& cookie);
   void GetCookieListWithOptionsInternalCallback(
@@ -113,7 +114,7 @@
   DelayedCookieMonsterChangeDispatcher change_dispatcher_;
 
   bool did_run_;
-  bool result_;
+  CanonicalCookie::CookieInclusionStatus result_;
   std::string cookie_;
   std::string cookie_line_;
   CookieList cookie_list_;
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h
index 96a23f8..d546f45 100644
--- a/net/cookies/cookie_store_unittest.h
+++ b/net/cookies/cookie_store_unittest.h
@@ -199,14 +199,14 @@
                             const std::string& cookie_line,
                             const CookieOptions& options) {
     DCHECK(cs);
-    ResultSavingCookieCallback<bool> callback;
+    ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback;
     cs->SetCookieWithOptionsAsync(
         url, cookie_line, options,
-        base::Bind(
-            &ResultSavingCookieCallback<bool>::Run,
-            base::Unretained(&callback)));
+        base::BindOnce(&ResultSavingCookieCallback<
+                           CanonicalCookie::CookieInclusionStatus>::Run,
+                       base::Unretained(&callback)));
     callback.WaitUntilDone();
-    return callback.result();
+    return callback.result() == CanonicalCookie::CookieInclusionStatus::INCLUDE;
   }
 
   bool SetCanonicalCookie(CookieStore* cs,
@@ -214,13 +214,14 @@
                           bool secure_source,
                           bool can_modify_httponly) {
     DCHECK(cs);
-    ResultSavingCookieCallback<bool> callback;
+    ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback;
     cs->SetCanonicalCookieAsync(
         std::move(cookie), secure_source, can_modify_httponly,
-        base::Bind(&ResultSavingCookieCallback<bool>::Run,
-                   base::Unretained(&callback)));
+        base::BindOnce(&ResultSavingCookieCallback<
+                           CanonicalCookie::CookieInclusionStatus>::Run,
+                       base::Unretained(&callback)));
     callback.WaitUntilDone();
-    return callback.result();
+    return callback.result() == CanonicalCookie::CookieInclusionStatus::INCLUDE;
   }
 
   bool SetCookieWithServerTime(CookieStore* cs,
@@ -243,6 +244,41 @@
     return SetCookieWithOptions(cs, url, cookie_line, options);
   }
 
+  CanonicalCookie::CookieInclusionStatus SetCookieReturnStatus(
+      CookieStore* cs,
+      const GURL& url,
+      const std::string& cookie_line) {
+    CookieOptions options;
+    if (!CookieStoreTestTraits::supports_http_only)
+      options.set_include_httponly();
+
+    DCHECK(cs);
+    ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback;
+    cs->SetCookieWithOptionsAsync(
+        url, cookie_line, options,
+        base::BindOnce(&ResultSavingCookieCallback<
+                           CanonicalCookie::CookieInclusionStatus>::Run,
+                       base::Unretained(&callback)));
+    callback.WaitUntilDone();
+    return callback.result();
+  }
+
+  CanonicalCookie::CookieInclusionStatus SetCanonicalCookieReturnStatus(
+      CookieStore* cs,
+      std::unique_ptr<CanonicalCookie> cookie,
+      bool secure_source,
+      bool can_modify_httponly) {
+    DCHECK(cs);
+    ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback;
+    cs->SetCanonicalCookieAsync(
+        std::move(cookie), secure_source, can_modify_httponly,
+        base::BindOnce(&ResultSavingCookieCallback<
+                           CanonicalCookie::CookieInclusionStatus>::Run,
+                       base::Unretained(&callback)));
+    callback.WaitUntilDone();
+    return callback.result();
+  }
+
   uint32_t DeleteCanonicalCookie(CookieStore* cs,
                                  const CanonicalCookie& cookie) {
     DCHECK(cs);
@@ -528,13 +564,14 @@
       false /* secure_source */, true));
 
   // A secure source is required for creating secure cookies.
-  EXPECT_FALSE(this->SetCanonicalCookie(
-      cs,
-      std::make_unique<CanonicalCookie>(
-          "E", "F", http_foo_host, "/", base::Time(), base::Time(),
-          base::Time(), true, false, CookieSameSite::DEFAULT_MODE,
-          COOKIE_PRIORITY_DEFAULT),
-      false /* secure_source */, true));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
+            this->SetCanonicalCookieReturnStatus(
+                cs,
+                std::make_unique<CanonicalCookie>(
+                    "E", "F", http_foo_host, "/", base::Time(), base::Time(),
+                    base::Time(), true, false, CookieSameSite::DEFAULT_MODE,
+                    COOKIE_PRIORITY_DEFAULT),
+                false /* secure_source */, true));
 
   // A secure source is also required for overwriting secure cookies.  Writing
   // a secure cookie then overwriting it from a non-secure source should fail.
@@ -546,24 +583,27 @@
           CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT),
       true /* secure_source */, true /* modify_http_only */));
 
-  EXPECT_FALSE(this->SetCanonicalCookie(
-      cs,
-      std::make_unique<CanonicalCookie>(
-          "E", "F", http_foo_host, "/", base::Time(), base::Time(),
-          base::Time(), true /* secure */, false /* httponly */,
-          CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT),
-      false /* secure_source */, true /* modify_http_only */));
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
+            this->SetCanonicalCookieReturnStatus(
+                cs,
+                std::make_unique<CanonicalCookie>(
+                    "E", "F", http_foo_host, "/", base::Time(), base::Time(),
+                    base::Time(), true /* secure */, false /* httponly */,
+                    CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT),
+                false /* secure_source */, true /* modify_http_only */));
 
   if (TypeParam::supports_http_only) {
     // Permission to modify http only cookies is required to create an
     // httponly cookie.
-    EXPECT_FALSE(this->SetCanonicalCookie(
-        cs,
-        std::make_unique<CanonicalCookie>(
-            "G", "H", http_foo_host, "/unique", base::Time(), base::Time(),
-            base::Time(), false /* secure */, true /* httponly */,
-            CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT),
-        false /* secure_source */, false /* modify_http_only */));
+    EXPECT_EQ(
+        CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
+        this->SetCanonicalCookieReturnStatus(
+            cs,
+            std::make_unique<CanonicalCookie>(
+                "G", "H", http_foo_host, "/unique", base::Time(), base::Time(),
+                base::Time(), false /* secure */, true /* httponly */,
+                CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT),
+            false /* secure_source */, false /* modify_http_only */));
 
     // Permission to modify httponly cookies is also required to overwrite
     // an httponly cookie.
@@ -575,13 +615,15 @@
             CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT),
         false /* secure_source */, true /* modify_http_only */));
 
-    EXPECT_FALSE(this->SetCanonicalCookie(
-        cs,
-        std::make_unique<CanonicalCookie>(
-            "G", "H", http_foo_host, "/unique", base::Time(), base::Time(),
-            base::Time(), false /* secure */, true /* httponly */,
-            CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT),
-        false /* secure_source */, false /* modify_http_only */));
+    EXPECT_EQ(
+        CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
+        this->SetCanonicalCookieReturnStatus(
+            cs,
+            std::make_unique<CanonicalCookie>(
+                "G", "H", http_foo_host, "/unique", base::Time(), base::Time(),
+                base::Time(), false /* secure */, true /* httponly */,
+                CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT),
+            false /* secure_source */, false /* modify_http_only */));
   } else {
     // Leave store in same state as if the above tests had been run.
     EXPECT_TRUE(this->SetCanonicalCookie(
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index fcd1eeec..48d7e148d 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -1793,8 +1793,8 @@
   CookieCallback()
       : result_(false), loop_to_quit_(std::make_unique<base::RunLoop>()) {}
 
-  void SetCookieCallback(bool result) {
-    result_ = result;
+  void SetCookieCallback(CanonicalCookie::CookieInclusionStatus result) {
+    result_ = (result == CanonicalCookie::CookieInclusionStatus::INCLUDE);
     loop_to_quit_->Quit();
   }
 
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
index 6f673ab9..656faf6c 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -1229,26 +1229,32 @@
   std::unique_ptr<CookieMonster> cookie_monster =
       std::make_unique<CookieMonster>(store_.get(), nullptr, nullptr);
   cookie_monster->SetCookieableSchemes({"gopher", "http"});
-  ResultSavingCookieCallback<bool> set_cookie_callback;
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
+      set_cookie_callback;
   cookie_monster->SetCookieWithOptionsAsync(
       GURL("gopher://subdomain.gopheriffic.com/page"), "A=B; max-age=3600",
       CookieOptions(),
-      base::BindOnce(&ResultSavingCookieCallback<bool>::Run,
+      base::BindOnce(&ResultSavingCookieCallback<
+                         CanonicalCookie::CookieInclusionStatus>::Run,
                      base::Unretained(&set_cookie_callback)));
   set_cookie_callback.WaitUntilDone();
-  EXPECT_TRUE(set_cookie_callback.result());
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            set_cookie_callback.result());
 
   // Also insert a whole bunch of cookies to slow down the background loading of
   // all the cookies.
   for (int i = 0; i < 50; ++i) {
-    ResultSavingCookieCallback<bool> set_cookie_callback2;
+    ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
+        set_cookie_callback2;
     cookie_monster->SetCookieWithOptionsAsync(
         GURL(base::StringPrintf("http://example%d.com/", i)),
         "A=B; max-age=3600", CookieOptions(),
-        base::BindOnce(&ResultSavingCookieCallback<bool>::Run,
+        base::BindOnce(&ResultSavingCookieCallback<
+                           CanonicalCookie::CookieInclusionStatus>::Run,
                        base::Unretained(&set_cookie_callback2)));
     set_cookie_callback2.WaitUntilDone();
-    EXPECT_TRUE(set_cookie_callback2.result());
+    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+              set_cookie_callback2.result());
   }
 
   net::TestClosure flush_closure;
@@ -1289,13 +1295,16 @@
   std::unique_ptr<CookieMonster> cookie_monster =
       std::make_unique<CookieMonster>(store_.get(), nullptr, nullptr);
 
-  ResultSavingCookieCallback<bool> set_cookie_callback;
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
+      set_cookie_callback;
   cookie_monster->SetCookieWithOptionsAsync(
       GURL("http://www.example.com/"), "A=B; max-age=3600", CookieOptions(),
-      base::BindOnce(&ResultSavingCookieCallback<bool>::Run,
+      base::BindOnce(&ResultSavingCookieCallback<
+                         CanonicalCookie::CookieInclusionStatus>::Run,
                      base::Unretained(&set_cookie_callback)));
   set_cookie_callback.WaitUntilDone();
-  EXPECT_TRUE(set_cookie_callback.result());
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            set_cookie_callback.result());
 
   // Things should commit once going out of scope.
 }
diff --git a/net/reporting/reporting_uploader_unittest.cc b/net/reporting/reporting_uploader_unittest.cc
index 1cf86c90..b9b4174 100644
--- a/net/reporting/reporting_uploader_unittest.cc
+++ b/net/reporting/reporting_uploader_unittest.cc
@@ -440,13 +440,16 @@
   server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
   ASSERT_TRUE(server_.Start());
 
-  ResultSavingCookieCallback<bool> cookie_callback;
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
+      cookie_callback;
   context_.cookie_store()->SetCookieWithOptionsAsync(
       server_.GetURL("/"), "foo=bar", CookieOptions(),
-      base::BindRepeating(&ResultSavingCookieCallback<bool>::Run,
+      base::BindRepeating(&ResultSavingCookieCallback<
+                              CanonicalCookie::CookieInclusionStatus>::Run,
                           base::Unretained(&cookie_callback)));
   cookie_callback.WaitUntilDone();
-  ASSERT_TRUE(cookie_callback.result());
+  ASSERT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            cookie_callback.result());
 
   TestUploadCallback upload_callback;
   uploader_->StartUpload(kOrigin, server_.GetURL("/"), kUploadBody, 0,
diff --git a/net/websockets/websocket_stream_cookie_test.cc b/net/websockets/websocket_stream_cookie_test.cc
index c93324b..65b5645 100644
--- a/net/websockets/websocket_stream_cookie_test.cc
+++ b/net/websockets/websocket_stream_cookie_test.cc
@@ -82,12 +82,13 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  static void SetCookieHelperFunction(const base::Closure& task,
-                                      base::WeakPtr<bool> weak_is_called,
-                                      base::WeakPtr<bool> weak_result,
-                                      bool success) {
+  static void SetCookieHelperFunction(
+      const base::RepeatingClosure& task,
+      base::WeakPtr<bool> weak_is_called,
+      base::WeakPtr<bool> weak_result,
+      CanonicalCookie::CookieInclusionStatus status) {
     *weak_is_called = true;
-    *weak_result = success;
+    *weak_result = (status == CanonicalCookie::CookieInclusionStatus::INCLUDE);
     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
   }
 };
diff --git a/services/network/cookie_manager.cc b/services/network/cookie_manager.cc
index 0b2ac0f..5565df5 100644
--- a/services/network/cookie_manager.cc
+++ b/services/network/cookie_manager.cc
@@ -60,6 +60,18 @@
       std::move(callback));
 }
 
+net::CookieStore::SetCookiesCallback StatusToBool(
+    base::OnceCallback<void(bool)> callback) {
+  return base::BindOnce(
+      [](base::OnceCallback<void(bool)> callback,
+         const net::CanonicalCookie::CookieInclusionStatus status) {
+        bool success =
+            (status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+        std::move(callback).Run(success);
+      },
+      std::move(callback));
+}
+
 }  // namespace
 
 CookieManager::ListenerRegistration::ListenerRegistration() {}
@@ -128,7 +140,7 @@
                                        SetCanonicalCookieCallback callback) {
   cookie_store_->SetCanonicalCookieAsync(
       std::make_unique<net::CanonicalCookie>(cookie), secure_source,
-      modify_http_only, std::move(callback));
+      modify_http_only, StatusToBool(std::move(callback)));
 }
 
 void CookieManager::DeleteCanonicalCookie(
diff --git a/services/network/cookie_manager_unittest.cc b/services/network/cookie_manager_unittest.cc
index 2497c61..848122d5 100644
--- a/services/network/cookie_manager_unittest.cc
+++ b/services/network/cookie_manager_unittest.cc
@@ -183,14 +183,17 @@
   bool SetCanonicalCookie(const net::CanonicalCookie& cookie,
                           bool secure_source,
                           bool can_modify_httponly) {
-    net::ResultSavingCookieCallback<bool> callback;
+    net::ResultSavingCookieCallback<net::CanonicalCookie::CookieInclusionStatus>
+        callback;
     cookie_monster_->SetCanonicalCookieAsync(
         std::make_unique<net::CanonicalCookie>(cookie), secure_source,
         can_modify_httponly,
-        base::BindOnce(&net::ResultSavingCookieCallback<bool>::Run,
+        base::BindOnce(&net::ResultSavingCookieCallback<
+                           net::CanonicalCookie::CookieInclusionStatus>::Run,
                        base::Unretained(&callback)));
     callback.WaitUntilDone();
-    return callback.result();
+    return callback.result() ==
+           net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
   }
 
   std::string DumpAllCookies() {
diff --git a/services/network/restricted_cookie_manager.cc b/services/network/restricted_cookie_manager.cc
index 7721ac21..e6ddf37 100644
--- a/services/network/restricted_cookie_manager.cc
+++ b/services/network/restricted_cookie_manager.cc
@@ -45,6 +45,18 @@
   return mojom::CookieChangeCause::EXPLICIT;
 }
 
+net::CookieStore::SetCookiesCallback StatusToBool(
+    base::OnceCallback<void(bool)> callback) {
+  return base::BindOnce(
+      [](base::OnceCallback<void(bool)> callback,
+         const net::CanonicalCookie::CookieInclusionStatus status) {
+        bool success =
+            (status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+        std::move(callback).Run(success);
+      },
+      std::move(callback));
+}
+
 }  // anonymous namespace
 
 class RestrictedCookieManager::Listener : public base::LinkNode<Listener> {
@@ -213,7 +225,7 @@
   bool modify_http_only = false;
   cookie_store_->SetCanonicalCookieAsync(std::move(sanitized_cookie),
                                          secure_source, modify_http_only,
-                                         std::move(callback));
+                                         StatusToBool(std::move(callback)));
 }
 
 void RestrictedCookieManager::AddChangeListener(
diff --git a/services/network/restricted_cookie_manager_unittest.cc b/services/network/restricted_cookie_manager_unittest.cc
index 85314b1..c20e8f2 100644
--- a/services/network/restricted_cookie_manager_unittest.cc
+++ b/services/network/restricted_cookie_manager_unittest.cc
@@ -107,14 +107,17 @@
   bool SetCanonicalCookie(const net::CanonicalCookie& cookie,
                           bool secure_source,
                           bool can_modify_httponly) {
-    net::ResultSavingCookieCallback<bool> callback;
+    net::ResultSavingCookieCallback<net::CanonicalCookie::CookieInclusionStatus>
+        callback;
     cookie_monster_.SetCanonicalCookieAsync(
         std::make_unique<net::CanonicalCookie>(cookie), secure_source,
         can_modify_httponly,
-        base::BindOnce(&net::ResultSavingCookieCallback<bool>::Run,
+        base::BindOnce(&net::ResultSavingCookieCallback<
+                           net::CanonicalCookie::CookieInclusionStatus>::Run,
                        base::Unretained(&callback)));
     callback.WaitUntilDone();
-    return callback.result();
+    return callback.result() ==
+           net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
   }
 
   // Simplified helper for SetCanonicalCookie.