Commit de1acf21 authored by Bo Liu's avatar Bo Liu Committed by Commit Bot

weblayer: Remove profile data before deletion

Commit writes and remove data before deleting the entire profile
directory. There are already no WebContents associated with the profile.
This is all to avoid racing with code that tries to write the profile
during deletion.

Bug: 1065585
Change-Id: Ic77fde85bccb7c0f79824bfc491ea6994dffdcab
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2135053Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Bo <boliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#756869}
parent d0d8a066
...@@ -12,7 +12,6 @@ import org.junit.Test; ...@@ -12,7 +12,6 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
...@@ -120,7 +119,6 @@ public class ProfileTest { ...@@ -120,7 +119,6 @@ public class ProfileTest {
@Test @Test
@SmallTest @SmallTest
@DisabledTest
public void testEnumerateAllProfileNames() throws Exception { public void testEnumerateAllProfileNames() throws Exception {
final String profileName = "TestEnumerateAllProfileNames"; final String profileName = "TestEnumerateAllProfileNames";
final WebLayer weblayer = mActivityTestRule.getWebLayer(); final WebLayer weblayer = mActivityTestRule.getWebLayer();
......
...@@ -56,11 +56,7 @@ public final class ProfileImpl extends IProfile.Stub { ...@@ -56,11 +56,7 @@ public final class ProfileImpl extends IProfile.Stub {
mDownloadCallbackProxy = new DownloadCallbackProxy(mName, mNativeProfile); mDownloadCallbackProxy = new DownloadCallbackProxy(mName, mNativeProfile);
} }
@Override private void destroyDependentJavaObjects() {
public void destroy() {
StrictModeWorkaround.apply();
if (mBeingDeleted) return;
if (mDownloadCallbackProxy != null) { if (mDownloadCallbackProxy != null) {
mDownloadCallbackProxy.destroy(); mDownloadCallbackProxy.destroy();
mDownloadCallbackProxy = null; mDownloadCallbackProxy = null;
...@@ -70,7 +66,14 @@ public final class ProfileImpl extends IProfile.Stub { ...@@ -70,7 +66,14 @@ public final class ProfileImpl extends IProfile.Stub {
mCookieManager.destroy(); mCookieManager.destroy();
mCookieManager = null; mCookieManager = null;
} }
}
@Override
public void destroy() {
StrictModeWorkaround.apply();
if (mBeingDeleted) return;
destroyDependentJavaObjects();
deleteNativeProfile(); deleteNativeProfile();
maybeRunDestroyCallback(); maybeRunDestroyCallback();
} }
...@@ -90,15 +93,19 @@ public final class ProfileImpl extends IProfile.Stub { ...@@ -90,15 +93,19 @@ public final class ProfileImpl extends IProfile.Stub {
public void destroyAndDeleteDataFromDisk(IObjectWrapper completionCallback) { public void destroyAndDeleteDataFromDisk(IObjectWrapper completionCallback) {
StrictModeWorkaround.apply(); StrictModeWorkaround.apply();
checkNotDestroyed(); checkNotDestroyed();
final Runnable callback = ObjectWrapper.unwrap(completionCallback, Runnable.class);
assert mNativeProfile != 0; assert mNativeProfile != 0;
mBeingDeleted = ProfileImplJni.get().deleteDataFromDisk(mNativeProfile, () -> { if (ProfileImplJni.get().getNumBrowserImpl(mNativeProfile) > 0) {
deleteNativeProfile();
if (callback != null) callback.run();
});
if (!mBeingDeleted) {
throw new IllegalStateException("Profile still in use: " + mName); throw new IllegalStateException("Profile still in use: " + mName);
} }
final Runnable callback = ObjectWrapper.unwrap(completionCallback, Runnable.class);
mBeingDeleted = true;
destroyDependentJavaObjects();
ProfileImplJni.get().destroyAndDeleteDataFromDisk(mNativeProfile, () -> {
if (callback != null) callback.run();
});
mNativeProfile = 0;
maybeRunDestroyCallback(); maybeRunDestroyCallback();
} }
...@@ -195,7 +202,8 @@ public final class ProfileImpl extends IProfile.Stub { ...@@ -195,7 +202,8 @@ public final class ProfileImpl extends IProfile.Stub {
void enumerateAllProfileNames(Callback<String[]> callback); void enumerateAllProfileNames(Callback<String[]> callback);
long createProfile(String name, ProfileImpl caller); long createProfile(String name, ProfileImpl caller);
void deleteProfile(long profile); void deleteProfile(long profile);
boolean deleteDataFromDisk(long nativeProfileImpl, Runnable completionCallback); int getNumBrowserImpl(long nativeProfileImpl);
void destroyAndDeleteDataFromDisk(long nativeProfileImpl, Runnable completionCallback);
void clearBrowsingData(long nativeProfileImpl, @ImplBrowsingDataType int[] dataTypes, void clearBrowsingData(long nativeProfileImpl, @ImplBrowsingDataType int[] dataTypes,
long fromMillis, long toMillis, Runnable callback); long fromMillis, long toMillis, Runnable callback);
void setDownloadDirectory(long nativeProfileImpl, String directory); void setDownloadDirectory(long nativeProfileImpl, String directory);
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "weblayer/browser/profile_impl.h" #include "weblayer/browser/profile_impl.h"
#include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
...@@ -19,7 +20,9 @@ ...@@ -19,7 +20,9 @@
#include "base/task/thread_pool.h" #include "base/task/thread_pool.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "components/prefs/pref_service.h"
#include "components/web_cache/browser/web_cache_manager.h" #include "components/web_cache/browser/web_cache_manager.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_remover.h" #include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/device_service.h" #include "content/public/browser/device_service.h"
...@@ -229,18 +232,6 @@ void ProfileImpl::DownloadsInitialized() { ...@@ -229,18 +232,6 @@ void ProfileImpl::DownloadsInitialized() {
#endif #endif
} }
bool ProfileImpl::DeleteDataFromDisk(base::OnceClosure done_callback) {
if (num_browser_impl_ > 0)
return false;
base::ThreadPool::PostTaskAndReply(
FROM_HERE,
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&NukeProfileFromDisk, name_, data_path_),
std::move(done_callback));
return true;
}
void ProfileImpl::ClearBrowsingData( void ProfileImpl::ClearBrowsingData(
const std::vector<BrowsingDataType>& data_types, const std::vector<BrowsingDataType>& data_types,
base::Time from_time, base::Time from_time,
...@@ -286,6 +277,31 @@ CookieManager* ProfileImpl::GetCookieManager() { ...@@ -286,6 +277,31 @@ CookieManager* ProfileImpl::GetCookieManager() {
return cookie_manager_.get(); return cookie_manager_.get();
} }
// static
void ProfileImpl::NukeDataAfterRemovingData(
std::unique_ptr<ProfileImpl> profile,
base::OnceClosure done_callback) {
// Need PostTask to avoid reentrancy for deleting |browser_context_|.
base::PostTask(FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&ProfileImpl::DoNukeData, std::move(profile),
std::move(done_callback)));
}
// static
void ProfileImpl::DoNukeData(std::unique_ptr<ProfileImpl> profile,
base::OnceClosure done_callback) {
std::string name = profile->name_;
base::FilePath data_path = profile->data_path_;
profile.reset();
base::ThreadPool::PostTaskAndReply(
FROM_HERE,
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&NukeProfileFromDisk, name, data_path),
std::move(done_callback));
}
void ProfileImpl::ClearRendererCache() { void ProfileImpl::ClearRendererCache() {
for (content::RenderProcessHost::iterator iter = for (content::RenderProcessHost::iterator iter =
content::RenderProcessHost::AllHostsIterator(); content::RenderProcessHost::AllHostsIterator();
...@@ -311,10 +327,44 @@ void ProfileImpl::OnLocaleChanged() { ...@@ -311,10 +327,44 @@ void ProfileImpl::OnLocaleChanged() {
i18n::GetAcceptLangs())); i18n::GetAcceptLangs()));
} }
// static
std::unique_ptr<Profile> Profile::Create(const std::string& name) { std::unique_ptr<Profile> Profile::Create(const std::string& name) {
return std::make_unique<ProfileImpl>(name); return std::make_unique<ProfileImpl>(name);
} }
// static
std::unique_ptr<Profile> Profile::DestroyAndDeleteDataFromDisk(
std::unique_ptr<Profile> profile,
base::OnceClosure done_callback) {
std::unique_ptr<ProfileImpl> impl(
static_cast<ProfileImpl*>(profile.release()));
return ProfileImpl::DestroyAndDeleteDataFromDisk(std::move(impl),
std::move(done_callback));
}
// static
std::unique_ptr<ProfileImpl> ProfileImpl::DestroyAndDeleteDataFromDisk(
std::unique_ptr<ProfileImpl> profile,
base::OnceClosure done_callback) {
if (profile->num_browser_impl_ > 0)
return profile;
// Try to finish all writes and remove all data before nuking the profile.
static_cast<BrowserContextImpl*>(profile->GetBrowserContext())
->pref_service()
->CommitPendingWrite();
// Unretained is safe here because DataClearer is owned by
// BrowserContextImpl which is owned by this.
auto* clearer = new DataClearer(
profile->GetBrowserContext(),
base::BindOnce(&ProfileImpl::NukeDataAfterRemovingData,
std::move(profile), std::move(done_callback)));
int remove_all_mask = 0x8fffffff;
clearer->ClearData(remove_all_mask, base::Time::Min(), base::Time::Max());
return nullptr;
}
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
ProfileImpl::ProfileImpl( ProfileImpl::ProfileImpl(
JNIEnv* env, JNIEnv* env,
...@@ -347,12 +397,21 @@ static void JNI_ProfileImpl_EnumerateAllProfileNames( ...@@ -347,12 +397,21 @@ static void JNI_ProfileImpl_EnumerateAllProfileNames(
base::android::ScopedJavaGlobalRef<jobject>(callback))); base::android::ScopedJavaGlobalRef<jobject>(callback)));
} }
jboolean ProfileImpl::DeleteDataFromDisk( jint ProfileImpl::GetNumBrowserImpl(JNIEnv* env) {
return num_browser_impl_;
}
void ProfileImpl::DestroyAndDeleteDataFromDisk(
JNIEnv* env, JNIEnv* env,
const base::android::JavaRef<jobject>& j_completion_callback) { const base::android::JavaRef<jobject>& j_completion_callback) {
return DeleteDataFromDisk(base::BindOnce( std::unique_ptr<ProfileImpl> ptr(this);
&base::android::RunRunnableAndroid, std::unique_ptr<ProfileImpl> result =
base::android::ScopedJavaGlobalRef<jobject>(j_completion_callback))); ProfileImpl::DestroyAndDeleteDataFromDisk(
std::move(ptr),
base::BindOnce(&base::android::RunRunnableAndroid,
base::android::ScopedJavaGlobalRef<jobject>(
j_completion_callback)));
CHECK(!result);
} }
void ProfileImpl::ClearBrowsingData( void ProfileImpl::ClearBrowsingData(
......
...@@ -34,6 +34,10 @@ class ProfileImpl : public Profile { ...@@ -34,6 +34,10 @@ class ProfileImpl : public Profile {
// |context| must not be null. // |context| must not be null.
static base::FilePath GetCachePath(content::BrowserContext* context); static base::FilePath GetCachePath(content::BrowserContext* context);
static std::unique_ptr<ProfileImpl> DestroyAndDeleteDataFromDisk(
std::unique_ptr<ProfileImpl> profile,
base::OnceClosure done_callback);
explicit ProfileImpl(const std::string& name); explicit ProfileImpl(const std::string& name);
~ProfileImpl() override; ~ProfileImpl() override;
...@@ -53,7 +57,6 @@ class ProfileImpl : public Profile { ...@@ -53,7 +57,6 @@ class ProfileImpl : public Profile {
DownloadDelegate* download_delegate() { return download_delegate_; } DownloadDelegate* download_delegate() { return download_delegate_; }
// Profile implementation: // Profile implementation:
bool DeleteDataFromDisk(base::OnceClosure done_callback) override;
void ClearBrowsingData(const std::vector<BrowsingDataType>& data_types, void ClearBrowsingData(const std::vector<BrowsingDataType>& data_types,
base::Time from_time, base::Time from_time,
base::Time to_time, base::Time to_time,
...@@ -67,7 +70,8 @@ class ProfileImpl : public Profile { ...@@ -67,7 +70,8 @@ class ProfileImpl : public Profile {
const base::android::JavaParamRef<jstring>& path, const base::android::JavaParamRef<jstring>& path,
const base::android::JavaParamRef<jobject>& java_profile); const base::android::JavaParamRef<jobject>& java_profile);
jboolean DeleteDataFromDisk( jint GetNumBrowserImpl(JNIEnv* env);
void DestroyAndDeleteDataFromDisk(
JNIEnv* env, JNIEnv* env,
const base::android::JavaRef<jobject>& j_completion_callback); const base::android::JavaRef<jobject>& j_completion_callback);
void ClearBrowsingData( void ClearBrowsingData(
...@@ -94,6 +98,10 @@ class ProfileImpl : public Profile { ...@@ -94,6 +98,10 @@ class ProfileImpl : public Profile {
private: private:
class DataClearer; class DataClearer;
static void NukeDataAfterRemovingData(std::unique_ptr<ProfileImpl> profile,
base::OnceClosure done_callback);
static void DoNukeData(std::unique_ptr<ProfileImpl> profile,
base::OnceClosure done_callback);
void ClearRendererCache(); void ClearRendererCache();
// Callback when the system locale has been updated. // Callback when the system locale has been updated.
......
...@@ -30,12 +30,15 @@ class Profile { ...@@ -30,12 +30,15 @@ class Profile {
// underscore. // underscore.
static std::unique_ptr<Profile> Create(const std::string& name); static std::unique_ptr<Profile> Create(const std::string& name);
virtual ~Profile() {}
// Delete all profile's data from disk. If there are any existing usage // Delete all profile's data from disk. If there are any existing usage
// of this profile, return false immediately and |done_callback| will not // of this profile, return |profile| immediately and |done_callback| will not
// be called. Otherwise |done_callback| is called when deletion is complete. // be called. Otherwise return nullptr and |done_callback| is called when
virtual bool DeleteDataFromDisk(base::OnceClosure done_callback) = 0; // deletion is complete.
static std::unique_ptr<Profile> DestroyAndDeleteDataFromDisk(
std::unique_ptr<Profile> profile,
base::OnceClosure done_callback);
virtual ~Profile() {}
virtual void ClearBrowsingData( virtual void ClearBrowsingData(
const std::vector<BrowsingDataType>& data_types, const std::vector<BrowsingDataType>& data_types,
......
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