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
,
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
)
58 HostContentSettingsMap::GetProviderTypeFromSource(settings_it
.source
) !=
59 HostContentSettingsMap::ProviderType::POLICY_PROVIDER
) {
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
)));
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());
102 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
:
103 Java_WebsitePreferenceBridge_insertCameraInfoIntoList(
104 env
, list
, jorigin
.obj(), jembedder
.obj());
106 case CONTENT_SETTINGS_TYPE_GEOLOCATION
:
107 Java_WebsitePreferenceBridge_insertGeolocationInfoIntoList(
108 env
, list
, jorigin
.obj(), jembedder
.obj());
110 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX
:
111 Java_WebsitePreferenceBridge_insertMidiInfoIntoList(
112 env
, list
, jorigin
.obj(), jembedder
.obj());
114 case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
:
115 Java_WebsitePreferenceBridge_insertProtectedMediaIdentifierInfoIntoList(
116 env
, list
, jorigin
.obj(), jembedder
.obj());
118 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS
:
119 Java_WebsitePreferenceBridge_insertPushNotificationIntoList(
120 env
, list
, jorigin
.obj(), jembedder
.obj());
122 case CONTENT_SETTINGS_TYPE_FULLSCREEN
:
123 Java_WebsitePreferenceBridge_insertFullscreenInfoIntoList(
124 env
, list
, jorigin
.obj(), jembedder
.obj());
133 static jint
GetSettingForOrigin(JNIEnv
* env
,
134 ContentSettingsType content_type
,
137 GURL
url(ConvertJavaStringToUTF8(env
, origin
));
138 GURL
embedder_url(ConvertJavaStringToUTF8(env
, embedder
));
139 ContentSetting setting
= GetHostContentSettingsMap()->GetContentSetting(
147 static void SetSettingForOrigin(JNIEnv
* env
,
148 ContentSettingsType content_type
,
150 ContentSettingsPattern secondary_pattern
,
152 GURL
url(ConvertJavaStringToUTF8(env
, origin
));
153 ContentSetting setting
= CONTENT_SETTING_DEFAULT
;
156 case 0: setting
= CONTENT_SETTING_DEFAULT
; break;
157 case 1: setting
= CONTENT_SETTING_ALLOW
; break;
158 case 2: setting
= CONTENT_SETTING_BLOCK
; break;
160 // Note: CONTENT_SETTINGS_ASK is not and should not be supported.
163 GetHostContentSettingsMap()->SetContentSetting(
164 ContentSettingsPattern::FromURLNoWildcard(url
),
169 WebSiteSettingsUmaUtil::LogPermissionChange(content_type
, setting
);
172 static void GetFullscreenOrigins(JNIEnv
* env
,
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
,
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
,
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
,
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
,
218 return GetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, origin
,
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
,
231 GetOrigins(env
, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
, list
,
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
,
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
;
270 DesktopNotificationProfileUtil::ClearSetting(
271 profile
, ContentSettingsPattern::FromURLNoWildcard(url
));
274 DesktopNotificationProfileUtil::GrantPermission(profile
, url
);
275 setting
= CONTENT_SETTING_ALLOW
;
278 DesktopNotificationProfileUtil::DenyPermission(profile
, url
);
279 setting
= CONTENT_SETTING_BLOCK
;
284 WebSiteSettingsUmaUtil::LogPermissionChange(
285 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, setting
);
288 static void GetCameraOrigins(JNIEnv
* env
,
291 jboolean managedOnly
) {
292 GetOrigins(env
, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, list
, managedOnly
);
295 static void GetMicrophoneOrigins(JNIEnv
* env
,
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
,
308 static jint
GetCameraSettingForOrigin(JNIEnv
* env
, jclass clazz
,
309 jstring origin
, jstring embedder
) {
310 return GetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
,
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
,
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
)
343 HostContentSettingsMap::GetProviderTypeFromSource(settings_it
.source
) !=
344 HostContentSettingsMap::ProviderType::POLICY_PROVIDER
) {
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
,
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
;
372 GetCookieSettings()->ResetCookieSetting(primary_pattern
, secondary_pattern
);
374 setting
= value
? CONTENT_SETTING_ALLOW
: CONTENT_SETTING_BLOCK
;
375 GetCookieSettings()->SetCookieSetting(primary_pattern
, secondary_pattern
,
378 WebSiteSettingsUmaUtil::LogPermissionChange(
379 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, setting
);
382 static jboolean
IsContentSettingsPatternValid(JNIEnv
* env
, jclass clazz
,
384 return ContentSettingsPattern::FromString(
385 ConvertJavaStringToUTF8(env
, pattern
)).IsValid();
388 static jboolean
UrlMatchesContentSettingsPattern(JNIEnv
* env
,
392 ContentSettingsPattern pattern
= ContentSettingsPattern::FromString(
393 ConvertJavaStringToUTF8(env
, jpattern
));
394 return pattern
.Matches(GURL(ConvertJavaStringToUTF8(env
, jurl
)));
399 class SiteDataDeleteHelper
:
400 public base::RefCountedThreadSafe
<SiteDataDeleteHelper
>,
401 public CookiesTreeModel::Observer
{
403 SiteDataDeleteHelper(Profile
* profile
, const GURL
& domain
)
404 : profile_(profile
), domain_(domain
), ending_batch_processing_(false) {
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_
),
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
),
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
,
440 int count
) override
{}
441 void TreeNodesRemoved(ui::TreeModel
* model
,
442 ui::TreeModelNode
* parent
,
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.
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
&&
471 domain_
.DomainIs(info
.cookie
->Domain().c_str()))
472 cookies_tree_model_
->DeleteCookieNode(node
);
476 friend class base::RefCountedThreadSafe
<SiteDataDeleteHelper
>;
478 ~SiteDataDeleteHelper() override
{}
482 // The domain we want to delete data for.
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
> {
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
) {
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));
512 virtual ~StorageInfoFetcher() {}
515 friend class base::RefCountedThreadSafe
<StorageInfoFetcher
>;
517 void GetUsageInfo() {
518 // We will have no explicit owner as soon as we leave this method.
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));
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());
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
> {
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
),
568 java_callback_(java_callback
) {
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.
576 BrowserThread::PostTask(
577 BrowserThread::IO
, FROM_HERE
,
578 base::Bind(&storage::QuotaManager::DeleteHostData
,
582 storage::QuotaClient::kAllClientsMask
,
583 base::Bind(&StorageDataDeleter::OnHostDataDeleted
,
588 virtual ~StorageDataDeleter() {}
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));
602 void InvokeCallback() {
603 Java_StorageInfoClearedCallback_onStorageInfoCleared(
604 env_
, java_callback_
.obj());
608 storage::QuotaManager
* quota_manager_
;
610 storage::StorageType type_
;
611 ScopedJavaGlobalRef
<jobject
> java_callback_
;
614 class LocalStorageInfoReadyCallback
{
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());
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
,
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(),
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
);