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

Side by Side Diff: chrome/browser/ui/webui/options/password_manager_handler.cc

Issue 1193143003: Enable import/export of passwords into/from Password Manager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 9 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
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/ui/webui/options/password_manager_handler.h" 5 #include "chrome/browser/ui/webui/options/password_manager_handler.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h"
8 #include "base/feature_list.h" 9 #include "base/feature_list.h"
10 #include "base/files/file_path.h"
9 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/metrics/histogram.h"
10 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_split.h" 15 #include "base/strings/string_split.h"
12 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h" 17 #include "base/values.h"
14 #include "build/build_config.h" 18 #include "build/build_config.h"
15 #include "chrome/browser/chrome_notification_types.h" 19 #include "chrome/browser/chrome_notification_types.h"
20 #include "chrome/browser/password_manager/password_store_factory.h"
16 #include "chrome/browser/profiles/profile.h" 21 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/sync/profile_sync_service_factory.h" 22 #include "chrome/browser/sync/profile_sync_service_factory.h"
23 #include "chrome/browser/ui/chrome_select_file_policy.h"
18 #include "chrome/common/pref_names.h" 24 #include "chrome/common/pref_names.h"
19 #include "chrome/common/url_constants.h" 25 #include "chrome/common/url_constants.h"
20 #include "chrome/grit/generated_resources.h" 26 #include "chrome/grit/generated_resources.h"
21 #include "components/autofill/core/common/password_form.h" 27 #include "components/autofill/core/common/password_form.h"
22 #include "components/browser_sync/browser/profile_sync_service.h" 28 #include "components/browser_sync/browser/profile_sync_service.h"
29 #include "components/password_manager/core/browser/export/password_exporter.h"
23 #include "components/password_manager/core/browser/password_bubble_experiment.h" 30 #include "components/password_manager/core/browser/password_bubble_experiment.h"
24 #include "components/password_manager/core/browser/password_manager_constants.h" 31 #include "components/password_manager/core/browser/password_manager_constants.h"
32 #include "components/password_manager/core/browser/password_store.h"
25 #include "components/password_manager/core/browser/password_ui_utils.h" 33 #include "components/password_manager/core/browser/password_ui_utils.h"
26 #include "components/password_manager/core/common/experiments.h" 34 #include "components/password_manager/core/common/experiments.h"
35 #include "components/password_manager/core/common/password_manager_features.h"
27 #include "components/prefs/pref_service.h" 36 #include "components/prefs/pref_service.h"
28 #include "components/strings/grit/components_strings.h" 37 #include "components/strings/grit/components_strings.h"
29 #include "components/url_formatter/url_formatter.h" 38 #include "components/url_formatter/url_formatter.h"
39 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/notification_details.h" 40 #include "content/public/browser/notification_details.h"
31 #include "content/public/browser/notification_source.h" 41 #include "content/public/browser/notification_source.h"
32 #include "content/public/browser/user_metrics.h" 42 #include "content/public/browser/user_metrics.h"
33 #include "content/public/browser/web_contents.h" 43 #include "content/public/browser/web_contents.h"
34 #include "content/public/browser/web_ui.h" 44 #include "content/public/browser/web_ui.h"
35 #include "content/public/common/content_features.h" 45 #include "content/public/common/content_features.h"
36 #include "content/public/common/origin_util.h" 46 #include "content/public/common/origin_util.h"
37 #include "ui/base/l10n/l10n_util.h" 47 #include "ui/base/l10n/l10n_util.h"
38 48
39 #if defined(OS_WIN) && defined(USE_ASH) 49 #if defined(OS_WIN) && defined(USE_ASH)
(...skipping 23 matching lines...) Expand all
63 url_formatter::FormatUrl( 73 url_formatter::FormatUrl(
64 form.origin, languages, url_formatter::kFormatUrlOmitNothing, 74 form.origin, languages, url_formatter::kFormatUrlOmitNothing,
65 net::UnescapeRule::SPACES, nullptr, nullptr, nullptr)); 75 net::UnescapeRule::SPACES, nullptr, nullptr, nullptr));
66 bool is_android_uri = false; 76 bool is_android_uri = false;
67 entry->SetString(kShownUrlField, password_manager::GetShownOrigin( 77 entry->SetString(kShownUrlField, password_manager::GetShownOrigin(
68 form, languages, &is_android_uri)); 78 form, languages, &is_android_uri));
69 entry->SetBoolean(kIsAndroidUriField, is_android_uri); 79 entry->SetBoolean(kIsAndroidUriField, is_android_uri);
70 entry->SetBoolean(kIsSecureField, content::IsOriginSecure(form.origin)); 80 entry->SetBoolean(kIsSecureField, content::IsOriginSecure(form.origin));
71 } 81 }
72 82
83 // Enumeration of different callers of SelectFile. Starting count at 1 so
84 // accidental call of SelectFile with params=NULL will error out.
85 enum FileSelectorCaller {
86 IMPORT_FILE_SELECTED = 1,
87 EXPORT_FILE_SELECTED,
88 };
89
73 } // namespace 90 } // namespace
74 91
75 PasswordManagerHandler::PasswordManagerHandler() 92 PasswordManagerHandler::PasswordManagerHandler() {
76 : password_manager_presenter_(this) {} 93 password_manager_presenter_.reset(new PasswordManagerPresenter(this));
94 }
95
96 PasswordManagerHandler::PasswordManagerHandler(
97 scoped_ptr<PasswordManagerPresenter> presenter)
98 : password_manager_presenter_(std::move(presenter)) {}
77 99
78 PasswordManagerHandler::~PasswordManagerHandler() {} 100 PasswordManagerHandler::~PasswordManagerHandler() {}
79 101
80 Profile* PasswordManagerHandler::GetProfile() { 102 Profile* PasswordManagerHandler::GetProfile() {
81 return Profile::FromWebUI(web_ui()); 103 return Profile::FromWebUI(web_ui());
82 } 104 }
83 105
84 #if !defined(OS_ANDROID) 106 #if !defined(OS_ANDROID)
85 gfx::NativeWindow PasswordManagerHandler::GetNativeWindow() const { 107 gfx::NativeWindow PasswordManagerHandler::GetNativeWindow() const {
86 return web_ui()->GetWebContents()->GetTopLevelNativeWindow(); 108 return web_ui()->GetWebContents()->GetTopLevelNativeWindow();
87 } 109 }
88 #endif 110 #endif
89 111
90 void PasswordManagerHandler::GetLocalizedValues( 112 void PasswordManagerHandler::GetLocalizedValues(
91 base::DictionaryValue* localized_strings) { 113 base::DictionaryValue* localized_strings) {
92 DCHECK(localized_strings); 114 DCHECK(localized_strings);
93 115
94 static const OptionsStringResource resources[] = { 116 static const OptionsStringResource resources[] = {
95 {"autoSigninTitle", IDS_PASSWORDS_AUTO_SIGNIN_TITLE}, 117 {"autoSigninTitle", IDS_PASSWORDS_AUTO_SIGNIN_TITLE},
96 {"autoSigninDescription", IDS_PASSWORDS_AUTO_SIGNIN_DESCRIPTION}, 118 {"autoSigninDescription", IDS_PASSWORDS_AUTO_SIGNIN_DESCRIPTION},
97 {"savedPasswordsTitle", IDS_PASSWORD_MANAGER_SHOW_PASSWORDS_TAB_TITLE}, 119 {"savedPasswordsTitle", IDS_PASSWORD_MANAGER_SHOW_PASSWORDS_TAB_TITLE},
98 {"passwordExceptionsTitle", IDS_PASSWORD_MANAGER_EXCEPTIONS_TAB_TITLE}, 120 {"passwordExceptionsTitle", IDS_PASSWORD_MANAGER_EXCEPTIONS_TAB_TITLE},
99 {"passwordSearchPlaceholder", IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS}, 121 {"passwordSearchPlaceholder", IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS},
100 {"passwordShowButton", IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON}, 122 {"passwordShowButton", IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON},
101 {"passwordHideButton", IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON}, 123 {"passwordHideButton", IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON},
102 {"passwordsNoPasswordsDescription", 124 {"passwordsNoPasswordsDescription",
103 IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION}, 125 IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION},
104 {"passwordsNoExceptionsDescription", 126 {"passwordsNoExceptionsDescription",
105 IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION}, 127 IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION},
128 {"passwordManagerImportPasswordButtonText",
129 IDS_PASSWORD_MANAGER_IMPORT_BUTTON},
130 {"passwordManagerExportPasswordButtonText",
131 IDS_PASSWORD_MANAGER_EXPORT_BUTTON},
106 }; 132 };
107 133
108 RegisterStrings(localized_strings, resources, arraysize(resources)); 134 RegisterStrings(localized_strings, resources, arraysize(resources));
109 135
110 const ProfileSyncService* sync_service = 136 const ProfileSyncService* sync_service =
111 ProfileSyncServiceFactory::GetForProfile(GetProfile()); 137 ProfileSyncServiceFactory::GetForProfile(GetProfile());
112 int title_id = 138 int title_id =
113 password_bubble_experiment::IsSmartLockBrandingEnabled(sync_service) 139 password_bubble_experiment::IsSmartLockBrandingEnabled(sync_service)
114 ? IDS_PASSWORD_MANAGER_SMART_LOCK_FOR_PASSWORDS 140 ? IDS_PASSWORD_MANAGER_SMART_LOCK_FOR_PASSWORDS
115 : IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE; 141 : IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 base::Bind(&PasswordManagerHandler::HandleRemoveSavedPassword, 188 base::Bind(&PasswordManagerHandler::HandleRemoveSavedPassword,
163 base::Unretained(this))); 189 base::Unretained(this)));
164 web_ui()->RegisterMessageCallback( 190 web_ui()->RegisterMessageCallback(
165 "removePasswordException", 191 "removePasswordException",
166 base::Bind(&PasswordManagerHandler::HandleRemovePasswordException, 192 base::Bind(&PasswordManagerHandler::HandleRemovePasswordException,
167 base::Unretained(this))); 193 base::Unretained(this)));
168 web_ui()->RegisterMessageCallback( 194 web_ui()->RegisterMessageCallback(
169 "requestShowPassword", 195 "requestShowPassword",
170 base::Bind(&PasswordManagerHandler::HandleRequestShowPassword, 196 base::Bind(&PasswordManagerHandler::HandleRequestShowPassword,
171 base::Unretained(this))); 197 base::Unretained(this)));
198 web_ui()->RegisterMessageCallback(
199 "importPassword",
200 base::Bind(&PasswordManagerHandler::HandlePasswordImport,
201 base::Unretained(this)));
202 web_ui()->RegisterMessageCallback(
203 "exportPassword",
204 base::Bind(&PasswordManagerHandler::HandlePasswordExport,
205 base::Unretained(this)));
172 } 206 }
173 207
174 void PasswordManagerHandler::InitializeHandler() { 208 void PasswordManagerHandler::InitializeHandler() {
175 password_manager_presenter_.Initialize(); 209 password_manager_presenter_->Initialize();
210 }
211
212 void PasswordManagerHandler::InitializePage() {
213 if (base::FeatureList::IsEnabled(
214 password_manager::features::kPasswordImportExport))
215 web_ui()->CallJavascriptFunction("PasswordManager.showImportExportButton");
176 } 216 }
177 217
178 void PasswordManagerHandler::HandleRemoveSavedPassword( 218 void PasswordManagerHandler::HandleRemoveSavedPassword(
179 const base::ListValue* args) { 219 const base::ListValue* args) {
180 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); 220 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args));
181 int index; 221 int index;
182 if (base::StringToInt(string_value, &index) && index >= 0) { 222 if (base::StringToInt(string_value, &index) && index >= 0) {
183 password_manager_presenter_.RemoveSavedPassword(static_cast<size_t>(index)); 223 password_manager_presenter_->RemoveSavedPassword(
224 static_cast<size_t>(index));
184 } 225 }
185 } 226 }
186 227
187 void PasswordManagerHandler::HandleRemovePasswordException( 228 void PasswordManagerHandler::HandleRemovePasswordException(
188 const base::ListValue* args) { 229 const base::ListValue* args) {
189 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); 230 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args));
190 int index; 231 int index;
191 if (base::StringToInt(string_value, &index) && index >= 0) { 232 if (base::StringToInt(string_value, &index) && index >= 0) {
192 password_manager_presenter_.RemovePasswordException( 233 password_manager_presenter_->RemovePasswordException(
193 static_cast<size_t>(index)); 234 static_cast<size_t>(index));
194 } 235 }
195 } 236 }
196 237
197 void PasswordManagerHandler::HandleRequestShowPassword( 238 void PasswordManagerHandler::HandleRequestShowPassword(
198 const base::ListValue* args) { 239 const base::ListValue* args) {
199 int index; 240 int index;
200 if (!ExtractIntegerValue(args, &index)) 241 if (!ExtractIntegerValue(args, &index))
201 NOTREACHED(); 242 NOTREACHED();
202 243
203 password_manager_presenter_.RequestShowPassword(static_cast<size_t>(index)); 244 password_manager_presenter_->RequestShowPassword(static_cast<size_t>(index));
204 } 245 }
205 246
206 void PasswordManagerHandler::ShowPassword( 247 void PasswordManagerHandler::ShowPassword(
207 size_t index, 248 size_t index,
208 const std::string& origin_url, 249 const std::string& origin_url,
209 const std::string& username, 250 const std::string& username,
210 const base::string16& password_value) { 251 const base::string16& password_value) {
211 // Call back the front end to reveal the password. 252 // Call back the front end to reveal the password.
212 web_ui()->CallJavascriptFunction( 253 web_ui()->CallJavascriptFunction(
213 "PasswordManager.showPassword", 254 "PasswordManager.showPassword",
214 base::FundamentalValue(static_cast<int>(index)), 255 base::FundamentalValue(static_cast<int>(index)),
215 base::StringValue(password_value)); 256 base::StringValue(password_value));
216 } 257 }
217 258
218 void PasswordManagerHandler::HandleUpdatePasswordLists( 259 void PasswordManagerHandler::HandleUpdatePasswordLists(
219 const base::ListValue* args) { 260 const base::ListValue* args) {
220 password_manager_presenter_.UpdatePasswordLists(); 261 password_manager_presenter_->UpdatePasswordLists();
221 } 262 }
222 263
223 void PasswordManagerHandler::SetPasswordList( 264 void PasswordManagerHandler::SetPasswordList(
224 const std::vector<scoped_ptr<autofill::PasswordForm>>& password_list, 265 const std::vector<scoped_ptr<autofill::PasswordForm>>& password_list,
225 bool show_passwords) { 266 bool show_passwords) {
226 base::ListValue entries; 267 base::ListValue entries;
227 languages_ = GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages); 268 languages_ = GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages);
228 base::string16 placeholder(base::ASCIIToUTF16(" ")); 269 base::string16 placeholder(base::ASCIIToUTF16(" "));
229 for (const auto& saved_password : password_list) { 270 for (const auto& saved_password : password_list) {
230 scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue); 271 scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
(...skipping 30 matching lines...) Expand all
261 for (const auto& exception : password_exception_list) { 302 for (const auto& exception : password_exception_list) {
262 scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue); 303 scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
263 CopyOriginInfoOfPasswordForm(*exception, languages_, entry.get()); 304 CopyOriginInfoOfPasswordForm(*exception, languages_, entry.get());
264 entries.Append(entry.release()); 305 entries.Append(entry.release());
265 } 306 }
266 307
267 web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList", 308 web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList",
268 entries); 309 entries);
269 } 310 }
270 311
312 void PasswordManagerHandler::FileSelected(const base::FilePath& path,
313 int index,
314 void* params) {
315 switch (static_cast<FileSelectorCaller>(reinterpret_cast<intptr_t>(params))) {
316 case IMPORT_FILE_SELECTED:
317 ImportPasswordFileSelected(path);
318 break;
319 case EXPORT_FILE_SELECTED:
320 ExportPasswordFileSelected(path);
321 break;
322 }
323 }
324
325 void PasswordManagerHandler::HandlePasswordImport(const base::ListValue* args) {
326 #if !defined(OS_ANDROID) // This is never called on Android.
327 ui::SelectFileDialog::FileTypeInfo file_type_info;
328
329 file_type_info.extensions =
330 password_manager::PasswordImporter::GetSupportedFileExtensions();
331 DCHECK(!file_type_info.extensions.empty() &&
332 !file_type_info.extensions[0].empty());
333 file_type_info.include_all_files = true;
334 selected_file_dialog_ = ui::SelectFileDialog::Create(
335 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
336 selected_file_dialog_->SelectFile(
337 ui::SelectFileDialog::SELECT_OPEN_FILE,
338 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_IMPORT_DIALOG_TITLE),
339 base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0],
340 web_ui()->GetWebContents()->GetTopLevelNativeWindow(),
341 reinterpret_cast<void*>(IMPORT_FILE_SELECTED));
342 #endif
343 }
344
345 void PasswordManagerHandler::ImportPasswordFileSelected(
346 const base::FilePath& path) {
347 scoped_refptr<ImportPasswordResultConsumer> form_consumer(
348 new ImportPasswordResultConsumer(GetProfile()));
349
350 password_manager::PasswordImporter::Import(
351 path, content::BrowserThread::GetMessageLoopProxyForThread(
352 content::BrowserThread::FILE)
353 .get(),
354 base::Bind(&ImportPasswordResultConsumer::ConsumePassword,
355 form_consumer));
356 }
357
358 PasswordManagerHandler::ImportPasswordResultConsumer::
359 ImportPasswordResultConsumer(Profile* profile)
360 : profile_(profile) {}
361
362 void PasswordManagerHandler::ImportPasswordResultConsumer::ConsumePassword(
363 password_manager::PasswordImporter::Result result,
364 const std::vector<autofill::PasswordForm>& forms) {
365 UMA_HISTOGRAM_ENUMERATION(
366 "PasswordManager.ImportPasswordFromCSVResult", result,
367 password_manager::PasswordImporter::NUM_IMPORT_RESULTS);
368 if (result != password_manager::PasswordImporter::SUCCESS)
369 return;
370
371 UMA_HISTOGRAM_COUNTS("PasswordManager.ImportedPasswordsPerUserInCSV",
372 forms.size());
373
374 scoped_refptr<password_manager::PasswordStore> store(
375 PasswordStoreFactory::GetForProfile(profile_,
376 ServiceAccessType::EXPLICIT_ACCESS));
377 if (store) {
378 for (const autofill::PasswordForm& form : forms) {
379 store->AddLogin(form);
380 }
381 } else {
382 UMA_HISTOGRAM_COUNTS("PasswordManager.FailToStorePasswordImportedFromCSV",
Steven Holte 2016/03/23 18:57:39 You should probably use UMA_HISTOGRAM_BOOLEAN here
xunlu 2016/03/24 06:19:30 Done.
383 1);
384 }
385 }
386
387 void PasswordManagerHandler::HandlePasswordExport(const base::ListValue* args) {
388 #if !defined(OS_ANDROID) // This is never called on Android.
389 if (!password_manager_presenter_->IsUserAuthenticated()) {
390 return;
391 }
392 ui::SelectFileDialog::FileTypeInfo file_type_info;
393 file_type_info.extensions =
394 password_manager::PasswordExporter::GetSupportedFileExtensions();
395 DCHECK(!file_type_info.extensions.empty() &&
396 !file_type_info.extensions[0].empty());
397 file_type_info.include_all_files = true;
398 selected_file_dialog_ = ui::SelectFileDialog::Create(
399 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
400 selected_file_dialog_->SelectFile(
401 ui::SelectFileDialog::SELECT_SAVEAS_FILE,
402 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE),
403 base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0],
404 GetNativeWindow(), reinterpret_cast<void*>(EXPORT_FILE_SELECTED));
405 #endif
406 }
407
408 void PasswordManagerHandler::ExportPasswordFileSelected(
409 const base::FilePath& path) {
410 std::vector<scoped_ptr<autofill::PasswordForm>> password_list =
411 password_manager_presenter_->GetAllPasswords();
412 UMA_HISTOGRAM_COUNTS("PasswordManager.ExportedPasswordsPerUserInCSV",
413 password_list.size());
414 password_manager::PasswordExporter::Export(
415 path, std::move(password_list),
416 content::BrowserThread::GetMessageLoopProxyForThread(
417 content::BrowserThread::FILE)
418 .get());
419 }
420
271 } // namespace options 421 } // namespace options
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698