Commit f7c5b3e6 authored by Vasilii Sukhanov's avatar Vasilii Sukhanov Committed by Commit Bot

Make a network request from BulkLeakCheckImpl.

Bug: 1049185
Change-Id: Ia34aad31bf40f5ba5dfbfa52c41982666b3335d6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2066791
Commit-Queue: Vasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#744053}
parent f987c517
...@@ -67,6 +67,8 @@ jumbo_source_set("test_support") { ...@@ -67,6 +67,8 @@ jumbo_source_set("test_support") {
"mock_leak_detection_check_factory.h", "mock_leak_detection_check_factory.h",
"mock_leak_detection_delegate.cc", "mock_leak_detection_delegate.cc",
"mock_leak_detection_delegate.h", "mock_leak_detection_delegate.h",
"mock_leak_detection_request_factory.cc",
"mock_leak_detection_request_factory.h",
] ]
deps = [ deps = [
":leak_detection", ":leak_detection",
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h" #include "components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h"
#include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h" #include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h" #include "components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h"
#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_request_factory.h"
#include "components/password_manager/core/browser/leak_detection/single_lookup_response.h" #include "components/password_manager/core/browser/leak_detection/single_lookup_response.h"
#include "components/signin/public/identity_manager/identity_test_environment.h" #include "components/signin/public/identity_manager/identity_test_environment.h"
#include "crypto/sha2.h" #include "crypto/sha2.h"
...@@ -39,16 +40,6 @@ constexpr char kExampleCom[] = "https://example.com"; ...@@ -39,16 +40,6 @@ constexpr char kExampleCom[] = "https://example.com";
const int64_t kMockElapsedTime = const int64_t kMockElapsedTime =
base::ScopedMockElapsedTimersForTest::kMockElapsedTime.InMilliseconds(); base::ScopedMockElapsedTimersForTest::kMockElapsedTime.InMilliseconds();
class MockLeakDetectionRequest : public LeakDetectionRequestInterface {
public:
// LeakDetectionRequestInterface:
MOCK_METHOD(void, LookupSingleLeak,
(network::mojom::URLLoaderFactory*,
const std::string&,
LookupSingleLeakPayload,
LookupSingleLeakCallback), (override));
};
struct TestLeakDetectionRequest : public LeakDetectionRequestInterface { struct TestLeakDetectionRequest : public LeakDetectionRequestInterface {
~TestLeakDetectionRequest() override = default; ~TestLeakDetectionRequest() override = default;
// LeakDetectionRequestInterface: // LeakDetectionRequestInterface:
...@@ -64,13 +55,6 @@ struct TestLeakDetectionRequest : public LeakDetectionRequestInterface { ...@@ -64,13 +55,6 @@ struct TestLeakDetectionRequest : public LeakDetectionRequestInterface {
LookupSingleLeakCallback callback_; LookupSingleLeakCallback callback_;
}; };
class MockLeakDetectionRequestFactory : public LeakDetectionRequestFactory {
public:
// LeakDetectionRequestFactory:
MOCK_CONST_METHOD0(CreateNetworkRequest,
std::unique_ptr<LeakDetectionRequestInterface>());
};
// Helper struct for making a fake network request. // Helper struct for making a fake network request.
struct PayloadAndCallback { struct PayloadAndCallback {
std::string payload; std::string payload;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "components/password_manager/core/browser/leak_detection/encryption_utils.h" #include "components/password_manager/core/browser/leak_detection/encryption_utils.h"
#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h" #include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
#include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h" #include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
#include "components/password_manager/core/browser/leak_detection/single_lookup_response.h"
#include "components/signin/public/identity_manager/access_token_fetcher.h" #include "components/signin/public/identity_manager/access_token_fetcher.h"
#include "components/signin/public/identity_manager/access_token_info.h" #include "components/signin/public/identity_manager/access_token_info.h"
#include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/shared_url_loader_factory.h"
...@@ -27,7 +28,7 @@ std::unique_ptr<BulkLeakCheckImpl::CredentialHolder> RemoveFromQueue( ...@@ -27,7 +28,7 @@ std::unique_ptr<BulkLeakCheckImpl::CredentialHolder> RemoveFromQueue(
[weak_holder](const auto& element) { [weak_holder](const auto& element) {
return element.get() == weak_holder; return element.get() == weak_holder;
}); });
DCHECK(it != queue->end()); CHECK(it != queue->end());
std::unique_ptr<BulkLeakCheckImpl::CredentialHolder> holder = std::move(*it); std::unique_ptr<BulkLeakCheckImpl::CredentialHolder> holder = std::move(*it);
queue->erase(it); queue->erase(it);
return holder; return holder;
...@@ -51,6 +52,9 @@ struct BulkLeakCheckImpl::CredentialHolder { ...@@ -51,6 +52,9 @@ struct BulkLeakCheckImpl::CredentialHolder {
// Request for the needed access token. // Request for the needed access token.
std::unique_ptr<signin::AccessTokenFetcher> token_fetcher; std::unique_ptr<signin::AccessTokenFetcher> token_fetcher;
// Network request for the API call.
std::unique_ptr<LeakDetectionRequestInterface> network_request_;
}; };
LeakCheckCredential::LeakCheckCredential(base::string16 username, LeakCheckCredential::LeakCheckCredential(base::string16 username,
...@@ -138,7 +142,25 @@ void BulkLeakCheckImpl::OnTokenReady( ...@@ -138,7 +142,25 @@ void BulkLeakCheckImpl::OnTokenReady(
// |this| can be destroyed here. // |this| can be destroyed here.
return; return;
} }
// TODO(crbug.com/1049185): make a network request.
holder->token_fetcher.reset();
holder->network_request_ = network_request_factory_->CreateNetworkRequest();
holder->network_request_->LookupSingleLeak(
url_loader_factory_.get(), access_token_info.token,
std::move(holder->payload),
base::BindOnce(&BulkLeakCheckImpl::OnLookupLeakResponse,
weak_ptr_factory_.GetWeakPtr(), holder.get()));
waiting_response_.push_back(std::move(holder));
}
void BulkLeakCheckImpl::OnLookupLeakResponse(
CredentialHolder* weak_holder,
std::unique_ptr<SingleLookupResponse> response) {
std::unique_ptr<CredentialHolder> holder =
RemoveFromQueue(weak_holder, &waiting_response_);
holder->network_request_.reset();
// TODO(crbug.com/1049185): decrypt the stuff.
} }
} // namespace password_manager } // namespace password_manager
\ No newline at end of file
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h" #include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h"
#include "components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h"
#include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h" #include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
namespace network { namespace network {
...@@ -25,6 +26,7 @@ class IdentityManager; ...@@ -25,6 +26,7 @@ class IdentityManager;
namespace password_manager { namespace password_manager {
class BulkLeakCheckDelegateInterface; class BulkLeakCheckDelegateInterface;
struct SingleLookupResponse;
// Implementation of the bulk leak check. // Implementation of the bulk leak check.
// Every credential in the list is processed consequitively: // Every credential in the list is processed consequitively:
...@@ -48,6 +50,13 @@ class BulkLeakCheckImpl : public BulkLeakCheck { ...@@ -48,6 +50,13 @@ class BulkLeakCheckImpl : public BulkLeakCheck {
void CheckCredentials(std::vector<LeakCheckCredential> credentials) override; void CheckCredentials(std::vector<LeakCheckCredential> credentials) override;
size_t GetPendingChecksCount() const override; size_t GetPendingChecksCount() const override;
#if defined(UNIT_TEST)
void set_network_factory(
std::unique_ptr<LeakDetectionRequestFactory> factory) {
network_request_factory_ = std::move(factory);
}
#endif // defined(UNIT_TEST)
private: private:
// Called when a payload for one credential is ready. // Called when a payload for one credential is ready.
void OnPayloadReady(CredentialHolder* weak_holder, void OnPayloadReady(CredentialHolder* weak_holder,
...@@ -58,6 +67,10 @@ class BulkLeakCheckImpl : public BulkLeakCheck { ...@@ -58,6 +67,10 @@ class BulkLeakCheckImpl : public BulkLeakCheck {
GoogleServiceAuthError error, GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info); signin::AccessTokenInfo access_token_info);
// Called when the server replied with something.
void OnLookupLeakResponse(CredentialHolder* weak_holder,
std::unique_ptr<SingleLookupResponse> response);
// Delegate for the instance. Should outlive |this|. // Delegate for the instance. Should outlive |this|.
BulkLeakCheckDelegateInterface* const delegate_; BulkLeakCheckDelegateInterface* const delegate_;
...@@ -68,6 +81,10 @@ class BulkLeakCheckImpl : public BulkLeakCheck { ...@@ -68,6 +81,10 @@ class BulkLeakCheckImpl : public BulkLeakCheck {
// endpoint. // endpoint.
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// A factory for creating network requests.
std::unique_ptr<LeakDetectionRequestFactory> network_request_factory_ =
std::make_unique<LeakDetectionRequestFactory>();
// The key used to encrypt/decrypt all the payloads for all the credentials. // The key used to encrypt/decrypt all the payloads for all the credentials.
// Creating it once saves CPU time. // Creating it once saves CPU time.
const std::string encryption_key_; const std::string encryption_key_;
...@@ -81,6 +98,9 @@ class BulkLeakCheckImpl : public BulkLeakCheck { ...@@ -81,6 +98,9 @@ class BulkLeakCheckImpl : public BulkLeakCheck {
// the background thread. // the background thread.
base::circular_deque<std::unique_ptr<CredentialHolder>> waiting_token_; base::circular_deque<std::unique_ptr<CredentialHolder>> waiting_token_;
// The queue of the requests waiting for the server reply.
base::circular_deque<std::unique_ptr<CredentialHolder>> waiting_response_;
// Task runner for preparing the payload. It takes a lot of memory. Therefore, // Task runner for preparing the payload. It takes a lot of memory. Therefore,
// those tasks aren't parallelized. // those tasks aren't parallelized.
scoped_refptr<base::SequencedTaskRunner> payload_task_runner_; scoped_refptr<base::SequencedTaskRunner> payload_task_runner_;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h" #include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h" #include "components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h"
#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_request_factory.h"
#include "components/signin/public/identity_manager/identity_test_environment.h" #include "components/signin/public/identity_manager/identity_test_environment.h"
#include "services/network/test/test_shared_url_loader_factory.h" #include "services/network/test/test_shared_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
...@@ -16,6 +17,14 @@ ...@@ -16,6 +17,14 @@
namespace password_manager { namespace password_manager {
namespace { namespace {
using ::testing::_;
using ::testing::AllOf;
using ::testing::ByMove;
using ::testing::ElementsAre;
using ::testing::Field;
using ::testing::Return;
constexpr char kAccessToken[] = "access_token";
constexpr char kTestEmail[] = "user@gmail.com"; constexpr char kTestEmail[] = "user@gmail.com";
LeakCheckCredential TestCredential(base::StringPiece username) { LeakCheckCredential TestCredential(base::StringPiece username) {
...@@ -29,7 +38,12 @@ class BulkLeakCheckTest : public testing::Test { ...@@ -29,7 +38,12 @@ class BulkLeakCheckTest : public testing::Test {
: bulk_check_( : bulk_check_(
&delegate_, &delegate_,
identity_test_env_.identity_manager(), identity_test_env_.identity_manager(),
base::MakeRefCounted<network::TestSharedURLLoaderFactory>()) {} base::MakeRefCounted<network::TestSharedURLLoaderFactory>()) {
auto mock_request_factory = std::make_unique<
::testing::StrictMock<MockLeakDetectionRequestFactory>>();
request_factory_ = mock_request_factory.get();
bulk_check_.set_network_factory(std::move(mock_request_factory));
}
void RunUntilIdle() { task_env_.RunUntilIdle(); } void RunUntilIdle() { task_env_.RunUntilIdle(); }
...@@ -37,12 +51,16 @@ class BulkLeakCheckTest : public testing::Test { ...@@ -37,12 +51,16 @@ class BulkLeakCheckTest : public testing::Test {
return identity_test_env_; return identity_test_env_;
} }
MockBulkLeakCheckDelegateInterface& delegate() { return delegate_; } MockBulkLeakCheckDelegateInterface& delegate() { return delegate_; }
MockLeakDetectionRequestFactory* request_factory() {
return request_factory_;
}
BulkLeakCheckImpl& bulk_check() { return bulk_check_; } BulkLeakCheckImpl& bulk_check() { return bulk_check_; }
private: private:
base::test::TaskEnvironment task_env_; base::test::TaskEnvironment task_env_;
signin::IdentityTestEnvironment identity_test_env_; signin::IdentityTestEnvironment identity_test_env_;
::testing::StrictMock<MockBulkLeakCheckDelegateInterface> delegate_; ::testing::StrictMock<MockBulkLeakCheckDelegateInterface> delegate_;
MockLeakDetectionRequestFactory* request_factory_;
BulkLeakCheckImpl bulk_check_; BulkLeakCheckImpl bulk_check_;
}; };
...@@ -81,7 +99,6 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsAccessTokenAuthError) { ...@@ -81,7 +99,6 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsAccessTokenAuthError) {
identity_test_env().SetCookieAccounts({{info.email, info.gaia}}); identity_test_env().SetCookieAccounts({{info.email, info.gaia}});
identity_test_env().SetRefreshTokenForAccount(info.account_id); identity_test_env().SetRefreshTokenForAccount(info.account_id);
EXPECT_CALL(delegate(), OnFinishedCredential).Times(0);
EXPECT_CALL(delegate(), OnError(LeakDetectionError::kTokenRequestFailure)); EXPECT_CALL(delegate(), OnError(LeakDetectionError::kTokenRequestFailure));
std::vector<LeakCheckCredential> credentials; std::vector<LeakCheckCredential> credentials;
...@@ -98,7 +115,6 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsAccessTokenNetError) { ...@@ -98,7 +115,6 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsAccessTokenNetError) {
identity_test_env().SetCookieAccounts({{info.email, info.gaia}}); identity_test_env().SetCookieAccounts({{info.email, info.gaia}});
identity_test_env().SetRefreshTokenForAccount(info.account_id); identity_test_env().SetRefreshTokenForAccount(info.account_id);
EXPECT_CALL(delegate(), OnFinishedCredential).Times(0);
EXPECT_CALL(delegate(), OnError(LeakDetectionError::kNetworkError)); EXPECT_CALL(delegate(), OnError(LeakDetectionError::kNetworkError));
std::vector<LeakCheckCredential> credentials; std::vector<LeakCheckCredential> credentials;
...@@ -108,5 +124,52 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsAccessTokenNetError) { ...@@ -108,5 +124,52 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsAccessTokenNetError) {
GoogleServiceAuthError::FromConnectionError(net::ERR_TIMED_OUT)); GoogleServiceAuthError::FromConnectionError(net::ERR_TIMED_OUT));
} }
TEST_F(BulkLeakCheckTest, CheckCredentialsAccessDoesNetworkRequest) {
AccountInfo info = identity_test_env().MakeAccountAvailable(kTestEmail);
identity_test_env().SetCookieAccounts({{info.email, info.gaia}});
identity_test_env().SetRefreshTokenForAccount(info.account_id);
std::vector<LeakCheckCredential> credentials;
credentials.push_back(TestCredential("USERNAME@gmail.com"));
bulk_check().CheckCredentials(std::move(credentials));
auto network_request = std::make_unique<MockLeakDetectionRequest>();
EXPECT_CALL(*network_request,
LookupSingleLeak(
_, kAccessToken,
AllOf(Field(&LookupSingleLeakPayload::username_hash_prefix,
ElementsAre(-67, 116, -87)),
Field(&LookupSingleLeakPayload::encrypted_payload,
testing::Ne(""))),
_));
EXPECT_CALL(*request_factory(), CreateNetworkRequest)
.WillOnce(Return(ByMove(std::move(network_request))));
identity_test_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
kAccessToken, base::Time::Max());
}
TEST_F(BulkLeakCheckTest, CheckCredentialsMultipleNetworkRequests) {
AccountInfo info = identity_test_env().MakeAccountAvailable(kTestEmail);
identity_test_env().SetCookieAccounts({{info.email, info.gaia}});
identity_test_env().SetRefreshTokenForAccount(info.account_id);
std::vector<LeakCheckCredential> credentials;
credentials.push_back(TestCredential("user1"));
credentials.push_back(TestCredential("user2"));
bulk_check().CheckCredentials(std::move(credentials));
auto network_request1 = std::make_unique<MockLeakDetectionRequest>();
auto network_request2 = std::make_unique<MockLeakDetectionRequest>();
EXPECT_CALL(*network_request1, LookupSingleLeak(_, kAccessToken, _, _));
EXPECT_CALL(*network_request2, LookupSingleLeak(_, kAccessToken, _, _));
EXPECT_CALL(*request_factory(), CreateNetworkRequest)
.WillOnce(Return(ByMove(std::move(network_request1))))
.WillOnce(Return(ByMove(std::move(network_request2))));
identity_test_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
kAccessToken, base::Time::Max());
identity_test_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
kAccessToken, base::Time::Max());
}
} // namespace } // namespace
} // namespace password_manager } // namespace password_manager
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_request_factory.h"
namespace password_manager {
MockLeakDetectionRequest::MockLeakDetectionRequest() = default;
MockLeakDetectionRequest::~MockLeakDetectionRequest() = default;
MockLeakDetectionRequestFactory::MockLeakDetectionRequestFactory() = default;
MockLeakDetectionRequestFactory::~MockLeakDetectionRequestFactory() = default;
} // namespace password_manager
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_MOCK_LEAK_DETECTION_REQUEST_FACTORY_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_MOCK_LEAK_DETECTION_REQUEST_FACTORY_H_
#include "components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h"
#include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace password_manager {
class MockLeakDetectionRequest : public LeakDetectionRequestInterface {
public:
MockLeakDetectionRequest();
~MockLeakDetectionRequest() override;
// LeakDetectionRequestInterface:
MOCK_METHOD(void,
LookupSingleLeak,
(network::mojom::URLLoaderFactory*,
const std::string&,
LookupSingleLeakPayload,
LookupSingleLeakCallback),
(override));
};
class MockLeakDetectionRequestFactory : public LeakDetectionRequestFactory {
public:
MockLeakDetectionRequestFactory();
~MockLeakDetectionRequestFactory() override;
// LeakDetectionRequestFactory:
MOCK_METHOD(std::unique_ptr<LeakDetectionRequestInterface>,
CreateNetworkRequest,
(),
(const override));
};
} // namespace password_manager
#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_MOCK_LEAK_DETECTION_REQUEST_FACTORY_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment