summaryrefslogtreecommitdiffstats
path: root/chrome/browser/themes/theme_service.cc
blob: eae2b76a84b862c808e211b860a0f70981f0e02b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// 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/themes/theme_service.h"

#include "base/logging.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/browser_theme_provider.h"
#include "content/common/notification_service.h"

#if defined(TOOLKIT_USES_GTK)
#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
#endif

// static
BrowserThemeProvider* ThemeServiceFactory::GetForProfile(Profile* top_profile) {
  // We may be asked for the Theme of an incognito profile. Make sure we're
  // operating on the real profile.
  Profile* profile = top_profile->GetOriginalProfile();

  ThemeServiceFactory* service = GetInstance();

  std::map<Profile*, BrowserThemeProvider*>::const_iterator it =
      service->mapping_.find(profile);
  if (it != service->mapping_.end())
    return it->second;

  BrowserThemeProvider* provider = NULL;
#if defined(TOOLKIT_USES_GTK)
  provider = new GtkThemeProvider;
#else
  provider = new BrowserThemeProvider;
#endif
  provider->Init(profile);

  service->Associate(profile, provider);
  return provider;
}

const Extension* ThemeServiceFactory::GetThemeForProfile(Profile* profile) {
  std::string id = GetForProfile(profile)->GetThemeID();
  if (id == BrowserThemeProvider::kDefaultThemeID)
    return NULL;

  return profile->GetExtensionService()->GetExtensionById(id, false);
}

void ThemeServiceFactory::ForceAssociationBetween(Profile* top_profile,
                                           BrowserThemeProvider* provider) {
  ThemeServiceFactory* service = GetInstance();
  Profile* profile = top_profile->GetOriginalProfile();

  service->Associate(profile, provider);
}

ThemeServiceFactory* ThemeServiceFactory::GetInstance() {
  return Singleton<ThemeServiceFactory>::get();
}

ThemeServiceFactory::ThemeServiceFactory() {}

ThemeServiceFactory::~ThemeServiceFactory() {
  DCHECK(mapping_.empty());
}

void ThemeServiceFactory::Associate(Profile* profile,
                             BrowserThemeProvider* provider) {
  DCHECK(mapping_.find(profile) == mapping_.end());
  mapping_.insert(std::make_pair(profile, provider));

  registrar_.Add(this,
                 NotificationType::PROFILE_DESTROYED,
                 Source<Profile>(profile));
  registrar_.Add(this,
                 NotificationType::THEME_INSTALLED,
                 Source<Profile>(profile));
}

void ThemeServiceFactory::Observe(NotificationType type,
                           const NotificationSource& source,
                           const NotificationDetails& details) {
  std::map<Profile*, BrowserThemeProvider*>::iterator it =
      mapping_.find(Source<Profile>(source).ptr());
  DCHECK(it != mapping_.end());

  if (NotificationType::PROFILE_DESTROYED == type) {
    delete it->second;
    mapping_.erase(it);

    // Remove ourselves from listening to all notifications because the source
    // profile has been deleted. We have to do this because several unit tests
    // are set up so a Profile is on the same place on the stack multiple
    // times, so while they are different instances, they have the same
    // addresses.
    registrar_.Remove(this,
                      NotificationType::PROFILE_DESTROYED,
                      source);
    registrar_.Remove(this,
                      NotificationType::THEME_INSTALLED,
                      source);
  } else if (NotificationType::THEME_INSTALLED == type) {
    const Extension* extension = Details<const Extension>(details).ptr();
    it->second->SetTheme(extension);
  } else {
    NOTREACHED();
  }
}