15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/password_manager/core/browser/password_syncable_service.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/auto_reset.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/location.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_vector.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/autofill/core/common/password_form.h"
13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "components/password_manager/core/browser/password_store_sync.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/escape.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sync/api/sync_error_factory.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace password_manager {
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Converts the |password| into a SyncData object.
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccisyncer::SyncData SyncDataFromPassword(const autofill::PasswordForm& password);
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Extracts the |PasswordForm| data from sync's protobuf format.
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciautofill::PasswordForm PasswordFromSpecifics(
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const sync_pb::PasswordSpecificsData& password);
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Returns the unique tag that will serve as the sync identifier for the
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// |password| entry.
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string MakePasswordSyncTag(const sync_pb::PasswordSpecificsData& password);
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string MakePasswordSyncTag(const autofill::PasswordForm& password);
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace {
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Returns true iff |password_specifics| and |password_specifics| are equal
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// memberwise.
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool AreLocalAndSyncPasswordsEqual(
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const sync_pb::PasswordSpecificsData& password_specifics,
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const autofill::PasswordForm& password_form) {
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return (password_form.scheme == password_specifics.scheme() &&
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          password_form.signon_realm == password_specifics.signon_realm() &&
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          password_form.origin.spec() == password_specifics.origin() &&
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          password_form.action.spec() == password_specifics.action() &&
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          base::UTF16ToUTF8(password_form.username_element) ==
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              password_specifics.username_element() &&
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          base::UTF16ToUTF8(password_form.password_element) ==
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              password_specifics.password_element() &&
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          base::UTF16ToUTF8(password_form.username_value) ==
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              password_specifics.username_value() &&
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          base::UTF16ToUTF8(password_form.password_value) ==
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              password_specifics.password_value() &&
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          password_form.ssl_valid == password_specifics.ssl_valid() &&
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          password_form.preferred == password_specifics.preferred() &&
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          password_form.date_created.ToInternalValue() ==
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              password_specifics.date_created() &&
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          password_form.blacklisted_by_user ==
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              password_specifics.blacklisted() &&
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          password_form.type == password_specifics.type() &&
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          password_form.times_used == password_specifics.times_used() &&
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          base::UTF16ToUTF8(password_form.display_name) ==
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              password_specifics.display_name() &&
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          password_form.avatar_url.spec() == password_specifics.avatar_url() &&
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          password_form.federation_url.spec() ==
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              password_specifics.federation_url());
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)syncer::SyncChange::SyncChangeType GetSyncChangeType(
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PasswordStoreChange::Type type) {
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (type) {
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case PasswordStoreChange::ADD: return syncer::SyncChange::ACTION_ADD;
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case PasswordStoreChange::UPDATE: return syncer::SyncChange::ACTION_UPDATE;
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case PasswordStoreChange::REMOVE: return syncer::SyncChange::ACTION_DELETE;
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NOTREACHED();
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return syncer::SyncChange::ACTION_INVALID;
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Creates a PasswordForm from |specifics| and |sync_time|, appends it to
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// |entries|.
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AppendPasswordFromSpecifics(
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const sync_pb::PasswordSpecificsData& specifics,
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::Time sync_time,
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ScopedVector<autofill::PasswordForm>* entries) {
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  entries->push_back(
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new autofill::PasswordForm(PasswordFromSpecifics(specifics)));
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  entries->back()->date_synced = sync_time;
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistruct PasswordSyncableService::SyncEntries {
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedVector<autofill::PasswordForm>* EntriesForChangeType(
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      syncer::SyncChange::SyncChangeType type) {
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    switch (type) {
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      case syncer::SyncChange::ACTION_ADD: return &new_entries;
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      case syncer::SyncChange::ACTION_UPDATE: return &updated_entries;
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      case syncer::SyncChange::ACTION_DELETE: return &deleted_entries;
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      case syncer::SyncChange::ACTION_INVALID: return NULL;
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NOTREACHED();
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return NULL;
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // List that contains the entries that are known only to sync.
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedVector<autofill::PasswordForm> new_entries;
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // List that contains the entries that are known to both sync and the local
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // database but have updates in sync. They need to be updated in the local
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // database.
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedVector<autofill::PasswordForm> updated_entries;
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The list of entries to be deleted from the local database.
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedVector<autofill::PasswordForm> deleted_entries;
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)PasswordSyncableService::PasswordSyncableService(
115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    PasswordStoreSync* password_store)
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : password_store_(password_store),
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      is_processing_sync_changes_(false) {
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordSyncableService::~PasswordSyncableService() {}
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)syncer::SyncMergeResult PasswordSyncableService::MergeDataAndStartSyncing(
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    syncer::ModelType type,
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const syncer::SyncDataList& initial_sync_data,
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(syncer::PASSWORDS, type);
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::AutoReset<bool> processing_changes(&is_processing_sync_changes_, true);
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  syncer::SyncMergeResult merge_result(type);
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We add all the db entries as |new_local_entries| initially. During model
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // association entries that match a sync entry will be removed and this list
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // will only contain entries that are not in sync.
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedVector<autofill::PasswordForm> password_entries;
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PasswordEntryMap new_local_entries;
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ReadFromPasswordStore(&password_entries, &new_local_entries)) {
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    merge_result.set_error(sync_error_factory->CreateAndUploadError(
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        FROM_HERE,
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        "Failed to get passwords from store."));
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return merge_result;
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (password_entries.size() != new_local_entries.size()) {
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    merge_result.set_error(sync_error_factory->CreateAndUploadError(
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FROM_HERE,
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "There are passwords with identical sync tags in the database."));
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return merge_result;
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Save |sync_processor_| only if reading the PasswordStore succeeded. In case
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // of failure Sync shouldn't receive any updates from the PasswordStore.
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  sync_error_factory_ = sync_error_factory.Pass();
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  sync_processor_ = sync_processor.Pass();
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  merge_result.set_num_items_before_association(new_local_entries.size());
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SyncEntries sync_entries;
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Changes from password db that need to be propagated to sync.
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  syncer::SyncChangeList updated_db_entries;
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (syncer::SyncDataList::const_iterator sync_iter =
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           initial_sync_data.begin();
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       sync_iter != initial_sync_data.end(); ++sync_iter) {
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CreateOrUpdateEntry(*sync_iter,
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        &new_local_entries,
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        &sync_entries,
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        &updated_db_entries);
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WriteToPasswordStore(sync_entries);
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  merge_result.set_num_items_after_association(
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      merge_result.num_items_before_association() +
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      sync_entries.new_entries.size());
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  merge_result.set_num_items_added(sync_entries.new_entries.size());
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  merge_result.set_num_items_modified(sync_entries.updated_entries.size());
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PasswordEntryMap::iterator it = new_local_entries.begin();
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       it != new_local_entries.end(); ++it) {
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    updated_db_entries.push_back(
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        syncer::SyncChange(FROM_HERE,
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           syncer::SyncChange::ACTION_ADD,
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           SyncDataFromPassword(*it->second)));
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  merge_result.set_error(
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      sync_processor_->ProcessSyncChanges(FROM_HERE, updated_db_entries));
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return merge_result;
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordSyncableService::StopSyncing(syncer::ModelType type) {
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(CalledOnValidThread());
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(syncer::PASSWORDS, type);
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sync_processor_.reset();
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sync_error_factory_.reset();
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)syncer::SyncDataList PasswordSyncableService::GetAllSyncData(
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    syncer::ModelType type) const {
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(syncer::PASSWORDS, type);
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedVector<autofill::PasswordForm> password_entries;
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ReadFromPasswordStore(&password_entries, NULL);
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  syncer::SyncDataList sync_data;
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PasswordForms::iterator it = password_entries.begin();
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != password_entries.end(); ++it) {
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    sync_data.push_back(SyncDataFromPassword(**it));
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return sync_data;
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)syncer::SyncError PasswordSyncableService::ProcessSyncChanges(
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const tracked_objects::Location& from_here,
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const syncer::SyncChangeList& change_list) {
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(CalledOnValidThread());
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::AutoReset<bool> processing_changes(&is_processing_sync_changes_, true);
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SyncEntries sync_entries;
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::Time time_now = base::Time::Now();
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (syncer::SyncChangeList::const_iterator it = change_list.begin();
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       it != change_list.end(); ++it) {
226a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const sync_pb::EntitySpecifics& specifics = it->sync_data().GetSpecifics();
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ScopedVector<autofill::PasswordForm>* entries =
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        sync_entries.EntriesForChangeType(it->change_type());
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!entries) {
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return sync_error_factory_->CreateAndUploadError(
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          FROM_HERE,
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          "Failed to process sync changes for passwords datatype.");
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AppendPasswordFromSpecifics(
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        specifics.password().client_only_encrypted_data(), time_now, entries);
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WriteToPasswordStore(sync_entries);
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return syncer::SyncError();
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordSyncableService::ActOnPasswordStoreChanges(
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const PasswordStoreChangeList& local_changes) {
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(CalledOnValidThread());
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!sync_processor_) {
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!flare_.is_null()) {
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      flare_.Run(syncer::PASSWORDS);
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      flare_.Reset();
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // ActOnPasswordStoreChanges() can be called from ProcessSyncChanges(). Do
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // nothing in this case.
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (is_processing_sync_changes_)
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  syncer::SyncChangeList sync_changes;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PasswordStoreChangeList::const_iterator it = local_changes.begin();
2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       it != local_changes.end(); ++it) {
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    syncer::SyncData data = (it->type() == PasswordStoreChange::REMOVE ?
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        syncer::SyncData::CreateLocalDelete(MakePasswordSyncTag(it->form()),
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                            syncer::PASSWORDS) :
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        SyncDataFromPassword(it->form()));
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    sync_changes.push_back(
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        syncer::SyncChange(FROM_HERE, GetSyncChangeType(it->type()), data));
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sync_processor_->ProcessSyncChanges(FROM_HERE, sync_changes);
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PasswordSyncableService::InjectStartSyncFlare(
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const syncer::SyncableService::StartSyncFlare& flare) {
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(CalledOnValidThread());
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  flare_ = flare;
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PasswordSyncableService::ReadFromPasswordStore(
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ScopedVector<autofill::PasswordForm>* password_entries,
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PasswordEntryMap* passwords_entry_map) const {
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(password_entries);
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!password_store_->FillAutofillableLogins(&password_entries->get()) ||
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !password_store_->FillBlacklistLogins(&password_entries->get())) {
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Password store often fails to load passwords. Track failures with UMA.
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // (http://crbug.com/249000)
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("Sync.LocalDataFailedToLoad",
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              ModelTypeToHistogramInt(syncer::PASSWORDS),
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              syncer::MODEL_TYPE_COUNT);
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!passwords_entry_map)
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  PasswordEntryMap& entry_map = *passwords_entry_map;
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PasswordForms::iterator it = password_entries->begin();
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != password_entries->end(); ++it) {
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     autofill::PasswordForm* password_form = *it;
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     entry_map[MakePasswordSyncTag(*password_form)] = password_form;
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PasswordSyncableService::WriteToPasswordStore(const SyncEntries& entries) {
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PasswordStoreChangeList changes;
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WriteEntriesToDatabase(&PasswordStoreSync::AddLoginImpl,
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         entries.new_entries.get(),
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         &changes);
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WriteEntriesToDatabase(&PasswordStoreSync::UpdateLoginImpl,
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         entries.updated_entries.get(),
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         &changes);
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WriteEntriesToDatabase(&PasswordStoreSync::RemoveLoginImpl,
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         entries.deleted_entries.get(),
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         &changes);
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We have to notify password store observers of the change by hand since
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // we use internal password store interfaces to make changes synchronously.
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  password_store_->NotifyLoginsChanged(changes);
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordSyncableService::CreateOrUpdateEntry(
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const syncer::SyncData& data,
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    PasswordEntryMap* unmatched_data_from_password_db,
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SyncEntries* sync_entries,
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    syncer::SyncChangeList* updated_db_entries) {
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const sync_pb::EntitySpecifics& specifics = data.GetSpecifics();
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const sync_pb::PasswordSpecificsData& password_specifics(
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      specifics.password().client_only_encrypted_data());
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string tag = MakePasswordSyncTag(password_specifics);
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Check whether the data from sync is already in the password store.
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PasswordEntryMap::iterator existing_local_entry_iter =
3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      unmatched_data_from_password_db->find(tag);
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::Time time_now = base::Time::Now();
3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (existing_local_entry_iter == unmatched_data_from_password_db->end()) {
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // The sync data is not in the password store, so we need to create it in
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // the password store. Add the entry to the new_entries list.
3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AppendPasswordFromSpecifics(password_specifics, time_now,
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                &sync_entries->new_entries);
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // The entry is in password store. If the entries are not identical, then
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // the entries need to be merged.
3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // If the passwords differ, take the one that was created more recently.
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const autofill::PasswordForm& password_form =
3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        *existing_local_entry_iter->second;
3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!AreLocalAndSyncPasswordsEqual(password_specifics, password_form)) {
3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (base::Time::FromInternalValue(password_specifics.date_created()) <
3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              password_form.date_created) {
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        updated_db_entries->push_back(
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            syncer::SyncChange(FROM_HERE,
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               syncer::SyncChange::ACTION_UPDATE,
3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               SyncDataFromPassword(password_form)));
3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else {
3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        AppendPasswordFromSpecifics(password_specifics, time_now,
3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    &sync_entries->updated_entries);
3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Remove the entry from the entry map to indicate a match has been found.
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Entries that remain in the map at the end of associating all sync entries
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // will be treated as additions that need to be propagated to sync.
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    unmatched_data_from_password_db->erase(existing_local_entry_iter);
3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PasswordSyncableService::WriteEntriesToDatabase(
3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DatabaseOperation operation,
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const PasswordForms& entries,
3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    PasswordStoreChangeList* all_changes) {
3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (PasswordForms::const_iterator it = entries.begin();
3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       it != entries.end(); ++it) {
3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    PasswordStoreChangeList new_changes = (password_store_->*operation)(**it);
3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    all_changes->insert(all_changes->end(),
3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        new_changes.begin(),
3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        new_changes.end());
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)syncer::SyncData SyncDataFromPassword(
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const autofill::PasswordForm& password_form) {
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sync_pb::EntitySpecifics password_data;
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sync_pb::PasswordSpecificsData* password_specifics =
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      password_data.mutable_password()->mutable_client_only_encrypted_data();
3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define CopyField(field) password_specifics->set_ ## field(password_form.field)
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define CopyStringField(field) \
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    password_specifics->set_ ## field(base::UTF16ToUTF8(password_form.field))
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CopyField(scheme);
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CopyField(signon_realm);
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  password_specifics->set_origin(password_form.origin.spec());
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  password_specifics->set_action(password_form.action.spec());
3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CopyStringField(username_element);
3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CopyStringField(password_element);
3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CopyStringField(username_value);
3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CopyStringField(password_value);
3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CopyField(ssl_valid);
3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CopyField(preferred);
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  password_specifics->set_date_created(
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      password_form.date_created.ToInternalValue());
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  password_specifics->set_blacklisted(password_form.blacklisted_by_user);
3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CopyField(type);
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CopyField(times_used);
4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CopyStringField(display_name);
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  password_specifics->set_avatar_url(password_form.avatar_url.spec());
4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  password_specifics->set_federation_url(password_form.federation_url.spec());
4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#undef CopyStringField
4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#undef CopyField
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string tag = MakePasswordSyncTag(*password_specifics);
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return syncer::SyncData::CreateLocalData(tag, tag, password_data);
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciautofill::PasswordForm PasswordFromSpecifics(
4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const sync_pb::PasswordSpecificsData& password) {
4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  autofill::PasswordForm new_password;
4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.scheme =
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      static_cast<autofill::PasswordForm::Scheme>(password.scheme());
4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.signon_realm = password.signon_realm();
4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.origin = GURL(password.origin());
4171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.action = GURL(password.action());
4181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.username_element =
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF8ToUTF16(password.username_element());
4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.password_element =
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF8ToUTF16(password.password_element());
4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.username_value = base::UTF8ToUTF16(password.username_value());
4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.password_value = base::UTF8ToUTF16(password.password_value());
4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.ssl_valid = password.ssl_valid();
4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.preferred = password.preferred();
4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.date_created =
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Time::FromInternalValue(password.date_created());
4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.blacklisted_by_user = password.blacklisted();
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.type =
4300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      static_cast<autofill::PasswordForm::Type>(password.type());
4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.times_used = password.times_used();
4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.display_name = base::UTF8ToUTF16(password.display_name());
4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.avatar_url = GURL(password.avatar_url());
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_password.federation_url = GURL(password.federation_url());
4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return new_password;
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string MakePasswordSyncTag(
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const sync_pb::PasswordSpecificsData& password) {
4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return MakePasswordSyncTag(PasswordFromSpecifics(password));
4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string MakePasswordSyncTag(const autofill::PasswordForm& password) {
4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return (net::EscapePath(password.origin.spec()) + "|" +
4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          net::EscapePath(base::UTF16ToUTF8(password.username_element)) + "|" +
4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          net::EscapePath(base::UTF16ToUTF8(password.username_value)) + "|" +
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          net::EscapePath(base::UTF16ToUTF8(password.password_element)) + "|" +
4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          net::EscapePath(password.signon_realm));
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
450c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
451c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace password_manager
452