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 "components/gcm_driver/gcm_profile_service.h"
6 
7 #include <utility>
8 #include <vector>
9 
10 #include "base/macros.h"
11 #include "build/build_config.h"
12 #include "components/gcm_driver/gcm_driver.h"
13 #include "components/gcm_driver/gcm_driver_constants.h"
14 #include "components/pref_registry/pref_registry_syncable.h"
15 #include "components/prefs/pref_service.h"
16 #include "services/network/public/cpp/shared_url_loader_factory.h"
17 
18 #if BUILDFLAG(USE_GCM_FROM_PLATFORM)
19 #include "base/sequenced_task_runner.h"
20 #include "components/gcm_driver/gcm_driver_android.h"
21 #else
22 #include "base/bind.h"
23 #include "base/files/file_path.h"
24 #include "base/memory/weak_ptr.h"
25 #include "components/gcm_driver/account_tracker.h"
26 #include "components/gcm_driver/gcm_account_tracker.h"
27 #include "components/gcm_driver/gcm_client_factory.h"
28 #include "components/gcm_driver/gcm_desktop_utils.h"
29 #include "components/gcm_driver/gcm_driver_desktop.h"
30 #include "components/signin/public/identity_manager/identity_manager.h"
31 #endif
32 
33 namespace gcm {
34 
35 #if !BUILDFLAG(USE_GCM_FROM_PLATFORM)
36 // Identity observer only has actual work to do when the user is actually signed
37 // in. It ensures that account tracker is taking
38 class GCMProfileService::IdentityObserver
39     : public signin::IdentityManager::Observer {
40  public:
41   IdentityObserver(
42       signin::IdentityManager* identity_manager,
43       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
44       GCMDriver* driver);
45   ~IdentityObserver() override;
46 
47   // signin::IdentityManager::Observer:
48   void OnPrimaryAccountSet(
49       const CoreAccountInfo& primary_account_info) override;
50   void OnPrimaryAccountCleared(
51       const CoreAccountInfo& previous_primary_account_info) override;
52 
53  private:
54   void StartAccountTracker(
55       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
56 
57   GCMDriver* driver_;
58   signin::IdentityManager* identity_manager_;
59   std::unique_ptr<GCMAccountTracker> gcm_account_tracker_;
60 
61   // The account ID that this service is responsible for. Empty when the service
62   // is not running.
63   CoreAccountId account_id_;
64 
65   base::WeakPtrFactory<GCMProfileService::IdentityObserver> weak_ptr_factory_{
66       this};
67 
68   DISALLOW_COPY_AND_ASSIGN(IdentityObserver);
69 };
70 
IdentityObserver(signin::IdentityManager * identity_manager,scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,GCMDriver * driver)71 GCMProfileService::IdentityObserver::IdentityObserver(
72     signin::IdentityManager* identity_manager,
73     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
74     GCMDriver* driver)
75     : driver_(driver), identity_manager_(identity_manager) {
76   identity_manager_->AddObserver(this);
77 
78   OnPrimaryAccountSet(identity_manager_->GetPrimaryAccountInfo());
79   StartAccountTracker(std::move(url_loader_factory));
80 }
81 
~IdentityObserver()82 GCMProfileService::IdentityObserver::~IdentityObserver() {
83   if (gcm_account_tracker_)
84     gcm_account_tracker_->Shutdown();
85   identity_manager_->RemoveObserver(this);
86 }
87 
OnPrimaryAccountSet(const CoreAccountInfo & primary_account_info)88 void GCMProfileService::IdentityObserver::OnPrimaryAccountSet(
89     const CoreAccountInfo& primary_account_info) {
90   // This might be called multiple times when the password changes.
91   if (primary_account_info.account_id == account_id_)
92     return;
93   account_id_ = primary_account_info.account_id;
94 
95   // Still need to notify GCMDriver for UMA purpose.
96   driver_->OnSignedIn();
97 }
98 
OnPrimaryAccountCleared(const CoreAccountInfo & previous_primary_account_info)99 void GCMProfileService::IdentityObserver::OnPrimaryAccountCleared(
100     const CoreAccountInfo& previous_primary_account_info) {
101   account_id_ = CoreAccountId();
102 
103   // Still need to notify GCMDriver for UMA purpose.
104   driver_->OnSignedOut();
105 }
106 
StartAccountTracker(scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)107 void GCMProfileService::IdentityObserver::StartAccountTracker(
108     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
109   if (gcm_account_tracker_)
110     return;
111 
112   std::unique_ptr<AccountTracker> gaia_account_tracker(
113       new AccountTracker(identity_manager_));
114 
115   gcm_account_tracker_.reset(new GCMAccountTracker(
116       std::move(gaia_account_tracker), identity_manager_, driver_));
117 
118   gcm_account_tracker_->Start();
119 }
120 
121 #endif  // !BUILDFLAG(USE_GCM_FROM_PLATFORM)
122 
123 #if BUILDFLAG(USE_GCM_FROM_PLATFORM)
GCMProfileService(base::FilePath path,scoped_refptr<base::SequencedTaskRunner> & blocking_task_runner)124 GCMProfileService::GCMProfileService(
125     base::FilePath path,
126     scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner) {
127   driver_ = std::make_unique<GCMDriverAndroid>(
128       path.Append(gcm_driver::kGCMStoreDirname), blocking_task_runner);
129 }
130 #else
GCMProfileService(PrefService * prefs,base::FilePath path,base::RepeatingCallback<void (base::WeakPtr<GCMProfileService>,mojo::PendingReceiver<network::mojom::ProxyResolvingSocketFactory>)> get_socket_factory_callback,scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,network::NetworkConnectionTracker * network_connection_tracker,version_info::Channel channel,const std::string & product_category_for_subtypes,signin::IdentityManager * identity_manager,std::unique_ptr<GCMClientFactory> gcm_client_factory,const scoped_refptr<base::SequencedTaskRunner> & ui_task_runner,const scoped_refptr<base::SequencedTaskRunner> & io_task_runner,scoped_refptr<base::SequencedTaskRunner> & blocking_task_runner)131 GCMProfileService::GCMProfileService(
132     PrefService* prefs,
133     base::FilePath path,
134     base::RepeatingCallback<void(
135         base::WeakPtr<GCMProfileService>,
136         mojo::PendingReceiver<network::mojom::ProxyResolvingSocketFactory>)>
137         get_socket_factory_callback,
138     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
139     network::NetworkConnectionTracker* network_connection_tracker,
140     version_info::Channel channel,
141     const std::string& product_category_for_subtypes,
142     signin::IdentityManager* identity_manager,
143     std::unique_ptr<GCMClientFactory> gcm_client_factory,
144     const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner,
145     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner,
146     scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner)
147     : identity_manager_(identity_manager),
148       url_loader_factory_(std::move(url_loader_factory)) {
149   signin::IdentityManager::AccountIdMigrationState id_migration =
150       identity_manager_->GetAccountIdMigrationState();
151   bool remove_account_mappings_with_email_key =
152       (id_migration == signin::IdentityManager::MIGRATION_IN_PROGRESS) ||
153       (id_migration == signin::IdentityManager::MIGRATION_DONE);
154   driver_ = CreateGCMDriverDesktop(
155       std::move(gcm_client_factory), prefs,
156       path.Append(gcm_driver::kGCMStoreDirname),
157       remove_account_mappings_with_email_key,
158       base::BindRepeating(get_socket_factory_callback,
159                           weak_ptr_factory_.GetWeakPtr()),
160       url_loader_factory_, network_connection_tracker, channel,
161       product_category_for_subtypes, ui_task_runner, io_task_runner,
162       blocking_task_runner);
163 
164   identity_observer_.reset(new IdentityObserver(
165       identity_manager_, url_loader_factory_, driver_.get()));
166 }
167 #endif  // BUILDFLAG(USE_GCM_FROM_PLATFORM)
168 
GCMProfileService()169 GCMProfileService::GCMProfileService() {}
170 
~GCMProfileService()171 GCMProfileService::~GCMProfileService() {}
172 
Shutdown()173 void GCMProfileService::Shutdown() {
174 #if !BUILDFLAG(USE_GCM_FROM_PLATFORM)
175   identity_observer_.reset();
176 #endif  // !BUILDFLAG(USE_GCM_FROM_PLATFORM)
177   if (driver_) {
178     driver_->Shutdown();
179     driver_.reset();
180   }
181 }
182 
SetDriverForTesting(std::unique_ptr<GCMDriver> driver)183 void GCMProfileService::SetDriverForTesting(std::unique_ptr<GCMDriver> driver) {
184   driver_ = std::move(driver);
185 
186 #if !BUILDFLAG(USE_GCM_FROM_PLATFORM)
187   if (identity_observer_) {
188     identity_observer_ = std::make_unique<IdentityObserver>(
189         identity_manager_, url_loader_factory_, driver.get());
190   }
191 #endif  // !BUILDFLAG(USE_GCM_FROM_PLATFORM)
192 }
193 
194 }  // namespace gcm
195