1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <memory>
6 #include <string>
7 #include <utility>
8 #include <vector>
9 
10 #include "base/bind.h"
11 #include "base/run_loop.h"
12 #include "base/test/bind_test_util.h"
13 #include "base/time/time.h"
14 #include "content/browser/browsing_data/browsing_data_test_utils.h"
15 #include "content/browser/browsing_data/same_site_data_remover_impl.h"
16 #include "content/public/browser/storage_partition.h"
17 #include "content/public/test/browser_task_environment.h"
18 #include "content/public/test/test_browser_context.h"
19 #include "content/public/test/test_storage_partition.h"
20 #include "net/cookies/cookie_monster.h"
21 #include "net/url_request/url_request_context.h"
22 #include "services/network/public/mojom/cookie_manager.mojom.h"
23 #include "storage/browser/test/mock_special_storage_policy.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 
27 using testing::IsEmpty;
28 using testing::SizeIs;
29 using testing::UnorderedElementsAre;
30 
31 namespace content {
32 
33 struct StoragePartitionSameSiteRemovalData {
34   uint32_t removal_mask = 0;
35   uint32_t quota_storage_removal_mask = 0;
36   StoragePartition::OriginMatcherFunction origin_matcher;
37 };
38 
39 class SameSiteRemoverTestStoragePartition : public TestStoragePartition {
40  public:
SameSiteRemoverTestStoragePartition()41   SameSiteRemoverTestStoragePartition() {}
~SameSiteRemoverTestStoragePartition()42   ~SameSiteRemoverTestStoragePartition() override {}
43 
ClearData(uint32_t removal_mask,uint32_t quota_storage_removal_mask,OriginMatcherFunction origin_matcher,network::mojom::CookieDeletionFilterPtr cookie_deletion_filter,bool perform_storage_cleanup,const base::Time begin,const base::Time end,base::OnceClosure callback)44   void ClearData(uint32_t removal_mask,
45                  uint32_t quota_storage_removal_mask,
46                  OriginMatcherFunction origin_matcher,
47                  network::mojom::CookieDeletionFilterPtr cookie_deletion_filter,
48                  bool perform_storage_cleanup,
49                  const base::Time begin,
50                  const base::Time end,
51                  base::OnceClosure callback) override {
52     storage_partition_removal_data_.removal_mask = removal_mask;
53     storage_partition_removal_data_.quota_storage_removal_mask =
54         quota_storage_removal_mask;
55     storage_partition_removal_data_.origin_matcher = std::move(origin_matcher);
56     std::move(callback).Run();
57   }
58 
GetStoragePartitionRemovalData()59   const StoragePartitionSameSiteRemovalData& GetStoragePartitionRemovalData() {
60     return storage_partition_removal_data_;
61   }
62 
63  private:
64   StoragePartitionSameSiteRemovalData storage_partition_removal_data_;
65 
66   DISALLOW_COPY_AND_ASSIGN(SameSiteRemoverTestStoragePartition);
67 };
68 
69 class SameSiteDataRemoverImplTest : public testing::Test {
70  public:
SameSiteDataRemoverImplTest()71   SameSiteDataRemoverImplTest()
72       : browser_context_(std::make_unique<TestBrowserContext>()),
73         same_site_remover_(
74             std::make_unique<SameSiteDataRemoverImpl>(browser_context_.get())) {
75   }
76 
TearDown()77   void TearDown() override { browser_context_.reset(); }
78 
GetSameSiteDataRemoverImpl()79   SameSiteDataRemoverImpl* GetSameSiteDataRemoverImpl() {
80     return same_site_remover_.get();
81   }
82 
GetBrowserContext()83   BrowserContext* GetBrowserContext() { return browser_context_.get(); }
84 
DeleteSameSiteNoneCookies()85   void DeleteSameSiteNoneCookies() {
86     base::RunLoop run_loop;
87     GetSameSiteDataRemoverImpl()->DeleteSameSiteNoneCookies(
88         run_loop.QuitClosure());
89     run_loop.Run();
90   }
91 
ClearStoragePartitionData()92   void ClearStoragePartitionData() {
93     base::RunLoop run_loop;
94     GetSameSiteDataRemoverImpl()->ClearStoragePartitionData(
95         run_loop.QuitClosure());
96     run_loop.Run();
97   }
98 
99  private:
100   BrowserTaskEnvironment task_environment_;
101   std::unique_ptr<BrowserContext> browser_context_;
102   std::unique_ptr<SameSiteDataRemoverImpl> same_site_remover_;
103 
104   DISALLOW_COPY_AND_ASSIGN(SameSiteDataRemoverImplTest);
105 };
106 
TEST_F(SameSiteDataRemoverImplTest,TestRemoveSameSiteNoneCookies)107 TEST_F(SameSiteDataRemoverImplTest, TestRemoveSameSiteNoneCookies) {
108   BrowserContext* browser_context = GetBrowserContext();
109 
110   CreateCookieForTest(
111       "TestCookie1", "www.google.com", net::CookieSameSite::NO_RESTRICTION,
112       net::CookieOptions::SameSiteCookieContext(
113           net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE),
114       true /* is_cookie_secure */, browser_context);
115   CreateCookieForTest(
116       "TestCookie2", "www.gmail.google.com",
117       net::CookieSameSite::NO_RESTRICTION,
118       net::CookieOptions::SameSiteCookieContext(
119           net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE),
120       true /* is_cookie_secure */, browser_context);
121 
122   DeleteSameSiteNoneCookies();
123 
124   EXPECT_THAT(GetSameSiteDataRemoverImpl()->GetDeletedDomainsForTesting(),
125               UnorderedElementsAre("www.google.com", "www.gmail.google.com"));
126 
127   const std::vector<net::CanonicalCookie>& cookies =
128       GetAllCookies(browser_context);
129   EXPECT_THAT(cookies, IsEmpty());
130 }
131 
TEST_F(SameSiteDataRemoverImplTest,TestRemoveOnlySameSiteNoneCookies)132 TEST_F(SameSiteDataRemoverImplTest, TestRemoveOnlySameSiteNoneCookies) {
133   BrowserContext* browser_context = GetBrowserContext();
134   CreateCookieForTest(
135       "TestCookie1", "www.google.com", net::CookieSameSite::NO_RESTRICTION,
136       net::CookieOptions::SameSiteCookieContext(
137           net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE),
138       true /* is_cookie_secure */, browser_context);
139   // The second cookie has SameSite value STRICT_MODE instead of NO_RESTRICTION.
140   CreateCookieForTest("TestCookie2", "www.gmail.google.com",
141                       net::CookieSameSite::STRICT_MODE,
142                       net::CookieOptions::SameSiteCookieContext(
143                           net::CookieOptions::SameSiteCookieContext::
144                               ContextType::SAME_SITE_STRICT),
145                       true /* is_cookie_secure */, browser_context);
146 
147   DeleteSameSiteNoneCookies();
148 
149   EXPECT_THAT(GetSameSiteDataRemoverImpl()->GetDeletedDomainsForTesting(),
150               UnorderedElementsAre("www.google.com"));
151 
152   const std::vector<net::CanonicalCookie>& cookies =
153       GetAllCookies(browser_context);
154   ASSERT_EQ(1u, cookies.size());
155   ASSERT_EQ(cookies[0].Name(), "TestCookie2");
156 }
157 
TEST_F(SameSiteDataRemoverImplTest,TestRemoveSameDomainCookies)158 TEST_F(SameSiteDataRemoverImplTest, TestRemoveSameDomainCookies) {
159   BrowserContext* browser_context = GetBrowserContext();
160   CreateCookieForTest(
161       "TestCookie1", "www.google.com", net::CookieSameSite::NO_RESTRICTION,
162       net::CookieOptions::SameSiteCookieContext(
163           net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE),
164       true /* is_cookie_secure */, browser_context);
165   // The second cookie has the same domain as the first cookie, but also has
166   // SameSite value STRICT_MODE instead of NO_RESTRICTION.
167   CreateCookieForTest("TestCookie2", "www.google.com",
168                       net::CookieSameSite::STRICT_MODE,
169                       net::CookieOptions::SameSiteCookieContext(
170                           net::CookieOptions::SameSiteCookieContext::
171                               ContextType::SAME_SITE_STRICT),
172                       false /* is_cookie_secure */, browser_context);
173 
174   DeleteSameSiteNoneCookies();
175 
176   EXPECT_THAT(GetSameSiteDataRemoverImpl()->GetDeletedDomainsForTesting(),
177               UnorderedElementsAre("www.google.com"));
178 
179   const std::vector<net::CanonicalCookie>& cookies =
180       GetAllCookies(browser_context);
181   ASSERT_EQ(1u, cookies.size());
182   ASSERT_EQ(cookies[0].Name(), "TestCookie2");
183 }
184 
TEST_F(SameSiteDataRemoverImplTest,TestKeepSameSiteCookies)185 TEST_F(SameSiteDataRemoverImplTest, TestKeepSameSiteCookies) {
186   BrowserContext* browser_context = GetBrowserContext();
187   CreateCookieForTest("TestCookie1", "www.google.com",
188                       net::CookieSameSite::LAX_MODE,
189                       net::CookieOptions::SameSiteCookieContext(
190                           net::CookieOptions::SameSiteCookieContext::
191                               ContextType::SAME_SITE_LAX),
192                       false /* is_cookie_secure */, browser_context);
193   CreateCookieForTest("TestCookie2", "www.gmail.google.com",
194                       net::CookieSameSite::STRICT_MODE,
195                       net::CookieOptions::SameSiteCookieContext(
196                           net::CookieOptions::SameSiteCookieContext::
197                               ContextType::SAME_SITE_STRICT),
198                       false /* is_cookie_secure */, browser_context);
199 
200   DeleteSameSiteNoneCookies();
201 
202   ASSERT_THAT(GetSameSiteDataRemoverImpl()->GetDeletedDomainsForTesting(),
203               IsEmpty());
204 
205   const std::vector<net::CanonicalCookie>& cookies =
206       GetAllCookies(browser_context);
207   EXPECT_THAT(2u, cookies.size());
208 }
209 
TEST_F(SameSiteDataRemoverImplTest,TestCookieRemovalUnaffectedByParameters)210 TEST_F(SameSiteDataRemoverImplTest, TestCookieRemovalUnaffectedByParameters) {
211   BrowserContext* browser_context = GetBrowserContext();
212   network::mojom::CookieManager* cookie_manager =
213       GetCookieManager(browser_context);
214 
215   base::RunLoop run_loop1;
216   net::CookieOptions options;
217   options.set_include_httponly();
218   bool result_out = false;
219   cookie_manager->SetCanonicalCookie(
220       net::CanonicalCookie("TestCookie1", "20", "google.com", "/",
221                            base::Time::Now(), base::Time(), base::Time(), true,
222                            true, net::CookieSameSite::NO_RESTRICTION,
223                            net::COOKIE_PRIORITY_HIGH),
224       "https", options,
225       base::BindLambdaForTesting(
226           [&](net::CanonicalCookie::CookieInclusionStatus result) {
227             result_out = result.IsInclude();
228             run_loop1.Quit();
229           }));
230   run_loop1.Run();
231   EXPECT_TRUE(result_out);
232 
233   base::RunLoop run_loop2;
234   options.set_same_site_cookie_context(
235       net::CookieOptions::SameSiteCookieContext(
236           net::CookieOptions::SameSiteCookieContext::ContextType::
237               SAME_SITE_LAX));
238   result_out = false;
239   cookie_manager->SetCanonicalCookie(
240       net::CanonicalCookie("TestCookie2", "10", "gmail.google.com", "/",
241                            base::Time(), base::Time::Max(), base::Time(), false,
242                            true, net::CookieSameSite::LAX_MODE,
243                            net::COOKIE_PRIORITY_HIGH),
244       "https", options,
245       base::BindLambdaForTesting(
246           [&](net::CanonicalCookie::CookieInclusionStatus result) {
247             result_out = result.IsInclude();
248             run_loop2.Quit();
249           }));
250   run_loop2.Run();
251   EXPECT_TRUE(result_out);
252 
253   DeleteSameSiteNoneCookies();
254 
255   EXPECT_THAT(GetSameSiteDataRemoverImpl()->GetDeletedDomainsForTesting(),
256               UnorderedElementsAre("google.com"));
257 
258   const std::vector<net::CanonicalCookie>& cookies =
259       GetAllCookies(browser_context);
260   ASSERT_EQ(1u, cookies.size());
261   ASSERT_EQ(cookies[0].Name(), "TestCookie2");
262 }
263 
TEST_F(SameSiteDataRemoverImplTest,TestStoragePartitionDataRemoval)264 TEST_F(SameSiteDataRemoverImplTest, TestStoragePartitionDataRemoval) {
265   BrowserContext* browser_context = GetBrowserContext();
266   network::mojom::CookieManager* cookie_manager =
267       GetCookieManager(browser_context);
268   SameSiteRemoverTestStoragePartition storage_partition;
269   storage_partition.set_cookie_manager_for_browser_process(cookie_manager);
270   GetSameSiteDataRemoverImpl()->OverrideStoragePartitionForTesting(
271       &storage_partition);
272 
273   CreateCookieForTest(
274       "TestCookie1", ".google.com", net::CookieSameSite::NO_RESTRICTION,
275       net::CookieOptions::SameSiteCookieContext(
276           net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE),
277       true /* is_cookie_secure */, browser_context);
278   DeleteSameSiteNoneCookies();
279 
280   ClearStoragePartitionData();
281   StoragePartitionSameSiteRemovalData removal_data =
282       storage_partition.GetStoragePartitionRemovalData();
283 
284   const uint32_t expected_removal_mask =
285       content::StoragePartition::REMOVE_DATA_MASK_ALL &
286       ~content::StoragePartition::REMOVE_DATA_MASK_COOKIES;
287   EXPECT_EQ(removal_data.removal_mask, expected_removal_mask);
288 
289   const uint32_t expected_quota_storage_mask =
290       StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL;
291   EXPECT_EQ(removal_data.quota_storage_removal_mask,
292             expected_quota_storage_mask);
293 
294   auto special_storage_policy =
295       base::MakeRefCounted<storage::MockSpecialStoragePolicy>();
296   EXPECT_TRUE(removal_data.origin_matcher.Run(
297       url::Origin::Create(GURL("http://www.google.com/test")),
298       special_storage_policy.get()));
299   EXPECT_TRUE(removal_data.origin_matcher.Run(
300       url::Origin::Create(GURL("http://google.com")),
301       special_storage_policy.get()));
302   EXPECT_FALSE(removal_data.origin_matcher.Run(
303       url::Origin::Create(GURL("http://youtube.com")),
304       special_storage_policy.get()));
305 }
306 
307 }  // namespace content
308