- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / permissions_updater_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/files/file_path.h"
6 #include "base/json/json_file_value_serializer.h"
7 #include "base/memory/ref_counted.h"
8 #include "base/path_service.h"
9 #include "base/run_loop.h"
10 #include "base/values.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/extension_service_unittest.h"
14 #include "chrome/browser/extensions/permissions_updater.h"
15 #include "chrome/common/chrome_paths.h"
16 #include "chrome/common/extensions/extension.h"
17 #include "chrome/common/extensions/extension_test_util.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "content/public/browser/notification_observer.h"
20 #include "content/public/browser/notification_registrar.h"
21 #include "content/public/browser/notification_service.h"
22 #include "extensions/common/permissions/permission_set.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 using extension_test_util::LoadManifest;
26
27 namespace extensions {
28
29 namespace {
30
31 // A helper class that listens for NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED.
32 class PermissionsUpdaterListener : public content::NotificationObserver {
33  public:
34   PermissionsUpdaterListener()
35       : received_notification_(false), waiting_(false) {
36     registrar_.Add(this,
37                    chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
38                    content::NotificationService::AllSources());
39   }
40
41   void Reset() {
42     received_notification_ = false;
43     waiting_ = false;
44     extension_ = NULL;
45     permissions_ = NULL;
46   }
47
48   void Wait() {
49     if (received_notification_)
50       return;
51
52     waiting_ = true;
53     base::RunLoop run_loop;
54     run_loop.Run();
55   }
56
57   bool received_notification() const { return received_notification_; }
58   const Extension* extension() const { return extension_.get(); }
59   const PermissionSet* permissions() const { return permissions_.get(); }
60   UpdatedExtensionPermissionsInfo::Reason reason() const { return reason_; }
61
62  private:
63   virtual void Observe(int type,
64                        const content::NotificationSource& source,
65                        const content::NotificationDetails& details) OVERRIDE {
66     received_notification_ = true;
67     UpdatedExtensionPermissionsInfo* info =
68         content::Details<UpdatedExtensionPermissionsInfo>(details).ptr();
69
70     extension_ = info->extension;
71     permissions_ = info->permissions;
72     reason_ = info->reason;
73
74     if (waiting_) {
75       waiting_ = false;
76       base::MessageLoopForUI::current()->Quit();
77     }
78   }
79
80   bool received_notification_;
81   bool waiting_;
82   content::NotificationRegistrar registrar_;
83   scoped_refptr<const Extension> extension_;
84   scoped_refptr<const PermissionSet> permissions_;
85   UpdatedExtensionPermissionsInfo::Reason reason_;
86 };
87
88 class PermissionsUpdaterTest : public ExtensionServiceTestBase {
89 };
90
91 scoped_refptr<Extension> LoadOurManifest() {
92   base::FilePath path;
93   path = path.AppendASCII("api_test")
94       .AppendASCII("permissions")
95       .AppendASCII("optional");
96   return LoadManifest(path.AsUTF8Unsafe(),
97                       "manifest.json",
98                       Manifest::INTERNAL,
99                       Extension::NO_FLAGS);
100 }
101
102 void AddPattern(URLPatternSet* extent, const std::string& pattern) {
103   int schemes = URLPattern::SCHEME_ALL;
104   extent->AddPattern(URLPattern(schemes, pattern));
105 }
106
107 }  // namespace
108
109 // Test that the PermissionUpdater can correctly add and remove active
110 // permissions. This tests all of PermissionsUpdater's public methods because
111 // GrantActivePermissions and UpdateActivePermissions are used by
112 // AddPermissions.
113 TEST_F(PermissionsUpdaterTest, AddAndRemovePermissions) {
114   InitializeEmptyExtensionService();
115
116   // Load the test extension.
117   scoped_refptr<Extension> extension = LoadOurManifest();
118   ASSERT_TRUE(extension.get());
119
120   APIPermissionSet default_apis;
121   default_apis.insert(APIPermission::kManagement);
122   URLPatternSet default_hosts;
123   AddPattern(&default_hosts, "http://a.com/*");
124   scoped_refptr<PermissionSet> default_permissions =
125       new PermissionSet(default_apis, default_hosts, URLPatternSet());
126
127   // Make sure it loaded properly.
128   scoped_refptr<const PermissionSet> permissions =
129       extension->GetActivePermissions();
130   ASSERT_EQ(*default_permissions.get(),
131             *extension->GetActivePermissions().get());
132
133   // Add a few permissions.
134   APIPermissionSet apis;
135   apis.insert(APIPermission::kTab);
136   apis.insert(APIPermission::kNotification);
137   URLPatternSet hosts;
138   AddPattern(&hosts, "http://*.c.com/*");
139
140   scoped_refptr<PermissionSet> delta =
141       new PermissionSet(apis, hosts, URLPatternSet());
142
143   PermissionsUpdaterListener listener;
144   PermissionsUpdater updater(profile_.get());
145   updater.AddPermissions(extension.get(), delta.get());
146
147   listener.Wait();
148
149   // Verify that the permission notification was sent correctly.
150   ASSERT_TRUE(listener.received_notification());
151   ASSERT_EQ(extension, listener.extension());
152   ASSERT_EQ(UpdatedExtensionPermissionsInfo::ADDED, listener.reason());
153   ASSERT_EQ(*delta.get(), *listener.permissions());
154
155   // Make sure the extension's active permissions reflect the change.
156   scoped_refptr<PermissionSet> active_permissions =
157       PermissionSet::CreateUnion(default_permissions.get(), delta.get());
158   ASSERT_EQ(*active_permissions.get(),
159             *extension->GetActivePermissions().get());
160
161   // Verify that the new granted and active permissions were also stored
162   // in the extension preferences. In this case, the granted permissions should
163   // be equal to the active permissions.
164   ExtensionPrefs* prefs = service_->extension_prefs();
165   scoped_refptr<PermissionSet> granted_permissions =
166       active_permissions;
167
168   scoped_refptr<PermissionSet> from_prefs =
169       prefs->GetActivePermissions(extension->id());
170   ASSERT_EQ(*active_permissions.get(), *from_prefs.get());
171
172   from_prefs = prefs->GetGrantedPermissions(extension->id());
173   ASSERT_EQ(*active_permissions.get(), *from_prefs.get());
174
175   // In the second part of the test, we'll remove the permissions that we
176   // just added except for 'notification'.
177   apis.erase(APIPermission::kNotification);
178   delta = new PermissionSet(apis, hosts, URLPatternSet());
179
180   listener.Reset();
181   updater.RemovePermissions(extension.get(), delta.get());
182   listener.Wait();
183
184   // Verify that the notification was correct.
185   ASSERT_TRUE(listener.received_notification());
186   ASSERT_EQ(extension, listener.extension());
187   ASSERT_EQ(UpdatedExtensionPermissionsInfo::REMOVED, listener.reason());
188   ASSERT_EQ(*delta.get(), *listener.permissions());
189
190   // Make sure the extension's active permissions reflect the change.
191   active_permissions =
192       PermissionSet::CreateDifference(active_permissions.get(), delta.get());
193   ASSERT_EQ(*active_permissions.get(),
194             *extension->GetActivePermissions().get());
195
196   // Verify that the extension prefs hold the new active permissions and the
197   // same granted permissions.
198   from_prefs = prefs->GetActivePermissions(extension->id());
199   ASSERT_EQ(*active_permissions.get(), *from_prefs.get());
200
201   from_prefs = prefs->GetGrantedPermissions(extension->id());
202   ASSERT_EQ(*granted_permissions.get(), *from_prefs.get());
203 }
204
205 }  // namespace extensions