Commit 6cb392eb authored by Dominic Battre's avatar Dominic Battre Committed by Commit Bot

Disable requirements fetching if browsing history is not synced

This CL disables password requirements fetching from gstatic unless the user
syncs browsing history without a custom passphrase.

NOTRY=true

Bug: 846694
Cq-Include-Trybots: luci.chromium.try:ios-simulator-full-configs;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: If500c349d4fcbc94c3fe8b6c74aec1f9a2403420
Reviewed-on: https://chromium-review.googlesource.com/1097411
Commit-Queue: Dominic Battré <battre@chromium.org>
Reviewed-by: default avatarVaclav Brozek <vabr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#566756}
parent a628d4ff
...@@ -593,6 +593,13 @@ password_manager::SyncState ChromePasswordManagerClient::GetPasswordSyncState() ...@@ -593,6 +593,13 @@ password_manager::SyncState ChromePasswordManagerClient::GetPasswordSyncState()
return password_manager_util::GetPasswordSyncState(sync_service); return password_manager_util::GetPasswordSyncState(sync_service);
} }
password_manager::SyncState ChromePasswordManagerClient::GetHistorySyncState()
const {
const browser_sync::ProfileSyncService* sync_service =
ProfileSyncServiceFactory::GetForProfile(profile_);
return password_manager_util::GetHistorySyncState(sync_service);
}
bool ChromePasswordManagerClient::WasLastNavigationHTTPError() const { bool ChromePasswordManagerClient::WasLastNavigationHTTPError() const {
DCHECK(web_contents()); DCHECK(web_contents());
......
...@@ -96,6 +96,7 @@ class ChromePasswordManagerClient ...@@ -96,6 +96,7 @@ class ChromePasswordManagerClient
PrefService* GetPrefs() const override; PrefService* GetPrefs() const override;
password_manager::PasswordStore* GetPasswordStore() const override; password_manager::PasswordStore* GetPasswordStore() const override;
password_manager::SyncState GetPasswordSyncState() const override; password_manager::SyncState GetPasswordSyncState() const override;
password_manager::SyncState GetHistorySyncState() const override;
bool WasLastNavigationHTTPError() const override; bool WasLastNavigationHTTPError() const override;
net::CertStatus GetMainFrameCertStatus() const override; net::CertStatus GetMainFrameCertStatus() const override;
bool IsIncognito() const override; bool IsIncognito() const override;
......
...@@ -108,6 +108,12 @@ void PasswordRequirementsSpecFetcherImpl::Fetch( ...@@ -108,6 +108,12 @@ void PasswordRequirementsSpecFetcherImpl::Fetch(
return; return;
} }
if (!url_loader_factory_) {
TriggerCallback(std::move(callback), ResultCode::kErrorNoUrlLoader,
PasswordRequirementsSpec());
return;
}
if (!origin.is_valid() || origin.HostIsIPAddress() || if (!origin.is_valid() || origin.HostIsIPAddress() ||
!origin.SchemeIsHTTPOrHTTPS()) { !origin.SchemeIsHTTPOrHTTPS()) {
VLOG(1) << "No valid origin"; VLOG(1) << "No valid origin";
......
...@@ -54,8 +54,10 @@ void PasswordGenerationManager::ProcessPasswordRequirements( ...@@ -54,8 +54,10 @@ void PasswordGenerationManager::ProcessPasswordRequirements(
return; return;
// Fetch password requirements for the domain. // Fetch password requirements for the domain.
password_requirements_service->PrefetchSpec( if (IsRequirementsFetchingEnabled()) {
client_->GetLastCommittedEntryURL().GetOrigin()); password_requirements_service->PrefetchSpec(
client_->GetLastCommittedEntryURL().GetOrigin());
}
// Store password requirements from the autofill server. // Store password requirements from the autofill server.
for (const autofill::FormStructure* form : forms) { for (const autofill::FormStructure* form : forms) {
...@@ -128,6 +130,10 @@ bool PasswordGenerationManager::IsGenerationEnabled(bool log_debug_data) const { ...@@ -128,6 +130,10 @@ bool PasswordGenerationManager::IsGenerationEnabled(bool log_debug_data) const {
return false; return false;
} }
bool PasswordGenerationManager::IsRequirementsFetchingEnabled() const {
return client_->GetHistorySyncState() == SYNCING_NORMAL_ENCRYPTION;
}
void PasswordGenerationManager::CheckIfFormClassifierShouldRun() { void PasswordGenerationManager::CheckIfFormClassifierShouldRun() {
if (autofill::FormStructure::IsAutofillFieldMetadataEnabled()) if (autofill::FormStructure::IsAutofillFieldMetadataEnabled())
driver_->AllowToRunFormClassifier(); driver_->AllowToRunFormClassifier();
......
...@@ -56,6 +56,10 @@ class PasswordGenerationManager { ...@@ -56,6 +56,10 @@ class PasswordGenerationManager {
// autofill::SavePasswordProgressLogger. // autofill::SavePasswordProgressLogger.
bool IsGenerationEnabled(bool log_debug_data) const; bool IsGenerationEnabled(bool log_debug_data) const;
// Determines whether the PasswordGeneraitonManager has the permission to
// fetch domain wide password requirements from gstatic.com.
bool IsRequirementsFetchingEnabled() const;
// Determine if the form classifier should run. If yes, sends a message to the // Determine if the form classifier should run. If yes, sends a message to the
// renderer. // renderer.
// TODO(crbug.com/621442): Remove client-side form classifier when server-side // TODO(crbug.com/621442): Remove client-side form classifier when server-side
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h" #include "base/metrics/field_trial.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_field.h" #include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_metrics.h" #include "components/autofill/core/browser/autofill_metrics.h"
...@@ -44,11 +45,11 @@ namespace password_manager { ...@@ -44,11 +45,11 @@ namespace password_manager {
namespace { namespace {
// Magic constants. // Magic constants.
// Origin of a server for which no domain wide requirements are given. // Host (suffix) of a server for which no domain wide requirements are given.
constexpr char kNoServerResponse[] = "https://www.no_server_response.com/"; constexpr char kNoServerResponse[] = "www.no_server_response.com";
// Origin of a server for which the autofill requirements are overriden via a // Host (suffix) of a server for which the autofill requirements are overriden
// domain wide spec. // via a domain wide spec.
constexpr char kHasServerResponse[] = "https://www.has_server_response.com/"; constexpr char kHasServerResponse[] = "www.has_server_response.com";
class TestPasswordManagerDriver : public StubPasswordManagerDriver { class TestPasswordManagerDriver : public StubPasswordManagerDriver {
public: public:
...@@ -113,9 +114,11 @@ class FakePasswordRequirementsSpecFetcher ...@@ -113,9 +114,11 @@ class FakePasswordRequirementsSpecFetcher
~FakePasswordRequirementsSpecFetcher() override = default; ~FakePasswordRequirementsSpecFetcher() override = default;
void Fetch(GURL origin, FetchCallback callback) override { void Fetch(GURL origin, FetchCallback callback) override {
if (origin.GetOrigin() == GURL(kNoServerResponse)) { if (origin.GetOrigin().host_piece().find(kNoServerResponse) !=
std::string::npos) {
std::move(callback).Run(autofill::PasswordRequirementsSpec()); std::move(callback).Run(autofill::PasswordRequirementsSpec());
} else if (origin.GetOrigin() == GURL(kHasServerResponse)) { } else if (origin.GetOrigin().host_piece().find(kHasServerResponse) !=
std::string::npos) {
std::move(callback).Run(GetDomainWideRequirements()); std::move(callback).Run(GetDomainWideRequirements());
} else { } else {
NOTREACHED(); NOTREACHED();
...@@ -126,6 +129,7 @@ class FakePasswordRequirementsSpecFetcher ...@@ -126,6 +129,7 @@ class FakePasswordRequirementsSpecFetcher
class MockPasswordManagerClient : public StubPasswordManagerClient { class MockPasswordManagerClient : public StubPasswordManagerClient {
public: public:
MOCK_CONST_METHOD0(GetPasswordSyncState, SyncState()); MOCK_CONST_METHOD0(GetPasswordSyncState, SyncState());
MOCK_CONST_METHOD0(GetHistorySyncState, SyncState());
MOCK_CONST_METHOD0(IsSavingAndFillingEnabledForCurrentPage, bool()); MOCK_CONST_METHOD0(IsSavingAndFillingEnabledForCurrentPage, bool());
MOCK_CONST_METHOD0(IsIncognito, bool()); MOCK_CONST_METHOD0(IsIncognito, bool());
...@@ -233,11 +237,11 @@ TEST_F(PasswordGenerationManagerTest, ProcessPasswordRequirements) { ...@@ -233,11 +237,11 @@ TEST_F(PasswordGenerationManagerTest, ProcessPasswordRequirements) {
.WillRepeatedly(testing::Return(true)); .WillRepeatedly(testing::Return(true));
EXPECT_CALL(*client_, GetPasswordSyncState()) EXPECT_CALL(*client_, GetPasswordSyncState())
.WillRepeatedly(testing::Return(SYNCING_NORMAL_ENCRYPTION)); .WillRepeatedly(testing::Return(SYNCING_NORMAL_ENCRYPTION));
struct { struct {
const char* name; const char* name;
bool has_domain_wide_requirements = false; bool has_domain_wide_requirements = false;
bool has_field_requirements = false; bool has_field_requirements = false;
bool allowed_to_fetch_specs = true;
autofill::PasswordRequirementsSpec expected_spec; autofill::PasswordRequirementsSpec expected_spec;
} kTests[] = { } kTests[] = {
{ {
...@@ -260,10 +264,24 @@ TEST_F(PasswordGenerationManagerTest, ProcessPasswordRequirements) { ...@@ -260,10 +264,24 @@ TEST_F(PasswordGenerationManagerTest, ProcessPasswordRequirements) {
.has_field_requirements = true, .has_field_requirements = true,
.expected_spec = GetDomainWideRequirements(), .expected_spec = GetDomainWideRequirements(),
}, },
{
.name = "Don't fetch spec if not allowed",
.has_domain_wide_requirements = true,
.allowed_to_fetch_specs = false,
// Default value is expected even though .has_domain_wide_requirements
// is true.
.expected_spec = autofill::PasswordRequirementsSpec(),
},
}; };
// The purpose of this counter is to generate unique URLs and field signatures
// so that no caching can happen between test runs. If this causes issues in
// the future, the test should be converted into a parameterized test that
// creates unqieue PasswordRequirementsService instances for each run.
int test_counter = 0;
for (const auto& test : kTests) { for (const auto& test : kTests) {
SCOPED_TRACE(test.name); SCOPED_TRACE(test.name);
++test_counter;
autofill::FormFieldData username; autofill::FormFieldData username;
username.label = ASCIIToUTF16("username"); username.label = ASCIIToUTF16("username");
...@@ -272,7 +290,8 @@ TEST_F(PasswordGenerationManagerTest, ProcessPasswordRequirements) { ...@@ -272,7 +290,8 @@ TEST_F(PasswordGenerationManagerTest, ProcessPasswordRequirements) {
autofill::FormFieldData password; autofill::FormFieldData password;
password.label = ASCIIToUTF16("password"); password.label = ASCIIToUTF16("password");
password.name = ASCIIToUTF16("password"); password.name =
ASCIIToUTF16(base::StringPrintf("password%d", test_counter));
password.form_control_type = "password"; password.form_control_type = "password";
autofill::FormData account_creation_form; autofill::FormData account_creation_form;
...@@ -299,14 +318,21 @@ TEST_F(PasswordGenerationManagerTest, ProcessPasswordRequirements) { ...@@ -299,14 +318,21 @@ TEST_F(PasswordGenerationManagerTest, ProcessPasswordRequirements) {
// Configure the last committed entry URL with some magic constants for // Configure the last committed entry URL with some magic constants for
// which the FakePasswordRequirementsFetcher is configured to respond // which the FakePasswordRequirementsFetcher is configured to respond
// with a filled or empty response. // with a filled or empty response.
GURL origin = test.has_domain_wide_requirements ? GURL(kHasServerResponse) GURL origin(base::StringPrintf("https://%d-%s/", test_counter,
: GURL(kNoServerResponse); test.has_domain_wide_requirements
? kHasServerResponse
: kNoServerResponse));
client_->SetLastCommittedEntryUrl(origin); client_->SetLastCommittedEntryUrl(origin);
std::string response_string; std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string)); ASSERT_TRUE(response.SerializeToString(&response_string));
autofill::FormStructure::ParseQueryResponse(response_string, forms); autofill::FormStructure::ParseQueryResponse(response_string, forms);
EXPECT_CALL(*client_, GetHistorySyncState())
.WillRepeatedly(testing::Return(test.allowed_to_fetch_specs
? SYNCING_NORMAL_ENCRYPTION
: NOT_SYNCING));
// Processs the password requirements with expected side effects of // Processs the password requirements with expected side effects of
// either storing the requirements from the AutofillQueryResponseContents) // either storing the requirements from the AutofillQueryResponseContents)
// in the PasswordRequirementsService or triggering a lookup for the // in the PasswordRequirementsService or triggering a lookup for the
......
...@@ -44,6 +44,10 @@ SyncState PasswordManagerClient::GetPasswordSyncState() const { ...@@ -44,6 +44,10 @@ SyncState PasswordManagerClient::GetPasswordSyncState() const {
return NOT_SYNCING; return NOT_SYNCING;
} }
SyncState PasswordManagerClient::GetHistorySyncState() const {
return NOT_SYNCING;
}
bool PasswordManagerClient::WasLastNavigationHTTPError() const { bool PasswordManagerClient::WasLastNavigationHTTPError() const {
return false; return false;
} }
......
...@@ -178,9 +178,14 @@ class PasswordManagerClient { ...@@ -178,9 +178,14 @@ class PasswordManagerClient {
// Reports whether and how passwords are synced in the embedder. The default // Reports whether and how passwords are synced in the embedder. The default
// implementation always returns NOT_SYNCING. // implementation always returns NOT_SYNCING.
// TODO(vabr): Factor this out of the client to the sync layer. // TODO(crbug.com/515108): Factor this out of the client to the sync layer.
virtual SyncState GetPasswordSyncState() const; virtual SyncState GetPasswordSyncState() const;
// Reports whether and how browsing history is synced in the embedder. The
// default implementation always returns NOT_SYNCING.
// TODO(crbug.com/515108): Factor this out of the client to the sync layer.
virtual SyncState GetHistorySyncState() const;
// Returns true if last navigation page had HTTP error i.e 5XX or 4XX // Returns true if last navigation page had HTTP error i.e 5XX or 4XX
virtual bool WasLastNavigationHTTPError() const; virtual bool WasLastNavigationHTTPError() const;
......
...@@ -97,6 +97,20 @@ password_manager::SyncState GetPasswordSyncState( ...@@ -97,6 +97,20 @@ password_manager::SyncState GetPasswordSyncState(
return password_manager::NOT_SYNCING; return password_manager::NOT_SYNCING;
} }
password_manager::SyncState GetHistorySyncState(
const syncer::SyncService* sync_service) {
if (sync_service && sync_service->IsFirstSetupComplete() &&
sync_service->IsSyncActive() &&
(sync_service->GetActiveDataTypes().Has(
syncer::HISTORY_DELETE_DIRECTIVES) ||
sync_service->GetActiveDataTypes().Has(syncer::PROXY_TABS))) {
return sync_service->IsUsingSecondaryPassphrase()
? password_manager::SYNCING_WITH_CUSTOM_PASSPHRASE
: password_manager::SYNCING_NORMAL_ENCRYPTION;
}
return password_manager::NOT_SYNCING;
}
void FindDuplicates( void FindDuplicates(
std::vector<std::unique_ptr<autofill::PasswordForm>>* forms, std::vector<std::unique_ptr<autofill::PasswordForm>>* forms,
std::vector<std::unique_ptr<autofill::PasswordForm>>* duplicates, std::vector<std::unique_ptr<autofill::PasswordForm>>* duplicates,
......
...@@ -33,10 +33,15 @@ class PrefService; ...@@ -33,10 +33,15 @@ class PrefService;
namespace password_manager_util { namespace password_manager_util {
// Reports whether and how passwords are currently synced. In particular, for a // Reports whether and how passwords are currently synced. In particular, for a
// null |sync_service| returns NOT_SYNCING_PASSWORDS. // null |sync_service| returns NOT_SYNCING.
password_manager::SyncState GetPasswordSyncState( password_manager::SyncState GetPasswordSyncState(
const syncer::SyncService* sync_service); const syncer::SyncService* sync_service);
// Reports whether and how browsing history is currently synced. In particular,
// for a null |sync_service| returns NOT_SYNCING.
password_manager::SyncState GetHistorySyncState(
const syncer::SyncService* sync_service);
// Finds the forms with a duplicate sync tags in |forms|. The first one of // Finds the forms with a duplicate sync tags in |forms|. The first one of
// the duplicated entries stays in |forms|, the others are moved to // the duplicated entries stays in |forms|, the others are moved to
// |duplicates|. // |duplicates|.
......
...@@ -55,6 +55,7 @@ class IOSChromePasswordManagerClient ...@@ -55,6 +55,7 @@ class IOSChromePasswordManagerClient
// password_manager::PasswordManagerClient implementation. // password_manager::PasswordManagerClient implementation.
password_manager::SyncState GetPasswordSyncState() const override; password_manager::SyncState GetPasswordSyncState() const override;
password_manager::SyncState GetHistorySyncState() const override;
bool PromptUserToSaveOrUpdatePassword( bool PromptUserToSaveOrUpdatePassword(
std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save, std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save,
bool update_password) override; bool update_password) override;
......
...@@ -76,6 +76,12 @@ SyncState IOSChromePasswordManagerClient::GetPasswordSyncState() const { ...@@ -76,6 +76,12 @@ SyncState IOSChromePasswordManagerClient::GetPasswordSyncState() const {
return password_manager_util::GetPasswordSyncState(sync_service); return password_manager_util::GetPasswordSyncState(sync_service);
} }
SyncState IOSChromePasswordManagerClient::GetHistorySyncState() const {
browser_sync::ProfileSyncService* sync_service =
ProfileSyncServiceFactory::GetForBrowserState(delegate_.browserState);
return password_manager_util::GetHistorySyncState(sync_service);
}
bool IOSChromePasswordManagerClient::PromptUserToChooseCredentials( bool IOSChromePasswordManagerClient::PromptUserToChooseCredentials(
std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms, std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
const GURL& origin, const GURL& origin,
......
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