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.
5 #include "chrome/browser/sync/test/integration/extensions_helper.h"
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"
21 using sync_datatype_helper::test
;
23 namespace extensions_helper
{
25 const char extension_name_prefix
[] = "fakeextension";
27 bool HasSameExtensionsAsVerifier(int index
) {
28 return SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(
29 test()->GetProfile(index
), test()->verifier());
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.";
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"
56 std::string
InstallExtension(Profile
* profile
, int index
) {
57 return SyncExtensionHelper::GetInstance()->InstallExtension(
59 CreateFakeExtensionName(index
),
60 extensions::Manifest::TYPE_EXTENSION
);
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
);
69 void UninstallExtension(Profile
* profile
, int index
) {
70 return SyncExtensionHelper::GetInstance()->UninstallExtension(
71 profile
, CreateFakeExtensionName(index
));
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
) {
81 if (ExtensionNameToIndex(*it
, &index
)) {
82 indices
.push_back(index
);
88 void EnableExtension(Profile
* profile
, int index
) {
89 return SyncExtensionHelper::GetInstance()->EnableExtension(
90 profile
, CreateFakeExtensionName(index
));
93 void DisableExtension(Profile
* profile
, int index
) {
94 return SyncExtensionHelper::GetInstance()->DisableExtension(
95 profile
, CreateFakeExtensionName(index
));
98 bool IsExtensionEnabled(Profile
* profile
, int index
) {
99 return SyncExtensionHelper::GetInstance()->IsExtensionEnabled(
100 profile
, CreateFakeExtensionName(index
));
103 void IncognitoEnableExtension(Profile
* profile
, int index
) {
104 return SyncExtensionHelper::GetInstance()->IncognitoEnableExtension(
105 profile
, CreateFakeExtensionName(index
));
108 void IncognitoDisableExtension(Profile
* profile
, int index
) {
109 return SyncExtensionHelper::GetInstance()->IncognitoDisableExtension(
110 profile
, CreateFakeExtensionName(index
));
113 bool IsIncognitoEnabled(Profile
* profile
, int index
) {
114 return SyncExtensionHelper::GetInstance()->IsIncognitoEnabled(
115 profile
, CreateFakeExtensionName(index
));
118 void InstallExtensionsPendingForSync(Profile
* profile
) {
119 SyncExtensionHelper::GetInstance()->InstallExtensionsPendingForSync(profile
);
122 std::string
CreateFakeExtensionName(int index
) {
123 return extension_name_prefix
+ base::IntToString(index
);
126 bool ExtensionNameToIndex(const std::string
& name
, int* index
) {
127 if (!base::StartsWith(name
, extension_name_prefix
,
128 base::CompareCase::SENSITIVE
) ||
129 !base::StringToInt(name
.substr(strlen(extension_name_prefix
)), index
)) {
130 LOG(WARNING
) << "Unable to convert extension name \"" << name
139 // A helper class to implement waiting for a set of profiles to have matching
141 class ExtensionsMatchChecker
: public StatusChangeChecker
,
142 public extensions::ExtensionRegistryObserver
{
144 explicit ExtensionsMatchChecker(const std::vector
<Profile
*>& profiles
);
145 ~ExtensionsMatchChecker() override
;
147 // StatusChangeChecker implementation.
148 std::string
GetDebugMessage() const override
;
149 bool IsExitConditionSatisfied() override
;
151 // extensions::ExtensionRegistryObserver implementation.
152 void OnExtensionLoaded(content::BrowserContext
* context
,
153 const extensions::Extension
* extension
) override
;
154 void OnExtensionUnloaded(
155 content::BrowserContext
* context
,
156 const extensions::Extension
* extenion
,
157 extensions::UnloadedExtensionInfo::Reason reason
) override
;
158 void OnExtensionInstalled(content::BrowserContext
* browser_context
,
159 const extensions::Extension
* extension
,
160 bool is_update
) override
;
161 void OnExtensionUninstalled(content::BrowserContext
* browser_context
,
162 const extensions::Extension
* extension
,
163 extensions::UninstallReason reason
) override
;
168 std::vector
<Profile
*> profiles_
;
169 ScopedVector
<SyncedExtensionInstaller
> synced_extension_installers_
;
172 DISALLOW_COPY_AND_ASSIGN(ExtensionsMatchChecker
);
175 ExtensionsMatchChecker::ExtensionsMatchChecker(
176 const std::vector
<Profile
*>& profiles
)
177 : profiles_(profiles
), observing_(false) {
178 DCHECK_GE(profiles_
.size(), 2U);
181 ExtensionsMatchChecker::~ExtensionsMatchChecker() {
183 for (std::vector
<Profile
*>::iterator it
= profiles_
.begin();
184 it
!= profiles_
.end();
186 extensions::ExtensionRegistry
* registry
=
187 extensions::ExtensionRegistry::Get(*it
);
188 registry
->RemoveObserver(this);
193 std::string
ExtensionsMatchChecker::GetDebugMessage() const {
194 return "Waiting for extensions to match";
197 bool ExtensionsMatchChecker::IsExitConditionSatisfied() {
198 std::vector
<Profile
*>::iterator it
= profiles_
.begin();
199 Profile
* profile0
= *it
;
201 for (; it
!= profiles_
.end(); ++it
) {
202 if (!SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(profile0
,
210 void ExtensionsMatchChecker::OnExtensionLoaded(
211 content::BrowserContext
* context
,
212 const extensions::Extension
* extension
) {
213 CheckExitCondition();
216 void ExtensionsMatchChecker::OnExtensionUnloaded(
217 content::BrowserContext
* context
,
218 const extensions::Extension
* extenion
,
219 extensions::UnloadedExtensionInfo::Reason reason
) {
220 CheckExitCondition();
223 void ExtensionsMatchChecker::OnExtensionInstalled(
224 content::BrowserContext
* browser_context
,
225 const extensions::Extension
* extension
,
227 CheckExitCondition();
230 void ExtensionsMatchChecker::OnExtensionUninstalled(
231 content::BrowserContext
* browser_context
,
232 const extensions::Extension
* extension
,
233 extensions::UninstallReason reason
) {
234 CheckExitCondition();
237 void ExtensionsMatchChecker::Wait() {
238 for (std::vector
<Profile
*>::iterator it
= profiles_
.begin();
239 it
!= profiles_
.end();
241 // Begin mocking the installation of synced extensions from the web store.
242 synced_extension_installers_
.push_back(new SyncedExtensionInstaller(*it
));
244 extensions::ExtensionRegistry
* registry
=
245 extensions::ExtensionRegistry::Get(*it
);
246 registry
->AddObserver(this);
251 if (IsExitConditionSatisfied()) {
252 DVLOG(1) << "Extensions matched without waiting";
256 DVLOG(1) << "Starting Wait: " << GetDebugMessage();
262 bool 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
));
269 ExtensionsMatchChecker
checker(profiles
);
271 return !checker
.TimedOut();
274 } // namespace extensions_helper