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

Unified Diff: chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc

Issue 1142693003: Implement the chrome.passwordsPrivate API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: stevenjb comment. 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 side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698