blob: 5efb8a000de2e3e6240f783f3f2d9edf7aeecc3d [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "signin_manager_android.h"
#include <memory>
#include <set>
#include "base/android/build_info.h"
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_factory.h"
#include "chrome/browser/download/chrome_download_manager_delegate.h"
#include "chrome/browser/download/download_core_service_factory.h"
#include "chrome/browser/download/download_core_service_impl.h"
#include "chrome/browser/offline_pages/offline_page_model_factory.h"
#include "chrome/browser/password_manager/account_password_store_factory.h"
#include "chrome/browser/password_manager/profile_password_store_factory.h"
#include "chrome/browser/profiles/profile_key.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/test/bookmark_test_helpers.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/keyed_service/core/service_access_type.h"
#include "components/keyed_service/core/simple_factory_key.h"
#include "components/offline_pages/core/stub_offline_page_model.h"
#include "components/password_manager/core/browser/password_manager_test_utils.h"
#include "components/password_manager/core/browser/password_store/test_password_store.h"
#include "components/password_manager/core/browser/split_stores_and_local_upm.h"
#include "content/public/browser/background_tracing_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "url/origin.h"
using ::testing::IsEmpty;
using ::testing::Pair;
using ::testing::SizeIs;
using ::testing::UnorderedElementsAre;
namespace {
class MockOfflinePageModel : public offline_pages::StubOfflinePageModel {
public:
void DeleteCachedPagesByURLPredicate(
const offline_pages::UrlPredicate& predicate,
offline_pages::DeletePageCallback callback) override {
std::move(callback).Run(DeletePageResult::SUCCESS);
}
};
std::unique_ptr<KeyedService> BuildOfflinePageModel(SimpleFactoryKey* key) {
return std::make_unique<MockOfflinePageModel>();
}
} // namespace
class SigninManagerAndroidTest : public ::testing::Test {
public:
SigninManagerAndroidTest() {
// Override the GMS version to be big enough for local UPM support, so
// DoNotWipePasswordsIfLocalUpmOn still passes on bots with outdated GMS.
base::android::BuildInfo::GetInstance()->set_gms_version_code_for_test(
base::NumberToString(password_manager::GetLocalUpmMinGmsVersion()));
}
SigninManagerAndroidTest(const SigninManagerAndroidTest&) = delete;
SigninManagerAndroidTest& operator=(const SigninManagerAndroidTest&) = delete;
~SigninManagerAndroidTest() override = default;
void SetUp() override {
TestingProfile::Builder profile_builder;
profile_builder.AddTestingFactories(
{TestingProfile::TestingFactory{
BookmarkModelFactory::GetInstance(),
BookmarkModelFactory::GetDefaultFactory()},
TestingProfile::TestingFactory{
ProfilePasswordStoreFactory::GetInstance(),
base::BindRepeating(&password_manager::BuildPasswordStore<
content::BrowserContext,
password_manager::TestPasswordStore>)},
TestingProfile::TestingFactory{
AccountPasswordStoreFactory::GetInstance(),
base::BindRepeating(&password_manager::BuildPasswordStoreWithArgs<
content::BrowserContext,
password_manager::TestPasswordStore,
password_manager::IsAccountStore>,
password_manager::IsAccountStore(true))}});
profile_ = profile_builder.Build();
background_tracing_manager_ =
content::BackgroundTracingManager::CreateInstance();
// Creating a BookmarkModel also a creates a StubOfflinePageModel.
// We need to replace this with a mock that responds to deletions.
offline_pages::OfflinePageModelFactory::GetInstance()->SetTestingFactory(
profile_->GetProfileKey(), base::BindRepeating(&BuildOfflinePageModel));
// TODO(crbug.com/41335519): Remove requirement for this delegate in
// unit_tests.
DownloadCoreServiceFactory::GetForBrowserContext(profile_.get())
->SetDownloadManagerDelegateForTesting(
std::make_unique<ChromeDownloadManagerDelegate>(profile_.get()));
}
void TearDown() override { background_tracing_manager_.reset(); }
TestingProfile* profile() { return profile_.get(); }
password_manager::TestPasswordStore* profile_password_store() {
return static_cast<password_manager::TestPasswordStore*>(
ProfilePasswordStoreFactory::GetForProfile(
profile_.get(), ServiceAccessType::EXPLICIT_ACCESS)
.get());
}
password_manager::TestPasswordStore* account_password_store() {
return static_cast<password_manager::TestPasswordStore*>(
AccountPasswordStoreFactory::GetForProfile(
profile_.get(), ServiceAccessType::EXPLICIT_ACCESS)
.get());
}
// Adds two testing bookmarks to |profile_|.
bookmarks::BookmarkModel* AddTestBookmarks() {
bookmarks::BookmarkModel* bookmark_model =
BookmarkModelFactory::GetForBrowserContext(profile());
bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model);
bookmark_model->AddURL(bookmark_model->bookmark_bar_node(), 0, u"Example 1",
GURL("https://example.org/1"));
bookmark_model->AddURL(bookmark_model->bookmark_bar_node(), 1, u"Example 2",
GURL("https://example.com/2"));
return bookmark_model;
}
// Calls SigninManager::WipeData(|all_data|) and waits for its completion.
void WipeData(bool all_data) {
std::unique_ptr<base::RunLoop> run_loop(new base::RunLoop());
SigninManagerAndroid::WipeData(profile(), all_data,
run_loop->QuitClosure());
run_loop->Run();
}
private:
content::BrowserTaskEnvironment task_environment_;
ScopedTestingLocalState local_state_{TestingBrowserProcess::GetGlobal()};
std::unique_ptr<TestingProfile> profile_;
std::unique_ptr<content::BackgroundTracingManager>
background_tracing_manager_;
};
// Tests that wiping all data also deletes bookmarks.
TEST_F(SigninManagerAndroidTest, DeleteBookmarksWhenWipingAllData) {
bookmarks::BookmarkModel* bookmark_model = AddTestBookmarks();
ASSERT_GE(bookmark_model->bookmark_bar_node()->children().size(), 0u);
WipeData(true);
EXPECT_EQ(0u, bookmark_model->bookmark_bar_node()->children().size());
}
// Tests that wiping Google service worker caches does not delete bookmarks.
TEST_F(SigninManagerAndroidTest, DontDeleteBookmarksWhenDeletingSWCaches) {
bookmarks::BookmarkModel* bookmark_model = AddTestBookmarks();
size_t num_bookmarks = bookmark_model->bookmark_bar_node()->children().size();
ASSERT_GE(num_bookmarks, 0u);
WipeData(false);
EXPECT_EQ(num_bookmarks,
bookmark_model->bookmark_bar_node()->children().size());
}
TEST_F(SigninManagerAndroidTest, DoNotWipePasswordsIfLocalUpmOn) {
password_manager::PasswordForm profile_store_form;
profile_store_form.username_value = u"username";
profile_store_form.password_value = u"password";
profile_store_form.signon_realm = "https://local.com";
password_manager::PasswordForm account_store_form = profile_store_form;
account_store_form.signon_realm = "htts://account.com";
profile_password_store()->AddLogin(profile_store_form);
ASSERT_TRUE(account_password_store());
account_password_store()->AddLogin(account_store_form);
WipeData(/*all_data=*/true);
EXPECT_THAT(
profile_password_store()->stored_passwords(),
UnorderedElementsAre(Pair(profile_store_form.signon_realm, SizeIs(1))));
EXPECT_THAT(
account_password_store()->stored_passwords(),
UnorderedElementsAre(Pair(account_store_form.signon_realm, SizeIs(1))));
}
class SigninManagerAndroidWithoutLocalUpmTest
: public SigninManagerAndroidTest {
public:
SigninManagerAndroidWithoutLocalUpmTest() {
// Fake a user with outdated GmsCore.
base::android::BuildInfo::GetInstance()->set_gms_version_code_for_test("0");
}
};
TEST_F(SigninManagerAndroidWithoutLocalUpmTest, WipePasswordsIfLocalUpmOff) {
password_manager::PasswordForm form;
form.username_value = u"username";
form.password_value = u"password";
form.signon_realm = "https://g.com";
profile_password_store()->AddLogin(form);
ASSERT_FALSE(account_password_store());
WipeData(/*all_data=*/true);
EXPECT_THAT(profile_password_store()->stored_passwords(), IsEmpty());
}