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 "base/values.h"
6 #include "chrome/browser/content_settings/cookie_settings.h"
7 #include "chrome/browser/extensions/extension_special_storage_policy.h"
8 #include "chrome/test/base/testing_profile.h"
9 #include "components/content_settings/core/common/content_settings.h"
10 #include "components/content_settings/core/common/content_settings_types.h"
11 #include "content/public/test/test_browser_thread.h"
12 #include "content/public/test/test_browser_thread_bundle.h"
13 #include "extensions/common/extension.h"
14 #include "extensions/common/extension_set.h"
15 #include "extensions/common/manifest.h"
16 #include "extensions/common/manifest_constants.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using content::BrowserThread
;
20 using extensions::Extension
;
21 using extensions::ExtensionSet
;
22 using extensions::Manifest
;
23 using storage::SpecialStoragePolicy
;
25 typedef SpecialStoragePolicy::StoragePolicy StoragePolicy
;
27 namespace keys
= extensions::manifest_keys
;
29 class ExtensionSpecialStoragePolicyTest
: public testing::Test
{
31 class PolicyChangeObserver
: public SpecialStoragePolicy::Observer
{
33 PolicyChangeObserver()
34 : expected_type_(NOTIFICATION_TYPE_NONE
),
35 expected_change_flags_(0) {
38 void OnGranted(const GURL
& origin
, int change_flags
) override
{
39 EXPECT_EQ(expected_type_
, NOTIFICATION_TYPE_GRANT
);
40 EXPECT_EQ(expected_origin_
, origin
);
41 EXPECT_EQ(expected_change_flags_
, change_flags
);
42 expected_type_
= NOTIFICATION_TYPE_NONE
;
45 void OnRevoked(const GURL
& origin
, 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
;
52 void OnCleared() override
{
53 EXPECT_EQ(expected_type_
, NOTIFICATION_TYPE_CLEAR
);
54 expected_type_
= NOTIFICATION_TYPE_NONE
;
57 void ExpectGrant(const std::string
& extension_id
,
59 expected_type_
= NOTIFICATION_TYPE_GRANT
;
60 expected_origin_
= Extension::GetBaseURLFromExtensionId(extension_id
);
61 expected_change_flags_
= change_flags
;
64 void ExpectRevoke(const std::string
& extension_id
,
66 expected_type_
= NOTIFICATION_TYPE_REVOKE
;
67 expected_origin_
= Extension::GetBaseURLFromExtensionId(extension_id
);
68 expected_change_flags_
= change_flags
;
72 expected_type_
= NOTIFICATION_TYPE_CLEAR
;
76 return expected_type_
== NOTIFICATION_TYPE_NONE
;
81 NOTIFICATION_TYPE_NONE
,
82 NOTIFICATION_TYPE_GRANT
,
83 NOTIFICATION_TYPE_REVOKE
,
84 NOTIFICATION_TYPE_CLEAR
,
87 GURL expected_origin_
;
88 int expected_change_flags_
;
90 DISALLOW_COPY_AND_ASSIGN(PolicyChangeObserver
);
93 void SetUp() override
{ policy_
= new ExtensionSpecialStoragePolicy(NULL
); }
95 scoped_refptr
<Extension
> CreateProtectedApp() {
97 base::FilePath
path(FILE_PATH_LITERAL("c:\\foo"));
98 #elif defined(OS_POSIX)
99 base::FilePath
path(FILE_PATH_LITERAL("/foo"));
101 base::DictionaryValue manifest
;
102 manifest
.SetString(keys::kName
, "Protected");
103 manifest
.SetString(keys::kVersion
, "1");
104 manifest
.SetString(keys::kLaunchWebURL
, "http://explicit/protected/start");
105 base::ListValue
* list
= new base::ListValue();
106 list
->Append(new base::StringValue("http://explicit/protected"));
107 list
->Append(new base::StringValue("*://*.wildcards/protected"));
108 manifest
.Set(keys::kWebURLs
, list
);
110 scoped_refptr
<Extension
> protected_app
= Extension::Create(
111 path
, Manifest::INVALID_LOCATION
, manifest
,
112 Extension::NO_FLAGS
, &error
);
113 EXPECT_TRUE(protected_app
.get()) << error
;
114 return protected_app
;
117 scoped_refptr
<Extension
> CreateUnlimitedApp() {
119 base::FilePath
path(FILE_PATH_LITERAL("c:\\bar"));
120 #elif defined(OS_POSIX)
121 base::FilePath
path(FILE_PATH_LITERAL("/bar"));
123 base::DictionaryValue manifest
;
124 manifest
.SetString(keys::kName
, "Unlimited");
125 manifest
.SetString(keys::kVersion
, "1");
126 manifest
.SetString(keys::kLaunchWebURL
, "http://explicit/unlimited/start");
127 base::ListValue
* list
= new base::ListValue();
128 list
->Append(new base::StringValue("unlimitedStorage"));
129 manifest
.Set(keys::kPermissions
, list
);
130 list
= new base::ListValue();
131 list
->Append(new base::StringValue("http://explicit/unlimited"));
132 list
->Append(new base::StringValue("*://*.wildcards/unlimited"));
133 manifest
.Set(keys::kWebURLs
, list
);
135 scoped_refptr
<Extension
> unlimited_app
= Extension::Create(
136 path
, Manifest::INVALID_LOCATION
, manifest
,
137 Extension::NO_FLAGS
, &error
);
138 EXPECT_TRUE(unlimited_app
.get()) << error
;
139 return unlimited_app
;
142 scoped_refptr
<Extension
> CreateRegularApp() {
144 base::FilePath
path(FILE_PATH_LITERAL("c:\\app"));
145 #elif defined(OS_POSIX)
146 base::FilePath
path(FILE_PATH_LITERAL("/app"));
148 base::DictionaryValue manifest
;
149 manifest
.SetString(keys::kName
, "App");
150 manifest
.SetString(keys::kVersion
, "1");
151 manifest
.SetString(keys::kPlatformAppBackgroundPage
, "background.html");
153 scoped_refptr
<Extension
> app
= Extension::Create(
154 path
, Manifest::INVALID_LOCATION
, manifest
,
155 Extension::NO_FLAGS
, &error
);
156 EXPECT_TRUE(app
.get()) << error
;
160 // Verifies that the set of extensions protecting |url| is *exactly* equal to
161 // |expected_extensions|. Pass in an empty set to verify that an origin is not
163 void ExpectProtectedBy(const ExtensionSet
& expected_extensions
,
165 const ExtensionSet
* extensions
= policy_
->ExtensionsProtectingOrigin(url
);
166 EXPECT_EQ(expected_extensions
.size(), extensions
->size());
167 for (ExtensionSet::const_iterator it
= expected_extensions
.begin();
168 it
!= expected_extensions
.end(); ++it
) {
169 EXPECT_TRUE(extensions
->Contains((*it
)->id()))
170 << "Origin " << url
<< "not protected by extension ID "
175 content::TestBrowserThreadBundle thread_bundle_
;
176 scoped_refptr
<ExtensionSpecialStoragePolicy
> policy_
;
179 TEST_F(ExtensionSpecialStoragePolicyTest
, EmptyPolicy
) {
180 const GURL
kHttpUrl("http://foo");
181 const GURL
kExtensionUrl("chrome-extension://bar");
182 scoped_refptr
<Extension
> app(CreateRegularApp());
184 EXPECT_FALSE(policy_
->IsStorageUnlimited(kHttpUrl
));
185 EXPECT_FALSE(policy_
->IsStorageUnlimited(kHttpUrl
)); // test cached result
186 EXPECT_FALSE(policy_
->IsStorageUnlimited(kExtensionUrl
));
187 EXPECT_FALSE(policy_
->IsStorageUnlimited(app
->url()));
188 ExtensionSet empty_set
;
189 ExpectProtectedBy(empty_set
, kHttpUrl
);
191 // This one is just based on the scheme.
192 EXPECT_TRUE(policy_
->IsStorageProtected(kExtensionUrl
));
193 EXPECT_TRUE(policy_
->IsStorageProtected(app
->url()));
196 TEST_F(ExtensionSpecialStoragePolicyTest
, AppWithProtectedStorage
) {
197 scoped_refptr
<Extension
> extension(CreateProtectedApp());
198 policy_
->GrantRightsForExtension(extension
.get(), NULL
);
199 ExtensionSet protecting_extensions
;
200 protecting_extensions
.Insert(extension
);
201 ExtensionSet empty_set
;
203 EXPECT_FALSE(policy_
->IsStorageUnlimited(extension
->url()));
204 EXPECT_FALSE(policy_
->IsStorageUnlimited(GURL("http://explicit/")));
205 ExpectProtectedBy(protecting_extensions
, GURL("http://explicit/"));
206 ExpectProtectedBy(protecting_extensions
, GURL("http://explicit:6000/"));
207 ExpectProtectedBy(protecting_extensions
, GURL("http://foo.wildcards/"));
208 ExpectProtectedBy(protecting_extensions
, GURL("https://bar.wildcards/"));
209 ExpectProtectedBy(empty_set
, GURL("http://not_listed/"));
211 policy_
->RevokeRightsForExtension(extension
.get());
212 ExpectProtectedBy(empty_set
, GURL("http://explicit/"));
213 ExpectProtectedBy(empty_set
, GURL("http://foo.wildcards/"));
214 ExpectProtectedBy(empty_set
, GURL("https://bar.wildcards/"));
217 TEST_F(ExtensionSpecialStoragePolicyTest
, AppWithUnlimitedStorage
) {
218 scoped_refptr
<Extension
> extension(CreateUnlimitedApp());
219 policy_
->GrantRightsForExtension(extension
.get(), NULL
);
220 ExtensionSet protecting_extensions
;
221 protecting_extensions
.Insert(extension
);
222 ExtensionSet empty_set
;
224 ExpectProtectedBy(protecting_extensions
, GURL("http://explicit/"));
225 ExpectProtectedBy(protecting_extensions
, GURL("http://explicit:6000/"));
226 ExpectProtectedBy(protecting_extensions
, GURL("https://foo.wildcards/"));
227 ExpectProtectedBy(protecting_extensions
, GURL("https://foo.wildcards/"));
228 ExpectProtectedBy(protecting_extensions
, GURL("http://bar.wildcards/"));
229 ExpectProtectedBy(empty_set
, GURL("http://not_listed/"));
230 EXPECT_TRUE(policy_
->IsStorageUnlimited(extension
->url()));
231 EXPECT_TRUE(policy_
->IsStorageUnlimited(GURL("http://explicit/")));
232 EXPECT_TRUE(policy_
->IsStorageUnlimited(GURL("http://explicit:6000/")));
233 EXPECT_TRUE(policy_
->IsStorageUnlimited(GURL("https://foo.wildcards/")));
234 EXPECT_TRUE(policy_
->IsStorageUnlimited(GURL("https://bar.wildcards/")));
235 EXPECT_FALSE(policy_
->IsStorageUnlimited(GURL("http://not_listed/")));
237 policy_
->RevokeRightsForExtension(extension
.get());
238 ExpectProtectedBy(empty_set
, GURL("http://explicit/"));
239 ExpectProtectedBy(empty_set
, GURL("https://foo.wildcards/"));
240 ExpectProtectedBy(empty_set
, GURL("https://foo.wildcards/"));
241 ExpectProtectedBy(empty_set
, GURL("http://bar.wildcards/"));
242 EXPECT_FALSE(policy_
->IsStorageUnlimited(GURL("http://explicit/")));
243 EXPECT_FALSE(policy_
->IsStorageUnlimited(GURL("https://foo.wildcards/")));
244 EXPECT_FALSE(policy_
->IsStorageUnlimited(GURL("https://bar.wildcards/")));
247 TEST_F(ExtensionSpecialStoragePolicyTest
, CanQueryDiskSize
) {
248 const GURL
kHttpUrl("http://foo");
249 const GURL
kExtensionUrl("chrome-extension://bar");
250 scoped_refptr
<Extension
> regular_app(CreateRegularApp());
251 scoped_refptr
<Extension
> protected_app(CreateProtectedApp());
252 scoped_refptr
<Extension
> unlimited_app(CreateUnlimitedApp());
253 policy_
->GrantRightsForExtension(regular_app
.get(), NULL
);
254 policy_
->GrantRightsForExtension(protected_app
.get(), NULL
);
255 policy_
->GrantRightsForExtension(unlimited_app
.get(), NULL
);
257 EXPECT_FALSE(policy_
->CanQueryDiskSize(kHttpUrl
));
258 EXPECT_FALSE(policy_
->CanQueryDiskSize(kExtensionUrl
));
259 EXPECT_TRUE(policy_
->CanQueryDiskSize(regular_app
->url()));
260 EXPECT_TRUE(policy_
->CanQueryDiskSize(protected_app
->url()));
261 EXPECT_TRUE(policy_
->CanQueryDiskSize(unlimited_app
->url()));
264 TEST_F(ExtensionSpecialStoragePolicyTest
, HasIsolatedStorage
) {
265 const GURL
kHttpUrl("http://foo");
266 const GURL
kExtensionUrl("chrome-extension://bar");
267 scoped_refptr
<Extension
> app(CreateRegularApp());
268 policy_
->GrantRightsForExtension(app
.get(), NULL
);
270 EXPECT_FALSE(policy_
->HasIsolatedStorage(kHttpUrl
));
271 EXPECT_FALSE(policy_
->HasIsolatedStorage(kExtensionUrl
));
272 EXPECT_TRUE(policy_
->HasIsolatedStorage(app
->url()));
275 TEST_F(ExtensionSpecialStoragePolicyTest
, OverlappingApps
) {
276 scoped_refptr
<Extension
> protected_app(CreateProtectedApp());
277 scoped_refptr
<Extension
> unlimited_app(CreateUnlimitedApp());
278 policy_
->GrantRightsForExtension(protected_app
.get(), NULL
);
279 policy_
->GrantRightsForExtension(unlimited_app
.get(), NULL
);
280 ExtensionSet protecting_extensions
;
281 ExtensionSet empty_set
;
282 protecting_extensions
.Insert(protected_app
);
283 protecting_extensions
.Insert(unlimited_app
);
285 ExpectProtectedBy(protecting_extensions
, GURL("http://explicit/"));
286 ExpectProtectedBy(protecting_extensions
, GURL("http://explicit:6000/"));
287 ExpectProtectedBy(protecting_extensions
, GURL("https://foo.wildcards/"));
288 ExpectProtectedBy(protecting_extensions
, GURL("https://foo.wildcards/"));
289 ExpectProtectedBy(protecting_extensions
, GURL("http://bar.wildcards/"));
290 ExpectProtectedBy(empty_set
, GURL("http://not_listed/"));
291 EXPECT_TRUE(policy_
->IsStorageUnlimited(GURL("http://explicit/")));
292 EXPECT_TRUE(policy_
->IsStorageUnlimited(GURL("http://explicit:6000/")));
293 EXPECT_TRUE(policy_
->IsStorageUnlimited(GURL("https://foo.wildcards/")));
294 EXPECT_TRUE(policy_
->IsStorageUnlimited(GURL("https://bar.wildcards/")));
295 EXPECT_FALSE(policy_
->IsStorageUnlimited(GURL("http://not_listed/")));
297 policy_
->RevokeRightsForExtension(unlimited_app
.get());
298 protecting_extensions
.Remove(unlimited_app
->id());
299 EXPECT_FALSE(policy_
->IsStorageUnlimited(GURL("http://explicit/")));
300 EXPECT_FALSE(policy_
->IsStorageUnlimited(GURL("https://foo.wildcards/")));
301 EXPECT_FALSE(policy_
->IsStorageUnlimited(GURL("https://bar.wildcards/")));
302 ExpectProtectedBy(protecting_extensions
, GURL("http://explicit/"));
303 ExpectProtectedBy(protecting_extensions
, GURL("http://foo.wildcards/"));
304 ExpectProtectedBy(protecting_extensions
, GURL("https://bar.wildcards/"));
306 policy_
->RevokeRightsForExtension(protected_app
.get());
307 ExpectProtectedBy(empty_set
, GURL("http://explicit/"));
308 ExpectProtectedBy(empty_set
, GURL("http://foo.wildcards/"));
309 ExpectProtectedBy(empty_set
, GURL("https://bar.wildcards/"));
312 TEST_F(ExtensionSpecialStoragePolicyTest
, HasSessionOnlyOrigins
) {
313 TestingProfile profile
;
314 CookieSettings
* cookie_settings
=
315 CookieSettings::Factory::GetForProfile(&profile
).get();
316 policy_
= new ExtensionSpecialStoragePolicy(cookie_settings
);
318 EXPECT_FALSE(policy_
->HasSessionOnlyOrigins());
320 // The default setting can be session-only.
321 cookie_settings
->SetDefaultCookieSetting(CONTENT_SETTING_SESSION_ONLY
);
322 EXPECT_TRUE(policy_
->HasSessionOnlyOrigins());
324 cookie_settings
->SetDefaultCookieSetting(CONTENT_SETTING_ALLOW
);
325 EXPECT_FALSE(policy_
->HasSessionOnlyOrigins());
327 // Or the session-onlyness can affect individual origins.
328 ContentSettingsPattern pattern
=
329 ContentSettingsPattern::FromString("pattern.com");
331 cookie_settings
->SetCookieSetting(pattern
,
332 ContentSettingsPattern::Wildcard(),
333 CONTENT_SETTING_SESSION_ONLY
);
335 EXPECT_TRUE(policy_
->HasSessionOnlyOrigins());
337 // Clearing an origin-specific rule.
338 cookie_settings
->ResetCookieSetting(pattern
,
339 ContentSettingsPattern::Wildcard());
341 EXPECT_FALSE(policy_
->HasSessionOnlyOrigins());
344 TEST_F(ExtensionSpecialStoragePolicyTest
, NotificationTest
) {
345 PolicyChangeObserver observer
;
346 policy_
->AddObserver(&observer
);
348 scoped_refptr
<Extension
> apps
[] = {
349 CreateProtectedApp(),
350 CreateUnlimitedApp(),
353 int change_flags
[] = {
354 SpecialStoragePolicy::STORAGE_PROTECTED
,
356 SpecialStoragePolicy::STORAGE_PROTECTED
|
357 SpecialStoragePolicy::STORAGE_UNLIMITED
,
360 ASSERT_EQ(arraysize(apps
), arraysize(change_flags
));
361 for (size_t i
= 0; i
< arraysize(apps
); ++i
) {
362 SCOPED_TRACE(testing::Message() << "i: " << i
);
363 observer
.ExpectGrant(apps
[i
]->id(), change_flags
[i
]);
364 policy_
->GrantRightsForExtension(apps
[i
].get(), NULL
);
365 base::MessageLoop::current()->RunUntilIdle();
366 EXPECT_TRUE(observer
.IsCompleted());
369 for (size_t i
= 0; i
< arraysize(apps
); ++i
) {
370 SCOPED_TRACE(testing::Message() << "i: " << i
);
371 policy_
->GrantRightsForExtension(apps
[i
].get(), NULL
);
372 base::MessageLoop::current()->RunUntilIdle();
373 EXPECT_TRUE(observer
.IsCompleted());
376 for (size_t i
= 0; i
< arraysize(apps
); ++i
) {
377 SCOPED_TRACE(testing::Message() << "i: " << i
);
378 observer
.ExpectRevoke(apps
[i
]->id(), change_flags
[i
]);
379 policy_
->RevokeRightsForExtension(apps
[i
].get());
380 base::MessageLoop::current()->RunUntilIdle();
381 EXPECT_TRUE(observer
.IsCompleted());
384 for (size_t i
= 0; i
< arraysize(apps
); ++i
) {
385 SCOPED_TRACE(testing::Message() << "i: " << i
);
386 policy_
->RevokeRightsForExtension(apps
[i
].get());
387 base::MessageLoop::current()->RunUntilIdle();
388 EXPECT_TRUE(observer
.IsCompleted());
391 observer
.ExpectClear();
392 policy_
->RevokeRightsForAllExtensions();
393 base::MessageLoop::current()->RunUntilIdle();
394 EXPECT_TRUE(observer
.IsCompleted());
396 policy_
->RemoveObserver(&observer
);