Commit 842ceac0 authored by edchin's avatar edchin Committed by Chromium LUCI CQ

[ios][PhishGuard] Create PasswordProtectionRequestContent

Extracts web_contents from PasswordProtectionRequest into a derived
class. The base class will be moved to /core in a future CL.

Bug: 1147967
Change-Id: I011f1a853168ce6c40108bc5d0fb1dd78e1321fe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2638775
Commit-Queue: edchin <edchin@chromium.org>
Reviewed-by: default avatarAli Juma <ajuma@chromium.org>
Reviewed-by: default avatarBettina Dea <bdea@chromium.org>
Cr-Commit-Position: refs/heads/master@{#845535}
parent 7d10c7b3
......@@ -387,7 +387,9 @@ void ChromePasswordProtectionService::ShowModalWarning(
ReusedPasswordAccountType::SAVED_PASSWORD &&
base::FeatureList::IsEnabled(
safe_browsing::kPasswordProtectionForSavedPasswords)));
content::WebContents* web_contents = request->web_contents();
PasswordProtectionRequestContent* request_content =
static_cast<PasswordProtectionRequestContent*>(request);
content::WebContents* web_contents = request_content->web_contents();
RequestOutcome outcome = request->request_outcome();
// Don't show warning again if there is already a modal warning showing.
if (IsModalWarningShowingInWebContents(web_contents))
......@@ -1235,9 +1237,11 @@ void ChromePasswordProtectionService::MaybeReportPasswordReuseDetected(
extensions::SafeBrowsingPrivateEventRouterFactory::GetForProfile(
profile_);
if (router) {
PasswordProtectionRequestContent* request_content =
static_cast<PasswordProtectionRequestContent*>(request);
router->OnPolicySpecifiedPasswordReuseDetected(
request->web_contents()->GetLastCommittedURL(), username_or_email,
is_phishing_url);
request_content->web_contents()->GetLastCommittedURL(),
username_or_email, is_phishing_url);
}
}
}
......@@ -1627,7 +1631,9 @@ void ChromePasswordProtectionService::
bool ChromePasswordProtectionService::UserClickedThroughSBInterstitial(
PasswordProtectionRequest* request) {
content::WebContents* web_contents = request->web_contents();
PasswordProtectionRequestContent* request_content =
static_cast<PasswordProtectionRequestContent*>(request);
content::WebContents* web_contents = request_content->web_contents();
SBThreatType current_threat_type;
if (!ui_manager_->IsUrlWhitelistedOrPendingForWebContents(
web_contents->GetLastCommittedURL().GetWithEmptyPath(),
......
......@@ -330,7 +330,7 @@ class ChromePasswordProtectionServiceTest
std::vector<password_manager::MatchingReusedCredential> credentials = {
{"somedomain.com"}};
if (trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
request_ = new PasswordProtectionRequest(
request_ = new PasswordProtectionRequestContent(
web_contents(), GURL(kPhishingURL), GURL(), GURL(),
web_contents()->GetContentsMimeType(), kUserName,
PasswordType::PASSWORD_TYPE_UNKNOWN, credentials, trigger_type, true,
......@@ -338,7 +338,7 @@ class ChromePasswordProtectionServiceTest
} else {
ASSERT_EQ(LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
trigger_type);
request_ = new PasswordProtectionRequest(
request_ = new PasswordProtectionRequestContent(
web_contents(), GURL(kPhishingURL), GURL(), GURL(),
web_contents()->GetContentsMimeType(), kUserName,
reused_password_type, credentials, trigger_type,
......
......@@ -53,7 +53,7 @@ class PasswordProtectionNavigationThrottleTest
std::make_unique<safe_browsing::MockPasswordProtectionService>();
scoped_refptr<PasswordProtectionRequest> request =
new PasswordProtectionRequest(
new PasswordProtectionRequestContent(
RenderViewHostTestHarness::web_contents(), GURL(), GURL(), GURL(),
RenderViewHostTestHarness::web_contents()->GetContentsMimeType(),
"username", PasswordType::PASSWORD_TYPE_UNKNOWN, credentials,
......
......@@ -85,21 +85,6 @@ class PasswordProtectionRequest
public base::RefCountedThreadSafe<PasswordProtectionRequest,
DeleteOnUIThread> {
public:
PasswordProtectionRequest(
content::WebContents* web_contents,
const GURL& main_frame_url,
const GURL& password_form_action,
const GURL& password_form_frame_url,
const std::string& mime_type,
const std::string& username,
PasswordType password_type,
const std::vector<password_manager::MatchingReusedCredential>&
matching_reused_credentials,
LoginReputationClientRequest::TriggerType type,
bool password_field_exists,
PasswordProtectionServiceBase* pps,
int request_timeout_in_ms);
// Not copyable or movable
PasswordProtectionRequest(const PasswordProtectionRequest&) = delete;
PasswordProtectionRequest& operator=(const PasswordProtectionRequest&) =
......@@ -125,8 +110,6 @@ class PasswordProtectionRequest
return request_proto_.get();
}
content::WebContents* web_contents() const { return web_contents_; }
LoginReputationClientRequest::TriggerType trigger_type() const {
return trigger_type_;
}
......@@ -171,12 +154,44 @@ class PasswordProtectionRequest
protected:
friend class base::RefCountedThreadSafe<PasswordProtectionRequest>;
PasswordProtectionRequest(
const GURL& main_frame_url,
const GURL& password_form_action,
const GURL& password_form_frame_url,
const std::string& mime_type,
const std::string& username,
PasswordType password_type,
const std::vector<password_manager::MatchingReusedCredential>&
matching_reused_credentials,
LoginReputationClientRequest::TriggerType type,
bool password_field_exists,
PasswordProtectionServiceBase* pps,
int request_timeout_in_ms);
~PasswordProtectionRequest() override;
// Initiates network request to Safe Browsing backend.
void SendRequest();
// Records an event for the result of the URL reputation lookup if the user
// enters their password on a website.
virtual void MaybeLogPasswordReuseLookupEvent(
RequestOutcome outcome,
const LoginReputationClientResponse* response) = 0;
// The PasswordProtectionServiceBase instance owns |this|.
// Can only be accessed on UI thread.
PasswordProtectionServiceBase* password_protection_service() {
return password_protection_service_;
}
std::unique_ptr<LoginReputationClientRequest> request_proto_;
private:
friend DeleteOnUIThread;
friend class base::DeleteHelper<PasswordProtectionRequest>;
friend class PasswordProtectionServiceTest;
friend class ChromePasswordProtectionServiceTest;
~PasswordProtectionRequest() override;
// Start checking the whitelist.
void CheckWhitelist();
......@@ -198,40 +213,14 @@ class PasswordProtectionRequest
#if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
// Extracts DOM features.
void GetDomFeatures();
// Called when the DOM feature extraction is complete.
void OnGetDomFeatures(mojom::PhishingDetectorResult result,
const std::string& verdict);
// Called when the DOM feature extraction times out.
void OnGetDomFeatureTimeout();
// If appropriate, collects visual features, otherwise continues on to sending
// the request.
void MaybeCollectVisualFeatures();
virtual void GetDomFeatures() = 0;
#endif // BUILDFLAG(SAFE_BROWSING_AVAILABLE)
#if BUILDFLAG(FULL_SAFE_BROWSING)
// Collects visual features from the current login page.
void CollectVisualFeatures();
// Processes the screenshot of the login page into visual features.
void OnScreenshotTaken(const SkBitmap& bitmap);
// Called when the visual feature extraction is complete.
void OnVisualFeatureCollectionDone(
std::unique_ptr<VisualFeatures> visual_features);
#endif // BUILDFLAG(FULL_SAFE_BROWSING)
#if defined(OS_ANDROID)
// Sets the referring app info.
void SetReferringAppInfo();
virtual void SetReferringAppInfo() = 0;
#endif // defined(OS_ANDROID)
// Initiates network request to Safe Browsing backend.
void SendRequest();
// Start a timer to cancel the request if it takes too long.
void StartTimeout();
......@@ -239,9 +228,6 @@ class PasswordProtectionRequest
void Finish(RequestOutcome outcome,
std::unique_ptr<LoginReputationClientResponse> response);
// WebContents of the password protection event.
content::WebContents* web_contents_;
// Main frame URL of the login form.
const GURL main_frame_url_;
......@@ -296,8 +282,6 @@ class PasswordProtectionRequest
// request.
const int request_timeout_in_ms_;
std::unique_ptr<LoginReputationClientRequest> request_proto_;
// Needed for canceling tasks posted to different threads.
base::CancelableTaskTracker tracker_;
......@@ -312,6 +296,77 @@ class PasswordProtectionRequest
// If a request is sent, this is the token returned by the WebUI.
int web_ui_token_;
base::WeakPtrFactory<PasswordProtectionRequest> weakptr_factory_{this};
};
class PasswordProtectionRequestContent : public PasswordProtectionRequest {
public:
PasswordProtectionRequestContent(
content::WebContents* web_contents,
const GURL& main_frame_url,
const GURL& password_form_action,
const GURL& password_form_frame_url,
const std::string& mime_type,
const std::string& username,
PasswordType password_type,
const std::vector<password_manager::MatchingReusedCredential>&
matching_reused_credentials,
LoginReputationClientRequest::TriggerType type,
bool password_field_exists,
PasswordProtectionServiceBase* pps,
int request_timeout_in_ms);
content::WebContents* web_contents() const { return web_contents_; }
base::WeakPtr<PasswordProtectionRequestContent> GetWeakPtr() {
return weakptr_factory_.GetWeakPtr();
}
private:
~PasswordProtectionRequestContent() override;
void MaybeLogPasswordReuseLookupEvent(
RequestOutcome outcome,
const LoginReputationClientResponse* response) override;
#if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
// Extracts DOM features.
void GetDomFeatures() override;
// Called when the DOM feature extraction is complete.
void OnGetDomFeatures(mojom::PhishingDetectorResult result,
const std::string& verdict);
// Called when the DOM feature extraction times out.
void OnGetDomFeatureTimeout();
// If appropriate, collects visual features, otherwise continues on to sending
// the request.
void MaybeCollectVisualFeatures();
#endif // BUILDFLAG(SAFE_BROWSING_AVAILABLE)
#if BUILDFLAG(FULL_SAFE_BROWSING)
// Collects visual features from the current login page.
void CollectVisualFeatures();
// Processes the screenshot of the login page into visual features.
void OnScreenshotTaken(const SkBitmap& bitmap);
// Called when the visual feature extraction is complete.
void OnVisualFeatureCollectionDone(
std::unique_ptr<VisualFeatures> visual_features);
#endif // BUILDFLAG(FULL_SAFE_BROWSING)
#if defined(OS_ANDROID)
void SetReferringAppInfo() override;
#endif // defined(OS_ANDROID)
// WebContents of the password protection event.
content::WebContents* web_contents_;
// Cancels the request when it is no longer valid.
std::unique_ptr<RequestCanceler> request_canceler_;
#if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
// When we start extracting visual features.
base::TimeTicks visual_feature_start_time_;
......@@ -329,10 +384,7 @@ class PasswordProtectionRequest
bool dom_features_collection_complete_;
#endif // BUILDFLAG(SAFE_BROWSING_AVAILABLE)
// Cancels the request when it is no longer valid.
std::unique_ptr<RequestCanceler> request_canceler_;
base::WeakPtrFactory<PasswordProtectionRequest> weakptr_factory_{this};
base::WeakPtrFactory<PasswordProtectionRequestContent> weakptr_factory_{this};
};
} // namespace safe_browsing
......
......@@ -206,7 +206,7 @@ void PasswordProtectionServiceBase::StartRequest(
bool password_field_exists) {
DCHECK(CurrentlyOnThread(ThreadID::UI));
scoped_refptr<PasswordProtectionRequest> request(
new PasswordProtectionRequest(
new PasswordProtectionRequestContent(
web_contents, main_frame_url, password_form_action,
password_form_frame_url, web_contents->GetContentsMimeType(),
username, password_type, matching_reused_credentials, trigger_type,
......@@ -541,7 +541,9 @@ PasswordProtectionService::MaybeCreateNavigationThrottle(
content::WebContents* web_contents = navigation_handle->GetWebContents();
for (scoped_refptr<PasswordProtectionRequest> request : pending_requests_) {
if (request->web_contents() == web_contents &&
PasswordProtectionRequestContent* request_content =
static_cast<PasswordProtectionRequestContent*>(request.get());
if (request_content->web_contents() == web_contents &&
request->trigger_type() ==
safe_browsing::LoginReputationClientRequest::PASSWORD_REUSE_EVENT &&
IsSupportedPasswordTypeForModalWarning(
......@@ -553,7 +555,9 @@ PasswordProtectionService::MaybeCreateNavigationThrottle(
}
for (scoped_refptr<PasswordProtectionRequest> request : warning_requests_) {
if (request->web_contents() == web_contents) {
PasswordProtectionRequestContent* request_content =
static_cast<PasswordProtectionRequestContent*>(request.get());
if (request_content->web_contents() == web_contents) {
return std::make_unique<PasswordProtectionNavigationThrottle>(
navigation_handle, request, /*is_warning_showing=*/true);
}
......@@ -564,7 +568,9 @@ PasswordProtectionService::MaybeCreateNavigationThrottle(
void PasswordProtectionService::RemoveWarningRequestsByWebContents(
content::WebContents* web_contents) {
for (auto it = warning_requests_.begin(); it != warning_requests_.end();) {
if (it->get()->web_contents() == web_contents)
PasswordProtectionRequestContent* request_content =
static_cast<PasswordProtectionRequestContent*>(it->get());
if (request_content->web_contents() == web_contents)
it = warning_requests_.erase(it);
else
++it;
......@@ -574,7 +580,9 @@ void PasswordProtectionService::RemoveWarningRequestsByWebContents(
bool PasswordProtectionService::IsModalWarningShowingInWebContents(
content::WebContents* web_contents) {
for (const auto& request : warning_requests_) {
if (request->web_contents() == web_contents)
PasswordProtectionRequestContent* request_content =
static_cast<PasswordProtectionRequestContent*>(request.get());
if (request_content->web_contents() == web_contents)
return true;
}
return false;
......
......@@ -292,6 +292,7 @@ class PasswordProtectionServiceBase : public history::HistoryServiceObserver {
protected:
friend class PasswordProtectionRequest;
friend class PasswordProtectionRequestContent;
// Chrome can send password protection ping if it is allowed by for the
// |trigger_type| and |password_type| and if Safe Browsing can compute
......
......@@ -254,14 +254,16 @@ class PasswordProtectionServiceTest : public ::testing::Test {
content::WebContents::CreateParams(&browser_context_)));
const std::vector<password_manager::MatchingReusedCredential>
matching_reused_credentials = {};
request_ = base::MakeRefCounted<safe_browsing::PasswordProtectionRequest>(
web_contents_.get(), GURL(kTargetUrl), /*password_form_action=*/GURL(),
/*password_form_frame_url=*/GURL(),
web_contents_->GetContentsMimeType(), kUserName,
PasswordType::PASSWORD_TYPE_UNKNOWN, matching_reused_credentials,
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
/*password_field_exists=*/true, password_protection_service_.get(),
/*request_timeout_in_ms=*/10000);
request_ =
base::MakeRefCounted<safe_browsing::PasswordProtectionRequestContent>(
web_contents_.get(), GURL(kTargetUrl),
/*password_form_action=*/GURL(),
/*password_form_frame_url=*/GURL(),
web_contents_->GetContentsMimeType(), kUserName,
PasswordType::PASSWORD_TYPE_UNKNOWN, matching_reused_credentials,
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
/*password_field_exists=*/true, password_protection_service_.get(),
/*request_timeout_in_ms=*/10000);
}
void TearDown() override {
......@@ -367,7 +369,7 @@ class PasswordProtectionServiceBaseTest
.WillRepeatedly(
Return(match_whitelist ? AsyncMatch::MATCH : AsyncMatch::NO_MATCH));
request_ = new PasswordProtectionRequest(
request_ = new PasswordProtectionRequestContent(
web_contents, target_url, GURL(kFormActionUrl), GURL(kPasswordFrameUrl),
web_contents->GetContentsMimeType(), kUserName,
PasswordType::PASSWORD_TYPE_UNKNOWN, {},
......@@ -388,7 +390,7 @@ class PasswordProtectionServiceBaseTest
.WillRepeatedly(
Return(match_whitelist ? AsyncMatch::MATCH : AsyncMatch::NO_MATCH));
request_ = new PasswordProtectionRequest(
request_ = new PasswordProtectionRequestContent(
web_contents, target_url, GURL(), GURL(),
web_contents->GetContentsMimeType(), kUserName, type,
matching_reused_credentials,
......
......@@ -9,13 +9,13 @@
namespace safe_browsing {
scoped_refptr<PasswordProtectionRequest> CreateDummyRequest(
scoped_refptr<PasswordProtectionRequestContent> CreateDummyRequest(
content::WebContents* web_contents) {
std::unique_ptr<safe_browsing::MockPasswordProtectionService>
password_protection_service =
std::make_unique<safe_browsing::MockPasswordProtectionService>();
scoped_refptr<PasswordProtectionRequest> request =
base::MakeRefCounted<PasswordProtectionRequest>(
scoped_refptr<PasswordProtectionRequestContent> request =
base::MakeRefCounted<PasswordProtectionRequestContent>(
web_contents, GURL(), GURL(), GURL(),
web_contents->GetContentsMimeType(), "",
PasswordType::PASSWORD_TYPE_UNKNOWN,
......
......@@ -16,7 +16,7 @@ namespace safe_browsing {
// Returns a request object with |web_contents|. Other request options are set
// to some default value and potentially nonsensical.
scoped_refptr<PasswordProtectionRequest> CreateDummyRequest(
scoped_refptr<PasswordProtectionRequestContent> CreateDummyRequest(
content::WebContents* web_contents);
} // namespace safe_browsing
......
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