Remove linux_chromium_gn_dbg from the chromium CQ.
[chromium-blink-merge.git] / components / gcm_driver / instance_id / instance_id_impl.cc
blob998ad8593f7da75f847ddb0aea0616cb10ab2fc1
1 // Copyright 2015 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.
5 #include "components/gcm_driver/instance_id/instance_id_impl.h"
7 #include <algorithm>
8 #include "base/base64.h"
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "components/gcm_driver/gcm_driver_desktop.h"
15 #include "crypto/random.h"
17 namespace instance_id {
19 namespace {
21 InstanceID::Result GCMClientResultToInstanceIDResult(
22 gcm::GCMClient::Result result) {
23 switch (result) {
24 case gcm::GCMClient::SUCCESS:
25 return InstanceID::SUCCESS;
26 case gcm::GCMClient::INVALID_PARAMETER:
27 return InstanceID::INVALID_PARAMETER;
28 case gcm::GCMClient::ASYNC_OPERATION_PENDING:
29 return InstanceID::ASYNC_OPERATION_PENDING;
30 case gcm::GCMClient::GCM_DISABLED:
31 return InstanceID::DISABLED;
32 case gcm::GCMClient::NETWORK_ERROR:
33 return InstanceID::NETWORK_ERROR;
34 case gcm::GCMClient::SERVER_ERROR:
35 return InstanceID::SERVER_ERROR;
36 case gcm::GCMClient::UNKNOWN_ERROR:
37 return InstanceID::UNKNOWN_ERROR;
38 default:
39 NOTREACHED() << "Unexpected value of result cannot be converted: "
40 << result;
42 return InstanceID::UNKNOWN_ERROR;
45 } // namespace
47 // static
48 scoped_ptr<InstanceID> InstanceID::Create(const std::string& app_id,
49 gcm::GCMDriver* gcm_driver) {
50 return make_scoped_ptr(new InstanceIDImpl(app_id, gcm_driver));
53 InstanceIDImpl::InstanceIDImpl(const std::string& app_id,
54 gcm::GCMDriver* gcm_driver)
55 : InstanceID(app_id),
56 gcm_driver_(gcm_driver),
57 load_from_store_(false),
58 weak_ptr_factory_(this) {
59 GetInstanceIDHandler()->GetInstanceIDData(
60 app_id,
61 base::Bind(&InstanceIDImpl::GetInstanceIDDataCompleted,
62 weak_ptr_factory_.GetWeakPtr()));
65 InstanceIDImpl::~InstanceIDImpl() {
68 void InstanceIDImpl::GetID(const GetIDCallback& callback) {
69 if (!delayed_task_controller_.CanRunTaskWithoutDelay()) {
70 delayed_task_controller_.AddTask(
71 base::Bind(&InstanceIDImpl::DoGetID,
72 weak_ptr_factory_.GetWeakPtr(),
73 callback));
74 return;
77 DoGetID(callback);
80 void InstanceIDImpl::DoGetID(const GetIDCallback& callback) {
81 EnsureIDGenerated();
82 callback.Run(id_);
85 void InstanceIDImpl::GetCreationTime(const GetCreationTimeCallback& callback) {
86 if (!delayed_task_controller_.CanRunTaskWithoutDelay()) {
87 delayed_task_controller_.AddTask(
88 base::Bind(&InstanceIDImpl::DoGetCreationTime,
89 weak_ptr_factory_.GetWeakPtr(),
90 callback));
91 return;
94 DoGetCreationTime(callback);
97 void InstanceIDImpl::DoGetCreationTime(
98 const GetCreationTimeCallback& callback) {
99 callback.Run(creation_time_);
102 void InstanceIDImpl::GetToken(
103 const std::string& authorized_entity,
104 const std::string& scope,
105 const std::map<std::string, std::string>& options,
106 const GetTokenCallback& callback) {
107 DCHECK(!authorized_entity.empty());
108 DCHECK(!scope.empty());
110 if (!delayed_task_controller_.CanRunTaskWithoutDelay()) {
111 delayed_task_controller_.AddTask(
112 base::Bind(&InstanceIDImpl::DoGetToken,
113 weak_ptr_factory_.GetWeakPtr(),
114 authorized_entity,
115 scope,
116 options,
117 callback));
118 return;
121 DoGetToken(authorized_entity, scope, options, callback);
124 void InstanceIDImpl::DoGetToken(
125 const std::string& authorized_entity,
126 const std::string& scope,
127 const std::map<std::string, std::string>& options,
128 const GetTokenCallback& callback) {
129 EnsureIDGenerated();
131 GetInstanceIDHandler()->GetToken(
132 app_id(),
133 authorized_entity,
134 scope,
135 options,
136 base::Bind(&InstanceIDImpl::OnGetTokenCompleted,
137 weak_ptr_factory_.GetWeakPtr(),
138 callback));
141 void InstanceIDImpl::DeleteToken(const std::string& authorized_entity,
142 const std::string& scope,
143 const DeleteTokenCallback& callback) {
144 DCHECK(!authorized_entity.empty());
145 DCHECK(!scope.empty());
147 if (!delayed_task_controller_.CanRunTaskWithoutDelay()) {
148 delayed_task_controller_.AddTask(
149 base::Bind(&InstanceIDImpl::DoDeleteToken,
150 weak_ptr_factory_.GetWeakPtr(),
151 authorized_entity,
152 scope,
153 callback));
154 return;
157 DoDeleteToken(authorized_entity, scope, callback);
160 void InstanceIDImpl::DoDeleteToken(
161 const std::string& authorized_entity,
162 const std::string& scope,
163 const DeleteTokenCallback& callback) {
164 // Nothing to delete if the ID has not been generated.
165 if (id_.empty()) {
166 callback.Run(InstanceID::INVALID_PARAMETER);
167 return;
170 GetInstanceIDHandler()->DeleteToken(
171 app_id(),
172 authorized_entity,
173 scope,
174 base::Bind(&InstanceIDImpl::OnDeleteTokenCompleted,
175 weak_ptr_factory_.GetWeakPtr(),
176 callback));
179 void InstanceIDImpl::DeleteID(const DeleteIDCallback& callback) {
180 if (!delayed_task_controller_.CanRunTaskWithoutDelay()) {
181 delayed_task_controller_.AddTask(
182 base::Bind(&InstanceIDImpl::DoDeleteID,
183 weak_ptr_factory_.GetWeakPtr(),
184 callback));
185 return;
188 DoDeleteID(callback);
191 void InstanceIDImpl::DoDeleteID(const DeleteIDCallback& callback) {
192 // Nothing to do if ID has not been generated.
193 if (id_.empty()) {
194 callback.Run(InstanceID::SUCCESS);
195 return;
198 GetInstanceIDHandler()->DeleteAllTokensForApp(
199 app_id(),
200 base::Bind(&InstanceIDImpl::OnDeleteIDCompleted,
201 weak_ptr_factory_.GetWeakPtr(),
202 callback));
204 GetInstanceIDHandler()->RemoveInstanceIDData(app_id());
206 id_.clear();
207 creation_time_ = base::Time();
210 void InstanceIDImpl::OnGetTokenCompleted(const GetTokenCallback& callback,
211 const std::string& token,
212 gcm::GCMClient::Result result) {
213 callback.Run(token, GCMClientResultToInstanceIDResult(result));
216 void InstanceIDImpl::OnDeleteTokenCompleted(
217 const DeleteTokenCallback& callback,
218 gcm::GCMClient::Result result) {
219 callback.Run(GCMClientResultToInstanceIDResult(result));
222 void InstanceIDImpl::OnDeleteIDCompleted(
223 const DeleteIDCallback& callback,
224 gcm::GCMClient::Result result) {
225 callback.Run(GCMClientResultToInstanceIDResult(result));
228 void InstanceIDImpl::GetInstanceIDDataCompleted(
229 const std::string& instance_id,
230 const std::string& extra_data) {
231 id_ = instance_id;
233 if (extra_data.empty()) {
234 creation_time_ = base::Time();
235 } else {
236 int64 time_internal = 0LL;
237 if (!base::StringToInt64(extra_data, &time_internal)) {
238 DVLOG(1) << "Failed to parse the time data: " + extra_data;
239 return;
241 creation_time_ = base::Time::FromInternalValue(time_internal);
244 delayed_task_controller_.SetReady();
247 gcm::InstanceIDHandler* InstanceIDImpl::GetInstanceIDHandler() const {
248 gcm::InstanceIDHandler* handler = gcm_driver_->GetInstanceIDHandler();
249 DCHECK(handler);
250 return handler;
253 void InstanceIDImpl::EnsureIDGenerated() {
254 if (!id_.empty())
255 return;
257 // Now produce the ID in the following steps:
259 // 1) Generates the random number in 8 bytes which is required by the server.
260 // We don't want to be strictly cryptographically secure. The server might
261 // reject the ID if there is a conflict or problem.
262 uint8 bytes[kInstanceIDByteLength];
263 crypto::RandBytes(bytes, sizeof(bytes));
265 // 2) Transforms the first 4 bits to 0x7. Note that this is required by the
266 // server.
267 bytes[0] &= 0x0f;
268 bytes[0] |= 0x70;
270 // 3) Encode the value in Android-compatible base64 scheme:
271 // * URL safe: '/' replaced by '_' and '+' replaced by '-'.
272 // * No padding: any trailing '=' will be removed.
273 base::Base64Encode(
274 base::StringPiece(reinterpret_cast<const char*>(bytes), sizeof(bytes)),
275 &id_);
276 std::replace(id_.begin(), id_.end(), '+', '-');
277 std::replace(id_.begin(), id_.end(), '/', '_');
278 id_.erase(std::remove(id_.begin(), id_.end(), '='), id_.end());
280 creation_time_ = base::Time::Now();
282 // Save to the persistent store.
283 GetInstanceIDHandler()->AddInstanceIDData(
284 app_id(),
285 id_,
286 base::Int64ToString(creation_time_.ToInternalValue()));
289 } // namespace instance_id