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"
7 #include "base/logging.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/sync/test/integration/status_change_checker.h"
11 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
12 #include "chrome/browser/sync/test/integration/sync_extension_helper.h"
13 #include "chrome/browser/sync/test/integration/sync_extension_installer.h"
14 #include "content/public/browser/notification_observer.h"
15 #include "content/public/browser/notification_registrar.h"
16 #include "content/public/browser/notification_source.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 // Returns a unique extension name based in the integer |index|.
26 std::string
CreateFakeExtensionName(int index
) {
27 return SyncExtensionHelper::GetInstance()->CreateFakeExtensionName(index
);
30 bool HasSameExtensions(int index1
, int index2
) {
31 return SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(
32 test()->GetProfile(index1
), test()->GetProfile(index2
));
35 bool HasSameExtensionsAsVerifier(int index
) {
36 return SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(
37 test()->GetProfile(index
), test()->verifier());
40 bool AllProfilesHaveSameExtensionsAsVerifier() {
41 for (int i
= 0; i
< test()->num_clients(); ++i
) {
42 if (!HasSameExtensionsAsVerifier(i
)) {
43 LOG(ERROR
) << "Profile " << i
<< " doesn't have the same extensions as"
44 " the verifier profile.";
51 bool AllProfilesHaveSameExtensions() {
52 for (int i
= 1; i
< test()->num_clients(); ++i
) {
53 if (!SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(
54 test()->GetProfile(0), test()->GetProfile(i
))) {
55 LOG(ERROR
) << "Profile " << i
<< " doesnt have the same extensions as"
64 std::string
InstallExtension(Profile
* profile
, int index
) {
65 return SyncExtensionHelper::GetInstance()->InstallExtension(
67 CreateFakeExtensionName(index
),
68 extensions::Manifest::TYPE_EXTENSION
);
71 std::string
InstallExtensionForAllProfiles(int index
) {
72 for (int i
= 0; i
< test()->num_clients(); ++i
)
73 InstallExtension(test()->GetProfile(i
), index
);
74 return InstallExtension(test()->verifier(), index
);
77 void UninstallExtension(Profile
* profile
, int index
) {
78 return SyncExtensionHelper::GetInstance()->UninstallExtension(
79 profile
, CreateFakeExtensionName(index
));
82 std::vector
<int> GetInstalledExtensions(Profile
* profile
) {
83 std::vector
<int> indices
;
84 std::vector
<std::string
> names
=
85 SyncExtensionHelper::GetInstance()->GetInstalledExtensionNames(profile
);
86 for (std::vector
<std::string
>::const_iterator it
= names
.begin();
87 it
!= names
.end(); ++it
) {
89 if (SyncExtensionHelper::GetInstance()->ExtensionNameToIndex(*it
, &index
)) {
90 indices
.push_back(index
);
96 void EnableExtension(Profile
* profile
, int index
) {
97 return SyncExtensionHelper::GetInstance()->EnableExtension(
98 profile
, CreateFakeExtensionName(index
));
101 void DisableExtension(Profile
* profile
, int index
) {
102 return SyncExtensionHelper::GetInstance()->DisableExtension(
103 profile
, CreateFakeExtensionName(index
));
106 bool IsExtensionEnabled(Profile
* profile
, int index
) {
107 return SyncExtensionHelper::GetInstance()->IsExtensionEnabled(
108 profile
, CreateFakeExtensionName(index
));
111 void IncognitoEnableExtension(Profile
* profile
, int index
) {
112 return SyncExtensionHelper::GetInstance()->IncognitoEnableExtension(
113 profile
, CreateFakeExtensionName(index
));
116 void IncognitoDisableExtension(Profile
* profile
, int index
) {
117 return SyncExtensionHelper::GetInstance()->IncognitoDisableExtension(
118 profile
, CreateFakeExtensionName(index
));
121 bool IsIncognitoEnabled(Profile
* profile
, int index
) {
122 return SyncExtensionHelper::GetInstance()->IsIncognitoEnabled(
123 profile
, CreateFakeExtensionName(index
));
126 void InstallExtensionsPendingForSync(Profile
* profile
) {
127 SyncExtensionHelper::GetInstance()->InstallExtensionsPendingForSync(profile
);
132 // A helper class to implement waiting for a set of profiles to have matching
133 // extensions lists. It waits for calls on both interfaces:
134 // ExtensionRegistryObserver and NotificationObserver. Observing
135 // NOTIFICATION_EXTENSION_UPDATING_STARTED notification is needed for tests
136 // against local server because in such tests extensions are not installed and
137 // ExtensionRegistryObserver methods are not called.
138 class ExtensionsMatchChecker
: public StatusChangeChecker
,
139 public extensions::ExtensionRegistryObserver
,
140 public content::NotificationObserver
{
142 explicit ExtensionsMatchChecker(const std::vector
<Profile
*>& profiles
);
143 ~ExtensionsMatchChecker() override
;
145 // StatusChangeChecker implementation.
146 std::string
GetDebugMessage() const override
;
147 bool IsExitConditionSatisfied() override
;
149 // extensions::ExtensionRegistryObserver implementation.
150 void OnExtensionLoaded(content::BrowserContext
* context
,
151 const extensions::Extension
* extension
) override
;
152 void OnExtensionUnloaded(
153 content::BrowserContext
* context
,
154 const extensions::Extension
* extenion
,
155 extensions::UnloadedExtensionInfo::Reason reason
) override
;
156 void OnExtensionInstalled(content::BrowserContext
* browser_context
,
157 const extensions::Extension
* extension
,
158 bool is_update
) override
;
159 void OnExtensionUninstalled(content::BrowserContext
* browser_context
,
160 const extensions::Extension
* extension
,
161 extensions::UninstallReason reason
) override
;
163 // content::NotificationObserver implementation.
164 void Observe(int type
,
165 const content::NotificationSource
& source
,
166 const content::NotificationDetails
& details
) override
;
171 std::vector
<Profile
*> profiles_
;
172 ScopedVector
<SyncedExtensionInstaller
> synced_extension_installers_
;
173 content::NotificationRegistrar registrar_
;
176 DISALLOW_COPY_AND_ASSIGN(ExtensionsMatchChecker
);
179 ExtensionsMatchChecker::ExtensionsMatchChecker(
180 const std::vector
<Profile
*>& profiles
)
181 : profiles_(profiles
), observing_(false) {
182 DCHECK_GE(profiles_
.size(), 2U);
185 ExtensionsMatchChecker::~ExtensionsMatchChecker() {
187 for (std::vector
<Profile
*>::iterator it
= profiles_
.begin();
188 it
!= profiles_
.end();
190 extensions::ExtensionRegistry
* registry
=
191 extensions::ExtensionRegistry::Get(*it
);
192 registry
->RemoveObserver(this);
197 std::string
ExtensionsMatchChecker::GetDebugMessage() const {
198 return "Waiting for extensions to match";
201 bool ExtensionsMatchChecker::IsExitConditionSatisfied() {
202 std::vector
<Profile
*>::iterator it
= profiles_
.begin();
203 Profile
* profile0
= *it
;
205 for (; it
!= profiles_
.end(); ++it
) {
206 if (!SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(profile0
,
214 void ExtensionsMatchChecker::OnExtensionLoaded(
215 content::BrowserContext
* context
,
216 const extensions::Extension
* extension
) {
217 CheckExitCondition();
220 void ExtensionsMatchChecker::OnExtensionUnloaded(
221 content::BrowserContext
* context
,
222 const extensions::Extension
* extenion
,
223 extensions::UnloadedExtensionInfo::Reason reason
) {
224 CheckExitCondition();
227 void ExtensionsMatchChecker::OnExtensionInstalled(
228 content::BrowserContext
* browser_context
,
229 const extensions::Extension
* extension
,
231 CheckExitCondition();
234 void ExtensionsMatchChecker::OnExtensionUninstalled(
235 content::BrowserContext
* browser_context
,
236 const extensions::Extension
* extension
,
237 extensions::UninstallReason reason
) {
238 CheckExitCondition();
241 void ExtensionsMatchChecker::Observe(
243 const content::NotificationSource
& source
,
244 const content::NotificationDetails
& details
) {
245 DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_UPDATING_STARTED
, type
);
246 CheckExitCondition();
249 void ExtensionsMatchChecker::Wait() {
250 for (std::vector
<Profile
*>::iterator it
= profiles_
.begin();
251 it
!= profiles_
.end();
253 // Begin mocking the installation of synced extensions from the web store.
254 synced_extension_installers_
.push_back(new SyncedExtensionInstaller(*it
));
256 extensions::ExtensionRegistry
* registry
=
257 extensions::ExtensionRegistry::Get(*it
);
258 registry
->AddObserver(this);
259 registrar_
.Add(this, extensions::NOTIFICATION_EXTENSION_UPDATING_STARTED
,
260 content::Source
<Profile
>(*it
));
265 if (IsExitConditionSatisfied()) {
266 DVLOG(1) << "Extensions matched without waiting";
270 DVLOG(1) << "Starting Wait: " << GetDebugMessage();
276 bool AwaitAllProfilesHaveSameExtensions() {
277 std::vector
<Profile
*> profiles
;
278 for (int i
= 0; i
< test()->num_clients(); ++i
) {
279 profiles
.push_back(test()->GetProfile(i
));
282 ExtensionsMatchChecker
checker(profiles
);
284 return !checker
.TimedOut();
287 } // namespace extensions_helper