diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-07-31 15:50:41 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-30 12:35:23 +0000 |
commit | 7b2ffa587235a47d4094787d72f38102089f402a (patch) | |
tree | 30e82af9cbab08a7fa028bb18f4f2987a3f74dfa /chromium/net/network_error_logging | |
parent | d94af01c90575348c4e81a418257f254b6f8d225 (diff) | |
download | qtwebengine-chromium-7b2ffa587235a47d4094787d72f38102089f402a.tar.gz |
BASELINE: Update Chromium to 76.0.3809.94
Change-Id: I321c3f5f929c105aec0f98c5091ef6108822e647
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/net/network_error_logging')
9 files changed, 941 insertions, 394 deletions
diff --git a/chromium/net/network_error_logging/mock_persistent_nel_store.cc b/chromium/net/network_error_logging/mock_persistent_nel_store.cc index 1f0fa8ceb43..9de31285f7f 100644 --- a/chromium/net/network_error_logging/mock_persistent_nel_store.cc +++ b/chromium/net/network_error_logging/mock_persistent_nel_store.cc @@ -8,82 +8,82 @@ namespace net { -MockPersistentNELStore::Command::Command( +MockPersistentNelStore::Command::Command( Type type, - NELPoliciesLoadedCallback loaded_callback) + NelPoliciesLoadedCallback loaded_callback) : type(type), loaded_callback(std::move(loaded_callback)) {} -MockPersistentNELStore::Command::Command( +MockPersistentNelStore::Command::Command( Type type, - const NetworkErrorLoggingService::NELPolicy& policy) + const NetworkErrorLoggingService::NelPolicy& policy) : type(type), origin(policy.origin) {} -MockPersistentNELStore::Command::Command(Type type) : type(type) {} +MockPersistentNelStore::Command::Command(Type type) : type(type) {} -MockPersistentNELStore::Command::Command(const Command& other) +MockPersistentNelStore::Command::Command(const Command& other) : type(other.type), origin(other.origin) {} -MockPersistentNELStore::Command::Command(Command&& other) = default; +MockPersistentNelStore::Command::Command(Command&& other) = default; -MockPersistentNELStore::Command::~Command() = default; +MockPersistentNelStore::Command::~Command() = default; -bool operator==(const MockPersistentNELStore::Command& lhs, - const MockPersistentNELStore::Command& rhs) { +bool operator==(const MockPersistentNelStore::Command& lhs, + const MockPersistentNelStore::Command& rhs) { if (lhs.type != rhs.type) return false; switch (lhs.type) { // For LOAD_NEL_POLICIES and FLUSH, just check the type. - case MockPersistentNELStore::Command::Type::LOAD_NEL_POLICIES: - case MockPersistentNELStore::Command::Type::FLUSH: + case MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES: + case MockPersistentNelStore::Command::Type::FLUSH: return true; // For ADD_NEL_POLICY, UPDATE_NEL_POLICY, and DELETE_NEL_POLICY, // additionally check the policy's origin. - case MockPersistentNELStore::Command::Type::ADD_NEL_POLICY: - case MockPersistentNELStore::Command::Type::UPDATE_NEL_POLICY: - case MockPersistentNELStore::Command::Type::DELETE_NEL_POLICY: + case MockPersistentNelStore::Command::Type::ADD_NEL_POLICY: + case MockPersistentNelStore::Command::Type::UPDATE_NEL_POLICY: + case MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY: return (lhs.origin == rhs.origin); } } -bool operator!=(const MockPersistentNELStore::Command& lhs, - const MockPersistentNELStore::Command& rhs) { +bool operator!=(const MockPersistentNelStore::Command& lhs, + const MockPersistentNelStore::Command& rhs) { return !(lhs == rhs); } -MockPersistentNELStore::MockPersistentNELStore() +MockPersistentNelStore::MockPersistentNelStore() : load_started_(false), policy_count_(0), queued_policy_count_delta_(0) {} -MockPersistentNELStore::~MockPersistentNELStore() = default; +MockPersistentNelStore::~MockPersistentNelStore() = default; -void MockPersistentNELStore::LoadNELPolicies( - NELPoliciesLoadedCallback loaded_callback) { +void MockPersistentNelStore::LoadNelPolicies( + NelPoliciesLoadedCallback loaded_callback) { DCHECK(!load_started_); command_list_.emplace_back(Command::Type::LOAD_NEL_POLICIES, std::move(loaded_callback)); load_started_ = true; } -void MockPersistentNELStore::AddNELPolicy( - const NetworkErrorLoggingService::NELPolicy& policy) { +void MockPersistentNelStore::AddNelPolicy( + const NetworkErrorLoggingService::NelPolicy& policy) { DCHECK(load_started_); command_list_.emplace_back(Command::Type::ADD_NEL_POLICY, policy); ++queued_policy_count_delta_; } -void MockPersistentNELStore::UpdateNELPolicyAccessTime( - const NetworkErrorLoggingService::NELPolicy& policy) { +void MockPersistentNelStore::UpdateNelPolicyAccessTime( + const NetworkErrorLoggingService::NelPolicy& policy) { DCHECK(load_started_); command_list_.emplace_back(Command::Type::UPDATE_NEL_POLICY, policy); } -void MockPersistentNELStore::DeleteNELPolicy( - const NetworkErrorLoggingService::NELPolicy& policy) { +void MockPersistentNelStore::DeleteNelPolicy( + const NetworkErrorLoggingService::NelPolicy& policy) { DCHECK(load_started_); command_list_.emplace_back(Command::Type::DELETE_NEL_POLICY, policy); --queued_policy_count_delta_; } -void MockPersistentNELStore::Flush() { +void MockPersistentNelStore::Flush() { // Can be called before |load_started_| is true, if the // NetworkErrorLoggingService is destroyed before getting a chance to load. command_list_.emplace_back(Command::Type::FLUSH); @@ -91,15 +91,15 @@ void MockPersistentNELStore::Flush() { queued_policy_count_delta_ = 0; } -void MockPersistentNELStore::SetPrestoredPolicies( - std::vector<NetworkErrorLoggingService::NELPolicy> policies) { +void MockPersistentNelStore::SetPrestoredPolicies( + std::vector<NetworkErrorLoggingService::NelPolicy> policies) { DCHECK(!load_started_); DCHECK_EQ(0, policy_count_); policy_count_ += policies.size(); prestored_policies_.swap(policies); } -void MockPersistentNELStore::FinishLoading(bool load_success) { +void MockPersistentNelStore::FinishLoading(bool load_success) { DCHECK(load_started_); for (size_t i = 0; i < command_list_.size(); ++i) { Command& command = command_list_[i]; @@ -112,7 +112,7 @@ void MockPersistentNELStore::FinishLoading(bool load_success) { std::move(command.loaded_callback).Run(std::move(prestored_policies_)); } else { std::move(command.loaded_callback) - .Run(std::vector<NetworkErrorLoggingService::NELPolicy>()); + .Run(std::vector<NetworkErrorLoggingService::NelPolicy>()); } } if (i > 0) { @@ -122,17 +122,17 @@ void MockPersistentNELStore::FinishLoading(bool load_success) { } } -bool MockPersistentNELStore::VerifyCommands( +bool MockPersistentNelStore::VerifyCommands( const CommandList& expected_commands) const { return command_list_ == expected_commands; } -MockPersistentNELStore::CommandList MockPersistentNELStore::GetAllCommands() +MockPersistentNelStore::CommandList MockPersistentNelStore::GetAllCommands() const { return command_list_; } -std::string MockPersistentNELStore::GetDebugString() const { +std::string MockPersistentNelStore::GetDebugString() const { std::ostringstream s; for (const Command& command : command_list_) { diff --git a/chromium/net/network_error_logging/mock_persistent_nel_store.h b/chromium/net/network_error_logging/mock_persistent_nel_store.h index 9f0d180a25f..cbf2f52add0 100644 --- a/chromium/net/network_error_logging/mock_persistent_nel_store.h +++ b/chromium/net/network_error_logging/mock_persistent_nel_store.h @@ -15,14 +15,14 @@ namespace net { -// A NetworkErrorLoggingService::PersistentNELStore implementation that stashes +// A NetworkErrorLoggingService::PersistentNelStore implementation that stashes // the received commands in order in a vector, to be checked by tests. // Simulates loading pre-existing stored policies, which can be provided // using SetLoadExpectation(). -class MockPersistentNELStore - : public NetworkErrorLoggingService::PersistentNELStore { +class MockPersistentNelStore + : public NetworkErrorLoggingService::PersistentNelStore { public: - // Represents a command that has been passed to the MockPersistentNELStore. + // Represents a command that has been passed to the MockPersistentNelStore. struct Command { enum class Type { LOAD_NEL_POLICIES, @@ -33,10 +33,10 @@ class MockPersistentNELStore }; // Constructor for LOAD_NEL_POLICIES commands. - Command(Type type, NELPoliciesLoadedCallback loaded_callback); + Command(Type type, NelPoliciesLoadedCallback loaded_callback); // Constructor for ADD_NEL_POLICY, UPDATE_NEL_POLICY, and DELETE_NEL_POLICY // commands. - Command(Type type, const NetworkErrorLoggingService::NELPolicy& policy); + Command(Type type, const NetworkErrorLoggingService::NelPolicy& policy); // Constructor for FLUSH commands. Command(Type type); @@ -54,28 +54,28 @@ class MockPersistentNELStore // The supplied callback to be run when loading is complete. (Only applies // for load commands). - NELPoliciesLoadedCallback loaded_callback; + NelPoliciesLoadedCallback loaded_callback; }; using CommandList = std::vector<Command>; - MockPersistentNELStore(); - ~MockPersistentNELStore() override; - - // PersistentNELStore implementation: - void LoadNELPolicies(NELPoliciesLoadedCallback loaded_callback) override; - void AddNELPolicy( - const NetworkErrorLoggingService::NELPolicy& policy) override; - void UpdateNELPolicyAccessTime( - const NetworkErrorLoggingService::NELPolicy& policy) override; - void DeleteNELPolicy( - const NetworkErrorLoggingService::NELPolicy& policy) override; + MockPersistentNelStore(); + ~MockPersistentNelStore() override; + + // PersistentNelStore implementation: + void LoadNelPolicies(NelPoliciesLoadedCallback loaded_callback) override; + void AddNelPolicy( + const NetworkErrorLoggingService::NelPolicy& policy) override; + void UpdateNelPolicyAccessTime( + const NetworkErrorLoggingService::NelPolicy& policy) override; + void DeleteNelPolicy( + const NetworkErrorLoggingService::NelPolicy& policy) override; void Flush() override; // Simulates pre-existing policies that were stored previously. Should only be // called once, at the beginning of the test before any other method calls. void SetPrestoredPolicies( - std::vector<NetworkErrorLoggingService::NELPolicy> policies); + std::vector<NetworkErrorLoggingService::NelPolicy> policies); // Simulate finishing loading policies by executing the loaded_callback of the // first LOAD_NEL_POLICIES command (which should also be the only @@ -102,9 +102,9 @@ class MockPersistentNELStore CommandList command_list_; // Simulated pre-existing stored policies. - std::vector<NetworkErrorLoggingService::NELPolicy> prestored_policies_; + std::vector<NetworkErrorLoggingService::NelPolicy> prestored_policies_; - // Set when LoadNELPolicies() is called. + // Set when LoadNelPolicies() is called. bool load_started_; // Simulates the total number of policies that would be stored in the store. @@ -115,13 +115,13 @@ class MockPersistentNELStore // called. Reset to 0 when Flush() is called. int queued_policy_count_delta_; - DISALLOW_COPY_AND_ASSIGN(MockPersistentNELStore); + DISALLOW_COPY_AND_ASSIGN(MockPersistentNelStore); }; -bool operator==(const MockPersistentNELStore::Command& lhs, - const MockPersistentNELStore::Command& rhs); -bool operator!=(const MockPersistentNELStore::Command& lhs, - const MockPersistentNELStore::Command& rhs); +bool operator==(const MockPersistentNelStore::Command& lhs, + const MockPersistentNelStore::Command& rhs); +bool operator!=(const MockPersistentNelStore::Command& lhs, + const MockPersistentNelStore::Command& rhs); } // namespace net diff --git a/chromium/net/network_error_logging/mock_persistent_nel_store_unittest.cc b/chromium/net/network_error_logging/mock_persistent_nel_store_unittest.cc index 3c976afa7a0..2835df49cb4 100644 --- a/chromium/net/network_error_logging/mock_persistent_nel_store_unittest.cc +++ b/chromium/net/network_error_logging/mock_persistent_nel_store_unittest.cc @@ -17,8 +17,8 @@ namespace net { namespace { const url::Origin kOrigin = url::Origin::Create(GURL("https://example.test/")); -NetworkErrorLoggingService::NELPolicy MakePolicyForOrigin(url::Origin origin) { - NetworkErrorLoggingService::NELPolicy policy; +NetworkErrorLoggingService::NelPolicy MakePolicyForOrigin(url::Origin origin) { + NetworkErrorLoggingService::NelPolicy policy; policy.origin = std::move(origin); policy.expires = base::Time(); policy.last_used = base::Time(); @@ -26,34 +26,34 @@ NetworkErrorLoggingService::NELPolicy MakePolicyForOrigin(url::Origin origin) { return policy; } -void RunClosureOnNELPoliciesLoaded( +void RunClosureOnNelPoliciesLoaded( base::OnceClosure closure, - std::vector<NetworkErrorLoggingService::NELPolicy>* policies_out, - std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies) { + std::vector<NetworkErrorLoggingService::NelPolicy>* policies_out, + std::vector<NetworkErrorLoggingService::NelPolicy> loaded_policies) { std::move(closure).Run(); loaded_policies.swap(*policies_out); } -// Makes a NELPoliciesLoadedCallback that will fail if it's never run before +// Makes a NelPoliciesLoadedCallback that will fail if it's never run before // destruction. -MockPersistentNELStore::NELPoliciesLoadedCallback -MakeExpectedRunNELPoliciesLoadedCallback( - std::vector<NetworkErrorLoggingService::NELPolicy>* policies_out) { +MockPersistentNelStore::NelPoliciesLoadedCallback +MakeExpectedRunNelPoliciesLoadedCallback( + std::vector<NetworkErrorLoggingService::NelPolicy>* policies_out) { base::OnceClosure closure = base::MakeExpectedRunClosure(FROM_HERE); - return base::BindOnce(&RunClosureOnNELPoliciesLoaded, std::move(closure), + return base::BindOnce(&RunClosureOnNelPoliciesLoaded, std::move(closure), policies_out); } // Test that FinishLoading() runs the callback. -TEST(MockPersistentNELStoreTest, FinishLoading) { - MockPersistentNELStore store; - MockPersistentNELStore::CommandList expected_commands; - std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies; +TEST(MockPersistentNelStoreTest, FinishLoading) { + MockPersistentNelStore store; + MockPersistentNelStore::CommandList expected_commands; + std::vector<NetworkErrorLoggingService::NelPolicy> loaded_policies; - store.LoadNELPolicies( - MakeExpectedRunNELPoliciesLoadedCallback(&loaded_policies)); + store.LoadNelPolicies( + MakeExpectedRunNelPoliciesLoadedCallback(&loaded_policies)); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::LOAD_NEL_POLICIES); + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); store.FinishLoading(true /* load_success */); EXPECT_EQ(0u, loaded_policies.size()); @@ -65,20 +65,20 @@ TEST(MockPersistentNELStoreTest, FinishLoading) { // Test should not crash because the callback has been run. } -TEST(MockPersistentNELStoreTest, PreStoredPolicies) { - MockPersistentNELStore store; - MockPersistentNELStore::CommandList expected_commands; - std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies; +TEST(MockPersistentNelStoreTest, PreStoredPolicies) { + MockPersistentNelStore store; + MockPersistentNelStore::CommandList expected_commands; + std::vector<NetworkErrorLoggingService::NelPolicy> loaded_policies; - std::vector<NetworkErrorLoggingService::NELPolicy> prestored_policies = { + std::vector<NetworkErrorLoggingService::NelPolicy> prestored_policies = { MakePolicyForOrigin(kOrigin)}; store.SetPrestoredPolicies(std::move(prestored_policies)); EXPECT_EQ(1, store.StoredPoliciesCount()); - store.LoadNELPolicies( - MakeExpectedRunNELPoliciesLoadedCallback(&loaded_policies)); + store.LoadNelPolicies( + MakeExpectedRunNelPoliciesLoadedCallback(&loaded_policies)); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::LOAD_NEL_POLICIES); + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); store.FinishLoading(true /* load_success */); ASSERT_EQ(1u, loaded_policies.size()); EXPECT_EQ(kOrigin, loaded_policies[0].origin); @@ -89,20 +89,20 @@ TEST(MockPersistentNELStoreTest, PreStoredPolicies) { } // Failed load should yield empty vector of policies. -TEST(MockPersistentNELStoreTest, FailedLoad) { - MockPersistentNELStore store; - MockPersistentNELStore::CommandList expected_commands; - std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies; +TEST(MockPersistentNelStoreTest, FailedLoad) { + MockPersistentNelStore store; + MockPersistentNelStore::CommandList expected_commands; + std::vector<NetworkErrorLoggingService::NelPolicy> loaded_policies; - std::vector<NetworkErrorLoggingService::NELPolicy> prestored_policies = { + std::vector<NetworkErrorLoggingService::NelPolicy> prestored_policies = { MakePolicyForOrigin(kOrigin)}; store.SetPrestoredPolicies(std::move(prestored_policies)); EXPECT_EQ(1, store.StoredPoliciesCount()); - store.LoadNELPolicies( - MakeExpectedRunNELPoliciesLoadedCallback(&loaded_policies)); + store.LoadNelPolicies( + MakeExpectedRunNelPoliciesLoadedCallback(&loaded_policies)); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::LOAD_NEL_POLICIES); + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); store.FinishLoading(false /* load_success */); // The pre-stored policy is not returned because loading failed. EXPECT_EQ(0u, loaded_policies.size()); @@ -112,30 +112,30 @@ TEST(MockPersistentNELStoreTest, FailedLoad) { EXPECT_EQ("LOAD; ", store.GetDebugString()); } -TEST(MockPersistentNELStoreTest, Add) { - MockPersistentNELStore store; - MockPersistentNELStore::CommandList expected_commands; - std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies; +TEST(MockPersistentNelStoreTest, Add) { + MockPersistentNelStore store; + MockPersistentNelStore::CommandList expected_commands; + std::vector<NetworkErrorLoggingService::NelPolicy> loaded_policies; - store.LoadNELPolicies( - MakeExpectedRunNELPoliciesLoadedCallback(&loaded_policies)); + store.LoadNelPolicies( + MakeExpectedRunNelPoliciesLoadedCallback(&loaded_policies)); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::LOAD_NEL_POLICIES); + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); EXPECT_EQ(1u, store.GetAllCommands().size()); store.FinishLoading(true /* load_success */); EXPECT_EQ(0u, loaded_policies.size()); - NetworkErrorLoggingService::NELPolicy policy = MakePolicyForOrigin(kOrigin); - store.AddNELPolicy(policy); + NetworkErrorLoggingService::NelPolicy policy = MakePolicyForOrigin(kOrigin); + store.AddNelPolicy(policy); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::ADD_NEL_POLICY, policy); + MockPersistentNelStore::Command::Type::ADD_NEL_POLICY, policy); // Add operation will be queued; the policy has not actually been stored yet EXPECT_EQ(0, store.StoredPoliciesCount()); EXPECT_EQ(2u, store.GetAllCommands().size()); store.Flush(); - expected_commands.emplace_back(MockPersistentNELStore::Command::Type::FLUSH); + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); EXPECT_EQ(1, store.StoredPoliciesCount()); EXPECT_EQ(3u, store.GetAllCommands().size()); @@ -144,33 +144,33 @@ TEST(MockPersistentNELStoreTest, Add) { store.GetDebugString()); } -TEST(MockPersistentNELStoreTest, AddThenDelete) { - MockPersistentNELStore store; - MockPersistentNELStore::CommandList expected_commands; - std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies; +TEST(MockPersistentNelStoreTest, AddThenDelete) { + MockPersistentNelStore store; + MockPersistentNelStore::CommandList expected_commands; + std::vector<NetworkErrorLoggingService::NelPolicy> loaded_policies; - store.LoadNELPolicies( - MakeExpectedRunNELPoliciesLoadedCallback(&loaded_policies)); + store.LoadNelPolicies( + MakeExpectedRunNelPoliciesLoadedCallback(&loaded_policies)); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::LOAD_NEL_POLICIES); + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); EXPECT_EQ(1u, store.GetAllCommands().size()); store.FinishLoading(true /* load_success */); EXPECT_EQ(0u, loaded_policies.size()); - NetworkErrorLoggingService::NELPolicy policy = MakePolicyForOrigin(kOrigin); - store.AddNELPolicy(policy); + NetworkErrorLoggingService::NelPolicy policy = MakePolicyForOrigin(kOrigin); + store.AddNelPolicy(policy); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::ADD_NEL_POLICY, policy); + MockPersistentNelStore::Command::Type::ADD_NEL_POLICY, policy); EXPECT_EQ(2u, store.GetAllCommands().size()); - store.DeleteNELPolicy(policy); + store.DeleteNelPolicy(policy); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::DELETE_NEL_POLICY, policy); + MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY, policy); EXPECT_EQ(3u, store.GetAllCommands().size()); store.Flush(); - expected_commands.emplace_back(MockPersistentNELStore::Command::Type::FLUSH); + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); EXPECT_EQ(0, store.StoredPoliciesCount()); EXPECT_EQ(4u, store.GetAllCommands().size()); @@ -182,38 +182,38 @@ TEST(MockPersistentNELStoreTest, AddThenDelete) { store.GetDebugString()); } -TEST(MockPersistentNELStoreTest, AddFlushThenDelete) { - MockPersistentNELStore store; - MockPersistentNELStore::CommandList expected_commands; - std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies; +TEST(MockPersistentNelStoreTest, AddFlushThenDelete) { + MockPersistentNelStore store; + MockPersistentNelStore::CommandList expected_commands; + std::vector<NetworkErrorLoggingService::NelPolicy> loaded_policies; - store.LoadNELPolicies( - MakeExpectedRunNELPoliciesLoadedCallback(&loaded_policies)); + store.LoadNelPolicies( + MakeExpectedRunNelPoliciesLoadedCallback(&loaded_policies)); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::LOAD_NEL_POLICIES); + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); EXPECT_EQ(1u, store.GetAllCommands().size()); store.FinishLoading(true /* load_success */); EXPECT_EQ(0u, loaded_policies.size()); - NetworkErrorLoggingService::NELPolicy policy = MakePolicyForOrigin(kOrigin); - store.AddNELPolicy(policy); + NetworkErrorLoggingService::NelPolicy policy = MakePolicyForOrigin(kOrigin); + store.AddNelPolicy(policy); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::ADD_NEL_POLICY, policy); + MockPersistentNelStore::Command::Type::ADD_NEL_POLICY, policy); EXPECT_EQ(2u, store.GetAllCommands().size()); store.Flush(); - expected_commands.emplace_back(MockPersistentNELStore::Command::Type::FLUSH); + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); EXPECT_EQ(1, store.StoredPoliciesCount()); EXPECT_EQ(3u, store.GetAllCommands().size()); - store.DeleteNELPolicy(policy); + store.DeleteNelPolicy(policy); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::DELETE_NEL_POLICY, policy); + MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY, policy); EXPECT_EQ(4u, store.GetAllCommands().size()); store.Flush(); - expected_commands.emplace_back(MockPersistentNELStore::Command::Type::FLUSH); + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); EXPECT_EQ(0, store.StoredPoliciesCount()); EXPECT_EQ(5u, store.GetAllCommands().size()); @@ -225,32 +225,32 @@ TEST(MockPersistentNELStoreTest, AddFlushThenDelete) { store.GetDebugString()); } -TEST(MockPersistentNELStoreTest, AddThenUpdate) { - MockPersistentNELStore store; - MockPersistentNELStore::CommandList expected_commands; - std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies; +TEST(MockPersistentNelStoreTest, AddThenUpdate) { + MockPersistentNelStore store; + MockPersistentNelStore::CommandList expected_commands; + std::vector<NetworkErrorLoggingService::NelPolicy> loaded_policies; - store.LoadNELPolicies( - MakeExpectedRunNELPoliciesLoadedCallback(&loaded_policies)); + store.LoadNelPolicies( + MakeExpectedRunNelPoliciesLoadedCallback(&loaded_policies)); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::LOAD_NEL_POLICIES); + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); EXPECT_EQ(1u, store.GetAllCommands().size()); store.FinishLoading(true /* load_success */); - NetworkErrorLoggingService::NELPolicy policy = MakePolicyForOrigin(kOrigin); - store.AddNELPolicy(policy); + NetworkErrorLoggingService::NelPolicy policy = MakePolicyForOrigin(kOrigin); + store.AddNelPolicy(policy); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::ADD_NEL_POLICY, policy); + MockPersistentNelStore::Command::Type::ADD_NEL_POLICY, policy); EXPECT_EQ(2u, store.GetAllCommands().size()); - store.UpdateNELPolicyAccessTime(policy); + store.UpdateNelPolicyAccessTime(policy); expected_commands.emplace_back( - MockPersistentNELStore::Command::Type::UPDATE_NEL_POLICY, policy); + MockPersistentNelStore::Command::Type::UPDATE_NEL_POLICY, policy); EXPECT_EQ(3u, store.GetAllCommands().size()); store.Flush(); - expected_commands.emplace_back(MockPersistentNELStore::Command::Type::FLUSH); + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); EXPECT_EQ(1, store.StoredPoliciesCount()); EXPECT_EQ(4u, store.GetAllCommands().size()); diff --git a/chromium/net/network_error_logging/network_error_logging_service.cc b/chromium/net/network_error_logging/network_error_logging_service.cc index aa875fb26b4..43c699c8be8 100644 --- a/chromium/net/network_error_logging/network_error_logging_service.cc +++ b/chromium/net/network_error_logging/network_error_logging_service.cc @@ -9,6 +9,7 @@ #include <utility> #include <vector> +#include "base/bind.h" #include "base/json/json_reader.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" @@ -180,11 +181,17 @@ void RecordSignedExchangeRequestOutcome( class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { public: - explicit NetworkErrorLoggingServiceImpl(PersistentNELStore* store) - : store_(store) {} + explicit NetworkErrorLoggingServiceImpl(PersistentNelStore* store) + : store_(store), + started_loading_policies_(false), + initialized_(false), + weak_factory_(this) { + if (!PoliciesArePersisted()) + initialized_ = true; + } ~NetworkErrorLoggingServiceImpl() override { - if (store_) + if (PoliciesArePersisted() && initialized_) store_->Flush(); } @@ -193,9 +200,6 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { void OnHeader(const url::Origin& origin, const IPAddress& received_ip_address, const std::string& value) override { - if (shut_down_) - return; - // NEL is only available to secure origins, so don't permit insecure origins // to set policies. if (!origin.GetURL().SchemeIsCryptographic()) { @@ -203,10 +207,184 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { return; } - NELPolicy policy; + base::Time header_received_time = clock_->Now(); + // base::Unretained is safe because the callback gets stored in + // task_backlog_, so the callback will not outlive |*this|. + DoOrBacklogTask(base::BindOnce( + &NetworkErrorLoggingServiceImpl::DoOnHeader, base::Unretained(this), + origin, received_ip_address, value, header_received_time)); + } + + void OnRequest(RequestDetails details) override { + // This method is only called on secure requests. + DCHECK(details.uri.SchemeIsCryptographic()); + + if (!reporting_service_) { + RecordRequestOutcome(RequestOutcome::kDiscardedNoReportingService); + return; + } + + base::Time request_received_time = clock_->Now(); + // base::Unretained is safe because the callback gets stored in + // task_backlog_, so the callback will not outlive |*this|. + DoOrBacklogTask(base::BindOnce(&NetworkErrorLoggingServiceImpl::DoOnRequest, + base::Unretained(this), std::move(details), + request_received_time)); + } + + void QueueSignedExchangeReport(SignedExchangeReportDetails details) override { + if (!reporting_service_) { + RecordSignedExchangeRequestOutcome( + RequestOutcome::kDiscardedNoReportingService); + return; + } + if (!details.outer_url.SchemeIsCryptographic()) { + RecordSignedExchangeRequestOutcome( + RequestOutcome::kDiscardedInsecureOrigin); + return; + } + + base::Time request_received_time = clock_->Now(); + // base::Unretained is safe because the callback gets stored in + // task_backlog_, so the callback will not outlive |*this|. + DoOrBacklogTask(base::BindOnce( + &NetworkErrorLoggingServiceImpl::DoQueueSignedExchangeReport, + base::Unretained(this), std::move(details), request_received_time)); + } + + void RemoveBrowsingData(const base::RepeatingCallback<bool(const GURL&)>& + origin_filter) override { + // base::Unretained is safe because the callback gets stored in + // task_backlog_, so the callback will not outlive |*this|. + DoOrBacklogTask( + base::BindOnce(&NetworkErrorLoggingServiceImpl::DoRemoveBrowsingData, + base::Unretained(this), origin_filter)); + } + + void RemoveAllBrowsingData() override { + // base::Unretained is safe because the callback gets stored in + // task_backlog_, so the callback will not outlive |*this|. + DoOrBacklogTask( + base::BindOnce(&NetworkErrorLoggingServiceImpl::DoRemoveAllBrowsingData, + base::Unretained(this))); + } + + base::Value StatusAsValue() const override { + base::Value dict(base::Value::Type::DICTIONARY); + std::vector<base::Value> policy_list; + // We wanted sorted (or at least reproducible) output; luckily, policies_ is + // a std::map, and therefore already sorted. + for (const auto& origin_and_policy : policies_) { + const auto& origin = origin_and_policy.first; + const auto& policy = origin_and_policy.second; + base::Value policy_dict(base::Value::Type::DICTIONARY); + policy_dict.SetKey("origin", base::Value(origin.Serialize())); + policy_dict.SetKey("includeSubdomains", + base::Value(policy.include_subdomains)); + policy_dict.SetKey("reportTo", base::Value(policy.report_to)); + policy_dict.SetKey("expires", + base::Value(NetLog::TimeToString(policy.expires))); + policy_dict.SetKey("successFraction", + base::Value(policy.success_fraction)); + policy_dict.SetKey("failureFraction", + base::Value(policy.failure_fraction)); + policy_list.push_back(std::move(policy_dict)); + } + dict.SetKey("originPolicies", base::Value(std::move(policy_list))); + return dict; + } + + std::set<url::Origin> GetPolicyOriginsForTesting() override { + std::set<url::Origin> origins; + for (const auto& entry : policies_) { + origins.insert(entry.first); + } + return origins; + } + + private: + // Map from origin to origin's (owned) policy. + // Would be unordered_map, but url::Origin has no hash. + using PolicyMap = std::map<url::Origin, NelPolicy>; + + // Wildcard policies are policies for which the include_subdomains flag is + // set. + // + // Wildcard policies are accessed by domain name, not full origin, so there + // can be multiple wildcard policies per domain name. + // + // This is a map from domain name to the set of pointers to wildcard policies + // in that domain. + // + // Policies in the map are unowned; they are pointers to the original in the + // PolicyMap. + using WildcardPolicyMap = std::map<std::string, std::set<const NelPolicy*>>; + + PolicyMap policies_; + WildcardPolicyMap wildcard_policies_; + + // The persistent store in which NEL policies will be stored to disk, if not + // null. If |store_| is null, then NEL policies will be in-memory only. + // The store is owned by the URLRequestContext because Reporting also needs + // access to it. + PersistentNelStore* store_; + + // Set to true when we have told the store to load NEL policies. This is to + // make sure we don't try to load policies multiple times. + bool started_loading_policies_; + + // Set to true when the NEL service has been initialized. Before + // initialization is complete, commands to the NEL service (i.e. public + // method calls) are stashed away in |task_backlog_|, to be executed once + // initialization is complete. Initialization is complete automatically if + // there is no PersistentNelStore. If there is a store, then initialization is + // complete when the NEL policies have finished being loaded from the store + // (either successfully or unsuccessfully). + bool initialized_; + + // Backlog of tasks waiting on initialization. + std::vector<base::OnceClosure> task_backlog_; + + base::WeakPtrFactory<NetworkErrorLoggingServiceImpl> weak_factory_; + + bool PoliciesArePersisted() const { return store_ != nullptr; } + + void DoOrBacklogTask(base::OnceClosure task) { + if (shut_down_) + return; + + FetchAllPoliciesFromStoreIfNecessary(); + + if (!initialized_) { + task_backlog_.push_back(std::move(task)); + return; + } + + std::move(task).Run(); + } + + void ExecuteBacklog() { + DCHECK(initialized_); + + if (shut_down_) + return; + + for (base::OnceClosure& task : task_backlog_) { + std::move(task).Run(); + } + task_backlog_.clear(); + } + + void DoOnHeader(const url::Origin& origin, + const IPAddress& received_ip_address, + const std::string& value, + base::Time header_received_time) { + DCHECK(initialized_); + + NelPolicy policy; policy.origin = origin; policy.received_ip_address = received_ip_address; - policy.last_used = clock_->Now(); + policy.last_used = header_received_time; HeaderOutcome outcome = ParseHeader(value, clock_->Now(), &policy); RecordHeaderOutcome(outcome); if (outcome != HeaderOutcome::SET && outcome != HeaderOutcome::REMOVED) @@ -224,9 +402,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { return; DVLOG(1) << "Received NEL policy for " << origin; - auto inserted = policies_.insert(std::make_pair(origin, policy)); - DCHECK(inserted.second); - MaybeAddWildcardPolicy(origin, &inserted.first->second); + AddPolicy(std::move(policy)); // Evict policies if the policy limit is exceeded. if (policies_.size() > kMaxPolicies) { @@ -237,27 +413,18 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { } } - void OnRequest(RequestDetails details) override { - if (shut_down_) - return; - - if (!reporting_service_) { - RecordRequestOutcome(RequestOutcome::kDiscardedNoReportingService); - return; - } - - // This method is only called on secure requests. - DCHECK(details.uri.SchemeIsCryptographic()); + void DoOnRequest(RequestDetails details, base::Time request_received_time) { + DCHECK(reporting_service_); + DCHECK(initialized_); auto report_origin = url::Origin::Create(details.uri); - const NELPolicy* policy = FindPolicyForOrigin(report_origin); + const NelPolicy* policy = FindPolicyForOrigin(report_origin); if (!policy) { RecordRequestOutcome(RequestOutcome::kDiscardedNoOriginPolicy); return; } - // Mark the policy used. - policy->last_used = clock_->Now(); + MarkPolicyUsed(policy, request_received_time); Error type = details.type; // It is expected for Reporting uploads to terminate with ERR_ABORTED, since @@ -329,31 +496,19 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { RecordRequestOutcome(RequestOutcome::kQueued); } - void QueueSignedExchangeReport( - const SignedExchangeReportDetails& details) override { - if (shut_down_) - return; + void DoQueueSignedExchangeReport(SignedExchangeReportDetails details, + base::Time request_received_time) { + DCHECK(reporting_service_); - if (!reporting_service_) { - RecordSignedExchangeRequestOutcome( - RequestOutcome::kDiscardedNoReportingService); - return; - } - if (!details.outer_url.SchemeIsCryptographic()) { - RecordSignedExchangeRequestOutcome( - RequestOutcome::kDiscardedInsecureOrigin); - return; - } const auto report_origin = url::Origin::Create(details.outer_url); - const NELPolicy* policy = FindPolicyForOrigin(report_origin); + const NelPolicy* policy = FindPolicyForOrigin(report_origin); if (!policy) { RecordSignedExchangeRequestOutcome( RequestOutcome::kDiscardedNoOriginPolicy); return; } - // Mark the policy used. - policy->last_used = clock_->Now(); + MarkPolicyUsed(policy, request_received_time); if (IsMismatchingSubdomainReport(*policy, report_origin)) { RecordSignedExchangeRequestOutcome( @@ -386,8 +541,9 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { RecordSignedExchangeRequestOutcome(RequestOutcome::kQueued); } - void RemoveBrowsingData(const base::RepeatingCallback<bool(const GURL&)>& - origin_filter) override { + void DoRemoveBrowsingData( + const base::RepeatingCallback<bool(const GURL&)>& origin_filter) { + DCHECK(initialized_); for (auto it = policies_.begin(); it != policies_.end();) { const url::Origin& origin = it->first; // Remove policies matching the filter. @@ -397,77 +553,27 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { ++it; } } + if (PoliciesArePersisted()) + store_->Flush(); } - void RemoveAllBrowsingData() override { - wildcard_policies_.clear(); - policies_.clear(); - } - - base::Value StatusAsValue() const override { - base::Value dict(base::Value::Type::DICTIONARY); - std::vector<base::Value> policy_list; - // We wanted sorted (or at least reproducible) output; luckily, policies_ is - // a std::map, and therefore already sorted. - for (const auto& origin_and_policy : policies_) { - const auto& origin = origin_and_policy.first; - const auto& policy = origin_and_policy.second; - base::Value policy_dict(base::Value::Type::DICTIONARY); - policy_dict.SetKey("origin", base::Value(origin.Serialize())); - policy_dict.SetKey("includeSubdomains", - base::Value(policy.include_subdomains)); - policy_dict.SetKey("reportTo", base::Value(policy.report_to)); - policy_dict.SetKey("expires", - base::Value(NetLog::TimeToString(policy.expires))); - policy_dict.SetKey("successFraction", - base::Value(policy.success_fraction)); - policy_dict.SetKey("failureFraction", - base::Value(policy.failure_fraction)); - policy_list.push_back(std::move(policy_dict)); + void DoRemoveAllBrowsingData() { + DCHECK(initialized_); + if (PoliciesArePersisted()) { + // TODO(chlily): Add a DeleteAllNelPolicies command to PersistentNelStore. + for (auto origin_and_policy : policies_) { + store_->DeleteNelPolicy(origin_and_policy.second); + } + store_->Flush(); } - dict.SetKey("originPolicies", base::Value(std::move(policy_list))); - return dict; - } - std::set<url::Origin> GetPolicyOriginsForTesting() override { - std::set<url::Origin> origins; - for (const auto& entry : policies_) { - origins.insert(entry.first); - } - return origins; + wildcard_policies_.clear(); + policies_.clear(); } - private: - // Map from origin to origin's (owned) policy. - // Would be unordered_map, but url::Origin has no hash. - using PolicyMap = std::map<url::Origin, NELPolicy>; - - // Wildcard policies are policies for which the include_subdomains flag is - // set. - // - // Wildcard policies are accessed by domain name, not full origin, so there - // can be multiple wildcard policies per domain name. - // - // This is a map from domain name to the set of pointers to wildcard policies - // in that domain. - // - // Policies in the map are unowned; they are pointers to the original in the - // PolicyMap. - using WildcardPolicyMap = std::map<std::string, std::set<const NELPolicy*>>; - - PolicyMap policies_; - WildcardPolicyMap wildcard_policies_; - - // The persistent store in which NEL policies will be stored to disk, if not - // null. If |store_| is null, then NEL policies will be in-memory only. - // The store is owned by the URLRequestContext because Reporting also needs - // access to it. - // TODO(chlily): Implement. - PersistentNELStore* store_; - HeaderOutcome ParseHeader(const std::string& json_value, base::Time now, - NELPolicy* policy_out) const { + NelPolicy* policy_out) const { DCHECK(policy_out); if (json_value.size() > kMaxJsonSize) @@ -528,13 +634,15 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { } } - const NELPolicy* FindPolicyForOrigin(const url::Origin& origin) const { + const NelPolicy* FindPolicyForOrigin(const url::Origin& origin) const { + DCHECK(initialized_); + auto it = policies_.find(origin); if (it != policies_.end() && clock_->Now() < it->second.expires) return &it->second; std::string domain = origin.host(); - const NELPolicy* wildcard_policy = nullptr; + const NelPolicy* wildcard_policy = nullptr; while (!wildcard_policy && !domain.empty()) { wildcard_policy = FindWildcardPolicyForDomain(domain); domain = GetSuperdomain(domain); @@ -543,7 +651,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { return wildcard_policy; } - const NELPolicy* FindWildcardPolicyForDomain( + const NelPolicy* FindWildcardPolicyForDomain( const std::string& domain) const { DCHECK(!domain.empty()); @@ -568,8 +676,27 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { return nullptr; } + // There must be no pre-existing policy for |policy.origin|. Returns iterator + // to the inserted policy. + PolicyMap::iterator AddPolicy(NelPolicy policy) { + // If |initialized_| is false, then we are calling this from + // OnPoliciesLoaded(), which means we don't want to add the given policy to + // the store because we have just loaded it from there. + if (PoliciesArePersisted() && initialized_) + store_->AddNelPolicy(policy); + + auto iter_and_result = + policies_.insert(std::make_pair(policy.origin, std::move(policy))); + DCHECK(iter_and_result.second); + + const NelPolicy& inserted_policy = iter_and_result.first->second; + MaybeAddWildcardPolicy(inserted_policy.origin, &inserted_policy); + + return iter_and_result.first; + } + void MaybeAddWildcardPolicy(const url::Origin& origin, - const NELPolicy* policy) { + const NelPolicy* policy) { DCHECK(policy); DCHECK_EQ(policy, &policies_[origin]); @@ -584,12 +711,16 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { // Returns the iterator to the next element. PolicyMap::iterator RemovePolicy(PolicyMap::iterator policy_it) { DCHECK(policy_it != policies_.end()); - NELPolicy* policy = &policy_it->second; + NelPolicy* policy = &policy_it->second; MaybeRemoveWildcardPolicy(policy); + + if (PoliciesArePersisted() && initialized_) + store_->DeleteNelPolicy(*policy); + return policies_.erase(policy_it); } - void MaybeRemoveWildcardPolicy(const NELPolicy* policy) { + void MaybeRemoveWildcardPolicy(const NelPolicy* policy) { DCHECK(policy); if (!policy->include_subdomains) @@ -607,6 +738,12 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { wildcard_policies_.erase(wildcard_it); } + void MarkPolicyUsed(const NelPolicy* policy, base::Time time_used) const { + policy->last_used = time_used; + if (PoliciesArePersisted() && initialized_) + store_->UpdateNelPolicyAccessTime(*policy); + } + void RemoveAllExpiredPolicies() { for (auto it = policies_.begin(); it != policies_.end();) { if (it->second.expires < clock_->Now()) { @@ -679,13 +816,13 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { return std::move(body); } - bool IsMismatchingSubdomainReport(const NELPolicy& policy, + bool IsMismatchingSubdomainReport(const NelPolicy& policy, const url::Origin& report_origin) const { return policy.include_subdomains && (policy.origin != report_origin); } // Returns a valid value of matching fraction iff the event should be sampled. - base::Optional<double> SampleAndReturnFraction(const NELPolicy& policy, + base::Optional<double> SampleAndReturnFraction(const NelPolicy& policy, bool success) const { const double sampling_fraction = success ? policy.success_fraction : policy.failure_fraction; @@ -701,16 +838,51 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { return base::nullopt; return sampling_fraction; } + + void FetchAllPoliciesFromStoreIfNecessary() { + if (!PoliciesArePersisted() || started_loading_policies_) + return; + + started_loading_policies_ = true; + FetchAllPoliciesFromStore(); + } + + void FetchAllPoliciesFromStore() { + DCHECK(PoliciesArePersisted()); + DCHECK(!initialized_); + + store_->LoadNelPolicies( + base::BindOnce(&NetworkErrorLoggingServiceImpl::OnPoliciesLoaded, + weak_factory_.GetWeakPtr())); + } + + // This is called when loading from the store is complete, regardless of + // success or failure. + // DB initialization may have failed, in which case we will receive an empty + // vector from the PersistentNelStore. This is indistinguishable from a + // successful load that happens to not yield any policies, but in + // either case we still want to go through the task backlog. + void OnPoliciesLoaded(std::vector<NelPolicy> loaded_policies) { + DCHECK(PoliciesArePersisted()); + DCHECK(!initialized_); + + // TODO(chlily): Toss any expired policies we encounter. + for (NelPolicy& policy : loaded_policies) { + AddPolicy(std::move(policy)); + } + initialized_ = true; + ExecuteBacklog(); + } }; } // namespace -NetworkErrorLoggingService::NELPolicy::NELPolicy() = default; +NetworkErrorLoggingService::NelPolicy::NelPolicy() = default; -NetworkErrorLoggingService::NELPolicy::NELPolicy(const NELPolicy& other) = +NetworkErrorLoggingService::NelPolicy::NelPolicy(const NelPolicy& other) = default; -NetworkErrorLoggingService::NELPolicy::~NELPolicy() = default; +NetworkErrorLoggingService::NelPolicy::~NelPolicy() = default; NetworkErrorLoggingService::RequestDetails::RequestDetails() = default; @@ -807,7 +979,7 @@ void NetworkErrorLoggingService::RecordRequestDiscardedForInsecureOrigin() { // static std::unique_ptr<NetworkErrorLoggingService> NetworkErrorLoggingService::Create( - PersistentNELStore* store) { + PersistentNelStore* store) { return std::make_unique<NetworkErrorLoggingServiceImpl>(store); } @@ -815,12 +987,13 @@ NetworkErrorLoggingService::~NetworkErrorLoggingService() = default; void NetworkErrorLoggingService::SetReportingService( ReportingService* reporting_service) { + DCHECK(!reporting_service_); reporting_service_ = reporting_service; } void NetworkErrorLoggingService::OnShutdown() { shut_down_ = true; - SetReportingService(nullptr); + reporting_service_ = nullptr; } void NetworkErrorLoggingService::SetClockForTesting(const base::Clock* clock) { diff --git a/chromium/net/network_error_logging/network_error_logging_service.h b/chromium/net/network_error_logging/network_error_logging_service.h index 642e2fc9932..7f38335b83c 100644 --- a/chromium/net/network_error_logging/network_error_logging_service.h +++ b/chromium/net/network_error_logging/network_error_logging_service.h @@ -41,13 +41,13 @@ namespace net { class NET_EXPORT NetworkErrorLoggingService { public: - class PersistentNELStore; + class PersistentNelStore; // NEL policy set by an origin. - struct NET_EXPORT NELPolicy { - NELPolicy(); - NELPolicy(const NELPolicy& other); - ~NELPolicy(); + struct NET_EXPORT NelPolicy { + NelPolicy(); + NelPolicy(const NelPolicy& other); + ~NelPolicy(); url::Origin origin; IPAddress received_ip_address = IPAddress(); @@ -201,7 +201,7 @@ class NET_EXPORT NetworkErrorLoggingService { // NEL policies are persisted to disk if |store| is not null. // The store, if given, should outlive |*this|. static std::unique_ptr<NetworkErrorLoggingService> Create( - PersistentNELStore* store); + PersistentNelStore* store); virtual ~NetworkErrorLoggingService(); @@ -227,7 +227,7 @@ class NET_EXPORT NetworkErrorLoggingService { // Queues a Signed Exchange report. virtual void QueueSignedExchangeReport( - const SignedExchangeReportDetails& details) = 0; + SignedExchangeReportDetails details) = 0; // Removes browsing data (origin policies) associated with any origin for // which |origin_filter| returns true. @@ -241,10 +241,12 @@ class NET_EXPORT NetworkErrorLoggingService { // Sets the ReportingService that will be used to queue network error reports. // If |nullptr| is passed, reports will be queued locally or discarded. // |reporting_service| must outlive the NetworkErrorLoggingService. + // Should not be called again if previously called with a non-null pointer. void SetReportingService(ReportingService* reporting_service); - // Shuts down the NEL service so that no more requests or headers are - // processed and no more reports are queued. + // Shuts down the NEL service, so that no more requests or headers can be + // processed, no more reports are queued, and browsing data can no longer be + // cleared. void OnShutdown(); // Sets a base::Clock (used to track policy expiration) for tests. @@ -272,32 +274,32 @@ class NET_EXPORT NetworkErrorLoggingService { }; // Persistent storage for NEL policies. -class NET_EXPORT NetworkErrorLoggingService::PersistentNELStore { +class NET_EXPORT NetworkErrorLoggingService::PersistentNelStore { public: - using NELPoliciesLoadedCallback = - base::OnceCallback<void(std::vector<NELPolicy>)>; + using NelPoliciesLoadedCallback = + base::OnceCallback<void(std::vector<NelPolicy>)>; - PersistentNELStore() = default; - virtual ~PersistentNELStore() = default; + PersistentNelStore() = default; + virtual ~PersistentNelStore() = default; // Initializes the store and retrieves stored NEL policies. This will be // called only once at startup. - virtual void LoadNELPolicies(NELPoliciesLoadedCallback loaded_callback) = 0; + virtual void LoadNelPolicies(NelPoliciesLoadedCallback loaded_callback) = 0; // Adds a NEL policy to the store. - virtual void AddNELPolicy(const NELPolicy& policy) = 0; + virtual void AddNelPolicy(const NelPolicy& policy) = 0; // Updates the access time of the NEL policy in the store. - virtual void UpdateNELPolicyAccessTime(const NELPolicy& policy) = 0; + virtual void UpdateNelPolicyAccessTime(const NelPolicy& policy) = 0; // Deletes a NEL policy from the store. - virtual void DeleteNELPolicy(const NELPolicy& policy) = 0; + virtual void DeleteNelPolicy(const NelPolicy& policy) = 0; // Flushes the store. virtual void Flush() = 0; private: - DISALLOW_COPY_AND_ASSIGN(PersistentNELStore); + DISALLOW_COPY_AND_ASSIGN(PersistentNelStore); }; } // namespace net diff --git a/chromium/net/network_error_logging/network_error_logging_service_unittest.cc b/chromium/net/network_error_logging/network_error_logging_service_unittest.cc index 8e274fd5370..c1203fc9eae 100644 --- a/chromium/net/network_error_logging/network_error_logging_service_unittest.cc +++ b/chromium/net/network_error_logging/network_error_logging_service_unittest.cc @@ -18,8 +18,7 @@ #include "net/base/net_errors.h" #include "net/network_error_logging/mock_persistent_nel_store.h" #include "net/network_error_logging/network_error_logging_service.h" -#include "net/reporting/reporting_policy.h" -#include "net/reporting/reporting_service.h" +#include "net/reporting/reporting_test_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" #include "url/origin.h" @@ -27,102 +26,20 @@ namespace net { namespace { -class TestReportingService : public ReportingService { - public: - struct Report { - Report() = default; - - Report(Report&& other) - : url(other.url), - user_agent(other.user_agent), - group(other.group), - type(other.type), - body(std::move(other.body)), - depth(other.depth) {} - - Report(const GURL& url, - const std::string& user_agent, - const std::string& group, - const std::string& type, - std::unique_ptr<const base::Value> body, - int depth) - : url(url), - user_agent(user_agent), - group(group), - type(type), - body(std::move(body)), - depth(depth) {} - - ~Report() = default; - - GURL url; - std::string user_agent; - std::string group; - std::string type; - std::unique_ptr<const base::Value> body; - int depth; - - private: - DISALLOW_COPY(Report); - }; - - TestReportingService() = default; - - const std::vector<Report>& reports() const { return reports_; } - - // ReportingService implementation: - - ~TestReportingService() override = default; - - void QueueReport(const GURL& url, - const std::string& user_agent, - const std::string& group, - const std::string& type, - std::unique_ptr<const base::Value> body, - int depth) override { - reports_.push_back( - Report(url, user_agent, group, type, std::move(body), depth)); - } - - void ProcessHeader(const GURL& url, - const std::string& header_value) override { - NOTREACHED(); - } - - void RemoveBrowsingData(int data_type_mask, - const base::RepeatingCallback<bool(const GURL&)>& - origin_filter) override { - NOTREACHED(); - } - - void RemoveAllBrowsingData(int data_type_mask) override { NOTREACHED(); } - - void OnShutdown() override {} - - const ReportingPolicy& GetPolicy() const override { - NOTREACHED(); - return dummy_policy_; - } - - ReportingContext* GetContextForTesting() const override { - NOTREACHED(); - return nullptr; - } - - private: - std::vector<Report> reports_; - ReportingPolicy dummy_policy_; - - DISALLOW_COPY_AND_ASSIGN(TestReportingService); -}; - // The tests are parametrized on a boolean value which represents whether or not -// to use a MockPersistentNELStore. +// to use a MockPersistentNelStore. +// If a MockPersistentNelStore is used, then calls to +// NetworkErrorLoggingService::OnHeader(), OnRequest(), +// QueueSignedExchangeReport(), RemoveBrowsingData(), and +// RemoveAllBrowsingData() will block until the store finishes loading. +// Therefore, for tests that should run synchronously (i.e. tests that don't +// specifically test the asynchronous/deferred task behavior), FinishLoading() +// must be called after the first call to one of the above methods. class NetworkErrorLoggingServiceTest : public ::testing::TestWithParam<bool> { protected: NetworkErrorLoggingServiceTest() { if (GetParam()) { - store_ = std::make_unique<MockPersistentNELStore>(); + store_ = std::make_unique<MockPersistentNelStore>(); } else { store_.reset(nullptr); } @@ -137,13 +54,6 @@ class NetworkErrorLoggingServiceTest : public ::testing::TestWithParam<bool> { service_->SetReportingService(reporting_service_.get()); } - void DestroyReportingService() { - DCHECK(reporting_service_); - - service_->SetReportingService(nullptr); - reporting_service_.reset(); - } - NetworkErrorLoggingService::RequestDetails MakeRequestDetails( GURL url, Error error_type, @@ -188,7 +98,7 @@ class NetworkErrorLoggingServiceTest : public ::testing::TestWithParam<bool> { return details; } NetworkErrorLoggingService* service() { return service_.get(); } - MockPersistentNELStore* store() { return store_.get(); } + MockPersistentNelStore* store() { return store_.get(); } const std::vector<TestReportingService::Report>& reports() { return reporting_service_->reports(); } @@ -198,6 +108,18 @@ class NetworkErrorLoggingServiceTest : public ::testing::TestWithParam<bool> { return url::Origin::Create(url); } + NetworkErrorLoggingService::NelPolicy MakePolicyForOrigin( + url::Origin origin, + base::Time expires = base::Time(), + base::Time last_used = base::Time()) { + NetworkErrorLoggingService::NelPolicy policy; + policy.origin = std::move(origin); + policy.expires = expires; + policy.last_used = last_used; + + return policy; + } + // Returns whether the NetworkErrorLoggingService has a policy corresponding // to |origin|. Returns true if so, even if the policy is expired. bool HasPolicyForOrigin(const url::Origin& origin) { @@ -208,6 +130,12 @@ class NetworkErrorLoggingServiceTest : public ::testing::TestWithParam<bool> { size_t PolicyCount() { return service_->GetPolicyOriginsForTesting().size(); } + // Makes the rest of the test run synchronously. + void FinishLoading(bool load_success) { + if (store()) + store()->FinishLoading(load_success); + } + const GURL kUrl_ = GURL("https://example.com/path"); const GURL kUrlDifferentPort_ = GURL("https://example.com:4433/path"); const GURL kUrlSubdomain_ = GURL("https://subdomain.example.com/path"); @@ -247,9 +175,8 @@ class NetworkErrorLoggingServiceTest : public ::testing::TestWithParam<bool> { const GURL kReferrer_ = GURL("https://referrer.com/"); - private: // |store_| needs to outlive |service_|. - std::unique_ptr<MockPersistentNELStore> store_; + std::unique_ptr<MockPersistentNelStore> store_; std::unique_ptr<NetworkErrorLoggingService> service_; std::unique_ptr<TestReportingService> reporting_service_; }; @@ -268,22 +195,32 @@ TEST_P(NetworkErrorLoggingServiceTest, CreateService) { } TEST_P(NetworkErrorLoggingServiceTest, NoReportingService) { - DestroyReportingService(); + service_ = NetworkErrorLoggingService::Create(store_.get()); service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + + // Should not crash. service()->OnRequest(MakeRequestDetails(kUrl_, ERR_CONNECTION_REFUSED)); } TEST_P(NetworkErrorLoggingServiceTest, NoPolicyForOrigin) { service()->OnRequest(MakeRequestDetails(kUrl_, ERR_CONNECTION_REFUSED)); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + EXPECT_TRUE(reports().empty()); } TEST_P(NetworkErrorLoggingServiceTest, JsonTooLong) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderTooLong_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest(MakeRequestDetails(kUrl_, ERR_CONNECTION_REFUSED)); EXPECT_TRUE(reports().empty()); @@ -292,6 +229,9 @@ TEST_P(NetworkErrorLoggingServiceTest, JsonTooLong) { TEST_P(NetworkErrorLoggingServiceTest, JsonTooDeep) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderTooDeep_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest(MakeRequestDetails(kUrl_, ERR_CONNECTION_REFUSED)); EXPECT_TRUE(reports().empty()); @@ -300,6 +240,9 @@ TEST_P(NetworkErrorLoggingServiceTest, JsonTooDeep) { TEST_P(NetworkErrorLoggingServiceTest, SuccessReportQueued) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderSuccessFraction1_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest(MakeRequestDetails(kUrl_, OK)); ASSERT_EQ(1u, reports().size()); @@ -337,6 +280,9 @@ TEST_P(NetworkErrorLoggingServiceTest, FailureReportQueued) { "{\"report_to\":\"group\",\"max_age\":86400,\"failure_fraction\":1.0}"; service()->OnHeader(kOrigin_, kServerIP_, kHeaderFailureFraction1); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest(MakeRequestDetails(kUrl_, ERR_CONNECTION_REFUSED)); ASSERT_EQ(1u, reports().size()); @@ -374,6 +320,9 @@ TEST_P(NetworkErrorLoggingServiceTest, UnknownFailureReportQueued) { "{\"report_to\":\"group\",\"max_age\":86400,\"failure_fraction\":1.0}"; service()->OnHeader(kOrigin_, kServerIP_, kHeaderFailureFraction1); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + // This error code happens to not be mapped to a NEL report `type` field // value. service()->OnRequest(MakeRequestDetails(kUrl_, ERR_FILE_NO_SPACE)); @@ -392,6 +341,9 @@ TEST_P(NetworkErrorLoggingServiceTest, UnknownCertFailureReportQueued) { "{\"report_to\":\"group\",\"max_age\":86400,\"failure_fraction\":1.0}"; service()->OnHeader(kOrigin_, kServerIP_, kHeaderFailureFraction1); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + // This error code happens to not be mapped to a NEL report `type` field // value. Because it's a certificate error, we'll set the `phase` to be // `connection`. @@ -411,6 +363,9 @@ TEST_P(NetworkErrorLoggingServiceTest, HttpErrorReportQueued) { "{\"report_to\":\"group\",\"max_age\":86400,\"failure_fraction\":1.0}"; service()->OnHeader(kOrigin_, kServerIP_, kHeaderFailureFraction1); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest(MakeRequestDetails(kUrl_, OK, "GET", 504)); ASSERT_EQ(1u, reports().size()); @@ -446,6 +401,9 @@ TEST_P(NetworkErrorLoggingServiceTest, HttpErrorReportQueued) { TEST_P(NetworkErrorLoggingServiceTest, SuccessReportDowngraded) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderSuccessFraction1_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest( MakeRequestDetails(kUrl_, OK, "GET", 200, kOtherServerIP_)); @@ -480,6 +438,9 @@ TEST_P(NetworkErrorLoggingServiceTest, SuccessReportDowngraded) { TEST_P(NetworkErrorLoggingServiceTest, FailureReportDowngraded) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderSuccessFraction1_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest(MakeRequestDetails(kUrl_, ERR_CONNECTION_REFUSED, "GET", 200, kOtherServerIP_)); @@ -514,6 +475,9 @@ TEST_P(NetworkErrorLoggingServiceTest, FailureReportDowngraded) { TEST_P(NetworkErrorLoggingServiceTest, HttpErrorReportDowngraded) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderSuccessFraction1_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest( MakeRequestDetails(kUrl_, OK, "GET", 504, kOtherServerIP_)); @@ -548,6 +512,9 @@ TEST_P(NetworkErrorLoggingServiceTest, HttpErrorReportDowngraded) { TEST_P(NetworkErrorLoggingServiceTest, DNSFailureReportNotDowngraded) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderSuccessFraction1_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest(MakeRequestDetails(kUrl_, ERR_NAME_NOT_RESOLVED, "GET", 0, kOtherServerIP_)); @@ -582,6 +549,9 @@ TEST_P(NetworkErrorLoggingServiceTest, DNSFailureReportNotDowngraded) { TEST_P(NetworkErrorLoggingServiceTest, SuccessPOSTReportQueued) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderSuccessFraction1_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest(MakeRequestDetails(kUrl_, OK, "POST")); ASSERT_EQ(1u, reports().size()); @@ -610,6 +580,10 @@ TEST_P(NetworkErrorLoggingServiceTest, SuccessPOSTReportQueued) { TEST_P(NetworkErrorLoggingServiceTest, MaxAge0) { service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + EXPECT_EQ(1u, PolicyCount()); // Max_age of 0 removes the policy. @@ -624,6 +598,9 @@ TEST_P(NetworkErrorLoggingServiceTest, MaxAge0) { TEST_P(NetworkErrorLoggingServiceTest, SuccessFraction0) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderSuccessFraction0_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + // Each network error has a 0% chance of being reported. Fire off several and // verify that no reports are produced. constexpr size_t kReportCount = 100; @@ -641,6 +618,9 @@ TEST_P(NetworkErrorLoggingServiceTest, SuccessFractionHalf) { "\"failure_fraction\":0.25}"; service()->OnHeader(kOrigin_, kServerIP_, kHeaderSuccessFractionHalf); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + // Each network error has a 50% chance of being reported. Fire off several // and verify that some requests were reported and some weren't. (We can't // verify exact counts because each decision is made randomly.) @@ -672,6 +652,9 @@ TEST_P(NetworkErrorLoggingServiceTest, FailureFraction0) { "{\"report_to\":\"group\",\"max_age\":86400,\"failure_fraction\":0.0}"; service()->OnHeader(kOrigin_, kServerIP_, kHeaderFailureFraction0); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + // Each network error has a 0% chance of being reported. Fire off several and // verify that no reports are produced. constexpr size_t kReportCount = 100; @@ -689,6 +672,9 @@ TEST_P(NetworkErrorLoggingServiceTest, FailureFractionHalf) { "\"success_fraction\":0.25}"; service()->OnHeader(kOrigin_, kServerIP_, kHeaderFailureFractionHalf); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + // Each network error has a 50% chance of being reported. Fire off several // and verify that some requests were reported and some weren't. (We can't // verify exact counts because each decision is made randomly.) @@ -717,6 +703,9 @@ TEST_P(NetworkErrorLoggingServiceTest, ExcludeSubdomainsDoesntMatchDifferentPort) { service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest( MakeRequestDetails(kUrlDifferentPort_, ERR_CONNECTION_REFUSED)); @@ -726,6 +715,9 @@ TEST_P(NetworkErrorLoggingServiceTest, TEST_P(NetworkErrorLoggingServiceTest, ExcludeSubdomainsDoesntMatchSubdomain) { service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest( MakeRequestDetails(kUrlSubdomain_, ERR_CONNECTION_REFUSED)); @@ -735,6 +727,9 @@ TEST_P(NetworkErrorLoggingServiceTest, ExcludeSubdomainsDoesntMatchSubdomain) { TEST_P(NetworkErrorLoggingServiceTest, IncludeSubdomainsMatchesDifferentPort) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderIncludeSubdomains_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest( MakeRequestDetails(kUrlDifferentPort_, ERR_NAME_NOT_RESOLVED)); @@ -745,6 +740,9 @@ TEST_P(NetworkErrorLoggingServiceTest, IncludeSubdomainsMatchesDifferentPort) { TEST_P(NetworkErrorLoggingServiceTest, IncludeSubdomainsMatchesSubdomain) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderIncludeSubdomains_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest( MakeRequestDetails(kUrlSubdomain_, ERR_NAME_NOT_RESOLVED)); @@ -755,6 +753,9 @@ TEST_P(NetworkErrorLoggingServiceTest, IncludeSubdomainsDoesntMatchSuperdomain) { service()->OnHeader(kOriginSubdomain_, kServerIP_, kHeaderIncludeSubdomains_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest(MakeRequestDetails(kUrl_, ERR_NAME_NOT_RESOLVED)); EXPECT_TRUE(reports().empty()); @@ -764,6 +765,9 @@ TEST_P(NetworkErrorLoggingServiceTest, IncludeSubdomainsDoesntReportConnectionError) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderIncludeSubdomains_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest( MakeRequestDetails(kUrlSubdomain_, ERR_CONNECTION_REFUSED)); @@ -774,6 +778,9 @@ TEST_P(NetworkErrorLoggingServiceTest, IncludeSubdomainsDoesntReportApplicationError) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderIncludeSubdomains_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest( MakeRequestDetails(kUrlSubdomain_, ERR_INVALID_HTTP_RESPONSE)); @@ -783,6 +790,9 @@ TEST_P(NetworkErrorLoggingServiceTest, TEST_P(NetworkErrorLoggingServiceTest, IncludeSubdomainsDoesntReportSuccess) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderIncludeSubdomains_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest(MakeRequestDetails(kUrlSubdomain_, OK)); EXPECT_TRUE(reports().empty()); @@ -795,6 +805,9 @@ TEST_P(NetworkErrorLoggingServiceTest, "\"include_subdomains\":true,\"success_fraction\":1.0}"; service()->OnHeader(kOrigin_, kServerIP_, kHeaderIncludeSubdomainsSuccess1); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnRequest(MakeRequestDetails(kUrl_, OK)); ASSERT_EQ(1u, reports().size()); @@ -803,6 +816,10 @@ TEST_P(NetworkErrorLoggingServiceTest, TEST_P(NetworkErrorLoggingServiceTest, RemoveAllBrowsingData) { service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + EXPECT_EQ(1u, PolicyCount()); EXPECT_TRUE(HasPolicyForOrigin(kOrigin_)); @@ -817,6 +834,10 @@ TEST_P(NetworkErrorLoggingServiceTest, RemoveAllBrowsingData) { TEST_P(NetworkErrorLoggingServiceTest, RemoveSomeBrowsingData) { service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnHeader(kOriginDifferentHost_, kServerIP_, kHeader_); EXPECT_EQ(2u, PolicyCount()); @@ -842,6 +863,9 @@ TEST_P(NetworkErrorLoggingServiceTest, RemoveSomeBrowsingData) { TEST_P(NetworkErrorLoggingServiceTest, Nested) { service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + NetworkErrorLoggingService::RequestDetails details = MakeRequestDetails(kUrl_, ERR_CONNECTION_REFUSED); details.reporting_upload_depth = @@ -856,6 +880,9 @@ TEST_P(NetworkErrorLoggingServiceTest, Nested) { TEST_P(NetworkErrorLoggingServiceTest, NestedTooDeep) { service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + NetworkErrorLoggingService::RequestDetails details = MakeRequestDetails(kUrl_, ERR_CONNECTION_REFUSED); details.reporting_upload_depth = @@ -880,6 +907,10 @@ TEST_P(NetworkErrorLoggingServiceTest, StatusAsValue) { clock.Advance(delta_from_origin); service()->OnHeader(kOrigin_, kServerIP_, kHeaderSuccessFraction1_); + + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->OnHeader(kOriginDifferentHost_, kServerIP_, kHeader_); service()->OnHeader(kOriginSubdomain_, kServerIP_, kHeaderIncludeSubdomains_); const std::string kHeaderWrongTypes = @@ -938,9 +969,14 @@ TEST_P(NetworkErrorLoggingServiceTest, StatusAsValue) { } TEST_P(NetworkErrorLoggingServiceTest, NoReportingService_SignedExchange) { - DestroyReportingService(); + service_ = NetworkErrorLoggingService::Create(store_.get()); service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + + // Should not crash service()->QueueSignedExchangeReport(MakeSignedExchangeReportDetails( false, "sxg.failed", kUrl_, kInnerUrl_, kCertUrl_, kServerIP_)); } @@ -948,12 +984,19 @@ TEST_P(NetworkErrorLoggingServiceTest, NoReportingService_SignedExchange) { TEST_P(NetworkErrorLoggingServiceTest, NoPolicyForOrigin_SignedExchange) { service()->QueueSignedExchangeReport(MakeSignedExchangeReportDetails( false, "sxg.failed", kUrl_, kInnerUrl_, kCertUrl_, kServerIP_)); + + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + EXPECT_TRUE(reports().empty()); } TEST_P(NetworkErrorLoggingServiceTest, SuccessFraction0_SignedExchange) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderSuccessFraction0_); + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + // Each network error has a 0% chance of being reported. Fire off several and // verify that no reports are produced. constexpr size_t kReportCount = 100; @@ -967,6 +1010,10 @@ TEST_P(NetworkErrorLoggingServiceTest, SuccessFraction0_SignedExchange) { TEST_P(NetworkErrorLoggingServiceTest, SuccessReportQueued_SignedExchange) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderSuccessFraction1_); + + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->QueueSignedExchangeReport(MakeSignedExchangeReportDetails( true, "ok", kUrl_, kInnerUrl_, kCertUrl_, kServerIP_)); ASSERT_EQ(1u, reports().size()); @@ -1013,6 +1060,10 @@ TEST_P(NetworkErrorLoggingServiceTest, SuccessReportQueued_SignedExchange) { TEST_P(NetworkErrorLoggingServiceTest, FailureReportQueued_SignedExchange) { service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->QueueSignedExchangeReport(MakeSignedExchangeReportDetails( false, "sxg.failed", kUrl_, kInnerUrl_, kCertUrl_, kServerIP_)); ASSERT_EQ(1u, reports().size()); @@ -1059,6 +1110,10 @@ TEST_P(NetworkErrorLoggingServiceTest, FailureReportQueued_SignedExchange) { TEST_P(NetworkErrorLoggingServiceTest, MismatchingSubdomain_SignedExchange) { service()->OnHeader(kOrigin_, kServerIP_, kHeaderIncludeSubdomains_); + + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->QueueSignedExchangeReport(MakeSignedExchangeReportDetails( false, "sxg.failed", kUrlSubdomain_, kInnerUrl_, kCertUrl_, kServerIP_)); EXPECT_TRUE(reports().empty()); @@ -1066,6 +1121,10 @@ TEST_P(NetworkErrorLoggingServiceTest, MismatchingSubdomain_SignedExchange) { TEST_P(NetworkErrorLoggingServiceTest, MismatchingIPAddress_SignedExchange) { service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + service()->QueueSignedExchangeReport(MakeSignedExchangeReportDetails( false, "sxg.failed", kUrl_, kInnerUrl_, kCertUrl_, kOtherServerIP_)); EXPECT_TRUE(reports().empty()); @@ -1081,6 +1140,9 @@ TEST_P(NetworkErrorLoggingServiceTest, EvictAllExpiredPoliciesFirst) { for (size_t i = 0; i < 100; ++i) { service()->OnHeader(MakeOrigin(i), kServerIP_, kHeader_); } + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + EXPECT_EQ(100u, PolicyCount()); clock.Advance(base::TimeDelta::FromSeconds(86401)); // max_age is 86400 sec // Expired policies are allowed to linger before hitting the policy limit. @@ -1106,6 +1168,8 @@ TEST_P(NetworkErrorLoggingServiceTest, EvictLeastRecentlyUsedPolicy) { service()->OnHeader(MakeOrigin(i), kServerIP_, kHeader_); clock.Advance(base::TimeDelta::FromSeconds(1)); } + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); EXPECT_EQ(PolicyCount(), NetworkErrorLoggingService::kMaxPolicies); @@ -1152,6 +1216,315 @@ TEST_P(NetworkErrorLoggingServiceTest, EvictLeastRecentlyUsedPolicy) { // this test. } +TEST_P(NetworkErrorLoggingServiceTest, SendsCommandsToStoreSynchronous) { + if (!store()) + return; + + MockPersistentNelStore::CommandList expected_commands; + NetworkErrorLoggingService::NelPolicy policy1 = MakePolicyForOrigin(kOrigin_); + NetworkErrorLoggingService::NelPolicy policy2 = + MakePolicyForOrigin(kOriginDifferentHost_); + std::vector<NetworkErrorLoggingService::NelPolicy> prestored_policies = { + policy1, policy2}; + store()->SetPrestoredPolicies(std::move(prestored_policies)); + + // The first call to any of the public methods triggers a load. + service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + // Make the rest of the test run synchronously. + FinishLoading(true /* load_success */); + // DoOnHeader() should now execute. + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY, policy1); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::ADD_NEL_POLICY, policy1); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + service()->OnRequest( + MakeRequestDetails(kOrigin_.GetURL(), ERR_CONNECTION_REFUSED)); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::UPDATE_NEL_POLICY, policy1); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + service()->QueueSignedExchangeReport(MakeSignedExchangeReportDetails( + false, "sxg.failed", kUrl_, kInnerUrl_, kCertUrl_, kServerIP_)); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::UPDATE_NEL_POLICY, policy1); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + // Removes policy1 but not policy2. + EXPECT_EQ(2, store()->StoredPoliciesCount()); + service()->RemoveBrowsingData( + base::BindRepeating([](const GURL& origin) -> bool { + return origin.host() == "example.com"; + })); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY, policy1); + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); + EXPECT_EQ(1, store()->StoredPoliciesCount()); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + service()->RemoveAllBrowsingData(); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY, policy2); + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); + EXPECT_EQ(0, store()->StoredPoliciesCount()); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); +} + +// Same as the above test, except that all the tasks are queued until loading +// is complete. +TEST_P(NetworkErrorLoggingServiceTest, SendsCommandsToStoreDeferred) { + if (!store()) + return; + + MockPersistentNelStore::CommandList expected_commands; + NetworkErrorLoggingService::NelPolicy policy1 = MakePolicyForOrigin(kOrigin_); + NetworkErrorLoggingService::NelPolicy policy2 = + MakePolicyForOrigin(kOriginDifferentHost_); + std::vector<NetworkErrorLoggingService::NelPolicy> prestored_policies = { + policy1, policy2}; + store()->SetPrestoredPolicies(std::move(prestored_policies)); + + // The first call to any of the public methods triggers a load. + service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + service()->OnRequest( + MakeRequestDetails(kOrigin_.GetURL(), ERR_CONNECTION_REFUSED)); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + service()->QueueSignedExchangeReport(MakeSignedExchangeReportDetails( + false, "sxg.failed", kUrl_, kInnerUrl_, kCertUrl_, kServerIP_)); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + // Removes policy1 but not policy2. + service()->RemoveBrowsingData( + base::BindRepeating([](const GURL& origin) -> bool { + return origin.host() == "example.com"; + })); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + service()->RemoveAllBrowsingData(); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + // The store has not yet been told to remove the policies because the tasks + // to remove browsing data were queued pending initialization. + EXPECT_EQ(2, store()->StoredPoliciesCount()); + + FinishLoading(true /* load_success */); + // DoOnHeader() + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY, policy1); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::ADD_NEL_POLICY, policy1); + // DoOnRequest() + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::UPDATE_NEL_POLICY, policy1); + // DoQueueSignedExchangeReport() + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::UPDATE_NEL_POLICY, policy1); + // DoRemoveBrowsingData() + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY, policy1); + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); + // DoRemoveAllBrowsingData() + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY, policy2); + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); +} + +// These two tests check that if loading fails, the commands should still +// be sent to the store; the actual store impl will just ignore them. +TEST_P(NetworkErrorLoggingServiceTest, + SendsCommandsToStoreSynchronousLoadFailed) { + if (!store()) + return; + + MockPersistentNelStore::CommandList expected_commands; + NetworkErrorLoggingService::NelPolicy policy1 = MakePolicyForOrigin(kOrigin_); + NetworkErrorLoggingService::NelPolicy policy2 = + MakePolicyForOrigin(kOriginDifferentHost_); + std::vector<NetworkErrorLoggingService::NelPolicy> prestored_policies = { + policy1, policy2}; + store()->SetPrestoredPolicies(std::move(prestored_policies)); + + // The first call to any of the public methods triggers a load. + service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + // Make the rest of the test run synchronously. + FinishLoading(false /* load_success */); + // DoOnHeader() should now execute. + // Because the load failed, there will be no policies in memory, so the store + // is not told to delete anything. + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::ADD_NEL_POLICY, policy1); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + LOG(INFO) << store()->GetDebugString(); + + service()->OnRequest( + MakeRequestDetails(kOrigin_.GetURL(), ERR_CONNECTION_REFUSED)); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::UPDATE_NEL_POLICY, policy1); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + service()->QueueSignedExchangeReport(MakeSignedExchangeReportDetails( + false, "sxg.failed", kUrl_, kInnerUrl_, kCertUrl_, kServerIP_)); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::UPDATE_NEL_POLICY, policy1); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + // Removes policy1 but not policy2. + service()->RemoveBrowsingData( + base::BindRepeating([](const GURL& origin) -> bool { + return origin.host() == "example.com"; + })); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY, policy1); + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + service()->RemoveAllBrowsingData(); + // We failed to load policy2 from the store, so there is nothing to remove + // here. + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); +} + +TEST_P(NetworkErrorLoggingServiceTest, SendsCommandsToStoreDeferredLoadFailed) { + if (!store()) + return; + + MockPersistentNelStore::CommandList expected_commands; + NetworkErrorLoggingService::NelPolicy policy1 = MakePolicyForOrigin(kOrigin_); + NetworkErrorLoggingService::NelPolicy policy2 = + MakePolicyForOrigin(kOriginDifferentHost_); + std::vector<NetworkErrorLoggingService::NelPolicy> prestored_policies = { + policy1, policy2}; + store()->SetPrestoredPolicies(std::move(prestored_policies)); + + // The first call to any of the public methods triggers a load. + service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + service()->OnRequest( + MakeRequestDetails(kOrigin_.GetURL(), ERR_CONNECTION_REFUSED)); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + service()->QueueSignedExchangeReport(MakeSignedExchangeReportDetails( + false, "sxg.failed", kUrl_, kInnerUrl_, kCertUrl_, kServerIP_)); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + // Removes policy1 but not policy2. + service()->RemoveBrowsingData( + base::BindRepeating([](const GURL& origin) -> bool { + return origin.host() == "example.com"; + })); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + service()->RemoveAllBrowsingData(); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + FinishLoading(false /* load_success */); + // DoOnHeader() + // Because the load failed, there will be no policies in memory, so the store + // is not told to delete anything. + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::ADD_NEL_POLICY, policy1); + // DoOnRequest() + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::UPDATE_NEL_POLICY, policy1); + // DoQueueSignedExchangeReport() + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::UPDATE_NEL_POLICY, policy1); + // DoRemoveBrowsingData() + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::DELETE_NEL_POLICY, policy1); + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); + // DoRemoveAllBrowsingData() + // We failed to load policy2 from the store, so there is nothing to remove + // here. + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); +} + +TEST_P(NetworkErrorLoggingServiceTest, FlushesStoreOnDestruction) { + auto store = std::make_unique<MockPersistentNelStore>(); + std::unique_ptr<NetworkErrorLoggingService> service = + NetworkErrorLoggingService::Create(store.get()); + + MockPersistentNelStore::CommandList expected_commands; + + service->OnHeader(kOrigin_, kServerIP_, kHeader_); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); + EXPECT_TRUE(store->VerifyCommands(expected_commands)); + + store->FinishLoading(false /* load_success */); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::ADD_NEL_POLICY, + MakePolicyForOrigin(kOrigin_)); + EXPECT_TRUE(store->VerifyCommands(expected_commands)); + + // Store should be flushed on destruction of service. + service.reset(); + expected_commands.emplace_back(MockPersistentNelStore::Command::Type::FLUSH); + EXPECT_TRUE(store->VerifyCommands(expected_commands)); +} + +TEST_P(NetworkErrorLoggingServiceTest, + DoesntFlushStoreOnDestructionBeforeLoad) { + auto store = std::make_unique<MockPersistentNelStore>(); + std::unique_ptr<NetworkErrorLoggingService> service = + NetworkErrorLoggingService::Create(store.get()); + + service.reset(); + EXPECT_EQ(0u, store->GetAllCommands().size()); +} + +TEST_P(NetworkErrorLoggingServiceTest, DoNothingIfShutDown) { + if (!store()) + return; + + MockPersistentNelStore::CommandList expected_commands; + + // The first call to any of the public methods triggers a load. + service()->OnHeader(kOrigin_, kServerIP_, kHeader_); + expected_commands.emplace_back( + MockPersistentNelStore::Command::Type::LOAD_NEL_POLICIES); + EXPECT_TRUE(store()->VerifyCommands(expected_commands)); + + service()->OnRequest( + MakeRequestDetails(kOrigin_.GetURL(), ERR_CONNECTION_REFUSED)); + service()->QueueSignedExchangeReport(MakeSignedExchangeReportDetails( + false, "sxg.failed", kUrl_, kInnerUrl_, kCertUrl_, kServerIP_)); + service()->RemoveBrowsingData( + base::BindRepeating([](const GURL& origin) -> bool { + return origin.host() == "example.com"; + })); + service()->RemoveAllBrowsingData(); + + // Finish loading after the service has been shut down. + service()->OnShutdown(); + FinishLoading(true /* load_success */); + + // Only the LOAD command should have been sent to the store. + EXPECT_EQ(1u, store()->GetAllCommands().size()); + EXPECT_EQ(0u, PolicyCount()); + EXPECT_EQ(0u, reports().size()); +} + INSTANTIATE_TEST_SUITE_P(NetworkErrorLoggingServiceStoreTest, NetworkErrorLoggingServiceTest, testing::Bool()); diff --git a/chromium/net/network_error_logging/network_error_logging_test_util.cc b/chromium/net/network_error_logging/network_error_logging_test_util.cc index 54d637613d9..a75a06d8e49 100644 --- a/chromium/net/network_error_logging/network_error_logging_test_util.cc +++ b/chromium/net/network_error_logging/network_error_logging_test_util.cc @@ -33,7 +33,7 @@ void TestNetworkErrorLoggingService::OnRequest(RequestDetails details) { } void TestNetworkErrorLoggingService::QueueSignedExchangeReport( - const SignedExchangeReportDetails& details) {} + SignedExchangeReportDetails details) {} void TestNetworkErrorLoggingService::RemoveBrowsingData( const base::RepeatingCallback<bool(const GURL&)>& origin_filter) {} diff --git a/chromium/net/network_error_logging/network_error_logging_test_util.h b/chromium/net/network_error_logging/network_error_logging_test_util.h index 3eb29c3c4e8..c6af9416b29 100644 --- a/chromium/net/network_error_logging/network_error_logging_test_util.h +++ b/chromium/net/network_error_logging/network_error_logging_test_util.h @@ -48,8 +48,7 @@ class TestNetworkErrorLoggingService : public NetworkErrorLoggingService { const IPAddress& received_ip_address, const std::string& value) override; void OnRequest(RequestDetails details) override; - void QueueSignedExchangeReport( - const SignedExchangeReportDetails& details) override; + void QueueSignedExchangeReport(SignedExchangeReportDetails details) override; void RemoveBrowsingData( const base::RepeatingCallback<bool(const GURL&)>& origin_filter) override; void RemoveAllBrowsingData() override; diff --git a/chromium/net/network_error_logging/persistent_reporting_and_nel_store.h b/chromium/net/network_error_logging/persistent_reporting_and_nel_store.h index ac97e912776..49ae5848770 100644 --- a/chromium/net/network_error_logging/persistent_reporting_and_nel_store.h +++ b/chromium/net/network_error_logging/persistent_reporting_and_nel_store.h @@ -11,9 +11,9 @@ namespace net { // Stores Reporting reports, Reporting clients, and NEL policies. -class NET_EXPORT PersistentReportingAndNELStore +class NET_EXPORT PersistentReportingAndNelStore : public ReportingCache::PersistentReportingStore, - public NetworkErrorLoggingService::PersistentNELStore {}; + public NetworkErrorLoggingService::PersistentNelStore {}; } // namespace net |