- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / password_manager / password_syncable_service.cc
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/password_manager/password_syncable_service.h"
6
7 #include "base/location.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/password_manager/password_store.h"
10 #include "components/autofill/core/common/password_form.h"
11 #include "net/base/escape.h"
12 #include "sync/api/sync_error_factory.h"
13
14 namespace {
15
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
43 // local password and stores the output in the |new_password_form| pointer.
44 bool MergeLocalAndSyncPasswords(
45     const sync_pb::PasswordSpecificsData& password_specifics,
46     const autofill::PasswordForm& password_form,
47     autofill::PasswordForm* new_password_form) {
48   if (password_specifics.scheme() == password_form.scheme &&
49       password_form.signon_realm == password_specifics.signon_realm() &&
50       password_form.origin.spec() == password_specifics.origin() &&
51       password_form.action.spec() == password_specifics.action() &&
52       UTF16ToUTF8(password_form.username_element) ==
53           password_specifics.username_element() &&
54       UTF16ToUTF8(password_form.password_element) ==
55           password_specifics.password_element() &&
56       UTF16ToUTF8(password_form.username_value) ==
57           password_specifics.username_value() &&
58       UTF16ToUTF8(password_form.password_value) ==
59           password_specifics.password_value() &&
60       password_specifics.ssl_valid() == password_form.ssl_valid &&
61       password_specifics.preferred() == password_form.preferred &&
62       password_specifics.date_created() ==
63           password_form.date_created.ToInternalValue() &&
64       password_specifics.blacklisted() ==
65           password_form.blacklisted_by_user) {
66     return false;
67   }
68
69   // If the passwords differ, take the one that was created more recently.
70   if (base::Time::FromInternalValue(password_specifics.date_created()) <=
71           password_form.date_created) {
72     *new_password_form = password_form;
73   } else {
74     ExtractPasswordFromSpecifics(password_specifics, new_password_form);
75   }
76
77   return true;
78 }
79
80 }  // namespace
81
82 PasswordSyncableService::PasswordSyncableService(
83     scoped_refptr<PasswordStore> password_store)
84     : password_store_(password_store) {
85 }
86
87 PasswordSyncableService::~PasswordSyncableService() {}
88
89 syncer::SyncMergeResult
90 PasswordSyncableService::MergeDataAndStartSyncing(
91     syncer::ModelType type,
92     const syncer::SyncDataList& initial_sync_data,
93     scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
94     scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
95   syncer::SyncMergeResult merge_result(type);
96   sync_error_factory_ = sync_error_factory.Pass();
97   sync_processor_ = sync_processor.Pass();
98
99   merge_result.set_error(sync_error_factory->CreateAndUploadError(
100       FROM_HERE,
101       "Password Syncable Service Not Implemented."));
102   return merge_result;
103 }
104
105 void PasswordSyncableService::StopSyncing(syncer::ModelType type) {
106 }
107
108 syncer::SyncDataList PasswordSyncableService::GetAllSyncData(
109     syncer::ModelType type) const {
110   syncer::SyncDataList sync_data;
111   return sync_data;
112 }
113
114 syncer::SyncError PasswordSyncableService::ProcessSyncChanges(
115     const tracked_objects::Location& from_here,
116     const syncer::SyncChangeList& change_list) {
117   syncer::SyncError error(FROM_HERE,
118                           syncer::SyncError::UNRECOVERABLE_ERROR,
119                           "Password Syncable Service Not Implemented.",
120                           syncer::PASSWORDS);
121   return error;
122 }
123
124 void PasswordSyncableService::WriteToPasswordStore(
125     PasswordForms* new_entries,
126     PasswordForms* updated_entries) {
127   for (std::vector<autofill::PasswordForm*>::const_iterator it =
128            new_entries->begin();
129        it != new_entries->end();
130        ++it) {
131     password_store_->AddLoginImpl(**it);
132   }
133
134   for (std::vector<autofill::PasswordForm*>::const_iterator it =
135            updated_entries->begin();
136        it != updated_entries->end();
137        ++it) {
138     password_store_->UpdateLoginImpl(**it);
139   }
140
141   if (!new_entries->empty() || !updated_entries->empty()) {
142     // We have to notify password store observers of the change by hand since
143     // we use internal password store interfaces to make changes synchronously.
144     password_store_->PostNotifyLoginsChanged();
145   }
146 }
147
148 syncer::SyncData PasswordSyncableService::CreateSyncData(
149     const autofill::PasswordForm& password_form) {
150   sync_pb::EntitySpecifics password_data;
151   sync_pb::PasswordSpecificsData* password_specifics =
152       password_data.mutable_password()->mutable_client_only_encrypted_data();
153   password_specifics->set_scheme(password_form.scheme);
154   password_specifics->set_signon_realm(password_form.signon_realm);
155   password_specifics->set_origin(password_form.origin.spec());
156   password_specifics->set_action(password_form.action.spec());
157   password_specifics->set_username_element(
158       UTF16ToUTF8(password_form.username_element));
159   password_specifics->set_password_element(
160       UTF16ToUTF8(password_form.password_element));
161   password_specifics->set_username_value(
162       UTF16ToUTF8(password_form.username_value));
163   password_specifics->set_password_value(
164       UTF16ToUTF8(password_form.password_value));
165   password_specifics->set_ssl_valid(password_form.ssl_valid);
166   password_specifics->set_preferred(password_form.preferred);
167   password_specifics->set_date_created(
168       password_form.date_created.ToInternalValue());
169   password_specifics->set_blacklisted(password_form.blacklisted_by_user);
170
171   std::string tag = MakeTag(*password_specifics);
172   return syncer::SyncData::CreateLocalData(tag, tag, password_data);
173 }
174
175 // static
176 std::string PasswordSyncableService::MakeTag(
177     const std::string& origin_url,
178     const std::string& username_element,
179     const std::string& username_value,
180     const std::string& password_element,
181     const std::string& signon_realm) {
182   return net::EscapePath(origin_url) + "|" +
183          net::EscapePath(username_element) + "|" +
184          net::EscapePath(username_value) + "|" +
185          net::EscapePath(password_element) + "|" +
186          net::EscapePath(signon_realm);
187 }
188
189 // static
190 std::string PasswordSyncableService::MakeTag(
191     const autofill::PasswordForm& password) {
192   return MakeTag(password.origin.spec(),
193                  UTF16ToUTF8(password.username_element),
194                  UTF16ToUTF8(password.username_value),
195                  UTF16ToUTF8(password.password_element),
196                  password.signon_realm);
197 }
198
199 // static
200 std::string PasswordSyncableService::MakeTag(
201     const sync_pb::PasswordSpecificsData& password) {
202   return MakeTag(password.origin(),
203                  password.username_element(),
204                  password.username_value(),
205                  password.password_element(),
206                  password.signon_realm());
207 }
208