Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / test / integration / apps_helper.cc
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/apps_helper.h"
6
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"
24
25 using sync_datatype_helper::test;
26
27 namespace {
28
29 std::string CreateFakeAppName(int index) {
30   return "fakeapp" + base::IntToString(index);
31 }
32
33 }  // namespace
34
35 namespace apps_helper {
36
37 bool HasSameAppsAsVerifier(int index) {
38   return SyncAppHelper::GetInstance()->AppStatesMatch(
39       test()->GetProfile(index), test()->verifier());
40 }
41
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"
46                                      " verifier profile.";
47       return false;
48     }
49   }
50   return true;
51 }
52
53 std::string InstallApp(Profile* profile, int index) {
54   return SyncExtensionHelper::GetInstance()->InstallExtension(
55       profile,
56       CreateFakeAppName(index),
57       extensions::Manifest::TYPE_HOSTED_APP);
58 }
59
60 std::string InstallPlatformApp(Profile* profile, int index) {
61   return SyncExtensionHelper::GetInstance()->InstallExtension(
62       profile,
63       CreateFakeAppName(index),
64       extensions::Manifest::TYPE_PLATFORM_APP);
65 }
66
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);
71 }
72
73 void UninstallApp(Profile* profile, int index) {
74   return SyncExtensionHelper::GetInstance()->UninstallExtension(
75       profile, CreateFakeAppName(index));
76 }
77
78 void EnableApp(Profile* profile, int index) {
79   return SyncExtensionHelper::GetInstance()->EnableExtension(
80       profile, CreateFakeAppName(index));
81 }
82
83 void DisableApp(Profile* profile, int index) {
84   return SyncExtensionHelper::GetInstance()->DisableExtension(
85       profile, CreateFakeAppName(index));
86 }
87
88 void IncognitoEnableApp(Profile* profile, int index) {
89   return SyncExtensionHelper::GetInstance()->IncognitoEnableExtension(
90       profile, CreateFakeAppName(index));
91 }
92
93 void IncognitoDisableApp(Profile* profile, int index) {
94   return SyncExtensionHelper::GetInstance()->IncognitoDisableExtension(
95       profile, CreateFakeAppName(index));
96 }
97
98 void InstallAppsPendingForSync(Profile* profile) {
99   SyncExtensionHelper::GetInstance()->InstallExtensionsPendingForSync(profile);
100 }
101
102 syncer::StringOrdinal GetPageOrdinalForApp(Profile* profile,
103                                            int app_index) {
104   return SyncAppHelper::GetInstance()->GetPageOrdinalForApp(
105       profile, CreateFakeAppName(app_index));
106 }
107
108 void SetPageOrdinalForApp(Profile* profile,
109                           int app_index,
110                           const syncer::StringOrdinal& page_ordinal) {
111   SyncAppHelper::GetInstance()->SetPageOrdinalForApp(
112       profile, CreateFakeAppName(app_index), page_ordinal);
113 }
114
115 syncer::StringOrdinal GetAppLaunchOrdinalForApp(Profile* profile,
116                                                 int app_index) {
117   return SyncAppHelper::GetInstance()->GetAppLaunchOrdinalForApp(
118       profile, CreateFakeAppName(app_index));
119 }
120
121 void SetAppLaunchOrdinalForApp(
122     Profile* profile,
123     int app_index,
124     const syncer::StringOrdinal& app_launch_ordinal) {
125   SyncAppHelper::GetInstance()->SetAppLaunchOrdinalForApp(
126       profile, CreateFakeAppName(app_index), app_launch_ordinal);
127 }
128
129 void CopyNTPOrdinals(Profile* source, Profile* destination, int index) {
130   SetPageOrdinalForApp(destination, index, GetPageOrdinalForApp(source, index));
131   SetAppLaunchOrdinalForApp(
132       destination, index, GetAppLaunchOrdinalForApp(source, index));
133 }
134
135 void FixNTPOrdinalCollisions(Profile* profile) {
136   SyncAppHelper::GetInstance()->FixNTPOrdinalCollisions(profile);
137 }
138
139 namespace {
140
141 // A helper class to implement waiting for a set of profiles to have matching
142 // extensions lists.
143 class AppsMatchChecker : public StatusChangeChecker,
144                          public extensions::ExtensionRegistryObserver,
145                          public extensions::ExtensionPrefsObserver,
146                          public content::NotificationObserver {
147  public:
148   explicit AppsMatchChecker(const std::vector<Profile*>& profiles);
149   virtual ~AppsMatchChecker();
150
151   // StatusChangeChecker implementation.
152   virtual std::string GetDebugMessage() const OVERRIDE;
153   virtual bool IsExitConditionSatisfied() OVERRIDE;
154
155   // extensions::ExtensionRegistryObserver implementation.
156   virtual void OnExtensionLoaded(
157       content::BrowserContext* context,
158       const extensions::Extension* extension) OVERRIDE;
159   virtual void OnExtensionUnloaded(
160       content::BrowserContext* context,
161       const extensions::Extension* extenion,
162       extensions::UnloadedExtensionInfo::Reason reason) OVERRIDE;
163   virtual void OnExtensionInstalled(content::BrowserContext* browser_context,
164                                     const extensions::Extension* extension,
165                                     bool is_update) OVERRIDE;
166   virtual void OnExtensionUninstalled(
167       content::BrowserContext* browser_context,
168       const extensions::Extension* extension,
169       extensions::UninstallReason reason) OVERRIDE;
170
171   // extensions::ExtensionPrefsObserver implementation.
172   virtual void OnExtensionDisableReasonsChanged(const std::string& extension_id,
173                                                 int disabled_reasons) OVERRIDE;
174   virtual void OnExtensionRegistered(const std::string& extension_id,
175                                      const base::Time& install_time,
176                                      bool is_enabled) OVERRIDE;
177   virtual void OnExtensionPrefsLoaded(
178       const std::string& extension_id,
179       const extensions::ExtensionPrefs* prefs) OVERRIDE;
180   virtual void OnExtensionPrefsDeleted(
181       const std::string& extension_id) OVERRIDE;
182   virtual void OnExtensionStateChanged(const std::string& extension_id,
183                                        bool state) OVERRIDE;
184
185   // Implementation of content::NotificationObserver.
186   virtual void Observe(int type,
187                        const content::NotificationSource& source,
188                        const content::NotificationDetails& details) OVERRIDE;
189
190   void Wait();
191
192  private:
193   std::vector<Profile*> profiles_;
194   bool observing_;
195
196   content::NotificationRegistrar registrar_;
197
198   // This installs apps, too.
199   ScopedVector<SyncedExtensionInstaller> synced_extension_installers_;
200
201   DISALLOW_COPY_AND_ASSIGN(AppsMatchChecker);
202 };
203
204 AppsMatchChecker::AppsMatchChecker(const std::vector<Profile*>& profiles)
205     : profiles_(profiles), observing_(false) {
206   DCHECK_GE(profiles_.size(), 2U);
207 }
208
209 AppsMatchChecker::~AppsMatchChecker() {
210   if (observing_) {
211     for (std::vector<Profile*>::iterator it = profiles_.begin();
212          it != profiles_.end();
213          ++it) {
214       extensions::ExtensionRegistry* registry =
215           extensions::ExtensionRegistry::Get(*it);
216       registry->RemoveObserver(this);
217       extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(*it);
218       prefs->RemoveObserver(this);
219     }
220   }
221 }
222
223 std::string AppsMatchChecker::GetDebugMessage() const {
224   return "Waiting for apps to match";
225 }
226
227 bool AppsMatchChecker::IsExitConditionSatisfied() {
228   std::vector<Profile*>::iterator it = profiles_.begin();
229   Profile* profile0 = *it;
230   ++it;
231   for (; it != profiles_.end(); ++it) {
232     if (!SyncAppHelper::GetInstance()->AppStatesMatch(profile0, *it)) {
233       return false;
234     }
235   }
236   return true;
237 }
238
239 void AppsMatchChecker::OnExtensionLoaded(
240     content::BrowserContext* context,
241     const extensions::Extension* extension) {
242   CheckExitCondition();
243 }
244
245 void AppsMatchChecker::OnExtensionUnloaded(
246     content::BrowserContext* context,
247     const extensions::Extension* extenion,
248     extensions::UnloadedExtensionInfo::Reason reason) {
249   CheckExitCondition();
250 }
251
252 void AppsMatchChecker::OnExtensionInstalled(
253     content::BrowserContext* browser_context,
254     const extensions::Extension* extension,
255     bool is_update) {
256   CheckExitCondition();
257 }
258
259 void AppsMatchChecker::OnExtensionUninstalled(
260     content::BrowserContext* browser_context,
261     const extensions::Extension* extension,
262     extensions::UninstallReason reason) {
263   CheckExitCondition();
264 }
265
266 void AppsMatchChecker::OnExtensionDisableReasonsChanged(
267     const std::string& extension_id,
268     int disabled_reasons) {
269   CheckExitCondition();
270 }
271
272 void AppsMatchChecker::OnExtensionRegistered(const std::string& extension_id,
273                                              const base::Time& install_time,
274                                              bool is_enabled) {
275   CheckExitCondition();
276 }
277
278 void AppsMatchChecker::OnExtensionPrefsLoaded(
279     const std::string& extension_id,
280     const extensions::ExtensionPrefs* prefs) {
281   CheckExitCondition();
282 }
283
284 void AppsMatchChecker::OnExtensionPrefsDeleted(
285     const std::string& extension_id) {
286   CheckExitCondition();
287 }
288
289 void AppsMatchChecker::OnExtensionStateChanged(const std::string& extension_id,
290                                                bool state) {
291   CheckExitCondition();
292 }
293
294 void AppsMatchChecker::Observe(int type,
295                                const content::NotificationSource& source,
296                                const content::NotificationDetails& details) {
297   DCHECK_EQ(chrome::NOTIFICATION_APP_LAUNCHER_REORDERED, type);
298   CheckExitCondition();
299 }
300
301 void AppsMatchChecker::Wait() {
302   for (std::vector<Profile*>::iterator it = profiles_.begin();
303        it != profiles_.end();
304        ++it) {
305     // Begin mocking the installation of synced extensions from the web store.
306     synced_extension_installers_.push_back(new SyncedExtensionInstaller(*it));
307
308     // Register as an observer of ExtensionsRegistry to receive notifications of
309     // big events, like installs and uninstalls.
310     extensions::ExtensionRegistry* registry =
311         extensions::ExtensionRegistry::Get(*it);
312     registry->AddObserver(this);
313
314     // Register for ExtensionPrefs events, too, so we can get notifications
315     // about
316     // smaller but still syncable events, like launch type changes.
317     extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(*it);
318     prefs->AddObserver(this);
319   }
320
321   registrar_.Add(this,
322                  chrome::NOTIFICATION_APP_LAUNCHER_REORDERED,
323                  content::NotificationService::AllSources());
324
325   observing_ = true;
326
327   if (IsExitConditionSatisfied()) {
328     DVLOG(1) << "Apps matched without waiting";
329     return;
330   }
331
332   DVLOG(1) << "Starting Wait: " << GetDebugMessage();
333   StartBlockingWait();
334 }
335
336 }  // namespace
337
338 bool AwaitAllProfilesHaveSameAppsAsVerifier() {
339   std::vector<Profile*> profiles;
340   profiles.push_back(test()->verifier());
341   for (int i = 0; i < test()->num_clients(); ++i) {
342     profiles.push_back(test()->GetProfile(i));
343   }
344
345   AppsMatchChecker checker(profiles);
346   checker.Wait();
347   return !checker.TimedOut();
348 }
349
350 }  // namespace apps_helper