Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / extension_special_storage_policy.cc
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.
4
5 #include "chrome/browser/extensions/extension_special_storage_policy.h"
6
7 #include "base/bind.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/content_settings.h"
15 #include "chrome/common/content_settings_types.h"
16 #include "chrome/common/extensions/manifest_handlers/app_isolation_info.h"
17 #include "chrome/common/url_constants.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
24 using content::BrowserThread;
25 using extensions::APIPermission;
26 using extensions::Extension;
27 using quota::SpecialStoragePolicy;
28
29 ExtensionSpecialStoragePolicy::ExtensionSpecialStoragePolicy(
30     CookieSettings* cookie_settings)
31     : cookie_settings_(cookie_settings) {}
32
33 ExtensionSpecialStoragePolicy::~ExtensionSpecialStoragePolicy() {}
34
35 bool ExtensionSpecialStoragePolicy::IsStorageProtected(const GURL& origin) {
36   if (origin.SchemeIs(extensions::kExtensionScheme))
37     return true;
38   base::AutoLock locker(lock_);
39   return protected_apps_.Contains(origin);
40 }
41
42 bool ExtensionSpecialStoragePolicy::IsStorageUnlimited(const GURL& origin) {
43   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUnlimitedStorage))
44     return true;
45
46   if (origin.SchemeIs(content::kChromeDevToolsScheme) &&
47       origin.host() == chrome::kChromeUIDevToolsHost)
48     return true;
49
50   base::AutoLock locker(lock_);
51   return unlimited_extensions_.Contains(origin);
52 }
53
54 bool ExtensionSpecialStoragePolicy::IsStorageSessionOnly(const GURL& origin) {
55   if (cookie_settings_.get() == NULL)
56     return false;
57   return cookie_settings_->IsCookieSessionOnly(origin);
58 }
59
60 bool ExtensionSpecialStoragePolicy::CanQueryDiskSize(const GURL& origin) {
61   return installed_apps_.Contains(origin);
62 }
63
64 bool ExtensionSpecialStoragePolicy::HasSessionOnlyOrigins() {
65   if (cookie_settings_.get() == NULL)
66     return false;
67   if (cookie_settings_->GetDefaultCookieSetting(NULL) ==
68       CONTENT_SETTING_SESSION_ONLY)
69     return true;
70   ContentSettingsForOneType entries;
71   cookie_settings_->GetCookieSettings(&entries);
72   for (size_t i = 0; i < entries.size(); ++i) {
73     if (entries[i].setting == CONTENT_SETTING_SESSION_ONLY)
74       return true;
75   }
76   return false;
77 }
78
79 bool ExtensionSpecialStoragePolicy::IsFileHandler(
80     const std::string& extension_id) {
81   base::AutoLock locker(lock_);
82   return file_handler_extensions_.ContainsExtension(extension_id);
83 }
84
85 bool ExtensionSpecialStoragePolicy::HasIsolatedStorage(const GURL& origin) {
86   base::AutoLock locker(lock_);
87   return isolated_extensions_.Contains(origin);
88 }
89
90 bool ExtensionSpecialStoragePolicy::NeedsProtection(
91     const extensions::Extension* extension) {
92   return extension->is_hosted_app() && !extension->from_bookmark();
93 }
94
95 const extensions::ExtensionSet*
96 ExtensionSpecialStoragePolicy::ExtensionsProtectingOrigin(
97     const GURL& origin) {
98   base::AutoLock locker(lock_);
99   return protected_apps_.ExtensionsContaining(origin);
100 }
101
102 void ExtensionSpecialStoragePolicy::GrantRightsForExtension(
103     const extensions::Extension* extension) {
104   DCHECK(extension);
105   if (!(NeedsProtection(extension) ||
106         extension->HasAPIPermission(APIPermission::kUnlimitedStorage) ||
107         extension->HasAPIPermission(APIPermission::kFileBrowserHandler) ||
108         extensions::AppIsolationInfo::HasIsolatedStorage(extension) ||
109         extension->is_app())) {
110     return;
111   }
112
113   int change_flags = 0;
114   {
115     base::AutoLock locker(lock_);
116     if (NeedsProtection(extension) && protected_apps_.Add(extension))
117       change_flags |= SpecialStoragePolicy::STORAGE_PROTECTED;
118     // FIXME: Does GrantRightsForExtension imply |extension| is installed?
119     if (extension->is_app())
120       installed_apps_.Add(extension);
121
122     if (extension->HasAPIPermission(APIPermission::kUnlimitedStorage) &&
123         unlimited_extensions_.Add(extension))
124       change_flags |= SpecialStoragePolicy::STORAGE_UNLIMITED;
125
126     if (extension->HasAPIPermission(APIPermission::kFileBrowserHandler))
127       file_handler_extensions_.Add(extension);
128
129     if (extensions::AppIsolationInfo::HasIsolatedStorage(extension))
130       isolated_extensions_.Add(extension);
131   }
132
133   if (change_flags) {
134     NotifyGranted(Extension::GetBaseURLFromExtensionId(extension->id()),
135                   change_flags);
136   }
137 }
138
139 void ExtensionSpecialStoragePolicy::RevokeRightsForExtension(
140     const extensions::Extension* extension) {
141   DCHECK(extension);
142   if (!(NeedsProtection(extension) ||
143         extension->HasAPIPermission(APIPermission::kUnlimitedStorage) ||
144         extension->HasAPIPermission(APIPermission::kFileBrowserHandler) ||
145         extensions::AppIsolationInfo::HasIsolatedStorage(extension) ||
146         extension->is_app())) {
147     return;
148   }
149   int change_flags = 0;
150   {
151     base::AutoLock locker(lock_);
152     if (NeedsProtection(extension) && protected_apps_.Remove(extension))
153       change_flags |= SpecialStoragePolicy::STORAGE_PROTECTED;
154
155     if (extension->is_app())
156       installed_apps_.Remove(extension);
157
158     if (extension->HasAPIPermission(APIPermission::kUnlimitedStorage) &&
159         unlimited_extensions_.Remove(extension))
160       change_flags |= SpecialStoragePolicy::STORAGE_UNLIMITED;
161
162     if (extension->HasAPIPermission(APIPermission::kFileBrowserHandler))
163       file_handler_extensions_.Remove(extension);
164
165     if (extensions::AppIsolationInfo::HasIsolatedStorage(extension))
166       isolated_extensions_.Remove(extension);
167   }
168
169   if (change_flags) {
170     NotifyRevoked(Extension::GetBaseURLFromExtensionId(extension->id()),
171                   change_flags);
172   }
173 }
174
175 void ExtensionSpecialStoragePolicy::RevokeRightsForAllExtensions() {
176   {
177     base::AutoLock locker(lock_);
178     protected_apps_.Clear();
179     installed_apps_.Clear();
180     unlimited_extensions_.Clear();
181     file_handler_extensions_.Clear();
182     isolated_extensions_.Clear();
183   }
184
185   NotifyCleared();
186 }
187
188 void ExtensionSpecialStoragePolicy::NotifyGranted(
189     const GURL& origin,
190     int change_flags) {
191   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
192     BrowserThread::PostTask(
193         BrowserThread::IO, FROM_HERE,
194         base::Bind(&ExtensionSpecialStoragePolicy::NotifyGranted, this,
195                    origin, change_flags));
196     return;
197   }
198   SpecialStoragePolicy::NotifyGranted(origin, change_flags);
199 }
200
201 void ExtensionSpecialStoragePolicy::NotifyRevoked(
202     const GURL& origin,
203     int change_flags) {
204   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
205     BrowserThread::PostTask(
206         BrowserThread::IO, FROM_HERE,
207         base::Bind(&ExtensionSpecialStoragePolicy::NotifyRevoked, this,
208                    origin, change_flags));
209     return;
210   }
211   SpecialStoragePolicy::NotifyRevoked(origin, change_flags);
212 }
213
214 void ExtensionSpecialStoragePolicy::NotifyCleared() {
215   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
216     BrowserThread::PostTask(
217         BrowserThread::IO, FROM_HERE,
218         base::Bind(&ExtensionSpecialStoragePolicy::NotifyCleared, this));
219     return;
220   }
221   SpecialStoragePolicy::NotifyCleared();
222 }
223
224 //-----------------------------------------------------------------------------
225 // SpecialCollection helper class
226 //-----------------------------------------------------------------------------
227
228 ExtensionSpecialStoragePolicy::SpecialCollection::SpecialCollection() {}
229
230 ExtensionSpecialStoragePolicy::SpecialCollection::~SpecialCollection() {
231   STLDeleteValues(&cached_results_);
232 }
233
234 bool ExtensionSpecialStoragePolicy::SpecialCollection::Contains(
235     const GURL& origin) {
236   return !ExtensionsContaining(origin)->is_empty();
237 }
238
239 const extensions::ExtensionSet*
240 ExtensionSpecialStoragePolicy::SpecialCollection::ExtensionsContaining(
241     const GURL& origin) {
242   CachedResults::const_iterator found = cached_results_.find(origin);
243   if (found != cached_results_.end())
244     return found->second;
245
246   extensions::ExtensionSet* result = new extensions::ExtensionSet();
247   for (extensions::ExtensionSet::const_iterator iter = extensions_.begin();
248        iter != extensions_.end(); ++iter) {
249     if ((*iter)->OverlapsWithOrigin(origin))
250       result->Insert(*iter);
251   }
252   cached_results_[origin] = result;
253   return result;
254 }
255
256 bool ExtensionSpecialStoragePolicy::SpecialCollection::ContainsExtension(
257     const std::string& extension_id) {
258   return extensions_.Contains(extension_id);
259 }
260
261 bool ExtensionSpecialStoragePolicy::SpecialCollection::Add(
262     const extensions::Extension* extension) {
263   ClearCache();
264   return extensions_.Insert(extension);
265 }
266
267 bool ExtensionSpecialStoragePolicy::SpecialCollection::Remove(
268     const extensions::Extension* extension) {
269   ClearCache();
270   return extensions_.Remove(extension->id());
271 }
272
273 void ExtensionSpecialStoragePolicy::SpecialCollection::Clear() {
274   ClearCache();
275   extensions_.Clear();
276 }
277
278 void ExtensionSpecialStoragePolicy::SpecialCollection::ClearCache() {
279   STLDeleteValues(&cached_results_);
280   cached_results_.clear();
281 }