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/apps_helper.h"
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"
25 using sync_datatype_helper::test
;
29 std::string
CreateFakeAppName(int index
) {
30 return "fakeapp" + base::IntToString(index
);
35 namespace apps_helper
{
37 bool HasSameAppsAsVerifier(int index
) {
38 return SyncAppHelper::GetInstance()->AppStatesMatch(
39 test()->GetProfile(index
), test()->verifier());
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"
53 std::string
InstallApp(Profile
* profile
, int index
) {
54 return SyncExtensionHelper::GetInstance()->InstallExtension(
56 CreateFakeAppName(index
),
57 extensions::Manifest::TYPE_HOSTED_APP
);
60 std::string
InstallPlatformApp(Profile
* profile
, int index
) {
61 return SyncExtensionHelper::GetInstance()->InstallExtension(
63 CreateFakeAppName(index
),
64 extensions::Manifest::TYPE_PLATFORM_APP
);
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
);
73 void UninstallApp(Profile
* profile
, int index
) {
74 return SyncExtensionHelper::GetInstance()->UninstallExtension(
75 profile
, CreateFakeAppName(index
));
78 void EnableApp(Profile
* profile
, int index
) {
79 return SyncExtensionHelper::GetInstance()->EnableExtension(
80 profile
, CreateFakeAppName(index
));
83 void DisableApp(Profile
* profile
, int index
) {
84 return SyncExtensionHelper::GetInstance()->DisableExtension(
85 profile
, CreateFakeAppName(index
));
88 void IncognitoEnableApp(Profile
* profile
, int index
) {
89 return SyncExtensionHelper::GetInstance()->IncognitoEnableExtension(
90 profile
, CreateFakeAppName(index
));
93 void IncognitoDisableApp(Profile
* profile
, int index
) {
94 return SyncExtensionHelper::GetInstance()->IncognitoDisableExtension(
95 profile
, CreateFakeAppName(index
));
98 void InstallAppsPendingForSync(Profile
* profile
) {
99 SyncExtensionHelper::GetInstance()->InstallExtensionsPendingForSync(profile
);
102 syncer::StringOrdinal
GetPageOrdinalForApp(Profile
* profile
,
104 return SyncAppHelper::GetInstance()->GetPageOrdinalForApp(
105 profile
, CreateFakeAppName(app_index
));
108 void SetPageOrdinalForApp(Profile
* profile
,
110 const syncer::StringOrdinal
& page_ordinal
) {
111 SyncAppHelper::GetInstance()->SetPageOrdinalForApp(
112 profile
, CreateFakeAppName(app_index
), page_ordinal
);
115 syncer::StringOrdinal
GetAppLaunchOrdinalForApp(Profile
* profile
,
117 return SyncAppHelper::GetInstance()->GetAppLaunchOrdinalForApp(
118 profile
, CreateFakeAppName(app_index
));
121 void SetAppLaunchOrdinalForApp(
124 const syncer::StringOrdinal
& app_launch_ordinal
) {
125 SyncAppHelper::GetInstance()->SetAppLaunchOrdinalForApp(
126 profile
, CreateFakeAppName(app_index
), app_launch_ordinal
);
129 void CopyNTPOrdinals(Profile
* source
, Profile
* destination
, int index
) {
130 SetPageOrdinalForApp(destination
, index
, GetPageOrdinalForApp(source
, index
));
131 SetAppLaunchOrdinalForApp(
132 destination
, index
, GetAppLaunchOrdinalForApp(source
, index
));
135 void FixNTPOrdinalCollisions(Profile
* profile
) {
136 SyncAppHelper::GetInstance()->FixNTPOrdinalCollisions(profile
);
141 // A helper class to implement waiting for a set of profiles to have matching
143 class AppsMatchChecker
: public StatusChangeChecker
,
144 public extensions::ExtensionRegistryObserver
,
145 public extensions::ExtensionPrefsObserver
,
146 public content::NotificationObserver
{
148 explicit AppsMatchChecker(const std::vector
<Profile
*>& profiles
);
149 ~AppsMatchChecker() override
;
151 // StatusChangeChecker implementation.
152 std::string
GetDebugMessage() const override
;
153 bool IsExitConditionSatisfied() override
;
155 // extensions::ExtensionRegistryObserver implementation.
156 void OnExtensionLoaded(content::BrowserContext
* context
,
157 const extensions::Extension
* extension
) override
;
158 void OnExtensionUnloaded(
159 content::BrowserContext
* context
,
160 const extensions::Extension
* extenion
,
161 extensions::UnloadedExtensionInfo::Reason reason
) override
;
162 void OnExtensionInstalled(content::BrowserContext
* browser_context
,
163 const extensions::Extension
* extension
,
164 bool is_update
) override
;
165 void OnExtensionUninstalled(content::BrowserContext
* browser_context
,
166 const extensions::Extension
* extension
,
167 extensions::UninstallReason reason
) override
;
169 // extensions::ExtensionPrefsObserver implementation.
170 void OnExtensionDisableReasonsChanged(const std::string
& extension_id
,
171 int disabled_reasons
) override
;
172 void OnExtensionRegistered(const std::string
& extension_id
,
173 const base::Time
& install_time
,
174 bool is_enabled
) override
;
175 void OnExtensionPrefsLoaded(const std::string
& extension_id
,
176 const extensions::ExtensionPrefs
* prefs
) override
;
177 void OnExtensionPrefsDeleted(const std::string
& extension_id
) override
;
178 void OnExtensionStateChanged(const std::string
& extension_id
,
179 bool state
) override
;
181 // Implementation of content::NotificationObserver.
182 void Observe(int type
,
183 const content::NotificationSource
& source
,
184 const content::NotificationDetails
& details
) override
;
189 std::vector
<Profile
*> profiles_
;
192 content::NotificationRegistrar registrar_
;
194 // This installs apps, too.
195 ScopedVector
<SyncedExtensionInstaller
> synced_extension_installers_
;
197 DISALLOW_COPY_AND_ASSIGN(AppsMatchChecker
);
200 AppsMatchChecker::AppsMatchChecker(const std::vector
<Profile
*>& profiles
)
201 : profiles_(profiles
), observing_(false) {
202 DCHECK_GE(profiles_
.size(), 2U);
205 AppsMatchChecker::~AppsMatchChecker() {
207 for (std::vector
<Profile
*>::iterator it
= profiles_
.begin();
208 it
!= profiles_
.end();
210 extensions::ExtensionRegistry
* registry
=
211 extensions::ExtensionRegistry::Get(*it
);
212 registry
->RemoveObserver(this);
213 extensions::ExtensionPrefs
* prefs
= extensions::ExtensionPrefs::Get(*it
);
214 prefs
->RemoveObserver(this);
219 std::string
AppsMatchChecker::GetDebugMessage() const {
220 return "Waiting for apps to match";
223 bool AppsMatchChecker::IsExitConditionSatisfied() {
224 std::vector
<Profile
*>::iterator it
= profiles_
.begin();
225 Profile
* profile0
= *it
;
227 for (; it
!= profiles_
.end(); ++it
) {
228 if (!SyncAppHelper::GetInstance()->AppStatesMatch(profile0
, *it
)) {
235 void AppsMatchChecker::OnExtensionLoaded(
236 content::BrowserContext
* context
,
237 const extensions::Extension
* extension
) {
238 CheckExitCondition();
241 void AppsMatchChecker::OnExtensionUnloaded(
242 content::BrowserContext
* context
,
243 const extensions::Extension
* extenion
,
244 extensions::UnloadedExtensionInfo::Reason reason
) {
245 CheckExitCondition();
248 void AppsMatchChecker::OnExtensionInstalled(
249 content::BrowserContext
* browser_context
,
250 const extensions::Extension
* extension
,
252 CheckExitCondition();
255 void AppsMatchChecker::OnExtensionUninstalled(
256 content::BrowserContext
* browser_context
,
257 const extensions::Extension
* extension
,
258 extensions::UninstallReason reason
) {
259 CheckExitCondition();
262 void AppsMatchChecker::OnExtensionDisableReasonsChanged(
263 const std::string
& extension_id
,
264 int disabled_reasons
) {
265 CheckExitCondition();
268 void AppsMatchChecker::OnExtensionRegistered(const std::string
& extension_id
,
269 const base::Time
& install_time
,
271 CheckExitCondition();
274 void AppsMatchChecker::OnExtensionPrefsLoaded(
275 const std::string
& extension_id
,
276 const extensions::ExtensionPrefs
* prefs
) {
277 CheckExitCondition();
280 void AppsMatchChecker::OnExtensionPrefsDeleted(
281 const std::string
& extension_id
) {
282 CheckExitCondition();
285 void AppsMatchChecker::OnExtensionStateChanged(const std::string
& extension_id
,
287 CheckExitCondition();
290 void AppsMatchChecker::Observe(int type
,
291 const content::NotificationSource
& source
,
292 const content::NotificationDetails
& details
) {
293 DCHECK_EQ(chrome::NOTIFICATION_APP_LAUNCHER_REORDERED
, type
);
294 CheckExitCondition();
297 void AppsMatchChecker::Wait() {
298 for (std::vector
<Profile
*>::iterator it
= profiles_
.begin();
299 it
!= profiles_
.end();
301 // Begin mocking the installation of synced extensions from the web store.
302 synced_extension_installers_
.push_back(new SyncedExtensionInstaller(*it
));
304 // Register as an observer of ExtensionsRegistry to receive notifications of
305 // big events, like installs and uninstalls.
306 extensions::ExtensionRegistry
* registry
=
307 extensions::ExtensionRegistry::Get(*it
);
308 registry
->AddObserver(this);
310 // Register for ExtensionPrefs events, too, so we can get notifications
312 // smaller but still syncable events, like launch type changes.
313 extensions::ExtensionPrefs
* prefs
= extensions::ExtensionPrefs::Get(*it
);
314 prefs
->AddObserver(this);
318 chrome::NOTIFICATION_APP_LAUNCHER_REORDERED
,
319 content::NotificationService::AllSources());
323 if (IsExitConditionSatisfied()) {
324 DVLOG(1) << "Apps matched without waiting";
328 DVLOG(1) << "Starting Wait: " << GetDebugMessage();
334 bool AwaitAllProfilesHaveSameApps() {
335 std::vector
<Profile
*> profiles
;
336 if (test()->use_verifier()) {
337 profiles
.push_back(test()->verifier());
339 for (int i
= 0; i
< test()->num_clients(); ++i
) {
340 profiles
.push_back(test()->GetProfile(i
));
343 AppsMatchChecker
checker(profiles
);
345 return !checker
.TimedOut();
348 } // namespace apps_helper