Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5943)

Unified Diff: chrome/browser/android/preferences/website_preference_bridge.cc

Issue 850813002: Upstream Site Settings. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@location_settings_singleton
Patch Set: use findbugs annotations; fix test Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/android/preferences/website_preference_bridge.cc
diff --git a/chrome/browser/android/preferences/website_preference_bridge.cc b/chrome/browser/android/preferences/website_preference_bridge.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4ea9e47f788bd958f75a31abebbf9c097eb9fa10
--- /dev/null
+++ b/chrome/browser/android/preferences/website_preference_bridge.cc
@@ -0,0 +1,506 @@
+// 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/preferences/website_preference_bridge.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_path.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h"
+#include "chrome/browser/content_settings/cookie_settings.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
+#include "jni/WebsitePreferenceBridge_jni.h"
+#include "storage/browser/quota/quota_client.h"
+#include "storage/browser/quota/quota_manager.h"
+
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::JavaRef;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+using content::BrowserThread;
+
+static HostContentSettingsMap* GetHostContentSettingsMap() {
+ Profile* profile = ProfileManager::GetActiveUserProfile();
+ return profile->GetHostContentSettingsMap();
+}
+
+static void GetOrigins(JNIEnv* env,
+ ContentSettingsType content_type,
+ jobject list,
+ jboolean managedOnly) {
+ ContentSettingsForOneType all_settings;
+ HostContentSettingsMap* content_settings_map = GetHostContentSettingsMap();
+ content_settings_map->GetSettingsForOneType(
+ content_type, std::string(), &all_settings);
+ ContentSetting default_content_setting = content_settings_map->
+ GetDefaultContentSetting(content_type, NULL);
+ // Now add all origins that have a non-default setting to the list.
+ for (const auto& settings_it : all_settings) {
+ if (settings_it.setting == default_content_setting)
+ continue;
+ if (managedOnly &&
+ HostContentSettingsMap::GetProviderTypeFromSource(settings_it.source) !=
+ HostContentSettingsMap::ProviderType::POLICY_PROVIDER) {
+ continue;
+ }
+ const std::string origin = settings_it.primary_pattern.ToString();
+ const std::string embedder = settings_it.secondary_pattern.ToString();
+ ScopedJavaLocalRef<jstring> jorigin = ConvertUTF8ToJavaString(env, origin);
+ ScopedJavaLocalRef<jstring> jembedder;
+ if (embedder != origin)
+ jembedder = ConvertUTF8ToJavaString(env, embedder);
+ switch (content_type) {
+ case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
+ case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
+ Java_WebsitePreferenceBridge_insertVoiceAndVideoCaptureInfoIntoList(
+ env, list, jorigin.obj(), jembedder.obj());
+ break;
+ case CONTENT_SETTINGS_TYPE_GEOLOCATION:
+ Java_WebsitePreferenceBridge_insertGeolocationInfoIntoList(
+ env, list, jorigin.obj(), jembedder.obj());
+ break;
+ case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
+ Java_WebsitePreferenceBridge_insertMidiInfoIntoList(
+ env, list, jorigin.obj(), jembedder.obj());
+ break;
+ case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
+ Java_WebsitePreferenceBridge_insertProtectedMediaIdentifierInfoIntoList(
+ env, list, jorigin.obj(), jembedder.obj());
+ break;
+ case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
+ Java_WebsitePreferenceBridge_insertPushNotificationIntoList(
+ env, list, jorigin.obj(), jembedder.obj());
+ break;
+ default:
+ DCHECK(false);
+ break;
+ }
+ }
+}
+
+static jint GetSettingForOrigin(JNIEnv* env,
+ ContentSettingsType content_type,
+ jstring origin,
+ jstring embedder) {
+ GURL url(ConvertJavaStringToUTF8(env, origin));
+ GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
+ ContentSetting setting = GetHostContentSettingsMap()->GetContentSetting(
+ url,
+ embedder_url,
+ content_type,
+ std::string());
+ return setting;
+}
+
+static void SetSettingForOrigin(JNIEnv* env,
+ ContentSettingsType content_type,
+ jstring origin,
+ ContentSettingsPattern secondary_pattern,
+ jint value) {
+ GURL url(ConvertJavaStringToUTF8(env, origin));
+ ContentSetting setting = CONTENT_SETTING_DEFAULT;
+ switch (value) {
+ case -1: break;
+ case 1: setting = CONTENT_SETTING_ALLOW; break;
+ case 2: setting = CONTENT_SETTING_BLOCK; break;
+ default:
+ NOTREACHED();
+ }
+ GetHostContentSettingsMap()->SetContentSetting(
+ ContentSettingsPattern::FromURLNoWildcard(url),
+ secondary_pattern,
+ content_type,
+ std::string(),
+ setting);
+}
+
+static void GetGeolocationOrigins(JNIEnv* env,
+ jclass clazz,
+ jobject list,
+ jboolean managedOnly) {
+ GetOrigins(env, CONTENT_SETTINGS_TYPE_GEOLOCATION, list, managedOnly);
+}
+
+static jint GetGeolocationSettingForOrigin(JNIEnv* env, jclass clazz,
+ jstring origin, jstring embedder) {
+ return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_GEOLOCATION,
+ origin, embedder);
+}
+
+static void SetGeolocationSettingForOrigin(JNIEnv* env, jclass clazz,
+ jstring origin, jstring embedder, jint value) {
+ GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
+ SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_GEOLOCATION,
+ origin, ContentSettingsPattern::FromURLNoWildcard(embedder_url), value);
+}
+
+static void GetMidiOrigins(JNIEnv* env, jclass clazz, jobject list) {
+ GetOrigins(env, CONTENT_SETTINGS_TYPE_MIDI_SYSEX, list, false);
+}
+
+static jint GetMidiSettingForOrigin(JNIEnv* env, jclass clazz, jstring origin,
+ jstring embedder) {
+ return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MIDI_SYSEX, origin,
+ embedder);
+}
+
+static void SetMidiSettingForOrigin(JNIEnv* env, jclass clazz, jstring origin,
+ jstring embedder, jint value) {
+ GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
+ SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MIDI_SYSEX, origin,
+ ContentSettingsPattern::FromURLNoWildcard(embedder_url), value);
+}
+
+static void GetProtectedMediaIdentifierOrigins(JNIEnv* env, jclass clazz,
+ jobject list) {
+ GetOrigins(env, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, list,
+ false);
+}
+
+static jint GetProtectedMediaIdentifierSettingForOrigin(JNIEnv* env,
+ jclass clazz, jstring origin, jstring embedder) {
+ return GetSettingForOrigin(
+ env, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, origin, embedder);
+}
+
+static void SetProtectedMediaIdentifierSettingForOrigin(JNIEnv* env,
+ jclass clazz, jstring origin, jstring embedder, jint value) {
+ GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
+ SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER,
+ origin, ContentSettingsPattern::FromURLNoWildcard(embedder_url), value);
+}
+
+static void GetPushNotificationOrigins(JNIEnv* env,
+ jclass clazz,
+ jobject list) {
+ GetOrigins(env, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, list, false);
+}
+
+static jint GetPushNotificationSettingForOrigin(JNIEnv* env, jclass clazz,
+ jstring origin, jstring embedder) {
+ return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
+ origin, embedder);
+}
+
+static void SetPushNotificationSettingForOrigin(JNIEnv* env, jclass clazz,
+ jstring origin, jstring embedder, jint value) {
+ GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
+ SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
+ origin, ContentSettingsPattern::FromURLNoWildcard(embedder_url), value);
+}
+
+static void GetVoiceAndVideoCaptureOrigins(JNIEnv* env,
+ jclass clazz,
+ jobject list,
+ jboolean managedOnly) {
+ GetOrigins(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, list, managedOnly);
+ GetOrigins(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, list, managedOnly);
+}
+
+static jint GetVoiceCaptureSettingForOrigin(JNIEnv* env, jclass clazz,
+ jstring origin, jstring embedder) {
+ return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
+ origin, embedder);
+}
+
+static jint GetVideoCaptureSettingForOrigin(JNIEnv* env, jclass clazz,
+ jstring origin, jstring embedder) {
+ return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
+ origin, embedder);
+}
+
+static void SetVoiceCaptureSettingForOrigin(JNIEnv* env, jclass clazz,
+ jstring origin, jstring embedder, jint value) {
+ SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
+ origin, ContentSettingsPattern::Wildcard(), value);
+}
+
+static void SetVideoCaptureSettingForOrigin(JNIEnv* env, jclass clazz,
+ jstring origin, jstring embedder, jint value) {
+ SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
+ origin, ContentSettingsPattern::Wildcard(), value);
+}
+
+static scoped_refptr<CookieSettings> GetCookieSettings() {
+ Profile* profile = ProfileManager::GetActiveUserProfile();
+ return CookieSettings::Factory::GetForProfile(profile);
+}
+
+static void GetCookieOrigins(JNIEnv* env,
+ jclass clazz,
+ jobject list,
+ jboolean managedOnly) {
+ ContentSettingsForOneType all_settings;
+ GetCookieSettings()->GetCookieSettings(&all_settings);
+ const ContentSetting default_setting =
+ GetCookieSettings()->GetDefaultCookieSetting(nullptr);
+ for (const auto& settings_it : all_settings) {
+ if (settings_it.setting == default_setting)
+ continue;
+ if (managedOnly &&
+ HostContentSettingsMap::GetProviderTypeFromSource(settings_it.source) !=
+ HostContentSettingsMap::ProviderType::POLICY_PROVIDER) {
+ continue;
+ }
+ const std::string& origin = settings_it.primary_pattern.ToString();
+ const std::string& embedder = settings_it.secondary_pattern.ToString();
+ ScopedJavaLocalRef<jstring> jorigin = ConvertUTF8ToJavaString(env, origin);
+ ScopedJavaLocalRef<jstring> jembedder;
+ if (embedder != origin)
+ jembedder = ConvertUTF8ToJavaString(env, embedder);
+ Java_WebsitePreferenceBridge_insertCookieInfoIntoList(env, list,
+ jorigin.obj(), jembedder.obj());
+ }
+}
+
+static jint GetCookieSettingForOrigin(JNIEnv* env, jclass clazz,
+ jstring origin, jstring embedder) {
+ return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_COOKIES, origin,
+ embedder);
+}
+
+static void SetCookieSettingForOrigin(JNIEnv* env, jclass clazz,
+ jstring origin, jstring embedder, jint value) {
+ GURL url(ConvertJavaStringToUTF8(env, origin));
+ ContentSettingsPattern primary_pattern(
+ ContentSettingsPattern::FromURLNoWildcard(url));
+ ContentSettingsPattern secondary_pattern(ContentSettingsPattern::Wildcard());
+ if (value == -1) {
+ GetCookieSettings()->ResetCookieSetting(primary_pattern, secondary_pattern);
+ } else {
+ GetCookieSettings()->SetCookieSetting(primary_pattern, secondary_pattern,
+ value ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK);
+ }
+}
+
+namespace {
+
+class StorageInfoFetcher :
+ public base::RefCountedThreadSafe<StorageInfoFetcher> {
+ public:
+ StorageInfoFetcher(storage::QuotaManager* quota_manager,
+ const JavaRef<jobject>& java_callback)
+ : env_(base::android::AttachCurrentThread()),
+ quota_manager_(quota_manager),
+ java_callback_(java_callback) {
+ }
+
+ void Run() {
+ // QuotaManager must be called on IO thread, but java_callback must then be
+ // called back on UI thread.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&StorageInfoFetcher::GetUsageInfo, this));
+ }
+
+ protected:
+ virtual ~StorageInfoFetcher() {}
+
+ private:
+ friend class base::RefCountedThreadSafe<StorageInfoFetcher>;
+
+ void GetUsageInfo() {
+ // We will have no explicit owner as soon as we leave this method.
+ AddRef();
+ quota_manager_->GetUsageInfo(
+ base::Bind(&StorageInfoFetcher::OnGetUsageInfo, this));
+ }
+
+ void OnGetUsageInfo(const storage::UsageInfoEntries& entries) {
+ entries_.insert(entries_.begin(), entries.begin(), entries.end());
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&StorageInfoFetcher::InvokeCallback, this));
+ Release();
+ }
+
+ void InvokeCallback() {
+ ScopedJavaLocalRef<jobject> list =
+ Java_WebsitePreferenceBridge_createStorageInfoList(env_);
+
+ storage::UsageInfoEntries::const_iterator i;
+ for (i = entries_.begin(); i != entries_.end(); ++i) {
+ if (i->usage <= 0) continue;
+ ScopedJavaLocalRef<jstring> host =
+ ConvertUTF8ToJavaString(env_, i->host);
+
+ Java_WebsitePreferenceBridge_insertStorageInfoIntoList(
+ env_, list.obj(), host.obj(), i->type, i->usage);
+ }
+ Java_StorageInfoReadyCallback_onStorageInfoReady(
+ env_, java_callback_.obj(), list.obj());
+ }
+
+ JNIEnv* env_;
+ storage::QuotaManager* quota_manager_;
+ ScopedJavaGlobalRef<jobject> java_callback_;
+ storage::UsageInfoEntries entries_;
+
+ DISALLOW_COPY_AND_ASSIGN(StorageInfoFetcher);
+};
+
+class StorageDataDeleter :
+ public base::RefCountedThreadSafe<StorageDataDeleter> {
+ public:
+ StorageDataDeleter(storage::QuotaManager* quota_manager,
+ const std::string& host,
+ storage::StorageType type,
+ const JavaRef<jobject>& java_callback)
+ : env_(base::android::AttachCurrentThread()),
+ quota_manager_(quota_manager),
+ host_(host),
+ type_(type),
+ java_callback_(java_callback) {
+ }
+
+ void Run() {
+ // QuotaManager must be called on IO thread, but java_callback must then be
+ // called back on UI thread. Grant ourself an extra reference to avoid
+ // being deleted after DeleteHostData will return.
+ AddRef();
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&storage::QuotaManager::DeleteHostData,
+ quota_manager_,
+ host_,
+ type_,
+ storage::QuotaClient::kAllClientsMask,
+ base::Bind(&StorageDataDeleter::OnHostDataDeleted,
+ this)));
+ }
+
+ protected:
+ virtual ~StorageDataDeleter() {}
+
+ private:
+ friend class base::RefCountedThreadSafe<StorageDataDeleter>;
+
+ void OnHostDataDeleted(storage::QuotaStatusCode) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ quota_manager_->ResetUsageTracker(type_);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&StorageDataDeleter::InvokeCallback, this));
+ Release();
+ }
+
+ void InvokeCallback() {
+ Java_StorageInfoClearedCallback_onStorageInfoCleared(
+ env_, java_callback_.obj());
+ }
+
+ JNIEnv* env_;
+ storage::QuotaManager* quota_manager_;
+ std::string host_;
+ storage::StorageType type_;
+ ScopedJavaGlobalRef<jobject> java_callback_;
+};
+
+class LocalStorageInfoReadyCallback {
+ public:
+ LocalStorageInfoReadyCallback(
+ const ScopedJavaLocalRef<jobject>& java_callback)
+ : env_(base::android::AttachCurrentThread()),
+ java_callback_(java_callback) {
+ }
+
+ void OnLocalStorageModelInfoLoaded(
+ const std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>&
+ local_storage_info) {
+ ScopedJavaLocalRef<jobject> map =
+ Java_WebsitePreferenceBridge_createLocalStorageInfoMap(env_);
+
+ std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::const_iterator
+ i;
+ for (i = local_storage_info.begin(); i != local_storage_info.end(); ++i) {
+ ScopedJavaLocalRef<jstring> full_origin =
+ ConvertUTF8ToJavaString(env_, i->origin_url.spec());
+ ScopedJavaLocalRef<jstring> origin =
+ ConvertUTF8ToJavaString(env_, i->origin_url.GetOrigin().spec());
+ Java_WebsitePreferenceBridge_insertLocalStorageInfoIntoMap(
+ env_, map.obj(), origin.obj(), full_origin.obj(), i->size);
+ }
+
+ Java_LocalStorageInfoReadyCallback_onLocalStorageInfoReady(
+ env_, java_callback_.obj(), map.obj());
+ delete this;
+ }
+
+ private:
+ JNIEnv* env_;
+ ScopedJavaGlobalRef<jobject> java_callback_;
+};
+
+} // anonymous namespace
+
+// TODO(jknotten): These methods should not be static. Instead we should
+// expose a class to Java so that the fetch requests can be cancelled,
+// and manage the lifetimes of the callback (and indirectly the helper
+// by having a reference to it).
+
+// The helper methods (StartFetching, DeleteLocalStorageFile, DeleteDatabase)
+// are asynchronous. A "use after free" error is not possible because the
+// helpers keep a reference to themselves for the duration of their tasks,
+// which includes callback invocation.
+
+static void FetchLocalStorageInfo(JNIEnv* env, jclass clazz,
+ jobject java_callback) {
+ Profile* profile = ProfileManager::GetActiveUserProfile();
+ scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper(
+ new BrowsingDataLocalStorageHelper(profile));
+ // local_storage_callback will delete itself when it is run.
+ LocalStorageInfoReadyCallback* local_storage_callback =
+ new LocalStorageInfoReadyCallback(
+ ScopedJavaLocalRef<jobject>(env, java_callback));
+ local_storage_helper->StartFetching(
+ base::Bind(&LocalStorageInfoReadyCallback::OnLocalStorageModelInfoLoaded,
+ base::Unretained(local_storage_callback)));
+}
+
+static void FetchStorageInfo(JNIEnv* env, jclass clazz, jobject java_callback) {
+ Profile* profile = ProfileManager::GetActiveUserProfile();
+ scoped_refptr<StorageInfoFetcher> storage_info_fetcher(new StorageInfoFetcher(
+ content::BrowserContext::GetDefaultStoragePartition(
+ profile)->GetQuotaManager(),
+ ScopedJavaLocalRef<jobject>(env, java_callback)));
+ storage_info_fetcher->Run();
+}
+
+static void ClearLocalStorageData(JNIEnv* env, jclass clazz, jstring jorigin) {
+ Profile* profile = ProfileManager::GetActiveUserProfile();
+ scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper =
+ new BrowsingDataLocalStorageHelper(profile);
+ GURL origin_url = GURL(ConvertJavaStringToUTF8(env, jorigin));
+ local_storage_helper->DeleteOrigin(origin_url);
+}
+
+static void ClearStorageData(JNIEnv* env,
+ jclass clazz,
+ jstring jhost,
+ jint type,
+ jobject java_callback) {
+ Profile* profile = ProfileManager::GetActiveUserProfile();
+ std::string host = ConvertJavaStringToUTF8(env, jhost);
+ scoped_refptr<StorageDataDeleter> storage_data_deleter(new StorageDataDeleter(
+ content::BrowserContext::GetDefaultStoragePartition(
+ profile)->GetQuotaManager(),
+ host,
+ static_cast<storage::StorageType>(type),
+ ScopedJavaLocalRef<jobject>(env, java_callback)));
+ storage_data_deleter->Run();
+}
+
+// Register native methods
+bool RegisterWebsitePreferenceBridge(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}

Powered by Google App Engine
This is Rietveld 408576698