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 Profile
* GetActiveUserProfile(bool is_incognito
) {
39 Profile
* profile
= ProfileManager::GetActiveUserProfile();
41 profile
= profile
->GetOffTheRecordProfile();
45 static HostContentSettingsMap
* GetHostContentSettingsMap(bool is_incognito
) {
46 return GetActiveUserProfile(is_incognito
)->GetHostContentSettingsMap();
49 static void GetOrigins(JNIEnv
* env
,
50 ContentSettingsType content_type
,
52 jboolean managedOnly
) {
53 ContentSettingsForOneType all_settings
;
54 HostContentSettingsMap
* content_settings_map
=
55 GetHostContentSettingsMap(false);
56 content_settings_map
->GetSettingsForOneType(
57 content_type
, std::string(), &all_settings
);
58 ContentSetting default_content_setting
= content_settings_map
->
59 GetDefaultContentSetting(content_type
, NULL
);
60 // Now add all origins that have a non-default setting to the list.
61 for (const auto& settings_it
: all_settings
) {
62 if (settings_it
.setting
== default_content_setting
)
65 HostContentSettingsMap::GetProviderTypeFromSource(settings_it
.source
) !=
66 HostContentSettingsMap::ProviderType::POLICY_PROVIDER
) {
69 const std::string origin
= settings_it
.primary_pattern
.ToString();
70 const std::string embedder
= settings_it
.secondary_pattern
.ToString();
72 // The string |jorigin| is used to group permissions together in the Site
73 // Settings list. In order to group sites with the same origin, remove any
74 // standard port from the end of the URL if it's present (i.e. remove :443
75 // for HTTPS sites and :80 for HTTP sites).
76 // TODO(sashab,lgarron): Find out which settings are being saved with the
77 // port and omit it if it's the standard port.
78 // TODO(mvanouwerkerk): Remove all this logic and take two passes through
79 // HostContentSettingsMap: once to get all the 'interesting' hosts, and once
80 // (on SingleWebsitePreferences) to find permission patterns which match
81 // each of these hosts.
82 const char* kHttpPortSuffix
= ":80";
83 const char* kHttpsPortSuffix
= ":443";
84 ScopedJavaLocalRef
<jstring
> jorigin
;
85 if (base::StartsWith(origin
, url::kHttpsScheme
,
86 base::CompareCase::INSENSITIVE_ASCII
) &&
87 base::EndsWith(origin
, kHttpsPortSuffix
,
88 base::CompareCase::INSENSITIVE_ASCII
)) {
89 jorigin
= ConvertUTF8ToJavaString(
90 env
, origin
.substr(0, origin
.size() - strlen(kHttpsPortSuffix
)));
91 } else if (base::StartsWith(origin
, url::kHttpScheme
,
92 base::CompareCase::INSENSITIVE_ASCII
) &&
93 base::EndsWith(origin
, kHttpPortSuffix
,
94 base::CompareCase::INSENSITIVE_ASCII
)) {
95 jorigin
= ConvertUTF8ToJavaString(
96 env
, origin
.substr(0, origin
.size() - strlen(kHttpPortSuffix
)));
98 jorigin
= ConvertUTF8ToJavaString(env
, origin
);
101 ScopedJavaLocalRef
<jstring
> jembedder
;
102 if (embedder
!= origin
)
103 jembedder
= ConvertUTF8ToJavaString(env
, embedder
);
104 switch (content_type
) {
105 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
:
106 Java_WebsitePreferenceBridge_insertMicrophoneInfoIntoList(
107 env
, list
, jorigin
.obj(), jembedder
.obj());
109 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
:
110 Java_WebsitePreferenceBridge_insertCameraInfoIntoList(
111 env
, list
, jorigin
.obj(), jembedder
.obj());
113 case CONTENT_SETTINGS_TYPE_GEOLOCATION
:
114 Java_WebsitePreferenceBridge_insertGeolocationInfoIntoList(
115 env
, list
, jorigin
.obj(), jembedder
.obj());
117 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX
:
118 Java_WebsitePreferenceBridge_insertMidiInfoIntoList(
119 env
, list
, jorigin
.obj(), jembedder
.obj());
121 case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
:
122 Java_WebsitePreferenceBridge_insertProtectedMediaIdentifierInfoIntoList(
123 env
, list
, jorigin
.obj(), jembedder
.obj());
125 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS
:
126 Java_WebsitePreferenceBridge_insertPushNotificationIntoList(
127 env
, list
, jorigin
.obj(), jembedder
.obj());
129 case CONTENT_SETTINGS_TYPE_FULLSCREEN
:
130 Java_WebsitePreferenceBridge_insertFullscreenInfoIntoList(
131 env
, list
, jorigin
.obj(), jembedder
.obj());
140 static jint
GetSettingForOrigin(JNIEnv
* env
,
141 ContentSettingsType content_type
,
144 jboolean is_incognito
) {
145 GURL
url(ConvertJavaStringToUTF8(env
, origin
));
146 GURL
embedder_url(ConvertJavaStringToUTF8(env
, embedder
));
147 ContentSetting setting
=
148 GetHostContentSettingsMap(is_incognito
)
149 ->GetContentSetting(url
, embedder_url
, content_type
, std::string());
153 static void SetSettingForOrigin(JNIEnv
* env
,
154 ContentSettingsType content_type
,
156 ContentSettingsPattern secondary_pattern
,
158 jboolean is_incognito
) {
159 GURL
url(ConvertJavaStringToUTF8(env
, origin
));
160 ContentSetting setting
= CONTENT_SETTING_DEFAULT
;
163 case 0: setting
= CONTENT_SETTING_DEFAULT
; break;
164 case 1: setting
= CONTENT_SETTING_ALLOW
; break;
165 case 2: setting
= CONTENT_SETTING_BLOCK
; break;
167 // Note: CONTENT_SETTINGS_ASK is not and should not be supported.
170 GetHostContentSettingsMap(is_incognito
)
171 ->SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(url
),
172 secondary_pattern
, content_type
, std::string(),
174 WebSiteSettingsUmaUtil::LogPermissionChange(content_type
, setting
);
177 static void GetFullscreenOrigins(JNIEnv
* env
,
178 const JavaParamRef
<jclass
>& clazz
,
179 const JavaParamRef
<jobject
>& list
,
180 jboolean managedOnly
) {
181 GetOrigins(env
, CONTENT_SETTINGS_TYPE_FULLSCREEN
, list
, managedOnly
);
184 static jint
GetFullscreenSettingForOrigin(JNIEnv
* env
,
185 const JavaParamRef
<jclass
>& clazz
,
186 const JavaParamRef
<jstring
>& origin
,
187 const JavaParamRef
<jstring
>& embedder
,
188 jboolean is_incognito
) {
189 return GetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_FULLSCREEN
, origin
,
190 embedder
, is_incognito
);
193 static void SetFullscreenSettingForOrigin(JNIEnv
* env
,
194 const JavaParamRef
<jclass
>& clazz
,
195 const JavaParamRef
<jstring
>& origin
,
196 const JavaParamRef
<jstring
>& embedder
,
198 jboolean is_incognito
) {
199 GURL
embedder_url(ConvertJavaStringToUTF8(env
, embedder
));
200 SetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_FULLSCREEN
, origin
,
201 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
202 value
, is_incognito
);
205 static void GetGeolocationOrigins(JNIEnv
* env
,
206 const JavaParamRef
<jclass
>& clazz
,
207 const JavaParamRef
<jobject
>& list
,
208 jboolean managedOnly
) {
209 GetOrigins(env
, CONTENT_SETTINGS_TYPE_GEOLOCATION
, list
, managedOnly
);
212 static jint
GetGeolocationSettingForOrigin(
214 const JavaParamRef
<jclass
>& clazz
,
215 const JavaParamRef
<jstring
>& origin
,
216 const JavaParamRef
<jstring
>& embedder
,
217 jboolean is_incognito
) {
218 return GetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_GEOLOCATION
, origin
,
219 embedder
, is_incognito
);
222 static void SetGeolocationSettingForOrigin(
224 const JavaParamRef
<jclass
>& clazz
,
225 const JavaParamRef
<jstring
>& origin
,
226 const JavaParamRef
<jstring
>& embedder
,
228 jboolean is_incognito
) {
229 GURL
embedder_url(ConvertJavaStringToUTF8(env
, embedder
));
230 SetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_GEOLOCATION
, origin
,
231 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
232 value
, is_incognito
);
235 static void GetMidiOrigins(JNIEnv
* env
,
236 const JavaParamRef
<jclass
>& clazz
,
237 const JavaParamRef
<jobject
>& list
) {
238 GetOrigins(env
, CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, list
, false);
241 static jint
GetMidiSettingForOrigin(JNIEnv
* env
,
242 const JavaParamRef
<jclass
>& clazz
,
243 const JavaParamRef
<jstring
>& origin
,
244 const JavaParamRef
<jstring
>& embedder
,
245 jboolean is_incognito
) {
246 return GetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, origin
,
247 embedder
, is_incognito
);
250 static void SetMidiSettingForOrigin(JNIEnv
* env
,
251 const JavaParamRef
<jclass
>& clazz
,
252 const JavaParamRef
<jstring
>& origin
,
253 const JavaParamRef
<jstring
>& embedder
,
255 jboolean is_incognito
) {
256 GURL
embedder_url(ConvertJavaStringToUTF8(env
, embedder
));
257 SetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, origin
,
258 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
259 value
, is_incognito
);
262 static void GetProtectedMediaIdentifierOrigins(
264 const JavaParamRef
<jclass
>& clazz
,
265 const JavaParamRef
<jobject
>& list
) {
266 GetOrigins(env
, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
, list
,
270 static jint
GetProtectedMediaIdentifierSettingForOrigin(
272 const JavaParamRef
<jclass
>& clazz
,
273 const JavaParamRef
<jstring
>& origin
,
274 const JavaParamRef
<jstring
>& embedder
,
275 jboolean is_incognito
) {
276 return GetSettingForOrigin(env
,
277 CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
,
278 origin
, embedder
, is_incognito
);
281 static void SetProtectedMediaIdentifierSettingForOrigin(
283 const JavaParamRef
<jclass
>& clazz
,
284 const JavaParamRef
<jstring
>& origin
,
285 const JavaParamRef
<jstring
>& embedder
,
287 jboolean is_incognito
) {
288 GURL
embedder_url(ConvertJavaStringToUTF8(env
, embedder
));
289 SetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
,
291 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
292 value
, is_incognito
);
295 static void GetPushNotificationOrigins(JNIEnv
* env
,
296 const JavaParamRef
<jclass
>& clazz
,
297 const JavaParamRef
<jobject
>& list
) {
298 GetOrigins(env
, CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, list
, false);
301 static jint
GetPushNotificationSettingForOrigin(
303 const JavaParamRef
<jclass
>& clazz
,
304 const JavaParamRef
<jstring
>& origin
,
305 const JavaParamRef
<jstring
>& embedder
,
306 jboolean is_incognito
) {
307 return DesktopNotificationProfileUtil::GetContentSetting(
308 GetActiveUserProfile(is_incognito
),
309 GURL(ConvertJavaStringToUTF8(env
, origin
)));
312 static void SetPushNotificationSettingForOrigin(
314 const JavaParamRef
<jclass
>& clazz
,
315 const JavaParamRef
<jstring
>& origin
,
316 const JavaParamRef
<jstring
>& embedder
,
318 jboolean is_incognito
) {
319 // TODO(peter): Web Notification permission behaves differently from all other
320 // permission types. See https://crbug.com/416894.
321 Profile
* profile
= GetActiveUserProfile(is_incognito
);
322 GURL url
= GURL(ConvertJavaStringToUTF8(env
, origin
));
323 ContentSetting setting
= CONTENT_SETTING_DEFAULT
;
326 DesktopNotificationProfileUtil::ClearSetting(
327 profile
, ContentSettingsPattern::FromURLNoWildcard(url
));
330 DesktopNotificationProfileUtil::GrantPermission(profile
, url
);
331 setting
= CONTENT_SETTING_ALLOW
;
334 DesktopNotificationProfileUtil::DenyPermission(profile
, url
);
335 setting
= CONTENT_SETTING_BLOCK
;
340 WebSiteSettingsUmaUtil::LogPermissionChange(
341 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, setting
);
344 static void GetCameraOrigins(JNIEnv
* env
,
345 const JavaParamRef
<jclass
>& clazz
,
346 const JavaParamRef
<jobject
>& list
,
347 jboolean managedOnly
) {
348 GetOrigins(env
, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, list
, managedOnly
);
351 static void GetMicrophoneOrigins(JNIEnv
* env
,
352 const JavaParamRef
<jclass
>& clazz
,
353 const JavaParamRef
<jobject
>& list
,
354 jboolean managedOnly
) {
355 GetOrigins(env
, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, list
, managedOnly
);
358 static jint
GetMicrophoneSettingForOrigin(JNIEnv
* env
,
359 const JavaParamRef
<jclass
>& clazz
,
360 const JavaParamRef
<jstring
>& origin
,
361 const JavaParamRef
<jstring
>& embedder
,
362 jboolean is_incognito
) {
363 return GetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, origin
,
364 embedder
, is_incognito
);
367 static jint
GetCameraSettingForOrigin(JNIEnv
* env
,
368 const JavaParamRef
<jclass
>& clazz
,
369 const JavaParamRef
<jstring
>& origin
,
370 const JavaParamRef
<jstring
>& embedder
,
371 jboolean is_incognito
) {
372 return GetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
,
373 origin
, embedder
, is_incognito
);
376 static void SetMicrophoneSettingForOrigin(JNIEnv
* env
,
377 const JavaParamRef
<jclass
>& clazz
,
378 const JavaParamRef
<jstring
>& origin
,
379 const JavaParamRef
<jstring
>& embedder
,
381 jboolean is_incognito
) {
382 SetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, origin
,
383 ContentSettingsPattern::Wildcard(), value
, is_incognito
);
386 static void SetCameraSettingForOrigin(JNIEnv
* env
,
387 const JavaParamRef
<jclass
>& clazz
,
388 const JavaParamRef
<jstring
>& origin
,
389 const JavaParamRef
<jstring
>& embedder
,
391 jboolean is_incognito
) {
392 SetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, origin
,
393 ContentSettingsPattern::Wildcard(), value
, is_incognito
);
396 static scoped_refptr
<content_settings::CookieSettings
> GetCookieSettings() {
397 // A single cookie setting applies to both incognito and non-incognito.
398 Profile
* profile
= ProfileManager::GetActiveUserProfile();
399 return CookieSettingsFactory::GetForProfile(profile
);
402 static void GetCookieOrigins(JNIEnv
* env
,
403 const JavaParamRef
<jclass
>& clazz
,
404 const JavaParamRef
<jobject
>& list
,
405 jboolean managedOnly
) {
406 ContentSettingsForOneType all_settings
;
407 GetCookieSettings()->GetCookieSettings(&all_settings
);
408 const ContentSetting default_setting
=
409 GetCookieSettings()->GetDefaultCookieSetting(nullptr);
410 for (const auto& settings_it
: all_settings
) {
411 if (settings_it
.setting
== default_setting
)
414 HostContentSettingsMap::GetProviderTypeFromSource(settings_it
.source
) !=
415 HostContentSettingsMap::ProviderType::POLICY_PROVIDER
) {
418 const std::string
& origin
= settings_it
.primary_pattern
.ToString();
419 const std::string
& embedder
= settings_it
.secondary_pattern
.ToString();
420 ScopedJavaLocalRef
<jstring
> jorigin
= ConvertUTF8ToJavaString(env
, origin
);
421 ScopedJavaLocalRef
<jstring
> jembedder
;
422 if (embedder
!= origin
)
423 jembedder
= ConvertUTF8ToJavaString(env
, embedder
);
424 Java_WebsitePreferenceBridge_insertCookieInfoIntoList(env
, list
,
425 jorigin
.obj(), jembedder
.obj());
429 static jint
GetCookieSettingForOrigin(JNIEnv
* env
,
430 const JavaParamRef
<jclass
>& clazz
,
431 const JavaParamRef
<jstring
>& origin
,
432 const JavaParamRef
<jstring
>& embedder
,
433 jboolean is_incognito
) {
434 return GetSettingForOrigin(env
, CONTENT_SETTINGS_TYPE_COOKIES
, origin
,
438 static void SetCookieSettingForOrigin(JNIEnv
* env
,
439 const JavaParamRef
<jclass
>& clazz
,
440 const JavaParamRef
<jstring
>& origin
,
441 const JavaParamRef
<jstring
>& embedder
,
443 jboolean is_incognito
) {
444 GURL
url(ConvertJavaStringToUTF8(env
, origin
));
445 ContentSettingsPattern
primary_pattern(
446 ContentSettingsPattern::FromURLNoWildcard(url
));
447 ContentSettingsPattern
secondary_pattern(ContentSettingsPattern::Wildcard());
448 ContentSetting setting
= CONTENT_SETTING_DEFAULT
;
450 GetCookieSettings()->ResetCookieSetting(primary_pattern
, secondary_pattern
);
452 setting
= value
? CONTENT_SETTING_ALLOW
: CONTENT_SETTING_BLOCK
;
453 GetCookieSettings()->SetCookieSetting(primary_pattern
, secondary_pattern
,
456 WebSiteSettingsUmaUtil::LogPermissionChange(
457 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, setting
);
460 static jboolean
IsContentSettingsPatternValid(
462 const JavaParamRef
<jclass
>& clazz
,
463 const JavaParamRef
<jstring
>& pattern
) {
464 return ContentSettingsPattern::FromString(
465 ConvertJavaStringToUTF8(env
, pattern
)).IsValid();
468 static jboolean
UrlMatchesContentSettingsPattern(
470 const JavaParamRef
<jclass
>& clazz
,
471 const JavaParamRef
<jstring
>& jurl
,
472 const JavaParamRef
<jstring
>& jpattern
) {
473 ContentSettingsPattern pattern
= ContentSettingsPattern::FromString(
474 ConvertJavaStringToUTF8(env
, jpattern
));
475 return pattern
.Matches(GURL(ConvertJavaStringToUTF8(env
, jurl
)));
480 class SiteDataDeleteHelper
:
481 public base::RefCountedThreadSafe
<SiteDataDeleteHelper
>,
482 public CookiesTreeModel::Observer
{
484 SiteDataDeleteHelper(Profile
* profile
, const GURL
& domain
)
485 : profile_(profile
), domain_(domain
), ending_batch_processing_(false) {
489 AddRef(); // Balanced in TreeModelEndBatch.
491 content::StoragePartition
* storage_partition
=
492 content::BrowserContext::GetDefaultStoragePartition(profile_
);
493 content::IndexedDBContext
* indexed_db_context
=
494 storage_partition
->GetIndexedDBContext();
495 content::ServiceWorkerContext
* service_worker_context
=
496 storage_partition
->GetServiceWorkerContext();
497 content::CacheStorageContext
* cache_storage_context
=
498 storage_partition
->GetCacheStorageContext();
499 storage::FileSystemContext
* file_system_context
=
500 storage_partition
->GetFileSystemContext();
501 LocalDataContainer
* container
= new LocalDataContainer(
502 new BrowsingDataCookieHelper(profile_
->GetRequestContext()),
503 new BrowsingDataDatabaseHelper(profile_
),
504 new BrowsingDataLocalStorageHelper(profile_
),
506 new BrowsingDataAppCacheHelper(profile_
),
507 new BrowsingDataIndexedDBHelper(indexed_db_context
),
508 BrowsingDataFileSystemHelper::Create(file_system_context
),
509 BrowsingDataQuotaHelper::Create(profile_
),
510 BrowsingDataChannelIDHelper::Create(profile_
->GetRequestContext()),
511 new BrowsingDataServiceWorkerHelper(service_worker_context
),
512 new BrowsingDataCacheStorageHelper(cache_storage_context
),
515 cookies_tree_model_
.reset(new CookiesTreeModel(
516 container
, profile_
->GetExtensionSpecialStoragePolicy(), false));
517 cookies_tree_model_
->AddCookiesTreeObserver(this);
520 // TreeModelObserver:
521 void TreeNodesAdded(ui::TreeModel
* model
,
522 ui::TreeModelNode
* parent
,
524 int count
) override
{}
525 void TreeNodesRemoved(ui::TreeModel
* model
,
526 ui::TreeModelNode
* parent
,
528 int count
) override
{}
530 // CookiesTreeModel::Observer:
531 void TreeNodeChanged(ui::TreeModel
* model
, ui::TreeModelNode
* node
) override
{
534 void TreeModelBeginBatch(CookiesTreeModel
* model
) override
{
535 DCHECK(!ending_batch_processing_
); // Extra batch-start sent.
538 void TreeModelEndBatch(CookiesTreeModel
* model
) override
{
539 DCHECK(!ending_batch_processing_
); // Already in end-stage.
540 ending_batch_processing_
= true;
542 RecursivelyFindSiteAndDelete(cookies_tree_model_
->GetRoot());
544 // This will result in this class getting deleted.
548 void RecursivelyFindSiteAndDelete(CookieTreeNode
* node
) {
549 CookieTreeNode::DetailedInfo info
= node
->GetDetailedInfo();
550 for (int i
= node
->child_count(); i
> 0; --i
)
551 RecursivelyFindSiteAndDelete(node
->GetChild(i
- 1));
553 if (info
.node_type
== CookieTreeNode::DetailedInfo::TYPE_COOKIE
&&
555 domain_
.DomainIs(info
.cookie
->Domain().c_str()))
556 cookies_tree_model_
->DeleteCookieNode(node
);
560 friend class base::RefCountedThreadSafe
<SiteDataDeleteHelper
>;
562 ~SiteDataDeleteHelper() override
{}
566 // The domain we want to delete data for.
569 // Keeps track of when we're ready to close batch processing.
570 bool ending_batch_processing_
;
572 scoped_ptr
<CookiesTreeModel
> cookies_tree_model_
;
574 DISALLOW_COPY_AND_ASSIGN(SiteDataDeleteHelper
);
577 class StorageInfoFetcher
:
578 public base::RefCountedThreadSafe
<StorageInfoFetcher
> {
580 StorageInfoFetcher(storage::QuotaManager
* quota_manager
,
581 const JavaRef
<jobject
>& java_callback
)
582 : env_(base::android::AttachCurrentThread()),
583 quota_manager_(quota_manager
),
584 java_callback_(java_callback
) {
588 // QuotaManager must be called on IO thread, but java_callback must then be
589 // called back on UI thread.
590 BrowserThread::PostTask(
591 BrowserThread::IO
, FROM_HERE
,
592 base::Bind(&StorageInfoFetcher::GetUsageInfo
, this));
596 virtual ~StorageInfoFetcher() {}
599 friend class base::RefCountedThreadSafe
<StorageInfoFetcher
>;
601 void GetUsageInfo() {
602 // We will have no explicit owner as soon as we leave this method.
604 quota_manager_
->GetUsageInfo(
605 base::Bind(&StorageInfoFetcher::OnGetUsageInfo
, this));
608 void OnGetUsageInfo(const storage::UsageInfoEntries
& entries
) {
609 entries_
.insert(entries_
.begin(), entries
.begin(), entries
.end());
610 BrowserThread::PostTask(
611 BrowserThread::UI
, FROM_HERE
,
612 base::Bind(&StorageInfoFetcher::InvokeCallback
, this));
616 void InvokeCallback() {
617 ScopedJavaLocalRef
<jobject
> list
=
618 Java_WebsitePreferenceBridge_createStorageInfoList(env_
);
620 storage::UsageInfoEntries::const_iterator i
;
621 for (i
= entries_
.begin(); i
!= entries_
.end(); ++i
) {
622 if (i
->usage
<= 0) continue;
623 ScopedJavaLocalRef
<jstring
> host
=
624 ConvertUTF8ToJavaString(env_
, i
->host
);
626 Java_WebsitePreferenceBridge_insertStorageInfoIntoList(
627 env_
, list
.obj(), host
.obj(), i
->type
, i
->usage
);
629 Java_StorageInfoReadyCallback_onStorageInfoReady(
630 env_
, java_callback_
.obj(), list
.obj());
634 storage::QuotaManager
* quota_manager_
;
635 ScopedJavaGlobalRef
<jobject
> java_callback_
;
636 storage::UsageInfoEntries entries_
;
638 DISALLOW_COPY_AND_ASSIGN(StorageInfoFetcher
);
641 class StorageDataDeleter
:
642 public base::RefCountedThreadSafe
<StorageDataDeleter
> {
644 StorageDataDeleter(storage::QuotaManager
* quota_manager
,
645 const std::string
& host
,
646 storage::StorageType type
,
647 const JavaRef
<jobject
>& java_callback
)
648 : env_(base::android::AttachCurrentThread()),
649 quota_manager_(quota_manager
),
652 java_callback_(java_callback
) {
656 // QuotaManager must be called on IO thread, but java_callback must then be
657 // called back on UI thread. Grant ourself an extra reference to avoid
658 // being deleted after DeleteHostData will return.
660 BrowserThread::PostTask(
661 BrowserThread::IO
, FROM_HERE
,
662 base::Bind(&storage::QuotaManager::DeleteHostData
,
666 storage::QuotaClient::kAllClientsMask
,
667 base::Bind(&StorageDataDeleter::OnHostDataDeleted
,
672 virtual ~StorageDataDeleter() {}
675 friend class base::RefCountedThreadSafe
<StorageDataDeleter
>;
677 void OnHostDataDeleted(storage::QuotaStatusCode
) {
678 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
679 quota_manager_
->ResetUsageTracker(type_
);
680 BrowserThread::PostTask(
681 BrowserThread::UI
, FROM_HERE
,
682 base::Bind(&StorageDataDeleter::InvokeCallback
, this));
686 void InvokeCallback() {
687 Java_StorageInfoClearedCallback_onStorageInfoCleared(
688 env_
, java_callback_
.obj());
692 storage::QuotaManager
* quota_manager_
;
694 storage::StorageType type_
;
695 ScopedJavaGlobalRef
<jobject
> java_callback_
;
698 class LocalStorageInfoReadyCallback
{
700 LocalStorageInfoReadyCallback(
701 const ScopedJavaLocalRef
<jobject
>& java_callback
)
702 : env_(base::android::AttachCurrentThread()),
703 java_callback_(java_callback
) {
706 void OnLocalStorageModelInfoLoaded(
707 const std::list
<BrowsingDataLocalStorageHelper::LocalStorageInfo
>&
708 local_storage_info
) {
709 ScopedJavaLocalRef
<jobject
> map
=
710 Java_WebsitePreferenceBridge_createLocalStorageInfoMap(env_
);
712 std::list
<BrowsingDataLocalStorageHelper::LocalStorageInfo
>::const_iterator
714 for (i
= local_storage_info
.begin(); i
!= local_storage_info
.end(); ++i
) {
715 ScopedJavaLocalRef
<jstring
> full_origin
=
716 ConvertUTF8ToJavaString(env_
, i
->origin_url
.spec());
717 // Remove the trailing backslash so the origin is matched correctly in
718 // SingleWebsitePreferences.mergePermissionInfoForTopLevelOrigin.
719 std::string origin_str
= i
->origin_url
.GetOrigin().spec();
720 DCHECK(origin_str
[origin_str
.size() - 1] == '/');
721 origin_str
= origin_str
.substr(0, origin_str
.size() - 1);
722 ScopedJavaLocalRef
<jstring
> origin
=
723 ConvertUTF8ToJavaString(env_
, origin_str
);
724 Java_WebsitePreferenceBridge_insertLocalStorageInfoIntoMap(
725 env_
, map
.obj(), origin
.obj(), full_origin
.obj(), i
->size
);
728 Java_LocalStorageInfoReadyCallback_onLocalStorageInfoReady(
729 env_
, java_callback_
.obj(), map
.obj());
735 ScopedJavaGlobalRef
<jobject
> java_callback_
;
738 } // anonymous namespace
740 // TODO(jknotten): These methods should not be static. Instead we should
741 // expose a class to Java so that the fetch requests can be cancelled,
742 // and manage the lifetimes of the callback (and indirectly the helper
743 // by having a reference to it).
745 // The helper methods (StartFetching, DeleteLocalStorageFile, DeleteDatabase)
746 // are asynchronous. A "use after free" error is not possible because the
747 // helpers keep a reference to themselves for the duration of their tasks,
748 // which includes callback invocation.
750 static void FetchLocalStorageInfo(JNIEnv
* env
,
751 const JavaParamRef
<jclass
>& clazz
,
752 const JavaParamRef
<jobject
>& java_callback
) {
753 Profile
* profile
= ProfileManager::GetActiveUserProfile();
754 scoped_refptr
<BrowsingDataLocalStorageHelper
> local_storage_helper(
755 new BrowsingDataLocalStorageHelper(profile
));
756 // local_storage_callback will delete itself when it is run.
757 LocalStorageInfoReadyCallback
* local_storage_callback
=
758 new LocalStorageInfoReadyCallback(
759 ScopedJavaLocalRef
<jobject
>(env
, java_callback
));
760 local_storage_helper
->StartFetching(
761 base::Bind(&LocalStorageInfoReadyCallback::OnLocalStorageModelInfoLoaded
,
762 base::Unretained(local_storage_callback
)));
765 static void FetchStorageInfo(JNIEnv
* env
,
766 const JavaParamRef
<jclass
>& clazz
,
767 const JavaParamRef
<jobject
>& java_callback
) {
768 Profile
* profile
= ProfileManager::GetActiveUserProfile();
769 scoped_refptr
<StorageInfoFetcher
> storage_info_fetcher(new StorageInfoFetcher(
770 content::BrowserContext::GetDefaultStoragePartition(
771 profile
)->GetQuotaManager(),
772 ScopedJavaLocalRef
<jobject
>(env
, java_callback
)));
773 storage_info_fetcher
->Run();
776 static void ClearLocalStorageData(JNIEnv
* env
,
777 const JavaParamRef
<jclass
>& clazz
,
778 const JavaParamRef
<jstring
>& jorigin
) {
779 Profile
* profile
= ProfileManager::GetActiveUserProfile();
780 scoped_refptr
<BrowsingDataLocalStorageHelper
> local_storage_helper
=
781 new BrowsingDataLocalStorageHelper(profile
);
782 GURL origin_url
= GURL(ConvertJavaStringToUTF8(env
, jorigin
));
783 local_storage_helper
->DeleteOrigin(origin_url
);
786 static void ClearStorageData(JNIEnv
* env
,
787 const JavaParamRef
<jclass
>& clazz
,
788 const JavaParamRef
<jstring
>& jhost
,
790 const JavaParamRef
<jobject
>& java_callback
) {
791 Profile
* profile
= ProfileManager::GetActiveUserProfile();
792 std::string host
= ConvertJavaStringToUTF8(env
, jhost
);
793 scoped_refptr
<StorageDataDeleter
> storage_data_deleter(new StorageDataDeleter(
794 content::BrowserContext::GetDefaultStoragePartition(
795 profile
)->GetQuotaManager(),
797 static_cast<storage::StorageType
>(type
),
798 ScopedJavaLocalRef
<jobject
>(env
, java_callback
)));
799 storage_data_deleter
->Run();
802 static void ClearCookieData(JNIEnv
* env
,
803 const JavaParamRef
<jclass
>& clazz
,
804 const JavaParamRef
<jstring
>& jorigin
) {
805 Profile
* profile
= ProfileManager::GetActiveUserProfile();
806 GURL
url(ConvertJavaStringToUTF8(env
, jorigin
));
807 scoped_refptr
<SiteDataDeleteHelper
> site_data_deleter(
808 new SiteDataDeleteHelper(profile
, url
));
809 site_data_deleter
->Run();
812 // Register native methods
813 bool RegisterWebsitePreferenceBridge(JNIEnv
* env
) {
814 return RegisterNativesImpl(env
);