Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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); |
| 155 } | 185 } |
| 156 | 186 |
| 157 void PasswordManagerHandler::HandleRemoveSavedPassword( | 187 void PasswordManagerHandler::HandleRemoveSavedPassword( |
| 158 const base::ListValue* args) { | 188 const base::ListValue* args) { |
| 159 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); | 189 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); |
| 160 int index; | 190 int index; |
| 161 if (base::StringToInt(string_value, &index) && index >= 0) { | 191 if (base::StringToInt(string_value, &index) && index >= 0) { |
| 162 password_manager_presenter_.RemoveSavedPassword(static_cast<size_t>(index)); | 192 password_manager_presenter_->RemoveSavedPassword( |
| 193 static_cast<size_t>(index)); | |
| 163 } | 194 } |
| 164 } | 195 } |
| 165 | 196 |
| 166 void PasswordManagerHandler::HandleRemovePasswordException( | 197 void PasswordManagerHandler::HandleRemovePasswordException( |
| 167 const base::ListValue* args) { | 198 const base::ListValue* args) { |
| 168 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); | 199 std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); |
| 169 int index; | 200 int index; |
| 170 if (base::StringToInt(string_value, &index) && index >= 0) { | 201 if (base::StringToInt(string_value, &index) && index >= 0) { |
| 171 password_manager_presenter_.RemovePasswordException( | 202 password_manager_presenter_->RemovePasswordException( |
| 172 static_cast<size_t>(index)); | 203 static_cast<size_t>(index)); |
| 173 } | 204 } |
| 174 } | 205 } |
| 175 | 206 |
| 176 void PasswordManagerHandler::HandleRequestShowPassword( | 207 void PasswordManagerHandler::HandleRequestShowPassword( |
| 177 const base::ListValue* args) { | 208 const base::ListValue* args) { |
| 178 int index; | 209 int index; |
| 179 if (!ExtractIntegerValue(args, &index)) | 210 if (!ExtractIntegerValue(args, &index)) |
| 180 NOTREACHED(); | 211 NOTREACHED(); |
| 181 | 212 |
| 182 password_manager_presenter_.RequestShowPassword(static_cast<size_t>(index)); | 213 password_manager_presenter_->RequestShowPassword(static_cast<size_t>(index)); |
| 183 } | 214 } |
| 184 | 215 |
| 185 void PasswordManagerHandler::ShowPassword( | 216 void PasswordManagerHandler::ShowPassword( |
| 186 size_t index, | 217 size_t index, |
| 187 const std::string& origin_url, | 218 const std::string& origin_url, |
| 188 const std::string& username, | 219 const std::string& username, |
| 189 const base::string16& password_value) { | 220 const base::string16& password_value) { |
| 190 // Call back the front end to reveal the password. | 221 // Call back the front end to reveal the password. |
| 191 web_ui()->CallJavascriptFunction( | 222 web_ui()->CallJavascriptFunction( |
| 192 "PasswordManager.showPassword", | 223 "PasswordManager.showPassword", |
| 193 base::FundamentalValue(static_cast<int>(index)), | 224 base::FundamentalValue(static_cast<int>(index)), |
| 194 base::StringValue(password_value)); | 225 base::StringValue(password_value)); |
| 195 } | 226 } |
| 196 | 227 |
| 197 void PasswordManagerHandler::HandleUpdatePasswordLists( | 228 void PasswordManagerHandler::HandleUpdatePasswordLists( |
| 198 const base::ListValue* args) { | 229 const base::ListValue* args) { |
| 199 password_manager_presenter_.UpdatePasswordLists(); | 230 password_manager_presenter_->UpdatePasswordLists(); |
| 200 } | 231 } |
| 201 | 232 |
| 202 void PasswordManagerHandler::SetPasswordList( | 233 void PasswordManagerHandler::SetPasswordList( |
| 203 const ScopedVector<autofill::PasswordForm>& password_list, | 234 const ScopedVector<autofill::PasswordForm>& password_list, |
| 204 bool show_passwords) { | 235 bool show_passwords) { |
| 205 base::ListValue entries; | 236 base::ListValue entries; |
| 206 languages_ = GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages); | 237 languages_ = GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages); |
| 207 base::string16 placeholder(base::ASCIIToUTF16(" ")); | 238 base::string16 placeholder(base::ASCIIToUTF16(" ")); |
| 208 for (size_t i = 0; i < password_list.size(); ++i) { | 239 for (size_t i = 0; i < password_list.size(); ++i) { |
| 209 base::ListValue* entry = new base::ListValue(); | 240 base::ListValue* entry = new base::ListValue(); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 235 base::ListValue entries; | 266 base::ListValue entries; |
| 236 for (size_t i = 0; i < password_exception_list.size(); ++i) { | 267 for (size_t i = 0; i < password_exception_list.size(); ++i) { |
| 237 entries.AppendString(password_manager::GetHumanReadableOrigin( | 268 entries.AppendString(password_manager::GetHumanReadableOrigin( |
| 238 *password_exception_list[i], languages_)); | 269 *password_exception_list[i], languages_)); |
| 239 } | 270 } |
| 240 | 271 |
| 241 web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList", | 272 web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList", |
| 242 entries); | 273 entries); |
| 243 } | 274 } |
| 244 | 275 |
| 276 void PasswordManagerHandler::FileSelected(const base::FilePath& path, | |
| 277 int index, | |
| 278 void* params) { | |
| 279 switch (reinterpret_cast<intptr_t>(params)) { | |
| 280 case IMPORT_FILE_SELECTED: | |
| 281 ImportPasswordFileSelected(path); | |
| 282 break; | |
| 283 case EXPORT_FILE_SELECTED: | |
| 284 ExportPasswordFileSelected(path); | |
| 285 break; | |
| 286 default: | |
| 287 NOTREACHED(); | |
| 288 } | |
| 289 } | |
| 290 | |
| 291 void PasswordManagerHandler::HandlePasswordImport(const base::ListValue* args) { | |
| 292 #if !defined(OS_ANDROID) // This is never called on Android. | |
| 293 ui::SelectFileDialog::FileTypeInfo file_type_info; | |
| 294 file_type_info.extensions = | |
| 295 password_manager::PasswordImporter::GetSupportedFileExtensions(); | |
| 296 DCHECK(!file_type_info.extensions.empty() && | |
| 297 !file_type_info.extensions[0].empty()); | |
| 298 file_type_info.include_all_files = true; | |
| 299 selected_file_dialog_ = ui::SelectFileDialog::Create( | |
| 300 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents())); | |
| 301 selected_file_dialog_->SelectFile( | |
| 302 ui::SelectFileDialog::SELECT_OPEN_FILE, | |
| 303 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_IMPORT_DIALOG_TITLE), | |
| 304 base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0], | |
| 305 web_ui()->GetWebContents()->GetTopLevelNativeWindow(), | |
| 306 reinterpret_cast<void*>(IMPORT_FILE_SELECTED)); | |
| 307 #endif | |
| 308 } | |
| 309 | |
| 310 void PasswordManagerHandler::ImportPasswordFileSelected( | |
| 311 const base::FilePath& path) { | |
| 312 password_manager::PasswordImporter::Import( | |
| 313 path, content::BrowserThread::GetMessageLoopProxyForThread( | |
| 314 content::BrowserThread::FILE).get(), | |
| 315 base::Bind(&PasswordManagerHandler::ImportPasswordFileRead, | |
| 316 base::Unretained(this))); | |
| 317 } | |
| 318 | |
| 319 void PasswordManagerHandler::ImportPasswordFileRead( | |
| 320 password_manager::PasswordImporter::Result result, | |
| 321 const std::vector<autofill::PasswordForm>& forms) { | |
| 322 UMA_HISTOGRAM_ENUMERATION("PasswordManager.ImportPasswordFromCSVResult", | |
| 323 result, | |
| 324 password_manager::PasswordImporter::SEMANTIC_ERROR); | |
| 325 if (result != password_manager::PasswordImporter::SUCCESS) { | |
| 326 return; | |
| 327 } | |
| 328 | |
| 329 UMA_HISTOGRAM_COUNTS("PasswordManager.ImportedPasswordsPerUserInCSV", | |
| 330 forms.size()); | |
| 331 | |
| 332 if (password_manager_presenter_->AddPasswordsToStore(forms)) { | |
| 333 // Display Feedback UI | |
| 334 base::FundamentalValue visible(true); | |
| 335 web_ui()->CallJavascriptFunction( | |
| 336 "PasswordManager.setImportCompleteUIVisibility", visible); | |
| 337 } else { | |
| 338 UMA_HISTOGRAM_COUNTS("PasswordManager.FailToStorePasswordImportedFromCSV", | |
| 339 1); | |
| 340 } | |
| 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 = | |
| 348 password_manager::PasswordExporter::GetSupportedFileExtensions(); | |
| 349 DCHECK(!file_type_info.extensions.empty() && | |
| 350 !file_type_info.extensions[0].empty()); | |
| 351 file_type_info.include_all_files = true; | |
| 352 selected_file_dialog_ = ui::SelectFileDialog::Create( | |
| 353 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents())); | |
| 354 selected_file_dialog_->SelectFile( | |
| 355 ui::SelectFileDialog::SELECT_SAVEAS_FILE, | |
| 356 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE), | |
| 357 base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0], | |
| 358 GetNativeWindow(), 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(FILE_PATH_LITERAL("csv")), password_list.Pass(), | |
|
Garrett Casto
2015/06/26 21:13:48
For encapsulation purposes, I don't think that I w
xunlu
2015/06/30 23:06:09
Done.
| |
| 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 // We do not plan to give any UI feedback for export | |
| 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 |
| OLD | NEW |