1 // Copyright 2021 Samsung Electronics. 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 "wrt_special_storage_policy.h"
7 #include "base/containers/contains.h"
8 #include "base/logging.h"
9 #include "content/public/browser/browser_task_traits.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "url/origin.h"
13 #if ENABLE_CHROME_EXTENSIONS
14 #include "extensions/common/constants.h"
15 #include "extensions/common/extension.h"
16 #include "extensions/common/extension_set.h"
17 #include "extensions/common/manifest_handlers/content_capabilities_handler.h"
18 #include "extensions/common/permissions/api_permission.h"
19 #include "extensions/common/permissions/permissions_data.h"
22 using content::BrowserThread;
24 #if ENABLE_CHROME_EXTENSIONS
25 using extensions::APIPermission;
26 using extensions::Extension;
31 WRTSpecialStoragePolicy::WRTSpecialStoragePolicy() {}
33 WRTSpecialStoragePolicy::~WRTSpecialStoragePolicy() {
34 quota_exceeded_callback_.Reset();
37 bool WRTSpecialStoragePolicy::IsStorageUnlimited(const GURL& origin) {
38 base::AutoLock locker(lock_);
39 if (base::Contains(unlimited_, origin))
40 return unlimited_.find(origin)->second;
42 #if ENABLE_CHROME_EXTENSIONS
43 if (unlimited_extensions_.Contains(origin) ||
44 content_capabilities_unlimited_extensions_.GrantsCapabilitiesTo(origin)) {
52 void WRTSpecialStoragePolicy::RequestUnlimitedStoragePolicy(
55 QuotaExceededReplyCallback callback) {
57 base::AutoLock locker(lock_);
58 if (base::Contains(unlimited_, origin) ||
59 quota_exceeded_callback_.is_null()) {
60 LOG(INFO) << __func__ << " unlimited.";
61 std::move(callback).Run(false /* policy_changed */);
65 LOG(INFO) << __func__ << " quota exceeded callback run.";
66 quota_exceeded_callback_.Run(origin, quota);
67 quota_exceeded_reply_callback_ = std::move(callback);
70 void WRTSpecialStoragePolicy::SetQuotaExceededCallback(
71 QuotaExceededCallback callback) {
72 quota_exceeded_callback_ = callback;
75 void WRTSpecialStoragePolicy::SetUnlimitedStoragePolicy(const GURL& origin,
77 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
78 content::GetIOThreadTaskRunner({})->PostTask(
80 base::BindOnce(&WRTSpecialStoragePolicy::SetUnlimitedStoragePolicy,
81 base::Unretained(this), origin, allow));
85 bool policy_changed = IsStorageUnlimited(origin) != allow;
86 LOG(INFO) << __func__ << "() allow:" << allow
87 << ", changed:" << policy_changed;
89 base::AutoLock locker(lock_);
90 unlimited_[origin] = allow;
94 NotifyGranted(url::Origin::Create(origin),
95 SpecialStoragePolicy::STORAGE_UNLIMITED);
97 NotifyRevoked(url::Origin::Create(origin),
98 SpecialStoragePolicy::STORAGE_UNLIMITED);
101 if (!quota_exceeded_reply_callback_.is_null()) {
102 LOG(INFO) << __func__ << " quota exceeded reply callback run.";
103 std::move(quota_exceeded_reply_callback_).Run(policy_changed);
107 #if ENABLE_CHROME_EXTENSIONS
108 void WRTSpecialStoragePolicy::GrantRightsForExtension(
109 const extensions::Extension* extension) {
110 base::AutoLock locker(lock_);
113 int change_flags = 0;
114 if (extensions::ContentCapabilitiesInfo::Get(extension).permissions.count(
115 extensions::mojom::APIPermissionID::kUnlimitedStorage) > 0) {
116 content_capabilities_unlimited_extensions_.Add(extension);
117 change_flags |= SpecialStoragePolicy::STORAGE_UNLIMITED;
120 if (extension->permissions_data()->HasAPIPermission(
121 extensions::mojom::APIPermissionID::kUnlimitedStorage) &&
122 unlimited_extensions_.Add(extension)) {
123 change_flags |= SpecialStoragePolicy::STORAGE_UNLIMITED;
127 const GURL origin = Extension::GetBaseURLFromExtensionId(extension->id());
128 NotifyGranted(url::Origin::Create(origin), change_flags);
132 void WRTSpecialStoragePolicy::RevokeRightsForExtension(
133 const extensions::Extension* extension) {
134 base::AutoLock locker(lock_);
137 int change_flags = 0;
138 if (extensions::ContentCapabilitiesInfo::Get(extension).permissions.count(
139 extensions::mojom::APIPermissionID::kUnlimitedStorage) > 0) {
140 content_capabilities_unlimited_extensions_.Remove(extension);
141 change_flags |= SpecialStoragePolicy::STORAGE_UNLIMITED;
144 if (extension->permissions_data()->HasAPIPermission(
145 extensions::mojom::APIPermissionID::kUnlimitedStorage) &&
146 unlimited_extensions_.Remove(extension)) {
147 change_flags |= SpecialStoragePolicy::STORAGE_UNLIMITED;
151 const GURL origin = Extension::GetBaseURLFromExtensionId(extension->id());
152 NotifyRevoked(url::Origin::Create(origin), change_flags);
156 //-----------------------------------------------------------------------------
157 // SpecialCollection helper class
158 //-----------------------------------------------------------------------------
160 WRTSpecialStoragePolicy::SpecialCollection::SpecialCollection() {}
162 WRTSpecialStoragePolicy::SpecialCollection::~SpecialCollection() {}
164 bool WRTSpecialStoragePolicy::SpecialCollection::Contains(const GURL& origin) {
165 return !ExtensionsContaining(origin)->is_empty();
168 bool WRTSpecialStoragePolicy::SpecialCollection::GrantsCapabilitiesTo(
169 const GURL& origin) {
170 for (const auto& extension : extensions_) {
171 if (extensions::ContentCapabilitiesInfo::Get(extension.get())
172 .url_patterns.MatchesURL(origin)) {
179 const extensions::ExtensionSet*
180 WRTSpecialStoragePolicy::SpecialCollection::ExtensionsContaining(
181 const GURL& origin) {
182 std::unique_ptr<extensions::ExtensionSet>& result = cached_results_[origin];
186 result = std::make_unique<extensions::ExtensionSet>();
187 for (auto& extension : extensions_) {
188 if (extension->OverlapsWithOrigin(origin))
189 result->Insert(extension);
195 bool WRTSpecialStoragePolicy::SpecialCollection::ContainsExtension(
196 const std::string& extension_id) {
197 return extensions_.Contains(extension_id);
200 bool WRTSpecialStoragePolicy::SpecialCollection::Add(
201 const extensions::Extension* extension) {
203 return extensions_.Insert(extension);
206 bool WRTSpecialStoragePolicy::SpecialCollection::Remove(
207 const extensions::Extension* extension) {
209 return extensions_.Remove(extension->id());
212 void WRTSpecialStoragePolicy::SpecialCollection::Clear() {
217 void WRTSpecialStoragePolicy::SpecialCollection::ClearCache() {
218 cached_results_.clear();
220 #endif // ENABLE_CHROME_EXTENSIONS