1 // Copyright (c) 2012 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/extensions/extension_special_storage_policy.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/stl_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/content_settings/cookie_settings.h"
13 #include "chrome/common/chrome_switches.h"
14 #include "chrome/common/extensions/manifest_handlers/app_isolation_info.h"
15 #include "chrome/common/url_constants.h"
16 #include "components/content_settings/core/common/content_settings.h"
17 #include "components/content_settings/core/common/content_settings_types.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/common/url_constants.h"
20 #include "extensions/common/constants.h"
21 #include "extensions/common/extension.h"
22 #include "extensions/common/extension_set.h"
23 #include "extensions/common/permissions/permissions_data.h"
25 using content::BrowserThread;
26 using extensions::APIPermission;
27 using extensions::Extension;
28 using storage::SpecialStoragePolicy;
30 ExtensionSpecialStoragePolicy::ExtensionSpecialStoragePolicy(
31 CookieSettings* cookie_settings)
32 : cookie_settings_(cookie_settings) {}
34 ExtensionSpecialStoragePolicy::~ExtensionSpecialStoragePolicy() {}
36 bool ExtensionSpecialStoragePolicy::IsStorageProtected(const GURL& origin) {
37 if (origin.SchemeIs(extensions::kExtensionScheme))
39 base::AutoLock locker(lock_);
40 return protected_apps_.Contains(origin);
43 bool ExtensionSpecialStoragePolicy::IsStorageUnlimited(const GURL& origin) {
44 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUnlimitedStorage))
47 if (origin.SchemeIs(content::kChromeDevToolsScheme) &&
48 origin.host() == chrome::kChromeUIDevToolsHost)
51 base::AutoLock locker(lock_);
52 return unlimited_extensions_.Contains(origin);
55 bool ExtensionSpecialStoragePolicy::IsStorageSessionOnly(const GURL& origin) {
56 if (cookie_settings_.get() == NULL)
58 return cookie_settings_->IsCookieSessionOnly(origin);
61 bool ExtensionSpecialStoragePolicy::CanQueryDiskSize(const GURL& origin) {
62 return installed_apps_.Contains(origin);
65 bool ExtensionSpecialStoragePolicy::HasSessionOnlyOrigins() {
66 if (cookie_settings_.get() == NULL)
68 if (cookie_settings_->GetDefaultCookieSetting(NULL) ==
69 CONTENT_SETTING_SESSION_ONLY)
71 ContentSettingsForOneType entries;
72 cookie_settings_->GetCookieSettings(&entries);
73 for (size_t i = 0; i < entries.size(); ++i) {
74 if (entries[i].setting == CONTENT_SETTING_SESSION_ONLY)
80 bool ExtensionSpecialStoragePolicy::IsFileHandler(
81 const std::string& extension_id) {
82 base::AutoLock locker(lock_);
83 return file_handler_extensions_.ContainsExtension(extension_id);
86 bool ExtensionSpecialStoragePolicy::HasIsolatedStorage(const GURL& origin) {
87 base::AutoLock locker(lock_);
88 return isolated_extensions_.Contains(origin);
91 bool ExtensionSpecialStoragePolicy::NeedsProtection(
92 const extensions::Extension* extension) {
93 return extension->is_hosted_app() && !extension->from_bookmark();
96 const extensions::ExtensionSet*
97 ExtensionSpecialStoragePolicy::ExtensionsProtectingOrigin(
99 base::AutoLock locker(lock_);
100 return protected_apps_.ExtensionsContaining(origin);
103 void ExtensionSpecialStoragePolicy::GrantRightsForExtension(
104 const extensions::Extension* extension) {
106 if (!(NeedsProtection(extension) ||
107 extension->permissions_data()->HasAPIPermission(
108 APIPermission::kUnlimitedStorage) ||
109 extension->permissions_data()->HasAPIPermission(
110 APIPermission::kFileBrowserHandler) ||
111 extensions::AppIsolationInfo::HasIsolatedStorage(extension) ||
112 extension->is_app())) {
116 int change_flags = 0;
118 base::AutoLock locker(lock_);
119 if (NeedsProtection(extension) && protected_apps_.Add(extension))
120 change_flags |= SpecialStoragePolicy::STORAGE_PROTECTED;
121 // FIXME: Does GrantRightsForExtension imply |extension| is installed?
122 if (extension->is_app())
123 installed_apps_.Add(extension);
125 if (extension->permissions_data()->HasAPIPermission(
126 APIPermission::kUnlimitedStorage) &&
127 unlimited_extensions_.Add(extension))
128 change_flags |= SpecialStoragePolicy::STORAGE_UNLIMITED;
130 if (extension->permissions_data()->HasAPIPermission(
131 APIPermission::kFileBrowserHandler))
132 file_handler_extensions_.Add(extension);
134 if (extensions::AppIsolationInfo::HasIsolatedStorage(extension))
135 isolated_extensions_.Add(extension);
139 NotifyGranted(Extension::GetBaseURLFromExtensionId(extension->id()),
144 void ExtensionSpecialStoragePolicy::RevokeRightsForExtension(
145 const extensions::Extension* extension) {
147 if (!(NeedsProtection(extension) ||
148 extension->permissions_data()->HasAPIPermission(
149 APIPermission::kUnlimitedStorage) ||
150 extension->permissions_data()->HasAPIPermission(
151 APIPermission::kFileBrowserHandler) ||
152 extensions::AppIsolationInfo::HasIsolatedStorage(extension) ||
153 extension->is_app())) {
156 int change_flags = 0;
158 base::AutoLock locker(lock_);
159 if (NeedsProtection(extension) && protected_apps_.Remove(extension))
160 change_flags |= SpecialStoragePolicy::STORAGE_PROTECTED;
162 if (extension->is_app())
163 installed_apps_.Remove(extension);
165 if (extension->permissions_data()->HasAPIPermission(
166 APIPermission::kUnlimitedStorage) &&
167 unlimited_extensions_.Remove(extension))
168 change_flags |= SpecialStoragePolicy::STORAGE_UNLIMITED;
170 if (extension->permissions_data()->HasAPIPermission(
171 APIPermission::kFileBrowserHandler))
172 file_handler_extensions_.Remove(extension);
174 if (extensions::AppIsolationInfo::HasIsolatedStorage(extension))
175 isolated_extensions_.Remove(extension);
179 NotifyRevoked(Extension::GetBaseURLFromExtensionId(extension->id()),
184 void ExtensionSpecialStoragePolicy::RevokeRightsForAllExtensions() {
186 base::AutoLock locker(lock_);
187 protected_apps_.Clear();
188 installed_apps_.Clear();
189 unlimited_extensions_.Clear();
190 file_handler_extensions_.Clear();
191 isolated_extensions_.Clear();
197 void ExtensionSpecialStoragePolicy::NotifyGranted(
200 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
201 BrowserThread::PostTask(
202 BrowserThread::IO, FROM_HERE,
203 base::Bind(&ExtensionSpecialStoragePolicy::NotifyGranted, this,
204 origin, change_flags));
207 SpecialStoragePolicy::NotifyGranted(origin, change_flags);
210 void ExtensionSpecialStoragePolicy::NotifyRevoked(
213 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
214 BrowserThread::PostTask(
215 BrowserThread::IO, FROM_HERE,
216 base::Bind(&ExtensionSpecialStoragePolicy::NotifyRevoked, this,
217 origin, change_flags));
220 SpecialStoragePolicy::NotifyRevoked(origin, change_flags);
223 void ExtensionSpecialStoragePolicy::NotifyCleared() {
224 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
225 BrowserThread::PostTask(
226 BrowserThread::IO, FROM_HERE,
227 base::Bind(&ExtensionSpecialStoragePolicy::NotifyCleared, this));
230 SpecialStoragePolicy::NotifyCleared();
233 //-----------------------------------------------------------------------------
234 // SpecialCollection helper class
235 //-----------------------------------------------------------------------------
237 ExtensionSpecialStoragePolicy::SpecialCollection::SpecialCollection() {}
239 ExtensionSpecialStoragePolicy::SpecialCollection::~SpecialCollection() {
240 STLDeleteValues(&cached_results_);
243 bool ExtensionSpecialStoragePolicy::SpecialCollection::Contains(
244 const GURL& origin) {
245 return !ExtensionsContaining(origin)->is_empty();
248 const extensions::ExtensionSet*
249 ExtensionSpecialStoragePolicy::SpecialCollection::ExtensionsContaining(
250 const GURL& origin) {
251 CachedResults::const_iterator found = cached_results_.find(origin);
252 if (found != cached_results_.end())
253 return found->second;
255 extensions::ExtensionSet* result = new extensions::ExtensionSet();
256 for (extensions::ExtensionSet::const_iterator iter = extensions_.begin();
257 iter != extensions_.end(); ++iter) {
258 if ((*iter)->OverlapsWithOrigin(origin))
259 result->Insert(*iter);
261 cached_results_[origin] = result;
265 bool ExtensionSpecialStoragePolicy::SpecialCollection::ContainsExtension(
266 const std::string& extension_id) {
267 return extensions_.Contains(extension_id);
270 bool ExtensionSpecialStoragePolicy::SpecialCollection::Add(
271 const extensions::Extension* extension) {
273 return extensions_.Insert(extension);
276 bool ExtensionSpecialStoragePolicy::SpecialCollection::Remove(
277 const extensions::Extension* extension) {
279 return extensions_.Remove(extension->id());
282 void ExtensionSpecialStoragePolicy::SpecialCollection::Clear() {
287 void ExtensionSpecialStoragePolicy::SpecialCollection::ClearCache() {
288 STLDeleteValues(&cached_results_);
289 cached_results_.clear();