| 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
|
| index ee744580d8251a96c6d64567f483748ce5009f4e..e942112a110dbe9f6155f7884df20c40c7f5628b 100644
|
| --- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
|
| +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h"
|
|
|
| +#include "base/strings/string_util.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "build/build_config.h"
|
| #include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h"
|
| @@ -13,20 +14,66 @@
|
| #include "chrome/common/pref_names.h"
|
| #include "chrome/grit/generated_resources.h"
|
| #include "components/password_manager/core/browser/affiliation_utils.h"
|
| +#include "components/password_manager/core/browser/password_ui_utils.h"
|
| #include "components/prefs/pref_service.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) {
|
| +const char kAndroidAppScheme[] = "android://";
|
| +const char kPlayStoreAppPrefix[] =
|
| + "https://play.google.com/store/apps/details?id=";
|
| +
|
| +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;
|
| }
|
|
|
| +// Conveniece struct that mirrors the UrlCollection dictionary in
|
| +// passwords_private.idl.
|
| +struct URLs {
|
| + std::string origin;
|
| + std::string shown;
|
| + std::string link;
|
| +};
|
| +
|
| +// Obtains origin and link URL from the passed in form. In case the origin
|
| +// corresponds to the identifier of an Android app, it tries to create a human
|
| +// readable version of the origin URL.
|
| +URLs CreateURLFromForm(const autofill::PasswordForm& form) {
|
| + bool is_android_uri = false;
|
| + GURL link_url;
|
| + bool origin_is_clickable = false;
|
| + std::string shown_url = password_manager::GetShownOriginAndLinkUrl(
|
| + form, &is_android_uri, &link_url, &origin_is_clickable);
|
| + std::string link_str = link_url.spec();
|
| +
|
| + if (is_android_uri) {
|
| + if (!origin_is_clickable) {
|
| + // e.g. android://com.example.r => r.example.com.
|
| + shown_url = password_manager::StripAndroidAndReverse(shown_url);
|
| + // Turn human unfriendly string into a clickable link to the PlayStore.
|
| + base::ReplaceFirstSubstringAfterOffset(&link_str, 0, kAndroidAppScheme,
|
| + kPlayStoreAppPrefix);
|
| + }
|
| +
|
| + // Currently we use "direction=rtl" in CSS to elide long origins from the
|
| + // left. This does not play nice with appending strings that end in
|
| + // punctuation symbols, which is why the bidirectional override tag is
|
| + // necessary.
|
| + // TODO(crbug.com/679434): Clean this up.
|
| + shown_url += "\u202D" + // equivalent to <bdo dir = "ltr">
|
| + l10n_util::GetStringUTF8(IDS_PASSWORDS_ANDROID_URI_SUFFIX) +
|
| + "\u202C"; // equivalent to </bdo>
|
| + }
|
| +
|
| + return {form.signon_realm, shown_url, link_str};
|
| }
|
|
|
| +} // namespace
|
| +
|
| namespace extensions {
|
|
|
| PasswordsPrivateDelegateImpl::PasswordsPrivateDelegateImpl(Profile* profile)
|
| @@ -65,7 +112,7 @@ void PasswordsPrivateDelegateImpl::SendPasswordExceptionsList() {
|
| }
|
|
|
| void PasswordsPrivateDelegateImpl::GetPasswordExceptionsList(
|
| - const ExceptionPairsCallback& callback) {
|
| + const ExceptionEntriesCallback& callback) {
|
| if (current_exceptions_initialized_)
|
| callback.Run(current_exceptions_);
|
| else
|
| @@ -166,22 +213,22 @@ void PasswordsPrivateDelegateImpl::SetPasswordList(
|
| const std::vector<std::unique_ptr<autofill::PasswordForm>>& password_list) {
|
| // Rebuild |login_pair_to_index_map_| so that it reflects the contents of the
|
| // new list.
|
| + // Also, create a list of PasswordUiEntry objects to send to observers.
|
| login_pair_to_index_map_.clear();
|
| + current_entries_.clear();
|
| +
|
| for (size_t i = 0; i < password_list.size(); i++) {
|
| - std::string key = LoginPairToMapKey(
|
| - password_manager::GetHumanReadableOrigin(*password_list[i]),
|
| - base::UTF16ToUTF8(password_list[i]->username_value));
|
| + const auto& form = password_list[i];
|
| + URLs urls = CreateURLFromForm(*form);
|
| + std::string key =
|
| + LoginPairToMapKey(urls.origin, base::UTF16ToUTF8(form->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 auto& form : password_list) {
|
| api::passwords_private::PasswordUiEntry entry;
|
| - entry.login_pair.origin_url =
|
| - password_manager::GetHumanReadableOrigin(*form);
|
| + entry.login_pair.urls.origin = std::move(urls.origin);
|
| + entry.login_pair.urls.shown = std::move(urls.shown);
|
| + entry.login_pair.urls.link = std::move(urls.link);
|
| entry.login_pair.username = base::UTF16ToUTF8(form->username_value);
|
| - entry.link_url = form->origin.spec();
|
| entry.num_characters_in_password = form->password_value.length();
|
|
|
| if (!form->federation_origin.unique()) {
|
| @@ -211,20 +258,20 @@ void PasswordsPrivateDelegateImpl::SetPasswordExceptionList(
|
| password_exception_list) {
|
| // Rebuild |exception_url_to_index_map_| so that it reflects the contents of
|
| // the new list.
|
| + // Also, create a list of exceptions to send to observers.
|
| 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]);
|
| - exception_url_to_index_map_[key] = i;
|
| - }
|
| -
|
| - // Now, create a list of exceptions to send to observers.
|
| current_exceptions_.clear();
|
| - for (const auto& form : password_exception_list) {
|
| - api::passwords_private::ExceptionPair pair;
|
| - pair.exception_url = password_manager::GetHumanReadableOrigin(*form);
|
| - pair.link_url = form->origin.spec();
|
| - current_exceptions_.push_back(std::move(pair));
|
| +
|
| + for (size_t i = 0; i < password_exception_list.size(); i++) {
|
| + const auto& form = password_exception_list[i];
|
| + URLs urls = CreateURLFromForm(*form);
|
| + exception_url_to_index_map_[urls.origin] = i;
|
| +
|
| + api::passwords_private::ExceptionEntry current_exception_entry;
|
| + current_exception_entry.urls.origin = std::move(urls.origin);
|
| + current_exception_entry.urls.shown = std::move(urls.shown);
|
| + current_exception_entry.urls.link = std::move(urls.link);
|
| + current_exceptions_.push_back(std::move(current_exception_entry));
|
| }
|
|
|
| SendPasswordExceptionsList();
|
|
|