1// Copyright (c) 2013 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/services/gcm/gcm_profile_service.h"
6
7#include "base/logging.h"
8#include "base/prefs/pref_service.h"
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/common/pref_names.h"
11#include "components/pref_registry/pref_registry_syncable.h"
12
13#if defined(OS_ANDROID)
14#include "components/gcm_driver/gcm_driver_android.h"
15#else
16#include "base/files/file_path.h"
17#include "chrome/browser/services/gcm/gcm_desktop_utils.h"
18#include "chrome/browser/signin/profile_identity_provider.h"
19#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
20#include "chrome/browser/signin/signin_manager_factory.h"
21#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
22#include "chrome/common/chrome_constants.h"
23#include "components/gcm_driver/gcm_client_factory.h"
24#include "components/signin/core/browser/signin_manager.h"
25#include "google_apis/gaia/identity_provider.h"
26#include "net/url_request/url_request_context_getter.h"
27#endif
28
29namespace gcm {
30
31#if !defined(OS_ANDROID)
32class GCMProfileService::IdentityObserver : public IdentityProvider::Observer {
33 public:
34  IdentityObserver(Profile* profile, GCMDriver* driver);
35  virtual ~IdentityObserver();
36
37  // IdentityProvider::Observer:
38  virtual void OnActiveAccountLogin() OVERRIDE;
39  virtual void OnActiveAccountLogout() OVERRIDE;
40
41  std::string SignedInUserName() const;
42
43 private:
44  GCMDriver* driver_;
45  scoped_ptr<IdentityProvider> identity_provider_;
46
47  // The account ID that this service is responsible for. Empty when the service
48  // is not running.
49  std::string account_id_;
50
51  DISALLOW_COPY_AND_ASSIGN(IdentityObserver);
52};
53
54GCMProfileService::IdentityObserver::IdentityObserver(Profile* profile,
55                                                      GCMDriver* driver)
56    : driver_(driver) {
57  identity_provider_.reset(new ProfileIdentityProvider(
58      SigninManagerFactory::GetForProfile(profile),
59      ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
60      LoginUIServiceFactory::GetForProfile(profile)));
61  identity_provider_->AddObserver(this);
62
63  OnActiveAccountLogin();
64}
65
66GCMProfileService::IdentityObserver::~IdentityObserver() {
67  identity_provider_->RemoveObserver(this);
68}
69
70void GCMProfileService::IdentityObserver::OnActiveAccountLogin() {
71  // This might be called multiple times when the password changes.
72  const std::string account_id = identity_provider_->GetActiveAccountId();
73  if (account_id == account_id_)
74    return;
75  account_id_ = account_id;
76
77  driver_->OnSignedIn();
78}
79
80void GCMProfileService::IdentityObserver::OnActiveAccountLogout() {
81  driver_->Purge();
82}
83
84std::string GCMProfileService::IdentityObserver::SignedInUserName() const {
85  return driver_->IsStarted() ? account_id_ : std::string();
86}
87#endif  // !defined(OS_ANDROID)
88
89// static
90bool GCMProfileService::IsGCMEnabled(Profile* profile) {
91  return profile->GetPrefs()->GetBoolean(prefs::kGCMChannelEnabled);
92}
93
94// static
95void GCMProfileService::RegisterProfilePrefs(
96    user_prefs::PrefRegistrySyncable* registry) {
97  registry->RegisterBooleanPref(
98      prefs::kGCMChannelEnabled,
99      true,
100      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
101  PushMessagingServiceImpl::RegisterProfilePrefs(registry);
102}
103
104#if defined(OS_ANDROID)
105GCMProfileService::GCMProfileService(Profile* profile)
106    : profile_(profile),
107      push_messaging_service_(this, profile) {
108  DCHECK(!profile->IsOffTheRecord());
109
110  driver_.reset(new GCMDriverAndroid);
111}
112#else
113GCMProfileService::GCMProfileService(
114    Profile* profile,
115    scoped_ptr<GCMClientFactory> gcm_client_factory)
116    : profile_(profile),
117      push_messaging_service_(this, profile) {
118  DCHECK(!profile->IsOffTheRecord());
119
120  driver_ = CreateGCMDriverDesktop(
121      gcm_client_factory.Pass(),
122      profile_->GetPath().Append(chrome::kGCMStoreDirname),
123      profile_->GetRequestContext());
124
125  identity_observer_.reset(new IdentityObserver(profile, driver_.get()));
126}
127#endif  // defined(OS_ANDROID)
128
129GCMProfileService::GCMProfileService()
130    : profile_(NULL),
131      push_messaging_service_(this, NULL) {
132}
133
134GCMProfileService::~GCMProfileService() {
135}
136
137void GCMProfileService::AddAppHandler(const std::string& app_id,
138                                      GCMAppHandler* handler) {
139  if (driver_)
140    driver_->AddAppHandler(app_id, handler);
141}
142
143void GCMProfileService::RemoveAppHandler(const std::string& app_id) {
144  if (driver_)
145    driver_->RemoveAppHandler(app_id);
146}
147
148void GCMProfileService::Register(const std::string& app_id,
149                                 const std::vector<std::string>& sender_ids,
150                                 const GCMDriver::RegisterCallback& callback) {
151  if (driver_)
152    driver_->Register(app_id, sender_ids, callback);
153}
154
155void GCMProfileService::Shutdown() {
156#if !defined(OS_ANDROID)
157  identity_observer_.reset();
158#endif  // !defined(OS_ANDROID)
159
160  if (driver_) {
161    driver_->Shutdown();
162    driver_.reset();
163  }
164}
165
166std::string GCMProfileService::SignedInUserName() const {
167#if defined(OS_ANDROID)
168  return std::string();
169#else
170  return identity_observer_ ? identity_observer_->SignedInUserName()
171                            : std::string();
172#endif  // defined(OS_ANDROID)
173}
174
175void GCMProfileService::SetDriverForTesting(GCMDriver* driver) {
176  driver_.reset(driver);
177}
178
179}  // namespace gcm
180