Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1132)

Side by Side Diff: chrome/browser/password_manager/password_syncable_service.cc

Issue 27233003: [Sync] Implementation of model association for passwords using sync API (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: For review. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/password_manager/password_syncable_service.h" 5 #include "chrome/browser/password_manager/password_syncable_service.h"
6 6
7 #include "base/location.h" 7 #include "base/location.h"
8 #include "base/memory/scoped_vector.h"
9 #include "base/metrics/histogram.h"
10 #include "base/stl_util.h"
8 #include "base/strings/utf_string_conversions.h" 11 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/password_manager/password_store.h" 12 #include "chrome/browser/password_manager/password_store.h"
10 #include "components/autofill/core/common/password_form.h" 13 #include "components/autofill/core/common/password_form.h"
11 #include "net/base/escape.h" 14 #include "net/base/escape.h"
12 #include "sync/api/sync_error_factory.h" 15 #include "sync/api/sync_error_factory.h"
13 16
14 namespace { 17 namespace {
15 18
16 // Converts the |PasswordSpecifics| obtained from sync to an
17 // object of type |PasswordForm|.
18 void ExtractPasswordFromSpecifics(
19 const sync_pb::PasswordSpecificsData& password,
20 autofill::PasswordForm* new_password) {
21 new_password->scheme =
22 static_cast<autofill::PasswordForm::Scheme>(password.scheme());
23 new_password->signon_realm = password.signon_realm();
24 new_password->origin = GURL(password.origin());
25 new_password->action = GURL(password.action());
26 new_password->username_element =
27 UTF8ToUTF16(password.username_element());
28 new_password->password_element =
29 UTF8ToUTF16(password.password_element());
30 new_password->username_value =
31 UTF8ToUTF16(password.username_value());
32 new_password->password_value =
33 UTF8ToUTF16(password.password_value());
34 new_password->ssl_valid = password.ssl_valid();
35 new_password->preferred = password.preferred();
36 new_password->date_created =
37 base::Time::FromInternalValue(password.date_created());
38 new_password->blacklisted_by_user =
39 password.blacklisted();
40 }
41
42 // Merges the sync password (obtained from the password specifics) and 19 // Merges the sync password (obtained from the password specifics) and
43 // local password and stores the output in the |new_password_form| pointer. 20 // local password and stores the output in the |new_password_form| pointer.
44 bool MergeLocalAndSyncPasswords( 21 bool MergeLocalAndSyncPasswords(
45 const sync_pb::PasswordSpecificsData& password_specifics, 22 const sync_pb::PasswordSpecificsData& password_specifics,
46 const autofill::PasswordForm& password_form, 23 const autofill::PasswordForm& password_form,
47 autofill::PasswordForm* new_password_form) { 24 autofill::PasswordForm* new_password_form) {
48 if (password_specifics.scheme() == password_form.scheme && 25 if (password_specifics.scheme() == password_form.scheme &&
49 password_form.signon_realm == password_specifics.signon_realm() && 26 password_form.signon_realm == password_specifics.signon_realm() &&
50 password_form.origin.spec() == password_specifics.origin() && 27 password_form.origin.spec() == password_specifics.origin() &&
51 password_form.action.spec() == password_specifics.action() && 28 password_form.action.spec() == password_specifics.action() &&
(...skipping 12 matching lines...) Expand all
64 password_specifics.blacklisted() == 41 password_specifics.blacklisted() ==
65 password_form.blacklisted_by_user) { 42 password_form.blacklisted_by_user) {
66 return false; 43 return false;
67 } 44 }
68 45
69 // If the passwords differ, take the one that was created more recently. 46 // If the passwords differ, take the one that was created more recently.
70 if (base::Time::FromInternalValue(password_specifics.date_created()) <= 47 if (base::Time::FromInternalValue(password_specifics.date_created()) <=
71 password_form.date_created) { 48 password_form.date_created) {
72 *new_password_form = password_form; 49 *new_password_form = password_form;
73 } else { 50 } else {
74 ExtractPasswordFromSpecifics(password_specifics, new_password_form); 51 PasswordSyncableService::ExtractPasswordFromSpecifics(
52 password_specifics,
53 new_password_form);
75 } 54 }
76 55
77 return true; 56 return true;
78 } 57 }
79 58
80 } // namespace 59 } // namespace
81 60
82 PasswordSyncableService::PasswordSyncableService( 61 PasswordSyncableService::PasswordSyncableService(
83 scoped_refptr<PasswordStore> password_store) 62 scoped_refptr<PasswordStore> password_store)
84 : password_store_(password_store) { 63 : password_store_(password_store) {
85 } 64 }
86 65
87 PasswordSyncableService::~PasswordSyncableService() {} 66 PasswordSyncableService::~PasswordSyncableService() {}
88 67
68 void PasswordSyncableService::CreateOrUpdateEntry(
69 const syncer::SyncData& data,
70 PasswordEntryMap* loaded_data,
71 ScopedVector<autofill::PasswordForm>* new_entries,
72 ScopedVector<autofill::PasswordForm>* updated_entries,
73 syncer::SyncChangeList* updated_db_entries) {
74 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics();
75 const sync_pb::PasswordSpecificsData& password_specifics(
76 specifics.password().client_only_encrypted_data());
77
78 std::string tag = MakeTag(password_specifics);
79
80 // Find if the data from sync is already in password store.
81 PasswordEntryMap::iterator it = loaded_data->find(tag);
82
83 if (it == loaded_data->end()) {
84 // The sync data is not in password store, so we need to create it in
85 // password store. Add the entry to the new_entries list.
86 autofill::PasswordForm* new_password = new autofill::PasswordForm();
87 ExtractPasswordFromSpecifics(password_specifics, new_password);
88 // The new_password pointer is owned by the caller.
89 new_entries->push_back(new_password);
90 } else {
91 // The entry is in password store. If the entries are not identical the
92 // entries need to be merged.
93 scoped_ptr<autofill::PasswordForm> new_password(
94 new autofill::PasswordForm());
95 if (MergeLocalAndSyncPasswords(password_specifics,
96 **(it->second),
97 new_password.get())) {
98 updated_db_entries->push_back(
99 syncer::SyncChange(FROM_HERE,
100 syncer::SyncChange::ACTION_UPDATE,
101 CreateSyncData(*(new_password.get()))));
102
103 updated_entries->push_back(new_password.release());
104 }
105 // Remove the entry from the entry map to indicate a match has been found.
106 // Entries that remain in the map at the end of associating all sync entries
107 // will be treated as additions that needs to be propagated to sync.
108 loaded_data->erase(it);
109 }
110 }
111
89 syncer::SyncMergeResult 112 syncer::SyncMergeResult
90 PasswordSyncableService::MergeDataAndStartSyncing( 113 PasswordSyncableService::MergeDataAndStartSyncing(
91 syncer::ModelType type, 114 syncer::ModelType type,
92 const syncer::SyncDataList& initial_sync_data, 115 const syncer::SyncDataList& initial_sync_data,
93 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 116 scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
94 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) { 117 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
95 syncer::SyncMergeResult merge_result(type); 118 syncer::SyncMergeResult merge_result(type);
96 sync_error_factory_ = sync_error_factory.Pass(); 119 sync_error_factory_ = sync_error_factory.Pass();
97 sync_processor_ = sync_processor.Pass(); 120 sync_processor_ = sync_processor.Pass();
98 121
99 merge_result.set_error(sync_error_factory->CreateAndUploadError( 122 ScopedVector<autofill::PasswordForm> password_entries;
100 FROM_HERE, 123 if (!password_store_->FillAutofillableLogins(&(password_entries.get())) ||
101 "Password Syncable Service Not Implemented.")); 124 !password_store_->FillBlacklistLogins(&(password_entries.get()))) {
125 // Password store often fails to load passwords. Track failures with UMA.
126 // (http://crbug.com/249000)
127 UMA_HISTOGRAM_ENUMERATION("Sync.LocalDataFailedToLoad",
128 ModelTypeToHistogramInt(syncer::PASSWORDS),
129 syncer::MODEL_TYPE_COUNT);
130 merge_result.set_error(sync_error_factory->CreateAndUploadError(
131 FROM_HERE,
132 "Failed to get passwords from store."));
133 return merge_result;;
134 }
135
136 PasswordEntryMap new_db_entries;
137 for (std::vector<autofill::PasswordForm*>::iterator
138 it = password_entries.begin();
139 it != password_entries.end();
140 ++it) {
141 // We add all the db entries as |new_db_entries| initially. While
142 // association entries with matching sync entries will be removed and this
143 // list will only contain entries that are not in sync.
144 new_db_entries[MakeTag(**it)] = it;
145 }
146
147 // List that contains the entries that are known only to sync.
148 ScopedVector<autofill::PasswordForm> new_synced_entries;
Nicolas Zea 2013/10/25 20:20:13 nit: I think the name here would better represent
lipalani1 2013/10/29 20:16:36 May be I am missing something here: The names refe
149
150 // List that contains the entries that are known to both sync and db but
151 // have to be updated in sync.
152 ScopedVector<autofill::PasswordForm> updated_sync_entries;
153
154 // Changes from password db that needs to be propagated to sync.
155 syncer::SyncChangeList db_changes;
156 for (syncer::SyncDataList::const_iterator sync_iter =
157 initial_sync_data.begin();
158 sync_iter != initial_sync_data.end(); ++sync_iter) {
159 CreateOrUpdateEntry(*sync_iter,
160 &new_db_entries,
161 &new_synced_entries,
162 &updated_sync_entries,
163 &db_changes);
164 }
165
166 WriteToPasswordStore(new_synced_entries.get(),
167 updated_sync_entries.get());
168
169 for (PasswordEntryMap::iterator it = new_db_entries.begin();
170 it != new_db_entries.end();
171 ++it) {
172 db_changes.push_back(syncer::SyncChange(FROM_HERE,
173 syncer::SyncChange::ACTION_ADD,
174 CreateSyncData(**(it->second))));
175 }
176
177 merge_result.set_error(
Nicolas Zea 2013/10/25 20:20:13 could you also fill calculate the other variables
lipalani1 2013/10/29 20:16:36 Done.
178 sync_processor_->ProcessSyncChanges(FROM_HERE, db_changes));
102 return merge_result; 179 return merge_result;
103 } 180 }
104 181
105 void PasswordSyncableService::StopSyncing(syncer::ModelType type) { 182 void PasswordSyncableService::StopSyncing(syncer::ModelType type) {
106 } 183 }
107 184
108 syncer::SyncDataList PasswordSyncableService::GetAllSyncData( 185 syncer::SyncDataList PasswordSyncableService::GetAllSyncData(
109 syncer::ModelType type) const { 186 syncer::ModelType type) const {
110 syncer::SyncDataList sync_data; 187 syncer::SyncDataList sync_data;
111 return sync_data; 188 return sync_data;
112 } 189 }
113 190
114 syncer::SyncError PasswordSyncableService::ProcessSyncChanges( 191 syncer::SyncError PasswordSyncableService::ProcessSyncChanges(
115 const tracked_objects::Location& from_here, 192 const tracked_objects::Location& from_here,
116 const syncer::SyncChangeList& change_list) { 193 const syncer::SyncChangeList& change_list) {
117 syncer::SyncError error(FROM_HERE, 194 syncer::SyncError error(FROM_HERE,
118 syncer::SyncError::UNRECOVERABLE_ERROR, 195 syncer::SyncError::UNRECOVERABLE_ERROR,
119 "Password Syncable Service Not Implemented.", 196 "Password Syncable Service Not Implemented.",
120 syncer::PASSWORDS); 197 syncer::PASSWORDS);
121 return error; 198 return error;
122 } 199 }
123 200
124 void PasswordSyncableService::WriteToPasswordStore( 201 void PasswordSyncableService::WriteToPasswordStore(
125 PasswordForms* new_entries, 202 const PasswordForms& new_entries,
126 PasswordForms* updated_entries) { 203 const PasswordForms& updated_entries) {
127 for (std::vector<autofill::PasswordForm*>::const_iterator it = 204 for (std::vector<autofill::PasswordForm*>::const_iterator it =
128 new_entries->begin(); 205 new_entries.begin();
129 it != new_entries->end(); 206 it != new_entries.end();
130 ++it) { 207 ++it) {
131 password_store_->AddLoginImpl(**it); 208 password_store_->AddLoginImpl(**it);
132 } 209 }
133 210
134 for (std::vector<autofill::PasswordForm*>::const_iterator it = 211 for (std::vector<autofill::PasswordForm*>::const_iterator it =
135 updated_entries->begin(); 212 updated_entries.begin();
136 it != updated_entries->end(); 213 it != updated_entries.end();
137 ++it) { 214 ++it) {
138 password_store_->UpdateLoginImpl(**it); 215 password_store_->UpdateLoginImpl(**it);
139 } 216 }
140 217
141 if (!new_entries->empty() || !updated_entries->empty()) { 218 if (!new_entries.empty() || !updated_entries.empty()) {
142 // We have to notify password store observers of the change by hand since 219 // We have to notify password store observers of the change by hand since
143 // we use internal password store interfaces to make changes synchronously. 220 // we use internal password store interfaces to make changes synchronously.
144 password_store_->PostNotifyLoginsChanged(); 221 NotifyPasswordStore();
145 } 222 }
146 } 223 }
147 224
225 void PasswordSyncableService::NotifyPasswordStore() {
226 password_store_->PostNotifyLoginsChanged();
227 }
228
148 syncer::SyncData PasswordSyncableService::CreateSyncData( 229 syncer::SyncData PasswordSyncableService::CreateSyncData(
149 const autofill::PasswordForm& password_form) { 230 const autofill::PasswordForm& password_form) {
150 sync_pb::EntitySpecifics password_data; 231 sync_pb::EntitySpecifics password_data;
151 sync_pb::PasswordSpecificsData* password_specifics = 232 sync_pb::PasswordSpecificsData* password_specifics =
152 password_data.mutable_password()->mutable_client_only_encrypted_data(); 233 password_data.mutable_password()->mutable_client_only_encrypted_data();
153 password_specifics->set_scheme(password_form.scheme); 234 password_specifics->set_scheme(password_form.scheme);
154 password_specifics->set_signon_realm(password_form.signon_realm); 235 password_specifics->set_signon_realm(password_form.signon_realm);
155 password_specifics->set_origin(password_form.origin.spec()); 236 password_specifics->set_origin(password_form.origin.spec());
156 password_specifics->set_action(password_form.action.spec()); 237 password_specifics->set_action(password_form.action.spec());
157 password_specifics->set_username_element( 238 password_specifics->set_username_element(
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 // static 280 // static
200 std::string PasswordSyncableService::MakeTag( 281 std::string PasswordSyncableService::MakeTag(
201 const sync_pb::PasswordSpecificsData& password) { 282 const sync_pb::PasswordSpecificsData& password) {
202 return MakeTag(password.origin(), 283 return MakeTag(password.origin(),
203 password.username_element(), 284 password.username_element(),
204 password.username_value(), 285 password.username_value(),
205 password.password_element(), 286 password.password_element(),
206 password.signon_realm()); 287 password.signon_realm());
207 } 288 }
208 289
290 // static
291 void PasswordSyncableService::ExtractPasswordFromSpecifics(
292 const sync_pb::PasswordSpecificsData& password,
293 autofill::PasswordForm* new_password) {
294 new_password->scheme =
295 static_cast<autofill::PasswordForm::Scheme>(password.scheme());
296 new_password->signon_realm = password.signon_realm();
297 new_password->origin = GURL(password.origin());
298 new_password->action = GURL(password.action());
299 new_password->username_element =
300 UTF8ToUTF16(password.username_element());
301 new_password->password_element =
302 UTF8ToUTF16(password.password_element());
303 new_password->username_value =
304 UTF8ToUTF16(password.username_value());
305 new_password->password_value =
306 UTF8ToUTF16(password.password_value());
307 new_password->ssl_valid = password.ssl_valid();
308 new_password->preferred = password.preferred();
309 new_password->date_created =
310 base::Time::FromInternalValue(password.date_created());
311 new_password->blacklisted_by_user =
312 password.blacklisted();
313 }
314
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698