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
,
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
)
57 HostContentSettingsMap::GetProviderTypeFromSource(settings_it
.source
) !=
58 HostContentSettingsMap::ProviderType::POLICY_PROVIDER
) {
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
)));
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());
97 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
:
98 Java_WebsitePreferenceBridge_insertCameraInfoIntoList(
99 env
, list
, jorigin
.obj(), jembedder
.obj());
101 case CONTENT_SETTINGS_TYPE_GEOLOCATION
:
102 Java_WebsitePreferenceBridge_insertGeolocationInfoIntoList(
103 env
, list
, jorigin
.obj(), jembedder
.obj());
105 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX
:
106 Java_WebsitePreferenceBridge_insertMidiInfoIntoList(
107 env
, list
, jorigin
.obj(), jembedder
.obj());
109 case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
:
110 Java_WebsitePreferenceBridge_insertProtectedMediaIdentifierInfoIntoList(
111 env
, list
, jorigin
.obj(), jembedder
.obj());
113 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS
:
114 Java_WebsitePreferenceBridge_insertPushNotificationIntoList(
115 env
, list
, jorigin
.obj(), jembedder
.obj());
117 case CONTENT_SETTINGS_TYPE_FULLSCREEN
:
118 Java_WebsitePreferenceBridge_insertFullscreenInfoIntoList(
119 env
, list
, jorigin
.obj(), jembedder
.obj());
128 static jint
GetSettingForOrigin(JNIEnv
* env
,
129 ContentSettingsType content_type
,
132 GURL
url(ConvertJavaStringToUTF8(env
, origin
));
133 GURL
embedder_url(ConvertJavaStringToUTF8(env
, embedder
));
134 ContentSetting setting
= GetHostContentSettingsMap()->GetContentSetting(
142 static void SetSettingForOrigin(JNIEnv
* env
,
143 ContentSettingsType content_type
,
145 ContentSettingsPattern secondary_pattern
,
147 GURL
url(ConvertJavaStringToUTF8(env
, origin
));
148 ContentSetting setting
= CONTENT_SETTING_DEFAULT
;
151 case 0: setting
= CONTENT_SETTING_DEFAULT
; break;
152 case 1: setting
= CONTENT_SETTING_ALLOW
; break;
153 case 2: setting
= CONTENT_SETTING_BLOCK
; break;
155 // Note: CONTENT_SETTINGS_ASK is not and should not be supported.
158 GetHostContentSettingsMap()->SetContentSetting(
159 ContentSettingsPattern::FromURLNoWildcard(url
),
164 WebSiteSettingsUmaUtil::LogPermissionChange(content_type
, setting
);
167 static void GetFullscreenOrigins(JNIEnv
* env
,
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
,
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
,
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
,
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
,
213 return GetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, origin
,
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
,
226 GetOrigins(env
, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
, list
,
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
,
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
;
265 DesktopNotificationProfileUtil::ClearSetting(
266 profile
, ContentSettingsPattern::FromURLNoWildcard(url
));
269 DesktopNotificationProfileUtil::GrantPermission(profile
, url
);
270 setting
= CONTENT_SETTING_ALLOW
;
273 DesktopNotificationProfileUtil::DenyPermission(profile
, url
);
274 setting
= CONTENT_SETTING_BLOCK
;
279 WebSiteSettingsUmaUtil::LogPermissionChange(
280 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, setting
);
283 static void GetCameraOrigins(JNIEnv
* env
,
286 jboolean managedOnly
) {
287 GetOrigins(env
, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, list
, managedOnly
);
290 static void GetMicrophoneOrigins(JNIEnv
* env
,
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
,
303 static jint
GetCameraSettingForOrigin(JNIEnv
* env
, jclass clazz
,
304 jstring origin
, jstring embedder
) {
305 return GetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
,
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
,
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
)
338 HostContentSettingsMap::GetProviderTypeFromSource(settings_it
.source
) !=
339 HostContentSettingsMap::ProviderType::POLICY_PROVIDER
) {
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
,
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
;
367 GetCookieSettings()->ResetCookieSetting(primary_pattern
, secondary_pattern
);
369 setting
= value
? CONTENT_SETTING_ALLOW
: CONTENT_SETTING_BLOCK
;
370 GetCookieSettings()->SetCookieSetting(primary_pattern
, secondary_pattern
,
373 WebSiteSettingsUmaUtil::LogPermissionChange(
374 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, setting
);
377 static jboolean
IsContentSettingsPatternValid(JNIEnv
* env
, jclass clazz
,
379 return ContentSettingsPattern::FromString(
380 ConvertJavaStringToUTF8(env
, pattern
)).IsValid();
385 class SiteDataDeleteHelper
:
386 public base::RefCountedThreadSafe
<SiteDataDeleteHelper
>,
387 public CookiesTreeModel::Observer
{
389 SiteDataDeleteHelper(Profile
* profile
, const GURL
& domain
)
390 : profile_(profile
), domain_(domain
), ending_batch_processing_(false) {
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_
),
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
),
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
,
426 int count
) override
{}
427 void TreeNodesRemoved(ui::TreeModel
* model
,
428 ui::TreeModelNode
* parent
,
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.
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
&&
457 domain_
.DomainIs(info
.cookie
->Domain().c_str()))
458 cookies_tree_model_
->DeleteCookieNode(node
);
462 friend class base::RefCountedThreadSafe
<SiteDataDeleteHelper
>;
464 ~SiteDataDeleteHelper() override
{}
468 // The domain we want to delete data for.
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
> {
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
) {
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));
498 virtual ~StorageInfoFetcher() {}
501 friend class base::RefCountedThreadSafe
<StorageInfoFetcher
>;
503 void GetUsageInfo() {
504 // We will have no explicit owner as soon as we leave this method.
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));
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());
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
> {
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
),
554 java_callback_(java_callback
) {
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.
562 BrowserThread::PostTask(
563 BrowserThread::IO
, FROM_HERE
,
564 base::Bind(&storage::QuotaManager::DeleteHostData
,
568 storage::QuotaClient::kAllClientsMask
,
569 base::Bind(&StorageDataDeleter::OnHostDataDeleted
,
574 virtual ~StorageDataDeleter() {}
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));
588 void InvokeCallback() {
589 Java_StorageInfoClearedCallback_onStorageInfoCleared(
590 env_
, java_callback_
.obj());
594 storage::QuotaManager
* quota_manager_
;
596 storage::StorageType type_
;
597 ScopedJavaGlobalRef
<jobject
> java_callback_
;
600 class LocalStorageInfoReadyCallback
{
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());
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
,
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(),
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
);