Home | History | Annotate | Download | only in extensions
      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/common/extensions/permissions/permission_set.h"
     19 #include "chrome/test/base/testing_profile.h"
     20 #include "content/public/browser/notification_observer.h"
     21 #include "content/public/browser/notification_registrar.h"
     22 #include "content/public/browser/notification_service.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
    206