summaryrefslogtreecommitdiffstats
path: root/chrome/browser/services/gcm/gcm_profile_service.cc
blob: 75e1bdd6c7cf2ddb4dc5a394cfd22570f9ce2137 (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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
// Copyright (c) 2013 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/services/gcm/gcm_profile_service.h"

#include <map>

#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"

#if defined(OS_ANDROID)
#include "components/gcm_driver/gcm_driver_android.h"
#else
#include "base/bind.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/services/gcm/chromeos_gcm_connection_observer.h"
#endif
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/services/gcm/gcm_account_tracker.h"
#include "chrome/browser/services/gcm/gcm_desktop_utils.h"
#include "chrome/browser/signin/profile_identity_provider.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/common/chrome_constants.h"
#include "components/gcm_driver/gcm_client_factory.h"
#include "components/gcm_driver/gcm_driver_desktop.h"
#include "components/signin/core/browser/signin_manager.h"
#include "google_apis/gaia/account_tracker.h"
#include "google_apis/gaia/identity_provider.h"
#include "net/url_request/url_request_context_getter.h"
#endif

namespace gcm {

#if !defined(OS_ANDROID)
// Identity observer only has actual work to do when the user is actually signed
// in. It ensures that account tracker is taking
class GCMProfileService::IdentityObserver : public IdentityProvider::Observer {
 public:
  IdentityObserver(Profile* profile, GCMDriverDesktop* driver);
  virtual ~IdentityObserver();

  // IdentityProvider::Observer:
  virtual void OnActiveAccountLogin() OVERRIDE;
  virtual void OnActiveAccountLogout() OVERRIDE;

  std::string SignedInUserName() const;

  // Called to inform IdentityObserver that a list of accounts was updated.
  // |account_tokens| maps email addresses to OAuth2 access tokens.
  void AccountsUpdated(
      const std::map<std::string, std::string>& account_tokens);

 private:
  Profile* profile_;
  GCMDriverDesktop* driver_;
  scoped_ptr<IdentityProvider> identity_provider_;
  scoped_ptr<GCMAccountTracker> gcm_account_tracker_;

  // The account ID that this service is responsible for. Empty when the service
  // is not running.
  std::string account_id_;

  base::WeakPtrFactory<GCMProfileService::IdentityObserver> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(IdentityObserver);
};

GCMProfileService::IdentityObserver::IdentityObserver(Profile* profile,
                                                      GCMDriverDesktop* driver)
    : profile_(profile), driver_(driver), weak_ptr_factory_(this) {
  identity_provider_.reset(new ProfileIdentityProvider(
      SigninManagerFactory::GetForProfile(profile),
      ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
      LoginUIServiceFactory::GetForProfile(profile)));
  identity_provider_->AddObserver(this);

  OnActiveAccountLogin();
}

GCMProfileService::IdentityObserver::~IdentityObserver() {
  if (gcm_account_tracker_)
    gcm_account_tracker_->Shutdown();
  identity_provider_->RemoveObserver(this);
}

void GCMProfileService::IdentityObserver::OnActiveAccountLogin() {
  // This might be called multiple times when the password changes.
  const std::string account_id = identity_provider_->GetActiveAccountId();
  if (account_id == account_id_)
    return;
  account_id_ = account_id;

  driver_->OnSignedIn();

  if (!gcm_account_tracker_) {
    scoped_ptr<gaia::AccountTracker> gaia_account_tracker(
        new gaia::AccountTracker(identity_provider_.get(),
                                 profile_->GetRequestContext()));

    gcm_account_tracker_.reset(new GCMAccountTracker(
        gaia_account_tracker.Pass(),
        base::Bind(&GCMProfileService::IdentityObserver::AccountsUpdated,
                   weak_ptr_factory_.GetWeakPtr())));
  }

  gcm_account_tracker_->Start();
}

void GCMProfileService::IdentityObserver::OnActiveAccountLogout() {
  account_id_.clear();

  // Check is necessary to not crash browser_tests.
  if (gcm_account_tracker_)
    gcm_account_tracker_->Stop();
  // When sign-in enforcement is not dropped, OnSignedOut will also clear all
  // the GCM data and a new GCM ID will be retrieved after the user signs in
  // again. Otherwise, the user sign-out will not affect the existing GCM
  // data.
  driver_->OnSignedOut();
}

std::string GCMProfileService::IdentityObserver::SignedInUserName() const {
  return driver_->IsStarted() ? account_id_ : std::string();
}

void GCMProfileService::IdentityObserver::AccountsUpdated(
    const std::map<std::string, std::string>& account_tokens) {
  driver_->SetAccountsForCheckin(account_tokens);
}
#endif  // !defined(OS_ANDROID)

// static
bool GCMProfileService::IsGCMEnabled(Profile* profile) {
  return profile->GetPrefs()->GetBoolean(prefs::kGCMChannelEnabled);
}

// static
void GCMProfileService::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterBooleanPref(
      prefs::kGCMChannelEnabled,
      true,
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
  PushMessagingServiceImpl::RegisterProfilePrefs(registry);
}

#if defined(OS_ANDROID)
GCMProfileService::GCMProfileService(Profile* profile)
    : profile_(profile),
      push_messaging_service_(this, profile) {
  DCHECK(!profile->IsOffTheRecord());

  driver_.reset(new GCMDriverAndroid);
}
#else
GCMProfileService::GCMProfileService(
    Profile* profile,
    scoped_ptr<GCMClientFactory> gcm_client_factory)
    : profile_(profile),
      push_messaging_service_(this, profile) {
  DCHECK(!profile->IsOffTheRecord());

  driver_ = CreateGCMDriverDesktop(
      gcm_client_factory.Pass(),
      profile_->GetPrefs(),
      profile_->GetPath().Append(chrome::kGCMStoreDirname),
      profile_->GetRequestContext());

#ifdef CHROMEOS
  chromeos_connection_observer_.reset(new gcm::ChromeOSGCMConnectionObserver);
  driver_->AddConnectionObserver(chromeos_connection_observer_.get());
#endif

  identity_observer_.reset(new IdentityObserver(
      profile, static_cast<gcm::GCMDriverDesktop*>(driver_.get())));
}
#endif  // defined(OS_ANDROID)

GCMProfileService::GCMProfileService()
    : profile_(NULL),
      push_messaging_service_(this, NULL) {
}

GCMProfileService::~GCMProfileService() {
}

void GCMProfileService::AddAppHandler(const std::string& app_id,
                                      GCMAppHandler* handler) {
  if (driver_)
    driver_->AddAppHandler(app_id, handler);
}

void GCMProfileService::RemoveAppHandler(const std::string& app_id) {
  if (driver_)
    driver_->RemoveAppHandler(app_id);
}

void GCMProfileService::Register(const std::string& app_id,
                                 const std::vector<std::string>& sender_ids,
                                 const GCMDriver::RegisterCallback& callback) {
  if (driver_)
    driver_->Register(app_id, sender_ids, callback);
}

void GCMProfileService::Shutdown() {
#if !defined(OS_ANDROID)
  identity_observer_.reset();
#endif  // !defined(OS_ANDROID)
#if defined(OS_CHROMEOS)
  driver_->RemoveConnectionObserver(chromeos_connection_observer_.get());
  chromeos_connection_observer_.reset();
#endif

  if (driver_) {
    driver_->Shutdown();
    driver_.reset();
  }
}

std::string GCMProfileService::SignedInUserName() const {
#if defined(OS_ANDROID)
  return std::string();
#else
  return identity_observer_ ? identity_observer_->SignedInUserName()
                            : std::string();
#endif  // defined(OS_ANDROID)
}

void GCMProfileService::SetDriverForTesting(GCMDriver* driver) {
  driver_.reset(driver);
}

}  // namespace gcm