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/webdata/autocomplete_syncable_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/webdata/autofill_table.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "components/webdata/common/web_database.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/api/sync_error.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/api/sync_error_factory.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/protocol/autofill_specifics.pb.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/protocol/sync.pb.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using autofill::AutofillChange;
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using autofill::AutofillChangeList;
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using autofill::AutofillEntry;
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using autofill::AutofillKey;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using autofill::AutofillTable;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using autofill::AutofillWebDataService;
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using autofill::AutofillWebDataBackend;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAutofillEntryNamespaceTag[] = "autofill_entry|";
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Merges timestamps from the |sync_timestamps| and the |local_entry|.
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Returns true if they were different, false if they were the same.  If the
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// timestamps were different, fills |date_created| and |date_last_used| with the
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// merged timestamps.  The |sync_timestamps| vector is assumed to be sorted.
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool MergeTimestamps(
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const google::protobuf::RepeatedField<int64_t>& sync_timestamps,
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const AutofillEntry& local_entry,
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::Time* date_created,
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::Time* date_last_used) {
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (sync_timestamps.size() == 0) {
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    *date_created = local_entry.date_created();
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    *date_last_used = local_entry.date_last_used();
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::Time sync_date_created =
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Time::FromInternalValue(*sync_timestamps.begin());
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::Time sync_date_last_used =
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Time::FromInternalValue(*sync_timestamps.rbegin());
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (sync_date_created == local_entry.date_created() &&
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      sync_date_last_used == local_entry.date_last_used())
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  *date_created = std::min(local_entry.date_created(), sync_date_created);
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  *date_last_used = std::max(local_entry.date_last_used(), sync_date_last_used);
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void* UserDataKey() {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Use the address of a static that COMDAT folding won't ever fold
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // with something else.
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static int user_data_key = 0;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return reinterpret_cast<void*>(&user_data_key);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutocompleteSyncableService::AutocompleteSyncableService(
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    AutofillWebDataBackend* web_data_backend)
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : web_data_backend_(web_data_backend),
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scoped_observer_(this) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(web_data_backend_);
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_observer_.Add(web_data_backend_);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutocompleteSyncableService::~AutocompleteSyncableService() {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void AutocompleteSyncableService::CreateForWebDataServiceAndBackend(
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    AutofillWebDataService* web_data_service,
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    AutofillWebDataBackend* web_data_backend) {
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  web_data_service->GetDBUserData()->SetUserData(
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      UserDataKey(), new AutocompleteSyncableService(web_data_backend));
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AutocompleteSyncableService* AutocompleteSyncableService::FromWebDataService(
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AutofillWebDataService* web_data_service) {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return static_cast<AutocompleteSyncableService*>(
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      web_data_service->GetDBUserData()->GetUserData(UserDataKey()));
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutocompleteSyncableService::AutocompleteSyncableService()
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : web_data_backend_(NULL),
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scoped_observer_(this) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AutocompleteSyncableService::InjectStartSyncFlare(
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const syncer::SyncableService::StartSyncFlare& flare) {
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  flare_ = flare;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncMergeResult AutocompleteSyncableService::MergeDataAndStartSyncing(
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelType type,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncer::SyncDataList& initial_sync_data,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<syncer::SyncErrorFactory> error_handler) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!sync_processor_);
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(sync_processor);
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(error_handler);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syncer::SyncMergeResult merge_result(type);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_handler_ = error_handler.Pass();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<AutofillEntry> entries;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!LoadAutofillData(&entries)) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    merge_result.set_error(error_handler_->CreateAndUploadError(
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        "Could not load autocomplete data from the WebDatabase."));
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return merge_result;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutocompleteEntryMap new_db_entries;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<AutofillEntry>::iterator it = entries.begin();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != entries.end(); ++it) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_db_entries[it->key()] =
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::make_pair(syncer::SyncChange::ACTION_ADD, it);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_processor_ = sync_processor.Pass();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<AutofillEntry> new_synced_entries;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Go through and check for all the entries that sync already knows about.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CreateOrUpdateEntry() will remove entries that are same with the synced
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ones from |new_db_entries|.
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (syncer::SyncDataList::const_iterator it = initial_sync_data.begin();
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != initial_sync_data.end(); ++it) {
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CreateOrUpdateEntry(*it, &new_db_entries, &new_synced_entries);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SaveChangesToWebData(new_synced_entries)) {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    merge_result.set_error(error_handler_->CreateAndUploadError(
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "Failed to update webdata."));
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return merge_result;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncChangeList new_changes;
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (AutocompleteEntryMap::iterator it = new_db_entries.begin();
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != new_db_entries.end(); ++it) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_changes.push_back(
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        syncer::SyncChange(FROM_HERE,
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           it->second.first,
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           CreateSyncData(*(it->second.second))));
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  merge_result.set_error(
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes));
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This will schedule a deletion operation on the DB thread, which will
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // trigger a notification to propagate the deletion to Sync.
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // NOTE: This must be called *after* the ProcessSyncChanges call above.
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Otherwise, an item that Sync is not yet aware of might expire, causing a
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Sync error when that item's deletion is propagated to Sync.
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  web_data_backend_->RemoveExpiredFormElements();
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return merge_result;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteSyncableService::StopSyncing(syncer::ModelType type) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(syncer::AUTOFILL, type);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  sync_processor_.reset();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_handler_.reset();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)syncer::SyncDataList AutocompleteSyncableService::GetAllSyncData(
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelType type) const {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(sync_processor_);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(type, syncer::AUTOFILL);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncDataList current_data;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<AutofillEntry> entries;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!LoadAutofillData(&entries))
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return current_data;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<AutofillEntry>::iterator it = entries.begin();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != entries.end(); ++it) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_data.push_back(CreateSyncData(*it));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return current_data;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)syncer::SyncError AutocompleteSyncableService::ProcessSyncChanges(
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& from_here,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncer::SyncChangeList& change_list) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(sync_processor_);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!sync_processor_) {
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    syncer::SyncError error(FROM_HERE,
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            syncer::SyncError::DATATYPE_ERROR,
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            "Models not yet associated.",
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            syncer::AUTOFILL);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Data is loaded only if we get new ADD/UPDATE change.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<AutofillEntry> entries;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AutocompleteEntryMap> db_entries;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<AutofillEntry> new_entries;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncError list_processing_error;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (syncer::SyncChangeList::const_iterator i = change_list.begin();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != change_list.end() && !list_processing_error.IsSet(); ++i) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(i->IsValid());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (i->change_type()) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case syncer::SyncChange::ACTION_ADD:
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case syncer::SyncChange::ACTION_UPDATE:
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (!db_entries) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!LoadAutofillData(&entries)) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return error_handler_->CreateAndUploadError(
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                FROM_HERE,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "Could not get the autocomplete data from WebDatabase.");
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          db_entries.reset(new AutocompleteEntryMap);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          for (std::vector<AutofillEntry>::iterator it = entries.begin();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it != entries.end(); ++it) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (*db_entries)[it->key()] =
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                std::make_pair(syncer::SyncChange::ACTION_ADD, it);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateOrUpdateEntry(i->sync_data(), db_entries.get(), &new_entries);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case syncer::SyncChange::ACTION_DELETE: {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK(i->sync_data().GetSpecifics().has_autofill())
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "Autofill specifics data not present on delete!";
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const sync_pb::AutofillSpecifics& autofill =
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            i->sync_data().GetSpecifics().autofill();
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (autofill.has_value())
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          list_processing_error = AutofillEntryDelete(autofill);
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          DVLOG(1) << "Delete for old-style autofill profile being dropped!";
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      case syncer::SyncChange::ACTION_INVALID:
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        NOTREACHED();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return error_handler_->CreateAndUploadError(
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FROM_HERE,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "ProcessSyncChanges failed on ChangeType " +
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 syncer::SyncChange::ChangeTypeToString(i->change_type()));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SaveChangesToWebData(new_entries)) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error_handler_->CreateAndUploadError(
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Failed to update webdata.");
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This will schedule a deletion operation on the DB thread, which will
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // trigger a notification to propagate the deletion to Sync.
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  web_data_backend_->RemoveExpiredFormElements();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return list_processing_error;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AutocompleteSyncableService::AutofillEntriesChanged(
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const AutofillChangeList& changes) {
285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Check if sync is on. If we receive this notification prior to sync being
2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // started, we'll notify sync to start as soon as it can and later process all
2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // entries when MergeDataAndStartSyncing() is called. If we receive this
2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // notification after sync has exited, it will be synced the next time Chrome
2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // starts.
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (sync_processor_) {
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ActOnChanges(changes);
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (!flare_.is_null()) {
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    flare_.Run(syncer::AUTOFILL);
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    flare_.Reset();
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutocompleteSyncableService::LoadAutofillData(
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<AutofillEntry>* entries) const {
3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return GetAutofillTable()->GetAllAutofillEntries(entries);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutocompleteSyncableService::SaveChangesToWebData(
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<AutofillEntry>& new_entries) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!GetAutofillTable()->UpdateAutofillEntries(new_entries))
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  web_data_backend_->NotifyOfMultipleAutofillChanges();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates or updates an autocomplete entry based on |data|.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteSyncableService::CreateOrUpdateEntry(
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncer::SyncData& data,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AutocompleteEntryMap* loaded_data,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<AutofillEntry>* new_entries) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const sync_pb::EntitySpecifics& specifics = data.GetSpecifics();
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const sync_pb::AutofillSpecifics& autofill_specifics(specifics.autofill());
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!autofill_specifics.has_value()) {
3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DVLOG(1) << "Add/Update for old-style autofill profile being dropped!";
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutofillKey key(autofill_specifics.name().c_str(),
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  autofill_specifics.value().c_str());
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutocompleteEntryMap::iterator it = loaded_data->find(key);
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const google::protobuf::RepeatedField<int64_t>& timestamps =
330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      autofill_specifics.usage_timestamp();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == loaded_data->end()) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // New entry.
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::Time date_created, date_last_used;
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (timestamps.size() > 0) {
335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      date_created = base::Time::FromInternalValue(*timestamps.begin());
336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      date_last_used = base::Time::FromInternalValue(*timestamps.rbegin());
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    new_entries->push_back(AutofillEntry(key, date_created, date_last_used));
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Entry already present - merge if necessary.
341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::Time date_created, date_last_used;
342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool different = MergeTimestamps(timestamps, *it->second.second,
343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     &date_created, &date_last_used);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (different) {
345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      AutofillEntry new_entry(
346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          it->second.second->key(), date_created, date_last_used);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_entries->push_back(new_entry);
348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Update the sync db since the timestamps have changed.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *(it->second.second) = new_entry;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it->second.first = syncer::SyncChange::ACTION_UPDATE;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loaded_data->erase(it);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteSyncableService::WriteAutofillEntry(
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AutofillEntry& entry, sync_pb::EntitySpecifics* autofill_specifics) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_pb::AutofillSpecifics* autofill =
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      autofill_specifics->mutable_autofill();
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  autofill->set_name(base::UTF16ToUTF8(entry.key().name()));
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  autofill->set_value(base::UTF16ToUTF8(entry.key().value()));
364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  autofill->add_usage_timestamp(entry.date_created().ToInternalValue());
365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (entry.date_created() != entry.date_last_used())
366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    autofill->add_usage_timestamp(entry.date_last_used().ToInternalValue());
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)syncer::SyncError AutocompleteSyncableService::AutofillEntryDelete(
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const sync_pb::AutofillSpecifics& autofill) {
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!GetAutofillTable()->RemoveFormElement(
3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::UTF8ToUTF16(autofill.name()),
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::UTF8ToUTF16(autofill.value()))) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error_handler_->CreateAndUploadError(
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Could not remove autocomplete entry from WebDatabase.");
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return syncer::SyncError();
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteSyncableService::ActOnChanges(
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     const AutofillChangeList& changes) {
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(sync_processor_);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncChangeList new_changes;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (AutofillChangeList::const_iterator change = changes.begin();
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       change != changes.end(); ++change) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (change->type()) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case AutofillChange::ADD:
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case AutofillChange::UPDATE: {
390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::Time date_created, date_last_used;
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        bool success = GetAutofillTable()->GetAutofillTimestamps(
3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            change->key().name(), change->key().value(),
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            &date_created, &date_last_used);
3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        DCHECK(success);
395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        AutofillEntry entry(change->key(), date_created, date_last_used);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        syncer::SyncChange::SyncChangeType change_type =
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (change->type() == AutofillChange::ADD) ?
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            syncer::SyncChange::ACTION_ADD :
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            syncer::SyncChange::ACTION_UPDATE;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_changes.push_back(syncer::SyncChange(FROM_HERE,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 change_type,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 CreateSyncData(entry)));
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case AutofillChange::REMOVE: {
407a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        AutofillEntry entry(change->key(), base::Time(), base::Time());
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_changes.push_back(
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            syncer::SyncChange(FROM_HERE,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               syncer::SyncChange::ACTION_DELETE,
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               CreateSyncData(entry)));
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncError error =
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error.IsSet()) {
4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DVLOG(1) << "[AUTOCOMPLETE SYNC] Failed processing change.  Error: "
4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             << error.message();
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)syncer::SyncData AutocompleteSyncableService::CreateSyncData(
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AutofillEntry& entry) const {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_pb::EntitySpecifics autofill_specifics;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteAutofillEntry(entry, &autofill_specifics);
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string tag(KeyToTag(base::UTF16ToUTF8(entry.key().name()),
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           base::UTF16ToUTF8(entry.key().value())));
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return syncer::SyncData::CreateLocalData(tag, tag, autofill_specifics);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)AutofillTable* AutocompleteSyncableService::GetAutofillTable() const {
4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase());
4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string AutocompleteSyncableService::KeyToTag(const std::string& name,
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  const std::string& value) {
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string prefix(kAutofillEntryNamespaceTag);
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return prefix + net::EscapePath(name) + "|" + net::EscapePath(value);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
443