Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / components / password_manager / core / browser / password_autofill_manager.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 "components/password_manager/core/browser/password_autofill_manager.h"
6
7 #include <vector>
8
9 #include "base/logging.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "components/autofill/core/browser/autofill_driver.h"
14 #include "components/autofill/core/browser/popup_item_ids.h"
15 #include "components/autofill/core/common/autofill_data_validation.h"
16 #include "components/password_manager/core/browser/password_manager_client.h"
17 #include "components/password_manager/core/browser/password_manager_driver.h"
18
19 namespace password_manager {
20
21 namespace {
22
23 // This function attempts to fill |suggestions| and |realms| form |fill_data|
24 // based on |current_username|. Unless |show_all| is true, it only picks
25 // suggestions where the username has |current_username| as a prefix.
26 void GetSuggestions(const autofill::PasswordFormFillData& fill_data,
27                     const base::string16& current_username,
28                     std::vector<base::string16>* suggestions,
29                     std::vector<base::string16>* realms,
30                     bool show_all) {
31   if (show_all ||
32       StartsWith(
33           fill_data.basic_data.fields[0].value, current_username, false)) {
34     suggestions->push_back(fill_data.basic_data.fields[0].value);
35     realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm));
36   }
37
38   for (const auto& login : fill_data.additional_logins) {
39     if (show_all || StartsWith(login.first, current_username, false)) {
40       suggestions->push_back(login.first);
41       realms->push_back(base::UTF8ToUTF16(login.second.realm));
42     }
43   }
44
45   for (const auto& usernames : fill_data.other_possible_usernames) {
46     for (size_t i = 0; i < usernames.second.size(); ++i) {
47       if (show_all ||
48           StartsWith(usernames.second[i], current_username, false)) {
49         suggestions->push_back(usernames.second[i]);
50         realms->push_back(base::UTF8ToUTF16(usernames.first.realm));
51       }
52     }
53   }
54 }
55
56 }  // namespace
57
58 ////////////////////////////////////////////////////////////////////////////////
59 // PasswordAutofillManager, public:
60
61 PasswordAutofillManager::PasswordAutofillManager(
62     PasswordManagerClient* password_manager_client,
63     autofill::AutofillClient* autofill_client)
64     : password_manager_client_(password_manager_client),
65       autofill_client_(autofill_client),
66       weak_ptr_factory_(this) {
67 }
68
69 PasswordAutofillManager::~PasswordAutofillManager() {
70 }
71
72 bool PasswordAutofillManager::FillSuggestion(int key,
73                                              const base::string16& username) {
74   autofill::PasswordFormFillData fill_data;
75   base::string16 password;
76   if (FindLoginInfo(key, &fill_data) &&
77       GetPasswordForUsername(username, fill_data, &password)) {
78     PasswordManagerDriver* driver = password_manager_client_->GetDriver();
79     driver->FillSuggestion(username, password);
80     return true;
81   }
82   return false;
83 }
84
85 bool PasswordAutofillManager::PreviewSuggestion(
86     int key,
87     const base::string16& username) {
88   autofill::PasswordFormFillData fill_data;
89   base::string16 password;
90   if (FindLoginInfo(key, &fill_data) &&
91       GetPasswordForUsername(username, fill_data, &password)) {
92     PasswordManagerDriver* driver = password_manager_client_->GetDriver();
93     driver->PreviewSuggestion(username, password);
94     return true;
95   }
96   return false;
97 }
98
99 void PasswordAutofillManager::OnAddPasswordFormMapping(
100     int key,
101     const autofill::PasswordFormFillData& fill_data) {
102   if (!autofill::IsValidPasswordFormFillData(fill_data))
103     return;
104
105   login_to_password_info_[key] = fill_data;
106 }
107
108 void PasswordAutofillManager::OnShowPasswordSuggestions(
109     int key,
110     base::i18n::TextDirection text_direction,
111     const base::string16& typed_username,
112     bool show_all,
113     const gfx::RectF& bounds) {
114   std::vector<base::string16> suggestions;
115   std::vector<base::string16> realms;
116   LoginToPasswordInfoMap::const_iterator fill_data_it =
117       login_to_password_info_.find(key);
118   if (fill_data_it == login_to_password_info_.end()) {
119     // Probably a compromised renderer.
120     NOTREACHED();
121     return;
122   }
123   GetSuggestions(fill_data_it->second, typed_username, &suggestions, &realms,
124                  show_all);
125   DCHECK_EQ(suggestions.size(), realms.size());
126
127   form_data_key_ = key;
128
129   if (suggestions.empty()) {
130     autofill_client_->HideAutofillPopup();
131     return;
132   }
133
134   std::vector<base::string16> empty(suggestions.size());
135   std::vector<int> password_ids(suggestions.size(),
136                                 autofill::POPUP_ITEM_ID_PASSWORD_ENTRY);
137   autofill_client_->ShowAutofillPopup(bounds,
138                                       text_direction,
139                                       suggestions,
140                                       realms,
141                                       empty,
142                                       password_ids,
143                                       weak_ptr_factory_.GetWeakPtr());
144 }
145
146 void PasswordAutofillManager::Reset() {
147   login_to_password_info_.clear();
148 }
149
150 bool PasswordAutofillManager::FillSuggestionForTest(
151     int key,
152     const base::string16& username) {
153   return FillSuggestion(key, username);
154 }
155
156 bool PasswordAutofillManager::PreviewSuggestionForTest(
157     int key,
158     const base::string16& username) {
159   return PreviewSuggestion(key, username);
160 }
161
162 void PasswordAutofillManager::OnPopupShown() {
163 }
164
165 void PasswordAutofillManager::OnPopupHidden() {
166 }
167
168 void PasswordAutofillManager::DidSelectSuggestion(const base::string16& value,
169                                                   int identifier) {
170   ClearPreviewedForm();
171   bool success = PreviewSuggestion(form_data_key_, value);
172   DCHECK(success);
173 }
174
175 void PasswordAutofillManager::DidAcceptSuggestion(const base::string16& value,
176                                                   int identifier) {
177   bool success = FillSuggestion(form_data_key_, value);
178   DCHECK(success);
179   autofill_client_->HideAutofillPopup();
180 }
181
182 void PasswordAutofillManager::RemoveSuggestion(const base::string16& value,
183                                                int identifier) {
184   NOTREACHED();
185 }
186
187 void PasswordAutofillManager::ClearPreviewedForm() {
188   PasswordManagerDriver* driver = password_manager_client_->GetDriver();
189   driver->ClearPreviewedForm();
190 }
191
192 ////////////////////////////////////////////////////////////////////////////////
193 // PasswordAutofillManager, private:
194
195 bool PasswordAutofillManager::GetPasswordForUsername(
196     const base::string16& current_username,
197     const autofill::PasswordFormFillData& fill_data,
198     base::string16* password) {
199   // TODO(dubroy): When password access requires some kind of authentication
200   // (e.g. Keychain access on Mac OS), use |password_manager_client_| here to
201   // fetch the actual password. See crbug.com/178358 for more context.
202
203   // Look for any suitable matches to current field text.
204   if (fill_data.basic_data.fields[0].value == current_username) {
205     *password = fill_data.basic_data.fields[1].value;
206     return true;
207   }
208
209   // Scan additional logins for a match.
210   for (autofill::PasswordFormFillData::LoginCollection::const_iterator iter =
211            fill_data.additional_logins.begin();
212        iter != fill_data.additional_logins.end();
213        ++iter) {
214     if (iter->first == current_username) {
215       *password = iter->second.password;
216       return true;
217     }
218   }
219
220   for (autofill::PasswordFormFillData::UsernamesCollection::const_iterator
221            usernames_iter = fill_data.other_possible_usernames.begin();
222        usernames_iter != fill_data.other_possible_usernames.end();
223        ++usernames_iter) {
224     for (size_t i = 0; i < usernames_iter->second.size(); ++i) {
225       if (usernames_iter->second[i] == current_username) {
226         *password = usernames_iter->first.password;
227         return true;
228       }
229     }
230   }
231
232   return false;
233 }
234
235 bool PasswordAutofillManager::FindLoginInfo(
236     int key,
237     autofill::PasswordFormFillData* found_password) {
238   LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(key);
239   if (iter == login_to_password_info_.end())
240     return false;
241
242   *found_password = iter->second;
243   return true;
244 }
245
246 }  //  namespace password_manager