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

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 and comments Created 5 years, 5 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/command_line.h"
9 #include "base/files/file_path.h"
10 #include "base/metrics/histogram.h"
9 #include "base/prefs/pref_service.h" 11 #include "base/prefs/pref_service.h"
10 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_split.h" 13 #include "base/strings/string_split.h"
12 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h" 15 #include "base/values.h"
14 #include "chrome/browser/chrome_notification_types.h" 16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/password_manager/sync_metrics.h"
15 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/sync/profile_sync_service.h" 19 #include "chrome/browser/sync/profile_sync_service.h"
17 #include "chrome/browser/sync/profile_sync_service_factory.h" 20 #include "chrome/browser/sync/profile_sync_service_factory.h"
18 #if defined(OS_WIN) && defined(USE_ASH) 21 #if defined(OS_WIN) && defined(USE_ASH)
19 #include "chrome/browser/ui/ash/ash_util.h" 22 #include "chrome/browser/ui/ash/ash_util.h"
20 #endif 23 #endif
24 #include "chrome/browser/ui/chrome_select_file_policy.h"
21 #include "chrome/common/pref_names.h" 25 #include "chrome/common/pref_names.h"
22 #include "chrome/common/url_constants.h" 26 #include "chrome/common/url_constants.h"
23 #include "chrome/grit/generated_resources.h" 27 #include "chrome/grit/generated_resources.h"
24 #include "components/autofill/core/common/password_form.h" 28 #include "components/autofill/core/common/password_form.h"
25 #include "components/password_manager/core/browser/affiliation_utils.h" 29 #include "components/password_manager/core/browser/affiliation_utils.h"
30 #include "components/password_manager/core/browser/export/password_exporter.h"
26 #include "components/password_manager/core/browser/password_bubble_experiment.h" 31 #include "components/password_manager/core/browser/password_bubble_experiment.h"
32 #include "components/password_manager/core/browser/password_store.h"
27 #include "components/password_manager/core/common/experiments.h" 33 #include "components/password_manager/core/common/experiments.h"
34 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/notification_details.h" 35 #include "content/public/browser/notification_details.h"
29 #include "content/public/browser/notification_source.h" 36 #include "content/public/browser/notification_source.h"
30 #include "content/public/browser/user_metrics.h" 37 #include "content/public/browser/user_metrics.h"
31 #include "content/public/browser/web_contents.h" 38 #include "content/public/browser/web_contents.h"
32 #include "content/public/browser/web_ui.h" 39 #include "content/public/browser/web_ui.h"
33 #include "content/public/common/content_switches.h" 40 #include "content/public/common/content_switches.h"
34 #include "net/base/net_util.h" 41 #include "net/base/net_util.h"
35 #include "ui/base/l10n/l10n_util.h" 42 #include "ui/base/l10n/l10n_util.h"
36 43
37 namespace options { 44 namespace options {
38 45
39 PasswordManagerHandler::PasswordManagerHandler() 46 namespace {
40 : password_manager_presenter_(this) {} 47
48 // Enumeration of different callers of SelectFile. Starting count at 1 so
49 // accidental call of SelectFile with params=NULL will error out.
50 enum FileSelectorCaller {
51 IMPORT_FILE_SELECTED = 1,
52 EXPORT_FILE_SELECTED,
53 };
54
55 } // namespace
56
57 PasswordManagerHandler::PasswordManagerHandler() {
58 password_manager_presenter_.reset(new PasswordManagerPresenter(this));
59 }
60
61 PasswordManagerHandler::PasswordManagerHandler(
62 PasswordManagerPresenter* presenter) {
63 password_manager_presenter_.reset(presenter);
64 }
41 65
42 PasswordManagerHandler::~PasswordManagerHandler() {} 66 PasswordManagerHandler::~PasswordManagerHandler() {}
43 67
44 Profile* PasswordManagerHandler::GetProfile() { 68 Profile* PasswordManagerHandler::GetProfile() {
45 return Profile::FromWebUI(web_ui()); 69 return Profile::FromWebUI(web_ui());
46 } 70 }
47 71
48 #if !defined(OS_ANDROID) 72 #if !defined(OS_ANDROID)
49 gfx::NativeWindow PasswordManagerHandler::GetNativeWindow() const { 73 gfx::NativeWindow PasswordManagerHandler::GetNativeWindow() const {
50 return web_ui()->GetWebContents()->GetTopLevelNativeWindow(); 74 return web_ui()->GetWebContents()->GetTopLevelNativeWindow();
51 } 75 }
52 #endif 76 #endif
53 77
54 void PasswordManagerHandler::GetLocalizedValues( 78 void PasswordManagerHandler::GetLocalizedValues(
55 base::DictionaryValue* localized_strings) { 79 base::DictionaryValue* localized_strings) {
56 DCHECK(localized_strings); 80 DCHECK(localized_strings);
57 81
58 static const OptionsStringResource resources[] = { 82 static const OptionsStringResource resources[] = {
59 { "autoSigninTitle", 83 {"autoSigninTitle", IDS_PASSWORDS_AUTO_SIGNIN_TITLE},
60 IDS_PASSWORDS_AUTO_SIGNIN_TITLE }, 84 {"autoSigninDescription", IDS_PASSWORDS_AUTO_SIGNIN_DESCRIPTION},
61 { "autoSigninDescription", 85 {"savedPasswordsTitle", IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE},
62 IDS_PASSWORDS_AUTO_SIGNIN_DESCRIPTION }, 86 {"passwordExceptionsTitle", IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE},
63 { "savedPasswordsTitle", 87 {"passwordSearchPlaceholder", IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS},
64 IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE }, 88 {"passwordShowButton", IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON},
65 { "passwordExceptionsTitle", 89 {"passwordHideButton", IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON},
66 IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE }, 90 {"passwordsNoPasswordsDescription",
67 { "passwordSearchPlaceholder", 91 IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION},
68 IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS }, 92 {"passwordsNoExceptionsDescription",
69 { "passwordShowButton", 93 IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION},
70 IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON }, 94 {"passwordManagerImportPasswordButtonText",
71 { "passwordHideButton", 95 IDS_PASSWORD_MANAGER_IMPORT_BUTTON},
72 IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON }, 96 {"passwordManagerExportPasswordButtonText",
73 { "passwordsNoPasswordsDescription", 97 IDS_PASSWORD_MANAGER_EXPORT_BUTTON},
74 IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION }, 98 {"importPasswordCompletedMessage",
75 { "passwordsNoExceptionsDescription", 99 IDS_PASSWORD_MANAGER_IMPORT_COMPLETED_MESSAGE},
76 IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION },
77 }; 100 };
78 101
79 RegisterStrings(localized_strings, resources, arraysize(resources)); 102 RegisterStrings(localized_strings, resources, arraysize(resources));
80 103
81 const ProfileSyncService* sync_service = 104 const ProfileSyncService* sync_service =
82 ProfileSyncServiceFactory::GetForProfile(GetProfile()); 105 ProfileSyncServiceFactory::GetForProfile(GetProfile());
83 int title_id = 106 int title_id =
84 password_bubble_experiment::IsSmartLockBrandingEnabled(sync_service) ? 107 password_bubble_experiment::IsSmartLockBrandingEnabled(sync_service) ?
85 IDS_PASSWORDS_EXCEPTIONS_SMART_LOCK_WINDOW_TITLE : 108 IDS_PASSWORDS_EXCEPTIONS_SMART_LOCK_WINDOW_TITLE :
86 IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE; 109 IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 base::Bind(&PasswordManagerHandler::HandleRemoveSavedPassword, 157 base::Bind(&PasswordManagerHandler::HandleRemoveSavedPassword,
135 base::Unretained(this))); 158 base::Unretained(this)));
136 web_ui()->RegisterMessageCallback( 159 web_ui()->RegisterMessageCallback(
137 "removePasswordException", 160 "removePasswordException",
138 base::Bind(&PasswordManagerHandler::HandleRemovePasswordException, 161 base::Bind(&PasswordManagerHandler::HandleRemovePasswordException,
139 base::Unretained(this))); 162 base::Unretained(this)));
140 web_ui()->RegisterMessageCallback( 163 web_ui()->RegisterMessageCallback(
141 "requestShowPassword", 164 "requestShowPassword",
142 base::Bind(&PasswordManagerHandler::HandleRequestShowPassword, 165 base::Bind(&PasswordManagerHandler::HandleRequestShowPassword,
143 base::Unretained(this))); 166 base::Unretained(this)));
167 web_ui()->RegisterMessageCallback(
168 "importPassword",
169 base::Bind(&PasswordManagerHandler::HandlePasswordImport,
170 base::Unretained(this)));
171 web_ui()->RegisterMessageCallback(
172 "exportPassword",
173 base::Bind(&PasswordManagerHandler::HandlePasswordExport,
174 base::Unretained(this)));
144 } 175 }
145 176
146 void PasswordManagerHandler::InitializeHandler() { 177 void PasswordManagerHandler::InitializeHandler() {
147 password_manager_presenter_.Initialize(); 178 password_manager_presenter_->Initialize();
148 } 179 }
149 180
150 void PasswordManagerHandler::InitializePage() { 181 void PasswordManagerHandler::InitializePage() {
151 base::FundamentalValue visible( 182 base::FundamentalValue visible(
152 password_manager::ManageAccountLinkExperimentEnabled()); 183 password_manager::ManageAccountLinkExperimentEnabled());
153 web_ui()->CallJavascriptFunction( 184 web_ui()->CallJavascriptFunction(
154 "PasswordManager.setManageAccountLinkVisibility", visible); 185 "PasswordManager.setManageAccountLinkVisibility", visible);
186 if (password_manager::ImportExportExperimentEnabled())
187 web_ui()->CallJavascriptFunction("PasswordManager.showImportExportButton");
155 } 188 }
156 189
157 void PasswordManagerHandler::HandleRemoveSavedPassword( 190 void PasswordManagerHandler::HandleRemoveSavedPassword(
158 const base::ListValue* args) { 191 const base::ListValue* args) {
159 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); 192 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args));
160 int index; 193 int index;
161 if (base::StringToInt(string_value, &index) && index >= 0) { 194 if (base::StringToInt(string_value, &index) && index >= 0) {
162 password_manager_presenter_.RemoveSavedPassword(static_cast<size_t>(index)); 195 password_manager_presenter_->RemoveSavedPassword(
196 static_cast<size_t>(index));
163 } 197 }
164 } 198 }
165 199
166 void PasswordManagerHandler::HandleRemovePasswordException( 200 void PasswordManagerHandler::HandleRemovePasswordException(
167 const base::ListValue* args) { 201 const base::ListValue* args) {
168 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); 202 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args));
169 int index; 203 int index;
170 if (base::StringToInt(string_value, &index) && index >= 0) { 204 if (base::StringToInt(string_value, &index) && index >= 0) {
171 password_manager_presenter_.RemovePasswordException( 205 password_manager_presenter_->RemovePasswordException(
172 static_cast<size_t>(index)); 206 static_cast<size_t>(index));
173 } 207 }
174 } 208 }
175 209
176 void PasswordManagerHandler::HandleRequestShowPassword( 210 void PasswordManagerHandler::HandleRequestShowPassword(
177 const base::ListValue* args) { 211 const base::ListValue* args) {
178 int index; 212 int index;
179 if (!ExtractIntegerValue(args, &index)) 213 if (!ExtractIntegerValue(args, &index))
180 NOTREACHED(); 214 NOTREACHED();
181 215
182 password_manager_presenter_.RequestShowPassword(static_cast<size_t>(index)); 216 password_manager_presenter_->RequestShowPassword(static_cast<size_t>(index));
183 } 217 }
184 218
185 void PasswordManagerHandler::ShowPassword( 219 void PasswordManagerHandler::ShowPassword(
186 size_t index, 220 size_t index,
187 const std::string& origin_url, 221 const std::string& origin_url,
188 const std::string& username, 222 const std::string& username,
189 const base::string16& password_value) { 223 const base::string16& password_value) {
190 // Call back the front end to reveal the password. 224 // Call back the front end to reveal the password.
191 web_ui()->CallJavascriptFunction( 225 web_ui()->CallJavascriptFunction(
192 "PasswordManager.showPassword", 226 "PasswordManager.showPassword",
193 base::FundamentalValue(static_cast<int>(index)), 227 base::FundamentalValue(static_cast<int>(index)),
194 base::StringValue(password_value)); 228 base::StringValue(password_value));
195 } 229 }
196 230
197 void PasswordManagerHandler::HandleUpdatePasswordLists( 231 void PasswordManagerHandler::HandleUpdatePasswordLists(
198 const base::ListValue* args) { 232 const base::ListValue* args) {
199 password_manager_presenter_.UpdatePasswordLists(); 233 password_manager_presenter_->UpdatePasswordLists();
200 } 234 }
201 235
202 void PasswordManagerHandler::SetPasswordList( 236 void PasswordManagerHandler::SetPasswordList(
203 const ScopedVector<autofill::PasswordForm>& password_list, 237 const ScopedVector<autofill::PasswordForm>& password_list,
204 bool show_passwords) { 238 bool show_passwords) {
205 base::ListValue entries; 239 base::ListValue entries;
206 languages_ = GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages); 240 languages_ = GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages);
207 base::string16 placeholder(base::ASCIIToUTF16(" ")); 241 base::string16 placeholder(base::ASCIIToUTF16(" "));
208 for (size_t i = 0; i < password_list.size(); ++i) { 242 for (size_t i = 0; i < password_list.size(); ++i) {
209 base::ListValue* entry = new base::ListValue(); 243 base::ListValue* entry = new base::ListValue();
(...skipping 25 matching lines...) Expand all
235 base::ListValue entries; 269 base::ListValue entries;
236 for (size_t i = 0; i < password_exception_list.size(); ++i) { 270 for (size_t i = 0; i < password_exception_list.size(); ++i) {
237 entries.AppendString(password_manager::GetHumanReadableOrigin( 271 entries.AppendString(password_manager::GetHumanReadableOrigin(
238 *password_exception_list[i], languages_)); 272 *password_exception_list[i], languages_));
239 } 273 }
240 274
241 web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList", 275 web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList",
242 entries); 276 entries);
243 } 277 }
244 278
279 void PasswordManagerHandler::FileSelected(const base::FilePath& path,
280 int index,
281 void* params) {
282 switch (static_cast<FileSelectorCaller>(reinterpret_cast<intptr_t>(params))) {
283 case IMPORT_FILE_SELECTED:
284 ImportPasswordFileSelected(path);
285 break;
286 case EXPORT_FILE_SELECTED:
287 ExportPasswordFileSelected(path);
288 break;
289 }
290 }
291
292 void PasswordManagerHandler::HandlePasswordImport(const base::ListValue* args) {
293 #if !defined(OS_ANDROID) // This is never called on Android.
294 ui::SelectFileDialog::FileTypeInfo file_type_info;
295 file_type_info.extensions =
296 password_manager::PasswordImporter::GetSupportedFileExtensions();
297 DCHECK(!file_type_info.extensions.empty() &&
298 !file_type_info.extensions[0].empty());
299 file_type_info.include_all_files = true;
300 selected_file_dialog_ = ui::SelectFileDialog::Create(
301 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
302 selected_file_dialog_->SelectFile(
303 ui::SelectFileDialog::SELECT_OPEN_FILE,
304 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_IMPORT_DIALOG_TITLE),
305 base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0],
306 web_ui()->GetWebContents()->GetTopLevelNativeWindow(),
307 reinterpret_cast<void*>(IMPORT_FILE_SELECTED));
308 #endif
309 }
310
311 void PasswordManagerHandler::ImportPasswordFileSelected(
312 const base::FilePath& path) {
313 password_manager::PasswordImporter::Import(
314 path, content::BrowserThread::GetMessageLoopProxyForThread(
315 content::BrowserThread::FILE).get(),
316 base::Bind(&PasswordManagerHandler::ImportPasswordFileRead,
317 base::Unretained(this)));
318 }
319
320 void PasswordManagerHandler::ImportPasswordFileRead(
321 password_manager::PasswordImporter::Result result,
322 const std::vector<autofill::PasswordForm>& forms) {
323 UMA_HISTOGRAM_ENUMERATION("PasswordManager.ImportPasswordFromCSVResult",
324 result,
325 password_manager::PasswordImporter::SEMANTIC_ERROR);
326 if (result != password_manager::PasswordImporter::SUCCESS)
327 return;
328
329 UMA_HISTOGRAM_COUNTS("PasswordManager.ImportedPasswordsPerUserInCSV",
330 forms.size());
331
332 password_manager::PasswordStore* store =
333 password_manager_presenter_->GetPasswordStore();
334 if (store) {
335 for (const autofill::PasswordForm& form : forms) {
336 store->AddLogin(form);
337 }
338
339 // Display Feedback UI
340 base::FundamentalValue visible(true);
341 web_ui()->CallJavascriptFunction(
342 "PasswordManager.setImportCompleteUiVisibility", visible);
343 } else {
344 UMA_HISTOGRAM_COUNTS("PasswordManager.FailToStorePasswordImportedFromCSV",
345 1);
346 }
347 }
348
349 void PasswordManagerHandler::HandlePasswordExport(const base::ListValue* args) {
350 #if !defined(OS_ANDROID) // This is never called on Android.
351 if (!password_manager_presenter_->IsUserAuthenticated()) {
352 return;
353 }
354 ui::SelectFileDialog::FileTypeInfo file_type_info;
355 file_type_info.extensions =
356 password_manager::PasswordExporter::GetSupportedFileExtensions();
357 DCHECK(!file_type_info.extensions.empty() &&
358 !file_type_info.extensions[0].empty());
359 file_type_info.include_all_files = true;
360 selected_file_dialog_ = ui::SelectFileDialog::Create(
361 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
362 selected_file_dialog_->SelectFile(
363 ui::SelectFileDialog::SELECT_SAVEAS_FILE,
364 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE),
365 base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0],
366 GetNativeWindow(), reinterpret_cast<void*>(EXPORT_FILE_SELECTED));
367 #endif
368 }
369
370 void PasswordManagerHandler::ExportPasswordFileSelected(
371 const base::FilePath& path) {
372 ScopedVector<autofill::PasswordForm> password_list =
373 password_manager_presenter_->GetAllPasswords().Pass();
374 UMA_HISTOGRAM_COUNTS("PasswordManager.ExportedPasswordsPerUserInCSV",
375 password_list.size());
376 password_manager::PasswordExporter::Export(
377 path, password_list.Pass(),
378 content::BrowserThread::GetMessageLoopProxyForThread(
379 content::BrowserThread::FILE).get(),
380 base::Closure());
381 }
382
383 void PasswordManagerHandler::ExportPasswordFileWritten() {
Evan Stade 2015/07/11 00:28:42 is this used?
xunlu 2015/07/13 21:30:26 Removed
384 // We do not plan to give any UI feedback for export at this moment as it
385 // will almost always succeed. If the plan changes, make this function the
386 // callback of password_manager::PasswordExporter::Export and put the feedback
387 // logic here.
388 }
389
245 } // namespace options 390 } // namespace options
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698