Home | History | Annotate | Download | only in options
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/webui/options/password_manager_handler.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/prefs/pref_service.h"
      9 #include "base/strings/string_number_conversions.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "base/values.h"
     12 #include "chrome/browser/chrome_notification_types.h"
     13 #include "chrome/browser/password_manager/password_store_factory.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/common/pref_names.h"
     16 #include "chrome/common/url_constants.h"
     17 #include "content/public/browser/notification_details.h"
     18 #include "content/public/browser/notification_source.h"
     19 #include "content/public/browser/web_ui.h"
     20 #include "content/public/common/password_form.h"
     21 #include "grit/chromium_strings.h"
     22 #include "grit/generated_resources.h"
     23 #include "net/base/net_util.h"
     24 #include "ui/base/l10n/l10n_util.h"
     25 
     26 namespace options {
     27 
     28 PasswordManagerHandler::PasswordManagerHandler()
     29     : populater_(this),
     30       exception_populater_(this) {
     31 }
     32 
     33 PasswordManagerHandler::~PasswordManagerHandler() {
     34   PasswordStore* store = GetPasswordStore();
     35   if (store)
     36     store->RemoveObserver(this);
     37 }
     38 
     39 void PasswordManagerHandler::GetLocalizedValues(
     40     DictionaryValue* localized_strings) {
     41   DCHECK(localized_strings);
     42 
     43   static const OptionsStringResource resources[] = {
     44     { "savedPasswordsTitle",
     45       IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE },
     46     { "passwordExceptionsTitle",
     47       IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE },
     48     { "passwordSearchPlaceholder",
     49       IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS },
     50     { "passwordShowButton",
     51       IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON },
     52     { "passwordHideButton",
     53       IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON },
     54     { "passwordsNoPasswordsDescription",
     55       IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION },
     56     { "passwordsNoExceptionsDescription",
     57       IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION },
     58   };
     59 
     60   RegisterStrings(localized_strings, resources, arraysize(resources));
     61   RegisterTitle(localized_strings, "passwordsPage",
     62                 IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE);
     63 
     64   localized_strings->SetString("passwordManagerLearnMoreURL",
     65                                chrome::kPasswordManagerLearnMoreURL);
     66 }
     67 
     68 void PasswordManagerHandler::InitializeHandler() {
     69   // Due to the way that handlers are (re)initialized under certain types of
     70   // navigation, we may already be initialized. (See bugs 88986 and 86448.)
     71   // If this is the case, return immediately. This is a hack.
     72   // TODO(mdm): remove this hack once it is no longer necessary.
     73   if (!show_passwords_.GetPrefName().empty())
     74     return;
     75 
     76   show_passwords_.Init(prefs::kPasswordManagerAllowShowPasswords,
     77                        Profile::FromWebUI(web_ui())->GetPrefs(),
     78                        base::Bind(&PasswordManagerHandler::UpdatePasswordLists,
     79                                   base::Unretained(this),
     80                                   static_cast<base::ListValue*>(NULL)));
     81   // We should not cache web_ui()->GetProfile(). See crosbug.com/6304.
     82   PasswordStore* store = GetPasswordStore();
     83   if (store)
     84     store->AddObserver(this);
     85 }
     86 
     87 void PasswordManagerHandler::RegisterMessages() {
     88   web_ui()->RegisterMessageCallback("updatePasswordLists",
     89       base::Bind(&PasswordManagerHandler::UpdatePasswordLists,
     90                  base::Unretained(this)));
     91   web_ui()->RegisterMessageCallback("removeSavedPassword",
     92       base::Bind(&PasswordManagerHandler::RemoveSavedPassword,
     93                  base::Unretained(this)));
     94   web_ui()->RegisterMessageCallback("removePasswordException",
     95       base::Bind(&PasswordManagerHandler::RemovePasswordException,
     96                  base::Unretained(this)));
     97   web_ui()->RegisterMessageCallback("removeAllSavedPasswords",
     98       base::Bind(&PasswordManagerHandler::RemoveAllSavedPasswords,
     99                  base::Unretained(this)));
    100   web_ui()->RegisterMessageCallback("removeAllPasswordExceptions",
    101       base::Bind(&PasswordManagerHandler::RemoveAllPasswordExceptions,
    102                  base::Unretained(this)));
    103 }
    104 
    105 void PasswordManagerHandler::OnLoginsChanged() {
    106   UpdatePasswordLists(NULL);
    107 }
    108 
    109 PasswordStore* PasswordManagerHandler::GetPasswordStore() {
    110   return PasswordStoreFactory::GetForProfile(Profile::FromWebUI(web_ui()),
    111                                              Profile::EXPLICIT_ACCESS).get();
    112 }
    113 
    114 void PasswordManagerHandler::UpdatePasswordLists(const ListValue* args) {
    115   // Reset the current lists.
    116   password_list_.clear();
    117   password_exception_list_.clear();
    118 
    119   languages_ = Profile::FromWebUI(web_ui())->GetPrefs()->
    120       GetString(prefs::kAcceptLanguages);
    121   populater_.Populate();
    122   exception_populater_.Populate();
    123 }
    124 
    125 void PasswordManagerHandler::RemoveSavedPassword(const ListValue* args) {
    126   PasswordStore* store = GetPasswordStore();
    127   if (!store)
    128     return;
    129   std::string string_value = UTF16ToUTF8(ExtractStringValue(args));
    130   int index;
    131   if (base::StringToInt(string_value, &index) && index >= 0 &&
    132       static_cast<size_t>(index) < password_list_.size())
    133     store->RemoveLogin(*password_list_[index]);
    134 }
    135 
    136 void PasswordManagerHandler::RemovePasswordException(
    137     const ListValue* args) {
    138   PasswordStore* store = GetPasswordStore();
    139   if (!store)
    140     return;
    141   std::string string_value = UTF16ToUTF8(ExtractStringValue(args));
    142   int index;
    143   if (base::StringToInt(string_value, &index) && index >= 0 &&
    144       static_cast<size_t>(index) < password_exception_list_.size())
    145     store->RemoveLogin(*password_exception_list_[index]);
    146 }
    147 
    148 void PasswordManagerHandler::RemoveAllSavedPasswords(
    149     const ListValue* args) {
    150   // TODO(jhawkins): This will cause a list refresh for every password in the
    151   // list. Add PasswordStore::RemoveAllLogins().
    152   PasswordStore* store = GetPasswordStore();
    153   if (!store)
    154     return;
    155   for (size_t i = 0; i < password_list_.size(); ++i)
    156     store->RemoveLogin(*password_list_[i]);
    157 }
    158 
    159 void PasswordManagerHandler::RemoveAllPasswordExceptions(
    160     const ListValue* args) {
    161   PasswordStore* store = GetPasswordStore();
    162   if (!store)
    163     return;
    164   for (size_t i = 0; i < password_exception_list_.size(); ++i)
    165     store->RemoveLogin(*password_exception_list_[i]);
    166 }
    167 
    168 void PasswordManagerHandler::SetPasswordList() {
    169   // Due to the way that handlers are (re)initialized under certain types of
    170   // navigation, we may not be initialized yet. (See bugs 88986 and 86448.)
    171   // If this is the case, initialize on demand. This is a hack.
    172   // TODO(mdm): remove this hack once it is no longer necessary.
    173   if (show_passwords_.GetPrefName().empty())
    174     InitializeHandler();
    175 
    176   ListValue entries;
    177   bool show_passwords = *show_passwords_;
    178   string16 empty;
    179   for (size_t i = 0; i < password_list_.size(); ++i) {
    180     ListValue* entry = new ListValue();
    181     entry->Append(new StringValue(net::FormatUrl(password_list_[i]->origin,
    182                                                  languages_)));
    183     entry->Append(new StringValue(password_list_[i]->username_value));
    184     entry->Append(new StringValue(
    185         show_passwords ? password_list_[i]->password_value : empty));
    186     entries.Append(entry);
    187   }
    188 
    189   web_ui()->CallJavascriptFunction("PasswordManager.setSavedPasswordsList",
    190                                    entries);
    191 }
    192 
    193 void PasswordManagerHandler::SetPasswordExceptionList() {
    194   ListValue entries;
    195   for (size_t i = 0; i < password_exception_list_.size(); ++i) {
    196     entries.Append(new StringValue(
    197         net::FormatUrl(password_exception_list_[i]->origin, languages_)));
    198   }
    199 
    200   web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList",
    201                                    entries);
    202 }
    203 
    204 PasswordManagerHandler::ListPopulater::ListPopulater(
    205     PasswordManagerHandler* page)
    206     : page_(page),
    207       pending_login_query_(0) {
    208 }
    209 
    210 PasswordManagerHandler::ListPopulater::~ListPopulater() {
    211 }
    212 
    213 PasswordManagerHandler::PasswordListPopulater::PasswordListPopulater(
    214     PasswordManagerHandler* page) : ListPopulater(page) {
    215 }
    216 
    217 void PasswordManagerHandler::PasswordListPopulater::Populate() {
    218   PasswordStore* store = page_->GetPasswordStore();
    219   if (store != NULL) {
    220     if (pending_login_query_)
    221       store->CancelRequest(pending_login_query_);
    222 
    223     pending_login_query_ = store->GetAutofillableLogins(this);
    224   } else {
    225     LOG(ERROR) << "No password store! Cannot display passwords.";
    226   }
    227 }
    228 
    229 void PasswordManagerHandler::PasswordListPopulater::
    230     OnPasswordStoreRequestDone(
    231         CancelableRequestProvider::Handle handle,
    232         const std::vector<content::PasswordForm*>& result) {
    233   DCHECK_EQ(pending_login_query_, handle);
    234   pending_login_query_ = 0;
    235   page_->password_list_.clear();
    236   page_->password_list_.insert(page_->password_list_.end(),
    237                                result.begin(), result.end());
    238   page_->SetPasswordList();
    239 }
    240 
    241 void PasswordManagerHandler::PasswordListPopulater::OnGetPasswordStoreResults(
    242     const std::vector<content::PasswordForm*>& results) {
    243   // TODO(kaiwang): Implement when I refactor
    244   // PasswordStore::GetAutofillableLogins and PasswordStore::GetBlacklistLogins.
    245   NOTIMPLEMENTED();
    246 }
    247 
    248 PasswordManagerHandler::PasswordExceptionListPopulater::
    249     PasswordExceptionListPopulater(PasswordManagerHandler* page)
    250         : ListPopulater(page) {
    251 }
    252 
    253 void PasswordManagerHandler::PasswordExceptionListPopulater::Populate() {
    254   PasswordStore* store = page_->GetPasswordStore();
    255   if (store != NULL) {
    256     if (pending_login_query_)
    257       store->CancelRequest(pending_login_query_);
    258 
    259     pending_login_query_ = store->GetBlacklistLogins(this);
    260   } else {
    261     LOG(ERROR) << "No password store! Cannot display exceptions.";
    262   }
    263 }
    264 
    265 void PasswordManagerHandler::PasswordExceptionListPopulater::
    266     OnPasswordStoreRequestDone(
    267         CancelableRequestProvider::Handle handle,
    268         const std::vector<content::PasswordForm*>& result) {
    269   DCHECK_EQ(pending_login_query_, handle);
    270   pending_login_query_ = 0;
    271   page_->password_exception_list_.clear();
    272   page_->password_exception_list_.insert(page_->password_exception_list_.end(),
    273                                          result.begin(), result.end());
    274   page_->SetPasswordExceptionList();
    275 }
    276 
    277 void PasswordManagerHandler::PasswordExceptionListPopulater::
    278     OnGetPasswordStoreResults(
    279         const std::vector<content::PasswordForm*>& results) {
    280   // TODO(kaiwang): Implement when I refactor
    281   // PasswordStore::GetAutofillableLogins and PasswordStore::GetBlacklistLogins.
    282   NOTIMPLEMENTED();
    283 }
    284 
    285 }  // namespace options
    286