| 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 |