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

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

Powered by Google App Engine
This is Rietveld 408576698