| Index: components/password_manager/content/renderer/credential_manager_client_browsertest.cc
|
| diff --git a/components/password_manager/content/renderer/credential_manager_client_browsertest.cc b/components/password_manager/content/renderer/credential_manager_client_browsertest.cc
|
| index addbcf2a077f80e0c83569bc11b09e8d3cab3183..67dca8fa93dab74a78a52f4712a02ab26cf479e0 100644
|
| --- a/components/password_manager/content/renderer/credential_manager_client_browsertest.cc
|
| +++ b/components/password_manager/content/renderer/credential_manager_client_browsertest.cc
|
| @@ -9,19 +9,70 @@
|
| #include <memory>
|
| #include <tuple>
|
|
|
| -#include "components/password_manager/content/common/credential_manager_messages.h"
|
| +#include "content/public/common/service_registry.h"
|
| +#include "content/public/renderer/render_frame.h"
|
| +#include "content/public/renderer/render_view.h"
|
| #include "content/public/test/render_view_test.h"
|
| -#include "ipc/ipc_test_sink.h"
|
| +#include "mojo/public/cpp/bindings/binding_set.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| #include "third_party/WebKit/public/platform/WebCredential.h"
|
| #include "third_party/WebKit/public/platform/WebCredentialManagerClient.h"
|
| #include "third_party/WebKit/public/platform/WebCredentialManagerError.h"
|
| #include "third_party/WebKit/public/platform/WebPasswordCredential.h"
|
|
|
| +using content::ServiceRegistry;
|
| +
|
| namespace password_manager {
|
|
|
| namespace {
|
|
|
| +const char kTestCredentialPassword[] = "https://password.com/";
|
| +const char kTestCredentialEmpty[] = "https://empty.com/";
|
| +const char kTestCredentialReject[] = "https://reject.com/";
|
| +
|
| +class FakeCredentialManager : public mojom::CredentialManager {
|
| + public:
|
| + FakeCredentialManager() {}
|
| + ~FakeCredentialManager() override {}
|
| +
|
| + void BindRequest(mojom::CredentialManagerRequest request) {
|
| + bindings_.AddBinding(this, std::move(request));
|
| + }
|
| +
|
| + private:
|
| + // mojom::CredentialManager methods:
|
| + void Store(mojom::CredentialInfoPtr credential,
|
| + const StoreCallback& callback) override {
|
| + callback.Run();
|
| + }
|
| +
|
| + void RequireUserMediation(
|
| + const RequireUserMediationCallback& callback) override {
|
| + callback.Run();
|
| + }
|
| +
|
| + void Get(bool zero_click_only,
|
| + bool include_passwords,
|
| + mojo::Array<mojo::String> federations,
|
| + const GetCallback& callback) override {
|
| + mojo::String& url = federations[0];
|
| +
|
| + if (url == kTestCredentialPassword) {
|
| + mojom::CredentialInfoPtr info = mojom::CredentialInfo::New();
|
| + info->type = mojom::CredentialType::PASSWORD;
|
| + callback.Run(mojom::CredentialManagerError::SUCCESS, std::move(info));
|
| + } else if (url == kTestCredentialEmpty) {
|
| + callback.Run(mojom::CredentialManagerError::SUCCESS,
|
| + mojom::CredentialInfo::New());
|
| + } else if (url == kTestCredentialReject) {
|
| + callback.Run(mojom::CredentialManagerError::PASSWORDSTOREUNAVAILABLE,
|
| + nullptr);
|
| + }
|
| + }
|
| +
|
| + mojo::BindingSet<mojom::CredentialManager> bindings_;
|
| +};
|
| +
|
| class CredentialManagerClientTest : public content::RenderViewTest {
|
| public:
|
| CredentialManagerClientTest()
|
| @@ -30,8 +81,14 @@ class CredentialManagerClientTest : public content::RenderViewTest {
|
|
|
| void SetUp() override {
|
| content::RenderViewTest::SetUp();
|
| - credential_.reset(new blink::WebPasswordCredential("", "", "", GURL()));
|
| client_.reset(new CredentialManagerClient(view_));
|
| +
|
| + ServiceRegistry* registry =
|
| + view_->GetMainRenderFrame()->GetServiceRegistry();
|
| + registry->AddServiceOverrideForTesting(
|
| + mojom::CredentialManager::Name_,
|
| + base::Bind(&CredentialManagerClientTest::BindCredentialManager,
|
| + base::Unretained(this)));
|
| }
|
|
|
| void TearDown() override {
|
| @@ -40,60 +97,24 @@ class CredentialManagerClientTest : public content::RenderViewTest {
|
| content::RenderViewTest::TearDown();
|
| }
|
|
|
| - IPC::TestSink& sink() { return render_thread_->sink(); }
|
| -
|
| - blink::WebCredential* credential() { return credential_.get(); }
|
| -
|
| - // The browser's response to any of the messages the client sends must contain
|
| - // a request ID so that the client knows which request is being serviced. This
|
| - // method grabs the ID from an outgoing |message_id| message, and sets the
|
| - // |request_id| param to its value. If no request ID can be found, the method
|
| - // returns false, and the |request_id| is set to -1.
|
| - //
|
| - // Clears any pending messages upon return.
|
| - bool ExtractRequestId(uint32_t message_id, int& request_id) {
|
| - request_id = -1;
|
| - const IPC::Message* message = sink().GetFirstMessageMatching(message_id);
|
| - if (!message)
|
| - return false;
|
| -
|
| - switch (message_id) {
|
| - case CredentialManagerHostMsg_Store::ID: {
|
| - std::tuple<int, CredentialInfo> param;
|
| - CredentialManagerHostMsg_Store::Read(message, ¶m);
|
| - request_id = std::get<0>(param);
|
| - break;
|
| - }
|
| -
|
| - case CredentialManagerHostMsg_RequireUserMediation::ID: {
|
| - std::tuple<int> param;
|
| - CredentialManagerHostMsg_RequireUserMediation::Read(message, ¶m);
|
| - request_id = std::get<0>(param);
|
| - break;
|
| - }
|
| -
|
| - case CredentialManagerHostMsg_RequestCredential::ID: {
|
| - std::tuple<int, bool, bool, std::vector<GURL>> param;
|
| - CredentialManagerHostMsg_RequestCredential::Read(message, ¶m);
|
| - request_id = std::get<0>(param);
|
| - break;
|
| - }
|
| -
|
| - default:
|
| - break;
|
| - }
|
| - sink().ClearMessages();
|
| - return request_id != -1;
|
| - }
|
| -
|
| bool callback_errored() const { return callback_errored_; }
|
| void set_callback_errored(bool state) { callback_errored_ = state; }
|
| bool callback_succeeded() const { return callback_succeeded_; }
|
| void set_callback_succeeded(bool state) { callback_succeeded_ = state; }
|
|
|
| + void BindCredentialManager(mojo::ScopedMessagePipeHandle handle) {
|
| + fake_cm_.BindRequest(
|
| + mojo::MakeRequest<mojom::CredentialManager>(std::move(handle)));
|
| + }
|
| +
|
| + std::unique_ptr<blink::WebPasswordCredential> credential_;
|
| + blink::WebCredentialManagerError error_;
|
| +
|
| protected:
|
| std::unique_ptr<CredentialManagerClient> client_;
|
|
|
| + FakeCredentialManager fake_cm_;
|
| +
|
| // True if a message's callback's 'onSuccess'/'onError' methods were called,
|
| // false otherwise. We put these on the test object rather than on the
|
| // Test*Callbacks objects because ownership of those objects passes into the
|
| @@ -101,8 +122,6 @@ class CredentialManagerClientTest : public content::RenderViewTest {
|
| // pending Blink-side Promise.
|
| bool callback_errored_;
|
| bool callback_succeeded_;
|
| -
|
| - std::unique_ptr<blink::WebPasswordCredential> credential_;
|
| };
|
|
|
| class TestNotificationCallbacks
|
| @@ -131,90 +150,99 @@ class TestRequestCallbacks
|
|
|
| ~TestRequestCallbacks() override {}
|
|
|
| - void onSuccess(std::unique_ptr<blink::WebCredential>) override {
|
| + void onSuccess(std::unique_ptr<blink::WebCredential> credential) override {
|
| test_->set_callback_succeeded(true);
|
| +
|
| + blink::WebCredential* ptr = credential.release();
|
| + test_->credential_.reset(static_cast<blink::WebPasswordCredential*>(ptr));
|
| }
|
|
|
| void onError(blink::WebCredentialManagerError reason) override {
|
| test_->set_callback_errored(true);
|
| + test_->credential_.reset();
|
| + test_->error_ = reason;
|
| }
|
|
|
| private:
|
| CredentialManagerClientTest* test_;
|
| };
|
|
|
| +void RunAllPendingTasks() {
|
| + base::RunLoop run_loop;
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
|
| + run_loop.Run();
|
| +}
|
| +
|
| } // namespace
|
|
|
| TEST_F(CredentialManagerClientTest, SendStore) {
|
| - int request_id;
|
| - EXPECT_FALSE(
|
| - ExtractRequestId(CredentialManagerHostMsg_Store::ID, request_id));
|
| -
|
| + credential_.reset(new blink::WebPasswordCredential("", "", "", GURL()));
|
| std::unique_ptr<TestNotificationCallbacks> callbacks(
|
| new TestNotificationCallbacks(this));
|
| - client_->dispatchStore(*credential(), callbacks.release());
|
| + client_->dispatchStore(*credential_, callbacks.release());
|
|
|
| - EXPECT_TRUE(ExtractRequestId(CredentialManagerHostMsg_Store::ID, request_id));
|
| + RunAllPendingTasks();
|
|
|
| - client_->OnAcknowledgeStore(request_id);
|
| EXPECT_TRUE(callback_succeeded());
|
| EXPECT_FALSE(callback_errored());
|
| }
|
|
|
| TEST_F(CredentialManagerClientTest, SendRequestUserMediation) {
|
| - int request_id;
|
| - EXPECT_FALSE(ExtractRequestId(
|
| - CredentialManagerHostMsg_RequireUserMediation::ID, request_id));
|
| -
|
| std::unique_ptr<TestNotificationCallbacks> callbacks(
|
| new TestNotificationCallbacks(this));
|
| client_->dispatchRequireUserMediation(callbacks.release());
|
|
|
| - EXPECT_TRUE(ExtractRequestId(
|
| - CredentialManagerHostMsg_RequireUserMediation::ID, request_id));
|
| + RunAllPendingTasks();
|
|
|
| - client_->OnAcknowledgeRequireUserMediation(request_id);
|
| EXPECT_TRUE(callback_succeeded());
|
| EXPECT_FALSE(callback_errored());
|
| }
|
|
|
| TEST_F(CredentialManagerClientTest, SendRequestCredential) {
|
| - int request_id;
|
| - EXPECT_FALSE(ExtractRequestId(CredentialManagerHostMsg_RequestCredential::ID,
|
| - request_id));
|
| -
|
| std::unique_ptr<TestRequestCallbacks> callbacks(
|
| new TestRequestCallbacks(this));
|
| std::vector<GURL> federations;
|
| + federations.push_back(GURL(kTestCredentialPassword));
|
| client_->dispatchGet(false, true, federations, callbacks.release());
|
|
|
| - EXPECT_TRUE(ExtractRequestId(CredentialManagerHostMsg_RequestCredential::ID,
|
| - request_id));
|
| + RunAllPendingTasks();
|
|
|
| - CredentialInfo info;
|
| - info.type = CredentialType::CREDENTIAL_TYPE_PASSWORD;
|
| - client_->OnSendCredential(request_id, info);
|
| EXPECT_TRUE(callback_succeeded());
|
| EXPECT_FALSE(callback_errored());
|
| + EXPECT_TRUE(credential_);
|
| + EXPECT_EQ("password", credential_->type());
|
| }
|
|
|
| TEST_F(CredentialManagerClientTest, SendRequestCredentialEmpty) {
|
| - int request_id;
|
| - EXPECT_FALSE(ExtractRequestId(CredentialManagerHostMsg_RequestCredential::ID,
|
| - request_id));
|
| -
|
| std::unique_ptr<TestRequestCallbacks> callbacks(
|
| new TestRequestCallbacks(this));
|
| std::vector<GURL> federations;
|
| + federations.push_back(GURL(kTestCredentialEmpty));
|
| client_->dispatchGet(false, true, federations, callbacks.release());
|
|
|
| - EXPECT_TRUE(ExtractRequestId(CredentialManagerHostMsg_RequestCredential::ID,
|
| - request_id));
|
| + RunAllPendingTasks();
|
|
|
| - CredentialInfo info; // Send an empty credential in response.
|
| - client_->OnSendCredential(request_id, info);
|
| EXPECT_TRUE(callback_succeeded());
|
| EXPECT_FALSE(callback_errored());
|
| + EXPECT_FALSE(credential_);
|
| +}
|
| +
|
| +TEST_F(CredentialManagerClientTest, SendRequestCredentialReject) {
|
| + std::unique_ptr<TestRequestCallbacks> callbacks(
|
| + new TestRequestCallbacks(this));
|
| + std::vector<GURL> federations;
|
| + federations.push_back(GURL(kTestCredentialReject));
|
| + client_->dispatchGet(false, true, federations, callbacks.release());
|
| +
|
| + RunAllPendingTasks();
|
| +
|
| + EXPECT_FALSE(callback_succeeded());
|
| + EXPECT_TRUE(callback_errored());
|
| + EXPECT_FALSE(credential_);
|
| + EXPECT_EQ(blink::WebCredentialManagerError::
|
| + WebCredentialManagerPasswordStoreUnavailableError,
|
| + error_);
|
| }
|
|
|
| } // namespace password_manager
|
|
|