extensions_helper.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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 21using sync_datatype_helper::test; 22 23namespace extensions_helper { 24 25const char extension_name_prefix[] = "fakeextension"; 26 27bool HasSameExtensionsAsVerifier(int index) { 28 return SyncExtensionHelper::GetInstance()->ExtensionStatesMatch( 29 test()->GetProfile(index), test()->verifier()); 30} 31 32bool 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 43bool 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 56std::string InstallExtension(Profile* profile, int index) { 57 return SyncExtensionHelper::GetInstance()->InstallExtension( 58 profile, 59 CreateFakeExtensionName(index), 60 extensions::Manifest::TYPE_EXTENSION); 61} 62 63std::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 69void UninstallExtension(Profile* profile, int index) { 70 return SyncExtensionHelper::GetInstance()->UninstallExtension( 71 profile, CreateFakeExtensionName(index)); 72} 73 74std::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 88void EnableExtension(Profile* profile, int index) { 89 return SyncExtensionHelper::GetInstance()->EnableExtension( 90 profile, CreateFakeExtensionName(index)); 91} 92 93void DisableExtension(Profile* profile, int index) { 94 return SyncExtensionHelper::GetInstance()->DisableExtension( 95 profile, CreateFakeExtensionName(index)); 96} 97 98bool IsExtensionEnabled(Profile* profile, int index) { 99 return SyncExtensionHelper::GetInstance()->IsExtensionEnabled( 100 profile, CreateFakeExtensionName(index)); 101} 102 103void IncognitoEnableExtension(Profile* profile, int index) { 104 return SyncExtensionHelper::GetInstance()->IncognitoEnableExtension( 105 profile, CreateFakeExtensionName(index)); 106} 107 108void IncognitoDisableExtension(Profile* profile, int index) { 109 return SyncExtensionHelper::GetInstance()->IncognitoDisableExtension( 110 profile, CreateFakeExtensionName(index)); 111} 112 113bool IsIncognitoEnabled(Profile* profile, int index) { 114 return SyncExtensionHelper::GetInstance()->IsIncognitoEnabled( 115 profile, CreateFakeExtensionName(index)); 116} 117 118void InstallExtensionsPendingForSync(Profile* profile) { 119 SyncExtensionHelper::GetInstance()->InstallExtensionsPendingForSync(profile); 120} 121 122std::string CreateFakeExtensionName(int index) { 123 return extension_name_prefix + base::IntToString(index); 124} 125 126bool 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 136namespace { 137 138// A helper class to implement waiting for a set of profiles to have matching 139// extensions lists. 140class 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) OVERRIDE; 165 166 void Wait(); 167 168 private: 169 std::vector<Profile*> profiles_; 170 ScopedVector<SyncedExtensionInstaller> synced_extension_installers_; 171 bool observing_; 172 173 DISALLOW_COPY_AND_ASSIGN(ExtensionsMatchChecker); 174}; 175 176ExtensionsMatchChecker::ExtensionsMatchChecker( 177 const std::vector<Profile*>& profiles) 178 : profiles_(profiles), observing_(false) { 179 DCHECK_GE(profiles_.size(), 2U); 180} 181 182ExtensionsMatchChecker::~ExtensionsMatchChecker() { 183 if (observing_) { 184 for (std::vector<Profile*>::iterator it = profiles_.begin(); 185 it != profiles_.end(); 186 ++it) { 187 extensions::ExtensionRegistry* registry = 188 extensions::ExtensionRegistry::Get(*it); 189 registry->RemoveObserver(this); 190 } 191 } 192} 193 194std::string ExtensionsMatchChecker::GetDebugMessage() const { 195 return "Waiting for extensions to match"; 196} 197 198bool ExtensionsMatchChecker::IsExitConditionSatisfied() { 199 std::vector<Profile*>::iterator it = profiles_.begin(); 200 Profile* profile0 = *it; 201 ++it; 202 for (; it != profiles_.end(); ++it) { 203 if (!SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(profile0, 204 *it)) { 205 return false; 206 } 207 } 208 return true; 209} 210 211void ExtensionsMatchChecker::OnExtensionLoaded( 212 content::BrowserContext* context, 213 const extensions::Extension* extension) { 214 CheckExitCondition(); 215} 216 217void ExtensionsMatchChecker::OnExtensionUnloaded( 218 content::BrowserContext* context, 219 const extensions::Extension* extenion, 220 extensions::UnloadedExtensionInfo::Reason reason) { 221 CheckExitCondition(); 222} 223 224void ExtensionsMatchChecker::OnExtensionInstalled( 225 content::BrowserContext* browser_context, 226 const extensions::Extension* extension, 227 bool is_update) { 228 CheckExitCondition(); 229} 230 231void ExtensionsMatchChecker::OnExtensionUninstalled( 232 content::BrowserContext* browser_context, 233 const extensions::Extension* extension) { 234 CheckExitCondition(); 235} 236 237void ExtensionsMatchChecker::Wait() { 238 for (std::vector<Profile*>::iterator it = profiles_.begin(); 239 it != profiles_.end(); 240 ++it) { 241 // Begin mocking the installation of synced extensions from the web store. 242 synced_extension_installers_.push_back(new SyncedExtensionInstaller(*it)); 243 244 extensions::ExtensionRegistry* registry = 245 extensions::ExtensionRegistry::Get(*it); 246 registry->AddObserver(this); 247 } 248 249 observing_ = true; 250 251 if (IsExitConditionSatisfied()) { 252 VLOG(1) << "Extensions matched without waiting"; 253 return; 254 } 255 256 VLOG(1) << "Starting Wait: " << GetDebugMessage(); 257 StartBlockingWait(); 258} 259 260} // namespace 261 262bool AwaitAllProfilesHaveSameExtensionsAsVerifier() { 263 std::vector<Profile*> profiles; 264 profiles.push_back(test()->verifier()); 265 for (int i = 0; i < test()->num_clients(); ++i) { 266 profiles.push_back(test()->GetProfile(i)); 267 } 268 269 ExtensionsMatchChecker checker(profiles); 270 checker.Wait(); 271 return !checker.TimedOut(); 272} 273 274} // namespace extensions_helper 275