9c233748283fccf549238e05f92c53cd6cdc7706
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / test / integration / extensions_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/extensions_helper.h"
6
7 #include <cstring>
8
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"
20
21 using sync_datatype_helper::test;
22
23 namespace extensions_helper {
24
25 const char extension_name_prefix[] = "fakeextension";
26
27 bool HasSameExtensionsAsVerifier(int index) {
28   return SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(
29       test()->GetProfile(index), test()->verifier());
30 }
31
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.";
37       return false;
38     }
39   }
40   return true;
41 }
42
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"
48                                        " profile 0.";
49       return false;
50     }
51   }
52   return true;
53 }
54
55
56 std::string InstallExtension(Profile* profile, int index) {
57   return SyncExtensionHelper::GetInstance()->InstallExtension(
58       profile,
59       CreateFakeExtensionName(index),
60       extensions::Manifest::TYPE_EXTENSION);
61 }
62
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);
67 }
68
69 void UninstallExtension(Profile* profile, int index) {
70   return SyncExtensionHelper::GetInstance()->UninstallExtension(
71       profile, CreateFakeExtensionName(index));
72 }
73
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) {
80     int index;
81     if (ExtensionNameToIndex(*it, &index)) {
82       indices.push_back(index);
83     }
84   }
85   return indices;
86 }
87
88 void EnableExtension(Profile* profile, int index) {
89   return SyncExtensionHelper::GetInstance()->EnableExtension(
90       profile, CreateFakeExtensionName(index));
91 }
92
93 void DisableExtension(Profile* profile, int index) {
94   return SyncExtensionHelper::GetInstance()->DisableExtension(
95       profile, CreateFakeExtensionName(index));
96 }
97
98 bool IsExtensionEnabled(Profile* profile, int index) {
99   return SyncExtensionHelper::GetInstance()->IsExtensionEnabled(
100       profile, CreateFakeExtensionName(index));
101 }
102
103 void IncognitoEnableExtension(Profile* profile, int index) {
104   return SyncExtensionHelper::GetInstance()->IncognitoEnableExtension(
105       profile, CreateFakeExtensionName(index));
106 }
107
108 void IncognitoDisableExtension(Profile* profile, int index) {
109   return SyncExtensionHelper::GetInstance()->IncognitoDisableExtension(
110       profile, CreateFakeExtensionName(index));
111 }
112
113 bool IsIncognitoEnabled(Profile* profile, int index) {
114   return SyncExtensionHelper::GetInstance()->IsIncognitoEnabled(
115       profile, CreateFakeExtensionName(index));
116 }
117
118 void InstallExtensionsPendingForSync(Profile* profile) {
119   SyncExtensionHelper::GetInstance()->InstallExtensionsPendingForSync(profile);
120 }
121
122 std::string CreateFakeExtensionName(int index) {
123   return extension_name_prefix + base::IntToString(index);
124 }
125
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
130                  << "\" to index";
131     return false;
132   }
133   return true;
134 }
135
136 namespace {
137
138 // A helper class to implement waiting for a set of profiles to have matching
139 // extensions lists.
140 class ExtensionsMatchChecker : public StatusChangeChecker,
141                                public extensions::ExtensionRegistryObserver {
142  public:
143   explicit ExtensionsMatchChecker(const std::vector<Profile*>& profiles);
144   ~ExtensionsMatchChecker() override;
145
146   // StatusChangeChecker implementation.
147   std::string GetDebugMessage() const override;
148   bool IsExitConditionSatisfied() override;
149
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;
163
164   void Wait();
165
166  private:
167   std::vector<Profile*> profiles_;
168   ScopedVector<SyncedExtensionInstaller> synced_extension_installers_;
169   bool observing_;
170
171   DISALLOW_COPY_AND_ASSIGN(ExtensionsMatchChecker);
172 };
173
174 ExtensionsMatchChecker::ExtensionsMatchChecker(
175     const std::vector<Profile*>& profiles)
176     : profiles_(profiles), observing_(false) {
177   DCHECK_GE(profiles_.size(), 2U);
178 }
179
180 ExtensionsMatchChecker::~ExtensionsMatchChecker() {
181   if (observing_) {
182     for (std::vector<Profile*>::iterator it = profiles_.begin();
183          it != profiles_.end();
184          ++it) {
185       extensions::ExtensionRegistry* registry =
186           extensions::ExtensionRegistry::Get(*it);
187       registry->RemoveObserver(this);
188     }
189   }
190 }
191
192 std::string ExtensionsMatchChecker::GetDebugMessage() const {
193   return "Waiting for extensions to match";
194 }
195
196 bool ExtensionsMatchChecker::IsExitConditionSatisfied() {
197   std::vector<Profile*>::iterator it = profiles_.begin();
198   Profile* profile0 = *it;
199   ++it;
200   for (; it != profiles_.end(); ++it) {
201     if (!SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(profile0,
202                                                                   *it)) {
203       return false;
204     }
205   }
206   return true;
207 }
208
209 void ExtensionsMatchChecker::OnExtensionLoaded(
210     content::BrowserContext* context,
211     const extensions::Extension* extension) {
212   CheckExitCondition();
213 }
214
215 void ExtensionsMatchChecker::OnExtensionUnloaded(
216     content::BrowserContext* context,
217     const extensions::Extension* extenion,
218     extensions::UnloadedExtensionInfo::Reason reason) {
219   CheckExitCondition();
220 }
221
222 void ExtensionsMatchChecker::OnExtensionInstalled(
223     content::BrowserContext* browser_context,
224     const extensions::Extension* extension,
225     bool is_update) {
226   CheckExitCondition();
227 }
228
229 void ExtensionsMatchChecker::OnExtensionUninstalled(
230     content::BrowserContext* browser_context,
231     const extensions::Extension* extension,
232     extensions::UninstallReason reason) {
233   CheckExitCondition();
234 }
235
236 void ExtensionsMatchChecker::Wait() {
237   for (std::vector<Profile*>::iterator it = profiles_.begin();
238        it != profiles_.end();
239        ++it) {
240     // Begin mocking the installation of synced extensions from the web store.
241     synced_extension_installers_.push_back(new SyncedExtensionInstaller(*it));
242
243     extensions::ExtensionRegistry* registry =
244         extensions::ExtensionRegistry::Get(*it);
245     registry->AddObserver(this);
246   }
247
248   observing_ = true;
249
250   if (IsExitConditionSatisfied()) {
251     DVLOG(1) << "Extensions matched without waiting";
252     return;
253   }
254
255   DVLOG(1) << "Starting Wait: " << GetDebugMessage();
256   StartBlockingWait();
257 }
258
259 }  // namespace
260
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));
266   }
267
268   ExtensionsMatchChecker checker(profiles);
269   checker.Wait();
270   return !checker.TimedOut();
271 }
272
273 }  // namespace extensions_helper