blob: 67355e2a9668629a1af517a96612ca85160b350c [file] [log] [blame]
// Copyright 2013 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/password_syncable_service.h"
#include "base/location.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/password_manager/password_store.h"
#include "components/autofill/core/common/password_form.h"
#include "net/base/escape.h"
#include "sync/api/sync_error_factory.h"
namespace {
// Converts the |PasswordSpecifics| obtained from sync to an
// object of type |PasswordForm|.
void ExtractPasswordFromSpecifics(
const sync_pb::PasswordSpecificsData& password,
autofill::PasswordForm* new_password) {
new_password->scheme =
static_cast<autofill::PasswordForm::Scheme>(password.scheme());
new_password->signon_realm = password.signon_realm();
new_password->origin = GURL(password.origin());
new_password->action = GURL(password.action());
new_password->username_element =
UTF8ToUTF16(password.username_element());
new_password->password_element =
UTF8ToUTF16(password.password_element());
new_password->username_value =
UTF8ToUTF16(password.username_value());
new_password->password_value =
UTF8ToUTF16(password.password_value());
new_password->ssl_valid = password.ssl_valid();
new_password->preferred = password.preferred();
new_password->date_created =
base::Time::FromInternalValue(password.date_created());
new_password->blacklisted_by_user =
password.blacklisted();
}
// Merges the sync password (obtained from the password specifics) and
// local password and stores the output in the |new_password_form| pointer.
bool MergeLocalAndSyncPasswords(
const sync_pb::PasswordSpecificsData& password_specifics,
const autofill::PasswordForm& password_form,
autofill::PasswordForm* new_password_form) {
if (password_specifics.scheme() == password_form.scheme &&
password_form.signon_realm == password_specifics.signon_realm() &&
password_form.origin.spec() == password_specifics.origin() &&
password_form.action.spec() == password_specifics.action() &&
UTF16ToUTF8(password_form.username_element) ==
password_specifics.username_element() &&
UTF16ToUTF8(password_form.password_element) ==
password_specifics.password_element() &&
UTF16ToUTF8(password_form.username_value) ==
password_specifics.username_value() &&
UTF16ToUTF8(password_form.password_value) ==
password_specifics.password_value() &&
password_specifics.ssl_valid() == password_form.ssl_valid &&
password_specifics.preferred() == password_form.preferred &&
password_specifics.date_created() ==
password_form.date_created.ToInternalValue() &&
password_specifics.blacklisted() ==
password_form.blacklisted_by_user) {
return false;
}
// If the passwords differ, take the one that was created more recently.
if (base::Time::FromInternalValue(password_specifics.date_created()) <=
password_form.date_created) {
*new_password_form = password_form;
} else {
ExtractPasswordFromSpecifics(password_specifics, new_password_form);
}
return true;
}
} // namespace
PasswordSyncableService::PasswordSyncableService(
scoped_refptr<PasswordStore> password_store)
: password_store_(password_store) {
}
PasswordSyncableService::~PasswordSyncableService() {}
syncer::SyncMergeResult
PasswordSyncableService::MergeDataAndStartSyncing(
syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data,
scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
syncer::SyncMergeResult merge_result(type);
sync_error_factory_ = sync_error_factory.Pass();
sync_processor_ = sync_processor.Pass();
merge_result.set_error(sync_error_factory->CreateAndUploadError(
FROM_HERE,
"Password Syncable Service Not Implemented."));
return merge_result;
}
void PasswordSyncableService::StopSyncing(syncer::ModelType type) {
}
syncer::SyncDataList PasswordSyncableService::GetAllSyncData(
syncer::ModelType type) const {
syncer::SyncDataList sync_data;
return sync_data;
}
syncer::SyncError PasswordSyncableService::ProcessSyncChanges(
const tracked_objects::Location& from_here,
const syncer::SyncChangeList& change_list) {
syncer::SyncError error(FROM_HERE,
syncer::SyncError::UNRECOVERABLE_ERROR,
"Password Syncable Service Not Implemented.",
syncer::PASSWORDS);
return error;
}
void PasswordSyncableService::WriteToPasswordStore(
PasswordForms* new_entries,
PasswordForms* updated_entries) {
for (std::vector<autofill::PasswordForm*>::const_iterator it =
new_entries->begin();
it != new_entries->end();
++it) {
password_store_->AddLoginImpl(**it);
}
for (std::vector<autofill::PasswordForm*>::const_iterator it =
updated_entries->begin();
it != updated_entries->end();
++it) {
password_store_->UpdateLoginImpl(**it);
}
if (!new_entries->empty() || !updated_entries->empty()) {
// We have to notify password store observers of the change by hand since
// we use internal password store interfaces to make changes synchronously.
password_store_->PostNotifyLoginsChanged();
}
}
syncer::SyncData PasswordSyncableService::CreateSyncData(
const autofill::PasswordForm& password_form) {
sync_pb::EntitySpecifics password_data;
sync_pb::PasswordSpecificsData* password_specifics =
password_data.mutable_password()->mutable_client_only_encrypted_data();
password_specifics->set_scheme(password_form.scheme);
password_specifics->set_signon_realm(password_form.signon_realm);
password_specifics->set_origin(password_form.origin.spec());
password_specifics->set_action(password_form.action.spec());
password_specifics->set_username_element(
UTF16ToUTF8(password_form.username_element));
password_specifics->set_password_element(
UTF16ToUTF8(password_form.password_element));
password_specifics->set_username_value(
UTF16ToUTF8(password_form.username_value));
password_specifics->set_password_value(
UTF16ToUTF8(password_form.password_value));
password_specifics->set_ssl_valid(password_form.ssl_valid);
password_specifics->set_preferred(password_form.preferred);
password_specifics->set_date_created(
password_form.date_created.ToInternalValue());
password_specifics->set_blacklisted(password_form.blacklisted_by_user);
std::string tag = MakeTag(*password_specifics);
return syncer::SyncData::CreateLocalData(tag, tag, password_data);
}
// static
std::string PasswordSyncableService::MakeTag(
const std::string& origin_url,
const std::string& username_element,
const std::string& username_value,
const std::string& password_element,
const std::string& signon_realm) {
return net::EscapePath(origin_url) + "|" +
net::EscapePath(username_element) + "|" +
net::EscapePath(username_value) + "|" +
net::EscapePath(password_element) + "|" +
net::EscapePath(signon_realm);
}
// static
std::string PasswordSyncableService::MakeTag(
const autofill::PasswordForm& password) {
return MakeTag(password.origin.spec(),
UTF16ToUTF8(password.username_element),
UTF16ToUTF8(password.username_value),
UTF16ToUTF8(password.password_element),
password.signon_realm);
}
// static
std::string PasswordSyncableService::MakeTag(
const sync_pb::PasswordSpecificsData& password) {
return MakeTag(password.origin(),
password.username_element(),
password.username_value(),
password.password_element(),
password.signon_realm());
}