Index: chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc |
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7c462fa448af1c29411100e788505d7bca7abe97 |
--- /dev/null |
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc |
@@ -0,0 +1,198 @@ |
+// Copyright 2015 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 <sstream> |
+ |
+#include "base/command_line.h" |
+#include "base/memory/linked_ptr.h" |
+#include "base/observer_list_threadsafe.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "base/values.h" |
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h" |
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h" |
+#include "chrome/browser/extensions/extension_apitest.h" |
+#include "chrome/common/extensions/api/passwords_private.h" |
+#include "chrome/test/base/testing_profile.h" |
+#include "components/keyed_service/core/keyed_service.h" |
+#include "content/public/test/test_utils.h" |
+#include "extensions/common/switches.h" |
+ |
+namespace extensions { |
+ |
+namespace { |
+ |
+static const size_t kNumMocks = 3; |
+static const int kNumCharactersInPassword = 10; |
+static const char kPlaintextPassword[] = "plaintext"; |
+ |
+linked_ptr<api::passwords_private::PasswordUiEntry> CreateEntry(size_t num) { |
+ api::passwords_private::PasswordUiEntry* entry = |
+ new api::passwords_private::PasswordUiEntry(); |
+ std::stringstream ss; |
+ ss << "http://test" << num << ".com"; |
+ entry->login_pair.origin_url = ss.str(); |
+ ss.clear(); |
+ ss << "testName" << num; |
+ entry->login_pair.username = ss.str(); |
+ entry->num_characters_in_password = kNumCharactersInPassword; |
+ return make_linked_ptr(entry); |
+} |
+ |
+std::string CreateException(size_t num) { |
+ std::stringstream ss; |
+ ss << "http://exception" << num << ".com"; |
+ return ss.str(); |
+} |
+ |
+// A test PasswordsPrivateDelegate implementation which uses mock data. |
+// TestDelegate starts out with kNumMocks mocks of each type (saved password |
+// and password exception) and removes one mock each time RemoveSavedPassword() |
+// or RemovePasswordException() is called. |
+class TestDelegate : public PasswordsPrivateDelegate { |
+ public: |
+ TestDelegate() : observers_(new base::ObserverListThreadSafe<Observer>()) { |
+ // Create mock data. |
+ for (size_t i = 0; i < kNumMocks; i++) { |
+ current_entries_.push_back(CreateEntry(i));; |
+ current_exceptions_.push_back(CreateException(i)); |
+ } |
+ } |
+ ~TestDelegate() override {} |
+ |
+ void AddObserver(Observer* observer) override { |
+ observers_->AddObserver(observer); |
+ SendSavedPasswordsList(); |
+ SendPasswordExceptionsList(); |
+ } |
+ |
+ void RemoveObserver(Observer* observer) override { |
+ observers_->RemoveObserver(observer); |
+ } |
+ |
+ void RemoveSavedPassword( |
+ const std::string& origin_url, const std::string& username) override { |
+ if (!current_entries_.size()) |
+ return; |
+ |
+ // Since this is just mock data, remove the first entry regardless of |
+ // the data contained. |
+ current_entries_.erase(current_entries_.begin()); |
+ SendSavedPasswordsList(); |
+ } |
+ |
+ void RemovePasswordException(const std::string& exception_url) override { |
+ if (!current_exceptions_.size()) |
+ return; |
+ |
+ // Since this is just mock data, remove the first entry regardless of |
+ // the data contained. |
+ current_exceptions_.erase(current_exceptions_.begin()); |
+ SendPasswordExceptionsList(); |
+ } |
+ |
+ void RequestShowPassword( |
+ const std::string& origin_url, |
+ const std::string& username, |
+ const content::RenderViewHost* render_view_host) override { |
+ // Return a mocked password value. |
+ std::string plaintext_password(kPlaintextPassword); |
+ observers_->Notify( |
+ FROM_HERE, |
+ &Observer::OnPlaintextPasswordFetched, |
+ origin_url, |
+ username, |
+ plaintext_password); |
+ } |
+ |
+ private: |
+ void SendSavedPasswordsList() { |
+ observers_->Notify( |
+ FROM_HERE, |
+ &Observer::OnSavedPasswordsListChanged, |
+ current_entries_); |
+ } |
+ |
+ void SendPasswordExceptionsList() { |
+ observers_->Notify( |
+ FROM_HERE, |
+ &Observer::OnPasswordExceptionsListChanged, |
+ current_exceptions_); |
+ } |
+ |
+ // The current list of entries/exceptions. Cached here so that when new |
+ // observers are added, this delegate can send the current lists without |
+ // having to request them from |password_manager_presenter_| again. |
+ std::vector<linked_ptr<api::passwords_private::PasswordUiEntry>> |
+ current_entries_; |
+ std::vector<std::string> current_exceptions_; |
+ |
+ // The observers. |
+ scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_; |
+}; |
+ |
+class PasswordsPrivateApiTest : public ExtensionApiTest { |
+ public: |
+ PasswordsPrivateApiTest() { |
+ if (!s_test_delegate_) { |
+ s_test_delegate_ = new TestDelegate(); |
+ } |
+ } |
+ ~PasswordsPrivateApiTest() override {} |
+ |
+ static scoped_ptr<KeyedService> GetPasswordsPrivateDelegate( |
+ content::BrowserContext* profile) { |
+ CHECK(s_test_delegate_); |
+ return make_scoped_ptr(s_test_delegate_); |
+ } |
+ |
+ void SetUpCommandLine(base::CommandLine* command_line) override { |
+ ExtensionApiTest::SetUpCommandLine(command_line); |
+ } |
+ |
+ void SetUp() override { |
+ ExtensionApiTest::SetUp(); |
+ } |
+ |
+ void SetUpOnMainThread() override { |
+ ExtensionApiTest::SetUpOnMainThread(); |
+ PasswordsPrivateDelegateFactory::GetInstance()->SetTestingFactory( |
+ profile(), &PasswordsPrivateApiTest::GetPasswordsPrivateDelegate); |
+ content::RunAllPendingInMessageLoop(); |
+ } |
+ |
+ protected: |
+ bool RunPasswordsSubtest(const std::string& subtest) { |
+ return RunExtensionSubtest("passwords_private", |
+ "main.html?" + subtest, |
+ kFlagLoadAsComponent); |
+ } |
+ |
+ private: |
+ static TestDelegate* s_test_delegate_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateApiTest); |
+}; |
+ |
+// static |
+TestDelegate* PasswordsPrivateApiTest::s_test_delegate_ = nullptr; |
+ |
+} // namespace |
+ |
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, CanPasswordAccountBeManaged) { |
+ EXPECT_TRUE(RunPasswordsSubtest("canPasswordAccountBeManaged")) << message_; |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, RemoveSavedPassword) { |
+ EXPECT_TRUE(RunPasswordsSubtest("removeSavedPassword")) << message_; |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, RemovePasswordException) { |
+ EXPECT_TRUE(RunPasswordsSubtest("removePasswordException")) << message_; |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, RequestPlaintextPassword) { |
+ EXPECT_TRUE(RunPasswordsSubtest("requestPlaintextPassword")) << message_; |
+} |
+ |
+} // namespace extensions |