Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / android / preferences / website_preference_bridge.cc
blobab6630af4c2369e717457e75275e22182c3a2787
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/android/preferences/website_preference_bridge.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/android/scoped_java_ref.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/files/file_path.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h"
15 #include "chrome/browser/browsing_data/cookies_tree_model.h"
16 #include "chrome/browser/browsing_data/local_data_container.h"
17 #include "chrome/browser/content_settings/cookie_settings_factory.h"
18 #include "chrome/browser/content_settings/web_site_settings_uma_util.h"
19 #include "chrome/browser/notifications/desktop_notification_profile_util.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/profiles/profile_manager.h"
22 #include "components/content_settings/core/browser/cookie_settings.h"
23 #include "components/content_settings/core/browser/host_content_settings_map.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/storage_partition.h"
26 #include "jni/WebsitePreferenceBridge_jni.h"
27 #include "storage/browser/quota/quota_client.h"
28 #include "storage/browser/quota/quota_manager.h"
29 #include "url/url_constants.h"
31 using base::android::ConvertJavaStringToUTF8;
32 using base::android::ConvertUTF8ToJavaString;
33 using base::android::JavaRef;
34 using base::android::ScopedJavaGlobalRef;
35 using base::android::ScopedJavaLocalRef;
36 using content::BrowserThread;
38 static HostContentSettingsMap* GetHostContentSettingsMap() {
39 Profile* profile = ProfileManager::GetActiveUserProfile();
40 return profile->GetHostContentSettingsMap();
43 static void GetOrigins(JNIEnv* env,
44 ContentSettingsType content_type,
45 jobject list,
46 jboolean managedOnly) {
47 ContentSettingsForOneType all_settings;
48 HostContentSettingsMap* content_settings_map = GetHostContentSettingsMap();
49 content_settings_map->GetSettingsForOneType(
50 content_type, std::string(), &all_settings);
51 ContentSetting default_content_setting = content_settings_map->
52 GetDefaultContentSetting(content_type, NULL);
53 // Now add all origins that have a non-default setting to the list.
54 for (const auto& settings_it : all_settings) {
55 if (settings_it.setting == default_content_setting)
56 continue;
57 if (managedOnly &&
58 HostContentSettingsMap::GetProviderTypeFromSource(settings_it.source) !=
59 HostContentSettingsMap::ProviderType::POLICY_PROVIDER) {
60 continue;
62 const std::string origin = settings_it.primary_pattern.ToString();
63 const std::string embedder = settings_it.secondary_pattern.ToString();
65 // The string |jorigin| is used to group permissions together in the Site
66 // Settings list. In order to group sites with the same origin, remove any
67 // standard port from the end of the URL if it's present (i.e. remove :443
68 // for HTTPS sites and :80 for HTTP sites).
69 // TODO(sashab,lgarron): Find out which settings are being saved with the
70 // port and omit it if it's the standard port.
71 // TODO(mvanouwerkerk): Remove all this logic and take two passes through
72 // HostContentSettingsMap: once to get all the 'interesting' hosts, and once
73 // (on SingleWebsitePreferences) to find permission patterns which match
74 // each of these hosts.
75 const char* kHttpPortSuffix = ":80";
76 const char* kHttpsPortSuffix = ":443";
77 ScopedJavaLocalRef<jstring> jorigin;
78 if (base::StartsWith(origin, url::kHttpsScheme,
79 base::CompareCase::INSENSITIVE_ASCII) &&
80 base::EndsWith(origin, kHttpsPortSuffix,
81 base::CompareCase::INSENSITIVE_ASCII)) {
82 jorigin = ConvertUTF8ToJavaString(
83 env, origin.substr(0, origin.size() - strlen(kHttpsPortSuffix)));
84 } else if (base::StartsWith(origin, url::kHttpScheme,
85 base::CompareCase::INSENSITIVE_ASCII) &&
86 base::EndsWith(origin, kHttpPortSuffix,
87 base::CompareCase::INSENSITIVE_ASCII)) {
88 jorigin = ConvertUTF8ToJavaString(
89 env, origin.substr(0, origin.size() - strlen(kHttpPortSuffix)));
90 } else {
91 jorigin = ConvertUTF8ToJavaString(env, origin);
94 ScopedJavaLocalRef<jstring> jembedder;
95 if (embedder != origin)
96 jembedder = ConvertUTF8ToJavaString(env, embedder);
97 switch (content_type) {
98 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
99 Java_WebsitePreferenceBridge_insertMicrophoneInfoIntoList(
100 env, list, jorigin.obj(), jembedder.obj());
101 break;
102 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
103 Java_WebsitePreferenceBridge_insertCameraInfoIntoList(
104 env, list, jorigin.obj(), jembedder.obj());
105 break;
106 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
107 Java_WebsitePreferenceBridge_insertGeolocationInfoIntoList(
108 env, list, jorigin.obj(), jembedder.obj());
109 break;
110 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
111 Java_WebsitePreferenceBridge_insertMidiInfoIntoList(
112 env, list, jorigin.obj(), jembedder.obj());
113 break;
114 case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
115 Java_WebsitePreferenceBridge_insertProtectedMediaIdentifierInfoIntoList(
116 env, list, jorigin.obj(), jembedder.obj());
117 break;
118 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
119 Java_WebsitePreferenceBridge_insertPushNotificationIntoList(
120 env, list, jorigin.obj(), jembedder.obj());
121 break;
122 case CONTENT_SETTINGS_TYPE_FULLSCREEN:
123 Java_WebsitePreferenceBridge_insertFullscreenInfoIntoList(
124 env, list, jorigin.obj(), jembedder.obj());
125 break;
126 default:
127 DCHECK(false);
128 break;
133 static jint GetSettingForOrigin(JNIEnv* env,
134 ContentSettingsType content_type,
135 jstring origin,
136 jstring embedder) {
137 GURL url(ConvertJavaStringToUTF8(env, origin));
138 GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
139 ContentSetting setting = GetHostContentSettingsMap()->GetContentSetting(
140 url,
141 embedder_url,
142 content_type,
143 std::string());
144 return setting;
147 static void SetSettingForOrigin(JNIEnv* env,
148 ContentSettingsType content_type,
149 jstring origin,
150 ContentSettingsPattern secondary_pattern,
151 jint value) {
152 GURL url(ConvertJavaStringToUTF8(env, origin));
153 ContentSetting setting = CONTENT_SETTING_DEFAULT;
154 switch (value) {
155 case -1: break;
156 case 0: setting = CONTENT_SETTING_DEFAULT; break;
157 case 1: setting = CONTENT_SETTING_ALLOW; break;
158 case 2: setting = CONTENT_SETTING_BLOCK; break;
159 default:
160 // Note: CONTENT_SETTINGS_ASK is not and should not be supported.
161 NOTREACHED();
163 GetHostContentSettingsMap()->SetContentSetting(
164 ContentSettingsPattern::FromURLNoWildcard(url),
165 secondary_pattern,
166 content_type,
167 std::string(),
168 setting);
169 WebSiteSettingsUmaUtil::LogPermissionChange(content_type, setting);
172 static void GetFullscreenOrigins(JNIEnv* env,
173 jclass clazz,
174 jobject list,
175 jboolean managedOnly) {
176 GetOrigins(env, CONTENT_SETTINGS_TYPE_FULLSCREEN, list, managedOnly);
179 static jint GetFullscreenSettingForOrigin(JNIEnv* env, jclass clazz,
180 jstring origin, jstring embedder) {
181 return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_FULLSCREEN,
182 origin, embedder);
185 static void SetFullscreenSettingForOrigin(JNIEnv* env, jclass clazz,
186 jstring origin, jstring embedder, jint value) {
187 GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
188 SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_FULLSCREEN,
189 origin, ContentSettingsPattern::FromURLNoWildcard(embedder_url), value);
192 static void GetGeolocationOrigins(JNIEnv* env,
193 jclass clazz,
194 jobject list,
195 jboolean managedOnly) {
196 GetOrigins(env, CONTENT_SETTINGS_TYPE_GEOLOCATION, list, managedOnly);
199 static jint GetGeolocationSettingForOrigin(JNIEnv* env, jclass clazz,
200 jstring origin, jstring embedder) {
201 return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_GEOLOCATION,
202 origin, embedder);
205 static void SetGeolocationSettingForOrigin(JNIEnv* env, jclass clazz,
206 jstring origin, jstring embedder, jint value) {
207 GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
208 SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_GEOLOCATION,
209 origin, ContentSettingsPattern::FromURLNoWildcard(embedder_url), value);
212 static void GetMidiOrigins(JNIEnv* env, jclass clazz, jobject list) {
213 GetOrigins(env, CONTENT_SETTINGS_TYPE_MIDI_SYSEX, list, false);
216 static jint GetMidiSettingForOrigin(JNIEnv* env, jclass clazz, jstring origin,
217 jstring embedder) {
218 return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MIDI_SYSEX, origin,
219 embedder);
222 static void SetMidiSettingForOrigin(JNIEnv* env, jclass clazz, jstring origin,
223 jstring embedder, jint value) {
224 GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
225 SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MIDI_SYSEX, origin,
226 ContentSettingsPattern::FromURLNoWildcard(embedder_url), value);
229 static void GetProtectedMediaIdentifierOrigins(JNIEnv* env, jclass clazz,
230 jobject list) {
231 GetOrigins(env, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, list,
232 false);
235 static jint GetProtectedMediaIdentifierSettingForOrigin(JNIEnv* env,
236 jclass clazz, jstring origin, jstring embedder) {
237 return GetSettingForOrigin(
238 env, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, origin, embedder);
241 static void SetProtectedMediaIdentifierSettingForOrigin(JNIEnv* env,
242 jclass clazz, jstring origin, jstring embedder, jint value) {
243 GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
244 SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER,
245 origin, ContentSettingsPattern::FromURLNoWildcard(embedder_url), value);
248 static void GetPushNotificationOrigins(JNIEnv* env,
249 jclass clazz,
250 jobject list) {
251 GetOrigins(env, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, list, false);
254 static jint GetPushNotificationSettingForOrigin(JNIEnv* env, jclass clazz,
255 jstring origin, jstring embedder) {
256 return DesktopNotificationProfileUtil::GetContentSetting(
257 ProfileManager::GetActiveUserProfile(),
258 GURL(ConvertJavaStringToUTF8(env, origin)));
261 static void SetPushNotificationSettingForOrigin(JNIEnv* env, jclass clazz,
262 jstring origin, jstring embedder, jint value) {
263 // TODO(peter): Web Notification permission behaves differently from all other
264 // permission types. See https://crbug.com/416894.
265 Profile* profile = ProfileManager::GetActiveUserProfile();
266 GURL url = GURL(ConvertJavaStringToUTF8(env, origin));
267 ContentSetting setting = CONTENT_SETTING_DEFAULT;
268 switch (value) {
269 case -1:
270 DesktopNotificationProfileUtil::ClearSetting(
271 profile, ContentSettingsPattern::FromURLNoWildcard(url));
272 break;
273 case 1:
274 DesktopNotificationProfileUtil::GrantPermission(profile, url);
275 setting = CONTENT_SETTING_ALLOW;
276 break;
277 case 2:
278 DesktopNotificationProfileUtil::DenyPermission(profile, url);
279 setting = CONTENT_SETTING_BLOCK;
280 break;
281 default:
282 NOTREACHED();
284 WebSiteSettingsUmaUtil::LogPermissionChange(
285 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, setting);
288 static void GetCameraOrigins(JNIEnv* env,
289 jclass clazz,
290 jobject list,
291 jboolean managedOnly) {
292 GetOrigins(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, list, managedOnly);
295 static void GetMicrophoneOrigins(JNIEnv* env,
296 jclass clazz,
297 jobject list,
298 jboolean managedOnly) {
299 GetOrigins(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, list, managedOnly);
302 static jint GetMicrophoneSettingForOrigin(JNIEnv* env, jclass clazz,
303 jstring origin, jstring embedder) {
304 return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
305 origin, embedder);
308 static jint GetCameraSettingForOrigin(JNIEnv* env, jclass clazz,
309 jstring origin, jstring embedder) {
310 return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
311 origin, embedder);
314 static void SetMicrophoneSettingForOrigin(JNIEnv* env, jclass clazz,
315 jstring origin, jstring embedder, jint value) {
316 SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
317 origin, ContentSettingsPattern::Wildcard(), value);
320 static void SetCameraSettingForOrigin(JNIEnv* env, jclass clazz,
321 jstring origin, jstring embedder, jint value) {
322 SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
323 origin, ContentSettingsPattern::Wildcard(), value);
326 static scoped_refptr<content_settings::CookieSettings> GetCookieSettings() {
327 Profile* profile = ProfileManager::GetActiveUserProfile();
328 return CookieSettingsFactory::GetForProfile(profile);
331 static void GetCookieOrigins(JNIEnv* env,
332 jclass clazz,
333 jobject list,
334 jboolean managedOnly) {
335 ContentSettingsForOneType all_settings;
336 GetCookieSettings()->GetCookieSettings(&all_settings);
337 const ContentSetting default_setting =
338 GetCookieSettings()->GetDefaultCookieSetting(nullptr);
339 for (const auto& settings_it : all_settings) {
340 if (settings_it.setting == default_setting)
341 continue;
342 if (managedOnly &&
343 HostContentSettingsMap::GetProviderTypeFromSource(settings_it.source) !=
344 HostContentSettingsMap::ProviderType::POLICY_PROVIDER) {
345 continue;
347 const std::string& origin = settings_it.primary_pattern.ToString();
348 const std::string& embedder = settings_it.secondary_pattern.ToString();
349 ScopedJavaLocalRef<jstring> jorigin = ConvertUTF8ToJavaString(env, origin);
350 ScopedJavaLocalRef<jstring> jembedder;
351 if (embedder != origin)
352 jembedder = ConvertUTF8ToJavaString(env, embedder);
353 Java_WebsitePreferenceBridge_insertCookieInfoIntoList(env, list,
354 jorigin.obj(), jembedder.obj());
358 static jint GetCookieSettingForOrigin(JNIEnv* env, jclass clazz,
359 jstring origin, jstring embedder) {
360 return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_COOKIES, origin,
361 embedder);
364 static void SetCookieSettingForOrigin(JNIEnv* env, jclass clazz,
365 jstring origin, jstring embedder, jint value) {
366 GURL url(ConvertJavaStringToUTF8(env, origin));
367 ContentSettingsPattern primary_pattern(
368 ContentSettingsPattern::FromURLNoWildcard(url));
369 ContentSettingsPattern secondary_pattern(ContentSettingsPattern::Wildcard());
370 ContentSetting setting = CONTENT_SETTING_DEFAULT;
371 if (value == -1) {
372 GetCookieSettings()->ResetCookieSetting(primary_pattern, secondary_pattern);
373 } else {
374 setting = value ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
375 GetCookieSettings()->SetCookieSetting(primary_pattern, secondary_pattern,
376 setting);
378 WebSiteSettingsUmaUtil::LogPermissionChange(
379 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, setting);
382 static jboolean IsContentSettingsPatternValid(JNIEnv* env, jclass clazz,
383 jstring pattern) {
384 return ContentSettingsPattern::FromString(
385 ConvertJavaStringToUTF8(env, pattern)).IsValid();
388 static jboolean UrlMatchesContentSettingsPattern(JNIEnv* env,
389 jclass clazz,
390 jstring jurl,
391 jstring jpattern) {
392 ContentSettingsPattern pattern = ContentSettingsPattern::FromString(
393 ConvertJavaStringToUTF8(env, jpattern));
394 return pattern.Matches(GURL(ConvertJavaStringToUTF8(env, jurl)));
397 namespace {
399 class SiteDataDeleteHelper :
400 public base::RefCountedThreadSafe<SiteDataDeleteHelper>,
401 public CookiesTreeModel::Observer {
402 public:
403 SiteDataDeleteHelper(Profile* profile, const GURL& domain)
404 : profile_(profile), domain_(domain), ending_batch_processing_(false) {
407 void Run() {
408 AddRef(); // Balanced in TreeModelEndBatch.
410 content::StoragePartition* storage_partition =
411 content::BrowserContext::GetDefaultStoragePartition(profile_);
412 content::IndexedDBContext* indexed_db_context =
413 storage_partition->GetIndexedDBContext();
414 content::ServiceWorkerContext* service_worker_context =
415 storage_partition->GetServiceWorkerContext();
416 storage::FileSystemContext* file_system_context =
417 storage_partition->GetFileSystemContext();
418 LocalDataContainer* container = new LocalDataContainer(
419 new BrowsingDataCookieHelper(profile_->GetRequestContext()),
420 new BrowsingDataDatabaseHelper(profile_),
421 new BrowsingDataLocalStorageHelper(profile_),
422 NULL,
423 new BrowsingDataAppCacheHelper(profile_),
424 new BrowsingDataIndexedDBHelper(indexed_db_context),
425 BrowsingDataFileSystemHelper::Create(file_system_context),
426 BrowsingDataQuotaHelper::Create(profile_),
427 BrowsingDataChannelIDHelper::Create(profile_->GetRequestContext()),
428 new BrowsingDataServiceWorkerHelper(service_worker_context),
429 NULL);
431 cookies_tree_model_.reset(new CookiesTreeModel(
432 container, profile_->GetExtensionSpecialStoragePolicy(), false));
433 cookies_tree_model_->AddCookiesTreeObserver(this);
436 // TreeModelObserver:
437 void TreeNodesAdded(ui::TreeModel* model,
438 ui::TreeModelNode* parent,
439 int start,
440 int count) override {}
441 void TreeNodesRemoved(ui::TreeModel* model,
442 ui::TreeModelNode* parent,
443 int start,
444 int count) override {}
446 // CookiesTreeModel::Observer:
447 void TreeNodeChanged(ui::TreeModel* model, ui::TreeModelNode* node) override {
450 void TreeModelBeginBatch(CookiesTreeModel* model) override {
451 DCHECK(!ending_batch_processing_); // Extra batch-start sent.
454 void TreeModelEndBatch(CookiesTreeModel* model) override {
455 DCHECK(!ending_batch_processing_); // Already in end-stage.
456 ending_batch_processing_ = true;
458 RecursivelyFindSiteAndDelete(cookies_tree_model_->GetRoot());
460 // This will result in this class getting deleted.
461 Release();
464 void RecursivelyFindSiteAndDelete(CookieTreeNode* node) {
465 CookieTreeNode::DetailedInfo info = node->GetDetailedInfo();
466 for (int i = node->child_count(); i > 0; --i)
467 RecursivelyFindSiteAndDelete(node->GetChild(i - 1));
469 if (info.node_type == CookieTreeNode::DetailedInfo::TYPE_COOKIE &&
470 info.cookie &&
471 domain_.DomainIs(info.cookie->Domain().c_str()))
472 cookies_tree_model_->DeleteCookieNode(node);
475 private:
476 friend class base::RefCountedThreadSafe<SiteDataDeleteHelper>;
478 ~SiteDataDeleteHelper() override {}
480 Profile* profile_;
482 // The domain we want to delete data for.
483 GURL domain_;
485 // Keeps track of when we're ready to close batch processing.
486 bool ending_batch_processing_;
488 scoped_ptr<CookiesTreeModel> cookies_tree_model_;
490 DISALLOW_COPY_AND_ASSIGN(SiteDataDeleteHelper);
493 class StorageInfoFetcher :
494 public base::RefCountedThreadSafe<StorageInfoFetcher> {
495 public:
496 StorageInfoFetcher(storage::QuotaManager* quota_manager,
497 const JavaRef<jobject>& java_callback)
498 : env_(base::android::AttachCurrentThread()),
499 quota_manager_(quota_manager),
500 java_callback_(java_callback) {
503 void Run() {
504 // QuotaManager must be called on IO thread, but java_callback must then be
505 // called back on UI thread.
506 BrowserThread::PostTask(
507 BrowserThread::IO, FROM_HERE,
508 base::Bind(&StorageInfoFetcher::GetUsageInfo, this));
511 protected:
512 virtual ~StorageInfoFetcher() {}
514 private:
515 friend class base::RefCountedThreadSafe<StorageInfoFetcher>;
517 void GetUsageInfo() {
518 // We will have no explicit owner as soon as we leave this method.
519 AddRef();
520 quota_manager_->GetUsageInfo(
521 base::Bind(&StorageInfoFetcher::OnGetUsageInfo, this));
524 void OnGetUsageInfo(const storage::UsageInfoEntries& entries) {
525 entries_.insert(entries_.begin(), entries.begin(), entries.end());
526 BrowserThread::PostTask(
527 BrowserThread::UI, FROM_HERE,
528 base::Bind(&StorageInfoFetcher::InvokeCallback, this));
529 Release();
532 void InvokeCallback() {
533 ScopedJavaLocalRef<jobject> list =
534 Java_WebsitePreferenceBridge_createStorageInfoList(env_);
536 storage::UsageInfoEntries::const_iterator i;
537 for (i = entries_.begin(); i != entries_.end(); ++i) {
538 if (i->usage <= 0) continue;
539 ScopedJavaLocalRef<jstring> host =
540 ConvertUTF8ToJavaString(env_, i->host);
542 Java_WebsitePreferenceBridge_insertStorageInfoIntoList(
543 env_, list.obj(), host.obj(), i->type, i->usage);
545 Java_StorageInfoReadyCallback_onStorageInfoReady(
546 env_, java_callback_.obj(), list.obj());
549 JNIEnv* env_;
550 storage::QuotaManager* quota_manager_;
551 ScopedJavaGlobalRef<jobject> java_callback_;
552 storage::UsageInfoEntries entries_;
554 DISALLOW_COPY_AND_ASSIGN(StorageInfoFetcher);
557 class StorageDataDeleter :
558 public base::RefCountedThreadSafe<StorageDataDeleter> {
559 public:
560 StorageDataDeleter(storage::QuotaManager* quota_manager,
561 const std::string& host,
562 storage::StorageType type,
563 const JavaRef<jobject>& java_callback)
564 : env_(base::android::AttachCurrentThread()),
565 quota_manager_(quota_manager),
566 host_(host),
567 type_(type),
568 java_callback_(java_callback) {
571 void Run() {
572 // QuotaManager must be called on IO thread, but java_callback must then be
573 // called back on UI thread. Grant ourself an extra reference to avoid
574 // being deleted after DeleteHostData will return.
575 AddRef();
576 BrowserThread::PostTask(
577 BrowserThread::IO, FROM_HERE,
578 base::Bind(&storage::QuotaManager::DeleteHostData,
579 quota_manager_,
580 host_,
581 type_,
582 storage::QuotaClient::kAllClientsMask,
583 base::Bind(&StorageDataDeleter::OnHostDataDeleted,
584 this)));
587 protected:
588 virtual ~StorageDataDeleter() {}
590 private:
591 friend class base::RefCountedThreadSafe<StorageDataDeleter>;
593 void OnHostDataDeleted(storage::QuotaStatusCode) {
594 DCHECK_CURRENTLY_ON(BrowserThread::IO);
595 quota_manager_->ResetUsageTracker(type_);
596 BrowserThread::PostTask(
597 BrowserThread::UI, FROM_HERE,
598 base::Bind(&StorageDataDeleter::InvokeCallback, this));
599 Release();
602 void InvokeCallback() {
603 Java_StorageInfoClearedCallback_onStorageInfoCleared(
604 env_, java_callback_.obj());
607 JNIEnv* env_;
608 storage::QuotaManager* quota_manager_;
609 std::string host_;
610 storage::StorageType type_;
611 ScopedJavaGlobalRef<jobject> java_callback_;
614 class LocalStorageInfoReadyCallback {
615 public:
616 LocalStorageInfoReadyCallback(
617 const ScopedJavaLocalRef<jobject>& java_callback)
618 : env_(base::android::AttachCurrentThread()),
619 java_callback_(java_callback) {
622 void OnLocalStorageModelInfoLoaded(
623 const std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>&
624 local_storage_info) {
625 ScopedJavaLocalRef<jobject> map =
626 Java_WebsitePreferenceBridge_createLocalStorageInfoMap(env_);
628 std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::const_iterator
630 for (i = local_storage_info.begin(); i != local_storage_info.end(); ++i) {
631 ScopedJavaLocalRef<jstring> full_origin =
632 ConvertUTF8ToJavaString(env_, i->origin_url.spec());
633 // Remove the trailing backslash so the origin is matched correctly in
634 // SingleWebsitePreferences.mergePermissionInfoForTopLevelOrigin.
635 std::string origin_str = i->origin_url.GetOrigin().spec();
636 DCHECK(origin_str[origin_str.size() - 1] == '/');
637 origin_str = origin_str.substr(0, origin_str.size() - 1);
638 ScopedJavaLocalRef<jstring> origin =
639 ConvertUTF8ToJavaString(env_, origin_str);
640 Java_WebsitePreferenceBridge_insertLocalStorageInfoIntoMap(
641 env_, map.obj(), origin.obj(), full_origin.obj(), i->size);
644 Java_LocalStorageInfoReadyCallback_onLocalStorageInfoReady(
645 env_, java_callback_.obj(), map.obj());
646 delete this;
649 private:
650 JNIEnv* env_;
651 ScopedJavaGlobalRef<jobject> java_callback_;
654 } // anonymous namespace
656 // TODO(jknotten): These methods should not be static. Instead we should
657 // expose a class to Java so that the fetch requests can be cancelled,
658 // and manage the lifetimes of the callback (and indirectly the helper
659 // by having a reference to it).
661 // The helper methods (StartFetching, DeleteLocalStorageFile, DeleteDatabase)
662 // are asynchronous. A "use after free" error is not possible because the
663 // helpers keep a reference to themselves for the duration of their tasks,
664 // which includes callback invocation.
666 static void FetchLocalStorageInfo(JNIEnv* env, jclass clazz,
667 jobject java_callback) {
668 Profile* profile = ProfileManager::GetActiveUserProfile();
669 scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper(
670 new BrowsingDataLocalStorageHelper(profile));
671 // local_storage_callback will delete itself when it is run.
672 LocalStorageInfoReadyCallback* local_storage_callback =
673 new LocalStorageInfoReadyCallback(
674 ScopedJavaLocalRef<jobject>(env, java_callback));
675 local_storage_helper->StartFetching(
676 base::Bind(&LocalStorageInfoReadyCallback::OnLocalStorageModelInfoLoaded,
677 base::Unretained(local_storage_callback)));
680 static void FetchStorageInfo(JNIEnv* env, jclass clazz, jobject java_callback) {
681 Profile* profile = ProfileManager::GetActiveUserProfile();
682 scoped_refptr<StorageInfoFetcher> storage_info_fetcher(new StorageInfoFetcher(
683 content::BrowserContext::GetDefaultStoragePartition(
684 profile)->GetQuotaManager(),
685 ScopedJavaLocalRef<jobject>(env, java_callback)));
686 storage_info_fetcher->Run();
689 static void ClearLocalStorageData(JNIEnv* env, jclass clazz, jstring jorigin) {
690 Profile* profile = ProfileManager::GetActiveUserProfile();
691 scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper =
692 new BrowsingDataLocalStorageHelper(profile);
693 GURL origin_url = GURL(ConvertJavaStringToUTF8(env, jorigin));
694 local_storage_helper->DeleteOrigin(origin_url);
697 static void ClearStorageData(JNIEnv* env,
698 jclass clazz,
699 jstring jhost,
700 jint type,
701 jobject java_callback) {
702 Profile* profile = ProfileManager::GetActiveUserProfile();
703 std::string host = ConvertJavaStringToUTF8(env, jhost);
704 scoped_refptr<StorageDataDeleter> storage_data_deleter(new StorageDataDeleter(
705 content::BrowserContext::GetDefaultStoragePartition(
706 profile)->GetQuotaManager(),
707 host,
708 static_cast<storage::StorageType>(type),
709 ScopedJavaLocalRef<jobject>(env, java_callback)));
710 storage_data_deleter->Run();
713 static void ClearCookieData(JNIEnv* env, jclass clazz, jstring jorigin) {
714 Profile* profile = ProfileManager::GetActiveUserProfile();
715 GURL url(ConvertJavaStringToUTF8(env, jorigin));
716 scoped_refptr<SiteDataDeleteHelper> site_data_deleter(
717 new SiteDataDeleteHelper(profile, url));
718 site_data_deleter->Run();
721 // Register native methods
722 bool RegisterWebsitePreferenceBridge(JNIEnv* env) {
723 return RegisterNativesImpl(env);