// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/password_manager/native_backend_kwallet_x.h"

#include <vector>

#include "base/bind.h"
#include "base/logging.h"
#include "base/pickle.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/browser/browser_thread.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
#include "grit/chromium_strings.h"
#include "ui/base/l10n/l10n_util.h"

using autofill::PasswordForm;
using content::BrowserThread;

namespace {

// We could localize this string, but then changing your locale would cause
// you to lose access to all your stored passwords. Maybe best not to do that.
// Name of the folder to store passwords in.
const char kKWalletFolder[] = "Chrome Form Data";

// DBus service, path, and interface names for klauncher and kwalletd.
const char kKWalletServiceName[] = "org.kde.kwalletd";
const char kKWalletPath[] = "/modules/kwalletd";
const char kKWalletInterface[] = "org.kde.KWallet";
const char kKLauncherServiceName[] = "org.kde.klauncher";
const char kKLauncherPath[] = "/KLauncher";
const char kKLauncherInterface[] = "org.kde.KLauncher";

// Compares two PasswordForms and returns true if they are the same.
// If |update_check| is false, we only check the fields that are checked by
// LoginDatabase::UpdateLogin() when updating logins; otherwise, we check the
// fields that are checked by LoginDatabase::RemoveLogin() for removing them.
bool CompareForms(const autofill::PasswordForm& a,
                  const autofill::PasswordForm& b,
                  bool update_check) {
  // An update check doesn't care about the submit element.
  if (!update_check && a.submit_element != b.submit_element)
    return false;
  return a.origin           == b.origin &&
         a.password_element == b.password_element &&
         a.signon_realm     == b.signon_realm &&
         a.username_element == b.username_element &&
         a.username_value   == b.username_value;
}

// Checks a serialized list of PasswordForms for sanity. Returns true if OK.
// Note that |realm| is only used for generating a useful warning message.
bool CheckSerializedValue(const uint8_t* byte_array,
                          size_t length,
                          const std::string& realm) {
  const Pickle::Header* header =
      reinterpret_cast<const Pickle::Header*>(byte_array);
  if (length < sizeof(*header) ||
      header->payload_size > length - sizeof(*header)) {
    LOG(WARNING) << "Invalid KWallet entry detected (realm: " << realm << ")";
    return false;
  }
  return true;
}

// Convenience function to read a GURL from a Pickle. Assumes the URL has
// been written as a UTF-8 string. Returns true on success.
bool ReadGURL(PickleIterator* iter, bool warn_only, GURL* url) {
  std::string url_string;
  if (!iter->ReadString(&url_string)) {
    if (!warn_only)
      LOG(ERROR) << "Failed to deserialize URL.";
    *url = GURL();
    return false;
  }
  *url = GURL(url_string);
  return true;
}

}  // namespace

NativeBackendKWallet::NativeBackendKWallet(LocalProfileId id,
                                           PrefService* prefs)
    : profile_id_(id),
      prefs_(prefs),
      kwallet_proxy_(NULL),
      app_name_(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME)) {
  // TODO(mdm): after a few more releases, remove the code which is now dead due
  // to the true || here, and simplify this code. We don't do it yet to make it
  // easier to revert if necessary.
  if (true || PasswordStoreX::PasswordsUseLocalProfileId(prefs)) {
    folder_name_ = GetProfileSpecificFolderName();
    // We already did the migration previously. Don't try again.
    migrate_tried_ = true;
  } else {
    folder_name_ = kKWalletFolder;
    migrate_tried_ = false;
  }
}

NativeBackendKWallet::~NativeBackendKWallet() {
  // This destructor is called on the thread that is destroying the Profile
  // containing the PasswordStore that owns this NativeBackend. Generally that
  // won't be the DB thread; it will be the UI thread. So we post a message to
  // shut it down on the DB thread, and it will be destructed afterward when the
  // scoped_refptr<dbus::Bus> goes out of scope. The NativeBackend will be
  // destroyed before that occurs, but that's OK.
  if (session_bus_.get()) {
    BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
                            base::Bind(&dbus::Bus::ShutdownAndBlock,
                                       session_bus_.get()));
  }
}

bool NativeBackendKWallet::Init() {
  // Without the |optional_bus| parameter, a real bus will be instantiated.
  return InitWithBus(scoped_refptr<dbus::Bus>());
}

