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

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

Powered by Google App Engine
This is Rietveld 408576698