| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/sync/glue/theme_util.h" |
| |
| #include <string> |
| |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "chrome/browser/extensions/extension_install_ui.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/extensions/extension_updater.h" |
| #if defined(TOOLKIT_USES_GTK) |
| #include "chrome/browser/ui/gtk/gtk_theme_service.h" |
| #endif |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/sync/protocol/theme_specifics.pb.h" |
| #include "chrome/browser/themes/theme_service.h" |
| #include "chrome/browser/themes/theme_service_factory.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "chrome/common/extensions/extension_constants.h" |
| #include "googleurl/src/gurl.h" |
| |
| namespace browser_sync { |
| |
| const char kCurrentThemeClientTag[] = "current_theme"; |
| |
| namespace { |
| |
| bool IsSystemThemeDistinctFromDefaultTheme() { |
| #if defined(TOOLKIT_USES_GTK) |
| return true; |
| #else |
| return false; |
| #endif |
| } |
| |
| bool UseSystemTheme(Profile* profile) { |
| #if defined(TOOLKIT_USES_GTK) |
| return GtkThemeService::GetFrom(profile)->UseGtkTheme(); |
| #else |
| return false; |
| #endif |
| } |
| |
| } // namespace |
| |
| bool AreThemeSpecificsEqual(const sync_pb::ThemeSpecifics& a, |
| const sync_pb::ThemeSpecifics& b) { |
| return AreThemeSpecificsEqualHelper( |
| a, b, IsSystemThemeDistinctFromDefaultTheme()); |
| } |
| |
| bool AreThemeSpecificsEqualHelper( |
| const sync_pb::ThemeSpecifics& a, |
| const sync_pb::ThemeSpecifics& b, |
| bool is_system_theme_distinct_from_default_theme) { |
| if (a.use_custom_theme() != b.use_custom_theme()) { |
| return false; |
| } |
| |
| if (a.use_custom_theme()) { |
| // We're using a custom theme, so simply compare IDs since those |
| // are guaranteed unique. |
| return a.custom_theme_id() == b.custom_theme_id(); |
| } else if (is_system_theme_distinct_from_default_theme) { |
| // We're not using a custom theme, but we care about system |
| // vs. default. |
| return a.use_system_theme_by_default() == b.use_system_theme_by_default(); |
| } else { |
| // We're not using a custom theme, and we don't care about system |
| // vs. default. |
| return true; |
| } |
| } |
| |
| namespace { |
| |
| bool IsTheme(const Extension& extension) { |
| return extension.is_theme(); |
| } |
| |
| } // namespace |
| |
| void SetCurrentThemeFromThemeSpecifics( |
| const sync_pb::ThemeSpecifics& theme_specifics, |
| Profile* profile) { |
| DCHECK(profile); |
| if (theme_specifics.use_custom_theme()) { |
| // TODO(akalin): Figure out what to do about third-party themes |
| // (i.e., those not on either Google gallery). |
| std::string id(theme_specifics.custom_theme_id()); |
| GURL update_url(theme_specifics.custom_theme_update_url()); |
| VLOG(1) << "Applying theme " << id << " with update_url " << update_url; |
| ExtensionServiceInterface* extensions_service = |
| profile->GetExtensionService(); |
| CHECK(extensions_service); |
| const Extension* extension = extensions_service->GetExtensionById(id, true); |
| if (extension) { |
| if (!extension->is_theme()) { |
| VLOG(1) << "Extension " << id << " is not a theme; aborting"; |
| return; |
| } |
| if (!extensions_service->IsExtensionEnabled(id)) { |
| VLOG(1) << "Theme " << id << " is not enabled; aborting"; |
| return; |
| } |
| // Get previous theme info before we set the new theme. |
| std::string previous_theme_id; |
| { |
| const Extension* current_theme = |
| ThemeServiceFactory::GetThemeForProfile(profile); |
| if (current_theme) { |
| DCHECK(current_theme->is_theme()); |
| previous_theme_id = current_theme->id(); |
| } |
| } |
| bool previous_use_system_theme = UseSystemTheme(profile); |
| // An enabled theme extension with the given id was found, so |
| // just set the current theme to it. |
| ThemeServiceFactory::GetForProfile(profile)->SetTheme(extension); |
| // Pretend the theme was just installed. |
| ExtensionInstallUI::ShowThemeInfoBar( |
| previous_theme_id, previous_use_system_theme, |
| extension, profile); |
| } else { |
| // No extension with this id exists -- we must install it; we do |
| // so by adding it as a pending extension and then triggering an |
| // auto-update cycle. |
| // Themes don't need to install silently as they just pop up an |
| // informational dialog after installation instead of a |
| // confirmation dialog. |
| const bool kInstallSilently = false; |
| const bool kEnableOnInstall = true; |
| const bool kEnableIncognitoOnInstall = false; |
| extensions_service->pending_extension_manager()->AddFromSync( |
| id, update_url, &IsTheme, |
| kInstallSilently, kEnableOnInstall, kEnableIncognitoOnInstall); |
| extensions_service->CheckForUpdatesSoon(); |
| } |
| } else if (theme_specifics.use_system_theme_by_default()) { |
| ThemeServiceFactory::GetForProfile(profile)->SetNativeTheme(); |
| } else { |
| ThemeServiceFactory::GetForProfile(profile)->UseDefaultTheme(); |
| } |
| } |
| |
| bool UpdateThemeSpecificsOrSetCurrentThemeIfNecessary( |
| Profile* profile, sync_pb::ThemeSpecifics* theme_specifics) { |
| if (!theme_specifics->use_custom_theme() && |
| (ThemeServiceFactory::GetThemeForProfile(profile) || |
| (UseSystemTheme(profile) && |
| IsSystemThemeDistinctFromDefaultTheme()))) { |
| GetThemeSpecificsFromCurrentTheme(profile, theme_specifics); |
| return true; |
| } else { |
| SetCurrentThemeFromThemeSpecificsIfNecessary(*theme_specifics, profile); |
| return false; |
| } |
| } |
| |
| void GetThemeSpecificsFromCurrentTheme( |
| Profile* profile, |
| sync_pb::ThemeSpecifics* theme_specifics) { |
| DCHECK(profile); |
| const Extension* current_theme = |
| ThemeServiceFactory::GetThemeForProfile(profile); |
| if (current_theme) { |
| DCHECK(current_theme->is_theme()); |
| } |
| GetThemeSpecificsFromCurrentThemeHelper( |
| current_theme, |
| IsSystemThemeDistinctFromDefaultTheme(), |
| UseSystemTheme(profile), |
| theme_specifics); |
| } |
| |
| void GetThemeSpecificsFromCurrentThemeHelper( |
| const Extension* current_theme, |
| bool is_system_theme_distinct_from_default_theme, |
| bool use_system_theme_by_default, |
| sync_pb::ThemeSpecifics* theme_specifics) { |
| bool use_custom_theme = (current_theme != NULL); |
| theme_specifics->set_use_custom_theme(use_custom_theme); |
| if (is_system_theme_distinct_from_default_theme) { |
| theme_specifics->set_use_system_theme_by_default( |
| use_system_theme_by_default); |
| } else { |
| DCHECK(!use_system_theme_by_default); |
| } |
| if (use_custom_theme) { |
| DCHECK(current_theme); |
| DCHECK(current_theme->is_theme()); |
| theme_specifics->set_custom_theme_name(current_theme->name()); |
| theme_specifics->set_custom_theme_id(current_theme->id()); |
| theme_specifics->set_custom_theme_update_url( |
| current_theme->update_url().spec()); |
| } else { |
| DCHECK(!current_theme); |
| theme_specifics->clear_custom_theme_name(); |
| theme_specifics->clear_custom_theme_id(); |
| theme_specifics->clear_custom_theme_update_url(); |
| } |
| } |
| |
| void SetCurrentThemeFromThemeSpecificsIfNecessary( |
| const sync_pb::ThemeSpecifics& theme_specifics, Profile* profile) { |
| DCHECK(profile); |
| sync_pb::ThemeSpecifics old_theme_specifics; |
| GetThemeSpecificsFromCurrentTheme(profile, &old_theme_specifics); |
| if (!AreThemeSpecificsEqual(old_theme_specifics, theme_specifics)) { |
| SetCurrentThemeFromThemeSpecifics(theme_specifics, profile); |
| } |
| } |
| |
| } // namespace browser_sync |