blob: c137b255d687d190b6044cdebc196d36f0bde151 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <string>
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/test/bind.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/browsing_data/browsing_data_api.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/account_reconcilor_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/sync/sync_ui_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/signin/public/base/signin_buildflags.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/identity_test_utils.h"
#include "components/sync/driver/sync_service.h"
#include "components/sync/driver/sync_user_settings.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/test/browser_test.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "url/gurl.h"
using extension_function_test_utils::RunFunctionAndReturnSingleResult;
namespace {
class ExtensionBrowsingDataTest : public InProcessBrowserTest {};
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
// TODO(http://crbug.com/1266606): appcache is a noop and should be removed.
const char kRemoveEverythingArguments[] =
R"([{"since": 1000}, {
"appcache": true, "cache": true, "cookies": true,
"downloads": true, "fileSystems": true, "formData": true,
"history": true, "indexedDB": true, "localStorage": true,
"serverBoundCertificates": true, "passwords": true,
"pluginData": true, "serviceWorkers": true, "cacheStorage": true,
"webSQL": true
}])";
// Sets the SAPISID Gaia cookie, which is monitored by the AccountReconcilor.
bool SetGaiaCookieForProfile(Profile* profile) {
GURL google_url = GaiaUrls::GetInstance()->secure_google_url();
auto cookie = net::CanonicalCookie::CreateUnsafeCookieForTesting(
"SAPISID", std::string(), "." + google_url.host(), "/", base::Time(),
base::Time(), base::Time(), base::Time(),
/*secure=*/true, false, net::CookieSameSite::NO_RESTRICTION,
net::COOKIE_PRIORITY_DEFAULT, false);
bool success = false;
base::RunLoop loop;
base::OnceClosure loop_quit = loop.QuitClosure();
base::OnceCallback<void(net::CookieAccessResult)> callback =
base::BindLambdaForTesting(
[&success, &loop_quit](net::CookieAccessResult r) {
success = r.status.IsInclude();
std::move(loop_quit).Run();
});
network::mojom::CookieManager* cookie_manager =
profile->GetDefaultStoragePartition()
->GetCookieManagerForBrowserProcess();
cookie_manager->SetCanonicalCookie(
*cookie, google_url, net::CookieOptions::MakeAllInclusive(),
mojo::WrapCallbackWithDefaultInvokeIfNotRun(
std::move(callback),
net::CookieAccessResult(net::CookieInclusionStatus(
net::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR))));
loop.Run();
return success;
}
#endif
} // namespace
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
// Test that Sync is not paused when browsing data is cleared.
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, Syncing) {
Profile* profile = browser()->profile();
// Set a Gaia cookie.
ASSERT_TRUE(SetGaiaCookieForProfile(profile));
// Set a Sync account and a secondary account.
const char kPrimaryAccountEmail[] = "primary@email.com";
const char kSecondaryAccountEmail[] = "secondary@email.com";
signin::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(profile);
AccountInfo primary_account_info = signin::MakePrimaryAccountAvailable(
identity_manager, kPrimaryAccountEmail, signin::ConsentLevel::kSync);
AccountInfo secondary_account_info =
signin::MakeAccountAvailable(identity_manager, kSecondaryAccountEmail);
// Sync is running.
syncer::SyncService* sync_service =
SyncServiceFactory::GetForProfile(profile);
sync_service->GetUserSettings()->SetSyncRequested(true);
sync_service->GetUserSettings()->SetFirstSetupComplete(
syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
ASSERT_EQ(SyncStatusMessageType::kSynced, GetSyncStatusMessageType(profile));
// Clear browsing data.
auto function = base::MakeRefCounted<BrowsingDataRemoveFunction>();
EXPECT_EQ(nullptr,
RunFunctionAndReturnSingleResult(
function.get(), kRemoveEverythingArguments, browser()));
// Check that the Sync token was not revoked.
EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(
primary_account_info.account_id));
EXPECT_FALSE(
identity_manager->HasAccountWithRefreshTokenInPersistentErrorState(
primary_account_info.account_id));
// Check that the secondary token was revoked.
EXPECT_FALSE(identity_manager->HasAccountWithRefreshToken(
secondary_account_info.account_id));
}
// Test that Sync is paused when browsing data is cleared if Sync was in
// authentication error.
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, SyncError) {
Profile* profile = browser()->profile();
// Set a Gaia cookie.
ASSERT_TRUE(SetGaiaCookieForProfile(profile));
// Set a Sync account with authentication error.
const char kAccountEmail[] = "account@email.com";
signin::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(profile);
AccountInfo account_info = signin::MakePrimaryAccountAvailable(
identity_manager, kAccountEmail, signin::ConsentLevel::kSync);
signin::UpdatePersistentErrorOfRefreshTokenForAccount(
identity_manager, account_info.account_id,
GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::
CREDENTIALS_REJECTED_BY_SERVER));
// Sync is not running.
ASSERT_NE(SyncStatusMessageType::kSynced, GetSyncStatusMessageType(profile));
// Clear browsing data.
auto function = base::MakeRefCounted<BrowsingDataRemoveFunction>();
EXPECT_EQ(nullptr,
RunFunctionAndReturnSingleResult(
function.get(), kRemoveEverythingArguments, browser()));
// Check that the account was not removed and Sync was paused.
EXPECT_TRUE(
identity_manager->HasAccountWithRefreshToken(account_info.account_id));
EXPECT_EQ(GoogleServiceAuthError::InvalidGaiaCredentialsReason::
CREDENTIALS_REJECTED_BY_CLIENT,
identity_manager
->GetErrorStateOfRefreshTokenForAccount(account_info.account_id)
.GetInvalidGaiaCredentialsReason());
}
// Test that the tokens are revoked when browsing data is cleared when there is
// no primary account.
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, NotSyncing) {
Profile* profile = browser()->profile();
// Set a Gaia cookie.
ASSERT_TRUE(SetGaiaCookieForProfile(profile));
// Set a non-Sync account.
const char kAccountEmail[] = "account@email.com";
auto* identity_manager = IdentityManagerFactory::GetForProfile(profile);
AccountInfo account_info =
signin::MakeAccountAvailable(identity_manager, kAccountEmail);
// Clear browsing data.
auto function = base::MakeRefCounted<BrowsingDataRemoveFunction>();
EXPECT_EQ(nullptr,
RunFunctionAndReturnSingleResult(
function.get(), kRemoveEverythingArguments, browser()));
// Check that the account was removed.
EXPECT_FALSE(
identity_manager->HasAccountWithRefreshToken(account_info.account_id));
}
#endif