reporting_service_unittest.cc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. // Copyright 2017 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. #include "net/reporting/reporting_service.h"
  5. #include <memory>
  6. #include <string>
  7. #include "base/bind.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/test/scoped_feature_list.h"
  11. #include "base/time/tick_clock.h"
  12. #include "base/values.h"
  13. #include "net/base/features.h"
  14. #include "net/base/isolation_info.h"
  15. #include "net/base/network_isolation_key.h"
  16. #include "net/base/schemeful_site.h"
  17. #include "net/reporting/mock_persistent_reporting_store.h"
  18. #include "net/reporting/reporting_browsing_data_remover.h"
  19. #include "net/reporting/reporting_cache.h"
  20. #include "net/reporting/reporting_context.h"
  21. #include "net/reporting/reporting_endpoint.h"
  22. #include "net/reporting/reporting_policy.h"
  23. #include "net/reporting/reporting_report.h"
  24. #include "net/reporting/reporting_service.h"
  25. #include "net/reporting/reporting_test_util.h"
  26. #include "net/test/test_with_task_environment.h"
  27. #include "testing/gmock/include/gmock/gmock.h"
  28. #include "testing/gtest/include/gtest/gtest.h"
  29. #include "third_party/abseil-cpp/absl/types/optional.h"
  30. #include "url/gurl.h"
  31. #include "url/origin.h"
  32. namespace net {
  33. namespace {
  34. using CommandType = MockPersistentReportingStore::Command::Type;
  35. // The tests are parametrized on a boolean value which represents whether to use
  36. // a MockPersistentReportingStore (if false, no store is used).
  37. class ReportingServiceTest : public ::testing::TestWithParam<bool>,
  38. public WithTaskEnvironment {
  39. protected:
  40. const GURL kUrl_ = GURL("https://origin/path");
  41. const GURL kUrl2_ = GURL("https://origin2/path");
  42. const url::Origin kOrigin_ = url::Origin::Create(kUrl_);
  43. const url::Origin kOrigin2_ = url::Origin::Create(kUrl2_);
  44. const GURL kEndpoint_ = GURL("https://endpoint/");
  45. const GURL kEndpoint2_ = GURL("https://endpoint2/");
  46. const std::string kUserAgent_ = "Mozilla/1.0";
  47. const std::string kGroup_ = "group";
  48. const std::string kGroup2_ = "group2";
  49. const std::string kType_ = "type";
  50. const absl::optional<base::UnguessableToken> kReportingSource_ =
  51. base::UnguessableToken::Create();
  52. const NetworkIsolationKey kNik_ =
  53. NetworkIsolationKey(SchemefulSite(kOrigin_), SchemefulSite(kOrigin_));
  54. const NetworkIsolationKey kNik2_ =
  55. NetworkIsolationKey(SchemefulSite(kOrigin2_), SchemefulSite(kOrigin2_));
  56. const ReportingEndpointGroupKey kGroupKey_ =
  57. ReportingEndpointGroupKey(kNik_, kOrigin_, kGroup_);
  58. const ReportingEndpointGroupKey kGroupKey2_ =
  59. ReportingEndpointGroupKey(kNik2_, kOrigin2_, kGroup_);
  60. const IsolationInfo kIsolationInfo_ =
  61. IsolationInfo::Create(IsolationInfo::RequestType::kOther,
  62. kOrigin_,
  63. kOrigin_,
  64. SiteForCookies::FromOrigin(kOrigin_));
  65. ReportingServiceTest() {
  66. feature_list_.InitAndEnableFeature(
  67. features::kPartitionNelAndReportingByNetworkIsolationKey);
  68. Init();
  69. }
  70. // Initializes, or re-initializes, |service_| and its dependencies.
  71. void Init() {
  72. if (GetParam())
  73. store_ = std::make_unique<MockPersistentReportingStore>();
  74. else
  75. store_ = nullptr;
  76. auto test_context = std::make_unique<TestReportingContext>(
  77. &clock_, &tick_clock_, ReportingPolicy(), store_.get());
  78. context_ = test_context.get();
  79. service_ = ReportingService::CreateForTesting(std::move(test_context));
  80. }
  81. // If the store exists, simulate finishing loading the store, which should
  82. // make the rest of the test run synchronously.
  83. void FinishLoading(bool load_success) {
  84. if (store_)
  85. store_->FinishLoading(load_success);
  86. }
  87. MockPersistentReportingStore* store() { return store_.get(); }
  88. TestReportingContext* context() { return context_; }
  89. ReportingService* service() { return service_.get(); }
  90. private:
  91. base::test::ScopedFeatureList feature_list_;
  92. base::SimpleTestClock clock_;
  93. base::SimpleTestTickClock tick_clock_;
  94. std::unique_ptr<MockPersistentReportingStore> store_;
  95. raw_ptr<TestReportingContext> context_;
  96. std::unique_ptr<ReportingService> service_;
  97. };
  98. TEST_P(ReportingServiceTest, QueueReport) {
  99. service()->QueueReport(kUrl_, kReportingSource_, kNik_, kUserAgent_, kGroup_,
  100. kType_, base::Value::Dict(), 0);
  101. FinishLoading(true /* load_success */);
  102. std::vector<const ReportingReport*> reports;
  103. context()->cache()->GetReports(&reports);
  104. ASSERT_EQ(1u, reports.size());
  105. EXPECT_EQ(kUrl_, reports[0]->url);
  106. EXPECT_EQ(kNik_, reports[0]->network_isolation_key);
  107. EXPECT_EQ(kUserAgent_, reports[0]->user_agent);
  108. EXPECT_EQ(kGroup_, reports[0]->group);
  109. EXPECT_EQ(kType_, reports[0]->type);
  110. }
  111. TEST_P(ReportingServiceTest, QueueReportSanitizeUrl) {
  112. // Same as kUrl_ but with username, password, and fragment.
  113. GURL url = GURL("https://username:password@origin/path#fragment");
  114. service()->QueueReport(url, kReportingSource_, kNik_, kUserAgent_, kGroup_,
  115. kType_, base::Value::Dict(), 0);
  116. FinishLoading(true /* load_success */);
  117. std::vector<const ReportingReport*> reports;
  118. context()->cache()->GetReports(&reports);
  119. ASSERT_EQ(1u, reports.size());
  120. EXPECT_EQ(kUrl_, reports[0]->url);
  121. EXPECT_EQ(kNik_, reports[0]->network_isolation_key);
  122. EXPECT_EQ(kUserAgent_, reports[0]->user_agent);
  123. EXPECT_EQ(kGroup_, reports[0]->group);
  124. EXPECT_EQ(kType_, reports[0]->type);
  125. }
  126. TEST_P(ReportingServiceTest, DontQueueReportInvalidUrl) {
  127. GURL url = GURL("https://");
  128. // This does not trigger an attempt to load from the store because the url
  129. // is immediately rejected as invalid.
  130. service()->QueueReport(url, kReportingSource_, kNik_, kUserAgent_, kGroup_,
  131. kType_, base::Value::Dict(), 0);
  132. std::vector<const ReportingReport*> reports;
  133. context()->cache()->GetReports(&reports);
  134. ASSERT_EQ(0u, reports.size());
  135. }
  136. TEST_P(ReportingServiceTest, QueueReportNetworkIsolationKeyDisabled) {
  137. base::test::ScopedFeatureList feature_list;
  138. feature_list.InitAndDisableFeature(
  139. features::kPartitionNelAndReportingByNetworkIsolationKey);
  140. // Re-create the store, so it reads the new feature value.
  141. Init();
  142. service()->QueueReport(kUrl_, kReportingSource_, kNik_, kUserAgent_, kGroup_,
  143. kType_, base::Value::Dict(), 0);
  144. FinishLoading(true /* load_success */);
  145. std::vector<const ReportingReport*> reports;
  146. context()->cache()->GetReports(&reports);
  147. ASSERT_EQ(1u, reports.size());
  148. // NetworkIsolationKey should be empty, instead of kNik_;
  149. EXPECT_EQ(NetworkIsolationKey(), reports[0]->network_isolation_key);
  150. EXPECT_NE(kNik_, reports[0]->network_isolation_key);
  151. EXPECT_EQ(kUrl_, reports[0]->url);
  152. EXPECT_EQ(kUserAgent_, reports[0]->user_agent);
  153. EXPECT_EQ(kGroup_, reports[0]->group);
  154. EXPECT_EQ(kType_, reports[0]->type);
  155. }
  156. TEST_P(ReportingServiceTest, ProcessReportToHeader) {
  157. service()->ProcessReportToHeader(kOrigin_, kNik_,
  158. "{\"endpoints\":[{\"url\":\"" +
  159. kEndpoint_.spec() +
  160. "\"}],"
  161. "\"group\":\"" +
  162. kGroup_ +
  163. "\","
  164. "\"max_age\":86400}");
  165. FinishLoading(true /* load_success */);
  166. EXPECT_EQ(1u, context()->cache()->GetEndpointCount());
  167. EXPECT_TRUE(context()->cache()->GetEndpointForTesting(
  168. ReportingEndpointGroupKey(kNik_, kOrigin_, kGroup_), kEndpoint_));
  169. }
  170. TEST_P(ReportingServiceTest, ProcessReportingEndpointsHeader) {
  171. base::test::ScopedFeatureList feature_list;
  172. feature_list.InitAndEnableFeature(net::features::kDocumentReporting);
  173. auto parsed_header =
  174. ParseReportingEndpoints(kGroup_ + "=\"" + kEndpoint_.spec() + "\"");
  175. ASSERT_TRUE(parsed_header.has_value());
  176. service()->SetDocumentReportingEndpoints(*kReportingSource_, kOrigin_,
  177. kIsolationInfo_, *parsed_header);
  178. FinishLoading(true /* load_success */);
  179. // Endpoint should not be part of the persistent store.
  180. EXPECT_EQ(0u, context()->cache()->GetEndpointCount());
  181. // Endpoint should be associated with the reporting source.
  182. ReportingEndpoint cached_endpoint =
  183. context()->cache()->GetV1EndpointForTesting(*kReportingSource_, kGroup_);
  184. EXPECT_TRUE(cached_endpoint);
  185. // Ensure that the NIK is stored properly with the endpoint group.
  186. EXPECT_FALSE(cached_endpoint.group_key.network_isolation_key.IsEmpty());
  187. }
  188. TEST_P(ReportingServiceTest,
  189. ProcessReportingEndpointsHeaderNetworkIsolationKeyDisabled) {
  190. base::test::ScopedFeatureList feature_list;
  191. feature_list.InitWithFeatures(
  192. {net::features::kDocumentReporting},
  193. {features::kPartitionNelAndReportingByNetworkIsolationKey});
  194. // Re-create the store, so it reads the new feature value.
  195. Init();
  196. auto parsed_header =
  197. ParseReportingEndpoints(kGroup_ + "=\"" + kEndpoint_.spec() + "\"");
  198. ASSERT_TRUE(parsed_header.has_value());
  199. service()->SetDocumentReportingEndpoints(*kReportingSource_, kOrigin_,
  200. kIsolationInfo_, *parsed_header);
  201. FinishLoading(true /* load_success */);
  202. // Endpoint should not be part of the persistent store.
  203. EXPECT_EQ(0u, context()->cache()->GetEndpointCount());
  204. // Endpoint should be associated with the reporting source.
  205. ReportingEndpoint cached_endpoint =
  206. context()->cache()->GetV1EndpointForTesting(*kReportingSource_, kGroup_);
  207. EXPECT_TRUE(cached_endpoint);
  208. // When isolation is disabled, cached endpoints should have a null NIK.
  209. EXPECT_TRUE(cached_endpoint.group_key.network_isolation_key.IsEmpty());
  210. }
  211. TEST_P(ReportingServiceTest, SendReportsAndRemoveSource) {
  212. base::test::ScopedFeatureList feature_list;
  213. feature_list.InitAndEnableFeature(net::features::kDocumentReporting);
  214. auto parsed_header =
  215. ParseReportingEndpoints(kGroup_ + "=\"" + kEndpoint_.spec() + "\", " +
  216. kGroup2_ + "=\"" + kEndpoint2_.spec() + "\"");
  217. ASSERT_TRUE(parsed_header.has_value());
  218. service()->SetDocumentReportingEndpoints(*kReportingSource_, kOrigin_,
  219. kIsolationInfo_, *parsed_header);
  220. // This report should be sent immediately, starting the delivery agent timer.
  221. service()->QueueReport(kUrl_, kReportingSource_, kNik_, kUserAgent_, kGroup_,
  222. kType_, base::Value::Dict(), 0);
  223. FinishLoading(true /* load_success */);
  224. std::vector<const ReportingReport*> reports;
  225. context()->cache()->GetReports(&reports);
  226. ASSERT_EQ(1u, reports.size());
  227. EXPECT_EQ(0u, context()->cache()->GetReportCountWithStatusForTesting(
  228. ReportingReport::Status::QUEUED));
  229. // Now simulate the source being destroyed.
  230. service()->SendReportsAndRemoveSource(*kReportingSource_);
  231. // There should be no queued reports, but the previously sent report should
  232. // still be pending.
  233. EXPECT_EQ(0u, context()->cache()->GetReportCountWithStatusForTesting(
  234. ReportingReport::Status::QUEUED));
  235. EXPECT_EQ(1u, context()->cache()->GetReportCountWithStatusForTesting(
  236. ReportingReport::Status::PENDING));
  237. // Source should be marked as expired.
  238. ASSERT_TRUE(
  239. context()->cache()->GetExpiredSources().contains(*kReportingSource_));
  240. }
  241. TEST_P(ReportingServiceTest, SendReportsAndRemoveSourceWithPendingReports) {
  242. base::test::ScopedFeatureList feature_list;
  243. feature_list.InitAndEnableFeature(net::features::kDocumentReporting);
  244. auto parsed_header =
  245. ParseReportingEndpoints(kGroup_ + "=\"" + kEndpoint_.spec() + "\", " +
  246. kGroup2_ + "=\"" + kEndpoint2_.spec() + "\"");
  247. ASSERT_TRUE(parsed_header.has_value());
  248. service()->SetDocumentReportingEndpoints(*kReportingSource_, kOrigin_,
  249. kIsolationInfo_, *parsed_header);
  250. // This report should be sent immediately, starting the delivery agent timer.
  251. service()->QueueReport(kUrl_, kReportingSource_, kNik_, kUserAgent_, kGroup_,
  252. kType_, base::Value::Dict(), 0);
  253. FinishLoading(true /* load_success */);
  254. std::vector<const ReportingReport*> reports;
  255. context()->cache()->GetReports(&reports);
  256. ASSERT_EQ(1u, reports.size());
  257. EXPECT_EQ(0u, context()->cache()->GetReportCountWithStatusForTesting(
  258. ReportingReport::Status::QUEUED));
  259. EXPECT_EQ(1u, context()->cache()->GetReportCountWithStatusForTesting(
  260. ReportingReport::Status::PENDING));
  261. // Queue another report, which should remain queued.
  262. service()->QueueReport(kUrl_, kReportingSource_, kNik_, kUserAgent_, kGroup_,
  263. kType_, base::Value::Dict(), 0);
  264. EXPECT_EQ(1u, context()->cache()->GetReportCountWithStatusForTesting(
  265. ReportingReport::Status::QUEUED));
  266. EXPECT_EQ(1u, context()->cache()->GetReportCountWithStatusForTesting(
  267. ReportingReport::Status::PENDING));
  268. // Now simulate the source being destroyed.
  269. service()->SendReportsAndRemoveSource(*kReportingSource_);
  270. // The report should still be queued, while the source should be marked as
  271. // expired. (The original report is still pending.)
  272. EXPECT_EQ(1u, context()->cache()->GetReportCountWithStatusForTesting(
  273. ReportingReport::Status::QUEUED));
  274. EXPECT_EQ(1u, context()->cache()->GetReportCountWithStatusForTesting(
  275. ReportingReport::Status::PENDING));
  276. ASSERT_TRUE(
  277. context()->cache()->GetExpiredSources().contains(kReportingSource_));
  278. }
  279. #if BUILDFLAG(IS_CHROMEOS)
  280. #define MAYBE_ProcessReportingEndpointsHeaderPathAbsolute DISABLED_ProcessReportingEndpointsHeaderPathAbsolute
  281. #else
  282. #define MAYBE_ProcessReportingEndpointsHeaderPathAbsolute ProcessReportingEndpointsHeaderPathAbsolute
  283. #endif
  284. TEST_P(ReportingServiceTest, MAYBE_ProcessReportingEndpointsHeaderPathAbsolute) {
  285. base::test::ScopedFeatureList feature_list;
  286. feature_list.InitAndEnableFeature(net::features::kDocumentReporting);
  287. auto parsed_header = ParseReportingEndpoints(kGroup_ + "=\"/path-absolute\"");
  288. ASSERT_TRUE(parsed_header.has_value());
  289. service()->SetDocumentReportingEndpoints(*kReportingSource_, kOrigin_,
  290. kIsolationInfo_, *parsed_header);
  291. FinishLoading(true /* load_success */);
  292. // Endpoint should not be part of the persistent store.
  293. EXPECT_EQ(0u, context()->cache()->GetEndpointCount());
  294. // Endpoint should be associated with the reporting source.
  295. ReportingEndpoint endpoint =
  296. context()->cache()->GetV1EndpointForTesting(*kReportingSource_, kGroup_);
  297. EXPECT_TRUE(endpoint);
  298. // Endpoint should have the correct path.
  299. EXPECT_EQ(kUrl_.Resolve("/path-absolute"), endpoint.info.url);
  300. }
  301. TEST_P(ReportingServiceTest, ProcessReportToHeaderPathAbsolute) {
  302. service()->ProcessReportToHeader(
  303. kOrigin_, kNik_,
  304. "{\"endpoints\":[{\"url\":\"/path-absolute\"}],"
  305. "\"group\":\"" +
  306. kGroup_ +
  307. "\","
  308. "\"max_age\":86400}");
  309. FinishLoading(true /* load_success */);
  310. EXPECT_EQ(1u, context()->cache()->GetEndpointCount());
  311. }
  312. TEST_P(ReportingServiceTest, ProcessReportToHeader_TooLong) {
  313. const std::string header_too_long =
  314. "{\"endpoints\":[{\"url\":\"" + kEndpoint_.spec() +
  315. "\"}],"
  316. "\"group\":\"" +
  317. kGroup_ +
  318. "\","
  319. "\"max_age\":86400," +
  320. "\"junk\":\"" + std::string(32 * 1024, 'a') + "\"}";
  321. // This does not trigger an attempt to load from the store because the header
  322. // is immediately rejected as invalid.
  323. service()->ProcessReportToHeader(kOrigin_, kNik_, header_too_long);
  324. EXPECT_EQ(0u, context()->cache()->GetEndpointCount());
  325. }
  326. TEST_P(ReportingServiceTest, ProcessReportToHeader_TooDeep) {
  327. const std::string header_too_deep = "{\"endpoints\":[{\"url\":\"" +
  328. kEndpoint_.spec() +
  329. "\"}],"
  330. "\"group\":\"" +
  331. kGroup_ +
  332. "\","
  333. "\"max_age\":86400," +
  334. "\"junk\":[[[[[[[[[[]]]]]]]]]]}";
  335. // This does not trigger an attempt to load from the store because the header
  336. // is immediately rejected as invalid.
  337. service()->ProcessReportToHeader(kOrigin_, kNik_, header_too_deep);
  338. EXPECT_EQ(0u, context()->cache()->GetEndpointCount());
  339. }
  340. TEST_P(ReportingServiceTest, ProcessReportToHeaderNetworkIsolationKeyDisabled) {
  341. base::test::ScopedFeatureList feature_list;
  342. feature_list.InitAndDisableFeature(
  343. features::kPartitionNelAndReportingByNetworkIsolationKey);
  344. // Re-create the store, so it reads the new feature value.
  345. Init();
  346. service()->ProcessReportToHeader(kOrigin_, kNik_,
  347. "{\"endpoints\":[{\"url\":\"" +
  348. kEndpoint_.spec() +
  349. "\"}],"
  350. "\"group\":\"" +
  351. kGroup_ +
  352. "\","
  353. "\"max_age\":86400}");
  354. FinishLoading(true /* load_success */);
  355. EXPECT_EQ(1u, context()->cache()->GetEndpointCount());
  356. EXPECT_FALSE(context()->cache()->GetEndpointForTesting(
  357. ReportingEndpointGroupKey(kNik_, kOrigin_, kGroup_), kEndpoint_));
  358. EXPECT_TRUE(context()->cache()->GetEndpointForTesting(
  359. ReportingEndpointGroupKey(NetworkIsolationKey(), kOrigin_, kGroup_),
  360. kEndpoint_));
  361. }
  362. TEST_P(ReportingServiceTest, WriteToStore) {
  363. if (!store())
  364. return;
  365. MockPersistentReportingStore::CommandList expected_commands;
  366. // This first call to any public method triggers a load. The load will block
  367. // until we call FinishLoading.
  368. service()->ProcessReportToHeader(kOrigin_, kNik_,
  369. "{\"endpoints\":[{\"url\":\"" +
  370. kEndpoint_.spec() +
  371. "\"}],"
  372. "\"group\":\"" +
  373. kGroup_ +
  374. "\","
  375. "\"max_age\":86400}");
  376. expected_commands.emplace_back(CommandType::LOAD_REPORTING_CLIENTS);
  377. EXPECT_THAT(store()->GetAllCommands(),
  378. testing::UnorderedElementsAreArray(expected_commands));
  379. // Unblock the load. The will let the remaining calls to the service complete
  380. // without blocking.
  381. FinishLoading(true /* load_success */);
  382. expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
  383. kGroupKey_, kEndpoint_);
  384. expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
  385. kGroupKey_);
  386. EXPECT_THAT(store()->GetAllCommands(),
  387. testing::UnorderedElementsAreArray(expected_commands));
  388. service()->ProcessReportToHeader(kOrigin2_, kNik2_,
  389. "{\"endpoints\":[{\"url\":\"" +
  390. kEndpoint_.spec() +
  391. "\"}],"
  392. "\"group\":\"" +
  393. kGroup_ +
  394. "\","
  395. "\"max_age\":86400}");
  396. expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
  397. kGroupKey2_, kEndpoint_);
  398. expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
  399. kGroupKey2_);
  400. EXPECT_THAT(store()->GetAllCommands(),
  401. testing::UnorderedElementsAreArray(expected_commands));
  402. service()->QueueReport(kUrl_, kReportingSource_, kNik_, kUserAgent_, kGroup_,
  403. kType_, base::Value::Dict(), 0);
  404. expected_commands.emplace_back(
  405. CommandType::UPDATE_REPORTING_ENDPOINT_GROUP_ACCESS_TIME, kGroupKey_);
  406. EXPECT_THAT(store()->GetAllCommands(),
  407. testing::UnorderedElementsAreArray(expected_commands));
  408. service()->RemoveBrowsingData(
  409. ReportingBrowsingDataRemover::DATA_TYPE_CLIENTS,
  410. base::BindRepeating(
  411. [](const url::Origin& origin) { return origin.host() == "origin"; }));
  412. expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
  413. kGroupKey_, kEndpoint_);
  414. expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT_GROUP,
  415. kGroupKey_);
  416. expected_commands.emplace_back(CommandType::FLUSH);
  417. EXPECT_THAT(store()->GetAllCommands(),
  418. testing::UnorderedElementsAreArray(expected_commands));
  419. service()->RemoveAllBrowsingData(
  420. ReportingBrowsingDataRemover::DATA_TYPE_CLIENTS);
  421. expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
  422. kGroupKey2_, kEndpoint_);
  423. expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT_GROUP,
  424. kGroupKey2_);
  425. expected_commands.emplace_back(CommandType::FLUSH);
  426. EXPECT_THAT(store()->GetAllCommands(),
  427. testing::UnorderedElementsAreArray(expected_commands));
  428. }
  429. TEST_P(ReportingServiceTest, WaitUntilLoadFinishesBeforeWritingToStore) {
  430. if (!store())
  431. return;
  432. MockPersistentReportingStore::CommandList expected_commands;
  433. // This first call to any public method triggers a load. The load will block
  434. // until we call FinishLoading.
  435. service()->ProcessReportToHeader(kOrigin_, kNik_,
  436. "{\"endpoints\":[{\"url\":\"" +
  437. kEndpoint_.spec() +
  438. "\"}],"
  439. "\"group\":\"" +
  440. kGroup_ +
  441. "\","
  442. "\"max_age\":86400}");
  443. expected_commands.emplace_back(CommandType::LOAD_REPORTING_CLIENTS);
  444. EXPECT_THAT(store()->GetAllCommands(),
  445. testing::UnorderedElementsAreArray(expected_commands));
  446. service()->ProcessReportToHeader(kOrigin2_, kNik2_,
  447. "{\"endpoints\":[{\"url\":\"" +
  448. kEndpoint_.spec() +
  449. "\"}],"
  450. "\"group\":\"" +
  451. kGroup_ +
  452. "\","
  453. "\"max_age\":86400}");
  454. EXPECT_THAT(store()->GetAllCommands(),
  455. testing::UnorderedElementsAreArray(expected_commands));
  456. service()->QueueReport(kUrl_, kReportingSource_, kNik_, kUserAgent_, kGroup_,
  457. kType_, base::Value::Dict(), 0);
  458. EXPECT_THAT(store()->GetAllCommands(),
  459. testing::UnorderedElementsAreArray(expected_commands));
  460. service()->RemoveBrowsingData(
  461. ReportingBrowsingDataRemover::DATA_TYPE_CLIENTS,
  462. base::BindRepeating(
  463. [](const url::Origin& origin) { return origin.host() == "origin"; }));
  464. EXPECT_THAT(store()->GetAllCommands(),
  465. testing::UnorderedElementsAreArray(expected_commands));
  466. service()->RemoveAllBrowsingData(
  467. ReportingBrowsingDataRemover::DATA_TYPE_CLIENTS);
  468. EXPECT_THAT(store()->GetAllCommands(),
  469. testing::UnorderedElementsAreArray(expected_commands));
  470. // Unblock the load. The will let the remaining calls to the service complete
  471. // without blocking.
  472. FinishLoading(true /* load_success */);
  473. expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
  474. kGroupKey_, kEndpoint_);
  475. expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
  476. kGroupKey2_, kEndpoint_);
  477. expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
  478. kGroupKey_);
  479. expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
  480. kGroupKey2_);
  481. expected_commands.emplace_back(
  482. CommandType::UPDATE_REPORTING_ENDPOINT_GROUP_ACCESS_TIME, kGroupKey_);
  483. expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
  484. kGroupKey_, kEndpoint_);
  485. expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT_GROUP,
  486. kGroupKey_);
  487. expected_commands.emplace_back(CommandType::FLUSH);
  488. expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
  489. kGroupKey2_, kEndpoint_);
  490. expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT_GROUP,
  491. kGroupKey2_);
  492. expected_commands.emplace_back(CommandType::FLUSH);
  493. EXPECT_THAT(store()->GetAllCommands(),
  494. testing::UnorderedElementsAreArray(expected_commands));
  495. }
  496. INSTANTIATE_TEST_SUITE_P(ReportingServiceStoreTest,
  497. ReportingServiceTest,
  498. ::testing::Bool());
  499. } // namespace
  500. } // namespace net