• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
HasSameExtensionsAsVerifier(int index)27 bool HasSameExtensionsAsVerifier(int index) {
28   return SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(
29       test()->GetProfile(index), test()->verifier());
30 }
31 
AllProfilesHaveSameExtensionsAsVerifier()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 
AllProfilesHaveSameExtensions()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 
InstallExtension(Profile * profile,int index)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 
InstallExtensionForAllProfiles(int index)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 
UninstallExtension(Profile * profile,int index)69 void UninstallExtension(Profile* profile, int index) {
70   return SyncExtensionHelper::GetInstance()->UninstallExtension(
71       profile, CreateFakeExtensionName(index));
72 }
73 
GetInstalledExtensions(Profile * profile)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 
EnableExtension(Profile * profile,int index)88 void EnableExtension(Profile* profile, int index) {
89   return SyncExtensionHelper::GetInstance()->EnableExtension(
90       profile, CreateFakeExtensionName(index));
91 }
92 
DisableExtension(Profile * profile,int index)93 void DisableExtension(Profile* profile, int index) {
94   return SyncExtensionHelper::GetInstance()->DisableExtension(
95       profile, CreateFakeExtensionName(index));
96 }
97 
IsExtensionEnabled(Profile * profile,int index)98 bool IsExtensionEnabled(Profile* profile, int index) {
99   return SyncExtensionHelper::GetInstance()->IsExtensionEnabled(
100       profile, CreateFakeExtensionName(index));
101 }
102 
IncognitoEnableExtension(Profile * profile,int index)103 void IncognitoEnableExtension(Profile* profile, int index) {
104   return SyncExtensionHelper::GetInstance()->IncognitoEnableExtension(
105       profile, CreateFakeExtensionName(index));
106 }
107 
IncognitoDisableExtension(Profile * profile,int index)108 void IncognitoDisableExtension(Profile* profile, int index) {
109   return SyncExtensionHelper::GetInstance()->IncognitoDisableExtension(
110       profile, CreateFakeExtensionName(index));
111 }
112 
IsIncognitoEnabled(Profile * profile,int index)113 bool IsIncognitoEnabled(Profile* profile, int index) {
114   return SyncExtensionHelper::GetInstance()->IsIncognitoEnabled(
115       profile, CreateFakeExtensionName(index));
116 }
117 
InstallExtensionsPendingForSync(Profile * profile)118 void InstallExtensionsPendingForSync(Profile* profile) {
119   SyncExtensionHelper::GetInstance()->InstallExtensionsPendingForSync(profile);
120 }
121 
CreateFakeExtensionName(int index)122 std::string CreateFakeExtensionName(int index) {
123   return extension_name_prefix + base::IntToString(index);
124 }
125 
ExtensionNameToIndex(const std::string & name,int * 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
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   virtual ~ExtensionsMatchChecker();
145 
146   // StatusChangeChecker implementation.
147   virtual std::string GetDebugMessage() const OVERRIDE;
148   virtual bool IsExitConditionSatisfied() OVERRIDE;
149 
150   // extensions::ExtensionRegistryObserver implementation.
151   virtual void OnExtensionLoaded(
152       content::BrowserContext* context,
153       const extensions::Extension* extension) OVERRIDE;
154   virtual void OnExtensionUnloaded(
155       content::BrowserContext* context,
156       const extensions::Extension* extenion,
157       extensions::UnloadedExtensionInfo::Reason reason) OVERRIDE;
158   virtual void OnExtensionInstalled(
159       content::BrowserContext* browser_context,
160       const extensions::Extension* extension,
161       bool is_update) OVERRIDE;
162   virtual void OnExtensionUninstalled(
163       content::BrowserContext* browser_context,
164       const extensions::Extension* extension,
165       extensions::UninstallReason reason) OVERRIDE;
166 
167   void Wait();
168 
169  private:
170   std::vector<Profile*> profiles_;
171   ScopedVector<SyncedExtensionInstaller> synced_extension_installers_;
172   bool observing_;
173 
174   DISALLOW_COPY_AND_ASSIGN(ExtensionsMatchChecker);
175 };
176 
ExtensionsMatchChecker(const std::vector<Profile * > & profiles)177 ExtensionsMatchChecker::ExtensionsMatchChecker(
178     const std::vector<Profile*>& profiles)
179     : profiles_(profiles), observing_(false) {
180   DCHECK_GE(profiles_.size(), 2U);
181 }
182 
~ExtensionsMatchChecker()183 ExtensionsMatchChecker::~ExtensionsMatchChecker() {
184   if (observing_) {
185     for (std::vector<Profile*>::iterator it = profiles_.begin();
186          it != profiles_.end();
187          ++it) {
188       extensions::ExtensionRegistry* registry =
189           extensions::ExtensionRegistry::Get(*it);
190       registry->RemoveObserver(this);
191     }
192   }
193 }
194 
GetDebugMessage() const195 std::string ExtensionsMatchChecker::GetDebugMessage() const {
196   return "Waiting for extensions to match";
197 }
198 
IsExitConditionSatisfied()199 bool ExtensionsMatchChecker::IsExitConditionSatisfied() {
200   std::vector<Profile*>::iterator it = profiles_.begin();
201   Profile* profile0 = *it;
202   ++it;
203   for (; it != profiles_.end(); ++it) {
204     if (!SyncExtensionHelper::GetInstance()->ExtensionStatesMatch(profile0,
205                                                                   *it)) {
206       return false;
207     }
208   }
209   return true;
210 }
211 
OnExtensionLoaded(content::BrowserContext * context,const extensions::Extension * extension)212 void ExtensionsMatchChecker::OnExtensionLoaded(
213     content::BrowserContext* context,
214     const extensions::Extension* extension) {
215   CheckExitCondition();
216 }
217 
OnExtensionUnloaded(content::BrowserContext * context,const extensions::Extension * extenion,extensions::UnloadedExtensionInfo::Reason reason)218 void ExtensionsMatchChecker::OnExtensionUnloaded(
219     content::BrowserContext* context,
220     const extensions::Extension* extenion,
221     extensions::UnloadedExtensionInfo::Reason reason) {
222   CheckExitCondition();
223 }
224 
OnExtensionInstalled(content::BrowserContext * browser_context,const extensions::Extension * extension,bool is_update)225 void ExtensionsMatchChecker::OnExtensionInstalled(
226     content::BrowserContext* browser_context,
227     const extensions::Extension* extension,
228     bool is_update) {
229   CheckExitCondition();
230 }
231 
OnExtensionUninstalled(content::BrowserContext * browser_context,const extensions::Extension * extension,extensions::UninstallReason reason)232 void ExtensionsMatchChecker::OnExtensionUninstalled(
233     content::BrowserContext* browser_context,
234     const extensions::Extension* extension,
235     extensions::UninstallReason reason) {
236   CheckExitCondition();
237 }
238 
Wait()239 void ExtensionsMatchChecker::Wait() {
240   for (std::vector<Profile*>::iterator it = profiles_.begin();
241        it != profiles_.end();
242        ++it) {
243     // Begin mocking the installation of synced extensions from the web store.
244     synced_extension_installers_.push_back(new SyncedExtensionInstaller(*it));
245 
246     extensions::ExtensionRegistry* registry =
247         extensions::ExtensionRegistry::Get(*it);
248     registry->AddObserver(this);
249   }
250 
251   observing_ = true;
252 
253   if (IsExitConditionSatisfied()) {
254     VLOG(1) << "Extensions matched without waiting";
255     return;
256   }
257 
258   VLOG(1) << "Starting Wait: " << GetDebugMessage();
259   StartBlockingWait();
260 }
261 
262 }  // namespace
263 
AwaitAllProfilesHaveSameExtensionsAsVerifier()264 bool AwaitAllProfilesHaveSameExtensionsAsVerifier() {
265   std::vector<Profile*> profiles;
266   profiles.push_back(test()->verifier());
267   for (int i = 0; i < test()->num_clients(); ++i) {
268     profiles.push_back(test()->GetProfile(i));
269   }
270 
271   ExtensionsMatchChecker checker(profiles);
272   checker.Wait();
273   return !checker.TimedOut();
274 }
275 
276 }  // namespace extensions_helper
277