bool NativeBackendKWallet::InitWithBus(scoped_refptr<dbus::Bus> optional_bus) {
  // We must synchronously do a few DBus calls to figure out if initialization
  // succeeds, but later, we'll want to do most work on the DB thread. So we
  // have to do the initialization on the DB thread here too, and wait for it.
  bool success = false;
  base::WaitableEvent event(false, false);
  // NativeBackendKWallet isn't reference counted, but we wait for InitWithBus
  // to finish, so we can safely use base::Unretained here.
  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
                          base::Bind(&NativeBackendKWallet::InitOnDBThread,
                                     base::Unretained(this),
                                     optional_bus, &event, &success));

  // This ScopedAllowWait should not be here. http://crbug.com/125331
  base::ThreadRestrictions::ScopedAllowWait allow_wait;
  event.Wait();
  return success;
}

void NativeBackendKWallet::InitOnDBThread(scoped_refptr<dbus::Bus> optional_bus,
                                          base::WaitableEvent* event,
                                          bool* success) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
  DCHECK(!session_bus_.get());
  if (optional_bus.get()) {
    // The optional_bus parameter is given when this method is called in tests.
    session_bus_ = optional_bus;
  } else {
    // Get a (real) connection to the session bus.
    dbus::Bus::Options options;
    options.bus_type = dbus::Bus::SESSION;
    options.connection_type = dbus::Bus::PRIVATE;
    session_bus_ = new dbus::Bus(options);
  }
  kwallet_proxy_ =
      session_bus_->GetObjectProxy(kKWalletServiceName,
                                   dbus::ObjectPath(kKWalletPath));
  // kwalletd may not be running. If we get a temporary failure initializing it,
  // try to start it and then try again. (Note the short-circuit evaluation.)
  const InitResult result = InitWallet();
  *success = (result == INIT_SUCCESS ||
              (result == TEMPORARY_FAIL &&
               StartKWalletd() && InitWallet() == INIT_SUCCESS));
  event->Signal();
}

