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

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_ptr.h"
Nicolas Zea 2013/10/21 23:55:14 already have scoped_ptr in header
lipalani1 2013/10/24 00:13:58 Done.
9 #include "base/memory/scoped_vector.h"
10 #include "base/metrics/histogram.h"
11 #include "base/stl_util.h"
8 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/password_manager/password_store.h" 13 #include "chrome/browser/password_manager/password_store.h"
10 #include "components/autofill/core/common/password_form.h" 14 #include "components/autofill/core/common/password_form.h"
11 #include "net/base/escape.h" 15 #include "net/base/escape.h"
16 #include "sync/api/sync_error.h"
Nicolas Zea 2013/10/21 23:55:14 already have in header
lipalani1 2013/10/24 00:13:58 Done.
12 #include "sync/api/sync_error_factory.h" 17 #include "sync/api/sync_error_factory.h"
13 18
14 namespace { 19 namespace {
15 20
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 21 // Merges the sync password (obtained from the password specifics) and
43 // local password and stores the output in the |new_password_form| pointer. 22 // local password and stores the output in the |new_password_form| pointer.
44 bool MergeLocalAndSyncPasswords( 23 bool MergeLocalAndSyncPasswords(
45 const sync_pb::PasswordSpecificsData& password_specifics, 24 const sync_pb::PasswordSpecificsData& password_specifics,
46 const autofill::PasswordForm& password_form, 25 const autofill::PasswordForm& password_form,
47 autofill::PasswordForm* new_password_form) { 26 autofill::PasswordForm* new_password_form) {
48 if (password_specifics.scheme() == password_form.scheme && 27 if (password_specifics.scheme() == password_form.scheme &&
49 password_form.signon_realm == password_specifics.signon_realm() && 28 password_form.signon_realm == password_specifics.signon_realm() &&
50 password_form.origin.spec() == password_specifics.origin() && 29 password_form.origin.spec() == password_specifics.origin() &&
51 password_form.action.spec() == password_specifics.action() && 30 password_form.action.spec() == password_specifics.action() &&
(...skipping 12 matching lines...) Expand all
64 password_specifics.blacklisted() == 43 password_specifics.blacklisted() ==
65 password_form.blacklisted_by_user) { 44 password_form.blacklisted_by_user) {
66 return false; 45 return false;
67 } 46 }
68 47
69 // If the passwords differ, take the one that was created more recently. 48 // If the passwords differ, take the one that was created more recently.
70 if (base::Time::FromInternalValue(password_specifics.date_created()) <= 49 if (base::Time::FromInternalValue(password_specifics.date_created()) <=
71 password_form.date_created) { 50 password_form.date_created) {
72 *new_password_form = password_form; 51 *new_password_form = password_form;
73 } else { 52 } else {
74 ExtractPasswordFromSpecifics(password_specifics, new_password_form); 53 PasswordSyncableService::ExtractPasswordFromSpecifics(
54 password_specifics,
55 new_password_form);
75 } 56 }
76 57
77 return true; 58 return true;
78 } 59 }
79 60
80 } // namespace 61 } // namespace
81 62
82 PasswordSyncableService::PasswordSyncableService( 63 PasswordSyncableService::PasswordSyncableService(
83 scoped_refptr<PasswordStore> password_store) 64 scoped_refptr<PasswordStore> password_store)
84 : password_store_(password_store) { 65 : password_store_(password_store) {
85 } 66 }
86 67
87 PasswordSyncableService::~PasswordSyncableService() {} 68 PasswordSyncableService::~PasswordSyncableService() {}
88 69
70 void PasswordSyncableService::CreateOrUpdateEntry(
71 const syncer::SyncData& data,
72 PasswordEntryMap* loaded_data,
73 ScopedVector<autofill::PasswordForm>* new_entries,
74 ScopedVector<autofill::PasswordForm>* updated_entries) {
75 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics();
76 const sync_pb::PasswordSpecificsData& password_specifics(
77 specifics.password().client_only_encrypted_data());
78
79 std::string tag = MakeTag(password_specifics);
80
81 // Find if the data from sync is already in password store.
82 PasswordEntryMap::iterator it = loaded_data->find(tag);
83
84 if (it == loaded_data->end()) {
85 // The sync data is not in password store, so we need to create it in
86 // password store. Add the entry to the new_entries list.
87 autofill::PasswordForm* new_password = new autofill::PasswordForm();
88 ExtractPasswordFromSpecifics(password_specifics, new_password);
89 // The new_password pointer is owned by the caller.
90 new_entries->push_back(new_password);
91 } else {
92 // The entry is in password store. If the entries are not identical the
93 // entries need to be merged.
94 scoped_ptr<autofill::PasswordForm> new_password(
95 new autofill::PasswordForm());
96 if (MergeLocalAndSyncPasswords(password_specifics,
97 **(it->second.second),
98 new_password.get())) {
99 **(it->second.second) = *(new_password.get());
100 it->second.first = syncer::SyncChange::ACTION_UPDATE;
101
102 updated_entries->push_back(new_password.release());
103 } else {
104 // The entries are identical. Remove it from the |loaded_data| list to
105 // prevent it from being treated as an unassociated entry.
106 loaded_data->erase(it);
107 }
108 }
109 }
110
89 syncer::SyncMergeResult 111 syncer::SyncMergeResult
90 PasswordSyncableService::MergeDataAndStartSyncing( 112 PasswordSyncableService::MergeDataAndStartSyncing(
91 syncer::ModelType type, 113 syncer::ModelType type,
92 const syncer::SyncDataList& initial_sync_data, 114 const syncer::SyncDataList& initial_sync_data,
93 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 115 scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
94 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) { 116 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
95 syncer::SyncMergeResult merge_result(type); 117 syncer::SyncMergeResult merge_result(type);
96 sync_error_factory_ = sync_error_factory.Pass(); 118 sync_error_factory_ = sync_error_factory.Pass();
97 sync_processor_ = sync_processor.Pass(); 119 sync_processor_ = sync_processor.Pass();
98 120
99 merge_result.set_error(sync_error_factory->CreateAndUploadError( 121 ScopedVector<autofill::PasswordForm> password_entries;
100 FROM_HERE, 122 if (!password_store_->FillAutofillableLogins(&(password_entries.get())) ||
101 "Password Syncable Service Not Implemented.")); 123 !password_store_->FillBlacklistLogins(&(password_entries.get()))) {
124 // Password store often fails to load passwords. Track failures with UMA.
125 // (http://crbug.com/249000)
126 UMA_HISTOGRAM_ENUMERATION("Sync.LocalDataFailedToLoad",
127 ModelTypeToHistogramInt(syncer::PASSWORDS),
128 syncer::MODEL_TYPE_COUNT);
129 merge_result.set_error(sync_error_factory->CreateAndUploadError(
130 FROM_HERE,
131 "Failed to get passwords from store."));
132 return merge_result;;
133 }
134
135 PasswordEntryMap new_db_entries;
136 for (std::vector<autofill::PasswordForm*>::iterator
137 it = password_entries.begin();
138 it != password_entries.end();
139 ++it) {
140 // We add all the db entries as |new_db_entries| initially. While
141 // association entries with matching sync entries will be removed and this
142 // list will only contain entries that are not in sync.
143 new_db_entries[MakeTag(**it)] =
144 std::make_pair(syncer::SyncChange::ACTION_ADD, it);
145 }
146
147 // List that contains the entries that are known only to sync.
148 ScopedVector<autofill::PasswordForm> new_synced_entries;
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 for (syncer::SyncDataList::const_iterator sync_iter =
154 initial_sync_data.begin();
155 sync_iter != initial_sync_data.end(); ++sync_iter) {
156 CreateOrUpdateEntry(*sync_iter,
157 &new_db_entries,
158 &new_synced_entries,
159 &updated_sync_entries);
160 }
161
162 WriteToPasswordStore(&(new_synced_entries.get()),
Nicolas Zea 2013/10/21 23:55:14 nit: WriteToPasswordStore should be taking const r
lipalani1 2013/10/24 00:13:58 Done.
163 &(updated_sync_entries.get()));
164
165 syncer::SyncChangeList new_changes;
166 for (PasswordEntryMap::iterator it = new_db_entries.begin();
167 it != new_db_entries.end();
168 ++it) {
169 new_changes.push_back(syncer::SyncChange(FROM_HERE,
170 it->second.first,
171 CreateSyncData(**(it->second.second))));
172 }
173
174 merge_result.set_error(
175 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes));
102 return merge_result; 176 return merge_result;
103 } 177 }
104 178
105 void PasswordSyncableService::StopSyncing(syncer::ModelType type) { 179 void PasswordSyncableService::StopSyncing(syncer::ModelType type) {
106 } 180 }
107 181
108 syncer::SyncDataList PasswordSyncableService::GetAllSyncData( 182 syncer::SyncDataList PasswordSyncableService::GetAllSyncData(
109 syncer::ModelType type) const { 183 syncer::ModelType type) const {
110 syncer::SyncDataList sync_data; 184 syncer::SyncDataList sync_data;
111 return sync_data; 185 return sync_data;
(...skipping 22 matching lines...) Expand all
134 for (std::vector<autofill::PasswordForm*>::const_iterator it = 208 for (std::vector<autofill::PasswordForm*>::const_iterator it =
135 updated_entries->begin(); 209 updated_entries->begin();
136 it != updated_entries->end(); 210 it != updated_entries->end();
137 ++it) { 211 ++it) {
138 password_store_->UpdateLoginImpl(**it); 212 password_store_->UpdateLoginImpl(**it);
139 } 213 }
140 214
141 if (!new_entries->empty() || !updated_entries->empty()) { 215 if (!new_entries->empty() || !updated_entries->empty()) {
142 // We have to notify password store observers of the change by hand since 216 // We have to notify password store observers of the change by hand since
143 // we use internal password store interfaces to make changes synchronously. 217 // we use internal password store interfaces to make changes synchronously.
144 password_store_->PostNotifyLoginsChanged(); 218 NotifyPasswordStore();
145 } 219 }
146 } 220 }
147 221
222 void PasswordSyncableService::NotifyPasswordStore() {
223 password_store_->PostNotifyLoginsChanged();
224 }
225
148 syncer::SyncData PasswordSyncableService::CreateSyncData( 226 syncer::SyncData PasswordSyncableService::CreateSyncData(
149 const autofill::PasswordForm& password_form) { 227 const autofill::PasswordForm& password_form) {
150 sync_pb::EntitySpecifics password_data; 228 sync_pb::EntitySpecifics password_data;
151 sync_pb::PasswordSpecificsData* password_specifics = 229 sync_pb::PasswordSpecificsData* password_specifics =
152 password_data.mutable_password()->mutable_client_only_encrypted_data(); 230 password_data.mutable_password()->mutable_client_only_encrypted_data();
153 password_specifics->set_scheme(password_form.scheme); 231 password_specifics->set_scheme(password_form.scheme);
154 password_specifics->set_signon_realm(password_form.signon_realm); 232 password_specifics->set_signon_realm(password_form.signon_realm);
155 password_specifics->set_origin(password_form.origin.spec()); 233 password_specifics->set_origin(password_form.origin.spec());
156 password_specifics->set_action(password_form.action.spec()); 234 password_specifics->set_action(password_form.action.spec());
157 password_specifics->set_username_element( 235 password_specifics->set_username_element(
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 // static 277 // static
200 std::string PasswordSyncableService::MakeTag( 278 std::string PasswordSyncableService::MakeTag(
201 const sync_pb::PasswordSpecificsData& password) { 279 const sync_pb::PasswordSpecificsData& password) {
202 return MakeTag(password.origin(), 280 return MakeTag(password.origin(),
203 password.username_element(), 281 password.username_element(),
204 password.username_value(), 282 password.username_value(),
205 password.password_element(), 283 password.password_element(),
206 password.signon_realm()); 284 password.signon_realm());
207 } 285 }
208 286
287 // static
288 void PasswordSyncableService::ExtractPasswordFromSpecifics(
289 const sync_pb::PasswordSpecificsData& password,
290 autofill::PasswordForm* new_password) {
291 new_password->scheme =
292 static_cast<autofill::PasswordForm::Scheme>(password.scheme());
293 new_password->signon_realm = password.signon_realm();
294 new_password->origin = GURL(password.origin());
295 new_password->action = GURL(password.action());
296 new_password->username_element =
297 UTF8ToUTF16(password.username_element());
298 new_password->password_element =
299 UTF8ToUTF16(password.password_element());
300 new_password->username_value =
301 UTF8ToUTF16(password.username_value());
302 new_password->password_value =
303 UTF8ToUTF16(password.password_value());
304 new_password->ssl_valid = password.ssl_valid();
305 new_password->preferred = password.preferred();
306 new_password->date_created =
307 base::Time::FromInternalValue(password.date_created());
308 new_password->blacklisted_by_user =
309 password.blacklisted();
310 }
311
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698