Commit 100173ff authored by Vasilii Sukhanov's avatar Vasilii Sukhanov Committed by Commit Bot

Do not open the password bubble if the state of the controller has changed.

Previously the following happened:
- a background tab decided that it should pop up a password bubble.
- the bubble was suppressed as the tab is inactive.
- another event changed the state of the controller but the flag to open the bubble was still on.
- the tab became active and the bubble was popped up despite the state was unexpected.

With this CL the bubble is not gonna open automatically when the state has changed in the mean time.

Bug: 805556
Change-Id: Ia66054889550b1b26b3abeb5926acbb8d7ceea05
Reviewed-on: https://chromium-review.googlesource.com/893381
Commit-Queue: Vasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: default avatarVaclav Brozek <vabr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#532916}
parent 8ff58008
...@@ -145,6 +145,7 @@ void ManagePasswordsUIController::OnHideManualFallbackForSaving() { ...@@ -145,6 +145,7 @@ void ManagePasswordsUIController::OnHideManualFallbackForSaving() {
save_fallback_timer_.Stop(); save_fallback_timer_.Stop();
ClearPopUpFlagForBubble();
if (passwords_data_.GetCurrentForms().empty()) if (passwords_data_.GetCurrentForms().empty())
passwords_data_.OnInactive(); passwords_data_.OnInactive();
else else
...@@ -218,6 +219,7 @@ void ManagePasswordsUIController::OnPasswordAutofilled( ...@@ -218,6 +219,7 @@ void ManagePasswordsUIController::OnPasswordAutofilled(
// for the user that the current state. // for the user that the current state.
if (passwords_data_.state() == password_manager::ui::INACTIVE_STATE || if (passwords_data_.state() == password_manager::ui::INACTIVE_STATE ||
passwords_data_.state() == password_manager::ui::MANAGE_STATE) { passwords_data_.state() == password_manager::ui::MANAGE_STATE) {
ClearPopUpFlagForBubble();
passwords_data_.OnPasswordAutofilled(password_form_map, origin, passwords_data_.OnPasswordAutofilled(password_form_map, origin,
federated_matches); federated_matches);
// Don't close the existing bubble. Update the icon later. // Don't close the existing bubble. Update the icon later.
...@@ -232,8 +234,10 @@ void ManagePasswordsUIController::OnLoginsChanged( ...@@ -232,8 +234,10 @@ void ManagePasswordsUIController::OnLoginsChanged(
const password_manager::PasswordStoreChangeList& changes) { const password_manager::PasswordStoreChangeList& changes) {
password_manager::ui::State current_state = GetState(); password_manager::ui::State current_state = GetState();
passwords_data_.ProcessLoginsChanged(changes); passwords_data_.ProcessLoginsChanged(changes);
if (current_state != GetState()) if (current_state != GetState()) {
ClearPopUpFlagForBubble();
UpdateBubbleAndIconVisibility(); UpdateBubbleAndIconVisibility();
}
} }
void ManagePasswordsUIController::UpdateIconAndBubbleState( void ManagePasswordsUIController::UpdateIconAndBubbleState(
...@@ -247,8 +251,7 @@ void ManagePasswordsUIController::UpdateIconAndBubbleState( ...@@ -247,8 +251,7 @@ void ManagePasswordsUIController::UpdateIconAndBubbleState(
icon->SetState(GetState()); icon->SetState(GetState());
ShowBubbleWithoutUserInteraction(); ShowBubbleWithoutUserInteraction();
// If the bubble appeared then the status is updated in OnBubbleShown(). // If the bubble appeared then the status is updated in OnBubbleShown().
if (ShouldBubblePopUp()) ClearPopUpFlagForBubble();
bubble_status_ = NOT_SHOWN;
} else { } else {
password_manager::ui::State state = GetState(); password_manager::ui::State state = GetState();
// The dialog should hide the icon. // The dialog should hide the icon.
...@@ -439,6 +442,7 @@ void ManagePasswordsUIController::UpdatePassword( ...@@ -439,6 +442,7 @@ void ManagePasswordsUIController::UpdatePassword(
save_fallback_timer_.Stop(); save_fallback_timer_.Stop();
UpdatePasswordInternal(password_form); UpdatePasswordInternal(password_form);
ClearPopUpFlagForBubble();
passwords_data_.TransitionToState(password_manager::ui::MANAGE_STATE); passwords_data_.TransitionToState(password_manager::ui::MANAGE_STATE);
UpdateBubbleAndIconVisibility(); UpdateBubbleAndIconVisibility();
} }
...@@ -454,6 +458,7 @@ void ManagePasswordsUIController::ChooseCredential( ...@@ -454,6 +458,7 @@ void ManagePasswordsUIController::ChooseCredential(
autofill::PasswordForm copy_form = form; autofill::PasswordForm copy_form = form;
dialog_controller_.reset(); dialog_controller_.reset();
passwords_data_.ChooseCredential(&copy_form); passwords_data_.ChooseCredential(&copy_form);
ClearPopUpFlagForBubble();
passwords_data_.TransitionToState(password_manager::ui::MANAGE_STATE); passwords_data_.TransitionToState(password_manager::ui::MANAGE_STATE);
UpdateBubbleAndIconVisibility(); UpdateBubbleAndIconVisibility();
} }
...@@ -491,6 +496,7 @@ void ManagePasswordsUIController::NavigateToChromeSignIn() { ...@@ -491,6 +496,7 @@ void ManagePasswordsUIController::NavigateToChromeSignIn() {
void ManagePasswordsUIController::OnDialogHidden() { void ManagePasswordsUIController::OnDialogHidden() {
dialog_controller_.reset(); dialog_controller_.reset();
if (GetState() == password_manager::ui::CREDENTIAL_REQUEST_STATE) { if (GetState() == password_manager::ui::CREDENTIAL_REQUEST_STATE) {
ClearPopUpFlagForBubble();
passwords_data_.TransitionToState(password_manager::ui::MANAGE_STATE); passwords_data_.TransitionToState(password_manager::ui::MANAGE_STATE);
UpdateBubbleAndIconVisibility(); UpdateBubbleAndIconVisibility();
} }
...@@ -545,12 +551,14 @@ void ManagePasswordsUIController::UpdateBubbleAndIconVisibility() { ...@@ -545,12 +551,14 @@ void ManagePasswordsUIController::UpdateBubbleAndIconVisibility() {
// display either the bubble or the icon. // display either the bubble or the icon.
if (!ChromePasswordManagerClient::CanShowBubbleOnURL( if (!ChromePasswordManagerClient::CanShowBubbleOnURL(
web_contents()->GetLastCommittedURL())) { web_contents()->GetLastCommittedURL())) {
ClearPopUpFlagForBubble();
passwords_data_.OnInactive(); passwords_data_.OnInactive();
} }
Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
if (!browser) if (!browser)
return; return;
LocationBar* location_bar = browser->window()->GetLocationBar(); LocationBar* location_bar = browser->window()->GetLocationBar();
DCHECK(location_bar); DCHECK(location_bar);
location_bar->UpdateManagePasswordsIconAndBubble(); location_bar->UpdateManagePasswordsIconAndBubble();
...@@ -588,6 +596,7 @@ void ManagePasswordsUIController::DidFinishNavigation( ...@@ -588,6 +596,7 @@ void ManagePasswordsUIController::DidFinishNavigation(
// Otherwise, reset the password manager. // Otherwise, reset the password manager.
DestroyAccountChooser(); DestroyAccountChooser();
ClearPopUpFlagForBubble();
passwords_data_.OnInactive(); passwords_data_.OnInactive();
UpdateBubbleAndIconVisibility(); UpdateBubbleAndIconVisibility();
} }
...@@ -605,12 +614,18 @@ base::TimeDelta ManagePasswordsUIController::GetTimeoutForSaveFallback() { ...@@ -605,12 +614,18 @@ base::TimeDelta ManagePasswordsUIController::GetTimeoutForSaveFallback() {
void ManagePasswordsUIController::ShowBubbleWithoutUserInteraction() { void ManagePasswordsUIController::ShowBubbleWithoutUserInteraction() {
DCHECK(ShouldBubblePopUp()); DCHECK(ShouldBubblePopUp());
Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
if (!browser || browser->toolbar_model()->input_in_progress()) // Can be zero in the tests.
if (!browser)
return; return;
chrome::ExecuteCommand(browser, IDC_MANAGE_PASSWORDS_FOR_PAGE); chrome::ExecuteCommand(browser, IDC_MANAGE_PASSWORDS_FOR_PAGE);
} }
void ManagePasswordsUIController::ClearPopUpFlagForBubble() {
if (ShouldBubblePopUp())
bubble_status_ = NOT_SHOWN;
}
void ManagePasswordsUIController::DestroyAccountChooser() { void ManagePasswordsUIController::DestroyAccountChooser() {
if (dialog_controller_ && dialog_controller_->IsShowingAccountChooser()) { if (dialog_controller_ && dialog_controller_->IsShowingAccountChooser()) {
dialog_controller_.reset(); dialog_controller_.reset();
......
...@@ -132,6 +132,13 @@ class ManagePasswordsUIController ...@@ -132,6 +132,13 @@ class ManagePasswordsUIController
bool AuthenticateUser() override; bool AuthenticateUser() override;
bool ArePasswordsRevealedWhenBubbleIsOpened() const override; bool ArePasswordsRevealedWhenBubbleIsOpened() const override;
#if defined(UNIT_TEST)
// Overwrites the client for |passwords_data_|.
void set_client(password_manager::PasswordManagerClient* client) {
passwords_data_.set_client(client);
}
#endif // defined(UNIT_TEST)
protected: protected:
explicit ManagePasswordsUIController( explicit ManagePasswordsUIController(
content::WebContents* web_contents); content::WebContents* web_contents);
...@@ -165,11 +172,6 @@ class ManagePasswordsUIController ...@@ -165,11 +172,6 @@ class ManagePasswordsUIController
bubble_status_ == SHOULD_POP_UP_AFTER_REAUTH; bubble_status_ == SHOULD_POP_UP_AFTER_REAUTH;
} }
// Overwrites the client for |passwords_data_|.
void set_client(password_manager::PasswordManagerClient* client) {
passwords_data_.set_client(client);
}
// content::WebContentsObserver: // content::WebContentsObserver:
void DidFinishNavigation( void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override; content::NavigationHandle* navigation_handle) override;
...@@ -196,6 +198,10 @@ class ManagePasswordsUIController ...@@ -196,6 +198,10 @@ class ManagePasswordsUIController
// Shows the password bubble without user interaction. // Shows the password bubble without user interaction.
void ShowBubbleWithoutUserInteraction(); void ShowBubbleWithoutUserInteraction();
// Resets |bubble_status_| signalling that if the bubble was due to pop up,
// it shouldn't anymore.
void ClearPopUpFlagForBubble();
// Closes the account chooser gracefully so the callback is called. Then sets // Closes the account chooser gracefully so the callback is called. Then sets
// the state to MANAGE_STATE. // the state to MANAGE_STATE.
void DestroyAccountChooser(); void DestroyAccountChooser();
......
...@@ -181,6 +181,7 @@ class ManagePasswordsUIControllerTest : public ChromeRenderViewHostTestHarness { ...@@ -181,6 +181,7 @@ class ManagePasswordsUIControllerTest : public ChromeRenderViewHostTestHarness {
void SetUp() override; void SetUp() override;
password_manager::StubPasswordManagerClient& client() { return client_; }
password_manager::FakeFormFetcher& fetcher() { return fetcher_; } password_manager::FakeFormFetcher& fetcher() { return fetcher_; }
autofill::PasswordForm& test_local_form() { return test_local_form_; } autofill::PasswordForm& test_local_form() { return test_local_form_; }
autofill::PasswordForm& test_federated_form() { return test_federated_form_; } autofill::PasswordForm& test_federated_form() { return test_federated_form_; }
...@@ -429,6 +430,33 @@ TEST_F(ManagePasswordsUIControllerTest, PasswordSubmittedBubbleNotSuppressed) { ...@@ -429,6 +430,33 @@ TEST_F(ManagePasswordsUIControllerTest, PasswordSubmittedBubbleNotSuppressed) {
variations::testing::ClearAllVariationParams(); variations::testing::ClearAllVariationParams();
} }
TEST_F(ManagePasswordsUIControllerTest, PasswordSubmittedBubbleCancelled) {
// Test on the real controller.
std::unique_ptr<content::WebContents> web_content(CreateTestWebContents());
content::WebContentsTester::For(web_content.get())
->NavigateAndCommit(GURL("http://example.com"));
ManagePasswordsUIController::CreateForWebContents(web_content.get());
ManagePasswordsUIController* controller =
ManagePasswordsUIController::FromWebContents(web_content.get());
controller->set_client(&client());
std::unique_ptr<password_manager::PasswordFormManager> test_form_manager(
CreateFormManager());
test_form_manager->ProvisionallySave(
test_local_form(),
password_manager::PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
// The bubble is ready to open but the tab is inactive. Therefore, we don't
// call UpdateIconAndBubbleState here.
controller->OnPasswordSubmitted(std::move(test_form_manager));
EXPECT_TRUE(controller->IsAutomaticallyOpeningBubble());
// The tab navigated in background. Because the controller's state has changed
// the bubble shouldn't pop up anymore.
content::WebContentsTester::For(web_content.get())
->NavigateAndCommit(GURL("http://google.com"));
EXPECT_FALSE(controller->IsAutomaticallyOpeningBubble());
}
TEST_F(ManagePasswordsUIControllerTest, PasswordSaved) { TEST_F(ManagePasswordsUIControllerTest, PasswordSaved) {
std::unique_ptr<password_manager::PasswordFormManager> test_form_manager( std::unique_ptr<password_manager::PasswordFormManager> test_form_manager(
CreateFormManager()); CreateFormManager());
......
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