| Index: chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
|
| diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d6ae16392a8290508f7d5fd0d3c40671f597e78c
|
| --- /dev/null
|
| +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
|
| @@ -0,0 +1,263 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h"
|
| +
|
| +#include "base/prefs/pref_service.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
|
| +#include "chrome/common/pref_names.h"
|
| +#include "chrome/grit/generated_resources.h"
|
| +#include "components/password_manager/core/browser/affiliation_utils.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +
|
| +namespace {
|
| +
|
| +std::string LoginPairToMapKey(
|
| + const std::string& origin_url, const std::string& username) {
|
| + // Concatenate origin URL and username to form a unique key.
|
| + return origin_url + ',' + username;
|
| +}
|
| +
|
| +}
|
| +
|
| +namespace extensions {
|
| +
|
| +PasswordsPrivateDelegateImpl::PasswordsPrivateDelegateImpl(Profile* profile)
|
| + : profile_(profile),
|
| + password_manager_presenter_(new PasswordManagerPresenter(this)),
|
| + set_password_list_called_(false),
|
| + set_password_exception_list_called_(false),
|
| + is_initialized_(false),
|
| + languages_(profile->GetPrefs()->GetString(prefs::kAcceptLanguages)),
|
| + render_view_host_(nullptr),
|
| + observers_(new base::ObserverListThreadSafe<Observer>()) {
|
| + password_manager_presenter_->Initialize();
|
| + password_manager_presenter_->UpdatePasswordLists();
|
| +}
|
| +
|
| +PasswordsPrivateDelegateImpl::~PasswordsPrivateDelegateImpl() {}
|
| +
|
| +void PasswordsPrivateDelegateImpl::AddObserver(Observer* observer) {
|
| + observers_->AddObserver(observer);
|
| +
|
| + // Send the current cached lists to the new observer.
|
| + ExecuteFunction(base::Bind(
|
| + &PasswordsPrivateDelegateImpl::SendSavedPasswordsList,
|
| + base::Unretained(this)));
|
| + ExecuteFunction(base::Bind(
|
| + &PasswordsPrivateDelegateImpl::SendPasswordExceptionsList,
|
| + base::Unretained(this)));
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::RemoveObserver(Observer* observer) {
|
| + observers_->RemoveObserver(observer);
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::RemoveSavedPassword(
|
| + const std::string& origin_url, const std::string& username) {
|
| + ExecuteFunction(base::Bind(
|
| + &PasswordsPrivateDelegateImpl::RemoveSavedPasswordInternal,
|
| + base::Unretained(this),
|
| + origin_url,
|
| + username));
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::RemoveSavedPasswordInternal(
|
| + const std::string& origin_url, const std::string& username) {
|
| + std::string key = LoginPairToMapKey(origin_url, username);
|
| + if (login_pair_to_index_map_.find(key) == login_pair_to_index_map_.end()) {
|
| + // If the URL/username pair does not exist in the map, do nothing.
|
| + return;
|
| + }
|
| +
|
| + password_manager_presenter_->RemoveSavedPassword(
|
| + login_pair_to_index_map_[key]);
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::RemovePasswordException(
|
| + const std::string& exception_url) {
|
| + ExecuteFunction(base::Bind(
|
| + &PasswordsPrivateDelegateImpl::RemovePasswordExceptionInternal,
|
| + base::Unretained(this),
|
| + exception_url));
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::RemovePasswordExceptionInternal(
|
| + const std::string& exception_url) {
|
| + if (exception_url_to_index_map_.find(exception_url) ==
|
| + exception_url_to_index_map_.end()) {
|
| + // If the exception URL does not exist in the map, do nothing.
|
| + return;
|
| + }
|
| +
|
| + password_manager_presenter_->RemovePasswordException(
|
| + exception_url_to_index_map_[exception_url]);
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::RequestShowPassword(
|
| + const std::string& origin_url,
|
| + const std::string& username,
|
| + const content::RenderViewHost* render_view_host) {
|
| + ExecuteFunction(base::Bind(
|
| + &PasswordsPrivateDelegateImpl::RequestShowPasswordInternal,
|
| + base::Unretained(this),
|
| + origin_url,
|
| + username,
|
| + render_view_host));
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::RequestShowPasswordInternal(
|
| + const std::string& origin_url,
|
| + const std::string& username,
|
| + const content::RenderViewHost* render_view_host) {
|
| + std::string key = LoginPairToMapKey(origin_url, username);
|
| + if (login_pair_to_index_map_.find(key) == login_pair_to_index_map_.end()) {
|
| + // If the URL/username pair does not exist in the map, do nothing.
|
| + return;
|
| + }
|
| +
|
| + // Save |render_view_host| so that the call to RequestShowPassword() below can
|
| + // call use this value by calling GetNativeWindow(). Note: This is safe
|
| + // because GetNativeWindow() will only be called immediately from
|
| + // RequestShowPassword().
|
| + // TODO(stevenjb): Pass this directly to RequestShowPassword(); see
|
| + // crbug.com/495290.
|
| + render_view_host_ = render_view_host;
|
| +
|
| + // Request the password. When it is retrieved, ShowPassword() will be called.
|
| + password_manager_presenter_->RequestShowPassword(
|
| + login_pair_to_index_map_[key]);
|
| +}
|
| +
|
| +Profile* PasswordsPrivateDelegateImpl::GetProfile() {
|
| + return profile_;
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::ShowPassword(
|
| + size_t index,
|
| + const std::string& origin_url,
|
| + const std::string& username,
|
| + const base::string16& password_value) {
|
| + observers_->Notify(
|
| + FROM_HERE,
|
| + &Observer::OnPlaintextPasswordFetched,
|
| + origin_url,
|
| + username,
|
| + base::UTF16ToUTF8(password_value));
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::SetPasswordList(
|
| + const ScopedVector<autofill::PasswordForm>& password_list,
|
| + bool show_passwords) {
|
| + // Rebuild |login_pair_to_index_map_| so that it reflects the contents of the
|
| + // new list.
|
| + login_pair_to_index_map_.clear();
|
| + for (size_t i = 0; i < password_list.size(); i++) {
|
| + std::string key = LoginPairToMapKey(
|
| + password_manager::GetHumanReadableOrigin(*password_list[i], languages_),
|
| + base::UTF16ToUTF8(password_list[i]->username_value));
|
| + login_pair_to_index_map_[key] = i;
|
| + }
|
| +
|
| + // Now, create a list of PasswordUiEntry objects to send to observers.
|
| + current_entries_.clear();
|
| + for (const autofill::PasswordForm* form : password_list) {
|
| + linked_ptr<api::passwords_private::PasswordUiEntry> entry(
|
| + new api::passwords_private::PasswordUiEntry);
|
| + entry->login_pair.origin_url =
|
| + password_manager::GetHumanReadableOrigin(*form, languages_);
|
| + entry->login_pair.username = base::UTF16ToUTF8(form->username_value);
|
| + entry->num_characters_in_password = form->password_value.length();
|
| +
|
| + const GURL& federation_url = form->federation_url;
|
| + if (!federation_url.is_empty()) {
|
| + entry->federation_text.reset(new std::string(l10n_util::GetStringFUTF8(
|
| + IDS_PASSWORDS_VIA_FEDERATION,
|
| + base::UTF8ToUTF16(federation_url.host()))));
|
| + }
|
| +
|
| + current_entries_.push_back(entry);
|
| + }
|
| +
|
| + SendSavedPasswordsList();
|
| +
|
| + set_password_list_called_ = true;
|
| + InitializeIfNecessary();
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::SendSavedPasswordsList() {
|
| + observers_->Notify(
|
| + FROM_HERE, &Observer::OnSavedPasswordsListChanged, current_entries_);
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::SetPasswordExceptionList(
|
| + const ScopedVector<autofill::PasswordForm>& password_exception_list) {
|
| + // Rebuild |exception_url_to_index_map_| so that it reflects the contents of
|
| + // the new list.
|
| + exception_url_to_index_map_.clear();
|
| + for (size_t i = 0; i < password_exception_list.size(); i++) {
|
| + std::string key = password_manager::GetHumanReadableOrigin(
|
| + *password_exception_list[i], languages_);
|
| + exception_url_to_index_map_[key] = i;
|
| + }
|
| +
|
| + // Now, create a list of exceptions to send to observers.
|
| + current_exceptions_.clear();
|
| + for (const autofill::PasswordForm* form : password_exception_list) {
|
| + current_exceptions_.push_back(
|
| + password_manager::GetHumanReadableOrigin(*form, languages_));
|
| + }
|
| +
|
| + SendPasswordExceptionsList();
|
| +
|
| + set_password_exception_list_called_ = true;
|
| + InitializeIfNecessary();
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::SendPasswordExceptionsList() {
|
| + observers_->Notify(
|
| + FROM_HERE,
|
| + &Observer::OnPasswordExceptionsListChanged,
|
| + current_exceptions_);
|
| +}
|
| +
|
| +#if !defined(OS_ANDROID)
|
| +gfx::NativeWindow PasswordsPrivateDelegateImpl::GetNativeWindow() const {
|
| + DCHECK(render_view_host_);
|
| + return content::WebContents::FromRenderViewHost(render_view_host_)
|
| + ->GetTopLevelNativeWindow();
|
| +}
|
| +#endif
|
| +
|
| +void PasswordsPrivateDelegateImpl::Shutdown() {
|
| + password_manager_presenter_.reset();
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::ExecuteFunction(
|
| + const base::Callback<void()>& callback) {
|
| + if (is_initialized_) {
|
| + callback.Run();
|
| + return;
|
| + }
|
| +
|
| + pre_initialization_callbacks_.push_back(callback);
|
| +}
|
| +
|
| +void PasswordsPrivateDelegateImpl::InitializeIfNecessary() {
|
| + if (is_initialized_ ||
|
| + !set_password_list_called_ ||
|
| + !set_password_exception_list_called_)
|
| + return;
|
| +
|
| + is_initialized_ = true;
|
| +
|
| + for (const base::Callback<void()>& callback : pre_initialization_callbacks_) {
|
| + callback.Run();
|
| + }
|
| +}
|
| +
|
| +} // namespace extensions
|
|
|