Commit 76a820e4 authored by Viktor Semeniuk's avatar Viktor Semeniuk Committed by Commit Bot

[iOS][Password Check] Showing android credential

This change adds proper handling of android credentials on Password
Details screen. When android credential is compromised Change Password
button is hidden.

Bug: 1075494
Change-Id: Ib5915988c5ccd5b0ad4e3b7b4b8457dfd5cf8631
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2352881Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Reviewed-by: default avatarSergio Collazos <sczs@chromium.org>
Commit-Queue: Viktor Semeniuk <vsemeniuk@google.com>
Cr-Commit-Position: refs/heads/master@{#798663}
parent 3e30e14f
......@@ -50,7 +50,9 @@ source_set("password_details_ui") {
deps = [
"//base",
"//components/autofill/core/common",
"//components/password_manager/core/browser:affiliation",
"//components/password_manager/core/browser:browser",
"//components/password_manager/core/common",
"//components/strings",
"//ios/chrome/app/strings:ios_chromium_strings_grit",
"//ios/chrome/app/strings:ios_strings_grit",
......
......@@ -7,6 +7,8 @@
#import <Foundation/Foundation.h>
#include "url/gurl.h"
namespace autofill {
struct PasswordForm;
}
......@@ -16,20 +18,23 @@ struct PasswordForm;
@interface PasswordDetails : NSObject
// Short version of website.
@property(nonatomic, strong, readonly) NSString* origin;
@property(nonatomic, copy, readonly) NSString* origin;
// Associated website.
@property(nonatomic, strong, readonly) NSString* website;
@property(nonatomic, copy, readonly) NSString* website;
// Associated username.
@property(nonatomic, strong, readonly) NSString* username;
@property(nonatomic, copy, readonly) NSString* username;
// Associated password.
@property(nonatomic, strong) NSString* password;
@property(nonatomic, copy) NSString* password;
// Whether password is compromised or not.
@property(nonatomic, assign, getter=isCompromised) BOOL compromised;
// URL which allows to change the password of compromised credential.
@property(nonatomic, readonly) GURL changePasswordURL;
- (instancetype)initWithPasswordForm:(const autofill::PasswordForm&)form
NS_DESIGNATED_INITIALIZER;
......
......@@ -6,7 +6,10 @@
#include "base/strings/sys_string_conversions.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
#include "components/password_manager/core/browser/password_ui_utils.h"
#include "components/password_manager/core/browser/well_known_change_password_util.h"
#include "components/password_manager/core/common/password_manager_features.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -17,13 +20,38 @@
- (instancetype)initWithPasswordForm:(const autofill::PasswordForm&)form {
self = [super init];
if (self) {
auto nameWithLink = password_manager::GetShownOriginAndLinkUrl(form);
_origin = base::SysUTF8ToNSString(nameWithLink.first);
_website = base::SysUTF8ToNSString(nameWithLink.second.spec());
auto facetUri = password_manager::FacetURI::FromPotentiallyInvalidSpec(
form.signon_realm);
if (facetUri.IsValidAndroidFacetURI()) {
if (!form.app_display_name.empty()) {
_changePasswordURL =
[self changePasswordUrlFor:GURL(form.affiliated_web_realm)];
_origin = base::SysUTF8ToNSString(form.app_display_name);
_website = base::SysUTF8ToNSString(form.app_display_name);
} else {
_origin = base::SysUTF8ToNSString(facetUri.android_package_name());
_website = base::SysUTF8ToNSString(facetUri.android_package_name());
}
} else {
auto nameWithLink = password_manager::GetShownOriginAndLinkUrl(form);
_origin = base::SysUTF8ToNSString(nameWithLink.first);
_website = base::SysUTF8ToNSString(nameWithLink.second.spec());
_changePasswordURL = [self changePasswordUrlFor:form.url];
}
_username = base::SysUTF16ToNSString(form.username_value);
_password = base::SysUTF16ToNSString(form.password_value);
}
return self;
}
- (GURL)changePasswordUrlFor:(const GURL&)url {
if (!base::FeatureList::IsEnabled(
password_manager::features::kWellKnownChangePassword)) {
return url.GetOrigin();
}
return password_manager::CreateWellKnownNonExistingResourceURL(
url.GetOrigin());
}
@end
......@@ -138,8 +138,10 @@ typedef NS_ENUM(NSInteger, ReauthenticationReason) {
if (self.password.isCompromised) {
[model addSectionWithIdentifier:SectionIdentifierCompromisedInfo];
[model addItem:[self changePasswordItem]
toSectionWithIdentifier:SectionIdentifierCompromisedInfo];
if (self.password.changePasswordURL.is_valid()) {
[model addItem:[self changePasswordItem]
toSectionWithIdentifier:SectionIdentifierCompromisedInfo];
}
[model addItem:[self changePasswordRecommendationItem]
toSectionWithIdentifier:SectionIdentifierCompromisedInfo];
......@@ -237,10 +239,9 @@ typedef NS_ENUM(NSInteger, ReauthenticationReason) {
case ItemTypeChangePasswordButton:
if (!self.tableView.editing) {
DCHECK(self.commandsDispatcher);
GURL URL(base::SysNSStringToUTF8(self.password.website));
DCHECK(URL.is_valid());
OpenNewTabCommand* command =
[OpenNewTabCommand commandWithURLFromChrome:URL];
DCHECK(self.password.changePasswordURL.is_valid());
OpenNewTabCommand* command = [OpenNewTabCommand
commandWithURLFromChrome:self.password.changePasswordURL];
[self.commandsDispatcher closeSettingsUIAndOpenURL:command];
}
break;
......
......@@ -32,6 +32,13 @@
#error "This file requires ARC support."
#endif
namespace {
constexpr char kExampleCom[] = "http://www.example.com/";
constexpr char kAndroid[] = "android://hash@com.example.my.app";
constexpr char kUsername[] = "test@egmail.com";
constexpr char kPassword[] = "test";
}
// Test class that conforms to PasswordDetailsHanler in order to test the
// presenter methods are called correctly.
@interface FakePasswordDetailsHandler : NSObject <PasswordDetailsHandler>
......@@ -100,24 +107,26 @@ class PasswordDetailsTableViewControllerTest
return controller;
}
void SetPassword(bool isCompromised = false) {
void SetPassword(std::string website = kExampleCom,
std::string username = kUsername,
std::string password = kPassword,
bool isCompromised = false) {
auto form = autofill::PasswordForm();
form.url = GURL("http://www.example.com/");
form.action = GURL("http://www.example.com/accounts/Login");
form.username_element = base::ASCIIToUTF16("Email");
form.username_value = base::ASCIIToUTF16("test@egmail.com");
form.password_element = base::ASCIIToUTF16("Passwd");
form.password_value = base::ASCIIToUTF16("test");
form.submit_element = base::ASCIIToUTF16("signIn");
form.signon_realm = "http://www.example.com/";
form.signon_realm = website;
form.username_value = base::ASCIIToUTF16(username);
form.password_value = base::ASCIIToUTF16(password);
form.url = GURL(website);
form.action = GURL(website + "/action");
form.username_element = base::ASCIIToUTF16("email");
form.scheme = autofill::PasswordForm::Scheme::kHtml;
PasswordDetails* password =
PasswordDetails* passwordDetails =
[[PasswordDetails alloc] initWithPasswordForm:form];
password.compromised = isCompromised;
passwordDetails.compromised = isCompromised;
PasswordDetailsTableViewController* passwords_controller =
static_cast<PasswordDetailsTableViewController*>(controller());
[passwords_controller setPassword:password];
[passwords_controller setPassword:passwordDetails];
}
void CheckEditCellText(NSString* expected_text, int section, int item) {
......@@ -169,7 +178,7 @@ TEST_F(PasswordDetailsTableViewControllerTest, TestPassword) {
// Tests that compromised password is displayed properly.
TEST_F(PasswordDetailsTableViewControllerTest, TestCompromisedPassword) {
SetPassword(true);
SetPassword(kExampleCom, kUsername, kPassword, true);
EXPECT_EQ(2, NumberOfSections());
EXPECT_EQ(3, NumberOfItemsInSection(0));
EXPECT_EQ(2, NumberOfItemsInSection(1));
......@@ -300,7 +309,7 @@ TEST_F(PasswordDetailsTableViewControllerTest, TestEditPasswordConfirmed) {
EXPECT_FALSE(passwordDetails.tableView.editing);
}
// Tests password editing. User cancelled this action.
// Tests password editing. User cancelled this action.
TEST_F(PasswordDetailsTableViewControllerTest, TestEditPasswordCancel) {
SetPassword();
......@@ -319,3 +328,20 @@ TEST_F(PasswordDetailsTableViewControllerTest, TestEditPasswordCancel) {
EXPECT_FALSE(delegate().password);
EXPECT_TRUE(passwordDetails.tableView.editing);
}
// Tests android compromised credential is displayed without change password
// button.
TEST_F(PasswordDetailsTableViewControllerTest,
TestAndroidCompromisedCredential) {
SetPassword(kAndroid, kUsername, kPassword, true);
EXPECT_EQ(2, NumberOfSections());
EXPECT_EQ(3, NumberOfItemsInSection(0));
EXPECT_EQ(1, NumberOfItemsInSection(1));
CheckEditCellText(@"com.example.my.app", 0, 0);
CheckEditCellText(@"test@egmail.com", 0, 1);
CheckEditCellText(kMaskedPassword, 0, 2);
CheckDetailItemTextWithId(IDS_IOS_CHANGE_COMPROMISED_PASSWORD_DESCRIPTION, 1,
0);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment