15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/native_backend_gnome_x.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dlfcn.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gnome-keyring.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/basictypes.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/autofill/core/common/password_form.h"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/password_manager/core/browser/psl_matching_helper.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using autofill::PasswordForm;
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::UTF8ToUTF16;
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::UTF16ToUTF8;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GNOME_KEYRING_DEFINE_POINTER(name) \
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typeof(&::gnome_keyring_##name) GnomeKeyringLoader::gnome_keyring_##name;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_DEFINE_POINTER)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef GNOME_KEYRING_DEFINE_POINTER
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GnomeKeyringLoader::keyring_loaded = false;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(DLOPEN_GNOME_KEYRING)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GNOME_KEYRING_FUNCTION_INFO(name) \
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {"gnome_keyring_"#name, reinterpret_cast<void**>(&gnome_keyring_##name)},
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const GnomeKeyringLoader::FunctionInfo GnomeKeyringLoader::functions[] = {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_FUNCTION_INFO)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {NULL, NULL}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef GNOME_KEYRING_FUNCTION_INFO
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Load the library and initialize the function pointers. */
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GnomeKeyringLoader::LoadGnomeKeyring() {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (keyring_loaded)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* handle = dlopen("libgnome-keyring.so.0", RTLD_NOW | RTLD_GLOBAL);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!handle) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We wanted to use GNOME Keyring, but we couldn't load it. Warn, because
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // either the user asked for this, or we autodetected it incorrectly. (Or
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the system has broken libraries, which is also good to warn about.)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Could not load libgnome-keyring.so.0: " << dlerror();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; functions[i].name; ++i) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dlerror();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *functions[i].pointer = dlsym(handle, functions[i].name);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* error = dlerror();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Unable to load symbol "
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << functions[i].name << ": " << error;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dlclose(handle);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  keyring_loaded = true;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We leak the library handle. That's OK: this function is called only once.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else  // defined(DLOPEN_GNOME_KEYRING)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GnomeKeyringLoader::LoadGnomeKeyring() {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (keyring_loaded)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GNOME_KEYRING_ASSIGN_POINTER(name) \
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gnome_keyring_##name = &::gnome_keyring_##name;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_ASSIGN_POINTER)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef GNOME_KEYRING_ASSIGN_POINTER
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  keyring_loaded = true;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(DLOPEN_GNOME_KEYRING)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kGnomeKeyringAppString[] = "chrome";
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert the attributes of a given keyring entry into a new PasswordForm.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: does *not* get the actual password, as that is not a key attribute!
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns NULL if the attributes are for the wrong application.
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<PasswordForm> FormFromAttributes(GnomeKeyringAttributeList* attrs) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read the string and int attributes into the appropriate map.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<std::string, std::string> string_attr_map;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<std::string, uint32_t> uint_attr_map;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (guint i = 0; i < attrs->len; ++i) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GnomeKeyringAttribute attr = gnome_keyring_attribute_list_index(attrs, i);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (attr.type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_attr_map[attr.name] = attr.value.string;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (attr.type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint_attr_map[attr.name] = attr.value.integer;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to make sure this is a password we care about.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& app_value = string_attr_map["application"];
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!base::StringPiece(app_value).starts_with(kGnomeKeyringAppString))
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return scoped_ptr<PasswordForm>();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<PasswordForm> form(new PasswordForm());
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->origin = GURL(string_attr_map["origin_url"]);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->action = GURL(string_attr_map["action_url"]);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->username_element = UTF8ToUTF16(string_attr_map["username_element"]);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->username_value = UTF8ToUTF16(string_attr_map["username_value"]);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->password_element = UTF8ToUTF16(string_attr_map["password_element"]);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->submit_element = UTF8ToUTF16(string_attr_map["submit_element"]);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->signon_realm = string_attr_map["signon_realm"];
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->ssl_valid = uint_attr_map["ssl_valid"];
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->preferred = uint_attr_map["preferred"];
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 date_created = 0;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool date_ok = base::StringToInt64(string_attr_map["date_created"],
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &date_created);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(date_ok);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->date_created = base::Time::FromTimeT(date_created);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->blacklisted_by_user = uint_attr_map["blacklisted_by_user"];
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  form->type = static_cast<PasswordForm::Type>(uint_attr_map["type"]);
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  form->times_used = uint_attr_map["times_used"];
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->scheme = static_cast<PasswordForm::Scheme>(uint_attr_map["scheme"]);
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int64 date_synced = 0;
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::StringToInt64(string_attr_map["date_synced"], &date_synced);
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  form->date_synced = base::Time::FromInternalValue(date_synced);
14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  form->display_name = UTF8ToUTF16(string_attr_map["display_name"]);
14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  form->avatar_url = GURL(string_attr_map["avatar_url"]);
14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  form->federation_url = GURL(string_attr_map["federation_url"]);
14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  form->is_zero_click = uint_attr_map["is_zero_click"];
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return form.Pass();
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parse all the results from the given GList into a PasswordFormList, and free
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the GList. PasswordForms are allocated on the heap, and should be deleted by
1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// the consumer. If not NULL, |lookup_form| is used to filter out results --
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// only credentials with signon realms passing the PSL matching against
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// |lookup_form->signon_realm| will be kept. PSL matched results get their
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// signon_realm, origin, and action rewritten to those of |lookup_form_|, with
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// the original signon_realm saved into the result's original_signon_realm data
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// member.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConvertFormList(GList* found,
1595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     const PasswordForm* lookup_form,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     NativeBackendGnome::PasswordFormList* forms) {
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  password_manager::PSLDomainMatchMetric psl_domain_match_metric =
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      password_manager::PSL_DOMAIN_MATCH_NONE;
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (GList* element = g_list_first(found); element != NULL;
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       element = g_list_next(element)) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GnomeKeyringAttributeList* attrs = data->attributes;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<PasswordForm> form(FormFromAttributes(attrs));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (form) {
1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (lookup_form && form->signon_realm != lookup_form->signon_realm) {
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // This is not an exact match, we try PSL matching.
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (lookup_form->scheme != PasswordForm::SCHEME_HTML ||
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            form->scheme != PasswordForm::SCHEME_HTML ||
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            !(password_manager::IsPublicSuffixDomainMatch(
1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                lookup_form->signon_realm, form->signon_realm))) {
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          continue;
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        psl_domain_match_metric = password_manager::PSL_DOMAIN_MATCH_FOUND;
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        form->original_signon_realm = form->signon_realm;
1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        form->signon_realm = lookup_form->signon_realm;
1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        form->origin = lookup_form->origin;
1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        form->action = lookup_form->action;
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (data->secret) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        form->password_value = UTF8ToUTF16(data->secret);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Unable to access password from list element!";
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      forms->push_back(form.release());
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Could not initialize PasswordForm from attributes!";
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (lookup_form) {
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const GURL signon_realm(lookup_form->signon_realm);
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::string registered_domain =
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        password_manager::GetRegistryControlledDomain(signon_realm);
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION(
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        "PasswordManager.PslDomainMatchTriggering",
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        password_manager::ShouldPSLDomainMatchingApply(registered_domain)
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            ? psl_domain_match_metric
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            : password_manager::PSL_DOMAIN_MATCH_NOT_USED,
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        password_manager::PSL_DOMAIN_MATCH_COUNT);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Schema is analagous to the fields in PasswordForm.
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// TODO(gcasto): Adding 'form_data' would be nice, but we would need to
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// serialize in a way that is guaranteed to not have any embedded NULLs. Pickle
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// doesn't make this guarantee, so we just don't serialize this field. Since
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// it's only used to crowd source data collection it doesn't matter that much
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// if it's not available on this platform.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const GnomeKeyringPasswordSchema kGnomeSchema = {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GNOME_KEYRING_ITEM_GENERIC_SECRET, {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "action_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "submit_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "ssl_valid", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "preferred", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "date_created", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "scheme", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    { "type", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    { "times_used", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    { "date_synced", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    { "display_name", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
23103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    { "avatar_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
23203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    { "federation_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
23303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    { "is_zero_click", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This field is always "chrome" so that we can search for it.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { NULL }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sadly, PasswordStore goes to great lengths to switch from the originally
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// calling thread to the DB thread, and to provide an asynchronous API to
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callers while using a synchronous (virtual) API provided by subclasses like
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PasswordStoreX -- but GNOME Keyring really wants to be on the GLib main
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thread, which is the UI thread to us. So we end up having to switch threads
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// again, possibly back to the very same thread (in case the UI thread is the
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// caller, e.g. in the password management UI), and *block* the DB thread
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// waiting for a response from the UI thread to provide the synchronous API
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PasswordStore expects of us. (It will then in turn switch back to the
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// original caller to send the asynchronous reply to the original request.)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class represents a call to a GNOME Keyring method. A RunnableMethod
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// should be posted to the UI thread to call one of its action methods, and then
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a WaitResult() method should be called to wait for the result. Each instance
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// supports only one outstanding method at a time, though multiple instances may
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be used in parallel.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GKRMethod : public GnomeKeyringLoader {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef NativeBackendGnome::PasswordFormList PasswordFormList;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GKRMethod() : event_(false, false), result_(GNOME_KEYRING_RESULT_CANCELLED) {}
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Action methods. These call gnome_keyring_* functions. Call from UI thread.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See GetProfileSpecificAppString() for more information on the app string.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddLogin(const PasswordForm& form, const char* app_string);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddLoginSearch(const PasswordForm& form, const char* app_string);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdateLoginSearch(const PasswordForm& form, const char* app_string);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RemoveLogin(const PasswordForm& form, const char* app_string);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetLogins(const PasswordForm& form, const char* app_string);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetLoginsList(uint32_t blacklisted_by_user, const char* app_string);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetAllLogins(const char* app_string);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use after AddLogin, RemoveLogin.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GnomeKeyringResult WaitResult();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use after AddLoginSearch, UpdateLoginSearch, GetLogins, GetLoginsList,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetAllLogins.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GnomeKeyringResult WaitResult(PasswordFormList* forms);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct GnomeKeyringAttributeListFreeDeleter {
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    inline void operator()(void* list) const {
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gnome_keyring_attribute_list_free(
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          static_cast<GnomeKeyringAttributeList*>(list));
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  typedef scoped_ptr<GnomeKeyringAttributeList,
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     GnomeKeyringAttributeListFreeDeleter> ScopedAttributeList;
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Helper methods to abbreviate Gnome Keyring long API names.
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static void AppendString(ScopedAttributeList* list,
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           const char* name,
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           const char* value);
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static void AppendString(ScopedAttributeList* list,
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           const char* name,
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           const std::string& value);
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static void AppendUint32(ScopedAttributeList* list,
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           const char* name,
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           guint32 value);
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All these callbacks are called on UI thread.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void OnOperationDone(GnomeKeyringResult result, gpointer data);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void OnOperationGetList(GnomeKeyringResult result, GList* list,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 gpointer data);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent event_;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GnomeKeyringResult result_;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NativeBackendGnome::PasswordFormList forms_;
3105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // If the credential search is specified by a single form and needs to use PSL
3115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // matching, then the specifying form is stored in |lookup_form_|. If PSL
3125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // matching is used to find a result, then the results signon realm, origin
3135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // and action are stored are replaced by those of |lookup_form_|.
3145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Additionally, |lookup_form_->signon_realm| is also used to narrow down the
3155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // found logins to those which indeed PSL-match the look-up. And finally,
3165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // |lookup_form_| set to NULL means that PSL matching is not required.
3175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<PasswordForm> lookup_form_;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GKRMethod::AddLogin(const PasswordForm& form, const char* app_string) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  time_t date_created = form.date_created.ToTimeT();
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we are asked to save a password with 0 date, use the current time.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't want to actually save passwords as though on January 1, 1970.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!date_created)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    date_created = time(NULL);
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int64 date_synced = form.date_synced.ToInternalValue();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gnome_keyring_store_password(
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &kGnomeSchema,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL,  // Default keyring.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      form.origin.spec().c_str(),  // Display name.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UTF16ToUTF8(form.password_value).c_str(),
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnOperationDone,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,  // data
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL,  // destroy_data
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "origin_url", form.origin.spec().c_str(),
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "action_url", form.action.spec().c_str(),
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "username_element", UTF16ToUTF8(form.username_element).c_str(),
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "username_value", UTF16ToUTF8(form.username_value).c_str(),
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "password_element", UTF16ToUTF8(form.password_element).c_str(),
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "submit_element", UTF16ToUTF8(form.submit_element).c_str(),
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "signon_realm", form.signon_realm.c_str(),
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "ssl_valid", form.ssl_valid,
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "preferred", form.preferred,
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "date_created", base::Int64ToString(date_created).c_str(),
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "blacklisted_by_user", form.blacklisted_by_user,
347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      "type", form.type,
348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      "times_used", form.times_used,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "scheme", form.scheme,
350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "date_synced", base::Int64ToString(date_synced).c_str(),
35103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "display_name", UTF16ToUTF8(form.display_name).c_str(),
35203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "avatar_url", form.avatar_url.spec().c_str(),
35303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "federation_url", form.federation_url.spec().c_str(),
35403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "is_zero_click", form.is_zero_click,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "application", app_string,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GKRMethod::AddLoginSearch(const PasswordForm& form,
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const char* app_string) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  lookup_form_.reset(NULL);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Search GNOME Keyring for matching passwords to update.
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedAttributeList attrs(gnome_keyring_attribute_list_new());
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "origin_url", form.origin.spec());
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "username_element", UTF16ToUTF8(form.username_element));
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "username_value", UTF16ToUTF8(form.username_value));
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "password_element", UTF16ToUTF8(form.password_element));
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "submit_element", UTF16ToUTF8(form.submit_element));
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "signon_realm", form.signon_realm);
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "application", app_string);
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gnome_keyring_find_items(GNOME_KEYRING_ITEM_GENERIC_SECRET,
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           attrs.get(),
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           OnOperationGetList,
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           /*data=*/this,
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           /*destroy_data=*/NULL);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GKRMethod::UpdateLoginSearch(const PasswordForm& form,
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const char* app_string) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  lookup_form_.reset(NULL);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Search GNOME Keyring for matching passwords to update.
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedAttributeList attrs(gnome_keyring_attribute_list_new());
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "origin_url", form.origin.spec());
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "username_element", UTF16ToUTF8(form.username_element));
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "username_value", UTF16ToUTF8(form.username_value));
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "password_element", UTF16ToUTF8(form.password_element));
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "signon_realm", form.signon_realm);
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "application", app_string);
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gnome_keyring_find_items(GNOME_KEYRING_ITEM_GENERIC_SECRET,
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           attrs.get(),
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           OnOperationGetList,
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           /*data=*/this,
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           /*destroy_data=*/NULL);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GKRMethod::RemoveLogin(const PasswordForm& form, const char* app_string) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We find forms using the same fields as LoginDatabase::RemoveLogin().
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gnome_keyring_delete_password(
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &kGnomeSchema,
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnOperationDone,
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,  // data
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL,  // destroy_data
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "origin_url", form.origin.spec().c_str(),
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "username_element", UTF16ToUTF8(form.username_element).c_str(),
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "username_value", UTF16ToUTF8(form.username_value).c_str(),
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "password_element", UTF16ToUTF8(form.password_element).c_str(),
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "submit_element", UTF16ToUTF8(form.submit_element).c_str(),
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "signon_realm", form.signon_realm.c_str(),
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "application", app_string,
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GKRMethod::GetLogins(const PasswordForm& form, const char* app_string) {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  lookup_form_.reset(new PasswordForm(form));
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Search GNOME Keyring for matching passwords.
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedAttributeList attrs(gnome_keyring_attribute_list_new());
4211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!password_manager::ShouldPSLDomainMatchingApply(
4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          password_manager::GetRegistryControlledDomain(
4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              GURL(form.signon_realm)))) {
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppendString(&attrs, "signon_realm", form.signon_realm);
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "application", app_string);
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gnome_keyring_find_items(GNOME_KEYRING_ITEM_GENERIC_SECRET,
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           attrs.get(),
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           OnOperationGetList,
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           /*data=*/this,
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           /*destroy_data=*/NULL);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GKRMethod::GetLoginsList(uint32_t blacklisted_by_user,
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const char* app_string) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  lookup_form_.reset(NULL);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Search GNOME Keyring for matching passwords.
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedAttributeList attrs(gnome_keyring_attribute_list_new());
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendUint32(&attrs, "blacklisted_by_user", blacklisted_by_user);
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "application", app_string);
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gnome_keyring_find_items(GNOME_KEYRING_ITEM_GENERIC_SECRET,
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           attrs.get(),
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           OnOperationGetList,
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           /*data=*/this,
4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           /*destroy_data=*/NULL);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GKRMethod::GetAllLogins(const char* app_string) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  lookup_form_.reset(NULL);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to search for something, otherwise we get no results - so
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we search for the fixed application string.
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedAttributeList attrs(gnome_keyring_attribute_list_new());
4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(&attrs, "application", app_string);
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gnome_keyring_find_items(GNOME_KEYRING_ITEM_GENERIC_SECRET,
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           attrs.get(),
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           OnOperationGetList,
4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           /*data=*/this,
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           /*destroy_data=*/NULL);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GnomeKeyringResult GKRMethod::WaitResult() {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_.Wait();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result_;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GnomeKeyringResult GKRMethod::WaitResult(PasswordFormList* forms) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_.Wait();
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (forms->empty()) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Normal case. Avoid extra allocation by swapping.
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    forms->swap(forms_);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Rare case. Append forms_ to *forms.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    forms->insert(forms->end(), forms_.begin(), forms_.end());
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    forms_.clear();
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result_;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GKRMethod::AppendString(GKRMethod::ScopedAttributeList* list,
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const char* name,
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const char* value) {
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gnome_keyring_attribute_list_append_string(list->get(), name, value);
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GKRMethod::AppendString(GKRMethod::ScopedAttributeList* list,
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const char* name,
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const std::string& value) {
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppendString(list, name, value.c_str());
4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GKRMethod::AppendUint32(GKRMethod::ScopedAttributeList* list,
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const char* name,
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             guint32 value) {
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gnome_keyring_attribute_list_append_uint32(list->get(), name, value);
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GKRMethod::OnOperationDone(GnomeKeyringResult result, gpointer data) {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GKRMethod* method = static_cast<GKRMethod*>(data);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  method->result_ = result;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  method->event_.Signal();
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GKRMethod::OnOperationGetList(GnomeKeyringResult result, GList* list,
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   gpointer data) {
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GKRMethod* method = static_cast<GKRMethod*>(data);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  method->result_ = result;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  method->forms_.clear();
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |list| will be freed after this callback returns, so convert it now.
5181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ConvertFormList(list, method->lookup_form_.get(), &method->forms_);
5195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  method->lookup_form_.reset(NULL);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  method->event_.Signal();
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochNativeBackendGnome::NativeBackendGnome(LocalProfileId id)
526effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    : profile_id_(id) {
527effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  app_string_ = GetProfileSpecificAppString();
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeBackendGnome::~NativeBackendGnome() {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeBackendGnome::Init() {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return LoadGnomeKeyring() && gnome_keyring_is_available();
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeBackendGnome::RawAddLogin(const PasswordForm& form) {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GKRMethod method;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::Bind(&GKRMethod::AddLogin,
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base::Unretained(&method),
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     form, app_string_.c_str()));
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GnomeKeyringResult result = method.WaitResult();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != GNOME_KEYRING_RESULT_OK) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Keyring save failed: "
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << gnome_keyring_result_to_message(result);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)password_manager::PasswordStoreChangeList NativeBackendGnome::AddLogin(
554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const PasswordForm& form) {
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Based on LoginDatabase::AddLogin(), we search for an existing match based
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on origin_url, username_element, username_value, password_element, submit
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // element, and signon_realm first, remove that, and then add the new entry.
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We'd add the new one first, and then delete the original, but then the
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // delete might actually delete the newly-added entry!
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GKRMethod method;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::Bind(&GKRMethod::AddLoginSearch,
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base::Unretained(&method),
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     form, app_string_.c_str()));
566cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedVector<autofill::PasswordForm> forms;
567cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GnomeKeyringResult result = method.WaitResult(&forms.get());
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != GNOME_KEYRING_RESULT_OK &&
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result != GNOME_KEYRING_RESULT_NO_MATCH) {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Keyring find failed: "
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << gnome_keyring_result_to_message(result);
572cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return password_manager::PasswordStoreChangeList();
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
574cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  password_manager::PasswordStoreChangeList changes;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (forms.size() > 0) {
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (forms.size() > 1) {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Adding login when there are " << forms.size()
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << " matching logins already! Will replace only the first.";
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
581cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (RemoveLogin(*forms[0])) {
582cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      changes.push_back(password_manager::PasswordStoreChange(
583cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          password_manager::PasswordStoreChange::REMOVE, *forms[0]));
584cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
585cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
586cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (RawAddLogin(form)) {
587cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    changes.push_back(password_manager::PasswordStoreChange(
588cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        password_manager::PasswordStoreChange::ADD, form));
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return changes;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool NativeBackendGnome::UpdateLogin(
594cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const PasswordForm& form,
595cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    password_manager::PasswordStoreChangeList* changes) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Based on LoginDatabase::UpdateLogin(), we search for forms to update by
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // origin_url, username_element, username_value, password_element, and
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // signon_realm. We then compare the result to the updated form. If they
599a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // differ in any of the mutable fields, then we remove the original, and
600a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // then add the new entry. We'd add the new one first, and then delete the
601a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // original, but then the delete might actually delete the newly-added entry!
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
603cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(changes);
604cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  changes->clear();
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GKRMethod method;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::Bind(&GKRMethod::UpdateLoginSearch,
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base::Unretained(&method),
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     form, app_string_.c_str()));
610cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedVector<autofill::PasswordForm> forms;
611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GnomeKeyringResult result = method.WaitResult(&forms.get());
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != GNOME_KEYRING_RESULT_OK) {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Keyring find failed: "
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << gnome_keyring_result_to_message(result);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool removed = false;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < forms.size(); ++i) {
620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (*forms[i] != form) {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RemoveLogin(*forms[i]);
622cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      removed = true;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!removed)
626cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return true;
627cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
628cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (RawAddLogin(form)) {
629cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    password_manager::PasswordStoreChange change(
630cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        password_manager::PasswordStoreChange::UPDATE, form);
631cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    changes->push_back(change);
632cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return true;
633cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
634cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return false;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeBackendGnome::RemoveLogin(const PasswordForm& form) {
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GKRMethod method;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::Bind(&GKRMethod::RemoveLogin,
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base::Unretained(&method),
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     form, app_string_.c_str()));
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GnomeKeyringResult result = method.WaitResult();
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != GNOME_KEYRING_RESULT_OK) {
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Warning, not error, because this can sometimes happen due to the user
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // racing with the daemon to delete the password a second time.
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Keyring delete failed: "
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << gnome_keyring_result_to_message(result);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)bool NativeBackendGnome::RemoveLoginsCreatedBetween(
6566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    base::Time delete_begin,
6576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    base::Time delete_end,
6586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    password_manager::PasswordStoreChangeList* changes) {
659f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return RemoveLoginsBetween(
6606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      delete_begin, delete_end, CREATION_TIMESTAMP, changes);
661f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
663f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool NativeBackendGnome::RemoveLoginsSyncedBetween(
664f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    base::Time delete_begin,
665f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    base::Time delete_end,
666f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    password_manager::PasswordStoreChangeList* changes) {
667f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeBackendGnome::GetLogins(const PasswordForm& form,
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   PasswordFormList* forms) {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GKRMethod method;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::Bind(&GKRMethod::GetLogins,
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base::Unretained(&method),
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     form, app_string_.c_str()));
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GnomeKeyringResult result = method.WaitResult(forms);
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == GNOME_KEYRING_RESULT_NO_MATCH)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != GNOME_KEYRING_RESULT_OK) {
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Keyring find failed: "
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << gnome_keyring_result_to_message(result);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeBackendGnome::GetAutofillableLogins(PasswordFormList* forms) {
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetLoginsList(forms, true);
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeBackendGnome::GetBlacklistLogins(PasswordFormList* forms) {
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetLoginsList(forms, false);
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeBackendGnome::GetLoginsList(PasswordFormList* forms,
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       bool autofillable) {
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t blacklisted_by_user = !autofillable;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GKRMethod method;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::Bind(&GKRMethod::GetLoginsList,
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base::Unretained(&method),
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     blacklisted_by_user, app_string_.c_str()));
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GnomeKeyringResult result = method.WaitResult(forms);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == GNOME_KEYRING_RESULT_NO_MATCH)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != GNOME_KEYRING_RESULT_OK) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Keyring find failed: "
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << gnome_keyring_result_to_message(result);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NativeBackendGnome::GetAllLogins(PasswordFormList* forms) {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GKRMethod method;
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::Bind(&GKRMethod::GetAllLogins,
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base::Unretained(&method),
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     app_string_.c_str()));
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GnomeKeyringResult result = method.WaitResult(forms);
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == GNOME_KEYRING_RESULT_NO_MATCH)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != GNOME_KEYRING_RESULT_OK) {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Keyring find failed: "
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << gnome_keyring_result_to_message(result);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
736f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool NativeBackendGnome::GetLoginsBetween(base::Time get_begin,
737f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                          base::Time get_end,
738f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                          TimestampToCompare date_to_compare,
739f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                          PasswordFormList* forms) {
740f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
741f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // We could walk the list and add items as we find them, but it is much
742f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // easier to build the list and then filter the results.
743f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  PasswordFormList all_forms;
744f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!GetAllLogins(&all_forms))
745f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
746f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
747f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::Time autofill::PasswordForm::*date_member =
748f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      date_to_compare == CREATION_TIMESTAMP
749f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          ? &autofill::PasswordForm::date_created
750f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          : &autofill::PasswordForm::date_synced;
751f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t i = 0; i < all_forms.size(); ++i) {
752f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (get_begin <= all_forms[i]->*date_member &&
753f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        (get_end.is_null() || all_forms[i]->*date_member < get_end)) {
754f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      forms->push_back(all_forms[i]);
755f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else {
756f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      delete all_forms[i];
757f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
758f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
759f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
760f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
761f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
762f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
763f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool NativeBackendGnome::RemoveLoginsBetween(
764f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    base::Time get_begin,
765f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    base::Time get_end,
766f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    TimestampToCompare date_to_compare,
767f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    password_manager::PasswordStoreChangeList* changes) {
768f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
7696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  DCHECK(changes);
7706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  changes->clear();
771f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // We could walk the list and delete items as we find them, but it is much
772f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // easier to build the list and use RemoveLogin() to delete them.
773f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedVector<autofill::PasswordForm> forms;
774f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!GetLoginsBetween(get_begin, get_end, date_to_compare, &forms.get()))
775f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
776f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
777f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool ok = true;
778f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t i = 0; i < forms.size(); ++i) {
779f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (RemoveLogin(*forms[i])) {
7806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      changes->push_back(password_manager::PasswordStoreChange(
7816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          password_manager::PasswordStoreChange::REMOVE, *forms[i]));
782f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else {
783f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ok = false;
784f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
785f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
786f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return ok;
787f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
788f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string NativeBackendGnome::GetProfileSpecificAppString() const {
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Originally, the application string was always just "chrome" and used only
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so that we had *something* to search for since GNOME Keyring won't search
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for nothing. Now we use it to distinguish passwords for different profiles.
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::StringPrintf("%s-%d", kGnomeKeyringAppString, profile_id_);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795