OLD | NEW |
---|---|
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 <set> | 7 #include <set> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/location.h" | 10 #include "base/location.h" |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
12 #include "base/memory/scoped_vector.h" | 12 #include "base/memory/scoped_vector.h" |
13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
16 #include "chrome/browser/password_manager/password_store.h" | 16 #include "chrome/browser/password_manager/password_store.h" |
17 #include "components/autofill/core/common/password_form.h" | 17 #include "components/autofill/core/common/password_form.h" |
18 #include "net/base/escape.h" | 18 #include "net/base/escape.h" |
19 #include "sync/api/sync_error.h" | 19 #include "sync/api/sync_error.h" |
20 #include "sync/api/sync_error_factory.h" | 20 #include "sync/api/sync_error_factory.h" |
21 | 21 |
22 namespace { | 22 namespace { |
23 | |
24 void ExtractPasswordFromSpecifics( | |
25 const sync_pb::PasswordSpecificsData& password, | |
26 autofill::PasswordForm* new_password) { | |
27 new_password->scheme = | |
28 static_cast<autofill::PasswordForm::Scheme>(password.scheme()); | |
29 new_password->signon_realm = password.signon_realm(); | |
30 new_password->origin = GURL(password.origin()); | |
31 new_password->action = GURL(password.action()); | |
32 new_password->username_element = | |
33 UTF8ToUTF16(password.username_element()); | |
34 new_password->password_element = | |
35 UTF8ToUTF16(password.password_element()); | |
36 new_password->username_value = | |
37 UTF8ToUTF16(password.username_value()); | |
38 new_password->password_value = | |
39 UTF8ToUTF16(password.password_value()); | |
40 new_password->ssl_valid = password.ssl_valid(); | |
41 new_password->preferred = password.preferred(); | |
42 new_password->date_created = | |
43 base::Time::FromInternalValue(password.date_created()); | |
44 new_password->blacklisted_by_user = | |
45 password.blacklisted(); | |
46 } | |
47 | |
48 bool MergeLocalAndSyncPasswords( | 23 bool MergeLocalAndSyncPasswords( |
49 const sync_pb::PasswordSpecificsData& password, | 24 const sync_pb::PasswordSpecificsData& password, |
50 const autofill::PasswordForm& password_form, | 25 const autofill::PasswordForm& password_form, |
51 autofill::PasswordForm* new_password) { | 26 autofill::PasswordForm* new_password) { |
52 DCHECK(new_password); | 27 DCHECK(new_password); |
53 | 28 |
54 if (password.scheme() == password_form.scheme && | 29 if (password.scheme() == password_form.scheme && |
55 password_form.signon_realm == password.signon_realm() && | 30 password_form.signon_realm == password.signon_realm() && |
56 password_form.origin.spec() == password.origin() && | 31 password_form.origin.spec() == password.origin() && |
57 password_form.action.spec() == password.action() && | 32 password_form.action.spec() == password.action() && |
(...skipping 10 matching lines...) Expand all Loading... | |
68 password.date_created() == password_form.date_created.ToInternalValue() && | 43 password.date_created() == password_form.date_created.ToInternalValue() && |
69 password.blacklisted() == password_form.blacklisted_by_user) { | 44 password.blacklisted() == password_form.blacklisted_by_user) { |
70 return false; | 45 return false; |
71 } | 46 } |
72 | 47 |
73 // If the passwords differ, we take the one that was created more recently. | 48 // If the passwords differ, we take the one that was created more recently. |
74 if (base::Time::FromInternalValue(password.date_created()) <= | 49 if (base::Time::FromInternalValue(password.date_created()) <= |
75 password_form.date_created) { | 50 password_form.date_created) { |
76 *new_password = password_form; | 51 *new_password = password_form; |
77 } else { | 52 } else { |
78 ExtractPasswordFromSpecifics(password, new_password); | 53 PasswordSyncableService::ExtractPasswordFromSpecifics( |
54 password, | |
55 new_password); | |
79 } | 56 } |
80 | 57 |
81 return true; | 58 return true; |
82 } | 59 } |
83 | 60 |
84 } // namespace | 61 } // namespace |
85 | 62 |
86 PasswordSyncableService::PasswordSyncableService( | 63 PasswordSyncableService::PasswordSyncableService( |
87 PasswordStore* password_store) : password_store_(password_store) { | 64 PasswordStore* password_store) : password_store_(password_store) { |
88 } | 65 } |
89 | 66 |
90 PasswordSyncableService::~PasswordSyncableService() {} | 67 PasswordSyncableService::~PasswordSyncableService() {} |
91 | 68 |
69 void PasswordSyncableService::CreateOrUpdateEntry( | |
70 const syncer::SyncData& data, | |
71 PasswordEntryMap* loaded_data, | |
72 std::vector<autofill::PasswordForm*>* new_entries, | |
Nicolas Zea
2013/10/15 22:04:10
pass ScopedVectors instead?
lipalani1
2013/10/18 23:33:03
Done.
| |
73 std::vector<autofill::PasswordForm*>* udpated_entries) { | |
Nicolas Zea
2013/10/15 22:04:10
udpated -> updated
lipalani1
2013/10/18 23:33:03
Done.
| |
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 // passowrd store. Add the entry to the new_entries list. | |
Nicolas Zea
2013/10/15 22:04:10
passowrd -> password
lipalani1
2013/10/18 23:33:03
Done.
| |
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.second), | |
97 new_password.get())) { | |
Nicolas Zea
2013/10/15 22:04:10
fix indent
lipalani1
2013/10/18 23:33:03
Done.
| |
98 delete *(it->second.second); | |
99 *(it->second.second) = new_password.release(); | |
100 it->second.first = syncer::SyncChange::ACTION_UPDATE; | |
101 | |
102 // Make a copy for updated list. | |
103 autofill::PasswordForm* updated_password = new autofill::PasswordForm(); | |
104 *updated_password = **(it->second.second); | |
105 udpated_entries->push_back(updated_password); | |
106 } else { | |
107 // The entries are identical. Remove it from the |loaded_data| list to | |
108 // prevent it from being treated as an unassociated entry. | |
109 loaded_data->erase(it); | |
110 } | |
111 } | |
112 } | |
113 | |
92 syncer::SyncMergeResult | 114 syncer::SyncMergeResult |
93 PasswordSyncableService::MergeDataAndStartSyncing( | 115 PasswordSyncableService::MergeDataAndStartSyncing( |
94 syncer::ModelType type, | 116 syncer::ModelType type, |
95 const syncer::SyncDataList& initial_sync_data, | 117 const syncer::SyncDataList& initial_sync_data, |
96 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, | 118 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, |
97 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) { | 119 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) { |
98 syncer::SyncMergeResult merge_result(type); | 120 syncer::SyncMergeResult merge_result(type); |
99 sync_error_factory_ = sync_error_factory.Pass(); | 121 sync_error_factory_ = sync_error_factory.Pass(); |
100 sync_processor_ = sync_processor.Pass(); | 122 sync_processor_ = sync_processor.Pass(); |
101 merge_result.set_error(sync_error_factory->CreateAndUploadError( | 123 |
102 FROM_HERE, | 124 ScopedVector<autofill::PasswordForm> password_entries; |
103 "Password Syncable Service Not Implemented.")); | 125 if (!password_store_->FillAutofillableLogins(&(password_entries.get())) || |
126 !password_store_->FillBlacklistLogins(&(password_entries.get()))) { | |
127 STLDeleteElements(&password_entries); | |
128 | |
129 // Password store often fails to load passwords. Track failures with UMA. | |
130 // (http://crbug.com/249000) | |
131 UMA_HISTOGRAM_ENUMERATION("Sync.LocalDataFailedToLoad", | |
132 ModelTypeToHistogramInt(syncer::PASSWORDS), | |
133 syncer::MODEL_TYPE_COUNT); | |
134 merge_result.set_error(sync_error_factory->CreateAndUploadError( | |
135 FROM_HERE, | |
136 "Failed to get passwords from store.")); | |
137 return merge_result;; | |
138 } | |
139 | |
140 PasswordEntryMap new_db_entries; | |
Nicolas Zea
2013/10/15 22:04:10
I think it's cleaner to track the entries separate
lipalani1
2013/10/18 23:33:03
Possible I am missing something here:
delete *(it-
Nicolas Zea
2013/10/21 23:55:14
I'm not really suggesting to have two lists for tr
| |
141 for (std::vector<autofill::PasswordForm*>::iterator | |
142 it = password_entries.begin(); | |
Nicolas Zea
2013/10/15 22:04:10
indent four more spaces
lipalani1
2013/10/18 23:33:03
Done.
| |
143 it != password_entries.end(); | |
144 ++it) { | |
145 // We add all the db entries as |new_db_entries| initially. While | |
146 // association entries with matching sync entries will be removed and this | |
147 // list will only contain entries that are not in sync. | |
148 new_db_entries[MakeTag(**it)] = | |
149 std::make_pair(syncer::SyncChange::ACTION_ADD, it); | |
150 } | |
151 | |
152 // List that contains the entries that are known only to sync. | |
153 ScopedVector<autofill::PasswordForm> new_synced_entries; | |
154 | |
155 // List that contains the entries that are known to both sync and db but | |
156 // have to be updated in sync. | |
157 ScopedVector<autofill::PasswordForm> updated_sync_entries; | |
158 for (syncer::SyncDataList::const_iterator sync_iter = | |
159 initial_sync_data.begin(); | |
160 sync_iter != initial_sync_data.end(); ++sync_iter) { | |
161 CreateOrUpdateEntry(*sync_iter, | |
162 &new_db_entries, | |
163 &(new_synced_entries.get()), | |
164 &(updated_sync_entries.get())); | |
165 } | |
166 | |
167 WriteToPasswordStore(&(new_synced_entries.get()), | |
168 &(updated_sync_entries.get())); | |
169 | |
170 syncer::SyncChangeList new_changes; | |
171 for (PasswordEntryMap::iterator it = new_db_entries.begin(); | |
172 it != new_db_entries.end(); | |
173 ++it) { | |
174 new_changes.push_back(syncer::SyncChange(FROM_HERE, | |
175 it->second.first, | |
176 CreateSyncData(**(it->second.second)))); | |
177 } | |
178 | |
179 merge_result.set_error( | |
180 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); | |
104 return merge_result; | 181 return merge_result; |
105 } | 182 } |
106 | 183 |
107 void PasswordSyncableService::StopSyncing(syncer::ModelType type) { | 184 void PasswordSyncableService::StopSyncing(syncer::ModelType type) { |
108 } | 185 } |
109 | 186 |
110 syncer::SyncDataList PasswordSyncableService::GetAllSyncData( | 187 syncer::SyncDataList PasswordSyncableService::GetAllSyncData( |
111 syncer::ModelType type) const { | 188 syncer::ModelType type) const { |
112 syncer::SyncDataList sync_data; | 189 syncer::SyncDataList sync_data; |
113 return sync_data; | 190 return sync_data; |
(...skipping 24 matching lines...) Expand all Loading... | |
138 updated_entries->begin(); | 215 updated_entries->begin(); |
139 it != updated_entries->end(); | 216 it != updated_entries->end(); |
140 ++it) { | 217 ++it) { |
141 password_store_->UpdateLoginImpl(**it); | 218 password_store_->UpdateLoginImpl(**it); |
142 } | 219 } |
143 | 220 |
144 if (new_entries->size() > 0 || | 221 if (new_entries->size() > 0 || |
145 updated_entries->size() > 0) { | 222 updated_entries->size() > 0) { |
146 // We have to notify password store observers of the change by hand since | 223 // We have to notify password store observers of the change by hand since |
147 // we use internal password store interfaces to make changes synchronously. | 224 // we use internal password store interfaces to make changes synchronously. |
148 password_store_->PostNotifyLoginsChanged(); | 225 NotifyPasswordStore(); |
149 } | 226 } |
150 return true; | 227 return true; |
151 } | 228 } |
152 | 229 |
230 void PasswordSyncableService::NotifyPasswordStore() { | |
231 password_store_->PostNotifyLoginsChanged(); | |
232 } | |
233 | |
153 syncer::SyncData PasswordSyncableService::CreateSyncData( | 234 syncer::SyncData PasswordSyncableService::CreateSyncData( |
154 const autofill::PasswordForm& password_form) { | 235 const autofill::PasswordForm& password_form) { |
155 sync_pb::EntitySpecifics password_data; | 236 sync_pb::EntitySpecifics password_data; |
156 sync_pb::PasswordSpecificsData* password_specifics = | 237 sync_pb::PasswordSpecificsData* password_specifics = |
157 password_data.mutable_password()->mutable_client_only_encrypted_data(); | 238 password_data.mutable_password()->mutable_client_only_encrypted_data(); |
158 password_specifics->set_scheme(password_form.scheme); | 239 password_specifics->set_scheme(password_form.scheme); |
159 password_specifics->set_signon_realm(password_form.signon_realm); | 240 password_specifics->set_signon_realm(password_form.signon_realm); |
160 password_specifics->set_origin(password_form.origin.spec()); | 241 password_specifics->set_origin(password_form.origin.spec()); |
161 password_specifics->set_action(password_form.action.spec()); | 242 password_specifics->set_action(password_form.action.spec()); |
162 password_specifics->set_username_element( | 243 password_specifics->set_username_element( |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
204 // static | 285 // static |
205 std::string PasswordSyncableService::MakeTag( | 286 std::string PasswordSyncableService::MakeTag( |
206 const sync_pb::PasswordSpecificsData& password) { | 287 const sync_pb::PasswordSpecificsData& password) { |
207 return MakeTag(password.origin(), | 288 return MakeTag(password.origin(), |
208 password.username_element(), | 289 password.username_element(), |
209 password.username_value(), | 290 password.username_value(), |
210 password.password_element(), | 291 password.password_element(), |
211 password.signon_realm()); | 292 password.signon_realm()); |
212 } | 293 } |
213 | 294 |
295 // static | |
296 void PasswordSyncableService::ExtractPasswordFromSpecifics( | |
297 const sync_pb::PasswordSpecificsData& password, | |
298 autofill::PasswordForm* new_password) { | |
299 new_password->scheme = | |
300 static_cast<autofill::PasswordForm::Scheme>(password.scheme()); | |
301 new_password->signon_realm = password.signon_realm(); | |
302 new_password->origin = GURL(password.origin()); | |
303 new_password->action = GURL(password.action()); | |
304 new_password->username_element = | |
305 UTF8ToUTF16(password.username_element()); | |
306 new_password->password_element = | |
307 UTF8ToUTF16(password.password_element()); | |
308 new_password->username_value = | |
309 UTF8ToUTF16(password.username_value()); | |
310 new_password->password_value = | |
311 UTF8ToUTF16(password.password_value()); | |
312 new_password->ssl_valid = password.ssl_valid(); | |
313 new_password->preferred = password.preferred(); | |
314 new_password->date_created = | |
315 base::Time::FromInternalValue(password.date_created()); | |
316 new_password->blacklisted_by_user = | |
317 password.blacklisted(); | |
318 } | |
319 | |
OLD | NEW |