summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/automation/automation_provider.cc122
-rw-r--r--chrome/browser/automation/automation_provider.h15
-rw-r--r--chrome/browser/automation/automation_provider_observers.cc14
-rw-r--r--chrome/test/functional/passwords.py37
-rw-r--r--chrome/test/pyautolib/pyauto.py54
5 files changed, 182 insertions, 60 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index bf52686..5b3fe45 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -2536,35 +2536,87 @@ void AutomationProvider::ImportSettings(Browser* browser,
new ProfileWriter(profile), first_run);
}
+namespace {
+
+// Translates a dictionary password to a PasswordForm struct.
+webkit_glue::PasswordForm GetPasswordFormFromDict(
+ const DictionaryValue& password_dict) {
+
+ // If the time is specified, change time to the specified time.
+ base::Time time = base::Time::Now();
+ int it;
+ double dt;
+ if (password_dict.GetInteger(L"time", &it))
+ time = base::Time::FromTimeT(it);
+ else if (password_dict.GetReal(L"time", &dt))
+ time = base::Time::FromDoubleT(dt);
+
+ std::string signon_realm;
+ string16 username_value;
+ string16 password_value;
+ string16 origin_url_text;
+ string16 username_element;
+ string16 password_element;
+ string16 submit_element;
+ string16 action_target_text;
+ bool blacklist = false;
+ string16 old_password_element;
+ string16 old_password_value;
+
+ // We don't care if any of these fail - they are either optional or checked
+ // before this function is called.
+ password_dict.GetString(L"signon_realm", &signon_realm);
+ password_dict.GetStringAsUTF16(L"username_value", &username_value);
+ password_dict.GetStringAsUTF16(L"password_value", &password_value);
+ password_dict.GetStringAsUTF16(L"origin_url", &origin_url_text);
+ password_dict.GetStringAsUTF16(L"username_element", &username_element);
+ password_dict.GetStringAsUTF16(L"password_element", &password_element);
+ password_dict.GetStringAsUTF16(L"submit_element", &submit_element);
+ password_dict.GetStringAsUTF16(L"action_target", &action_target_text);
+ password_dict.GetBoolean(L"blacklist", &blacklist);
+
+ GURL origin_gurl(origin_url_text);
+ GURL action_target(action_target_text);
+
+ webkit_glue::PasswordForm password_form;
+ password_form.signon_realm = signon_realm;
+ password_form.username_value = username_value;
+ password_form.password_value = password_value;
+ password_form.origin = origin_gurl;
+ password_form.username_element = username_element;
+ password_form.password_element = password_element;
+ password_form.submit_element = submit_element;
+ password_form.action = action_target;
+ password_form.blacklisted_by_user = blacklist;
+ password_form.date_created = time;
+
+ return password_form;
+}
+
+} // namespace
+
// 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);
+ DictionaryValue* password_dict = NULL;
- if (!args->GetStringAsUTF16(L"password", &password) ||
- !args->GetStringAsUTF16(L"username", &username)) {
- reply.SendError("Username and password must be strings.");
+ if (!args->GetDictionary(L"password", &password_dict)) {
+ reply.SendError("Password must be a dictionary.");
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;
+ // The signon realm is effectively the primary key and must be included.
+ // Check here before calling GetPasswordFormFromDict.
+ if (!password_dict->HasKey(L"signon_realm")) {
+ reply.SendError("Password must include signon_realm.");
+ return;
+ }
+ webkit_glue::PasswordForm new_password =
+ GetPasswordFormFromDict(*password_dict);
Profile* profile = browser->profile();
// Use IMPLICIT_ACCESS since new passwords aren't added off the record.
@@ -2585,6 +2637,38 @@ void AutomationProvider::AddSavedPassword(Browser* browser,
reply.SendSuccess(return_value.get());
}
+// See RemoveSavedPassword() in chrome/test/functional/pyauto.py for sample
+// json input.
+// Sample json output: {}
+void AutomationProvider::RemoveSavedPassword(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ AutomationJSONReply reply(this, reply_message);
+ DictionaryValue* password_dict = NULL;
+
+ if (!args->GetDictionary(L"password", &password_dict)) {
+ reply.SendError("Password must be a dictionary.");
+ return;
+ }
+
+ // The signon realm is effectively the primary key and must be included.
+ // Check here before calling GetPasswordFormFromDict.
+ if (!password_dict->HasKey(L"signon_realm")) {
+ reply.SendError("Password must include signon_realm.");
+ return;
+ }
+ webkit_glue::PasswordForm to_remove =
+ GetPasswordFormFromDict(*password_dict);
+
+ Profile* profile = browser->profile();
+ // Use EXPLICIT_ACCESS since passwords can be removed off the record.
+ PasswordStore* password_store =
+ profile->GetPasswordStore(Profile::EXPLICIT_ACCESS);
+
+ password_store->RemoveLogin(to_remove);
+ reply.SendSuccess(NULL);
+}
+
// Sample json input: { "command": "GetSavedPasswords" }
// Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample
// json output.
@@ -2998,6 +3082,8 @@ void AutomationProvider::SendJSONRequest(int handle,
handler_map["ImportSettings"] = &AutomationProvider::ImportSettings;
handler_map["AddSavedPassword"] = &AutomationProvider::AddSavedPassword;
+ handler_map["RemoveSavedPassword"] =
+ &AutomationProvider::RemoveSavedPassword;
handler_map["GetSavedPasswords"] = &AutomationProvider::GetSavedPasswords;
handler_map["ClearBrowsingData"] = &AutomationProvider::ClearBrowsingData;
diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h
index 0bc30fcc..dbaeb1f 100644
--- a/chrome/browser/automation/automation_provider.h
+++ b/chrome/browser/automation/automation_provider.h
@@ -62,6 +62,10 @@ namespace gfx {
class Point;
}
+namespace webkit_glue {
+struct PasswordForm;
+}
+
class AutomationProvider : public base::RefCounted<AutomationProvider>,
public IPC::Channel::Listener,
public IPC::Message::Sender {
@@ -467,12 +471,21 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
DictionaryValue* args,
IPC::Message* reply_message);
- // Add a new username-password combination to the saved passwords.
+ // Add a new entry to the password store based on the password information
+ // provided. This method can also be used to add a blacklisted site (which
+ // will never fill in the password).
// Uses the JSON interface for input/output.
void AddSavedPassword(Browser* browser,
DictionaryValue* args,
IPC::Message* reply_message);
+ // Removes the password matching the information provided. This method can
+ // also be used to remove a blacklisted site.
+ // Uses the JSON interface for input/output.
+ void RemoveSavedPassword(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,
diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc
index 6725ae1..a9414be 100644
--- a/chrome/browser/automation/automation_provider_observers.cc
+++ b/chrome/browser/automation/automation_provider_observers.cc
@@ -1024,13 +1024,23 @@ void AutomationProviderGetPasswordsObserver::OnPasswordStoreRequestDone(
result.begin(); it != result.end(); ++it) {
DictionaryValue* password_val = new DictionaryValue;
webkit_glue::PasswordForm* password_form = *it;
- password_val->SetStringFromUTF16(L"username",
+ password_val->SetStringFromUTF16(L"username_value",
password_form->username_value);
- password_val->SetStringFromUTF16(L"password",
+ password_val->SetStringFromUTF16(L"password_value",
password_form->password_value);
+ password_val->SetString(L"signon_realm", password_form->signon_realm);
password_val->SetReal(
L"time", static_cast<double>(
password_form->date_created.ToDoubleT()));
+ password_val->SetString(L"origin_url", password_form->origin.spec());
+ password_val->SetStringFromUTF16(L"username_element",
+ password_form->username_element);
+ password_val->SetStringFromUTF16(L"password_element",
+ password_form->password_element);
+ password_val->SetStringFromUTF16(L"submit_element",
+ password_form->submit_element);
+ password_val->SetString(L"action_target", password_form->action.spec());
+ password_val->SetBoolean(L"blacklist", password_form->blacklisted_by_user);
passwords->Append(password_val);
}
diff --git a/chrome/test/functional/passwords.py b/chrome/test/functional/passwords.py
index f0d7e9e..7d88eb9 100644
--- a/chrome/test/functional/passwords.py
+++ b/chrome/test/functional/passwords.py
@@ -3,8 +3,6 @@
# 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
@@ -31,29 +29,18 @@ class PasswordTest(pyauto.PyUITest):
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'])
+ password1 = { 'username_value': 'user@example.com',
+ 'password_value': 'test.password',
+ 'signon_realm': 'https://www.example.com/',
+ 'time': 1279650942.0,
+ 'origin_url': 'https://www.example.com/login',
+ 'username_element': 'username',
+ 'password_element': 'password',
+ 'submit_element': 'submit',
+ 'action_target': 'https://www.example.com/login/',
+ 'blacklist': False }
+ self.assertTrue(self.AddSavedPassword(password1))
+ self.assertEquals(self.GetSavedPasswords(), [password1])
if __name__ == '__main__':
diff --git a/chrome/test/pyautolib/pyauto.py b/chrome/test/pyautolib/pyauto.py
index 716f14d..28e39ed 100644
--- a/chrome/test/pyautolib/pyauto.py
+++ b/chrome/test/pyautolib/pyauto.py
@@ -890,42 +890,68 @@ class PyUITest(pyautolib.PyUITestBase, unittest.TestCase):
}
return self._GetResultFromJSONRequest(cmd_dict)
- def AddSavedPassword(self, username, password, time=None, window_index=0):
+ def AddSavedPassword(self, password_dict, 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
+ password_dict: a dictionary that represents a password. Example:
+ { 'username_value': 'user@example.com', # Required
+ 'password_value': 'test.password', # Required
+ 'signon_realm': 'https://www.example.com/', # Required
+ 'time': 1279317810.0, # Can get from time.time()
+ 'origin_url': 'https://www.example.com/login',
+ 'username_element': 'username', # The HTML element
+ 'password_element': 'password', # The HTML element
+ 'submit_element': 'submit', # The HTML element
+ 'action_target': 'https://www.example.com/login/',
+ 'blacklist': False }
window_index: window index, defaults to 0
+ *Blacklist notes* To blacklist a site, add a blacklist password with the
+ following dictionary items: origin_url, signon_realm, username_element,
+ password_element, action_target, and 'blacklist': True. Then all sites that
+ have password forms matching those are blacklisted.
+
Returns:
- The success or failure of adding the password. In incognito mode, adding
- the password should fail. Example return:
- { "password_added": True }
+ True if adding the password succeeded, false otherwise. In incognito
+ mode, adding the password should fail.
Raises:
JSONInterfaceError on error.
"""
cmd_dict = { # Prepare command for the json interface
'command': 'AddSavedPassword',
- 'username': username,
- 'password': password,
- 'time': time
+ 'password': password_dict
}
- return self._GetResultFromJSONRequest(cmd_dict, windex=window_index)
+ return self._GetResultFromJSONRequest(
+ cmd_dict, windex=window_index)['password_added']
+
+ def RemoveSavedPassword(self, password_dict):
+ """Removes the password matching the provided password dictionary.
+
+ Args:
+ password_dict: A dictionary that represents a password.
+ For an example, see the dictionary in AddSavedPassword.
+ """
+ cmd_dict = { # Prepare command for the json interface
+ 'command': 'RemoveSavedPassword',
+ 'password': password_dict
+ }
+ self._GetResultFromJSONRequest(cmd_dict, windex=window_index)
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']] }
+ A list of dictionaries representing each password. For an example
+ dictionary see AddSavedPassword documentation. The overall structure will
+ be:
+ [ {password1 dictionary}, {password2 dictionary} ]
"""
cmd_dict = { # Prepare command for the json interface
'command': 'GetSavedPasswords'
}
- return self._GetResultFromJSONRequest(cmd_dict)
+ return self._GetResultFromJSONRequest(cmd_dict)['passwords']
def SetTheme(self, crx_file_path):
"""Installs the given theme synchronously.