Move StartsWith[ASCII] to base namespace.
[chromium-blink-merge.git] / chrome / browser / android / preferences / website_preference_bridge.cc
blob9d575d7e7f9f19ed74eaa9619da3c123befacd3b
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.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/host_content_settings_map.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/storage_partition.h"
25 #include "jni/WebsitePreferenceBridge_jni.h"
26 #include "storage/browser/quota/quota_client.h"
27 #include "storage/browser/quota/quota_manager.h"
28 #include "url/url_constants.h"
30 using base::android::ConvertJavaStringToUTF8;
31 using base::android::ConvertUTF8ToJavaString;
32 using base::android::JavaRef;
33 using base::android::ScopedJavaGlobalRef;
34 using base::android::ScopedJavaLocalRef;
35 using content::BrowserThread;
37 static HostContentSettingsMap* GetHostContentSettingsMap() {
38 Profile* profile = ProfileManager::GetActiveUserProfile();
39 return profile->GetHostContentSettingsMap();
42 static void GetOrigins(JNIEnv* env,
43 ContentSettingsType content_type,
44 jobject list,
45 jboolean managedOnly) {
46 ContentSettingsForOneType all_settings;
47 HostContentSettingsMap* content_settings_map = GetHostContentSettingsMap();
48 content_settings_map->GetSettingsForOneType(
49 content_type, std::string(), &all_settings);
50 ContentSetting default_content_setting = content_settings_map->
51 GetDefaultContentSetting(content_type, NULL);
52 // Now add all origins that have a non-default setting to the list.
53 for (const auto& settings_it : all_settings) {
54 if (settings_it.setting == default_content_setting)
55 continue;
56 if (managedOnly &&
57 HostContentSettingsMap::GetProviderTypeFromSource(settings_it.source) !=
58 HostContentSettingsMap::ProviderType::POLICY_PROVIDER) {
59 continue;
61 const std::string origin = settings_it.primary_pattern.ToString();
62 const std::string embedder = settings_it.secondary_pattern.ToString();
64 // The string |jorigin| is used to group permissions together in the Site
65 // Settings list. In order to group sites with the same origin, remove any
66 // standard port from the end of the URL if it's present (i.e. remove :443
67 // for HTTPS sites and :80 for HTTP sites).
68 // TODO(sashab,lgarron): Find out which settings are being saved with the
69 // port and omit it if it's the standard port.
70 // TODO(mvanouwerkerk): Remove all this logic and take two passes through
71 // HostContentSettingsMap: once to get all the 'interesting' hosts, and once
72 // (on SingleWebsitePreferences) to find permission patterns which match
73 // each of these hosts.
74 const char* kHttpPortSuffix = ":80";
75 const char* kHttpsPortSuffix = ":443";
76 ScopedJavaLocalRef<jstring> jorigin;
77 if (base::StartsWithASCII(origin, url::kHttpsScheme, false) &&
78 EndsWith(origin, kHttpsPortSuffix, false)) {
79 jorigin = ConvertUTF8ToJavaString(
80 env, origin.substr(0, origin.size() - strlen(kHttpsPortSuffix)));
81 } else if (base::StartsWithASCII(origin, url::kHttpScheme, false) &&
82 EndsWith(origin, kHttpPortSuffix, false)) {
83 jorigin = ConvertUTF8ToJavaString(
84 env, origin.substr(0, origin.size() - strlen(kHttpPortSuffix)));
85 } else {
86 jorigin = ConvertUTF8ToJavaString(env, origin);
89 ScopedJavaLocalRef<jstring> jembedder;
90 if (embedder != origin)
91 jembedder = ConvertUTF8ToJavaString(env, embedder);
92 switch (content_type) {
93 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
94 Java_WebsitePreferenceBridge_insertMicrophoneInfoIntoList(
95 env, list, jorigin.obj(), jembedder.obj());
96 break;
97 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
98 Java_WebsitePreferenceBridge_insertCameraInfoIntoList(
99 env, list, jorigin.obj(), jembedder.obj());
100 break;
101 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
102 Java_WebsitePreferenceBridge_insertGeolocationInfoIntoList(
103 env, list, jorigin.obj(), jembedder.obj());
104 break;
105 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
106 Java_WebsitePreferenceBridge_insertMidiInfoIntoList(
107 env, list, jorigin.obj(), jembedder.obj());
108 break;
109 case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
110 Java_WebsitePreferenceBridge_insertProtectedMediaIdentifierInfoIntoList(
111 env, list, jorigin.obj(), jembedder.obj());
112 break;
113 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
114 Java_WebsitePreferenceBridge_insertPushNotificationIntoList(
115 env, list, jorigin.obj(), jembedder.obj());
116 break;
117 case CONTENT_SETTINGS_TYPE_FULLSCREEN:
118 Java_WebsitePreferenceBridge_insertFullscreenInfoIntoList(
119 env, list, jorigin.obj(), jembedder.obj());
120 break;
121 default:
122 DCHECK(false);
123 break;
128 static jint GetSettingForOrigin(JNIEnv* env,
129 ContentSettingsType content_type,
130 jstring origin,
131 jstring embedder) {
132 GURL url(ConvertJavaStringToUTF8(env, origin));
133 GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
134 ContentSetting setting = GetHostContentSettingsMap()->GetContentSetting(
135 url,
136 embedder_url,
137 content_type,
138 std::string());
139 return setting;
142 static void SetSettingForOrigin(JNIEnv* env,
143 ContentSettingsType content_type,
144 jstring origin,
145 ContentSettingsPattern secondary_pattern,
146 jint value) {
147 GURL url(ConvertJavaStringToUTF8(env, origin));
148 ContentSetting setting = CONTENT_SETTING_DEFAULT;
149 switch (value) {
150 case -1: break;
151 case 0: setting = CONTENT_SETTING_DEFAULT; break;
152 case 1: setting = CONTENT_SETTING_ALLOW; break;
153 case 2: setting = CONTENT_SETTING_BLOCK; break;
154 default:
155 // Note: CONTENT_SETTINGS_ASK is not and should not be supported.
156 NOTREACHED();
158 GetHostContentSettingsMap()->SetContentSetting(
159 ContentSettingsPattern::FromURLNoWildcard(url),
160 secondary_pattern,
161 content_type,
162 std::string(),
163 setting);
164 WebSiteSettingsUmaUtil::LogPermissionChange(content_type, setting);
167 static void GetFullscreenOrigins(JNIEnv* env,
168 jclass clazz,
169 jobject list,
170 jboolean managedOnly) {
171 GetOrigins(env, CONTENT_SETTINGS_TYPE_FULLSCREEN, list, managedOnly);
174 static jint GetFullscreenSettingForOrigin(JNIEnv* env, jclass clazz,
175 jstring origin, jstring embedder) {
176 return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_FULLSCREEN,
177 origin, embedder);
180 static void SetFullscreenSettingForOrigin(JNIEnv* env, jclass clazz,
181 jstring origin, jstring embedder, jint value) {
182 GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
183 SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_FULLSCREEN,
184 origin, ContentSettingsPattern::FromURLNoWildcard(embedder_url), value);
187 static void GetGeolocationOrigins(JNIEnv* env,
188 jclass clazz,
189 jobject list,
190 jboolean managedOnly) {
191 GetOrigins(env, CONTENT_SETTINGS_TYPE_GEOLOCATION, list, managedOnly);
194 static jint GetGeolocationSettingForOrigin(JNIEnv* env, jclass clazz,
195 jstring origin, jstring embedder) {
196 return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_GEOLOCATION,
197 origin, embedder);
200 static void SetGeolocationSettingForOrigin(JNIEnv* env, jclass clazz,
201 jstring origin, jstring embedder, jint value) {
202 GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
203 SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_GEOLOCATION,
204 origin, ContentSettingsPattern::FromURLNoWildcard(embedder_url), value);
207 static void GetMidiOrigins(JNIEnv* env, jclass clazz, jobject list) {
208 GetOrigins(env, CONTENT_SETTINGS_TYPE_MIDI_SYSEX, list, false);
211 static jint GetMidiSettingForOrigin(JNIEnv* env, jclass clazz, jstring origin,
212 jstring embedder) {
213 return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MIDI_SYSEX, origin,
214 embedder);
217 static void SetMidiSettingForOrigin(JNIEnv* env, jclass clazz, jstring origin,
218 jstring embedder, jint value) {
219 GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
220 SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MIDI_SYSEX, origin,
221 ContentSettingsPattern::FromURLNoWildcard(embedder_url), value);
224 static void GetProtectedMediaIdentifierOrigins(JNIEnv* env, jclass clazz,
225 jobject list) {
226 GetOrigins(env, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, list,
227 false);
230 static jint GetProtectedMediaIdentifierSettingForOrigin(JNIEnv* env,
231 jclass clazz, jstring origin, jstring embedder) {
232 return GetSettingForOrigin(
233 env, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, origin, embedder);
236 static void SetProtectedMediaIdentifierSettingForOrigin(JNIEnv* env,
237 jclass clazz, jstring origin, jstring embedder, jint value) {
238 GURL embedder_url(ConvertJavaStringToUTF8(env, embedder));
239 SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER,
240 origin, ContentSettingsPattern::FromURLNoWildcard(embedder_url), value);
243 static void GetPushNotificationOrigins(JNIEnv* env,
244 jclass clazz,
245 jobject list) {
246 GetOrigins(env, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, list, false);
249 static jint GetPushNotificationSettingForOrigin(JNIEnv* env, jclass clazz,
250 jstring origin, jstring embedder) {
251 return DesktopNotificationProfileUtil::GetContentSetting(
252 ProfileManager::GetActiveUserProfile(),
253 GURL(ConvertJavaStringToUTF8(env, origin)));
256 static void SetPushNotificationSettingForOrigin(JNIEnv* env, jclass clazz,
257 jstring origin, jstring embedder, jint value) {
258 // TODO(peter): Web Notification permission behaves differently from all other
259 // permission types. See https://crbug.com/416894.
260 Profile* profile = ProfileManager::GetActiveUserProfile();
261 GURL url = GURL(ConvertJavaStringToUTF8(env, origin));
262 ContentSetting setting = CONTENT_SETTING_DEFAULT;
263 switch (value) {
264 case -1:
265 DesktopNotificationProfileUtil::ClearSetting(
266 profile, ContentSettingsPattern::FromURLNoWildcard(url));
267 break;
268 case 1:
269 DesktopNotificationProfileUtil::GrantPermission(profile, url);
270 setting = CONTENT_SETTING_ALLOW;
271 break;
272 case 2:
273 DesktopNotificationProfileUtil::DenyPermission(profile, url);
274 setting = CONTENT_SETTING_BLOCK;
275 break;
276 default:
277 NOTREACHED();
279 WebSiteSettingsUmaUtil::LogPermissionChange(
280 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, setting);
283 static void GetCameraOrigins(JNIEnv* env,
284 jclass clazz,
285 jobject list,
286 jboolean managedOnly) {
287 GetOrigins(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, list, managedOnly);
290 static void GetMicrophoneOrigins(JNIEnv* env,
291 jclass clazz,
292 jobject list,
293 jboolean managedOnly) {
294 GetOrigins(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, list, managedOnly);
297 static jint GetMicrophoneSettingForOrigin(JNIEnv* env, jclass clazz,
298 jstring origin, jstring embedder) {
299 return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
300 origin, embedder);
303 static jint GetCameraSettingForOrigin(JNIEnv* env, jclass clazz,
304 jstring origin, jstring embedder) {
305 return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
306 origin, embedder);
309 static void SetMicrophoneSettingForOrigin(JNIEnv* env, jclass clazz,
310 jstring origin, jstring embedder, jint value) {
311 SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
312 origin, ContentSettingsPattern::Wildcard(), value);
315 static void SetCameraSettingForOrigin(JNIEnv* env, jclass clazz,
316 jstring origin, jstring embedder, jint value) {
317 SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
318 origin, ContentSettingsPattern::Wildcard(), value);
321 static scoped_refptr<CookieSettings> GetCookieSettings() {
322 Profile* profile = ProfileManager::GetActiveUserProfile();
323 return CookieSettings::Factory::GetForProfile(profile);
326 static void GetCookieOrigins(JNIEnv* env,
327 jclass clazz,
328 jobject list,
329 jboolean managedOnly) {
330 ContentSettingsForOneType all_settings;
331 GetCookieSettings()->GetCookieSettings(&all_settings);
332 const ContentSetting default_setting =
333 GetCookieSettings()->GetDefaultCookieSetting(nullptr);
334 for (const auto& settings_it : all_settings) {
335 if (settings_it.setting == default_setting)
336 continue;
337 if (managedOnly &&
338 HostContentSettingsMap::GetProviderTypeFromSource(settings_it.source) !=
339 HostContentSettingsMap::ProviderType::POLICY_PROVIDER) {
340 continue;
342 const std::string& origin = settings_it.primary_pattern.ToString();
343 const std::string& embedder = settings_it.secondary_pattern.ToString();
344 ScopedJavaLocalRef<jstring> jorigin = ConvertUTF8ToJavaString(env, origin);
345 ScopedJavaLocalRef<jstring> jembedder;
346 if (embedder != origin)
347 jembedder = ConvertUTF8ToJavaString(env, embedder);
348 Java_WebsitePreferenceBridge_insertCookieInfoIntoList(env, list,
349 jorigin.obj(), jembedder.obj());
353 static jint GetCookieSettingForOrigin(JNIEnv* env, jclass clazz,
354 jstring origin, jstring embedder) {
355 return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_COOKIES, origin,
356 embedder);
359 static void SetCookieSettingForOrigin(JNIEnv* env, jclass clazz,
360 jstring origin, jstring embedder, jint value) {
361 GURL url(ConvertJavaStringToUTF8(env, origin));
362 ContentSettingsPattern primary_pattern(
363 ContentSettingsPattern::FromURLNoWildcard(url));
364 ContentSettingsPattern secondary_pattern(ContentSettingsPattern::Wildcard());
365 ContentSetting setting = CONTENT_SETTING_DEFAULT;
366 if (value == -1) {
367 GetCookieSettings()->ResetCookieSetting(primary_pattern, secondary_pattern);
368 } else {
369 setting = value ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
370 GetCookieSettings()->SetCookieSetting(primary_pattern, secondary_pattern,
371 setting);
373 WebSiteSettingsUmaUtil::LogPermissionChange(
374 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, setting);
377 static jboolean IsContentSettingsPatternValid(JNIEnv* env, jclass clazz,
378 jstring pattern) {
379 return ContentSettingsPattern::FromString(
380 ConvertJavaStringToUTF8(env, pattern)).IsValid();
383 namespace {
385 class SiteDataDeleteHelper :
386 public base::RefCountedThreadSafe<SiteDataDeleteHelper>,
387 public CookiesTreeModel::Observer {
388 public:
389 SiteDataDeleteHelper(Profile* profile, const GURL& domain)
390 : profile_(profile), domain_(domain), ending_batch_processing_(false) {
393 void Run() {
394 AddRef(); // Balanced in TreeModelEndBatch.
396 content::StoragePartition* storage_partition =
397 content::BrowserContext::GetDefaultStoragePartition(profile_);
398 content::IndexedDBContext* indexed_db_context =
399 storage_partition->GetIndexedDBContext();
400 content::ServiceWorkerContext* service_worker_context =
401 storage_partition->GetServiceWorkerContext();
402 storage::FileSystemContext* file_system_context =
403 storage_partition->GetFileSystemContext();
404 LocalDataContainer* container = new LocalDataContainer(
405 new BrowsingDataCookieHelper(profile_->GetRequestContext()),
406 new BrowsingDataDatabaseHelper(profile_),
407 new BrowsingDataLocalStorageHelper(profile_),
408 NULL,
409 new BrowsingDataAppCacheHelper(profile_),
410 new BrowsingDataIndexedDBHelper(indexed_db_context),
411 BrowsingDataFileSystemHelper::Create(file_system_context),
412 BrowsingDataQuotaHelper::Create(profile_),
413 BrowsingDataChannelIDHelper::Create(profile_->GetRequestContext()),
414 new BrowsingDataServiceWorkerHelper(service_worker_context),
415 NULL);
417 cookies_tree_model_.reset(new CookiesTreeModel(
418 container, profile_->GetExtensionSpecialStoragePolicy(), false));
419 cookies_tree_model_->AddCookiesTreeObserver(this);
422 // TreeModelObserver:
423 void TreeNodesAdded(ui::TreeModel* model,
424 ui::TreeModelNode* parent,
425 int start,
426 int count) override {}
427 void TreeNodesRemoved(ui::TreeModel* model,
428 ui::TreeModelNode* parent,
429 int start,
430 int count) override {}
432 // CookiesTreeModel::Observer:
433 void TreeNodeChanged(ui::TreeModel* model, ui::TreeModelNode* node) override {
436 void TreeModelBeginBatch(CookiesTreeModel* model) override {
437 DCHECK(!ending_batch_processing_); // Extra batch-start sent.
440 void TreeModelEndBatch(CookiesTreeModel* model) override {
441 DCHECK(!ending_batch_processing_); // Already in end-stage.
442 ending_batch_processing_ = true;
444 RecursivelyFindSiteAndDelete(cookies_tree_model_->GetRoot());
446 // This will result in this class getting deleted.
447 Release();
450 void RecursivelyFindSiteAndDelete(CookieTreeNode* node) {
451 CookieTreeNode::DetailedInfo info = node->GetDetailedInfo();
452 for (int i = node->child_count(); i > 0; --i)
453 RecursivelyFindSiteAndDelete(node->GetChild(i - 1));
455 if (info.node_type == CookieTreeNode::DetailedInfo::TYPE_COOKIE &&
456 info.cookie &&
457 domain_.DomainIs(info.cookie->Domain().c_str()))
458 cookies_tree_model_->DeleteCookieNode(node);
461 private:
462 friend class base::RefCountedThreadSafe<SiteDataDeleteHelper>;
464 ~SiteDataDeleteHelper() override {}
466 Profile* profile_;
468 // The domain we want to delete data for.
469 GURL domain_;
471 // Keeps track of when we're ready to close batch processing.
472 bool ending_batch_processing_;
474 scoped_ptr<CookiesTreeModel> cookies_tree_model_;
476 DISALLOW_COPY_AND_ASSIGN(SiteDataDeleteHelper);
479 class StorageInfoFetcher :
480 public base::RefCountedThreadSafe<StorageInfoFetcher> {
481 public:
482 StorageInfoFetcher(storage::QuotaManager* quota_manager,
483 const JavaRef<jobject>& java_callback)
484 : env_(base::android::AttachCurrentThread()),
485 quota_manager_(quota_manager),
486 java_callback_(java_callback) {
489 void Run() {
490 // QuotaManager must be called on IO thread, but java_callback must then be
491 // called back on UI thread.
492 BrowserThread::PostTask(
493 BrowserThread::IO, FROM_HERE,
494 base::Bind(&StorageInfoFetcher::GetUsageInfo, this));
497 protected:
498 virtual ~StorageInfoFetcher() {}
500 private:
501 friend class base::RefCountedThreadSafe<StorageInfoFetcher>;
503 void GetUsageInfo() {
504 // We will have no explicit owner as soon as we leave this method.
505 AddRef();
506 quota_manager_->GetUsageInfo(
507 base::Bind(&StorageInfoFetcher::OnGetUsageInfo, this));
510 void OnGetUsageInfo(const storage::UsageInfoEntries& entries) {
511 entries_.insert(entries_.begin(), entries.begin(), entries.end());
512 BrowserThread::PostTask(
513 BrowserThread::UI, FROM_HERE,
514 base::Bind(&StorageInfoFetcher::InvokeCallback, this));
515 Release();
518 void InvokeCallback() {
519 ScopedJavaLocalRef<jobject> list =
520 Java_WebsitePreferenceBridge_createStorageInfoList(env_);
522 storage::UsageInfoEntries::const_iterator i;
523 for (i = entries_.begin(); i != entries_.end(); ++i) {
524 if (i->usage <= 0) continue;
525 ScopedJavaLocalRef<jstring> host =
526 ConvertUTF8ToJavaString(env_, i->host);
528 Java_WebsitePreferenceBridge_insertStorageInfoIntoList(
529 env_, list.obj(), host.obj(), i->type, i->usage);
531 Java_StorageInfoReadyCallback_onStorageInfoReady(
532 env_, java_callback_.obj(), list.obj());
535 JNIEnv* env_;
536 storage::QuotaManager* quota_manager_;
537 ScopedJavaGlobalRef<jobject> java_callback_;
538 storage::UsageInfoEntries entries_;
540 DISALLOW_COPY_AND_ASSIGN(StorageInfoFetcher);
543 class StorageDataDeleter :
544 public base::RefCountedThreadSafe<StorageDataDeleter> {
545 public:
546 StorageDataDeleter(storage::QuotaManager* quota_manager,
547 const std::string& host,
548 storage::StorageType type,
549 const JavaRef<jobject>& java_callback)
550 : env_(base::android::AttachCurrentThread()),
551 quota_manager_(quota_manager),
552 host_(host),
553 type_(type),
554 java_callback_(java_callback) {
557 void Run() {
558 // QuotaManager must be called on IO thread, but java_callback must then be
559 // called back on UI thread. Grant ourself an extra reference to avoid
560 // being deleted after DeleteHostData will return.
561 AddRef();
562 BrowserThread::PostTask(
563 BrowserThread::IO, FROM_HERE,
564 base::Bind(&storage::QuotaManager::DeleteHostData,
565 quota_manager_,
566 host_,
567 type_,
568 storage::QuotaClient::kAllClientsMask,
569 base::Bind(&StorageDataDeleter::OnHostDataDeleted,
570 this)));
573 protected:
574 virtual ~StorageDataDeleter() {}
576 private:
577 friend class base::RefCountedThreadSafe<StorageDataDeleter>;
579 void OnHostDataDeleted(storage::QuotaStatusCode) {
580 DCHECK_CURRENTLY_ON(BrowserThread::IO);
581 quota_manager_->ResetUsageTracker(type_);
582 BrowserThread::PostTask(
583 BrowserThread::UI, FROM_HERE,
584 base::Bind(&StorageDataDeleter::InvokeCallback, this));
585 Release();
588 void InvokeCallback() {
589 Java_StorageInfoClearedCallback_onStorageInfoCleared(
590 env_, java_callback_.obj());
593 JNIEnv* env_;
594 storage::QuotaManager* quota_manager_;
595 std::string host_;
596 storage::StorageType type_;
597 ScopedJavaGlobalRef<jobject> java_callback_;
600 class LocalStorageInfoReadyCallback {
601 public:
602 LocalStorageInfoReadyCallback(
603 const ScopedJavaLocalRef<jobject>& java_callback)
604 : env_(base::android::AttachCurrentThread()),
605 java_callback_(java_callback) {
608 void OnLocalStorageModelInfoLoaded(
609 const std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>&
610 local_storage_info) {
611 ScopedJavaLocalRef<jobject> map =
612 Java_WebsitePreferenceBridge_createLocalStorageInfoMap(env_);
614 std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::const_iterator
616 for (i = local_storage_info.begin(); i != local_storage_info.end(); ++i) {
617 ScopedJavaLocalRef<jstring> full_origin =
618 ConvertUTF8ToJavaString(env_, i->origin_url.spec());
619 // Remove the trailing backslash so the origin is matched correctly in
620 // SingleWebsitePreferences.mergePermissionInfoForTopLevelOrigin.
621 std::string origin_str = i->origin_url.GetOrigin().spec();
622 DCHECK(origin_str[origin_str.size() - 1] == '/');
623 origin_str = origin_str.substr(0, origin_str.size() - 1);
624 ScopedJavaLocalRef<jstring> origin =
625 ConvertUTF8ToJavaString(env_, origin_str);
626 Java_WebsitePreferenceBridge_insertLocalStorageInfoIntoMap(
627 env_, map.obj(), origin.obj(), full_origin.obj(), i->size);
630 Java_LocalStorageInfoReadyCallback_onLocalStorageInfoReady(
631 env_, java_callback_.obj(), map.obj());
632 delete this;
635 private:
636 JNIEnv* env_;
637 ScopedJavaGlobalRef<jobject> java_callback_;
640 } // anonymous namespace
642 // TODO(jknotten): These methods should not be static. Instead we should
643 // expose a class to Java so that the fetch requests can be cancelled,
644 // and manage the lifetimes of the callback (and indirectly the helper
645 // by having a reference to it).
647 // The helper methods (StartFetching, DeleteLocalStorageFile, DeleteDatabase)
648 // are asynchronous. A "use after free" error is not possible because the
649 // helpers keep a reference to themselves for the duration of their tasks,
650 // which includes callback invocation.
652 static void FetchLocalStorageInfo(JNIEnv* env, jclass clazz,
653 jobject java_callback) {
654 Profile* profile = ProfileManager::GetActiveUserProfile();
655 scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper(
656 new BrowsingDataLocalStorageHelper(profile));
657 // local_storage_callback will delete itself when it is run.
658 LocalStorageInfoReadyCallback* local_storage_callback =
659 new LocalStorageInfoReadyCallback(
660 ScopedJavaLocalRef<jobject>(env, java_callback));
661 local_storage_helper->StartFetching(
662 base::Bind(&LocalStorageInfoReadyCallback::OnLocalStorageModelInfoLoaded,
663 base::Unretained(local_storage_callback)));
666 static void FetchStorageInfo(JNIEnv* env, jclass clazz, jobject java_callback) {
667 Profile* profile = ProfileManager::GetActiveUserProfile();
668 scoped_refptr<StorageInfoFetcher> storage_info_fetcher(new StorageInfoFetcher(
669 content::BrowserContext::GetDefaultStoragePartition(
670 profile)->GetQuotaManager(),
671 ScopedJavaLocalRef<jobject>(env, java_callback)));
672 storage_info_fetcher->Run();
675 static void ClearLocalStorageData(JNIEnv* env, jclass clazz, jstring jorigin) {
676 Profile* profile = ProfileManager::GetActiveUserProfile();
677 scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper =
678 new BrowsingDataLocalStorageHelper(profile);
679 GURL origin_url = GURL(ConvertJavaStringToUTF8(env, jorigin));
680 local_storage_helper->DeleteOrigin(origin_url);
683 static void ClearStorageData(JNIEnv* env,
684 jclass clazz,
685 jstring jhost,
686 jint type,
687 jobject java_callback) {
688 Profile* profile = ProfileManager::GetActiveUserProfile();
689 std::string host = ConvertJavaStringToUTF8(env, jhost);
690 scoped_refptr<StorageDataDeleter> storage_data_deleter(new StorageDataDeleter(
691 content::BrowserContext::GetDefaultStoragePartition(
692 profile)->GetQuotaManager(),
693 host,
694 static_cast<storage::StorageType>(type),
695 ScopedJavaLocalRef<jobject>(env, java_callback)));
696 storage_data_deleter->Run();
699 static void ClearCookieData(JNIEnv* env, jclass clazz, jstring jorigin) {
700 Profile* profile = ProfileManager::GetActiveUserProfile();
701 GURL url(ConvertJavaStringToUTF8(env, jorigin));
702 scoped_refptr<SiteDataDeleteHelper> site_data_deleter(
703 new SiteDataDeleteHelper(profile, url));
704 site_data_deleter->Run();
707 // Register native methods
708 bool RegisterWebsitePreferenceBridge(JNIEnv* env) {
709 return RegisterNativesImpl(env);