diff options
-rw-r--r-- | chrome/browser/automation/automation_provider.cc | 68 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider.h | 24 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_observers.cc | 25 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_observers.h | 19 | ||||
-rw-r--r-- | chrome/test/functional/PYAUTO_TESTS | 1 | ||||
-rw-r--r-- | chrome/test/functional/passwords.py | 60 | ||||
-rw-r--r-- | chrome/test/pyautolib/pyauto.py | 37 |
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. |