1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/sync/glue/autofill_profile_data_type_controller.h"
6
7 #include "base/bind.h"
8 #include "base/metrics/histogram.h"
9 #include "chrome/browser/autofill/personal_data_manager_factory.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h"
12 #include "chrome/browser/sync/profile_sync_components_factory.h"
13 #include "chrome/browser/webdata/web_data_service_factory.h"
14 #include "components/autofill/core/browser/personal_data_manager.h"
15 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "sync/api/sync_error.h"
18 #include "sync/api/syncable_service.h"
19
20 using autofill::AutofillWebDataService;
21 using content::BrowserThread;
22
23 namespace browser_sync {
24
AutofillProfileDataTypeController(ProfileSyncComponentsFactory * profile_sync_factory,Profile * profile,const DisableTypeCallback & disable_callback)25 AutofillProfileDataTypeController::AutofillProfileDataTypeController(
26 ProfileSyncComponentsFactory* profile_sync_factory,
27 Profile* profile,
28 const DisableTypeCallback& disable_callback)
29 : NonUIDataTypeController(
30 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
31 base::Bind(&ChromeReportUnrecoverableError),
32 disable_callback,
33 profile_sync_factory),
34 profile_(profile),
35 personal_data_(NULL),
36 callback_registered_(false) {}
37
type() const38 syncer::ModelType AutofillProfileDataTypeController::type() const {
39 return syncer::AUTOFILL_PROFILE;
40 }
41
42 syncer::ModelSafeGroup
model_safe_group() const43 AutofillProfileDataTypeController::model_safe_group() const {
44 return syncer::GROUP_DB;
45 }
46
WebDatabaseLoaded()47 void AutofillProfileDataTypeController::WebDatabaseLoaded() {
48 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
49 OnModelLoaded();
50 }
51
OnPersonalDataChanged()52 void AutofillProfileDataTypeController::OnPersonalDataChanged() {
53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
54 DCHECK_EQ(state(), MODEL_STARTING);
55
56 personal_data_->RemoveObserver(this);
57 autofill::AutofillWebDataService* web_data_service =
58 WebDataServiceFactory::GetAutofillWebDataForProfile(
59 profile_, Profile::EXPLICIT_ACCESS).get();
60
61 if (!web_data_service)
62 return;
63
64 if (web_data_service->IsDatabaseLoaded()) {
65 OnModelLoaded();
66 } else if (!callback_registered_) {
67 web_data_service->RegisterDBLoadedCallback(base::Bind(
68 &AutofillProfileDataTypeController::WebDatabaseLoaded, this));
69 callback_registered_ = true;
70 }
71 }
72
~AutofillProfileDataTypeController()73 AutofillProfileDataTypeController::~AutofillProfileDataTypeController() {}
74
PostTaskOnBackendThread(const tracked_objects::Location & from_here,const base::Closure & task)75 bool AutofillProfileDataTypeController::PostTaskOnBackendThread(
76 const tracked_objects::Location& from_here,
77 const base::Closure& task) {
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
79 return BrowserThread::PostTask(BrowserThread::DB, from_here, task);
80 }
81
StartModels()82 bool AutofillProfileDataTypeController::StartModels() {
83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
84 DCHECK_EQ(state(), MODEL_STARTING);
85 // Waiting for the personal data is subtle: we do this as the PDM resets
86 // its cache of unique IDs once it gets loaded. If we were to proceed with
87 // association, the local ids in the mappings would wind up colliding.
88 personal_data_ =
89 autofill::PersonalDataManagerFactory::GetForProfile(profile_);
90 if (!personal_data_->IsDataLoaded()) {
91 personal_data_->AddObserver(this);
92 return false;
93 }
94
95 autofill::AutofillWebDataService* web_data_service =
96 WebDataServiceFactory::GetAutofillWebDataForProfile(
97 profile_, Profile::EXPLICIT_ACCESS).get();
98
99 if (!web_data_service)
100 return false;
101
102 if (web_data_service->IsDatabaseLoaded())
103 return true;
104
105 if (!callback_registered_) {
106 web_data_service->RegisterDBLoadedCallback(base::Bind(
107 &AutofillProfileDataTypeController::WebDatabaseLoaded, this));
108 callback_registered_ = true;
109 }
110
111 return false;
112 }
113
StopModels()114 void AutofillProfileDataTypeController::StopModels() {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
116 personal_data_->RemoveObserver(this);
117 }
118
119 } // namespace browser_sync
120