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 |