- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / extension_special_storage_policy_unittest.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 "base/message_loop/message_loop.h"
6 #include "base/values.h"
7 #include "chrome/browser/content_settings/cookie_settings.h"
8 #include "chrome/browser/extensions/extension_special_storage_policy.h"
9 #include "chrome/common/content_settings.h"
10 #include "chrome/common/content_settings_types.h"
11 #include "chrome/common/extensions/extension.h"
12 #include "chrome/test/base/testing_profile.h"
13 #include "content/public/test/test_browser_thread.h"
14 #include "extensions/common/manifest.h"
15 #include "extensions/common/manifest_constants.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 using content::BrowserThread;
19 using extensions::Extension;
20 using extensions::Manifest;
21 using quota::SpecialStoragePolicy;
22
23 typedef SpecialStoragePolicy::StoragePolicy StoragePolicy;
24
25 namespace keys = extensions::manifest_keys;
26
27 class ExtensionSpecialStoragePolicyTest : public testing::Test {
28  protected:
29   class PolicyChangeObserver : public SpecialStoragePolicy::Observer {
30    public:
31     PolicyChangeObserver()
32         : expected_type_(NOTIFICATION_TYPE_NONE),
33           expected_change_flags_(0) {
34     }
35
36     virtual void OnGranted(const GURL& origin,
37                            int change_flags) OVERRIDE {
38       EXPECT_EQ(expected_type_, NOTIFICATION_TYPE_GRANT);
39       EXPECT_EQ(expected_origin_, origin);
40       EXPECT_EQ(expected_change_flags_, change_flags);
41       expected_type_ = NOTIFICATION_TYPE_NONE;
42     }
43
44     virtual void OnRevoked(const GURL& origin,
45                            int change_flags) OVERRIDE {
46       EXPECT_EQ(expected_type_, NOTIFICATION_TYPE_REVOKE);
47       EXPECT_EQ(expected_origin_, origin);
48       EXPECT_EQ(expected_change_flags_, change_flags);
49       expected_type_ = NOTIFICATION_TYPE_NONE;
50     }
51
52     virtual void OnCleared() OVERRIDE {
53       EXPECT_EQ(expected_type_, NOTIFICATION_TYPE_CLEAR);
54       expected_type_ = NOTIFICATION_TYPE_NONE;
55     }
56
57     void ExpectGrant(const std::string& extension_id,
58                      int change_flags) {
59       expected_type_ = NOTIFICATION_TYPE_GRANT;
60       expected_origin_ = Extension::GetBaseURLFromExtensionId(extension_id);
61       expected_change_flags_ = change_flags;
62     }
63
64     void ExpectRevoke(const std::string& extension_id,
65                       int change_flags) {
66       expected_type_ = NOTIFICATION_TYPE_REVOKE;
67       expected_origin_ = Extension::GetBaseURLFromExtensionId(extension_id);
68       expected_change_flags_ = change_flags;
69     }
70
71     void ExpectClear() {
72       expected_type_ = NOTIFICATION_TYPE_CLEAR;
73     }
74
75     bool IsCompleted() {
76       return expected_type_ == NOTIFICATION_TYPE_NONE;
77     }
78
79    private:
80     enum {
81       NOTIFICATION_TYPE_NONE,
82       NOTIFICATION_TYPE_GRANT,
83       NOTIFICATION_TYPE_REVOKE,
84       NOTIFICATION_TYPE_CLEAR,
85     } expected_type_;
86
87     GURL expected_origin_;
88     int expected_change_flags_;
89
90     DISALLOW_COPY_AND_ASSIGN(PolicyChangeObserver);
91   };
92
93   virtual void SetUp() OVERRIDE {
94     policy_ = new ExtensionSpecialStoragePolicy(NULL);
95   }
96
97   scoped_refptr<Extension> CreateProtectedApp() {
98 #if defined(OS_WIN)
99     base::FilePath path(FILE_PATH_LITERAL("c:\\foo"));
100 #elif defined(OS_POSIX)
101     base::FilePath path(FILE_PATH_LITERAL("/foo"));
102 #endif
103     DictionaryValue manifest;
104     manifest.SetString(keys::kName, "Protected");
105     manifest.SetString(keys::kVersion, "1");
106     manifest.SetString(keys::kLaunchWebURL, "http://explicit/protected/start");
107     base::ListValue* list = new base::ListValue();
108     list->Append(new base::StringValue("http://explicit/protected"));
109     list->Append(new base::StringValue("*://*.wildcards/protected"));
110     manifest.Set(keys::kWebURLs, list);
111     std::string error;
112     scoped_refptr<Extension> protected_app = Extension::Create(
113         path, Manifest::INVALID_LOCATION, manifest,
114         Extension::NO_FLAGS, &error);
115     EXPECT_TRUE(protected_app.get()) << error;
116     return protected_app;
117   }
118
119   scoped_refptr<Extension> CreateUnlimitedApp() {
120 #if defined(OS_WIN)
121     base::FilePath path(FILE_PATH_LITERAL("c:\\bar"));
122 #elif defined(OS_POSIX)
123     base::FilePath path(FILE_PATH_LITERAL("/bar"));
124 #endif
125     DictionaryValue manifest;
126     manifest.SetString(keys::kName, "Unlimited");
127     manifest.SetString(keys::kVersion, "1");
128     manifest.SetString(keys::kLaunchWebURL, "http://explicit/unlimited/start");
129     base::ListValue* list = new base::ListValue();
130     list->Append(new base::StringValue("unlimitedStorage"));
131     manifest.Set(keys::kPermissions, list);
132     list = new base::ListValue();
133     list->Append(new base::StringValue("http://explicit/unlimited"));
134     list->Append(new base::StringValue("*://*.wildcards/unlimited"));
135     manifest.Set(keys::kWebURLs, list);
136     std::string error;
137     scoped_refptr<Extension> unlimited_app = Extension::Create(
138         path, Manifest::INVALID_LOCATION, manifest,
139         Extension::NO_FLAGS, &error);
140     EXPECT_TRUE(unlimited_app.get()) << error;
141     return unlimited_app;
142   }
143
144   scoped_refptr<Extension> CreateRegularApp() {
145 #if defined(OS_WIN)
146     base::FilePath path(FILE_PATH_LITERAL("c:\\app"));
147 #elif defined(OS_POSIX)
148     base::FilePath path(FILE_PATH_LITERAL("/app"));
149 #endif
150     DictionaryValue manifest;
151     manifest.SetString(keys::kName, "App");
152     manifest.SetString(keys::kVersion, "1");
153     manifest.SetString(keys::kPlatformAppBackgroundPage, "background.html");
154     std::string error;
155     scoped_refptr<Extension> app = Extension::Create(
156         path, Manifest::INVALID_LOCATION, manifest,
157         Extension::NO_FLAGS, &error);
158     EXPECT_TRUE(app.get()) << error;
159     return app;
160   }
161
162   // Verifies that the set of extensions protecting |url| is *exactly* equal to
163   // |expected_extensions|. Pass in an empty set to verify that an origin is not
164   // protected.
165   void ExpectProtectedBy(const ExtensionSet& expected_extensions,
166                          const GURL& url) {
167     const ExtensionSet* extensions = policy_->ExtensionsProtectingOrigin(url);
168     EXPECT_EQ(expected_extensions.size(), extensions->size());
169     for (ExtensionSet::const_iterator it = expected_extensions.begin();
170          it != expected_extensions.end(); ++it) {
171       EXPECT_TRUE(extensions->Contains((*it)->id()))
172           << "Origin " << url << "not protected by extension ID "
173           << (*it)->id();
174     }
175   }
176
177   scoped_refptr<ExtensionSpecialStoragePolicy> policy_;
178 };
179
180 TEST_F(ExtensionSpecialStoragePolicyTest, EmptyPolicy) {
181   const GURL kHttpUrl("http://foo");
182   const GURL kExtensionUrl("chrome-extension://bar");
183   scoped_refptr<Extension> app(CreateRegularApp());
184
185   EXPECT_FALSE(policy_->IsStorageUnlimited(kHttpUrl));
186   EXPECT_FALSE(policy_->IsStorageUnlimited(kHttpUrl));  // test cached result
187   EXPECT_FALSE(policy_->IsStorageUnlimited(kExtensionUrl));
188   EXPECT_FALSE(policy_->IsStorageUnlimited(app->url()));
189   ExtensionSet empty_set;
190   ExpectProtectedBy(empty_set, kHttpUrl);
191
192   // This one is just based on the scheme.
193   EXPECT_TRUE(policy_->IsStorageProtected(kExtensionUrl));
194   EXPECT_TRUE(policy_->IsStorageProtected(app->url()));
195 }
196
197 TEST_F(ExtensionSpecialStoragePolicyTest, AppWithProtectedStorage) {
198   scoped_refptr<Extension> extension(CreateProtectedApp());
199   policy_->GrantRightsForExtension(extension.get());
200   ExtensionSet protecting_extensions;
201   protecting_extensions.Insert(extension);
202   ExtensionSet empty_set;
203
204   EXPECT_FALSE(policy_->IsStorageUnlimited(extension->url()));
205   EXPECT_FALSE(policy_->IsStorageUnlimited(GURL("http://explicit/")));
206   ExpectProtectedBy(protecting_extensions, GURL("http://explicit/"));
207   ExpectProtectedBy(protecting_extensions, GURL("http://explicit:6000/"));
208   ExpectProtectedBy(protecting_extensions, GURL("http://foo.wildcards/"));
209   ExpectProtectedBy(protecting_extensions, GURL("https://bar.wildcards/"));
210   ExpectProtectedBy(empty_set, GURL("http://not_listed/"));
211
212   policy_->RevokeRightsForExtension(extension.get());
213   ExpectProtectedBy(empty_set, GURL("http://explicit/"));
214   ExpectProtectedBy(empty_set, GURL("http://foo.wildcards/"));
215   ExpectProtectedBy(empty_set, GURL("https://bar.wildcards/"));
216 }
217
218 TEST_F(ExtensionSpecialStoragePolicyTest, AppWithUnlimitedStorage) {
219   scoped_refptr<Extension> extension(CreateUnlimitedApp());
220   policy_->GrantRightsForExtension(extension.get());
221   ExtensionSet protecting_extensions;
222   protecting_extensions.Insert(extension);
223   ExtensionSet empty_set;
224
225   ExpectProtectedBy(protecting_extensions, GURL("http://explicit/"));
226   ExpectProtectedBy(protecting_extensions, GURL("http://explicit:6000/"));
227   ExpectProtectedBy(protecting_extensions, GURL("https://foo.wildcards/"));
228   ExpectProtectedBy(protecting_extensions, GURL("https://foo.wildcards/"));
229   ExpectProtectedBy(protecting_extensions, GURL("http://bar.wildcards/"));
230   ExpectProtectedBy(empty_set, GURL("http://not_listed/"));
231   EXPECT_TRUE(policy_->IsStorageUnlimited(extension->url()));
232   EXPECT_TRUE(policy_->IsStorageUnlimited(GURL("http://explicit/")));
233   EXPECT_TRUE(policy_->IsStorageUnlimited(GURL("http://explicit:6000/")));
234   EXPECT_TRUE(policy_->IsStorageUnlimited(GURL("https://foo.wildcards/")));
235   EXPECT_TRUE(policy_->IsStorageUnlimited(GURL("https://bar.wildcards/")));
236   EXPECT_FALSE(policy_->IsStorageUnlimited(GURL("http://not_listed/")));
237
238   policy_->RevokeRightsForExtension(extension.get());
239   ExpectProtectedBy(empty_set, GURL("http://explicit/"));
240   ExpectProtectedBy(empty_set, GURL("https://foo.wildcards/"));
241   ExpectProtectedBy(empty_set, GURL("https://foo.wildcards/"));
242   ExpectProtectedBy(empty_set, GURL("http://bar.wildcards/"));
243   EXPECT_FALSE(policy_->IsStorageUnlimited(GURL("http://explicit/")));
244   EXPECT_FALSE(policy_->IsStorageUnlimited(GURL("https://foo.wildcards/")));
245   EXPECT_FALSE(policy_->IsStorageUnlimited(GURL("https://bar.wildcards/")));
246 }
247
248 TEST_F(ExtensionSpecialStoragePolicyTest, CanQueryDiskSize) {
249   const GURL kHttpUrl("http://foo");
250   const GURL kExtensionUrl("chrome-extension://bar");
251   scoped_refptr<Extension> regular_app(CreateRegularApp());
252   scoped_refptr<Extension> protected_app(CreateProtectedApp());
253   scoped_refptr<Extension> unlimited_app(CreateUnlimitedApp());
254   policy_->GrantRightsForExtension(regular_app.get());
255   policy_->GrantRightsForExtension(protected_app.get());
256   policy_->GrantRightsForExtension(unlimited_app.get());
257
258   EXPECT_FALSE(policy_->CanQueryDiskSize(kHttpUrl));
259   EXPECT_FALSE(policy_->CanQueryDiskSize(kExtensionUrl));
260   EXPECT_TRUE(policy_->CanQueryDiskSize(regular_app->url()));
261   EXPECT_TRUE(policy_->CanQueryDiskSize(protected_app->url()));
262   EXPECT_TRUE(policy_->CanQueryDiskSize(unlimited_app->url()));
263 }
264
265 TEST_F(ExtensionSpecialStoragePolicyTest, HasIsolatedStorage) {
266   const GURL kHttpUrl("http://foo");
267   const GURL kExtensionUrl("chrome-extension://bar");
268   scoped_refptr<Extension> app(CreateRegularApp());
269   policy_->GrantRightsForExtension(app.get());
270
271   EXPECT_FALSE(policy_->HasIsolatedStorage(kHttpUrl));
272   EXPECT_FALSE(policy_->HasIsolatedStorage(kExtensionUrl));
273   EXPECT_TRUE(policy_->HasIsolatedStorage(app->url()));
274 }
275
276 TEST_F(ExtensionSpecialStoragePolicyTest, OverlappingApps) {
277   scoped_refptr<Extension> protected_app(CreateProtectedApp());
278   scoped_refptr<Extension> unlimited_app(CreateUnlimitedApp());
279   policy_->GrantRightsForExtension(protected_app.get());
280   policy_->GrantRightsForExtension(unlimited_app.get());
281   ExtensionSet protecting_extensions;
282   ExtensionSet empty_set;
283   protecting_extensions.Insert(protected_app);
284   protecting_extensions.Insert(unlimited_app);
285
286   ExpectProtectedBy(protecting_extensions, GURL("http://explicit/"));
287   ExpectProtectedBy(protecting_extensions, GURL("http://explicit:6000/"));
288   ExpectProtectedBy(protecting_extensions, GURL("https://foo.wildcards/"));
289   ExpectProtectedBy(protecting_extensions, GURL("https://foo.wildcards/"));
290   ExpectProtectedBy(protecting_extensions, GURL("http://bar.wildcards/"));
291   ExpectProtectedBy(empty_set, GURL("http://not_listed/"));
292   EXPECT_TRUE(policy_->IsStorageUnlimited(GURL("http://explicit/")));
293   EXPECT_TRUE(policy_->IsStorageUnlimited(GURL("http://explicit:6000/")));
294   EXPECT_TRUE(policy_->IsStorageUnlimited(GURL("https://foo.wildcards/")));
295   EXPECT_TRUE(policy_->IsStorageUnlimited(GURL("https://bar.wildcards/")));
296   EXPECT_FALSE(policy_->IsStorageUnlimited(GURL("http://not_listed/")));
297
298   policy_->RevokeRightsForExtension(unlimited_app.get());
299   protecting_extensions.Remove(unlimited_app->id());
300   EXPECT_FALSE(policy_->IsStorageUnlimited(GURL("http://explicit/")));
301   EXPECT_FALSE(policy_->IsStorageUnlimited(GURL("https://foo.wildcards/")));
302   EXPECT_FALSE(policy_->IsStorageUnlimited(GURL("https://bar.wildcards/")));
303   ExpectProtectedBy(protecting_extensions, GURL("http://explicit/"));
304   ExpectProtectedBy(protecting_extensions, GURL("http://foo.wildcards/"));
305   ExpectProtectedBy(protecting_extensions, GURL("https://bar.wildcards/"));
306
307   policy_->RevokeRightsForExtension(protected_app.get());
308   ExpectProtectedBy(empty_set, GURL("http://explicit/"));
309   ExpectProtectedBy(empty_set, GURL("http://foo.wildcards/"));
310   ExpectProtectedBy(empty_set, GURL("https://bar.wildcards/"));
311 }
312
313 TEST_F(ExtensionSpecialStoragePolicyTest, HasSessionOnlyOrigins) {
314   base::MessageLoop message_loop;
315   content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
316
317   TestingProfile profile;
318   CookieSettings* cookie_settings =
319       CookieSettings::Factory::GetForProfile(&profile).get();
320   policy_ = new ExtensionSpecialStoragePolicy(cookie_settings);
321
322   EXPECT_FALSE(policy_->HasSessionOnlyOrigins());
323
324   // The default setting can be session-only.
325   cookie_settings->SetDefaultCookieSetting(CONTENT_SETTING_SESSION_ONLY);
326   EXPECT_TRUE(policy_->HasSessionOnlyOrigins());
327
328   cookie_settings->SetDefaultCookieSetting(CONTENT_SETTING_ALLOW);
329   EXPECT_FALSE(policy_->HasSessionOnlyOrigins());
330
331   // Or the session-onlyness can affect individual origins.
332   ContentSettingsPattern pattern =
333       ContentSettingsPattern::FromString("pattern.com");
334
335   cookie_settings->SetCookieSetting(pattern,
336                                     ContentSettingsPattern::Wildcard(),
337                                     CONTENT_SETTING_SESSION_ONLY);
338
339   EXPECT_TRUE(policy_->HasSessionOnlyOrigins());
340
341   // Clearing an origin-specific rule.
342   cookie_settings->ResetCookieSetting(pattern,
343                                       ContentSettingsPattern::Wildcard());
344
345   EXPECT_FALSE(policy_->HasSessionOnlyOrigins());
346 }
347
348 TEST_F(ExtensionSpecialStoragePolicyTest, NotificationTest) {
349   base::MessageLoop message_loop;
350   content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
351   content::TestBrowserThread io_thread(BrowserThread::IO, &message_loop);
352
353   PolicyChangeObserver observer;
354   policy_->AddObserver(&observer);
355
356   scoped_refptr<Extension> apps[] = {
357     CreateProtectedApp(),
358     CreateUnlimitedApp(),
359   };
360
361   int change_flags[] = {
362     SpecialStoragePolicy::STORAGE_PROTECTED,
363
364     SpecialStoragePolicy::STORAGE_PROTECTED |
365     SpecialStoragePolicy::STORAGE_UNLIMITED,
366   };
367
368   ASSERT_EQ(arraysize(apps), arraysize(change_flags));
369   for (size_t i = 0; i < arraysize(apps); ++i) {
370     SCOPED_TRACE(testing::Message() << "i: " << i);
371     observer.ExpectGrant(apps[i]->id(), change_flags[i]);
372     policy_->GrantRightsForExtension(apps[i].get());
373     message_loop.RunUntilIdle();
374     EXPECT_TRUE(observer.IsCompleted());
375   }
376
377   for (size_t i = 0; i < arraysize(apps); ++i) {
378     SCOPED_TRACE(testing::Message() << "i: " << i);
379     policy_->GrantRightsForExtension(apps[i].get());
380     message_loop.RunUntilIdle();
381     EXPECT_TRUE(observer.IsCompleted());
382   }
383
384   for (size_t i = 0; i < arraysize(apps); ++i) {
385     SCOPED_TRACE(testing::Message() << "i: " << i);
386     observer.ExpectRevoke(apps[i]->id(), change_flags[i]);
387     policy_->RevokeRightsForExtension(apps[i].get());
388     message_loop.RunUntilIdle();
389     EXPECT_TRUE(observer.IsCompleted());
390   }
391
392   for (size_t i = 0; i < arraysize(apps); ++i) {
393     SCOPED_TRACE(testing::Message() << "i: " << i);
394     policy_->RevokeRightsForExtension(apps[i].get());
395     message_loop.RunUntilIdle();
396     EXPECT_TRUE(observer.IsCompleted());
397   }
398
399   observer.ExpectClear();
400   policy_->RevokeRightsForAllExtensions();
401   message_loop.RunUntilIdle();
402   EXPECT_TRUE(observer.IsCompleted());
403
404   policy_->RemoveObserver(&observer);
405 }