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/apps_helper.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/strings/string_number_conversions.h"
      9 #include "chrome/browser/chrome_notification_types.h"
     10 #include "chrome/browser/profiles/profile.h"
     11 #include "chrome/browser/sync/test/integration/status_change_checker.h"
     12 #include "chrome/browser/sync/test/integration/sync_app_helper.h"
     13 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
     14 #include "chrome/browser/sync/test/integration/sync_extension_helper.h"
     15 #include "chrome/browser/sync/test/integration/sync_extension_installer.h"
     16 #include "content/public/browser/notification_observer.h"
     17 #include "content/public/browser/notification_registrar.h"
     18 #include "content/public/browser/notification_service.h"
     19 #include "extensions/browser/extension_prefs.h"
     20 #include "extensions/browser/extension_prefs_observer.h"
     21 #include "extensions/browser/extension_registry.h"
     22 #include "extensions/browser/extension_registry_observer.h"
     23 #include "extensions/common/manifest.h"
     24 
     25 using sync_datatype_helper::test;
     26 
     27 namespace {
     28 
     29 std::string CreateFakeAppName(int index) {
     30   return "fakeapp" + base::IntToString(index);
     31 }
     32 
     33 }  // namespace
     34 
     35 namespace apps_helper {
     36 
     37 bool HasSameAppsAsVerifier(int index) {
     38   return SyncAppHelper::GetInstance()->AppStatesMatch(
     39       test()->GetProfile(index), test()->verifier());
     40 }
     41 
     42 bool AllProfilesHaveSameAppsAsVerifier() {
     43   for (int i = 0; i < test()->num_clients(); ++i) {
     44     if (!HasSameAppsAsVerifier(i)) {
     45       DVLOG(1) << "Profile " << i << " doesn't have the same apps as the"
     46                                      " verifier profile.";
     47       return false;
     48     }
     49   }
     50   return true;
     51 }
     52 
     53 std::string InstallApp(Profile* profile, int index) {
     54   return SyncExtensionHelper::GetInstance()->InstallExtension(
     55       profile,
     56       CreateFakeAppName(index),
     57       extensions::Manifest::TYPE_HOSTED_APP);
     58 }
     59 
     60 std::string InstallPlatformApp(Profile* profile, int index) {
     61   return SyncExtensionHelper::GetInstance()->InstallExtension(
     62       profile,
     63       CreateFakeAppName(index),
     64       extensions::Manifest::TYPE_PLATFORM_APP);
     65 }
     66 
     67 std::string InstallAppForAllProfiles(int index) {
     68   for (int i = 0; i < test()->num_clients(); ++i)
     69     InstallApp(test()->GetProfile(i), index);
     70   return InstallApp(test()->verifier(), index);
     71 }
     72 
     73 void UninstallApp(Profile* profile, int index) {
     74   return SyncExtensionHelper::GetInstance()->UninstallExtension(
     75       profile, CreateFakeAppName(index));
     76 }
     77 
     78 void EnableApp(Profile* profile, int index) {
     79   return SyncExtensionHelper::GetInstance()->EnableExtension(
     80       profile, CreateFakeAppName(index));
     81 }
     82 
     83 void DisableApp(Profile* profile, int index) {
     84   return SyncExtensionHelper::GetInstance()->DisableExtension(
     85       profile, CreateFakeAppName(index));
     86 }
     87 
     88 void IncognitoEnableApp(Profile* profile, int index) {
     89   return SyncExtensionHelper::GetInstance()->IncognitoEnableExtension(
     90       profile, CreateFakeAppName(index));
     91 }
     92 
     93 void IncognitoDisableApp(Profile* profile, int index) {
     94   return SyncExtensionHelper::GetInstance()->IncognitoDisableExtension(
     95       profile, CreateFakeAppName(index));
     96 }
     97 
     98 void InstallAppsPendingForSync(Profile* profile) {
     99   SyncExtensionHelper::GetInstance()->InstallExtensionsPendingForSync(profile);
    100 }
    101 
    102 syncer::StringOrdinal GetPageOrdinalForApp(Profile* profile,
    103                                            int app_index) {
    104   return SyncAppHelper::GetInstance()->GetPageOrdinalForApp(
    105       profile, CreateFakeAppName(app_index));
    106 }
    107 
    108 void SetPageOrdinalForApp(Profile* profile,
    109                           int app_index,
    110                           const syncer::StringOrdinal& page_ordinal) {
    111   SyncAppHelper::GetInstance()->SetPageOrdinalForApp(
    112       profile, CreateFakeAppName(app_index), page_ordinal);
    113 }
    114 
    115 syncer::StringOrdinal GetAppLaunchOrdinalForApp(Profile* profile,
    116                                                 int app_index) {
    117   return SyncAppHelper::GetInstance()->GetAppLaunchOrdinalForApp(
    118       profile, CreateFakeAppName(app_index));
    119 }
    120 
    121 void SetAppLaunchOrdinalForApp(
    122     Profile* profile,
    123     int app_index,
    124     const syncer::StringOrdinal& app_launch_ordinal) {
    125   SyncAppHelper::GetInstance()->SetAppLaunchOrdinalForApp(
    126       profile, CreateFakeAppName(app_index), app_launch_ordinal);
    127 }
    128 
    129 void CopyNTPOrdinals(Profile* source, Profile* destination, int index) {
    130   SetPageOrdinalForApp(destination, index, GetPageOrdinalForApp(source, index));
    131   SetAppLaunchOrdinalForApp(
    132       destination, index, GetAppLaunchOrdinalForApp(source, index));
    133 }
    134 
    135 void FixNTPOrdinalCollisions(Profile* profile) {
    136   SyncAppHelper::GetInstance()->FixNTPOrdinalCollisions(profile);
    137 }
    138 
    139 namespace {
    140 
    141 // A helper class to implement waiting for a set of profiles to have matching
    142 // extensions lists.
    143 class AppsMatchChecker : public StatusChangeChecker,
    144                          public extensions::ExtensionRegistryObserver,
    145                          public extensions::ExtensionPrefsObserver,
    146                          public content::NotificationObserver {
    147  public:
    148   explicit AppsMatchChecker(const std::vector<Profile*>& profiles);
    149   virtual ~AppsMatchChecker();
    150 
    151   // StatusChangeChecker implementation.
    152   virtual std::string GetDebugMessage() const OVERRIDE;
    153   virtual bool IsExitConditionSatisfied() OVERRIDE;
    154 
    155   // extensions::ExtensionRegistryObserver implementation.
    156   virtual void OnExtensionLoaded(
    157       content::BrowserContext* context,
    158       const extensions::Extension* extension) OVERRIDE;
    159   virtual void OnExtensionUnloaded(
    160       content::BrowserContext* context,
    161       const extensions::Extension* extenion,
    162       extensions::UnloadedExtensionInfo::Reason reason) OVERRIDE;
    163   virtual void OnExtensionInstalled(content::BrowserContext* browser_context,
    164                                     const extensions::Extension* extension,
    165                                     bool is_update) OVERRIDE;
    166   virtual void OnExtensionUninstalled(
    167       content::BrowserContext* browser_context,
    168       const extensions::Extension* extension,
    169       extensions::UninstallReason reason) OVERRIDE;
    170 
    171   // extensions::ExtensionPrefsObserver implementation.
    172   virtual void OnExtensionDisableReasonsChanged(const std::string& extension_id,
    173                                                 int disabled_reasons) OVERRIDE;
    174   virtual void OnExtensionRegistered(const std::string& extension_id,
    175                                      const base::Time& install_time,
    176                                      bool is_enabled) OVERRIDE;
    177   virtual void OnExtensionPrefsLoaded(
    178       const std::string& extension_id,
    179       const extensions::ExtensionPrefs* prefs) OVERRIDE;
    180   virtual void OnExtensionPrefsDeleted(
    181       const std::string& extension_id) OVERRIDE;
    182   virtual void OnExtensionStateChanged(const std::string& extension_id,
    183                                        bool state) OVERRIDE;
    184 
    185   // Implementation of content::NotificationObserver.
    186   virtual void Observe(int type,
    187                        const content::NotificationSource& source,
    188                        const content::NotificationDetails& details) OVERRIDE;
    189 
    190   void Wait();
    191 
    192  private:
    193   std::vector<Profile*> profiles_;
    194   bool observing_;
    195 
    196   content::NotificationRegistrar registrar_;
    197 
    198   // This installs apps, too.
    199   ScopedVector<SyncedExtensionInstaller> synced_extension_installers_;
    200 
    201   DISALLOW_COPY_AND_ASSIGN(AppsMatchChecker);
    202 };
    203 
    204 AppsMatchChecker::AppsMatchChecker(const std::vector<Profile*>& profiles)
    205     : profiles_(profiles), observing_(false) {
    206   DCHECK_GE(profiles_.size(), 2U);
    207 }
    208 
    209 AppsMatchChecker::~AppsMatchChecker() {
    210   if (observing_) {
    211     for (std::vector<Profile*>::iterator it = profiles_.begin();
    212          it != profiles_.end();
    213          ++it) {
    214       extensions::ExtensionRegistry* registry =
    215           extensions::ExtensionRegistry::Get(*it);
    216       registry->RemoveObserver(this);
    217       extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(*it);
    218       prefs->RemoveObserver(this);
    219     }
    220   }
    221 }
    222 
    223 std::string AppsMatchChecker::GetDebugMessage() const {
    224   return "Waiting for apps to match";
    225 }
    226 
    227 bool AppsMatchChecker::IsExitConditionSatisfied() {
    228   std::vector<Profile*>::iterator it = profiles_.begin();
    229   Profile* profile0 = *it;
    230   ++it;
    231   for (; it != profiles_.end(); ++it) {
    232     if (!SyncAppHelper::GetInstance()->AppStatesMatch(profile0, *it)) {
    233       return false;
    234     }
    235   }
    236   return true;
    237 }
    238 
    239 void AppsMatchChecker::OnExtensionLoaded(
    240     content::BrowserContext* context,
    241     const extensions::Extension* extension) {
    242   CheckExitCondition();
    243 }
    244 
    245 void AppsMatchChecker::OnExtensionUnloaded(
    246     content::BrowserContext* context,
    247     const extensions::Extension* extenion,
    248     extensions::UnloadedExtensionInfo::Reason reason) {
    249   CheckExitCondition();
    250 }
    251 
    252 void AppsMatchChecker::OnExtensionInstalled(
    253     content::BrowserContext* browser_context,
    254     const extensions::Extension* extension,
    255     bool is_update) {
    256   CheckExitCondition();
    257 }
    258 
    259 void AppsMatchChecker::OnExtensionUninstalled(
    260     content::BrowserContext* browser_context,
    261     const extensions::Extension* extension,
    262     extensions::UninstallReason reason) {
    263   CheckExitCondition();
    264 }
    265 
    266 void AppsMatchChecker::OnExtensionDisableReasonsChanged(
    267     const std::string& extension_id,
    268     int disabled_reasons) {
    269   CheckExitCondition();
    270 }
    271 
    272 void AppsMatchChecker::OnExtensionRegistered(const std::string& extension_id,
    273                                              const base::Time& install_time,
    274                                              bool is_enabled) {
    275   CheckExitCondition();
    276 }
    277 
    278 void AppsMatchChecker::OnExtensionPrefsLoaded(
    279     const std::string& extension_id,
    280     const extensions::ExtensionPrefs* prefs) {
    281   CheckExitCondition();
    282 }
    283 
    284 void AppsMatchChecker::OnExtensionPrefsDeleted(
    285     const std::string& extension_id) {
    286   CheckExitCondition();
    287 }
    288 
    289 void AppsMatchChecker::OnExtensionStateChanged(const std::string& extension_id,
    290                                                bool state) {
    291   CheckExitCondition();
    292 }
    293 
    294 void AppsMatchChecker::Observe(int type,
    295                                const content::NotificationSource& source,
    296                                const content::NotificationDetails& details) {
    297   DCHECK_EQ(chrome::NOTIFICATION_APP_LAUNCHER_REORDERED, type);
    298   CheckExitCondition();
    299 }
    300 
    301 void AppsMatchChecker::Wait() {
    302   for (std::vector<Profile*>::iterator it = profiles_.begin();
    303        it != profiles_.end();
    304        ++it) {
    305     // Begin mocking the installation of synced extensions from the web store.
    306     synced_extension_installers_.push_back(new SyncedExtensionInstaller(*it));
    307 
    308     // Register as an observer of ExtensionsRegistry to receive notifications of
    309     // big events, like installs and uninstalls.
    310     extensions::ExtensionRegistry* registry =
    311         extensions::ExtensionRegistry::Get(*it);
    312     registry->AddObserver(this);
    313 
    314     // Register for ExtensionPrefs events, too, so we can get notifications
    315     // about
    316     // smaller but still syncable events, like launch type changes.
    317     extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(*it);
    318     prefs->AddObserver(this);
    319   }
    320 
    321   registrar_.Add(this,
    322                  chrome::NOTIFICATION_APP_LAUNCHER_REORDERED,
    323                  content::NotificationService::AllSources());
    324 
    325   observing_ = true;
    326 
    327   if (IsExitConditionSatisfied()) {
    328     DVLOG(1) << "Apps matched without waiting";
    329     return;
    330   }
    331 
    332   DVLOG(1) << "Starting Wait: " << GetDebugMessage();
    333   StartBlockingWait();
    334 }
    335 
    336 }  // namespace
    337 
    338 bool AwaitAllProfilesHaveSameAppsAsVerifier() {
    339   std::vector<Profile*> profiles;
    340   profiles.push_back(test()->verifier());
    341   for (int i = 0; i < test()->num_clients(); ++i) {
    342     profiles.push_back(test()->GetProfile(i));
    343   }
    344 
    345   AppsMatchChecker checker(profiles);
    346   checker.Wait();
    347   return !checker.TimedOut();
    348 }
    349 
    350 }  // namespace apps_helper
    351