Home | History | Annotate | Download | only in integration
      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 "chrome/browser/sync/test/integration/extensions_helper.h"
      6 
      7 #include <cstring>
      8 
      9 #include "base/logging.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/strings/string_util.h"
     12 #include "chrome/browser/profiles/profile.h"
     13 #include "chrome/browser/sync/test/integration/status_change_checker.h"
     14 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
     15 #include "chrome/browser/sync/test/integration/sync_extension_helper.h"
     16 #include "chrome/browser/sync/test/integration/sync_extension_installer.h"
     17 #include "extensions/browser/extension_registry.h"
     18 #include "extensions/browser/extension_registry_observer.h"
     19 #include "extensions/common/manifest.h"
     20 
     21 using sync_datatype_helper::test;
     22 
     23 namespace extensions_helper {
     24 
     25 const char extension_name_prefix[] = "fakeextension";
     26 
     27 bool HasSameExtensionsAsVerifier(int index) {
     28   return SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(
     29       test()->GetProfile(index), test()->verifier());
     30 }
     31 
     32 bool AllProfilesHaveSameExtensionsAsVerifier() {
     33   for (int i = 0; i < test()->num_clients(); ++i) {
     34     if (!HasSameExtensionsAsVerifier(i)) {
     35       LOG(ERROR) << "Profile " << i << " doesn't have the same extensions as"
     36                                        " the verifier profile.";
     37       return false;
     38     }
     39   }
     40   return true;
     41 }
     42 
     43 bool AllProfilesHaveSameExtensions() {
     44   for (int i = 1; i < test()->num_clients(); ++i) {
     45     if (!SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(
     46         test()->GetProfile(0), test()->GetProfile(i))) {
     47       LOG(ERROR) << "Profile " << i << " doesnt have the same extensions as"
     48                                        " profile 0.";
     49       return false;
     50     }
     51   }
     52   return true;
     53 }
     54 
     55 
     56 std::string InstallExtension(Profile* profile, int index) {
     57   return SyncExtensionHelper::GetInstance()->InstallExtension(
     58       profile,
     59       CreateFakeExtensionName(index),
     60       extensions::Manifest::TYPE_EXTENSION);
     61 }
     62 
     63 std::string InstallExtensionForAllProfiles(int index) {
     64   for (int i = 0; i < test()->num_clients(); ++i)
     65     InstallExtension(test()->GetProfile(i), index);
     66   return InstallExtension(test()->verifier(), index);
     67 }
     68 
     69 void UninstallExtension(Profile* profile, int index) {
     70   return SyncExtensionHelper::GetInstance()->UninstallExtension(
     71       profile, CreateFakeExtensionName(index));
     72 }
     73 
     74 std::vector<int> GetInstalledExtensions(Profile* profile) {
     75   std::vector<int> indices;
     76   std::vector<std::string> names =
     77       SyncExtensionHelper::GetInstance()->GetInstalledExtensionNames(profile);
     78   for (std::vector<std::string>::const_iterator it = names.begin();
     79        it != names.end(); ++it) {
     80     int index;
     81     if (ExtensionNameToIndex(*it, &index)) {
     82       indices.push_back(index);
     83     }
     84   }
     85   return indices;
     86 }
     87 
     88 void EnableExtension(Profile* profile, int index) {
     89   return SyncExtensionHelper::GetInstance()->EnableExtension(
     90       profile, CreateFakeExtensionName(index));
     91 }
     92 
     93 void DisableExtension(Profile* profile, int index) {
     94   return SyncExtensionHelper::GetInstance()->DisableExtension(
     95       profile, CreateFakeExtensionName(index));
     96 }
     97 
     98 bool IsExtensionEnabled(Profile* profile, int index) {
     99   return SyncExtensionHelper::GetInstance()->IsExtensionEnabled(
    100       profile, CreateFakeExtensionName(index));
    101 }
    102 
    103 void IncognitoEnableExtension(Profile* profile, int index) {
    104   return SyncExtensionHelper::GetInstance()->IncognitoEnableExtension(
    105       profile, CreateFakeExtensionName(index));
    106 }
    107 
    108 void IncognitoDisableExtension(Profile* profile, int index) {
    109   return SyncExtensionHelper::GetInstance()->IncognitoDisableExtension(
    110       profile, CreateFakeExtensionName(index));
    111 }
    112 
    113 bool IsIncognitoEnabled(Profile* profile, int index) {
    114   return SyncExtensionHelper::GetInstance()->IsIncognitoEnabled(
    115       profile, CreateFakeExtensionName(index));
    116 }
    117 
    118 void InstallExtensionsPendingForSync(Profile* profile) {
    119   SyncExtensionHelper::GetInstance()->InstallExtensionsPendingForSync(profile);
    120 }
    121 
    122 std::string CreateFakeExtensionName(int index) {
    123   return extension_name_prefix + base::IntToString(index);
    124 }
    125 
    126 bool ExtensionNameToIndex(const std::string& name, int* index) {
    127   if (!StartsWithASCII(name, extension_name_prefix, true) ||
    128       !base::StringToInt(name.substr(strlen(extension_name_prefix)), index)) {
    129     LOG(WARNING) << "Unable to convert extension name \"" << name
    130                  << "\" to index";
    131     return false;
    132   }
    133   return true;
    134 }
    135 
    136 namespace {
    137 
    138 // A helper class to implement waiting for a set of profiles to have matching
    139 // extensions lists.
    140 class ExtensionsMatchChecker : public StatusChangeChecker,
    141                                public extensions::ExtensionRegistryObserver {
    142  public:
    143   explicit ExtensionsMatchChecker(const std::vector<Profile*>& profiles);
    144   virtual ~ExtensionsMatchChecker();
    145 
    146   // StatusChangeChecker implementation.
    147   virtual std::string GetDebugMessage() const OVERRIDE;
    148   virtual bool IsExitConditionSatisfied() OVERRIDE;
    149 
    150   // extensions::ExtensionRegistryObserver implementation.
    151   virtual void OnExtensionLoaded(
    152       content::BrowserContext* context,
    153       const extensions::Extension* extension) OVERRIDE;
    154   virtual void OnExtensionUnloaded(
    155       content::BrowserContext* context,
    156       const extensions::Extension* extenion,
    157       extensions::UnloadedExtensionInfo::Reason reason) OVERRIDE;
    158   virtual void OnExtensionInstalled(
    159       content::BrowserContext* browser_context,
    160       const extensions::Extension* extension,
    161       bool is_update) OVERRIDE;
    162   virtual void OnExtensionUninstalled(
    163       content::BrowserContext* browser_context,
    164       const extensions::Extension* extension,
    165       extensions::UninstallReason reason) OVERRIDE;
    166 
    167   void Wait();
    168 
    169  private:
    170   std::vector<Profile*> profiles_;
    171   ScopedVector<SyncedExtensionInstaller> synced_extension_installers_;
    172   bool observing_;
    173 
    174   DISALLOW_COPY_AND_ASSIGN(ExtensionsMatchChecker);
    175 };
    176 
    177 ExtensionsMatchChecker::ExtensionsMatchChecker(
    178     const std::vector<Profile*>& profiles)
    179     : profiles_(profiles), observing_(false) {
    180   DCHECK_GE(profiles_.size(), 2U);
    181 }
    182 
    183 ExtensionsMatchChecker::~ExtensionsMatchChecker() {
    184   if (observing_) {
    185     for (std::vector<Profile*>::iterator it = profiles_.begin();
    186          it != profiles_.end();
    187          ++it) {
    188       extensions::ExtensionRegistry* registry =
    189           extensions::ExtensionRegistry::Get(*it);
    190       registry->RemoveObserver(this);
    191     }
    192   }
    193 }
    194 
    195 std::string ExtensionsMatchChecker::GetDebugMessage() const {
    196   return "Waiting for extensions to match";
    197 }
    198 
    199 bool ExtensionsMatchChecker::IsExitConditionSatisfied() {
    200   std::vector<Profile*>::iterator it = profiles_.begin();
    201   Profile* profile0 = *it;
    202   ++it;
    203   for (; it != profiles_.end(); ++it) {
    204     if (!SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(profile0,
    205                                                                   *it)) {
    206       return false;
    207     }
    208   }
    209   return true;
    210 }
    211 
    212 void ExtensionsMatchChecker::OnExtensionLoaded(
    213     content::BrowserContext* context,
    214     const extensions::Extension* extension) {
    215   CheckExitCondition();
    216 }
    217 
    218 void ExtensionsMatchChecker::OnExtensionUnloaded(
    219     content::BrowserContext* context,
    220     const extensions::Extension* extenion,
    221     extensions::UnloadedExtensionInfo::Reason reason) {
    222   CheckExitCondition();
    223 }
    224 
    225 void ExtensionsMatchChecker::OnExtensionInstalled(
    226     content::BrowserContext* browser_context,
    227     const extensions::Extension* extension,
    228     bool is_update) {
    229   CheckExitCondition();
    230 }
    231 
    232 void ExtensionsMatchChecker::OnExtensionUninstalled(
    233     content::BrowserContext* browser_context,
    234     const extensions::Extension* extension,
    235     extensions::UninstallReason reason) {
    236   CheckExitCondition();
    237 }
    238 
    239 void ExtensionsMatchChecker::Wait() {
    240   for (std::vector<Profile*>::iterator it = profiles_.begin();
    241        it != profiles_.end();
    242        ++it) {
    243     // Begin mocking the installation of synced extensions from the web store.
    244     synced_extension_installers_.push_back(new SyncedExtensionInstaller(*it));
    245 
    246     extensions::ExtensionRegistry* registry =
    247         extensions::ExtensionRegistry::Get(*it);
    248     registry->AddObserver(this);
    249   }
    250 
    251   observing_ = true;
    252 
    253   if (IsExitConditionSatisfied()) {
    254     VLOG(1) << "Extensions matched without waiting";
    255     return;
    256   }
    257 
    258   VLOG(1) << "Starting Wait: " << GetDebugMessage();
    259   StartBlockingWait();
    260 }
    261 
    262 }  // namespace
    263 
    264 bool AwaitAllProfilesHaveSameExtensionsAsVerifier() {
    265   std::vector<Profile*> profiles;
    266   profiles.push_back(test()->verifier());
    267   for (int i = 0; i < test()->num_clients(); ++i) {
    268     profiles.push_back(test()->GetProfile(i));
    269   }
    270 
    271   ExtensionsMatchChecker checker(profiles);
    272   checker.Wait();
    273   return !checker.TimedOut();
    274 }
    275 
    276 }  // namespace extensions_helper
    277