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 (!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
138 // A helper class to implement waiting for a set of profiles to have matching
140 class ExtensionsMatchChecker
: public StatusChangeChecker
,
141 public extensions::ExtensionRegistryObserver
{
143 explicit ExtensionsMatchChecker(const std::vector
<Profile
*>& profiles
);
144 ~ExtensionsMatchChecker() override
;
146 // StatusChangeChecker implementation.
147 std::string
GetDebugMessage() const override
;
148 bool IsExitConditionSatisfied() override
;
150 // extensions::ExtensionRegistryObserver implementation.
151 void OnExtensionLoaded(content::BrowserContext
* context
,
152 const extensions::Extension
* extension
) override
;
153 void OnExtensionUnloaded(
154 content::BrowserContext
* context
,
155 const extensions::Extension
* extenion
,
156 extensions::UnloadedExtensionInfo::Reason reason
) override
;
157 void OnExtensionInstalled(content::BrowserContext
* browser_context
,
158 const extensions::Extension
* extension
,
159 bool is_update
) override
;
160 void OnExtensionUninstalled(content::BrowserContext
* browser_context
,
161 const extensions::Extension
* extension
,
162 extensions::UninstallReason reason
) override
;
167 std::vector
<Profile
*> profiles_
;
168 ScopedVector
<SyncedExtensionInstaller
> synced_extension_installers_
;
171 DISALLOW_COPY_AND_ASSIGN(ExtensionsMatchChecker
);
174 ExtensionsMatchChecker::ExtensionsMatchChecker(
175 const std::vector
<Profile
*>& profiles
)
176 : profiles_(profiles
), observing_(false) {
177 DCHECK_GE(profiles_
.size(), 2U);
180 ExtensionsMatchChecker::~ExtensionsMatchChecker() {
182 for (std::vector
<Profile
*>::iterator it
= profiles_
.begin();
183 it
!= profiles_
.end();
185 extensions::ExtensionRegistry
* registry
=
186 extensions::ExtensionRegistry::Get(*it
);
187 registry
->RemoveObserver(this);
192 std::string
ExtensionsMatchChecker::GetDebugMessage() const {
193 return "Waiting for extensions to match";
196 bool ExtensionsMatchChecker::IsExitConditionSatisfied() {
197 std::vector
<Profile
*>::iterator it
= profiles_
.begin();
198 Profile
* profile0
= *it
;
200 for (; it
!= profiles_
.end(); ++it
) {
201 if (!SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(profile0
,
209 void ExtensionsMatchChecker::OnExtensionLoaded(
210 content::BrowserContext
* context
,
211 const extensions::Extension
* extension
) {
212 CheckExitCondition();
215 void ExtensionsMatchChecker::OnExtensionUnloaded(
216 content::BrowserContext
* context
,
217 const extensions::Extension
* extenion
,
218 extensions::UnloadedExtensionInfo::Reason reason
) {
219 CheckExitCondition();
222 void ExtensionsMatchChecker::OnExtensionInstalled(
223 content::BrowserContext
* browser_context
,
224 const extensions::Extension
* extension
,
226 CheckExitCondition();
229 void ExtensionsMatchChecker::OnExtensionUninstalled(
230 content::BrowserContext
* browser_context
,
231 const extensions::Extension
* extension
,
232 extensions::UninstallReason reason
) {
233 CheckExitCondition();
236 void ExtensionsMatchChecker::Wait() {
237 for (std::vector
<Profile
*>::iterator it
= profiles_
.begin();
238 it
!= profiles_
.end();
240 // Begin mocking the installation of synced extensions from the web store.
241 synced_extension_installers_
.push_back(new SyncedExtensionInstaller(*it
));
243 extensions::ExtensionRegistry
* registry
=
244 extensions::ExtensionRegistry::Get(*it
);
245 registry
->AddObserver(this);
250 if (IsExitConditionSatisfied()) {
251 DVLOG(1) << "Extensions matched without waiting";
255 DVLOG(1) << "Starting Wait: " << GetDebugMessage();
261 bool AwaitAllProfilesHaveSameExtensionsAsVerifier() {
262 std::vector
<Profile
*> profiles
;
263 profiles
.push_back(test()->verifier());
264 for (int i
= 0; i
< test()->num_clients(); ++i
) {
265 profiles
.push_back(test()->GetProfile(i
));
268 ExtensionsMatchChecker
checker(profiles
);
270 return !checker
.TimedOut();
273 } // namespace extensions_helper