Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: components/gcm_driver/gcm_driver_desktop.cc

Issue 1137463003: Support getting and deleting token for Instance ID. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add new files Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/gcm_driver/gcm_driver_desktop.h" 5 #include "components/gcm_driver/gcm_driver_desktop.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
12 #include "base/location.h" 12 #include "base/location.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
15 #include "base/profiler/scoped_tracker.h" 15 #include "base/profiler/scoped_tracker.h"
16 #include "base/sequenced_task_runner.h" 16 #include "base/sequenced_task_runner.h"
17 #include "base/threading/sequenced_worker_pool.h" 17 #include "base/threading/sequenced_worker_pool.h"
18 #include "components/gcm_driver/gcm_account_mapper.h" 18 #include "components/gcm_driver/gcm_account_mapper.h"
19 #include "components/gcm_driver/gcm_app_handler.h" 19 #include "components/gcm_driver/gcm_app_handler.h"
20 #include "components/gcm_driver/gcm_channel_status_syncer.h" 20 #include "components/gcm_driver/gcm_channel_status_syncer.h"
21 #include "components/gcm_driver/gcm_client_factory.h" 21 #include "components/gcm_driver/gcm_client_factory.h"
22 #include "components/gcm_driver/gcm_delayed_task_controller.h" 22 #include "components/gcm_driver/gcm_delayed_task_controller.h"
23 #include "components/gcm_driver/instance_id/instance_id_impl.h"
23 #include "components/gcm_driver/system_encryptor.h" 24 #include "components/gcm_driver/system_encryptor.h"
24 #include "google_apis/gcm/engine/account_mapping.h" 25 #include "google_apis/gcm/engine/account_mapping.h"
25 #include "net/base/ip_endpoint.h" 26 #include "net/base/ip_endpoint.h"
26 #include "net/url_request/url_request_context_getter.h" 27 #include "net/url_request/url_request_context_getter.h"
27 28
28 #if defined(OS_CHROMEOS) 29 #if defined(OS_CHROMEOS)
29 #include "components/timers/alarm_timer_chromeos.h" 30 #include "components/timers/alarm_timer_chromeos.h"
30 #endif 31 #endif
31 32
32 namespace gcm { 33 namespace gcm {
33 34
34 class GCMDriverDesktop::IOWorker : public GCMClient::Delegate { 35 class GCMDriverDesktop::IOWorker : public GCMClient::Delegate {
35 public: 36 public:
36 // Called on UI thread. 37 // Called on UI thread.
37 IOWorker(const scoped_refptr<base::SequencedTaskRunner>& ui_thread, 38 IOWorker(const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
38 const scoped_refptr<base::SequencedTaskRunner>& io_thread); 39 const scoped_refptr<base::SequencedTaskRunner>& io_thread);
39 virtual ~IOWorker(); 40 virtual ~IOWorker();
40 41
41 // Overridden from GCMClient::Delegate: 42 // Overridden from GCMClient::Delegate:
42 // Called on IO thread. 43 // Called on IO thread.
43 void OnRegisterFinished(const std::string& app_id, 44 void OnRegisterFinished(const linked_ptr<RegistrationInfo>& registration_info,
44 const std::string& registration_id, 45 const std::string& registration_id,
45 GCMClient::Result result) override; 46 GCMClient::Result result) override;
46 void OnUnregisterFinished(const std::string& app_id, 47 void OnUnregisterFinished(
47 GCMClient::Result result) override; 48 const linked_ptr<RegistrationInfo>& registration_info,
49 GCMClient::Result result) override;
48 void OnSendFinished(const std::string& app_id, 50 void OnSendFinished(const std::string& app_id,
49 const std::string& message_id, 51 const std::string& message_id,
50 GCMClient::Result result) override; 52 GCMClient::Result result) override;
51 void OnMessageReceived(const std::string& app_id, 53 void OnMessageReceived(const std::string& app_id,
52 const GCMClient::IncomingMessage& message) override; 54 const GCMClient::IncomingMessage& message) override;
53 void OnMessagesDeleted(const std::string& app_id) override; 55 void OnMessagesDeleted(const std::string& app_id) override;
54 void OnMessageSendError( 56 void OnMessageSendError(
55 const std::string& app_id, 57 const std::string& app_id,
56 const GCMClient::SendErrorDetails& send_error_details) override; 58 const GCMClient::SendErrorDetails& send_error_details) override;
57 void OnSendAcknowledged(const std::string& app_id, 59 void OnSendAcknowledged(const std::string& app_id,
(...skipping 26 matching lines...) Expand all
84 void SetAccountTokens( 86 void SetAccountTokens(
85 const std::vector<GCMClient::AccountTokenInfo>& account_tokens); 87 const std::vector<GCMClient::AccountTokenInfo>& account_tokens);
86 void UpdateAccountMapping(const AccountMapping& account_mapping); 88 void UpdateAccountMapping(const AccountMapping& account_mapping);
87 void RemoveAccountMapping(const std::string& account_id); 89 void RemoveAccountMapping(const std::string& account_id);
88 void SetLastTokenFetchTime(const base::Time& time); 90 void SetLastTokenFetchTime(const base::Time& time);
89 void WakeFromSuspendForHeartbeat(bool wake); 91 void WakeFromSuspendForHeartbeat(bool wake);
90 void AddInstanceIDData(const std::string& app_id, 92 void AddInstanceIDData(const std::string& app_id,
91 const std::string& instance_id_data); 93 const std::string& instance_id_data);
92 void RemoveInstanceIDData(const std::string& app_id); 94 void RemoveInstanceIDData(const std::string& app_id);
93 void GetInstanceIDData(const std::string& app_id); 95 void GetInstanceIDData(const std::string& app_id);
96 void GetToken(const std::string& app_id,
97 const std::string& authorized_entity,
98 const std::string& scope,
99 const std::map<std::string, std::string>& options);
100 void DeleteToken(const std::string& app_id,
101 const std::string& authorized_entity,
102 const std::string& scope);
94 103
95 // For testing purpose. Can be called from UI thread. Use with care. 104 // For testing purpose. Can be called from UI thread. Use with care.
96 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); } 105 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); }
97 106
98 private: 107 private:
99 scoped_refptr<base::SequencedTaskRunner> ui_thread_; 108 scoped_refptr<base::SequencedTaskRunner> ui_thread_;
100 scoped_refptr<base::SequencedTaskRunner> io_thread_; 109 scoped_refptr<base::SequencedTaskRunner> io_thread_;
101 110
102 base::WeakPtr<GCMDriverDesktop> service_; 111 base::WeakPtr<GCMDriverDesktop> service_;
103 112
(...skipping 30 matching lines...) Expand all
134 143
135 gcm_client_->Initialize(chrome_build_info, 144 gcm_client_->Initialize(chrome_build_info,
136 store_path, 145 store_path,
137 blocking_task_runner, 146 blocking_task_runner,
138 request_context, 147 request_context,
139 make_scoped_ptr<Encryptor>(new SystemEncryptor), 148 make_scoped_ptr<Encryptor>(new SystemEncryptor),
140 this); 149 this);
141 } 150 }
142 151
143 void GCMDriverDesktop::IOWorker::OnRegisterFinished( 152 void GCMDriverDesktop::IOWorker::OnRegisterFinished(
144 const std::string& app_id, 153 const linked_ptr<RegistrationInfo>& registration_info,
145 const std::string& registration_id, 154 const std::string& registration_id,
146 GCMClient::Result result) { 155 GCMClient::Result result) {
147 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 156 DCHECK(io_thread_->RunsTasksOnCurrentThread());
148 157
149 ui_thread_->PostTask( 158 const GCMRegistrationInfo* gcm_registration_info =
159 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get());
160 if (gcm_registration_info) {
161 ui_thread_->PostTask(
162 FROM_HERE,
163 base::Bind(&GCMDriverDesktop::RegisterFinished,
164 service_,
165 gcm_registration_info->app_id,
166 registration_id,
167 result));
168 }
169
170 const InstanceIDTokenInfo* instance_id_token_info =
171 InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get());
172 if (instance_id_token_info) {
173 ui_thread_->PostTask(
150 FROM_HERE, 174 FROM_HERE,
151 base::Bind(&GCMDriverDesktop::RegisterFinished, service_, app_id, 175 base::Bind(&GCMDriverDesktop::GetTokenFinished,
152 registration_id, result)); 176 service_,
177 instance_id_token_info->app_id,
178 instance_id_token_info->authorized_entity,
179 instance_id_token_info->scope,
180 registration_id,
181 result));
182 }
153 } 183 }
154 184
155 void GCMDriverDesktop::IOWorker::OnUnregisterFinished( 185 void GCMDriverDesktop::IOWorker::OnUnregisterFinished(
156 const std::string& app_id, 186 const linked_ptr<RegistrationInfo>& registration_info,
157 GCMClient::Result result) { 187 GCMClient::Result result) {
158 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 188 DCHECK(io_thread_->RunsTasksOnCurrentThread());
159 189
160 ui_thread_->PostTask(FROM_HERE, 190 ui_thread_->PostTask(FROM_HERE,
161 base::Bind(&GCMDriverDesktop::UnregisterFinished, 191 base::Bind(&GCMDriverDesktop::UnregisterFinished,
162 service_, 192 service_,
163 app_id, 193 registration_info->app_id,
164 result)); 194 result));
165 } 195 }
166 196
167 void GCMDriverDesktop::IOWorker::OnSendFinished(const std::string& app_id, 197 void GCMDriverDesktop::IOWorker::OnSendFinished(const std::string& app_id,
168 const std::string& message_id, 198 const std::string& message_id,
169 GCMClient::Result result) { 199 GCMClient::Result result) {
170 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 200 DCHECK(io_thread_->RunsTasksOnCurrentThread());
171 201
172 ui_thread_->PostTask( 202 ui_thread_->PostTask(
173 FROM_HERE, 203 FROM_HERE,
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 291 DCHECK(io_thread_->RunsTasksOnCurrentThread());
262 292
263 gcm_client_->Stop(); 293 gcm_client_->Stop();
264 } 294 }
265 295
266 void GCMDriverDesktop::IOWorker::Register( 296 void GCMDriverDesktop::IOWorker::Register(
267 const std::string& app_id, 297 const std::string& app_id,
268 const std::vector<std::string>& sender_ids) { 298 const std::vector<std::string>& sender_ids) {
269 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 299 DCHECK(io_thread_->RunsTasksOnCurrentThread());
270 300
271 gcm_client_->Register(app_id, sender_ids); 301 scoped_ptr<GCMRegistrationInfo> gcm_info(new GCMRegistrationInfo);
302 gcm_info->app_id = app_id;
303 gcm_info->sender_ids = sender_ids;
304 gcm_client_->Register(make_linked_ptr<RegistrationInfo>(gcm_info.release()));
272 } 305 }
273 306
274 void GCMDriverDesktop::IOWorker::Unregister(const std::string& app_id) { 307 void GCMDriverDesktop::IOWorker::Unregister(const std::string& app_id) {
275 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 308 DCHECK(io_thread_->RunsTasksOnCurrentThread());
276 309
277 gcm_client_->Unregister(app_id); 310 scoped_ptr<GCMRegistrationInfo> gcm_info(new GCMRegistrationInfo);
311 gcm_info->app_id = app_id;
312 gcm_client_->Unregister(
313 make_linked_ptr<RegistrationInfo>(gcm_info.release()));
278 } 314 }
279 315
280 void GCMDriverDesktop::IOWorker::Send( 316 void GCMDriverDesktop::IOWorker::Send(
281 const std::string& app_id, 317 const std::string& app_id,
282 const std::string& receiver_id, 318 const std::string& receiver_id,
283 const GCMClient::OutgoingMessage& message) { 319 const GCMClient::OutgoingMessage& message) {
284 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 320 DCHECK(io_thread_->RunsTasksOnCurrentThread());
285 321
286 gcm_client_->Send(app_id, receiver_id, message); 322 gcm_client_->Send(app_id, receiver_id, message);
287 } 323 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 std::string instance_id_data; 407 std::string instance_id_data;
372 if (gcm_client_.get()) 408 if (gcm_client_.get())
373 instance_id_data = gcm_client_->GetInstanceIDData(app_id); 409 instance_id_data = gcm_client_->GetInstanceIDData(app_id);
374 410
375 ui_thread_->PostTask( 411 ui_thread_->PostTask(
376 FROM_HERE, 412 FROM_HERE,
377 base::Bind(&GCMDriverDesktop::GetInstanceIDDataFinished, 413 base::Bind(&GCMDriverDesktop::GetInstanceIDDataFinished,
378 service_, app_id, instance_id_data)); 414 service_, app_id, instance_id_data));
379 } 415 }
380 416
417 void GCMDriverDesktop::IOWorker::GetToken(
418 const std::string& app_id,
419 const std::string& authorized_entity,
420 const std::string& scope,
421 const std::map<std::string, std::string>& options) {
422 DCHECK(io_thread_->RunsTasksOnCurrentThread());
423
424 scoped_ptr<InstanceIDTokenInfo> instance_id_token_info(
425 new InstanceIDTokenInfo);
426 instance_id_token_info->app_id = app_id;
427 instance_id_token_info->authorized_entity = authorized_entity;
428 instance_id_token_info->scope = scope;
429 instance_id_token_info->options = options;
430 gcm_client_->Register(
431 make_linked_ptr<RegistrationInfo>(instance_id_token_info.release()));
432 }
433
434 void GCMDriverDesktop::IOWorker::DeleteToken(
435 const std::string& app_id,
436 const std::string& authorized_entity,
437 const std::string& scope) {
438 scoped_ptr<InstanceIDTokenInfo> instance_id_token_info(
439 new InstanceIDTokenInfo);
440 instance_id_token_info->app_id = app_id;
441 instance_id_token_info->authorized_entity = authorized_entity;
442 instance_id_token_info->scope = scope;
443 gcm_client_->Unregister(
444 make_linked_ptr<RegistrationInfo>(instance_id_token_info.release()));
445 }
446
381 void GCMDriverDesktop::IOWorker::WakeFromSuspendForHeartbeat(bool wake) { 447 void GCMDriverDesktop::IOWorker::WakeFromSuspendForHeartbeat(bool wake) {
382 #if defined(OS_CHROMEOS) 448 #if defined(OS_CHROMEOS)
383 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 449 DCHECK(io_thread_->RunsTasksOnCurrentThread());
384 450
385 scoped_ptr<base::Timer> timer; 451 scoped_ptr<base::Timer> timer;
386 if (wake) 452 if (wake)
387 timer.reset(new timers::SimpleAlarmTimer()); 453 timer.reset(new timers::SimpleAlarmTimer());
388 else 454 else
389 timer.reset(new base::Timer(true, false)); 455 timer.reset(new base::Timer(true, false));
390 456
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 753
688 last_token_fetch_time_ = time; 754 last_token_fetch_time_ = time;
689 755
690 io_thread_->PostTask( 756 io_thread_->PostTask(
691 FROM_HERE, 757 FROM_HERE,
692 base::Bind(&GCMDriverDesktop::IOWorker::SetLastTokenFetchTime, 758 base::Bind(&GCMDriverDesktop::IOWorker::SetLastTokenFetchTime,
693 base::Unretained(io_worker_.get()), 759 base::Unretained(io_worker_.get()),
694 time)); 760 time));
695 } 761 }
696 762
697 InstanceIDStore* GCMDriverDesktop::GetInstanceIDStore() { 763 InstanceIDHandler* GCMDriverDesktop::GetInstanceIDHandler() {
698 return this; 764 return this;
699 } 765 }
700 766
767 void GCMDriverDesktop::GetToken(
768 const std::string& app_id,
769 const std::string& authorized_entity,
770 const std::string& scope,
771 const std::map<std::string, std::string>& options,
772 const GetTokenCallback& callback) {
773 DCHECK(!app_id.empty());
774 DCHECK(!authorized_entity.empty());
775 DCHECK(!scope.empty());
776 DCHECK(!callback.is_null());
777
778 GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
779 if (result != GCMClient::SUCCESS) {
780 callback.Run(std::string(), result);
781 return;
782 }
783
784 // If previous GetToken operation is still in progress, bail out.
785 TokenTuple tuple_key(app_id, authorized_entity, scope);
786 if (get_token_callbacks_.find(tuple_key) != get_token_callbacks_.end()) {
787 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
788 return;
789 }
790
791 get_token_callbacks_[tuple_key] = callback;
792
793 io_thread_->PostTask(
794 FROM_HERE,
795 base::Bind(&GCMDriverDesktop::IOWorker::GetToken,
796 base::Unretained(io_worker_.get()),
797 app_id,
798 authorized_entity,
799 scope,
800 options));
801 }
802
803 void GCMDriverDesktop::DeleteToken(const std::string& app_id,
804 const std::string& authorized_entity,
805 const std::string& scope,
806 const DeleteTokenCallback& callback) {
807 DCHECK(!app_id.empty());
808 DCHECK(!authorized_entity.empty());
809 DCHECK(!scope.empty());
810 DCHECK(!callback.is_null());
811
812 GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
813 if (result != GCMClient::SUCCESS) {
814 callback.Run(result);
815 return;
816 }
817
818 // If previous GetToken operation is still in progress, bail out.
819 TokenTuple tuple_key(app_id, authorized_entity, scope);
820 if (delete_token_callbacks_.find(tuple_key) !=
821 delete_token_callbacks_.end()) {
822 callback.Run(GCMClient::ASYNC_OPERATION_PENDING);
823 return;
824 }
825
826 delete_token_callbacks_[tuple_key] = callback;
827
828 io_thread_->PostTask(
829 FROM_HERE,
830 base::Bind(&GCMDriverDesktop::IOWorker::DeleteToken,
831 base::Unretained(io_worker_.get()),
832 app_id,
833 authorized_entity,
834 scope));
835 }
836
701 void GCMDriverDesktop::AddInstanceIDData( 837 void GCMDriverDesktop::AddInstanceIDData(
702 const std::string& app_id, 838 const std::string& app_id,
703 const std::string& instance_id_data) { 839 const std::string& instance_id_data) {
704 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 840 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
705 841
706 io_thread_->PostTask( 842 io_thread_->PostTask(
707 FROM_HERE, 843 FROM_HERE,
708 base::Bind(&GCMDriverDesktop::IOWorker::AddInstanceIDData, 844 base::Bind(&GCMDriverDesktop::IOWorker::AddInstanceIDData,
709 base::Unretained(io_worker_.get()), 845 base::Unretained(io_worker_.get()),
710 app_id, 846 app_id,
(...skipping 23 matching lines...) Expand all
734 } 870 }
735 871
736 void GCMDriverDesktop::GetInstanceIDDataFinished( 872 void GCMDriverDesktop::GetInstanceIDDataFinished(
737 const std::string& app_id, 873 const std::string& app_id,
738 const std::string& instance_id_data) { 874 const std::string& instance_id_data) {
739 DCHECK(get_instance_id_data_callbacks_.count(app_id)); 875 DCHECK(get_instance_id_data_callbacks_.count(app_id));
740 get_instance_id_data_callbacks_[app_id].Run(instance_id_data); 876 get_instance_id_data_callbacks_[app_id].Run(instance_id_data);
741 get_instance_id_data_callbacks_.erase(app_id); 877 get_instance_id_data_callbacks_.erase(app_id);
742 } 878 }
743 879
880 void GCMDriverDesktop::GetTokenFinished(const std::string& app_id,
881 const std::string& authorized_entity,
882 const std::string& scope,
883 const std::string& registration_id,
fgorski 2015/05/13 18:32:39 nit: we could just call it token
jianli 2015/05/13 22:42:56 Done.
884 GCMClient::Result result) {
885 TokenTuple tuple_key(app_id, authorized_entity, scope);
886 auto callback_iter = get_token_callbacks_.find(tuple_key);
887 if (callback_iter == get_token_callbacks_.end()) {
888 // The callback could have been removed when the app is uninstalled.
889 return;
890 }
891
892 GetTokenCallback callback = callback_iter->second;
893 get_token_callbacks_.erase(callback_iter);
894 callback.Run(registration_id, result);
895 }
896
897 void GCMDriverDesktop::DeleteTokenFinished(const std::string& app_id,
898 const std::string& authorized_entity,
899 const std::string& scope,
900 GCMClient::Result result) {
901 TokenTuple tuple_key(app_id, authorized_entity, scope);
902 auto callback_iter = delete_token_callbacks_.find(tuple_key);
903 if (callback_iter == delete_token_callbacks_.end()) {
904 // The callback could have been removed when the app is uninstalled.
905 return;
906 }
907
908 DeleteTokenCallback callback = callback_iter->second;
909 delete_token_callbacks_.erase(callback_iter);
910 callback.Run(result);
911 }
912
744 void GCMDriverDesktop::WakeFromSuspendForHeartbeat(bool wake) { 913 void GCMDriverDesktop::WakeFromSuspendForHeartbeat(bool wake) {
745 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 914 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
746 915
747 wake_from_suspend_enabled_ = wake; 916 wake_from_suspend_enabled_ = wake;
748 917
749 // The GCM service has not been initialized. 918 // The GCM service has not been initialized.
750 if (!delayed_task_controller_) 919 if (!delayed_task_controller_)
751 return; 920 return;
752 921
753 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 922 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 const GCMClient::GCMStatistics& stats) { 1091 const GCMClient::GCMStatistics& stats) {
923 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 1092 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
924 1093
925 // Normally request_gcm_statistics_callback_ would not be null. 1094 // Normally request_gcm_statistics_callback_ would not be null.
926 if (!request_gcm_statistics_callback_.is_null()) 1095 if (!request_gcm_statistics_callback_.is_null())
927 request_gcm_statistics_callback_.Run(stats); 1096 request_gcm_statistics_callback_.Run(stats);
928 else 1097 else
929 LOG(WARNING) << "request_gcm_statistics_callback_ is NULL."; 1098 LOG(WARNING) << "request_gcm_statistics_callback_ is NULL.";
930 } 1099 }
931 1100
1101 bool GCMDriverDesktop::TokenTupleComparer::operator()(
1102 const TokenTuple& a, const TokenTuple& b) const {
fgorski 2015/05/13 18:32:39 pretty cool
jianli 2015/05/13 22:42:56 Acknowledged.
1103 if (get<0>(a) < get<0>(b))
1104 return true;
1105 if (get<0>(a) > get<0>(b))
1106 return false;
1107
1108 if (get<1>(a) < get<1>(b))
1109 return true;
1110 if (get<1>(a) > get<1>(b))
1111 return false;
1112
1113 return get<2>(a) < get<2>(b);
1114 }
1115
932 } // namespace gcm 1116 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698