Commit 0e575f68 authored by msramek's avatar msramek Committed by Commit Bot

[Prototype] Delete Google service worker caches on Android signout.

Android Signin Manager already has the functionality to delete all data
when a managed user signs out.

This CL reuses that functionality to delete service worker caches when
any user signs out.

BUG=739982

Review-Url: https://codereview.chromium.org/2966763003
Cr-Commit-Position: refs/heads/master@{#486619}
parent 4f47f5ad
......@@ -540,7 +540,7 @@ public class SigninManager implements AccountTrackerService.OnSystemAccountsSeed
if (wipeData) {
wipeProfileData(wipeDataHooks);
} else {
onSignOutDone();
wipeGoogleServiceWorkerCaches(wipeDataHooks);
}
AccountTrackerService.get().invalidateAccountSeedStatus(true);
......@@ -592,6 +592,12 @@ public class SigninManager implements AccountTrackerService.OnSystemAccountsSeed
nativeWipeProfileData(mNativeSigninManagerAndroid, hooks);
}
private void wipeGoogleServiceWorkerCaches(WipeDataHooks hooks) {
if (hooks != null) hooks.preWipeData();
// This will call back to onProfileDataWiped().
nativeWipeGoogleServiceWorkerCaches(mNativeSigninManagerAndroid, hooks);
}
/**
* Convenience method to return a Promise to be fulfilled when the user's sync data has been
* wiped if the parameter is true, or an already fulfilled Promise if the parameter is false.
......@@ -679,6 +685,8 @@ public class SigninManager implements AccountTrackerService.OnSystemAccountsSeed
private native void nativeSignOut(long nativeSigninManagerAndroid);
private native String nativeGetManagementDomain(long nativeSigninManagerAndroid);
private native void nativeWipeProfileData(long nativeSigninManagerAndroid, WipeDataHooks hooks);
private native void nativeWipeGoogleServiceWorkerCaches(
long nativeSigninManagerAndroid, WipeDataHooks hooks);
private native void nativeClearLastSignedInUser(long nativeSigninManagerAndroid);
private native void nativeLogInSignedInUser(long nativeSigninManagerAndroid);
private native boolean nativeIsSignedInOnNative(long nativeSigninManagerAndroid);
......
......@@ -19,7 +19,6 @@
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browsing_data/browsing_data_helper.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
#include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
#include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h"
......@@ -31,6 +30,7 @@
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/common/pref_names.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/google/core/browser/google_util.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/cloud/cloud_policy_core.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
......@@ -42,6 +42,7 @@
#include "components/signin/core/browser/signin_metrics.h"
#include "components/signin/core/common/profile_management_switches.h"
#include "components/signin/core/common/signin_pref_names.h"
#include "content/public/browser/browsing_data_filter_builder.h"
#include "content/public/browser/browsing_data_remover.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/gaia_constants.h"
......@@ -53,19 +54,42 @@ using bookmarks::BookmarkModel;
namespace {
// A BrowsingDataRemover::Observer that clears all Profile data and then
// invokes a callback and deletes itself.
// A BrowsingDataRemover::Observer that clears Profile data and then invokes
// a callback and deletes itself. It can be configured to delete all data
// (for enterprise users) or only Google's service workers (for all users).
class ProfileDataRemover : public content::BrowsingDataRemover::Observer {
public:
ProfileDataRemover(Profile* profile, const base::Closure& callback)
ProfileDataRemover(Profile* profile,
bool all_data,
const base::Closure& callback)
: callback_(callback),
origin_runner_(base::ThreadTaskRunnerHandle::Get()),
remover_(content::BrowserContext::GetBrowsingDataRemover(profile)) {
remover_->AddObserver(this);
remover_->RemoveAndReply(
base::Time(), base::Time::Max(),
ChromeBrowsingDataRemoverDelegate::ALL_DATA_TYPES,
ChromeBrowsingDataRemoverDelegate::ALL_ORIGIN_TYPES, this);
if (all_data) {
remover_->RemoveAndReply(
base::Time(), base::Time::Max(),
ChromeBrowsingDataRemoverDelegate::ALL_DATA_TYPES,
ChromeBrowsingDataRemoverDelegate::ALL_ORIGIN_TYPES, this);
} else {
std::unique_ptr<content::BrowsingDataFilterBuilder> google_tld_filter =
content::BrowsingDataFilterBuilder::Create(
content::BrowsingDataFilterBuilder::WHITELIST);
// TODO(msramek): BrowsingDataFilterBuilder was not designed for
// large filters. Optimize it.
for (const std::string& domain :
google_util::GetGoogleRegistrableDomains()) {
google_tld_filter->AddRegisterableDomain(domain);
}
remover_->RemoveWithFilterAndReply(
base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE,
ChromeBrowsingDataRemoverDelegate::ALL_ORIGIN_TYPES,
std::move(google_tld_filter), this);
}
}
~ProfileDataRemover() override {}
......@@ -199,10 +223,21 @@ void SigninManagerAndroid::WipeProfileData(
base::android::ScopedJavaGlobalRef<jobject> java_callback;
java_callback.Reset(env, callback);
// The ProfileDataRemover deletes itself once done.
new ProfileDataRemover(
profile_, base::Bind(&SigninManagerAndroid::OnBrowsingDataRemoverDone,
weak_factory_.GetWeakPtr(), java_callback));
WipeData(profile_, true /* all data */,
base::Bind(&SigninManagerAndroid::OnBrowsingDataRemoverDone,
weak_factory_.GetWeakPtr(), java_callback));
}
void SigninManagerAndroid::WipeGoogleServiceWorkerCaches(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& callback) {
base::android::ScopedJavaGlobalRef<jobject> java_callback;
java_callback.Reset(env, callback);
WipeData(profile_, false /* only Google service worker caches */,
base::Bind(&SigninManagerAndroid::OnBrowsingDataRemoverDone,
weak_factory_.GetWeakPtr(), java_callback));
}
void SigninManagerAndroid::OnPolicyRegisterDone(
......@@ -315,6 +350,14 @@ void SigninManagerAndroid::OnSigninAllowedPrefChanged() {
SigninManagerFactory::GetForProfile(profile_)->IsSigninAllowed());
}
// static
void SigninManagerAndroid::WipeData(Profile* profile,
bool all_data,
const base::Closure& callback) {
// The ProfileDataRemover deletes itself once done.
new ProfileDataRemover(profile, all_data, callback);
}
static jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj) {
SigninManagerAndroid* signin_manager_android =
new SigninManagerAndroid(env, obj);
......
......@@ -57,10 +57,17 @@ class SigninManagerAndroid : public SigninManagerBase::Observer {
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
// Delete all data for this profile.
void WipeProfileData(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& hooks);
// Delete service worker caches for google.<eTLD>.
void WipeGoogleServiceWorkerCaches(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& hooks);
void LogInSignedInUser(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
......@@ -90,6 +97,9 @@ class SigninManagerAndroid : public SigninManagerBase::Observer {
const std::string& username) override;
private:
FRIEND_TEST_ALL_PREFIXES(SigninManagerAndroidTest,
DeleteGoogleServiceWorkerCaches);
~SigninManagerAndroid() override;
void OnPolicyRegisterDone(const std::string& dm_token,
......@@ -103,6 +113,10 @@ class SigninManagerAndroid : public SigninManagerBase::Observer {
void OnSigninAllowedPrefChanged();
static void WipeData(Profile* profile,
bool all_data,
const base::Closure& callback);
Profile* profile_;
// Java-side SigninManager object.
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// 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/memory/ref_counted.h"
#include "base/run_loop.h"
#include "chrome/browser/browsing_data/browsing_data_cache_storage_helper.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_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/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
class SigninManagerAndroidTest : public ::testing::Test {
public:
SigninManagerAndroidTest()
: profile_manager_(TestingBrowserProcess::GetGlobal()) {}
~SigninManagerAndroidTest() override{};
void SetUp() override {
ASSERT_TRUE(profile_manager_.SetUp());
profile_ = profile_manager_.CreateTestingProfile("Testing Profile");
}
TestingProfile* profile() { return profile_; }
private:
content::TestBrowserThreadBundle thread_bundle_;
TestingProfileManager profile_manager_;
TestingProfile* profile_; // Owned by |profile_manager_|.
DISALLOW_COPY_AND_ASSIGN(SigninManagerAndroidTest);
};
TEST_F(SigninManagerAndroidTest, DeleteGoogleServiceWorkerCaches) {
struct TestCase {
std::string worker_url;
bool should_be_deleted;
} kTestCases[] = {
// A Google domain.
{"https://google.com/foo/bar", true},
// A Google domain with long TLD.
{"https://plus.google.co.uk/?query_params", true},
// Youtube.
{"https://youtube.com", false},
// A random domain.
{"https://a.b.c.example.com", false},
// Another Google domain.
{"https://www.google.de/worker.html", true},
// Ports don't matter, only TLDs.
{"https://google.com:8444/worker.html", true},
};
// Add service workers.
scoped_refptr<CannedBrowsingDataCacheStorageHelper> helper(
new CannedBrowsingDataCacheStorageHelper(
content::BrowserContext::GetDefaultStoragePartition(profile())
->GetCacheStorageContext()));
for (const TestCase& test_case : kTestCases)
helper->AddCacheStorage(GURL(test_case.worker_url));
ASSERT_EQ(arraysize(kTestCases), helper->GetCacheStorageCount());
// Delete service workers and wait for completion.
base::RunLoop run_loop;
SigninManagerAndroid::WipeData(profile(),
false /* only Google service worker caches */,
run_loop.QuitClosure());
run_loop.Run();
// Test whether the correct service worker caches were deleted.
std::set<std::string> remaining_cache_storages;
for (const auto& info : helper->GetCacheStorageUsageInfo())
remaining_cache_storages.insert(info.origin.spec());
for (const TestCase& test_case : kTestCases) {
EXPECT_EQ(test_case.should_be_deleted,
base::ContainsKey(remaining_cache_storages, test_case.worker_url))
<< test_case.worker_url << " should "
<< (test_case.should_be_deleted ? "" : "NOT ")
<< "be deleted, but it was"
<< (test_case.should_be_deleted ? "NOT" : "") << ".";
}
}
......@@ -3016,6 +3016,7 @@ test("unit_tests") {
"../browser/android/physical_web/physical_web_data_source_android_unittest.cc",
"../browser/android/preferences/pref_service_bridge_unittest.cc",
"../browser/android/shortcut_info_unittest.cc",
"../browser/android/signin/signin_manager_android_unittest.cc",
"../browser/android/thumbnail/scoped_ptr_expiring_cache_unittest.cc",
"../browser/android/webapk/webapk_icon_hasher_unittest.cc",
"../browser/android/webapk/webapk_installer_unittest.cc",
......
......@@ -283,4 +283,30 @@ bool IsYoutubeDomainUrl(const GURL& url,
nullptr);
}
const std::vector<std::string>& GetGoogleRegistrableDomains() {
CR_DEFINE_STATIC_LOCAL(std::vector<std::string>, kGoogleRegisterableDomains,
());
// Initialize the list.
if (kGoogleRegisterableDomains.empty()) {
std::vector<std::string> tlds{GOOGLE_TLD_LIST};
for (const std::string& tld : tlds) {
std::string domain = "google." + tld;
// The Google TLD list might contain domains that are not considered
// to be registrable domains by net::registry_controlled_domains.
if (GetDomainAndRegistry(
domain,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES) !=
domain) {
continue;
}
kGoogleRegisterableDomains.push_back(domain);
}
}
return kGoogleRegisterableDomains;
}
} // namespace google_util
......@@ -8,6 +8,7 @@
#define COMPONENTS_GOOGLE_CORE_BROWSER_GOOGLE_UTIL_H_
#include <string>
#include <vector>
#include "base/strings/string_piece.h"
......@@ -112,6 +113,14 @@ bool IsYoutubeDomainUrl(const GURL& url,
SubdomainPermission subdomain_permission,
PortPermission port_permission);
// Returns the list of all Google's registerable domains, i.e. domains named
// google.<eTLD> owned by Google.
// TODO(msramek): This is currently only used to ensure the deletion of Google
// service workers on signout. Remove this once we have other options to do it,
// such as service workers discovering that signin cookies are missing and
// unregistering themselves.
const std::vector<std::string>& GetGoogleRegistrableDomains();
} // namespace google_util
#endif // COMPONENTS_GOOGLE_CORE_BROWSER_GOOGLE_UTIL_H_
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