From afb72b4c970ae3a62777099822d81df36598cedc Mon Sep 17 00:00:00 2001 From: lalitm Date: Fri, 11 Sep 2015 03:02:59 -0700 Subject: [PATCH] Clear webapp storage when site data is cleared From a privacy perspective, all webapp data should be cleared when site data is cleared by the user. Add the functionality to do this. Note: this CL does not delete the files themselves but no identifying information about either the webapp or the user is left in the SharedPreferences so there should be no problem. This is because of a platform limitation which does not allow SharedPreference consumers to delete the SharedPreference file. BUG=508627 Review URL: https://codereview.chromium.org/1329083002 Cr-Commit-Position: refs/heads/master@{#348370} --- .../privacy/ClearBrowsingDataDialogFragment.java | 6 ++ .../chrome/browser/webapps/WebappDataStorage.java | 23 +++- .../chrome/browser/webapps/WebappRegistry.java | 78 +++++++++++--- .../ClearBrowsingDataDialogFragmentTest.java | 119 +++++++++++++++++++++ .../chrome/browser/webapps/WebappRegistryTest.java | 73 ++++++++++--- chrome/browser/android/chrome_jni_registrar.cc | 2 + chrome/browser/android/webapps/webapp_registry.cc | 40 +++++++ chrome/browser/android/webapps/webapp_registry.h | 28 +++++ .../browser/browsing_data/browsing_data_remover.cc | 17 +++ .../browser/browsing_data/browsing_data_remover.h | 13 ++- chrome/chrome_browser.gypi | 3 + 11 files changed, 367 insertions(+), 35 deletions(-) create mode 100644 chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataDialogFragmentTest.java create mode 100644 chrome/browser/android/webapps/webapp_registry.cc create mode 100644 chrome/browser/android/webapps/webapp_registry.h diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataDialogFragment.java index 6a0b885c1d43..81add764e8eb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataDialogFragment.java @@ -24,6 +24,7 @@ import android.widget.Button; import android.widget.CheckedTextView; import android.widget.TextView; +import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.preferences.Preferences; @@ -280,4 +281,9 @@ public class ClearBrowsingDataDialogFragment extends DialogFragment getActivity().getString(R.string.clear_browsing_data_progress_message), true, false); } + + @VisibleForTesting + ProgressDialog getProgressDialog() { + return mProgressDialog; + } } diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java index 37511a3ccab4..20291a254180 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java @@ -36,7 +36,7 @@ public class WebappDataStorage { private final SharedPreferences mPreferences; /** - * Opens an instance of WebappDataStorage for the webapp specified. + * Opens an instance of WebappDataStorage for the web app specified. * @param context The context to open the SharedPreferences. * @param webappId The ID of the web app which is being opened. */ @@ -57,7 +57,7 @@ public class WebappDataStorage { * Asynchronously retrieves the time which this WebappDataStorage was last * opened using {@link WebappDataStorage#open(Context, String)}. * @param context The context to read the SharedPreferences file. - * @param webappId The ID of the webapp the used time is being read for. + * @param webappId The ID of the web app the used time is being read for. * @param callback Called when the last used time has been retrieved. */ public static void getLastUsedTime(final Context context, final String webappId, @@ -79,6 +79,17 @@ public class WebappDataStorage { } /** + * Deletes the data for a web app by clearing all the information inside the SharedPreferences + * file. This does NOT delete the file itself but the file is left empty. + * @param context The context to read the SharedPreferences file. + * @param webappId The ID of the web app being deleted. + */ + static void deleteDataForWebapp(final Context context, final String webappId) { + assert !ThreadUtils.runningOnUiThread(); + openSharedPreferences(context, webappId).edit().clear().commit(); + } + + /** * Sets the factory used to generate WebappDataStorage objects. */ @VisibleForTesting @@ -86,11 +97,15 @@ public class WebappDataStorage { sFactory = factory; } - protected WebappDataStorage(Context context, String webappId) { - mPreferences = context.getApplicationContext().getSharedPreferences( + private static SharedPreferences openSharedPreferences(Context context, String webappId) { + return context.getApplicationContext().getSharedPreferences( SHARED_PREFS_FILE_PREFIX + webappId, Context.MODE_PRIVATE); } + protected WebappDataStorage(Context context, String webappId) { + mPreferences = openSharedPreferences(context, webappId); + } + /* * Asynchronously retrieves the splash screen image associated with the * current web app. diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java index fe19baaa4b8a..dff54ad1e36a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java @@ -8,12 +8,15 @@ import android.content.Context; import android.content.SharedPreferences; import android.os.AsyncTask; +import org.chromium.base.VisibleForTesting; +import org.chromium.base.annotations.CalledByNative; + import java.util.Collections; import java.util.HashSet; import java.util.Set; /** - * Keeps track of webapps which have created a SharedPreference file (through the used of the + * Keeps track of web apps which have created a SharedPreference file (through the used of the * WebappDataStorage class) which may need to be cleaned up in the future. * * It is NOT intended to be 100% accurate nor a comprehensive list of all installed web apps @@ -27,6 +30,13 @@ public class WebappRegistry { static final String KEY_WEBAPP_SET = "webapp_set"; /** + * Called when a retrieval of the stored web apps occurs. + */ + public interface FetchCallback { + public void onWebappIdsRetrieved(Set readObject); + } + + /** * Registers the existence of a web app and creates the SharedPreference for it. * @param context Context to open the registry with. * @param webappId The id of the web app to register. @@ -35,16 +45,14 @@ public class WebappRegistry { new AsyncTask() { @Override protected final Void doInBackground(Void... nothing) { - SharedPreferences preferences = context.getSharedPreferences( - REGISTRY_FILE_NAME, Context.MODE_PRIVATE); - Set webapps = new HashSet( - preferences.getStringSet(KEY_WEBAPP_SET, Collections.emptySet())); + SharedPreferences preferences = openSharedPreferences(context); + Set webapps = new HashSet(getRegisteredWebappIds(preferences)); boolean added = webapps.add(webappId); assert added; - // Update the last used time of the webapp data storage so we can guarantee that - // the used time will be set (ie. != WebappDataStorage.INVALID_LAST_USED) if a - // webapp appears in the registry. + // Update the last used time of the {@link WebappDataStorage} so we can guarantee + // that the used time will be set (ie. != WebappDataStorage.INVALID_LAST_USED) if a + // web app appears in the registry. new WebappDataStorage(context, webappId).updateLastUsedTime(); preferences.edit().putStringSet(KEY_WEBAPP_SET, webapps).commit(); return null; @@ -57,13 +65,12 @@ public class WebappRegistry { * @param context Context to open the registry with. * @param callback Called when the set has been retrieved. The set may be empty. */ + @VisibleForTesting public static void getRegisteredWebappIds(final Context context, final FetchCallback callback) { new AsyncTask>() { @Override protected final Set doInBackground(Void... nothing) { - SharedPreferences preferences = context.getSharedPreferences( - REGISTRY_FILE_NAME, Context.MODE_PRIVATE); - return preferences.getStringSet(KEY_WEBAPP_SET, Collections.emptySet()); + return getRegisteredWebappIds(openSharedPreferences(context)); } @Override @@ -73,13 +80,50 @@ public class WebappRegistry { }.execute(); } - private WebappRegistry() { - } - /** - * Called when a retrieval of the stored web apps occurs. + * Deletes the data of all web apps, as well as the registry tracking the web apps. */ - public interface FetchCallback { - public void onWebappIdsRetrieved(Set readObject); + @VisibleForTesting + static void unregisterAllWebapps(final Context context, final Runnable callback) { + new AsyncTask() { + @Override + protected final Void doInBackground(Void... nothing) { + SharedPreferences preferences = openSharedPreferences(context); + for (String id : getRegisteredWebappIds(preferences)) { + WebappDataStorage.deleteDataForWebapp(context, id); + } + preferences.edit().clear().commit(); + return null; + } + + @Override + protected final void onPostExecute(Void nothing) { + if (callback == null) return; + callback.run(); + } + }.execute(); + } + + @CalledByNative + static void unregisterAllWebapps(Context context, final long callbackPointer) { + unregisterAllWebapps(context, new Runnable() { + @Override + public void run() { + nativeOnWebappsUnregistered(callbackPointer); + } + }); } + + private static SharedPreferences openSharedPreferences(Context context) { + return context.getSharedPreferences(REGISTRY_FILE_NAME, Context.MODE_PRIVATE); + } + + private static Set getRegisteredWebappIds(SharedPreferences preferences) { + return preferences.getStringSet(KEY_WEBAPP_SET, Collections.emptySet()); + } + + private WebappRegistry() { + } + + private static native void nativeOnWebappsUnregistered(long callbackPointer); } \ No newline at end of file diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataDialogFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataDialogFragmentTest.java new file mode 100644 index 000000000000..3ea1a98f63e7 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataDialogFragmentTest.java @@ -0,0 +1,119 @@ +// Copyright 2015 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. + +package org.chromium.chrome.browser.preferences.privacy; + +import android.app.Dialog; +import android.support.v7.app.AlertDialog; +import android.test.suitebuilder.annotation.MediumTest; +import android.widget.Button; + +import org.chromium.base.ThreadUtils; +import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.webapps.WebappRegistry; +import org.chromium.chrome.test.ChromeActivityTestCaseBase; +import org.chromium.content.browser.test.util.Criteria; +import org.chromium.content.browser.test.util.CriteriaHelper; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; + +/** + * Peforms integration tests with ClearBrowsingDataDialogFragment. + */ +public class ClearBrowsingDataDialogFragmentTest + extends ChromeActivityTestCaseBase { + + private TestClearDataDialogFragment mFragment; + private boolean mCallbackCalled; + + public ClearBrowsingDataDialogFragmentTest() { + super(ChromeActivity.class); + } + + @Override + public void startMainActivity() throws InterruptedException { + startMainActivityOnBlankPage(); + } + + @MediumTest + public void testClearingSiteDataClearsWebapps() throws Exception { + mFragment = new TestClearDataDialogFragment(EnumSet.of( + ClearBrowsingDataDialogFragment.DialogOption.CLEAR_COOKIES_AND_SITE_DATA)); + + WebappRegistry.registerWebapp(getActivity(), "first"); + WebappRegistry.getRegisteredWebappIds(getActivity(), new WebappRegistry.FetchCallback() { + @Override + public void onWebappIdsRetrieved(Set ids) { + assertEquals(new HashSet(Arrays.asList("first")), ids); + mCallbackCalled = true; + } + }); + assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() { + @Override + public boolean isSatisfied() { + return mCallbackCalled; + } + })); + mCallbackCalled = false; + + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mFragment.show(getActivity().getFragmentManager(), + ClearBrowsingDataDialogFragment.FRAGMENT_TAG); + } + }); + assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() { + @Override + public boolean isSatisfied() { + return mFragment.getDialog() != null; + } + })); + + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + Dialog dialog = mFragment.getDialog(); + Button clearButton = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE); + clearButton.performClick(); + } + }); + assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() { + @Override + public boolean isSatisfied() { + return mFragment.getProgressDialog() == null; + } + })); + + WebappRegistry.getRegisteredWebappIds(getActivity(), new WebappRegistry.FetchCallback() { + @Override + public void onWebappIdsRetrieved(Set ids) { + assertTrue(ids.isEmpty()); + mCallbackCalled = true; + } + }); + assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() { + @Override + public boolean isSatisfied() { + return mCallbackCalled; + } + })); + } + + private static class TestClearDataDialogFragment extends ClearBrowsingDataDialogFragment { + private final EnumSet mDefaultOptions; + + public TestClearDataDialogFragment(EnumSet defaultOptions) { + mDefaultOptions = defaultOptions; + } + + @Override + protected EnumSet getDefaultDialogOptionsSelections() { + return mDefaultOptions; + } + } +} diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java index a903f58a38c2..073e24bcb7e0 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java @@ -19,8 +19,10 @@ import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.annotation.Config; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.Map; import java.util.Set; /** @@ -82,13 +84,7 @@ public class WebappRegistryTest { @Test @Feature({"Webapp"}) public void testWebappIdsRetrieval() throws Exception { - final Set expected = new HashSet(); - expected.add("first"); - expected.add("second"); - - mSharedPreferences.edit() - .putStringSet(WebappRegistry.KEY_WEBAPP_SET, expected) - .commit(); + final Set expected = addWebappsToRegistry("first", "second"); WebappRegistry.getRegisteredWebappIds(Robolectric.application, new WebappRegistry.FetchCallback() { @@ -107,12 +103,7 @@ public class WebappRegistryTest { @Test @Feature({"Webapp"}) public void testWebappIdsRetrievalRegisterRetrival() throws Exception { - final Set expected = new HashSet(); - expected.add("first"); - - mSharedPreferences.edit() - .putStringSet(WebappRegistry.KEY_WEBAPP_SET, expected) - .commit(); + final Set expected = addWebappsToRegistry("first"); WebappRegistry.getRegisteredWebappIds(Robolectric.application, new WebappRegistry.FetchCallback() { @@ -149,4 +140,60 @@ public class WebappRegistryTest { assertTrue(mCallbackCalled); } + + @Test + @Feature({"Webapp"}) + public void testUnregisterRunsCallback() throws Exception { + WebappRegistry.unregisterAllWebapps(Robolectric.application, new Runnable() { + @Override + public void run() { + mCallbackCalled = true; + } + }); + BackgroundShadowAsyncTask.runBackgroundTasks(); + Robolectric.runUiThreadTasks(); + + assertTrue(mCallbackCalled); + } + + @Test + @Feature({"Webapp"}) + public void testUnregisterClearsRegistry() throws Exception { + addWebappsToRegistry("test"); + + WebappRegistry.unregisterAllWebapps(Robolectric.application, null); + BackgroundShadowAsyncTask.runBackgroundTasks(); + + assertTrue(getRegisteredWebapps().isEmpty()); + } + + @Test + @Feature({"Webapp"}) + public void testUnregisterClearsWebappDataStorage() throws Exception { + addWebappsToRegistry("test"); + SharedPreferences webAppPrefs = Robolectric.application.getSharedPreferences( + WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "test", Context.MODE_PRIVATE); + webAppPrefs.edit() + .putLong(WebappDataStorage.KEY_LAST_USED, 100L) + .commit(); + + WebappRegistry.unregisterAllWebapps(Robolectric.application, null); + BackgroundShadowAsyncTask.runBackgroundTasks(); + + Map actual = webAppPrefs.getAll(); + assertTrue(actual.isEmpty()); + } + + private Set addWebappsToRegistry(String... webapps) { + final Set expected = new HashSet(Arrays.asList(webapps)); + mSharedPreferences.edit() + .putStringSet(WebappRegistry.KEY_WEBAPP_SET, expected) + .commit(); + return expected; + } + + private Set getRegisteredWebapps() { + return mSharedPreferences.getStringSet( + WebappRegistry.KEY_WEBAPP_SET, Collections.emptySet()); + } } \ No newline at end of file diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc index 83848dafcc75..f20be0eb41ab 100644 --- a/chrome/browser/android/chrome_jni_registrar.cc +++ b/chrome/browser/android/chrome_jni_registrar.cc @@ -79,6 +79,7 @@ #include "chrome/browser/android/warmup_manager.h" #include "chrome/browser/android/web_contents_factory.h" #include "chrome/browser/android/webapps/add_to_homescreen_dialog_helper.h" +#include "chrome/browser/android/webapps/webapp_registry.h" #include "chrome/browser/autofill/android/personal_data_manager_android.h" #include "chrome/browser/dom_distiller/dom_distiller_service_factory_android.h" #include "chrome/browser/dom_distiller/tab_utils_android.h" @@ -331,6 +332,7 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = { {"Variations", variations::android::RegisterVariations}, {"VariationsSession", chrome::android::RegisterVariationsSession}, {"WarmupManager", RegisterWarmupManager}, + {"WebappRegistry", WebappRegistry::RegisterWebappRegistry}, {"WebContentsFactory", RegisterWebContentsFactory}, {"WebsitePreferenceBridge", RegisterWebsitePreferenceBridge}, {"WebsiteSettingsPopupAndroid", diff --git a/chrome/browser/android/webapps/webapp_registry.cc b/chrome/browser/android/webapps/webapp_registry.cc new file mode 100644 index 000000000000..e4466a3ea2e2 --- /dev/null +++ b/chrome/browser/android/webapps/webapp_registry.cc @@ -0,0 +1,40 @@ +// Copyright 2015 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 "chrome/browser/android/webapps/webapp_registry.h" + +#include + +#include "base/android/jni_android.h" +#include "base/callback.h" +#include "chrome/browser/io_thread.h" +#include "content/public/browser/browser_thread.h" +#include "jni/WebappRegistry_jni.h" + +// static +void WebappRegistry::UnregisterWebapps( + const base::Closure& callback) { + JNIEnv* env = base::android::AttachCurrentThread(); + uintptr_t callback_pointer = reinterpret_cast( + new base::Closure(callback)); + + Java_WebappRegistry_unregisterAllWebapps( + env, + base::android::GetApplicationContext(), + callback_pointer); +} + +// Callback used by Java when all web apps have been unregistered. +void OnWebappsUnregistered(JNIEnv* env, + const JavaParamRef& klass, + jlong jcallback) { + base::Closure* callback = reinterpret_cast(jcallback); + callback->Run(); + delete callback; +} + +// static +bool WebappRegistry::RegisterWebappRegistry(JNIEnv* env) { + return RegisterNativesImpl(env); +} diff --git a/chrome/browser/android/webapps/webapp_registry.h b/chrome/browser/android/webapps/webapp_registry.h new file mode 100644 index 000000000000..c54c2b9db861 --- /dev/null +++ b/chrome/browser/android/webapps/webapp_registry.h @@ -0,0 +1,28 @@ +// Copyright 2015 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. + +#ifndef CHROME_BROWSER_ANDROID_WEBAPPS_WEBAPP_REGISTRY_H_ +#define CHROME_BROWSER_ANDROID_WEBAPPS_WEBAPP_REGISTRY_H_ + +#include "base/android/jni_android.h" +#include "base/android/scoped_java_ref.h" +#include "base/callback_forward.h" + +// WebappRegistry is the C++ counterpart of +// org.chromium.chrome.browser.webapp's WebappRegistry in Java. +class WebappRegistry { + public: + // Registers JNI hooks. + static bool RegisterWebappRegistry(JNIEnv* env); + + // Cleans up data stored by web apps. + static void UnregisterWebapps(const base::Closure& callback); + + private: + ~WebappRegistry() = delete; + + DISALLOW_IMPLICIT_CONSTRUCTORS(WebappRegistry); +}; + +#endif // CHROME_BROWSER_ANDROID_WEBAPPS_WEBAPP_REGISTRY_H_ diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc index 12f327770805..16ffc0d04575 100644 --- a/chrome/browser/browsing_data/browsing_data_remover.cc +++ b/chrome/browser/browsing_data/browsing_data_remover.cc @@ -71,6 +71,7 @@ #include "url/origin.h" #if defined(OS_ANDROID) +#include "chrome/browser/android/webapps/webapp_registry.h" #include "chrome/browser/precache/precache_manager_factory.h" #include "components/precache/content/precache_manager.h" #endif @@ -760,6 +761,15 @@ void BrowsingDataRemover::RemoveImpl(int remove_mask, } } +#if defined(OS_ANDROID) + if (remove_mask & REMOVE_WEBAPP_DATA) { + waiting_for_clear_webapp_data_ = true; + WebappRegistry::UnregisterWebapps( + base::Bind(&BrowsingDataRemover::OnClearedWebappData, + base::Unretained(this))); + } +#endif + // Record the combined deletion of cookies and cache. CookieOrCacheDeletionChoice choice = NEITHER_COOKIES_NOR_CACHE; if (remove_mask & REMOVE_COOKIES && @@ -840,6 +850,7 @@ bool BrowsingDataRemover::AllDone() { !waiting_for_clear_pnacl_cache_ && #if defined(OS_ANDROID) !waiting_for_clear_precache_history_ && + !waiting_for_clear_webapp_data_ && #endif #if defined(ENABLE_WEBRTC) !waiting_for_clear_webrtc_logs_ && @@ -1132,6 +1143,12 @@ void BrowsingDataRemover::OnClearedPrecacheHistory() { waiting_for_clear_precache_history_ = false; NotifyAndDeleteIfDone(); } + +void BrowsingDataRemover::OnClearedWebappData() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + waiting_for_clear_webapp_data_ = false; + NotifyAndDeleteIfDone(); +} #endif void BrowsingDataRemover::OnClearedDomainReliabilityMonitor() { diff --git a/chrome/browser/browsing_data/browsing_data_remover.h b/chrome/browser/browsing_data/browsing_data_remover.h index 0333d9fe2762..2ebe6a0e2407 100644 --- a/chrome/browser/browsing_data/browsing_data_remover.h +++ b/chrome/browser/browsing_data/browsing_data_remover.h @@ -82,13 +82,17 @@ class BrowsingDataRemover REMOVE_NOCHECKS = 1 << 16, REMOVE_WEBRTC_IDENTITY = 1 << 17, REMOVE_CACHE_STORAGE = 1 << 18, +#if defined(OS_ANDROID) + REMOVE_WEBAPP_DATA = 1 << 19, +#endif // The following flag is used only in tests. In normal usage, hosted app // data is controlled by the REMOVE_COOKIES flag, applied to the // protected-web origin. REMOVE_HOSTED_APP_DATA_TESTONLY = 1 << 31, // "Site data" includes cookies, appcache, file systems, indexedDBs, local - // storage, webSQL, service workers, cache storage, and plugin data. + // storage, webSQL, service workers, cache storage, plugin data, and web app + // data (on Android). REMOVE_SITE_DATA = REMOVE_APPCACHE | REMOVE_COOKIES | REMOVE_FILE_SYSTEMS | REMOVE_INDEXEDDB | REMOVE_LOCAL_STORAGE | @@ -98,6 +102,9 @@ class BrowsingDataRemover REMOVE_WEBSQL | REMOVE_CHANNEL_IDS | REMOVE_SITE_USAGE_DATA | +#if defined(OS_ANDROID) + REMOVE_WEBAPP_DATA | +#endif REMOVE_WEBRTC_IDENTITY, // Includes all the available remove options. Meant to be used by clients @@ -386,6 +393,9 @@ class BrowsingDataRemover #if defined(OS_ANDROID) // Callback on UI thread when the precache history has been cleared. void OnClearedPrecacheHistory(); + + // Callback on UI thread when the webapp data has been cleared. + void OnClearedWebappData(); #endif void OnClearedDomainReliabilityMonitor(); @@ -446,6 +456,7 @@ class BrowsingDataRemover bool waiting_for_clear_pnacl_cache_ = false; #if defined(OS_ANDROID) bool waiting_for_clear_precache_history_ = false; + bool waiting_for_clear_webapp_data_ = false; #endif bool waiting_for_clear_storage_partition_data_ = false; #if defined(ENABLE_WEBRTC) diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 73da95ec65c5..d438c298dc45 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -259,6 +259,8 @@ 'browser/android/webapps/add_to_homescreen_dialog_helper.h', 'browser/android/webapps/single_tab_mode_tab_helper.cc', 'browser/android/webapps/single_tab_mode_tab_helper.h', + 'browser/android/webapps/webapp_registry.cc', + 'browser/android/webapps/webapp_registry.h', 'browser/app_controller_mac.h', 'browser/app_controller_mac.mm', 'browser/app_icon_win.cc', @@ -1834,6 +1836,7 @@ 'android/java/src/org/chromium/chrome/browser/ssl/ConnectionSecurity.java', 'android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java', 'android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenDialogHelper.java', + 'android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java', ], 'chrome_browser_mdns_sources': [ 'browser/local_discovery/privet_traffic_detector.cc', -- 2.11.4.GIT