| // 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 "chrome/browser/ui/passwords/ui_utils.h" |
| |
| #include <stddef.h> |
| |
| #include <algorithm> |
| |
| #include "base/feature_list.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "build/branding_buildflags.h" |
| #include "chrome/app/vector_icons/vector_icons.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/sync/sync_service_factory.h" |
| #include "chrome/browser/ui/browser_navigator.h" |
| #include "chrome/browser/ui/browser_navigator_params.h" |
| #include "chrome/browser/ui/chrome_pages.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/common/webui_url_constants.h" |
| #include "chrome/grit/chromium_strings.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "components/password_manager/core/browser/affiliation/affiliation_utils.h" |
| #include "components/password_manager/core/browser/leak_detection_dialog_utils.h" |
| #include "components/password_manager/core/browser/password_form.h" |
| #include "components/password_manager/core/browser/password_manager_client.h" |
| #include "components/password_manager/core/browser/password_manager_constants.h" |
| #include "components/password_manager/core/browser/password_manager_util.h" |
| #include "components/password_manager/core/common/password_manager_features.h" |
| #include "components/strings/grit/components_strings.h" |
| #include "components/sync/driver/sync_service.h" |
| #include "components/sync/driver/sync_user_settings.h" |
| #include "components/url_formatter/elide_url.h" |
| #include "components/vector_icons/vector_icons.h" |
| #include "content/public/browser/web_contents.h" |
| #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| #include "net/base/url_util.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/page_transition_types.h" |
| #include "ui/base/window_open_disposition.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/size.h" |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/gfx/image/image_skia_operations.h" |
| #include "url/gurl.h" |
| #include "url/origin.h" |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| #include "chrome/browser/ui/browser.h" |
| #endif |
| |
| namespace { |
| |
| using password_manager::ManagePasswordsReferrer; |
| |
| // Checks whether two URLs are from the same domain or host. |
| bool SameDomainOrHost(const GURL& gurl, const url::Origin& origin) { |
| return net::registry_controlled_domains::SameDomainOrHost( |
| gurl, origin, |
| net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); |
| } |
| |
| } // namespace |
| |
| gfx::ImageSkia ScaleImageForAccountAvatar(gfx::ImageSkia skia_image) { |
| gfx::Size size = skia_image.size(); |
| if (size.height() != size.width()) { |
| gfx::Rect target(size); |
| int side = std::min(size.height(), size.width()); |
| target.ClampToCenteredSize(gfx::Size(side, side)); |
| skia_image = gfx::ImageSkiaOperations::ExtractSubset(skia_image, target); |
| } |
| return gfx::ImageSkiaOperations::CreateResizedImage( |
| skia_image, skia::ImageOperations::RESIZE_BEST, |
| gfx::Size(kAvatarImageSize, kAvatarImageSize)); |
| } |
| |
| std::pair<std::u16string, std::u16string> GetCredentialLabelsForAccountChooser( |
| const password_manager::PasswordForm& form) { |
| std::u16string federation; |
| if (!form.federation_origin.opaque()) |
| federation = GetDisplayFederation(form); |
| |
| if (form.display_name.empty()) |
| return std::make_pair(form.username_value, std::move(federation)); |
| |
| // Display name isn't empty. |
| if (federation.empty()) |
| return std::make_pair(form.display_name, form.username_value); |
| |
| return std::make_pair(form.display_name, |
| form.username_value + u"\n" + federation); |
| } |
| |
| std::u16string GetSavePasswordDialogTitleText( |
| const GURL& user_visible_url, |
| const url::Origin& form_origin_url, |
| PasswordTitleType dialog_type) { |
| std::vector<size_t> offsets; |
| std::vector<std::u16string> replacements; |
| int title_id = 0; |
| switch (dialog_type) { |
| case PasswordTitleType::SAVE_PASSWORD: |
| title_id = IDS_SAVE_PASSWORD; |
| break; |
| case PasswordTitleType::SAVE_ACCOUNT: |
| title_id = IDS_SAVE_ACCOUNT; |
| break; |
| case PasswordTitleType::UPDATE_PASSWORD: |
| title_id = IDS_UPDATE_PASSWORD; |
| break; |
| } |
| |
| // Check whether the registry controlled domains for user-visible URL (i.e. |
| // the one seen in the omnibox) and the password form post-submit navigation |
| // URL differs or not. |
| if (!SameDomainOrHost(user_visible_url, form_origin_url)) { |
| DCHECK_NE(PasswordTitleType::SAVE_ACCOUNT, dialog_type) |
| << "Calls to save account should always happen on the same domain."; |
| title_id = dialog_type == PasswordTitleType::UPDATE_PASSWORD |
| ? IDS_UPDATE_PASSWORD_DIFFERENT_DOMAINS_TITLE |
| : IDS_SAVE_PASSWORD_DIFFERENT_DOMAINS_TITLE; |
| replacements.push_back(url_formatter::FormatOriginForSecurityDisplay( |
| form_origin_url, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS)); |
| } |
| |
| return l10n_util::GetStringFUTF16(title_id, replacements, &offsets); |
| } |
| |
| std::u16string GetManagePasswordsDialogTitleText( |
| const GURL& user_visible_url, |
| const url::Origin& password_origin_url, |
| bool has_credentials) { |
| DCHECK(!password_origin_url.opaque()); |
| // Check whether the registry controlled domains for user-visible URL |
| // (i.e. the one seen in the omnibox) and the managed password origin URL |
| // differ or not. |
| if (!SameDomainOrHost(user_visible_url, password_origin_url)) { |
| std::u16string formatted_url = |
| url_formatter::FormatOriginForSecurityDisplay(password_origin_url); |
| return l10n_util::GetStringFUTF16( |
| has_credentials |
| ? IDS_MANAGE_PASSWORDS_DIFFERENT_DOMAIN_TITLE |
| : IDS_MANAGE_PASSWORDS_DIFFERENT_DOMAIN_NO_PASSWORDS_TITLE, |
| formatted_url); |
| } |
| return l10n_util::GetStringUTF16( |
| has_credentials ? IDS_MANAGE_PASSWORDS_TITLE |
| : IDS_MANAGE_PASSWORDS_NO_PASSWORDS_TITLE); |
| } |
| |
| std::u16string GetDisplayUsername(const password_manager::PasswordForm& form) { |
| return form.username_value.empty() |
| ? l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN) |
| : form.username_value; |
| } |
| |
| std::u16string GetDisplayUsername( |
| const password_manager::UiCredential& credential) { |
| return credential.username().empty() |
| ? l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN) |
| : credential.username(); |
| } |
| |
| std::u16string GetDisplayFederation( |
| const password_manager::PasswordForm& form) { |
| return url_formatter::FormatOriginForSecurityDisplay( |
| form.federation_origin, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC); |
| } |
| |
| std::u16string GetDisplayPassword(const password_manager::PasswordForm& form) { |
| return form.federation_origin.opaque() |
| ? form.password_value |
| : l10n_util::GetStringFUTF16(IDS_PASSWORDS_VIA_FEDERATION, |
| GetDisplayFederation(form)); |
| } |
| |
| bool IsSyncingAutosignSetting(Profile* profile) { |
| const syncer::SyncService* sync_service = |
| SyncServiceFactory::GetForProfile(profile); |
| return (sync_service && |
| sync_service->GetUserSettings()->IsFirstSetupComplete() && |
| sync_service->IsSyncFeatureActive() && |
| sync_service->GetActiveDataTypes().Has(syncer::PRIORITY_PREFERENCES)); |
| } |
| |
| GURL GetGooglePasswordManagerURL(ManagePasswordsReferrer referrer) { |
| GURL url(chrome::kGooglePasswordManagerURL); |
| url = net::AppendQueryParameter(url, "utm_source", "chrome"); |
| #if BUILDFLAG(IS_ANDROID) |
| url = net::AppendQueryParameter(url, "utm_medium", "android"); |
| #else |
| url = net::AppendQueryParameter(url, "utm_medium", "desktop"); |
| #endif |
| std::string campaign = [referrer] { |
| switch (referrer) { |
| case ManagePasswordsReferrer::kChromeSettings: |
| return "chrome_settings"; |
| case ManagePasswordsReferrer::kManagePasswordsBubble: |
| return "manage_passwords_bubble"; |
| case ManagePasswordsReferrer::kPasswordContextMenu: |
| return "password_context_menu"; |
| case ManagePasswordsReferrer::kPasswordDropdown: |
| return "password_dropdown"; |
| case ManagePasswordsReferrer::kPasswordGenerationConfirmation: |
| return "password_generation_confirmation"; |
| case ManagePasswordsReferrer::kProfileChooser: |
| return "profile_chooser"; |
| case ManagePasswordsReferrer::kSafeStateBubble: |
| return "safe_state"; |
| case ManagePasswordsReferrer::kSaveUpdateBubble: |
| return "save_update_password_bubble"; |
| case ManagePasswordsReferrer::kPasswordGenerationPrompt: |
| return "password_generation_prompt_in_autofill_dropdown"; |
| case ManagePasswordsReferrer::kPasswordsGoogleWebsite: |
| return "passwords_google"; |
| case ManagePasswordsReferrer::kPasswordsAccessorySheet: |
| case ManagePasswordsReferrer::kTouchToFill: |
| case ManagePasswordsReferrer::kPasswordBreachDialog: |
| case ManagePasswordsReferrer::kSafetyCheck: |
| case ManagePasswordsReferrer::kBiometricAuthenticationBeforeFillingDialog: |
| case ManagePasswordsReferrer::kChromeMenuItem: |
| NOTREACHED(); |
| } |
| |
| NOTREACHED(); |
| return ""; |
| }(); |
| |
| return net::AppendQueryParameter(url, "utm_campaign", campaign); |
| } |
| |
| // Navigation is handled differently on Android. |
| #if !BUILDFLAG(IS_ANDROID) |
| void NavigateToGooglePasswordManager(Profile* profile, |
| ManagePasswordsReferrer referrer) { |
| NavigateParams params(profile, GetGooglePasswordManagerURL(referrer), |
| ui::PAGE_TRANSITION_LINK); |
| params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; |
| Navigate(¶ms); |
| } |
| |
| void NavigateToManagePasswordsPage(Browser* browser, |
| ManagePasswordsReferrer referrer) { |
| UMA_HISTOGRAM_ENUMERATION("PasswordManager.ManagePasswordsReferrer", |
| referrer); |
| chrome::ShowPasswordManager(browser); |
| } |
| |
| void NavigateToPasswordCheckupPage(Profile* profile) { |
| NavigateParams params(profile, password_manager::GetPasswordCheckupURL(), |
| ui::PAGE_TRANSITION_LINK); |
| params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; |
| Navigate(¶ms); |
| } |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| mojo::Remote<network::mojom::URLLoaderFactory> GetURLLoaderForMainFrame( |
| content::WebContents* web_contents) { |
| content::RenderFrameHost* frame = web_contents->GetPrimaryMainFrame(); |
| mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory; |
| frame->CreateNetworkServiceDefaultFactory( |
| url_loader_factory.BindNewPipeAndPassReceiver()); |
| return url_loader_factory; |
| } |
| |
| const gfx::VectorIcon& GooglePasswordManagerVectorIcon() { |
| #if BUILDFLAG(GOOGLE_CHROME_BRANDING) |
| return vector_icons::kGooglePasswordManagerIcon; |
| #else |
| return kKeyIcon; |
| #endif |
| } |