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

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: Add finch switch and address 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"
27 #include "components/password_manager/core/common/experiments.h" 32 #include "components/password_manager/core/common/experiments.h"
33 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/notification_details.h" 34 #include "content/public/browser/notification_details.h"
29 #include "content/public/browser/notification_source.h" 35 #include "content/public/browser/notification_source.h"
30 #include "content/public/browser/user_metrics.h" 36 #include "content/public/browser/user_metrics.h"
31 #include "content/public/browser/web_contents.h" 37 #include "content/public/browser/web_contents.h"
32 #include "content/public/browser/web_ui.h" 38 #include "content/public/browser/web_ui.h"
33 #include "content/public/common/content_switches.h" 39 #include "content/public/common/content_switches.h"
34 #include "net/base/net_util.h" 40 #include "net/base/net_util.h"
35 #include "ui/base/l10n/l10n_util.h" 41 #include "ui/base/l10n/l10n_util.h"
36 42
37 namespace options { 43 namespace options {
38 44
39 PasswordManagerHandler::PasswordManagerHandler() 45 namespace {
40 : password_manager_presenter_(this) {} 46
47 // Enumeration of different callers of SelectFile. Starting count at 1 so
48 // accidental call of SelectFile with params=NULL will error out.
49 enum {
50 IMPORT_FILE_SELECTED = 1,
51 EXPORT_FILE_SELECTED,
52 };
53
54 } // namespace
55
56 PasswordManagerHandler::PasswordManagerHandler() {
57 password_manager_presenter_.reset(new PasswordManagerPresenter(this));
58 }
59
60 PasswordManagerHandler::PasswordManagerHandler(
61 PasswordManagerPresenter* presenter) {
62 password_manager_presenter_.reset(presenter);
63 }
41 64
42 PasswordManagerHandler::~PasswordManagerHandler() {} 65 PasswordManagerHandler::~PasswordManagerHandler() {}
43 66
44 Profile* PasswordManagerHandler::GetProfile() { 67 Profile* PasswordManagerHandler::GetProfile() {
45 return Profile::FromWebUI(web_ui()); 68 return Profile::FromWebUI(web_ui());
46 } 69 }
47 70
48 #if !defined(OS_ANDROID) 71 #if !defined(OS_ANDROID)
49 gfx::NativeWindow PasswordManagerHandler::GetNativeWindow() const { 72 gfx::NativeWindow PasswordManagerHandler::GetNativeWindow() const {
50 return web_ui()->GetWebContents()->GetTopLevelNativeWindow(); 73 return web_ui()->GetWebContents()->GetTopLevelNativeWindow();
51 } 74 }
52 #endif 75 #endif
53 76
54 void PasswordManagerHandler::GetLocalizedValues( 77 void PasswordManagerHandler::GetLocalizedValues(
55 base::DictionaryValue* localized_strings) { 78 base::DictionaryValue* localized_strings) {
56 DCHECK(localized_strings); 79 DCHECK(localized_strings);
57 80
58 static const OptionsStringResource resources[] = { 81 static const OptionsStringResource resources[] = {
59 { "autoSigninTitle", 82 {"autoSigninTitle", IDS_PASSWORDS_AUTO_SIGNIN_TITLE},
60 IDS_PASSWORDS_AUTO_SIGNIN_TITLE }, 83 {"autoSigninDescription", IDS_PASSWORDS_AUTO_SIGNIN_DESCRIPTION},
61 { "autoSigninDescription", 84 {"savedPasswordsTitle", IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE},
62 IDS_PASSWORDS_AUTO_SIGNIN_DESCRIPTION }, 85 {"passwordExceptionsTitle", IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE},
63 { "savedPasswordsTitle", 86 {"passwordSearchPlaceholder", IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS},
64 IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE }, 87 {"passwordShowButton", IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON},
65 { "passwordExceptionsTitle", 88 {"passwordHideButton", IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON},
66 IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE }, 89 {"passwordsNoPasswordsDescription",
67 { "passwordSearchPlaceholder", 90 IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION},
68 IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS }, 91 {"passwordsNoExceptionsDescription",
69 { "passwordShowButton", 92 IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION},
70 IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON }, 93 {"passwordManagerImportPasswordButtonText",
71 { "passwordHideButton", 94 IDS_PASSWORD_MANAGER_IMPORT_BUTTON},
72 IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON }, 95 {"passwordManagerExportPasswordButtonText",
73 { "passwordsNoPasswordsDescription", 96 IDS_PASSWORD_MANAGER_EXPORT_BUTTON},
74 IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION }, 97 {"importPasswordCompletedMessage",
75 { "passwordsNoExceptionsDescription", 98 IDS_PASSWORD_MANAGER_IMPORT_COMPLETED_MESSAGE},
76 IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION },
77 }; 99 };
78 100
79 RegisterStrings(localized_strings, resources, arraysize(resources)); 101 RegisterStrings(localized_strings, resources, arraysize(resources));
80 102
81 const ProfileSyncService* sync_service = 103 const ProfileSyncService* sync_service =
82 ProfileSyncServiceFactory::GetForProfile(GetProfile()); 104 ProfileSyncServiceFactory::GetForProfile(GetProfile());
83 int title_id = 105 int title_id =
84 password_bubble_experiment::IsSmartLockBrandingEnabled(sync_service) ? 106 password_bubble_experiment::IsSmartLockBrandingEnabled(sync_service) ?
85 IDS_PASSWORDS_EXCEPTIONS_SMART_LOCK_WINDOW_TITLE : 107 IDS_PASSWORDS_EXCEPTIONS_SMART_LOCK_WINDOW_TITLE :
86 IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE; 108 IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 base::Bind(&PasswordManagerHandler::HandleRemoveSavedPassword, 156 base::Bind(&PasswordManagerHandler::HandleRemoveSavedPassword,
135 base::Unretained(this))); 157 base::Unretained(this)));
136 web_ui()->RegisterMessageCallback( 158 web_ui()->RegisterMessageCallback(
137 "removePasswordException", 159 "removePasswordException",
138 base::Bind(&PasswordManagerHandler::HandleRemovePasswordException, 160 base::Bind(&PasswordManagerHandler::HandleRemovePasswordException,
139 base::Unretained(this))); 161 base::Unretained(this)));
140 web_ui()->RegisterMessageCallback( 162 web_ui()->RegisterMessageCallback(
141 "requestShowPassword", 163 "requestShowPassword",
142 base::Bind(&PasswordManagerHandler::HandleRequestShowPassword, 164 base::Bind(&PasswordManagerHandler::HandleRequestShowPassword,
143 base::Unretained(this))); 165 base::Unretained(this)));
166 web_ui()->RegisterMessageCallback(
167 "importPassword",
168 base::Bind(&PasswordManagerHandler::HandlePasswordImport,
169 base::Unretained(this)));
170 web_ui()->RegisterMessageCallback(
171 "exportPassword",
172 base::Bind(&PasswordManagerHandler::HandlePasswordExport,
173 base::Unretained(this)));
144 } 174 }
145 175
146 void PasswordManagerHandler::InitializeHandler() { 176 void PasswordManagerHandler::InitializeHandler() {
147 password_manager_presenter_.Initialize(); 177 password_manager_presenter_->Initialize();
148 } 178 }
149 179
150 void PasswordManagerHandler::InitializePage() { 180 void PasswordManagerHandler::InitializePage() {
151 base::FundamentalValue visible( 181 base::FundamentalValue visible(
152 password_manager::ManageAccountLinkExperimentEnabled()); 182 password_manager::ManageAccountLinkExperimentEnabled());
153 web_ui()->CallJavascriptFunction( 183 web_ui()->CallJavascriptFunction(
154 "PasswordManager.setManageAccountLinkVisibility", visible); 184 "PasswordManager.setManageAccountLinkVisibility", visible);
185 if (password_manager::ImportExportExperimentEnabled()) {
186 web_ui()->CallJavascriptFunction("PasswordManager.showImportExportButton");
187 }
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 (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 default:
290 NOTREACHED();
291 }
292 }
293
294 void PasswordManagerHandler::HandlePasswordImport(const base::ListValue* args) {
295 #if !defined(OS_ANDROID) // This is never called on Android.
296 ui::SelectFileDialog::FileTypeInfo file_type_info;
297 file_type_info.extensions =
298 password_manager::PasswordImporter::GetSupportedFileExtensions();
299 DCHECK(!file_type_info.extensions.empty() &&
300 !file_type_info.extensions[0].empty());
301 file_type_info.include_all_files = true;
302 selected_file_dialog_ = ui::SelectFileDialog::Create(
303 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
304 selected_file_dialog_->SelectFile(
305 ui::SelectFileDialog::SELECT_OPEN_FILE,
306 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_IMPORT_DIALOG_TITLE),
307 base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0],
308 web_ui()->GetWebContents()->GetTopLevelNativeWindow(),
309 reinterpret_cast<void*>(IMPORT_FILE_SELECTED));
310 #endif
311 }
312
313 void PasswordManagerHandler::ImportPasswordFileSelected(
314 const base::FilePath& path) {
315 password_manager::PasswordImporter::Import(
316 path, content::BrowserThread::GetMessageLoopProxyForThread(
317 content::BrowserThread::FILE).get(),
318 base::Bind(&PasswordManagerHandler::ImportPasswordFileRead,
319 base::Unretained(this)));
320 }
321
322 void PasswordManagerHandler::ImportPasswordFileRead(
323 password_manager::PasswordImporter::Result result,
324 const std::vector<autofill::PasswordForm>& forms) {
325 UMA_HISTOGRAM_ENUMERATION("PasswordManager.ImportPasswordFromCSVResult",
326 result,
327 password_manager::PasswordImporter::SEMANTIC_ERROR);
328 if (result != password_manager::PasswordImporter::SUCCESS) {
329 return;
330 }
331
332 UMA_HISTOGRAM_COUNTS("PasswordManager.ImportedPasswordsPerUserInCSV",
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 } else {
341 UMA_HISTOGRAM_COUNTS("PasswordManager.FailToStorePasswordImportedFromCSV",
342 1);
343 }
344 }
345
346 void PasswordManagerHandler::HandlePasswordExport(const base::ListValue* args) {
347 #if !defined(OS_ANDROID) // This is never called on Android.
348 if (password_manager_presenter_->RequestToExportPassword()) {
349 ui::SelectFileDialog::FileTypeInfo file_type_info;
350 file_type_info.extensions =
351 password_manager::PasswordExporter::GetSupportedFileExtensions();
352 DCHECK(!file_type_info.extensions.empty() &&
353 !file_type_info.extensions[0].empty());
354 file_type_info.include_all_files = true;
355 selected_file_dialog_ = ui::SelectFileDialog::Create(
356 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
357 selected_file_dialog_->SelectFile(
358 ui::SelectFileDialog::SELECT_SAVEAS_FILE,
359 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE),
360 base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0],
361 GetNativeWindow(), reinterpret_cast<void*>(EXPORT_FILE_SELECTED));
362 }
363 #endif
364 }
365
366 void PasswordManagerHandler::ExportPasswordFileSelected(
367 const base::FilePath& path) {
368 ScopedVector<autofill::PasswordForm> password_list =
369 password_manager_presenter_->GetAllPasswords().Pass();
370 UMA_HISTOGRAM_COUNTS("PasswordManager.ExportedPasswordsPerUserInCSV",
371 password_list.size());
372 password_manager::PasswordExporter::Export(
373 path, password_list.Pass(),
374 content::BrowserThread::GetMessageLoopProxyForThread(
375 content::BrowserThread::FILE).get(),
376 base::Bind(&PasswordManagerHandler::ExportPasswordFileWritten,
377 base::Unretained(this)));
378 }
379
380 void PasswordManagerHandler::ExportPasswordFileWritten() {
381 // We do not plan to give any UI feedback for export
382 // at this moment as it will almost always succeed. If the plan changes, this
383 // is the place to put the feedback logic.
384 }
385
245 } // namespace options 386 } // namespace options
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698