1 // Copyright (c) 2011 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/themes_helper.h"
7 #include "base/callback.h"
8 #include "base/logging.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/stringprintf.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/sync/test/integration/status_change_checker.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/themes/theme_service.h"
16 #include "chrome/browser/themes/theme_service_factory.h"
17 #include "components/crx_file/id_util.h"
18 #include "content/public/browser/notification_observer.h"
19 #include "content/public/browser/notification_registrar.h"
20 #include "content/public/browser/notification_source.h"
21 #include "extensions/common/manifest.h"
23 using sync_datatype_helper::test
;
27 // Make a name to pass to an extension helper.
28 std::string
MakeName(int index
) {
29 return "faketheme" + base::IntToString(index
);
32 ThemeService
* GetThemeService(Profile
* profile
) {
33 return ThemeServiceFactory::GetForProfile(profile
);
38 namespace themes_helper
{
40 std::string
GetCustomTheme(int index
) {
41 return crx_file::id_util::GenerateId(MakeName(index
));
44 std::string
GetThemeID(Profile
* profile
) {
45 return GetThemeService(profile
)->GetThemeID();
48 bool UsingCustomTheme(Profile
* profile
) {
49 return GetThemeID(profile
) != ThemeService::kDefaultThemeID
;
52 bool UsingDefaultTheme(Profile
* profile
) {
53 return GetThemeService(profile
)->UsingDefaultTheme();
56 bool UsingSystemTheme(Profile
* profile
) {
57 return GetThemeService(profile
)->UsingSystemTheme();
60 bool ThemeIsPendingInstall(Profile
* profile
, const std::string
& id
) {
61 return SyncExtensionHelper::GetInstance()->
62 IsExtensionPendingInstallForSync(profile
, id
);
65 void UseCustomTheme(Profile
* profile
, int index
) {
66 SyncExtensionHelper::GetInstance()->InstallExtension(
67 profile
, MakeName(index
), extensions::Manifest::TYPE_THEME
);
70 void UseDefaultTheme(Profile
* profile
) {
71 GetThemeService(profile
)->UseDefaultTheme();
74 void UseSystemTheme(Profile
* profile
) {
75 GetThemeService(profile
)->UseSystemTheme();
80 // Helper to wait until the specified theme is pending for install on the
83 // The themes sync integration tests don't actually install any custom themes,
84 // but they do occasionally check that the ThemeService attempts to install
86 class ThemePendingInstallChecker
: public StatusChangeChecker
,
87 public content::NotificationObserver
{
89 ThemePendingInstallChecker(Profile
* profile
, const std::string
& theme
);
90 ~ThemePendingInstallChecker() override
;
92 // Implementation of StatusChangeChecker.
93 std::string
GetDebugMessage() const override
;
94 bool IsExitConditionSatisfied() override
;
96 // Implementation of content::NotificationObserver.
97 void Observe(int type
,
98 const content::NotificationSource
& source
,
99 const content::NotificationDetails
& details
) override
;
101 // Waits until the condition to be met or a timeout occurs.
106 const std::string
& theme_
;
108 content::NotificationRegistrar registrar_
;
111 ThemePendingInstallChecker::ThemePendingInstallChecker(Profile
* profile
,
112 const std::string
& theme
)
113 : profile_(profile
), theme_(theme
) {
116 ThemePendingInstallChecker::~ThemePendingInstallChecker() {
119 std::string
ThemePendingInstallChecker::GetDebugMessage() const {
120 return base::StringPrintf("Waiting for pending theme to be '%s'",
124 bool ThemePendingInstallChecker::IsExitConditionSatisfied() {
125 return ThemeIsPendingInstall(profile_
, theme_
);
128 void ThemePendingInstallChecker::Observe(
130 const content::NotificationSource
& source
,
131 const content::NotificationDetails
& details
) {
132 DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_UPDATING_STARTED
, type
);
133 CheckExitCondition();
136 void ThemePendingInstallChecker::Wait() {
137 // We'll check to see if the condition is met whenever the extension system
138 // tries to contact the web store.
140 extensions::NOTIFICATION_EXTENSION_UPDATING_STARTED
,
141 content::Source
<Profile
>(profile_
));
143 if (IsExitConditionSatisfied()) {
152 bool AwaitThemeIsPendingInstall(Profile
* profile
, const std::string
& theme
) {
153 ThemePendingInstallChecker
checker(profile
, theme
);
155 return !checker
.TimedOut();
160 // Helper to wait until a given condition is met, checking every time the
161 // current theme changes.
163 // The |exit_condition_| closure may be invoked zero or more times.
164 class ThemeConditionChecker
: public StatusChangeChecker
,
165 public content::NotificationObserver
{
167 ThemeConditionChecker(Profile
* profile
,
168 const std::string
& debug_message_
,
169 base::Callback
<bool(ThemeService
*)> exit_condition
);
170 ~ThemeConditionChecker() override
;
172 // Implementation of StatusChangeChecker.
173 std::string
GetDebugMessage() const override
;
174 bool IsExitConditionSatisfied() override
;
176 // Implementation of content::NotificationObserver.
177 void Observe(int type
,
178 const content::NotificationSource
& source
,
179 const content::NotificationDetails
& details
) override
;
181 // Waits until the condition to be met or a timeout occurs.
186 const std::string debug_message_
;
187 base::Callback
<bool(ThemeService
*)> exit_condition_
;
189 content::NotificationRegistrar registrar_
;
192 ThemeConditionChecker::ThemeConditionChecker(
194 const std::string
& debug_message
,
195 base::Callback
<bool(ThemeService
*)> exit_condition
)
197 debug_message_(debug_message
),
198 exit_condition_(exit_condition
) {
201 ThemeConditionChecker::~ThemeConditionChecker() {
204 std::string
ThemeConditionChecker::GetDebugMessage() const {
205 return debug_message_
;
208 bool ThemeConditionChecker::IsExitConditionSatisfied() {
209 return exit_condition_
.Run(GetThemeService(profile_
));
212 void ThemeConditionChecker::Observe(
214 const content::NotificationSource
& source
,
215 const content::NotificationDetails
& details
) {
216 DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED
, type
);
217 CheckExitCondition();
220 void ThemeConditionChecker::Wait() {
222 chrome::NOTIFICATION_BROWSER_THEME_CHANGED
,
223 content::Source
<ThemeService
>(GetThemeService(profile_
)));
225 if (IsExitConditionSatisfied()) {
232 // Helper function to let us bind this functionality into a base::Callback.
233 bool UsingSystemThemeFunc(ThemeService
* theme_service
) {
234 return theme_service
->UsingSystemTheme();
237 // Helper function to let us bind this functionality into a base::Callback.
238 bool UsingDefaultThemeFunc(ThemeService
* theme_service
) {
239 return theme_service
->UsingDefaultTheme();
244 bool AwaitUsingSystemTheme(Profile
* profile
) {
245 ThemeConditionChecker
checker(
247 std::string("Waiting until profile is using system theme"),
248 base::Bind(&UsingSystemThemeFunc
));
250 return !checker
.TimedOut();
253 bool AwaitUsingDefaultTheme(Profile
* profile
) {
254 ThemeConditionChecker
checker(
256 std::string("Waiting until profile is using default theme"),
257 base::Bind(&UsingDefaultThemeFunc
));
259 return !checker
.TimedOut();
262 } // namespace themes_helper