bool NativeBackendKWallet::StartKWalletd() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
  // Sadly kwalletd doesn't use DBus activation, so we have to make a call to
  // klauncher to start it.
  dbus::ObjectProxy* klauncher =
      session_bus_->GetObjectProxy(kKLauncherServiceName,
                                   dbus::ObjectPath(kKLauncherPath));

  dbus::MethodCall method_call(kKLauncherInterface,
                               "start_service_by_desktop_name");
  dbus::MessageWriter builder(&method_call);
  std::vector<std::string> empty;
  builder.AppendString("kwalletd");     // serviceName
  builder.AppendArrayOfStrings(empty);  // urls
  builder.AppendArrayOfStrings(empty);  // envs
  builder.AppendString(std::string());  // startup_id
  builder.AppendBool(false);            // blind
  scoped_ptr<dbus::Response> response(
      klauncher->CallMethodAndBlock(
          &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
  if (!response.get()) {
    LOG(ERROR) << "Error contacting klauncher to start kwalletd";
    return false;
  }
  dbus::MessageReader reader(response.get());
  int32_t ret = -1;
  std::string dbus_name;
  std::string error;
  int32_t pid = -1;
  if (!reader.PopInt32(&ret) || !reader.PopString(&dbus_name) ||
      !reader.PopString(&error) || !reader.PopInt32(&pid)) {
    LOG(ERROR) << "Error reading response from klauncher to start kwalletd: "
               << response->ToString();
    return false;
  }
  if (!error.empty() || ret) {
    LOG(ERROR) << "Error launching kwalletd: error '" << error << "' "
               << " (code " << ret << ")";
    return false;
  }

  return true;
}

NativeBackendKWallet::InitResult NativeBackendKWallet::InitWallet() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
  {
    // Check that KWallet is enabled.
    dbus::MethodCall method_call(kKWalletInterface, "isEnabled");
    scoped_ptr<dbus::Response> response(
        kwallet_proxy_->CallMethodAndBlock(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response.get()) {
      LOG(ERROR) << "Error contacting kwalletd (isEnabled)";
      return TEMPORARY_FAIL;
    }
    dbus::MessageReader reader(response.get());
    bool enabled = false;
    if (!reader.PopBool(&enabled)) {
      LOG(ERROR) << "Error reading response from kwalletd (isEnabled): "
                 << response->ToString();
      return PERMANENT_FAIL;
    }
    // Not enabled? Don't use KWallet. But also don't warn here.
    if (!enabled) {
      VLOG(1) << "kwalletd reports that KWallet is not enabled.";
      return PERMANENT_FAIL;
    }
  }

  {
    // Get the wallet name.
    dbus::MethodCall method_call(kKWalletInterface, "networkWallet");
    scoped_ptr<dbus::Response> response(
        kwallet_proxy_->CallMethodAndBlock(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response.get()) {
      LOG(ERROR) << "Error contacting kwalletd (networkWallet)";
      return TEMPORARY_FAIL;
    }
    dbus::MessageReader reader(response.get());
    if (!reader.PopString(&wallet_name_)) {
      LOG(ERROR) << "Error reading response from kwalletd (networkWallet): "
                 << response->ToString();
      return PERMANENT_FAIL;
    }
  }

  return INIT_SUCCESS;
}

bool NativeBackendKWallet::AddLogin(const PasswordForm& form) {
  int wallet_handle = WalletHandle();
  if (wallet_handle == kInvalidKWalletHandle)
    return false;

  PasswordFormList forms;
  GetLoginsList(&forms, form.signon_realm, wallet_handle);

  // We search for a login to update, rather than unconditionally appending the
  // login, because in some cases (especially involving sync) we can be asked to
  // add a login that already exists. In these cases we want to just update.
  bool updated = false;
  for (size_t i = 0; i < forms.size(); ++i) {
    // Use the more restrictive removal comparison, so that we never have
    // duplicate logins that would all be removed together by RemoveLogin().
    if (CompareForms(form, *forms[i], false)) {
      *forms[i] = form;
      updated = true;
    }
  }
  if (!updated)
    forms.push_back(new PasswordForm(form));

  bool ok = SetLoginsList(forms, form.signon_realm, wallet_handle);

  STLDeleteElements(&forms);
  return ok;
}

bool NativeBackendKWallet::UpdateLogin(const PasswordForm& form) {
  int wallet_handle = WalletHandle();
  if (wallet_handle == kInvalidKWalletHandle)
    return false;

  PasswordFormList forms;
  GetLoginsList(&forms, form.signon_realm, wallet_handle);

  for (size_t i = 0; i < forms.size(); ++i) {
    if (CompareForms(form, *forms[i], true))
      *forms[i] = form;
  }

  bool ok = SetLoginsList(forms, form.signon_realm, wallet_handle);

  STLDeleteElements(&forms);
  return ok;
}

bool NativeBackendKWallet::RemoveLogin(const PasswordForm& form) {
  int wallet_handle = WalletHandle();
  if (wallet_handle == kInvalidKWalletHandle)
    return false;

  PasswordFormList all_forms;
  GetLoginsList(&all_forms, form.signon_realm, wallet_handle);

  PasswordFormList kept_forms;
  kept_forms.reserve(all_forms.size());
  for (size_t i = 0; i < all_forms.size(); ++i) {
    if (CompareForms(form, *all_forms[i], false))
      delete all_forms[i];
    else
      kept_forms.push_back(all_forms[i]);
  }

  // Update the entry in the wallet, possibly deleting it.
  bool ok = SetLoginsList(kept_forms, form.signon_realm, wallet_handle);

  STLDeleteElements(&kept_forms);
  return ok;
}

bool NativeBackendKWallet::RemoveLoginsCreatedBetween(
    const base::Time& delete_begin,
    const base::Time& delete_end) {
  int wallet_handle = WalletHandle();
  if (wallet_handle == kInvalidKWalletHandle)
    return false;

  // We could probably also use readEntryList here.
  std::vector<std::string> realm_list;
  {
    dbus::MethodCall method_call(kKWalletInterface, "entryList");
    dbus::MessageWriter builder(&method_call);
    builder.AppendInt32(wallet_handle);  // handle
    builder.AppendString(folder_name_);  // folder
    builder.AppendString(app_name_);     // appid
    scoped_ptr<dbus::Response> response(
        kwallet_proxy_->CallMethodAndBlock(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response.get()) {
      LOG(ERROR) << "Error contacting kwalletd (entryList)";
      return false;
    }
    dbus::MessageReader reader(response.get());
    dbus::MessageReader array(response.get());
    if (!reader.PopArray(&array)) {
      LOG(ERROR) << "Error reading response from kwalletd (entryList): "
                 << response->ToString();
      return false;
    }
    while (array.HasMoreData()) {
      std::string realm;
      if (!array.PopString(&realm)) {
        LOG(ERROR) << "Error reading response from kwalletd (entryList): "
                   << response->ToString();
        return false;
      }
      realm_list.push_back(realm);
    }
  }

  bool ok = true;
  for (size_t i = 0; i < realm_list.size(); ++i) {
    const std::string& signon_realm = realm_list[i];
    dbus::MethodCall method_call(kKWalletInterface, "readEntry");
    dbus::MessageWriter builder(&method_call);
    builder.AppendInt32(wallet_handle);  // handle
    builder.AppendString(folder_name_);  // folder
    builder.AppendString(signon_realm);  // key
    builder.AppendString(app_name_);     // appid
    scoped_ptr<dbus::Response> response(
        kwallet_proxy_->CallMethodAndBlock(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response.get()) {
      LOG(ERROR) << "Error contacting kwalletd (readEntry)";
      continue;
    }
    dbus::MessageReader reader(response.get());
    uint8_t* bytes = NULL;
    size_t length = 0;
    if (!reader.PopArrayOfBytes(&bytes, &length)) {
      LOG(ERROR) << "Error reading response from kwalletd (readEntry): "
                 << response->ToString();
      continue;
    }
    if (!bytes || !CheckSerializedValue(bytes, length, signon_realm))
      continue;

    // Can't we all just agree on whether bytes are signed or not? Please?
    Pickle pickle(reinterpret_cast<const char*>(bytes), length);
    PasswordFormList all_forms;
    DeserializeValue(signon_realm, pickle, &all_forms);

    PasswordFormList kept_forms;
    kept_forms.reserve(all_forms.size());
    for (size_t i = 0; i < all_forms.size(); ++i) {
      if (delete_begin <= all_forms[i]->date_created &&
          (delete_end.is_null() || all_forms[i]->date_created < delete_end)) {
        delete all_forms[i];
      } else {
        kept_forms.push_back(all_forms[i]);
      }
    }

    if (!SetLoginsList(kept_forms, signon_realm, wallet_handle))
      ok = false;
    STLDeleteElements(&kept_forms);
  }
  return ok;
}

bool NativeBackendKWallet::GetLogins(const PasswordForm& form,
                                     PasswordFormList* forms) {
  int wallet_handle = WalletHandle();
  if (wallet_handle == kInvalidKWalletHandle)
    return false;
  return GetLoginsList(forms, form.signon_realm, wallet_handle);
}

bool NativeBackendKWallet::GetLoginsCreatedBetween(const base::Time& get_begin,
                                                   const base::Time& get_end,
                                                   PasswordFormList* forms) {
  int wallet_handle = WalletHandle();
  if (wallet_handle == kInvalidKWalletHandle)
    return false;
  return GetLoginsList(forms, get_begin, get_end, wallet_handle);
}

bool NativeBackendKWallet::GetAutofillableLogins(PasswordFormList* forms) {
  int wallet_handle = WalletHandle();
  if (wallet_handle == kInvalidKWalletHandle)
    return false;
  return GetLoginsList(forms, true, wallet_handle);
}

bool NativeBackendKWallet::GetBlacklistLogins(PasswordFormList* forms) {
  int wallet_handle = WalletHandle();
  if (wallet_handle == kInvalidKWalletHandle)
    return false;
  return GetLoginsList(forms, false, wallet_handle);
}

bool NativeBackendKWallet::GetLoginsList(PasswordFormList* forms,
                                         const std::string& signon_realm,
                                         int wallet_handle) {
  // Is there an entry in the wallet?
  {
    dbus::MethodCall method_call(kKWalletInterface, "hasEntry");
    dbus::MessageWriter builder(&method_call);
    builder.AppendInt32(wallet_handle);  // handle
    builder.AppendString(folder_name_);  // folder
    builder.AppendString(signon_realm);  // key
    builder.AppendString(app_name_);     // appid
    scoped_ptr<dbus::Response> response(
        kwallet_proxy_->CallMethodAndBlock(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response.get()) {
      LOG(ERROR) << "Error contacting kwalletd (hasEntry)";
      return false;
    }
    dbus::MessageReader reader(response.get());
    bool has_entry = false;
    if (!reader.PopBool(&has_entry)) {
      LOG(ERROR) << "Error reading response from kwalletd (hasEntry): "
                 << response->ToString();
      return false;
    }
    if (!has_entry) {
      // This is not an error. There just isn't a matching entry.
      return true;
    }
  }

  {
    dbus::MethodCall method_call(kKWalletInterface, "readEntry");
    dbus::MessageWriter builder(&method_call);
    builder.AppendInt32(wallet_handle);  // handle
    builder.AppendString(folder_name_);  // folder
    builder.AppendString(signon_realm);  // key
    builder.AppendString(app_name_);     // appid
    scoped_ptr<dbus::Response> response(
        kwallet_proxy_->CallMethodAndBlock(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response.get()) {
      LOG(ERROR) << "Error contacting kwalletd (readEntry)";
      return false;
    }
    dbus::MessageReader reader(response.get());
    uint8_t* bytes = NULL;
    size_t length = 0;
    if (!reader.PopArrayOfBytes(&bytes, &length)) {
      LOG(ERROR) << "Error reading response from kwalletd (readEntry): "
                 << response->ToString();
      return false;
    }
    if (!bytes)
      return false;
    if (!CheckSerializedValue(bytes, length, signon_realm)) {
      // This is weird, but we choose not to call it an error. There is an
      // invalid entry somehow, but by just ignoring it, we make it easier to
      // repair without having to delete it using kwalletmanager (that is, by
      // just saving a new password within this realm to overwrite it).
      return true;
    }

    // Can't we all just agree on whether bytes are signed or not? Please?
    Pickle pickle(reinterpret_cast<const char*>(bytes), length);
    PasswordFormList all_forms;
    DeserializeValue(signon_realm, pickle, forms);
  }

  return true;
}

bool NativeBackendKWallet::GetLoginsList(PasswordFormList* forms,
                                         bool autofillable,
                                         int wallet_handle) {
  PasswordFormList all_forms;
  if (!GetAllLogins(&all_forms, wallet_handle))
    return false;

  // We have to read all the entries, and then filter them here.
  forms->reserve(forms->size() + all_forms.size());
  for (size_t i = 0; i < all_forms.size(); ++i) {
    if (all_forms[i]->blacklisted_by_user == !autofillable)
      forms->push_back(all_forms[i]);
    else
      delete all_forms[i];
  }

  return true;
}

bool NativeBackendKWallet::GetLoginsList(PasswordFormList* forms,
                                         const base::Time& begin,
                                         const base::Time& end,
                                         int wallet_handle) {
  PasswordFormList all_forms;
  if (!GetAllLogins(&all_forms, wallet_handle))
    return false;

  // We have to read all the entries, and then filter them here.
  forms->reserve(forms->size() + all_forms.size());
  for (size_t i = 0; i < all_forms.size(); ++i) {
    if (begin <= all_forms[i]->date_created &&
        (end.is_null() || all_forms[i]->date_created < end)) {
      forms->push_back(all_forms[i]);
    } else {
      delete all_forms[i];
    }
  }

  return true;
}

bool NativeBackendKWallet::GetAllLogins(PasswordFormList* forms,
                                        int wallet_handle) {
  // We could probably also use readEntryList here.
  std::vector<std::string> realm_list;
  {
    dbus::MethodCall method_call(kKWalletInterface, "entryList");
    dbus::MessageWriter builder(&method_call);
    builder.AppendInt32(wallet_handle);  // handle
    builder.AppendString(folder_name_);  // folder
    builder.AppendString(app_name_);     // appid
    scoped_ptr<dbus::Response> response(
        kwallet_proxy_->CallMethodAndBlock(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response.get()) {
      LOG(ERROR) << "Error contacting kwalletd (entryList)";
      return false;
    }
    dbus::MessageReader reader(response.get());
    if (!reader.PopArrayOfStrings(&realm_list)) {
      LOG(ERROR) << "Error reading response from kwalletd (entryList): "
                 << response->ToString();
      return false;
    }
  }

  for (size_t i = 0; i < realm_list.size(); ++i) {
    const std::string& signon_realm = realm_list[i];
    dbus::MethodCall method_call(kKWalletInterface, "readEntry");
    dbus::MessageWriter builder(&method_call);
    builder.AppendInt32(wallet_handle);  // handle
    builder.AppendString(folder_name_);  // folder
    builder.AppendString(signon_realm);  // key
    builder.AppendString(app_name_);     // appid
    scoped_ptr<dbus::Response> response(
        kwallet_proxy_->CallMethodAndBlock(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response.get()) {
      LOG(ERROR) << "Error contacting kwalletd (readEntry)";
      continue;
    }
    dbus::MessageReader reader(response.get());
    uint8_t* bytes = NULL;
    size_t length = 0;
    if (!reader.PopArrayOfBytes(&bytes, &length)) {
      LOG(ERROR) << "Error reading response from kwalletd (readEntry): "
                 << response->ToString();
      continue;
    }
    if (!bytes || !CheckSerializedValue(bytes, length, signon_realm))
      continue;

    // Can't we all just agree on whether bytes are signed or not? Please?
    Pickle pickle(reinterpret_cast<const char*>(bytes), length);
    PasswordFormList all_forms;
    DeserializeValue(signon_realm, pickle, forms);
  }
  return true;
}

bool NativeBackendKWallet::SetLoginsList(const PasswordFormList& forms,
                                         const std::string& signon_realm,
                                         int wallet_handle) {
  if (forms.empty()) {
    // No items left? Remove the entry from the wallet.
    dbus::MethodCall method_call(kKWalletInterface, "removeEntry");
    dbus::MessageWriter builder(&method_call);
    builder.AppendInt32(wallet_handle);  // handle
    builder.AppendString(folder_name_);  // folder
    builder.AppendString(signon_realm);  // key
    builder.AppendString(app_name_);     // appid
    scoped_ptr<dbus::Response> response(
        kwallet_proxy_->CallMethodAndBlock(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response.get()) {
      LOG(ERROR) << "Error contacting kwalletd (removeEntry)";
      return kInvalidKWalletHandle;
    }
    dbus::MessageReader reader(response.get());
    int ret = 0;
    if (!reader.PopInt32(&ret)) {
      LOG(ERROR) << "Error reading response from kwalletd (removeEntry): "
                 << response->ToString();
      return false;
    }
    if (ret != 0)
      LOG(ERROR) << "Bad return code " << ret << " from KWallet removeEntry";
    return ret == 0;
  }

  Pickle value;
  SerializeValue(forms, &value);

  dbus::MethodCall method_call(kKWalletInterface, "writeEntry");
  dbus::MessageWriter builder(&method_call);
  builder.AppendInt32(wallet_handle);  // handle
  builder.AppendString(folder_name_);  // folder
  builder.AppendString(signon_realm);  // key
  builder.AppendArrayOfBytes(static_cast<const uint8_t*>(value.data()),
                             value.size());  // value
  builder.AppendString(app_name_);     // appid
  scoped_ptr<dbus::Response> response(
      kwallet_proxy_->CallMethodAndBlock(
          &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
  if (!response.get()) {
    LOG(ERROR) << "Error contacting kwalletd (writeEntry)";
    return kInvalidKWalletHandle;
  }
  dbus::MessageReader reader(response.get());
  int ret = 0;
  if (!reader.PopInt32(&ret)) {
    LOG(ERROR) << "Error reading response from kwalletd (writeEntry): "
               << response->ToString();
    return false;
  }
  if (ret != 0)
    LOG(ERROR) << "Bad return code " << ret << " from KWallet writeEntry";
  return ret == 0;
}

// static
void NativeBackendKWallet::SerializeValue(const PasswordFormList& forms,
                                          Pickle* pickle) {
  pickle->WriteInt(kPickleVersion);
  pickle->WriteUInt64(forms.size());
  for (PasswordFormList::const_iterator it = forms.begin();
       it != forms.end(); ++it) {
    const PasswordForm* form = *it;
    pickle->WriteInt(form->scheme);
    pickle->WriteString(form->origin.spec());
    pickle->WriteString(form->action.spec());
    pickle->WriteString16(form->username_element);
    pickle->WriteString16(form->username_value);
    pickle->WriteString16(form->password_element);
    pickle->WriteString16(form->password_value);
    pickle->WriteString16(form->submit_element);
    pickle->WriteBool(form->ssl_valid);
    pickle->WriteBool(form->preferred);
    pickle->WriteBool(form->blacklisted_by_user);
    pickle->WriteInt64(form->date_created.ToTimeT());
  }
}

// static
bool NativeBackendKWallet::DeserializeValueSize(const std::string& signon_realm,
                                                const PickleIterator& init_iter,
                                                bool size_32, bool warn_only,
                                                PasswordFormList* forms) {
  PickleIterator iter = init_iter;

  uint64_t count = 0;
  if (size_32) {
    uint32_t count_32 = 0;
    if (!iter.ReadUInt32(&count_32)) {
      LOG(ERROR) << "Failed to deserialize KWallet entry "
                 << "(realm: " << signon_realm << ")";
      return false;
    }
    count = count_32;
  } else {
    if (!iter.ReadUInt64(&count)) {
      LOG(ERROR) << "Failed to deserialize KWallet entry "
                 << "(realm: " << signon_realm << ")";
      return false;
    }
  }

  if (count > 0xFFFF) {
    // Trying to pin down the cause of http://crbug.com/80728 (or fix it).
    // This is a very large number of passwords to be saved for a single realm.
    // It is almost certainly a corrupt pickle and not real data. Ignore it.
    // This very well might actually be http://crbug.com/107701, so if we're
    // reading an old pickle, we don't even log this the first time we try to
    // read it. (That is, when we're reading the native architecture size.)
    if (!warn_only) {
      LOG(ERROR) << "Suspiciously large number of entries in KWallet entry "
                 << "(" << count << "; realm: " << signon_realm << ")";
    }
    return false;
  }

  forms->reserve(forms->size() + count);
  for (uint64_t i = 0; i < count; ++i) {
    scoped_ptr<PasswordForm> form(new PasswordForm());
    form->signon_realm.assign(signon_realm);

    int scheme = 0;
    int64 date_created = 0;
    // Note that these will be read back in the order listed due to
    // short-circuit evaluation. This is important.
    if (!iter.ReadInt(&scheme) ||
        !ReadGURL(&iter, warn_only, &form->origin) ||
        !ReadGURL(&iter, warn_only, &form->action) ||
        !iter.ReadString16(&form->username_element) ||
        !iter.ReadString16(&form->username_value) ||
        !iter.ReadString16(&form->password_element) ||
        !iter.ReadString16(&form->password_value) ||
        !iter.ReadString16(&form->submit_element) ||
        !iter.ReadBool(&form->ssl_valid) ||
        !iter.ReadBool(&form->preferred) ||
        !iter.ReadBool(&form->blacklisted_by_user) ||
        !iter.ReadInt64(&date_created)) {
      if (warn_only) {
        LOG(WARNING) << "Failed to deserialize version 0 KWallet entry "
                     << "(realm: " << signon_realm << ") with native "
                     << "architecture size; will try alternate size.";
      } else {
        LOG(ERROR) << "Failed to deserialize KWallet entry "
                   << "(realm: " << signon_realm << ")";
      }
      return false;
    }
    form->scheme = static_cast<PasswordForm::Scheme>(scheme);
    form->date_created = base::Time::FromTimeT(date_created);
    forms->push_back(form.release());
  }

  return true;
}

// static
void NativeBackendKWallet::DeserializeValue(const std::string& signon_realm,
                                            const Pickle& pickle,
                                            PasswordFormList* forms) {
  PickleIterator iter(pickle);

  int version = -1;
  if (!iter.ReadInt(&version) ||
      version < 0 || version > kPickleVersion) {
    LOG(ERROR) << "Failed to deserialize KWallet entry "
               << "(realm: " << signon_realm << ")";
    return;
  }

  if (version == kPickleVersion) {
    // In current pickles, we expect 64-bit sizes. Failure is an error.
    DeserializeValueSize(signon_realm, iter, false, false, forms);
    return;
  }

  const size_t saved_forms_size = forms->size();
  const bool size_32 = sizeof(size_t) == sizeof(uint32_t);
  if (!DeserializeValueSize(signon_realm, iter, size_32, true, forms)) {
    // We failed to read the pickle using the native architecture of the system.
    // Try again with the opposite architecture. Note that we do this even on
    // 32-bit machines, in case we're reading a 64-bit pickle. (Probably rare,
    // since mostly we expect upgrades, not downgrades, but both are possible.)
    forms->resize(saved_forms_size);
    DeserializeValueSize(signon_realm, iter, !size_32, false, forms);
  }
}

int NativeBackendKWallet::WalletHandle() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));

  // Open the wallet.
  // TODO(mdm): Are we leaking these handles? Find out.
  int32_t handle = kInvalidKWalletHandle;
  {
    dbus::MethodCall method_call(kKWalletInterface, "open");
    dbus::MessageWriter builder(&method_call);
    builder.AppendString(wallet_name_);  // wallet
    builder.AppendInt64(0);              // wid
    builder.AppendString(app_name_);     // appid
    scoped_ptr<dbus::Response> response(
        kwallet_proxy_->CallMethodAndBlock(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response.get()) {
      LOG(ERROR) << "Error contacting kwalletd (open)";
      return kInvalidKWalletHandle;
    }
    dbus::MessageReader reader(response.get());
    if (!reader.PopInt32(&handle)) {
      LOG(ERROR) << "Error reading response from kwalletd (open): "
                 << response->ToString();
      return kInvalidKWalletHandle;
    }
    if (handle == kInvalidKWalletHandle) {
      LOG(ERROR) << "Error obtaining KWallet handle";
      return kInvalidKWalletHandle;
    }
  }

  // Check if our folder exists.
  bool has_folder = false;
  {
    dbus::MethodCall method_call(kKWalletInterface, "hasFolder");
    dbus::MessageWriter builder(&method_call);
    builder.AppendInt32(handle);         // handle
    builder.AppendString(folder_name_);  // folder
    builder.AppendString(app_name_);     // appid
    scoped_ptr<dbus::Response> response(
        kwallet_proxy_->CallMethodAndBlock(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response.get()) {
      LOG(ERROR) << "Error contacting kwalletd (hasFolder)";
      return kInvalidKWalletHandle;
    }
    dbus::MessageReader reader(response.get());
    if (!reader.PopBool(&has_folder)) {
      LOG(ERROR) << "Error reading response from kwalletd (hasFolder): "
                 << response->ToString();
      return kInvalidKWalletHandle;
    }
  }

  // Create it if it didn't.
  if (!has_folder) {
    dbus::MethodCall method_call(kKWalletInterface, "createFolder");
    dbus::MessageWriter builder(&method_call);
    builder.AppendInt32(handle);         // handle
    builder.AppendString(folder_name_);  // folder
    builder.AppendString(app_name_);     // appid
    scoped_ptr<dbus::Response> response(
        kwallet_proxy_->CallMethodAndBlock(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response.get()) {
      LOG(ERROR) << "Error contacting kwalletd (createFolder)";
      return kInvalidKWalletHandle;
    }
    dbus::MessageReader reader(response.get());
    bool success = false;
    if (!reader.PopBool(&success)) {
      LOG(ERROR) << "Error reading response from kwalletd (createFolder): "
                 << response->ToString();
      return kInvalidKWalletHandle;
    }
    if (!success) {
      LOG(ERROR) << "Error creating KWallet folder";
      return kInvalidKWalletHandle;
    }
  }

  // Successful initialization. Try migration if necessary.
  if (!migrate_tried_)
    MigrateToProfileSpecificLogins();

  return handle;
}

std::string NativeBackendKWallet::GetProfileSpecificFolderName() const {
  // Originally, the folder name was always just "Chrome Form Data".
  // Now we use it to distinguish passwords for different profiles.
  return base::StringPrintf("%s (%d)", kKWalletFolder, profile_id_);
}

void NativeBackendKWallet::MigrateToProfileSpecificLogins() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));

  DCHECK(!migrate_tried_);
  DCHECK_EQ(folder_name_, kKWalletFolder);

  // Record the fact that we've attempted migration already right away, so that
  // we don't get recursive calls back to MigrateToProfileSpecificLogins().
  migrate_tried_ = true;

  // First get all the logins, using the old folder name.
  int wallet_handle = WalletHandle();
  if (wallet_handle == kInvalidKWalletHandle)
    return;
  PasswordFormList forms;
  if (!GetAllLogins(&forms, wallet_handle))
    return;

  // Now switch to a profile-specific folder name.
  folder_name_ = GetProfileSpecificFolderName();

  // Try to add all the logins with the new folder name.
  // This could be done more efficiently by grouping by signon realm and using
  // SetLoginsList(), but we do this for simplicity since it is only done once.
  // Note, however, that we do need another call to WalletHandle() to create
  // this folder if necessary.
  bool ok = true;
  for (size_t i = 0; i < forms.size(); ++i) {
    if (!AddLogin(*forms[i]))
      ok = false;
    delete forms[i];
  }
  if (forms.empty()) {
    // If there were no logins to migrate, we do an extra call to WalletHandle()
    // for its side effect of attempting to create the profile-specific folder.
    // This is not strictly necessary, but it's safe and helps in testing.
    wallet_handle = WalletHandle();
    if (wallet_handle == kInvalidKWalletHandle)
      ok = false;
  }

  if (ok) {
    // All good! Keep the new app string and set a persistent pref.
    // NOTE: We explicitly don't delete the old passwords yet. They are
    // potentially shared with other profiles and other user data dirs!
    // Each other profile must be able to migrate the shared data as well,
    // so we must leave it alone. After a few releases, we'll add code to
    // delete them, and eventually remove this migration code.
    // TODO(mdm): follow through with the plan above.
    PasswordStoreX::SetPasswordsUseLocalProfileId(prefs_);
  } else {
    // We failed to migrate for some reason. Use the old folder name.
    folder_name_ = kKWalletFolder;
  }
}
