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

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: Removed import-complete dialog. 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"
16 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/sync/profile_sync_service_factory.h" 21 #include "chrome/browser/sync/profile_sync_service_factory.h"
22 #if defined(OS_WIN) && defined(USE_ASH)
23 #include "chrome/browser/ui/ash/ash_util.h"
vabr (Chromium) 2016/03/10 10:53:31 nit: Please move this #ifdefed #include into the s
xunlu 2016/03/16 07:23:58 Done.
24 #endif
25 #include "chrome/browser/ui/chrome_select_file_policy.h"
18 #include "chrome/common/pref_names.h" 26 #include "chrome/common/pref_names.h"
19 #include "chrome/common/url_constants.h" 27 #include "chrome/common/url_constants.h"
20 #include "chrome/grit/generated_resources.h" 28 #include "chrome/grit/generated_resources.h"
21 #include "components/autofill/core/common/password_form.h" 29 #include "components/autofill/core/common/password_form.h"
22 #include "components/browser_sync/browser/profile_sync_service.h" 30 #include "components/browser_sync/browser/profile_sync_service.h"
31 #include "components/password_manager/core/browser/export/password_exporter.h"
23 #include "components/password_manager/core/browser/password_bubble_experiment.h" 32 #include "components/password_manager/core/browser/password_bubble_experiment.h"
24 #include "components/password_manager/core/browser/password_manager_constants.h" 33 #include "components/password_manager/core/browser/password_manager_constants.h"
34 #include "components/password_manager/core/browser/password_store.h"
25 #include "components/password_manager/core/browser/password_ui_utils.h" 35 #include "components/password_manager/core/browser/password_ui_utils.h"
26 #include "components/password_manager/core/common/experiments.h" 36 #include "components/password_manager/core/common/experiments.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 23 matching lines...) Expand all
63 url_formatter::FormatUrl( 74 url_formatter::FormatUrl(
64 form.origin, languages, url_formatter::kFormatUrlOmitNothing, 75 form.origin, languages, url_formatter::kFormatUrlOmitNothing,
65 net::UnescapeRule::SPACES, nullptr, nullptr, nullptr)); 76 net::UnescapeRule::SPACES, nullptr, nullptr, nullptr));
66 bool is_android_uri = false; 77 bool is_android_uri = false;
67 entry->SetString(kShownUrlField, password_manager::GetShownOrigin( 78 entry->SetString(kShownUrlField, password_manager::GetShownOrigin(
68 form, languages, &is_android_uri)); 79 form, languages, &is_android_uri));
69 entry->SetBoolean(kIsAndroidUriField, is_android_uri); 80 entry->SetBoolean(kIsAndroidUriField, is_android_uri);
70 entry->SetBoolean(kIsSecureField, content::IsOriginSecure(form.origin)); 81 entry->SetBoolean(kIsSecureField, content::IsOriginSecure(form.origin));
71 } 82 }
72 83
84 // Enumeration of different callers of SelectFile. Starting count at 1 so
85 // accidental call of SelectFile with params=NULL will error out.
86 enum FileSelectorCaller {
87 IMPORT_FILE_SELECTED = 1,
88 EXPORT_FILE_SELECTED,
89 };
90
73 } // namespace 91 } // namespace
74 92
75 PasswordManagerHandler::PasswordManagerHandler() 93 PasswordManagerHandler::PasswordManagerHandler() {
76 : password_manager_presenter_(this) {} 94 password_manager_presenter_.reset(new PasswordManagerPresenter(this));
95 }
96
97 PasswordManagerHandler::PasswordManagerHandler(
98 PasswordManagerPresenter* presenter) {
99 password_manager_presenter_.reset(presenter);
100 }
77 101
78 PasswordManagerHandler::~PasswordManagerHandler() {} 102 PasswordManagerHandler::~PasswordManagerHandler() {}
79 103
80 Profile* PasswordManagerHandler::GetProfile() { 104 Profile* PasswordManagerHandler::GetProfile() {
81 return Profile::FromWebUI(web_ui()); 105 return Profile::FromWebUI(web_ui());
82 } 106 }
83 107
84 #if !defined(OS_ANDROID) 108 #if !defined(OS_ANDROID)
85 gfx::NativeWindow PasswordManagerHandler::GetNativeWindow() const { 109 gfx::NativeWindow PasswordManagerHandler::GetNativeWindow() const {
86 return web_ui()->GetWebContents()->GetTopLevelNativeWindow(); 110 return web_ui()->GetWebContents()->GetTopLevelNativeWindow();
87 } 111 }
88 #endif 112 #endif
89 113
90 void PasswordManagerHandler::GetLocalizedValues( 114 void PasswordManagerHandler::GetLocalizedValues(
91 base::DictionaryValue* localized_strings) { 115 base::DictionaryValue* localized_strings) {
92 DCHECK(localized_strings); 116 DCHECK(localized_strings);
93 117
94 static const OptionsStringResource resources[] = { 118 static const OptionsStringResource resources[] = {
95 {"autoSigninTitle", IDS_PASSWORDS_AUTO_SIGNIN_TITLE}, 119 {"autoSigninTitle", IDS_PASSWORDS_AUTO_SIGNIN_TITLE},
96 {"autoSigninDescription", IDS_PASSWORDS_AUTO_SIGNIN_DESCRIPTION}, 120 {"autoSigninDescription", IDS_PASSWORDS_AUTO_SIGNIN_DESCRIPTION},
97 {"savedPasswordsTitle", IDS_PASSWORD_MANAGER_SHOW_PASSWORDS_TAB_TITLE}, 121 {"savedPasswordsTitle", IDS_PASSWORD_MANAGER_SHOW_PASSWORDS_TAB_TITLE},
98 {"passwordExceptionsTitle", IDS_PASSWORD_MANAGER_EXCEPTIONS_TAB_TITLE}, 122 {"passwordExceptionsTitle", IDS_PASSWORD_MANAGER_EXCEPTIONS_TAB_TITLE},
99 {"passwordSearchPlaceholder", IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS}, 123 {"passwordSearchPlaceholder", IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS},
100 {"passwordShowButton", IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON}, 124 {"passwordShowButton", IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON},
101 {"passwordHideButton", IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON}, 125 {"passwordHideButton", IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON},
102 {"passwordsNoPasswordsDescription", 126 {"passwordsNoPasswordsDescription",
103 IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION}, 127 IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION},
104 {"passwordsNoExceptionsDescription", 128 {"passwordsNoExceptionsDescription",
105 IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION}, 129 IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION},
130 {"passwordManagerImportPasswordButtonText",
131 IDS_PASSWORD_MANAGER_IMPORT_BUTTON},
132 {"passwordManagerExportPasswordButtonText",
133 IDS_PASSWORD_MANAGER_EXPORT_BUTTON},
106 }; 134 };
107 135
108 RegisterStrings(localized_strings, resources, arraysize(resources)); 136 RegisterStrings(localized_strings, resources, arraysize(resources));
109 137
110 const ProfileSyncService* sync_service = 138 const ProfileSyncService* sync_service =
111 ProfileSyncServiceFactory::GetForProfile(GetProfile()); 139 ProfileSyncServiceFactory::GetForProfile(GetProfile());
112 int title_id = 140 int title_id =
113 password_bubble_experiment::IsSmartLockBrandingEnabled(sync_service) 141 password_bubble_experiment::IsSmartLockBrandingEnabled(sync_service)
114 ? IDS_PASSWORD_MANAGER_SMART_LOCK_FOR_PASSWORDS 142 ? IDS_PASSWORD_MANAGER_SMART_LOCK_FOR_PASSWORDS
115 : IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE; 143 : IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 base::Bind(&PasswordManagerHandler::HandleRemoveSavedPassword, 190 base::Bind(&PasswordManagerHandler::HandleRemoveSavedPassword,
163 base::Unretained(this))); 191 base::Unretained(this)));
164 web_ui()->RegisterMessageCallback( 192 web_ui()->RegisterMessageCallback(
165 "removePasswordException", 193 "removePasswordException",
166 base::Bind(&PasswordManagerHandler::HandleRemovePasswordException, 194 base::Bind(&PasswordManagerHandler::HandleRemovePasswordException,
167 base::Unretained(this))); 195 base::Unretained(this)));
168 web_ui()->RegisterMessageCallback( 196 web_ui()->RegisterMessageCallback(
169 "requestShowPassword", 197 "requestShowPassword",
170 base::Bind(&PasswordManagerHandler::HandleRequestShowPassword, 198 base::Bind(&PasswordManagerHandler::HandleRequestShowPassword,
171 base::Unretained(this))); 199 base::Unretained(this)));
200 web_ui()->RegisterMessageCallback(
201 "importPassword",
202 base::Bind(&PasswordManagerHandler::HandlePasswordImport,
203 base::Unretained(this)));
204 web_ui()->RegisterMessageCallback(
205 "exportPassword",
206 base::Bind(&PasswordManagerHandler::HandlePasswordExport,
207 base::Unretained(this)));
172 } 208 }
173 209
174 void PasswordManagerHandler::InitializeHandler() { 210 void PasswordManagerHandler::InitializeHandler() {
175 password_manager_presenter_.Initialize(); 211 password_manager_presenter_->Initialize();
212 }
213
214 void PasswordManagerHandler::InitializePage() {
215 if (password_manager::ImportExportExperimentEnabled())
216 web_ui()->CallJavascriptFunction("PasswordManager.showImportExportButton");
176 } 217 }
177 218
178 void PasswordManagerHandler::HandleRemoveSavedPassword( 219 void PasswordManagerHandler::HandleRemoveSavedPassword(
179 const base::ListValue* args) { 220 const base::ListValue* args) {
180 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); 221 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args));
181 int index; 222 int index;
182 if (base::StringToInt(string_value, &index) && index >= 0) { 223 if (base::StringToInt(string_value, &index) && index >= 0) {
183 password_manager_presenter_.RemoveSavedPassword(static_cast<size_t>(index)); 224 password_manager_presenter_->RemoveSavedPassword(
225 static_cast<size_t>(index));
184 } 226 }
185 } 227 }
186 228
187 void PasswordManagerHandler::HandleRemovePasswordException( 229 void PasswordManagerHandler::HandleRemovePasswordException(
188 const base::ListValue* args) { 230 const base::ListValue* args) {
189 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); 231 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args));
190 int index; 232 int index;
191 if (base::StringToInt(string_value, &index) && index >= 0) { 233 if (base::StringToInt(string_value, &index) && index >= 0) {
192 password_manager_presenter_.RemovePasswordException( 234 password_manager_presenter_->RemovePasswordException(
193 static_cast<size_t>(index)); 235 static_cast<size_t>(index));
194 } 236 }
195 } 237 }
196 238
197 void PasswordManagerHandler::HandleRequestShowPassword( 239 void PasswordManagerHandler::HandleRequestShowPassword(
198 const base::ListValue* args) { 240 const base::ListValue* args) {
199 int index; 241 int index;
200 if (!ExtractIntegerValue(args, &index)) 242 if (!ExtractIntegerValue(args, &index))
201 NOTREACHED(); 243 NOTREACHED();
202 244
203 password_manager_presenter_.RequestShowPassword(static_cast<size_t>(index)); 245 password_manager_presenter_->RequestShowPassword(static_cast<size_t>(index));
204 } 246 }
205 247
206 void PasswordManagerHandler::ShowPassword( 248 void PasswordManagerHandler::ShowPassword(
207 size_t index, 249 size_t index,
208 const std::string& origin_url, 250 const std::string& origin_url,
209 const std::string& username, 251 const std::string& username,
210 const base::string16& password_value) { 252 const base::string16& password_value) {
211 // Call back the front end to reveal the password. 253 // Call back the front end to reveal the password.
212 web_ui()->CallJavascriptFunction( 254 web_ui()->CallJavascriptFunction(
213 "PasswordManager.showPassword", 255 "PasswordManager.showPassword",
214 base::FundamentalValue(static_cast<int>(index)), 256 base::FundamentalValue(static_cast<int>(index)),
215 base::StringValue(password_value)); 257 base::StringValue(password_value));
216 } 258 }
217 259
218 void PasswordManagerHandler::HandleUpdatePasswordLists( 260 void PasswordManagerHandler::HandleUpdatePasswordLists(
219 const base::ListValue* args) { 261 const base::ListValue* args) {
220 password_manager_presenter_.UpdatePasswordLists(); 262 password_manager_presenter_->UpdatePasswordLists();
221 } 263 }
222 264
223 void PasswordManagerHandler::SetPasswordList( 265 void PasswordManagerHandler::SetPasswordList(
224 const std::vector<scoped_ptr<autofill::PasswordForm>>& password_list, 266 const std::vector<scoped_ptr<autofill::PasswordForm>>& password_list,
225 bool show_passwords) { 267 bool show_passwords) {
226 base::ListValue entries; 268 base::ListValue entries;
227 languages_ = GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages); 269 languages_ = GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages);
228 base::string16 placeholder(base::ASCIIToUTF16(" ")); 270 base::string16 placeholder(base::ASCIIToUTF16(" "));
229 for (const auto& saved_password : password_list) { 271 for (const auto& saved_password : password_list) {
230 scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue); 272 scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
(...skipping 30 matching lines...) Expand all
261 for (const auto& exception : password_exception_list) { 303 for (const auto& exception : password_exception_list) {
262 scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue); 304 scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
263 CopyOriginInfoOfPasswordForm(*exception, languages_, entry.get()); 305 CopyOriginInfoOfPasswordForm(*exception, languages_, entry.get());
264 entries.Append(entry.release()); 306 entries.Append(entry.release());
265 } 307 }
266 308
267 web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList", 309 web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList",
268 entries); 310 entries);
269 } 311 }
270 312
313 void PasswordManagerHandler::FileSelected(const base::FilePath& path,
314 int index,
315 void* params) {
316 switch (static_cast<FileSelectorCaller>(reinterpret_cast<intptr_t>(params))) {
317 case IMPORT_FILE_SELECTED:
318 ImportPasswordFileSelected(path);
319 break;
320 case EXPORT_FILE_SELECTED:
321 ExportPasswordFileSelected(path);
322 break;
323 }
324 }
325
326 void PasswordManagerHandler::HandlePasswordImport(const base::ListValue* args) {
327 #if !defined(OS_ANDROID) // This is never called on Android.
328 ui::SelectFileDialog::FileTypeInfo file_type_info;
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 password_manager::PasswordImporter::Import(
348 path, content::BrowserThread::GetMessageLoopProxyForThread(
349 content::BrowserThread::FILE)
350 .get(),
351 base::Bind(&PasswordManagerHandler::ImportPasswordFileRead,
vabr (Chromium) 2016/03/10 10:53:31 What happens when the user closes the settings pag
xunlu 2016/03/16 07:23:58 Maybe not, but the other options here(https://www.
vabr (Chromium) 2016/03/16 17:48:28 My suggestion is to split the functionality: Inste
xunlu 2016/03/18 21:15:30 There is a problem: ImportPasswordFileRead needs t
vabr (Chromium) 2016/03/21 14:01:30 Yes, Profile definitely outlives the handler objec
xunlu 2016/03/22 07:17:15 Done.
352 base::Unretained(this)));
353 }
354
355 void PasswordManagerHandler::ImportPasswordFileRead(
356 password_manager::PasswordImporter::Result result,
357 const std::vector<autofill::PasswordForm>& forms) {
358 UMA_HISTOGRAM_ENUMERATION("PasswordManager.ImportPasswordFromCSVResult",
359 result,
360 password_manager::PasswordImporter::SEMANTIC_ERROR);
vabr (Chromium) 2016/03/10 10:53:31 Please do not hard-code the fact that SEMANTIC_ERR
xunlu 2016/03/16 07:23:58 Done.
361 if (result != password_manager::PasswordImporter::SUCCESS)
362 return;
363
364 UMA_HISTOGRAM_COUNTS("PasswordManager.ImportedPasswordsPerUserInCSV",
365 forms.size());
366
367 password_manager::PasswordStore* store =
368 password_manager_presenter_->GetPasswordStore();
vabr (Chromium) 2016/03/10 10:53:31 Could you use PasswordStoreFactory::GetForProfile
xunlu 2016/03/16 07:23:58 Done.
369 if (store) {
370 for (const autofill::PasswordForm& form : forms) {
371 store->AddLogin(form);
372 }
373 } else {
374 UMA_HISTOGRAM_COUNTS("PasswordManager.FailToStorePasswordImportedFromCSV",
375 1);
376 }
377 }
378
379 void PasswordManagerHandler::HandlePasswordExport(const base::ListValue* args) {
380 #if !defined(OS_ANDROID) // This is never called on Android.
381 if (!password_manager_presenter_->IsUserAuthenticated()) {
382 return;
383 }
384 ui::SelectFileDialog::FileTypeInfo file_type_info;
385 file_type_info.extensions =
386 password_manager::PasswordExporter::GetSupportedFileExtensions();
387 DCHECK(!file_type_info.extensions.empty() &&
388 !file_type_info.extensions[0].empty());
389 file_type_info.include_all_files = true;
390 selected_file_dialog_ = ui::SelectFileDialog::Create(
391 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
392 selected_file_dialog_->SelectFile(
393 ui::SelectFileDialog::SELECT_SAVEAS_FILE,
394 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE),
395 base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0],
396 GetNativeWindow(), reinterpret_cast<void*>(EXPORT_FILE_SELECTED));
397 #endif
398 }
399
400 void PasswordManagerHandler::ExportPasswordFileSelected(
401 const base::FilePath& path) {
402 std::vector<scoped_ptr<autofill::PasswordForm>> password_list =
403 password_manager_presenter_->GetAllPasswords();
404 UMA_HISTOGRAM_COUNTS("PasswordManager.ExportedPasswordsPerUserInCSV",
405 password_list.size());
406 password_manager::PasswordExporter::Export(
407 path, std::move(password_list),
408 content::BrowserThread::GetMessageLoopProxyForThread(
409 content::BrowserThread::FILE)
410 .get(),
411 base::Closure());
412 }
413
271 } // namespace options 414 } // namespace options
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698