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_test_util.h"
     17 #include "chrome/test/base/testing_profile.h"
     18 #include "content/public/browser/notification_observer.h"
     19 #include "content/public/browser/notification_registrar.h"
     20 #include "content/public/browser/notification_service.h"
     21 #include "extensions/common/extension.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   ManifestPermissionSet empty_manifest_permissions;
    123 
    124   URLPatternSet default_hosts;
    125   AddPattern(&default_hosts, "http://a.com/*");
    126   scoped_refptr<PermissionSet> default_permissions =
    127       new PermissionSet(default_apis, empty_manifest_permissions,
    128                         default_hosts, URLPatternSet());
    129 
    130   // Make sure it loaded properly.
    131   scoped_refptr<const PermissionSet> permissions =
    132       extension->GetActivePermissions();
    133   ASSERT_EQ(*default_permissions.get(),
    134             *extension->GetActivePermissions().get());
    135 
    136   // Add a few permissions.
    137   APIPermissionSet apis;
    138   apis.insert(APIPermission::kTab);
    139   apis.insert(APIPermission::kNotification);
    140   URLPatternSet hosts;
    141   AddPattern(&hosts, "http://*.c.com/*");
    142 
    143   scoped_refptr<PermissionSet> delta =
    144       new PermissionSet(apis, empty_manifest_permissions,
    145                         hosts, URLPatternSet());
    146 
    147   PermissionsUpdaterListener listener;
    148   PermissionsUpdater updater(profile_.get());
    149   updater.AddPermissions(extension.get(), delta.get());
    150 
    151   listener.Wait();
    152 
    153   // Verify that the permission notification was sent correctly.
    154   ASSERT_TRUE(listener.received_notification());
    155   ASSERT_EQ(extension, listener.extension());
    156   ASSERT_EQ(UpdatedExtensionPermissionsInfo::ADDED, listener.reason());
    157   ASSERT_EQ(*delta.get(), *listener.permissions());
    158 
    159   // Make sure the extension's active permissions reflect the change.
    160   scoped_refptr<PermissionSet> active_permissions =
    161       PermissionSet::CreateUnion(default_permissions.get(), delta.get());
    162   ASSERT_EQ(*active_permissions.get(),
    163             *extension->GetActivePermissions().get());
    164 
    165   // Verify that the new granted and active permissions were also stored
    166   // in the extension preferences. In this case, the granted permissions should
    167   // be equal to the active permissions.
    168   ExtensionPrefs* prefs = service_->extension_prefs();
    169   scoped_refptr<PermissionSet> granted_permissions =
    170       active_permissions;
    171 
    172   scoped_refptr<PermissionSet> from_prefs =
    173       prefs->GetActivePermissions(extension->id());
    174   ASSERT_EQ(*active_permissions.get(), *from_prefs.get());
    175 
    176   from_prefs = prefs->GetGrantedPermissions(extension->id());
    177   ASSERT_EQ(*active_permissions.get(), *from_prefs.get());
    178 
    179   // In the second part of the test, we'll remove the permissions that we
    180   // just added except for 'notification'.
    181   apis.erase(APIPermission::kNotification);
    182   delta = new PermissionSet(apis, empty_manifest_permissions,
    183                             hosts, URLPatternSet());
    184 
    185   listener.Reset();
    186   updater.RemovePermissions(extension.get(), delta.get());
    187   listener.Wait();
    188 
    189   // Verify that the notification was correct.
    190   ASSERT_TRUE(listener.received_notification());
    191   ASSERT_EQ(extension, listener.extension());
    192   ASSERT_EQ(UpdatedExtensionPermissionsInfo::REMOVED, listener.reason());
    193   ASSERT_EQ(*delta.get(), *listener.permissions());
    194 
    195   // Make sure the extension's active permissions reflect the change.
    196   active_permissions =
    197       PermissionSet::CreateDifference(active_permissions.get(), delta.get());
    198   ASSERT_EQ(*active_permissions.get(),
    199             *extension->GetActivePermissions().get());
    200 
    201   // Verify that the extension prefs hold the new active permissions and the
    202   // same granted permissions.
    203   from_prefs = prefs->GetActivePermissions(extension->id());
    204   ASSERT_EQ(*active_permissions.get(), *from_prefs.get());
    205 
    206   from_prefs = prefs->GetGrantedPermissions(extension->id());
    207   ASSERT_EQ(*granted_permissions.get(), *from_prefs.get());
    208 }
    209 
    210 }  // namespace extensions
    211