summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/automation/automation_provider.cc68
-rw-r--r--chrome/browser/automation/automation_provider.h24
-rw-r--r--chrome/browser/automation/automation_provider_observers.cc25
-rw-r--r--chrome/browser/automation/automation_provider_observers.h19
-rw-r--r--chrome/test/functional/PYAUTO_TESTS1
-rw-r--r--chrome/test/functional/passwords.py60
-rw-r--r--chrome/test/pyautolib/pyauto.py37
7 files changed, 228 insertions, 6 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index 7aeca99..18b7d7b 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -96,6 +96,7 @@
#include "net/url_request/url_request_context.h"
#include "chrome/browser/automation/ui_controls.h"
#include "views/event.h"
+#include "webkit/glue/password_form.h"
#include "webkit/glue/plugins/plugin_list.h"
#if defined(OS_WIN)
@@ -2359,6 +2360,70 @@ void AutomationProvider::ImportSettings(Browser* browser,
new ProfileWriter(profile), first_run);
}
+// See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json
+// input.
+// Sample json output: { "password_added": true }
+void AutomationProvider::AddSavedPassword(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ string16 username;
+ string16 password;
+ base::Time time = base::Time::Now();
+ AutomationJSONReply reply(this, reply_message);
+
+ if (!args->GetStringAsUTF16(L"password", &password) ||
+ !args->GetStringAsUTF16(L"username", &username)) {
+ reply.SendError("Username and password must be strings.");
+ return;
+ }
+
+ // If the time is specified, change time to the specified time.
+ int it;
+ double dt;
+ if (args->GetInteger(L"time", &it))
+ time = base::Time::FromTimeT(it);
+ else if (args->GetReal(L"time", &dt))
+ time = base::Time::FromDoubleT(dt);
+
+ webkit_glue::PasswordForm new_password;
+ new_password.username_value = username;
+ new_password.password_value = password;
+ new_password.date_created = time;
+
+ Profile* profile = browser->profile();
+ // Use IMPLICIT_ACCESS since new passwords aren't added off the record.
+ PasswordStore* password_store =
+ profile->GetPasswordStore(Profile::IMPLICIT_ACCESS);
+
+ // Set the return based on whether setting the password succeeded.
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+
+ // It will be null if it's accessed in an incognito window.
+ if (password_store != NULL) {
+ password_store->AddLogin(new_password);
+ return_value->SetBoolean(L"password_added", true);
+ } else {
+ return_value->SetBoolean(L"password_added", false);
+ }
+
+ reply.SendSuccess(return_value.get());
+}
+
+// Sample json input: { "command": "GetSavedPasswords" }
+// Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample
+// json output.
+void AutomationProvider::GetSavedPasswords(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ Profile* profile = browser->profile();
+ // Use EXPLICIT_ACCESS since saved passwords can be retreived off the record.
+ PasswordStore* password_store =
+ profile->GetPasswordStore(Profile::EXPLICIT_ACCESS);
+ password_store->GetAutofillableLogins(
+ new AutomationProviderGetPasswordsObserver(this, reply_message));
+ // Observer deletes itself after returning.
+}
+
// Refer to ClearBrowsingData() in chrome/test/pyautolib/pyauto.py for sample
// json input.
// Sample json output: {}
@@ -2752,6 +2817,9 @@ void AutomationProvider::SendJSONRequest(int handle,
handler_map["ImportSettings"] = &AutomationProvider::ImportSettings;
+ handler_map["AddSavedPassword"] = &AutomationProvider::AddSavedPassword;
+ handler_map["GetSavedPasswords"] = &AutomationProvider::GetSavedPasswords;
+
handler_map["ClearBrowsingData"] = &AutomationProvider::ClearBrowsingData;
// SetTheme() implemented using InstallExtension().
diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h
index 78aa363..cb09280 100644
--- a/chrome/browser/automation/automation_provider.h
+++ b/chrome/browser/automation/automation_provider.h
@@ -442,6 +442,24 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
DictionaryValue* args,
IPC::Message* reply_message);
+ // Import the given settings from the given browser.
+ // Uses the JSON interface for input/output.
+ void ImportSettings(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Add a new username-password combination to the saved passwords.
+ // Uses the JSON interface for input/output.
+ void AddSavedPassword(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Return the saved username/password combinations.
+ // Uses the JSON interface for input/output.
+ void GetSavedPasswords(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
// Clear the specified browsing data. This call provides similar
// functionality to RemoveBrowsingData but is synchronous.
// Uses the JSON interface for input/output.
@@ -461,12 +479,6 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
DictionaryValue* args,
IPC::Message* reply_message);
- // Import the given settings from the given browser.
- // Uses the JSON interface for input/output.
- void ImportSettings(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
// Fill in an AutoFillProfile with the given profile information.
// Uses the JSON interface for input/output.
void FillAutoFillProfile(Browser* browser,
diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc
index 0745a90..a60883d 100644
--- a/chrome/browser/automation/automation_provider_observers.cc
+++ b/chrome/browser/automation/automation_provider_observers.cc
@@ -1013,6 +1013,31 @@ void AutomationProviderImportSettingsObserver::ImportEnded() {
delete this;
}
+void AutomationProviderGetPasswordsObserver::OnPasswordStoreRequestDone(
+ int handle, const std::vector<webkit_glue::PasswordForm*>& result) {
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+
+ ListValue* passwords = new ListValue;
+ for (std::vector<webkit_glue::PasswordForm*>::const_iterator it =
+ result.begin(); it != result.end(); ++it) {
+ DictionaryValue* password_val = new DictionaryValue;
+ webkit_glue::PasswordForm* password_form = *it;
+ password_val->SetStringFromUTF16(L"username",
+ password_form->username_value);
+ password_val->SetStringFromUTF16(L"password",
+ password_form->password_value);
+ password_val->SetReal(
+ L"time", static_cast<double>(
+ password_form->date_created.ToDoubleT()));
+ passwords->Append(password_val);
+ }
+
+ return_value->Set(L"passwords", passwords);
+ AutomationJSONReply(provider_, reply_message_).SendSuccess(
+ return_value.get());
+ delete this;
+}
+
void AutomationProviderBrowsingDataObserver::OnBrowsingDataRemoverDone() {
// Send back an empty success message
AutomationJSONReply(provider_, reply_message_).SendSuccess(NULL);
diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h
index 8bb100a..21e87c0 100644
--- a/chrome/browser/automation/automation_provider_observers.h
+++ b/chrome/browser/automation/automation_provider_observers.h
@@ -14,6 +14,7 @@
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/importer/importer.h"
#include "chrome/browser/importer/importer_data_types.h"
+#include "chrome/browser/password_manager/password_store.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_type.h"
@@ -632,6 +633,24 @@ class AutomationProviderImportSettingsObserver :
IPC::Message* reply_message_;
};
+// Allows automation provider to wait for getting passwords to finish.
+class AutomationProviderGetPasswordsObserver :
+ public PasswordStoreConsumer {
+ public:
+ AutomationProviderGetPasswordsObserver(
+ AutomationProvider* provider,
+ IPC::Message* reply_message)
+ : provider_(provider),
+ reply_message_(reply_message) {}
+
+ void OnPasswordStoreRequestDone(
+ int handle, const std::vector<webkit_glue::PasswordForm*>& result);
+
+ private:
+ AutomationProvider* provider_;
+ IPC::Message* reply_message_;
+};
+
// Allows the automation provider to wait for clearing browser data to finish.
class AutomationProviderBrowsingDataObserver :
public BrowsingDataRemover::Observer {
diff --git a/chrome/test/functional/PYAUTO_TESTS b/chrome/test/functional/PYAUTO_TESTS
index afb3885..783d86b 100644
--- a/chrome/test/functional/PYAUTO_TESTS
+++ b/chrome/test/functional/PYAUTO_TESTS
@@ -33,6 +33,7 @@
'history',
'navigation',
'omnibox',
+ 'passwords',
'plugins',
'prefs',
'special_tabs',
diff --git a/chrome/test/functional/passwords.py b/chrome/test/functional/passwords.py
new file mode 100644
index 0000000..f0d7e9e
--- /dev/null
+++ b/chrome/test/functional/passwords.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+# Copyright (c) 2010 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.
+
+import time
+
+import pyauto_functional # Must be imported before pyauto
+import pyauto
+
+
+class PasswordTest(pyauto.PyUITest):
+ """Tests that passwords work correctly"""
+
+ def Debug(self):
+ """Test method for experimentation.
+
+ This method will not run automatically.
+ """
+ while True:
+ raw_input('Interact with the browser and hit <enter> to dump passwords. ')
+ print '*' * 20
+ import pprint
+ pp = pprint.PrettyPrinter(indent=2)
+ pp.pprint(self.GetSavedPasswords())
+
+ def _AssertWithinOneSecond(self, time1, time2):
+ self.assertTrue(abs(time1 - time2) < 1.0,
+ 'Times not within an acceptable range. '
+ 'First was %lf, second was %lf' % (time1, time2))
+
+ def testSavePassword(self):
+ """Test saving a password and getting saved passwords."""
+ username1 = 'username1'
+ password1 = 'password1'
+ username2 = 'username2'
+ password2 = 'password2'
+
+ self.AddSavedPassword(username1, password1)
+ passwords = self.GetSavedPasswords()['passwords']
+ self.assertEqual(1, len(passwords))
+ pw = passwords[0]
+ self.assertEqual(username1, pw['username'])
+ self.assertEqual(password1, pw['password'])
+
+ now = time.time()
+ self.AddSavedPassword(username2, password2, now)
+ passwords = self.GetSavedPasswords()['passwords']
+ self.assertEqual(2, len(passwords))
+ pw1 = passwords[0]
+ pw2 = passwords[1]
+ self.assertEqual(username1, pw1['username'])
+ self.assertEqual(password1, pw1['password'])
+ self.assertEqual(username2, pw2['username'])
+ self.assertEqual(password2, pw2['password'])
+ self._AssertWithinOneSecond(now, pw2['time'])
+
+
+if __name__ == '__main__':
+ pyauto_functional.Main()
diff --git a/chrome/test/pyautolib/pyauto.py b/chrome/test/pyautolib/pyauto.py
index 10a4504..fc3e306 100644
--- a/chrome/test/pyautolib/pyauto.py
+++ b/chrome/test/pyautolib/pyauto.py
@@ -806,6 +806,43 @@ class PyUITest(pyautolib.PyUITestBase, unittest.TestCase):
}
return self._GetResultFromJSONRequest(cmd_dict)
+ def AddSavedPassword(self, username, password, time=None, window_index=0):
+ """Adds the given username-password combination to the saved passwords.
+
+ Args:
+ username: a string representing the username
+ password: a string representing the password
+ window_index: window index, defaults to 0
+
+ Returns:
+ The success or failure of adding the password. In incognito mode, adding
+ the password should fail. Example return:
+ { "password_added": True }
+
+ Raises:
+ JSONInterfaceError on error.
+ """
+ cmd_dict = { # Prepare command for the json interface
+ 'command': 'AddSavedPassword',
+ 'username': username,
+ 'password': password,
+ 'time': time
+ }
+ return self._GetResultFromJSONRequest(cmd_dict)
+
+ def GetSavedPasswords(self):
+ """Return the passwords currently saved.
+
+ Returns:
+ A list of 2-item lists of username, password for all saved passwords.
+ Example:
+ { 'passwords': [['username1', 'password1'], ['username2', 'password2']] }
+ """
+ cmd_dict = { # Prepare command for the json interface
+ 'command': 'GetSavedPasswords'
+ }
+ return self._GetResultFromJSONRequest(cmd_dict)
+
def SetTheme(self, crx_file_path):
"""Installs the given theme synchronously.