blob: 2d7d4b918c4f955601373dc129334bbf3e346792 [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/password_manager/core/browser/password_ui_utils.h"
#include <algorithm>
#include <string>
#include <vector>
#include "base/metrics/histogram_macros.h"
#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/password_manager/core/browser/affiliation/affiliation_utils.h"
#include "components/password_manager/core/browser/password_form.h"
#include "components/password_manager/core/browser/password_form_manager_for_ui.h"
#include "components/password_manager/core/browser/password_form_metrics_recorder.h"
#include "components/password_manager/core/browser/ui/credential_ui_entry.h"
#include "components/strings/grit/components_strings.h"
#include "components/url_formatter/elide_url.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/l10n/l10n_util.h"
namespace password_manager {
namespace {
// The URL prefixes that are removed from shown origin.
const char* const kRemovedPrefixes[] = {"m.", "mobile.", "www."};
constexpr char kPlayStoreAppPrefix[] =
"https://play.google.com/store/apps/details?id=";
std::string GetShownOrigin(const FacetURI& facet_uri,
const std::string& app_display_name,
const GURL& url) {
if (facet_uri.IsValidAndroidFacetURI()) {
return app_display_name.empty()
? SplitByDotAndReverse(facet_uri.android_package_name())
: app_display_name;
} else {
return password_manager::GetShownOrigin(url::Origin::Create(url));
}
}
GURL GetShownURL(const FacetURI& facet_uri, const GURL& url) {
if (facet_uri.IsValidAndroidFacetURI()) {
return GURL(kPlayStoreAppPrefix + facet_uri.android_package_name());
} else {
return url;
}
}
} // namespace
std::string SplitByDotAndReverse(base::StringPiece host) {
std::vector<base::StringPiece> parts = base::SplitStringPiece(
host, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
std::reverse(parts.begin(), parts.end());
return base::JoinString(parts, ".");
}
std::pair<std::string, GURL> GetShownOriginAndLinkUrl(
const PasswordForm& password_form) {
FacetURI facet_uri =
FacetURI::FromPotentiallyInvalidSpec(password_form.signon_realm);
return {GetShownOrigin(facet_uri, password_form.app_display_name,
password_form.url),
GetShownURL(facet_uri, password_form.url)};
}
std::string GetShownOrigin(const CredentialFacet& facet) {
auto facet_uri = password_manager::FacetURI::FromPotentiallyInvalidSpec(
facet.signon_realm);
return GetShownOrigin(facet_uri, facet.display_name, facet.url);
}
std::string GetShownOrigin(const CredentialUIEntry& credential) {
FacetURI facet_uri =
FacetURI::FromPotentiallyInvalidSpec(credential.GetFirstSignonRealm());
return GetShownOrigin(facet_uri, credential.GetDisplayName(),
credential.GetURL());
}
GURL GetShownUrl(const CredentialUIEntry& credential) {
FacetURI facet_uri =
FacetURI::FromPotentiallyInvalidSpec(credential.GetFirstSignonRealm());
return GetShownURL(facet_uri, credential.GetURL());
}
GURL GetShownUrl(const CredentialFacet& facet) {
FacetURI facet_uri = FacetURI::FromPotentiallyInvalidSpec(facet.signon_realm);
return GetShownURL(facet_uri, facet.url);
}
std::string GetShownOrigin(const url::Origin& origin) {
std::string original =
base::UTF16ToUTF8(url_formatter::FormatOriginForSecurityDisplay(
origin, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS));
base::StringPiece result = original;
for (base::StringPiece prefix : kRemovedPrefixes) {
if (base::StartsWith(result, prefix,
base::CompareCase::INSENSITIVE_ASCII)) {
result.remove_prefix(prefix.length());
break; // Remove only one prefix (e.g. www.mobile.de).
}
}
return result.find('.') != base::StringPiece::npos ? std::string(result)
: original;
}
void UpdatePasswordFormUsernameAndPassword(
const std::u16string& username,
const std::u16string& password,
PasswordFormManagerForUI* form_manager) {
const auto& pending_credentials = form_manager->GetPendingCredentials();
bool username_edited = pending_credentials.username_value != username;
bool password_changed = pending_credentials.password_value != password;
if (username_edited) {
form_manager->OnUpdateUsernameFromPrompt(username);
if (form_manager->GetMetricsRecorder()) {
form_manager->GetMetricsRecorder()->RecordDetailedUserAction(
password_manager::PasswordFormMetricsRecorder::DetailedUserAction::
kEditedUsernameInBubble);
}
}
if (password_changed) {
form_manager->OnUpdatePasswordFromPrompt(password);
if (form_manager->GetMetricsRecorder()) {
form_manager->GetMetricsRecorder()->RecordDetailedUserAction(
password_manager::PasswordFormMetricsRecorder::DetailedUserAction::
kSelectedDifferentPasswordInBubble);
}
}
// Values of this histogram are a bit mask. Only the lower two bits are used:
// 0001 to indicate that the user has edited the username in the password save
// bubble.
// 0010 to indicate that the user has changed the password in the
// password save bubble.
// The maximum possible value is defined by OR-ing these values.
UMA_HISTOGRAM_ENUMERATION("PasswordManager.EditsInSaveBubble",
username_edited + 2 * password_changed, 4);
}
std::vector<std::u16string> GetUsernamesForRealm(
const std::vector<password_manager::CredentialUIEntry>& credentials,
const std::string& signon_realm,
bool is_using_account_store) {
std::vector<std::u16string> usernames;
PasswordForm::Store store = is_using_account_store
? PasswordForm::Store::kAccountStore
: PasswordForm::Store::kProfileStore;
for (const auto& credential : credentials) {
if (credential.GetFirstSignonRealm() == signon_realm &&
credential.stored_in.contains(store)) {
usernames.push_back(credential.username);
}
}
return usernames;
}
std::u16string ToUsernameString(const std::u16string& username) {
if (!username.empty()) {
return username;
}
return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN);
}
std::u16string ToUsernameString(const std::string& username) {
return ToUsernameString(base::UTF8ToUTF16(username));
}
GURL RPIDToURL(const std::string& relying_party_id) {
return GURL(base::StrCat(
{url::kHttpsScheme, url::kStandardSchemeSeparator, relying_party_id}));
}
} // namespace password_manager