OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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/instance_id/instance_id_impl.h" | 5 #include "components/gcm_driver/instance_id/instance_id_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include "base/base64.h" | 8 #include "base/base64.h" |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
13 #include "components/gcm_driver/gcm_driver_desktop.h" | 13 #include "components/gcm_driver/gcm_driver_desktop.h" |
14 #include "crypto/random.h" | 14 #include "crypto/random.h" |
15 | 15 |
16 namespace instance_id { | 16 namespace instance_id { |
17 | 17 |
| 18 namespace { |
| 19 |
| 20 InstanceID::Result GCMClientResultToInstanceIDResult( |
| 21 gcm::GCMClient::Result result) { |
| 22 switch (result) { |
| 23 case gcm::GCMClient::SUCCESS: |
| 24 return InstanceID::SUCCESS; |
| 25 case gcm::GCMClient::INVALID_PARAMETER: |
| 26 return InstanceID::INVALID_PARAMETER; |
| 27 case gcm::GCMClient::ASYNC_OPERATION_PENDING: |
| 28 return InstanceID::ASYNC_OPERATION_PENDING; |
| 29 case gcm::GCMClient::GCM_DISABLED: |
| 30 return InstanceID::DISABLED; |
| 31 case gcm::GCMClient::NETWORK_ERROR: |
| 32 return InstanceID::NETWORK_ERROR; |
| 33 case gcm::GCMClient::SERVER_ERROR: |
| 34 return InstanceID::SERVER_ERROR; |
| 35 case gcm::GCMClient::UNKNOWN_ERROR: |
| 36 return InstanceID::UNKNOWN_ERROR; |
| 37 default: |
| 38 NOTREACHED() << "Unexpected value of result cannot be converted: " |
| 39 << result; |
| 40 } |
| 41 return InstanceID::UNKNOWN_ERROR; |
| 42 } |
| 43 |
| 44 } // namespace |
| 45 |
18 // static | 46 // static |
19 InstanceID* InstanceID::Create(const std::string& app_id, | 47 InstanceID* InstanceID::Create(const std::string& app_id, |
20 gcm::GCMDriver* gcm_driver) { | 48 gcm::GCMDriver* gcm_driver) { |
21 return new InstanceIDImpl(app_id, gcm_driver); | 49 return new InstanceIDImpl(app_id, gcm_driver); |
22 } | 50 } |
23 | 51 |
24 InstanceIDImpl::InstanceIDImpl(const std::string& app_id, | 52 InstanceIDImpl::InstanceIDImpl(const std::string& app_id, |
25 gcm::GCMDriver* gcm_driver) | 53 gcm::GCMDriver* gcm_driver) |
26 : InstanceID(app_id), | 54 : InstanceID(app_id), |
27 gcm_driver_(gcm_driver), | 55 gcm_driver_(gcm_driver), |
28 load_from_store_(false), | 56 load_from_store_(false), |
29 weak_ptr_factory_(this) { | 57 weak_ptr_factory_(this) { |
30 gcm_driver_->GetInstanceIDStore()->GetInstanceIDData( | 58 GetInstanceIDHandler()->GetInstanceIDData( |
31 app_id, | 59 app_id, |
32 base::Bind(&InstanceIDImpl::GetInstanceIDDataCompleted, | 60 base::Bind(&InstanceIDImpl::GetInstanceIDDataCompleted, |
33 weak_ptr_factory_.GetWeakPtr())); | 61 weak_ptr_factory_.GetWeakPtr())); |
34 } | 62 } |
35 | 63 |
36 InstanceIDImpl::~InstanceIDImpl() { | 64 InstanceIDImpl::~InstanceIDImpl() { |
37 } | 65 } |
38 | 66 |
39 void InstanceIDImpl::GetID(const GetIDCallback& callback) { | 67 void InstanceIDImpl::GetID(const GetIDCallback& callback) { |
40 if (!delayed_task_controller_.CanRunTaskWithoutDelay()) { | 68 if (!delayed_task_controller_.CanRunTaskWithoutDelay()) { |
(...skipping 27 matching lines...) Expand all Loading... |
68 void InstanceIDImpl::DoGetCreationTime( | 96 void InstanceIDImpl::DoGetCreationTime( |
69 const GetCreationTimeCallback& callback) { | 97 const GetCreationTimeCallback& callback) { |
70 callback.Run(creation_time_); | 98 callback.Run(creation_time_); |
71 } | 99 } |
72 | 100 |
73 void InstanceIDImpl::GetToken( | 101 void InstanceIDImpl::GetToken( |
74 const std::string& authorized_entity, | 102 const std::string& authorized_entity, |
75 const std::string& scope, | 103 const std::string& scope, |
76 const std::map<std::string, std::string>& options, | 104 const std::map<std::string, std::string>& options, |
77 const GetTokenCallback& callback) { | 105 const GetTokenCallback& callback) { |
78 NOTIMPLEMENTED(); | 106 if (!delayed_task_controller_.CanRunTaskWithoutDelay()) { |
| 107 delayed_task_controller_.AddTask( |
| 108 base::Bind(&InstanceIDImpl::DoGetToken, |
| 109 weak_ptr_factory_.GetWeakPtr(), |
| 110 authorized_entity, |
| 111 scope, |
| 112 options, |
| 113 callback)); |
| 114 return; |
| 115 } |
| 116 |
| 117 DoGetToken(authorized_entity, scope, options, callback); |
| 118 } |
| 119 |
| 120 void InstanceIDImpl::DoGetToken( |
| 121 const std::string& authorized_entity, |
| 122 const std::string& scope, |
| 123 const std::map<std::string, std::string>& options, |
| 124 const GetTokenCallback& callback) { |
| 125 EnsureIDGenerated(); |
| 126 |
| 127 GetInstanceIDHandler()->GetToken( |
| 128 app_id(), |
| 129 authorized_entity, |
| 130 scope, |
| 131 options, |
| 132 base::Bind(&InstanceIDImpl::OnGetTokenCompleted, |
| 133 weak_ptr_factory_.GetWeakPtr(), |
| 134 callback)); |
79 } | 135 } |
80 | 136 |
81 void InstanceIDImpl::DeleteToken(const std::string& authorized_entity, | 137 void InstanceIDImpl::DeleteToken(const std::string& authorized_entity, |
82 const std::string& scope, | 138 const std::string& scope, |
83 const DeleteTokenCallback& callback) { | 139 const DeleteTokenCallback& callback) { |
84 NOTIMPLEMENTED(); | 140 if (!delayed_task_controller_.CanRunTaskWithoutDelay()) { |
| 141 delayed_task_controller_.AddTask( |
| 142 base::Bind(&InstanceIDImpl::DoDeleteToken, |
| 143 weak_ptr_factory_.GetWeakPtr(), |
| 144 authorized_entity, |
| 145 scope, |
| 146 callback)); |
| 147 return; |
| 148 } |
| 149 |
| 150 DoDeleteToken(authorized_entity, scope, callback); |
| 151 } |
| 152 |
| 153 void InstanceIDImpl::DoDeleteToken( |
| 154 const std::string& authorized_entity, |
| 155 const std::string& scope, |
| 156 const DeleteTokenCallback& callback) { |
| 157 // Nothing to delete if the ID has not been generated. |
| 158 if (id_.empty()) { |
| 159 callback.Run(InstanceID::SUCCESS); |
| 160 return; |
| 161 } |
| 162 |
| 163 GetInstanceIDHandler()->DeleteToken( |
| 164 app_id(), |
| 165 authorized_entity, |
| 166 scope, |
| 167 base::Bind(&InstanceIDImpl::OnDeleteTokenCompleted, |
| 168 weak_ptr_factory_.GetWeakPtr(), |
| 169 callback)); |
85 } | 170 } |
86 | 171 |
87 void InstanceIDImpl::DeleteID(const DeleteIDCallback& callback) { | 172 void InstanceIDImpl::DeleteID(const DeleteIDCallback& callback) { |
88 gcm_driver_->GetInstanceIDStore()->RemoveInstanceIDData(app_id()); | 173 if (!delayed_task_controller_.CanRunTaskWithoutDelay()) { |
| 174 delayed_task_controller_.AddTask( |
| 175 base::Bind(&InstanceIDImpl::DoDeleteID, |
| 176 weak_ptr_factory_.GetWeakPtr(), |
| 177 callback)); |
| 178 return; |
| 179 } |
| 180 |
| 181 DoDeleteID(callback); |
| 182 } |
| 183 |
| 184 void InstanceIDImpl::DoDeleteID(const DeleteIDCallback& callback) { |
| 185 // Nothing to do if ID has not been generated. |
| 186 if (id_.empty()) { |
| 187 callback.Run(InstanceID::SUCCESS); |
| 188 return; |
| 189 } |
| 190 |
| 191 GetInstanceIDHandler()->DeleteToken( |
| 192 app_id(), |
| 193 "*", |
| 194 "*", |
| 195 base::Bind(&InstanceIDImpl::OnDeleteIDCompleted, |
| 196 weak_ptr_factory_.GetWeakPtr(), |
| 197 callback)); |
| 198 |
| 199 GetInstanceIDHandler()->RemoveInstanceIDData(app_id()); |
89 | 200 |
90 id_.clear(); | 201 id_.clear(); |
91 creation_time_ = base::Time(); | 202 creation_time_ = base::Time(); |
| 203 } |
92 | 204 |
93 base::MessageLoop::current()->PostTask( | 205 void InstanceIDImpl::OnGetTokenCompleted(const GetTokenCallback& callback, |
94 FROM_HERE, | 206 const std::string& token, |
95 base::Bind(callback, InstanceID::SUCCESS)); | 207 gcm::GCMClient::Result result) { |
| 208 callback.Run(token, GCMClientResultToInstanceIDResult(result)); |
| 209 } |
| 210 |
| 211 void InstanceIDImpl::OnDeleteTokenCompleted( |
| 212 const DeleteTokenCallback& callback, |
| 213 gcm::GCMClient::Result result) { |
| 214 callback.Run(GCMClientResultToInstanceIDResult(result)); |
| 215 } |
| 216 |
| 217 void InstanceIDImpl::OnDeleteIDCompleted( |
| 218 const DeleteIDCallback& callback, |
| 219 gcm::GCMClient::Result result) { |
| 220 callback.Run(GCMClientResultToInstanceIDResult(result)); |
96 } | 221 } |
97 | 222 |
98 void InstanceIDImpl::GetInstanceIDDataCompleted( | 223 void InstanceIDImpl::GetInstanceIDDataCompleted( |
99 const std::string& instance_id_data) { | 224 const std::string& instance_id, |
100 Deserialize(instance_id_data); | 225 const std::string& extra_data) { |
| 226 id_ = instance_id; |
| 227 |
| 228 if (extra_data.empty()) { |
| 229 creation_time_ = base::Time(); |
| 230 } else { |
| 231 int64 time_internal = 0LL; |
| 232 if (!base::StringToInt64(extra_data, &time_internal)) { |
| 233 DVLOG(1) << "Failed to parse the time data: " + extra_data; |
| 234 return; |
| 235 } |
| 236 creation_time_ = base::Time::FromInternalValue(time_internal); |
| 237 } |
| 238 |
101 delayed_task_controller_.SetReady(); | 239 delayed_task_controller_.SetReady(); |
102 } | 240 } |
103 | 241 |
| 242 gcm::InstanceIDHandler* InstanceIDImpl::GetInstanceIDHandler() const { |
| 243 gcm::InstanceIDHandler* handler = gcm_driver_->GetInstanceIDHandler(); |
| 244 DCHECK(handler); |
| 245 return handler; |
| 246 } |
| 247 |
104 void InstanceIDImpl::EnsureIDGenerated() { | 248 void InstanceIDImpl::EnsureIDGenerated() { |
105 if (!id_.empty()) | 249 if (!id_.empty()) |
106 return; | 250 return; |
107 | 251 |
108 // Now produce the ID in the following steps: | 252 // Now produce the ID in the following steps: |
109 | 253 |
110 // 1) Generates the random number in 8 bytes which is required by the server. | 254 // 1) Generates the random number in 8 bytes which is required by the server. |
111 // We don't want to be strictly cryptographically secure. The server might | 255 // We don't want to be strictly cryptographically secure. The server might |
112 // reject the ID if there is a conflict or problem. | 256 // reject the ID if there is a conflict or problem. |
113 uint8 bytes[kInstanceIDByteLength]; | 257 uint8 bytes[kInstanceIDByteLength]; |
(...skipping 10 matching lines...) Expand all Loading... |
124 base::Base64Encode( | 268 base::Base64Encode( |
125 base::StringPiece(reinterpret_cast<const char*>(bytes), sizeof(bytes)), | 269 base::StringPiece(reinterpret_cast<const char*>(bytes), sizeof(bytes)), |
126 &id_); | 270 &id_); |
127 std::replace(id_.begin(), id_.end(), '+', '-'); | 271 std::replace(id_.begin(), id_.end(), '+', '-'); |
128 std::replace(id_.begin(), id_.end(), '/', '_'); | 272 std::replace(id_.begin(), id_.end(), '/', '_'); |
129 id_.erase(std::remove(id_.begin(), id_.end(), '='), id_.end()); | 273 id_.erase(std::remove(id_.begin(), id_.end(), '='), id_.end()); |
130 | 274 |
131 creation_time_ = base::Time::Now(); | 275 creation_time_ = base::Time::Now(); |
132 | 276 |
133 // Save to the persistent store. | 277 // Save to the persistent store. |
134 gcm_driver_->GetInstanceIDStore()->AddInstanceIDData( | 278 GetInstanceIDHandler()->AddInstanceIDData( |
135 app_id(), SerializeAsString()); | 279 app_id(), |
136 } | 280 id_, |
137 | 281 base::Int64ToString(creation_time_.ToInternalValue())); |
138 std::string InstanceIDImpl::SerializeAsString() const { | |
139 std::string serialized_data; | |
140 serialized_data += id_; | |
141 serialized_data += ","; | |
142 serialized_data += base::Int64ToString(creation_time_.ToInternalValue()); | |
143 return serialized_data; | |
144 } | |
145 | |
146 void InstanceIDImpl::Deserialize(const std::string& serialized_data) { | |
147 if (serialized_data.empty()) | |
148 return; | |
149 std::size_t pos = serialized_data.find(','); | |
150 if (pos == std::string::npos) { | |
151 DVLOG(1) << "Failed to deserialize the InstanceID data: " + serialized_data; | |
152 return; | |
153 } | |
154 | |
155 id_ = serialized_data.substr(0, pos); | |
156 | |
157 int64 time_internal = 0LL; | |
158 if (!base::StringToInt64(serialized_data.substr(pos + 1), &time_internal)) { | |
159 DVLOG(1) << "Failed to deserialize the InstanceID data: " + serialized_data; | |
160 return; | |
161 } | |
162 creation_time_ = base::Time::FromInternalValue(time_internal); | |
163 } | 282 } |
164 | 283 |
165 } // namespace instance_id | 284 } // namespace instance_id |
OLD | NEW |