Commit 05f2ff8a authored by mkwst's avatar mkwst Committed by Commit bot

Credential Manager: Wire `notifySignedOut` to the PasswordStore.

When `notifySignedOut` is called, we need to ensure that we stop
automagically providing a user's credentials to the website that
triggered the notification. This CL does that in the brute-force
way that we all know and love: grab all forms, walk through each
and set a flag for matching origins.

BUG=450581

Review URL: https://codereview.chromium.org/902843002

Cr-Commit-Position: refs/heads/master@{#315016}
parent c3d07759
......@@ -487,6 +487,9 @@ void BrowsingDataRemover::RemoveImpl(int remove_mask,
}
#endif
MediaDeviceIDSalt::Reset(profile_->GetPrefs());
// TODO(mkwst): If we're not removing passwords, then clear the 'zero-click'
// flag for all credentials in the password store.
}
// Channel IDs are not separated for protected and unprotected web
......
......@@ -261,13 +261,32 @@ TEST_F(CredentialManagerDispatcherTest, CredentialManagerIncognitoSignedIn) {
}
TEST_F(CredentialManagerDispatcherTest, CredentialManagerOnNotifySignedOut) {
store_->AddLogin(form_);
store_->AddLogin(cross_origin_form_);
RunAllPendingTasks();
TestPasswordStore::PasswordMap passwords = store_->stored_passwords();
EXPECT_EQ(2U, passwords.size());
EXPECT_EQ(1U, passwords[form_.signon_realm].size());
EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
EXPECT_FALSE(passwords[form_.signon_realm][0].skip_zero_click);
EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
dispatcher()->OnNotifySignedOut(kRequestId);
RunAllPendingTasks();
const uint32 kMsgID = CredentialManagerMsg_AcknowledgeSignedOut::ID;
const IPC::Message* message =
process()->sink().GetFirstMessageMatching(kMsgID);
EXPECT_TRUE(message);
process()->sink().ClearMessages();
passwords = store_->stored_passwords();
EXPECT_EQ(2U, passwords.size());
EXPECT_EQ(1U, passwords[form_.signon_realm].size());
EXPECT_EQ(1U, passwords[cross_origin_form_.signon_realm].size());
EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click);
EXPECT_FALSE(passwords[cross_origin_form_.signon_realm][0].skip_zero_click);
}
TEST_F(CredentialManagerDispatcherTest,
......
......@@ -23,6 +23,8 @@
namespace password_manager {
// CredentialManagerDispatcher::PendingRequestTask -----------------------------
class CredentialManagerDispatcher::PendingRequestTask
: public PasswordStoreConsumer {
public:
......@@ -102,6 +104,60 @@ class CredentialManagerDispatcher::PendingRequestTask
DISALLOW_COPY_AND_ASSIGN(PendingRequestTask);
};
// CredentialManagerDispatcher::PendingSignedOutTask ---------------------------
class CredentialManagerDispatcher::PendingSignedOutTask
: public PasswordStoreConsumer {
public:
PendingSignedOutTask(CredentialManagerDispatcher* const dispatcher,
const GURL& origin);
void AddOrigin(const GURL& origin);
// PasswordStoreConsumer implementation.
void OnGetPasswordStoreResults(
const std::vector<autofill::PasswordForm*>& results) override;
private:
// Backlink to the CredentialManagerDispatcher that owns this object.
CredentialManagerDispatcher* const dispatcher_;
std::set<std::string> origins_;
DISALLOW_COPY_AND_ASSIGN(PendingSignedOutTask);
};
CredentialManagerDispatcher::PendingSignedOutTask::PendingSignedOutTask(
CredentialManagerDispatcher* const dispatcher,
const GURL& origin)
: dispatcher_(dispatcher) {
origins_.insert(origin.spec());
}
void CredentialManagerDispatcher::PendingSignedOutTask::AddOrigin(
const GURL& origin) {
origins_.insert(origin.spec());
}
void CredentialManagerDispatcher::PendingSignedOutTask::
OnGetPasswordStoreResults(
const std::vector<autofill::PasswordForm*>& results) {
PasswordStore* store = dispatcher_->GetPasswordStore();
for (autofill::PasswordForm* form : results) {
if (origins_.count(form->origin.spec())) {
form->skip_zero_click = true;
store->UpdateLogin(*form);
}
// We own the PasswordForms, so we need to dispose of them. This is safe to
// do, as ::UpdateLogin ends up copying the form while posting a task to
// update the PasswordStore.
delete form;
}
dispatcher_->DoneSigningOut();
}
// CredentialManagerDispatcher -------------------------------------------------
CredentialManagerDispatcher::CredentialManagerDispatcher(
content::WebContents* web_contents,
PasswordManagerClient* client)
......@@ -153,6 +209,7 @@ void CredentialManagerDispatcher::OnNotifySignedIn(
scoped_ptr<autofill::PasswordForm> form(CreatePasswordFormFromCredentialInfo(
credential, web_contents()->GetLastCommittedURL().GetOrigin()));
form->skip_zero_click = !IsZeroClickAllowed();
// TODO(mkwst): This is a stub; we should be checking the PasswordStore to
// determine whether or not the credential exists, and calling UpdateLogin
......@@ -168,7 +225,22 @@ void CredentialManagerDispatcher::OnProvisionalSaveComplete() {
void CredentialManagerDispatcher::OnNotifySignedOut(int request_id) {
DCHECK(request_id);
// TODO(mkwst): This is a stub.
PasswordStore* store = GetPasswordStore();
if (store) {
if (!pending_sign_out_) {
pending_sign_out_.reset(new PendingSignedOutTask(
this, web_contents()->GetLastCommittedURL().GetOrigin()));
// This will result in a callback to
// PendingSignedOutTask::OnGetPasswordStoreResults().
store->GetAutofillableLogins(pending_sign_out_.get());
} else {
pending_sign_out_->AddOrigin(
web_contents()->GetLastCommittedURL().GetOrigin());
}
}
web_contents()->GetRenderViewHost()->Send(
new CredentialManagerMsg_AcknowledgeSignedOut(
web_contents()->GetRenderViewHost()->GetRoutingID(), request_id));
......@@ -234,6 +306,9 @@ void CredentialManagerDispatcher::SendCredential(int request_id,
const CredentialInfo& info) {
DCHECK(pending_request_);
DCHECK_EQ(pending_request_->id(), request_id);
// TODO(mkwst): We need to update the underlying PasswordForm if the user
// has enabled zeroclick globally, and clicks through a non-zeroclick form
// for an origin.
web_contents()->GetRenderViewHost()->Send(
new CredentialManagerMsg_SendCredential(
web_contents()->GetRenderViewHost()->GetRoutingID(),
......@@ -241,4 +316,9 @@ void CredentialManagerDispatcher::SendCredential(int request_id,
pending_request_.reset();
}
void CredentialManagerDispatcher::DoneSigningOut() {
DCHECK(pending_sign_out_);
pending_sign_out_.reset();
}
} // namespace password_manager
......@@ -72,6 +72,7 @@ class CredentialManagerDispatcher : public content::WebContentsObserver {
private:
class PendingRequestTask;
class PendingSignedOutTask;
PasswordStore* GetPasswordStore();
......@@ -83,6 +84,7 @@ class CredentialManagerDispatcher : public content::WebContentsObserver {
virtual base::WeakPtr<PasswordManagerDriver> GetDriver();
void SendCredential(int request_id, const CredentialInfo& info);
void DoneSigningOut();
PasswordManagerClient* client_;
scoped_ptr<CredentialManagerPasswordFormManager> form_manager_;
......@@ -95,6 +97,7 @@ class CredentialManagerDispatcher : public content::WebContentsObserver {
// they can properly respond to the request once the PasswordStore gives
// us data.
scoped_ptr<PendingRequestTask> pending_request_;
scoped_ptr<PendingSignedOutTask> pending_sign_out_;
DISALLOW_COPY_AND_ASSIGN(CredentialManagerDispatcher);
};
......
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