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 GetInstanceIDHandler()->RemoveInstanceIDData(app_id()); |
89 | 174 |
90 id_.clear(); | 175 id_.clear(); |
91 creation_time_ = base::Time(); | 176 creation_time_ = base::Time(); |
92 | 177 |
93 base::MessageLoop::current()->PostTask( | 178 base::MessageLoop::current()->PostTask( |
94 FROM_HERE, | 179 FROM_HERE, |
95 base::Bind(callback, InstanceID::SUCCESS)); | 180 base::Bind(callback, InstanceID::SUCCESS)); |
96 } | 181 } |
97 | 182 |
| 183 void InstanceIDImpl::OnGetTokenCompleted(const GetTokenCallback& callback, |
| 184 const std::string& token, |
| 185 gcm::GCMClient::Result result) { |
| 186 callback.Run(token, GCMClientResultToInstanceIDResult(result)); |
| 187 } |
| 188 |
| 189 void InstanceIDImpl::OnDeleteTokenCompleted( |
| 190 const DeleteTokenCallback& callback, |
| 191 gcm::GCMClient::Result result) { |
| 192 callback.Run(GCMClientResultToInstanceIDResult(result)); |
| 193 } |
| 194 |
98 void InstanceIDImpl::GetInstanceIDDataCompleted( | 195 void InstanceIDImpl::GetInstanceIDDataCompleted( |
99 const std::string& instance_id_data) { | 196 const std::string& instance_id, |
100 Deserialize(instance_id_data); | 197 const std::string& extra_data) { |
| 198 id_ = instance_id; |
| 199 |
| 200 if (extra_data.empty()) { |
| 201 creation_time_ = base::Time(); |
| 202 } else { |
| 203 int64 time_internal = 0LL; |
| 204 if (!base::StringToInt64(extra_data, &time_internal)) { |
| 205 DVLOG(1) << "Failed to parse the time data: " + extra_data; |
| 206 return; |
| 207 } |
| 208 creation_time_ = base::Time::FromInternalValue(time_internal); |
| 209 } |
| 210 |
101 delayed_task_controller_.SetReady(); | 211 delayed_task_controller_.SetReady(); |
102 } | 212 } |
103 | 213 |
| 214 gcm::InstanceIDHandler* InstanceIDImpl::GetInstanceIDHandler() const { |
| 215 gcm::InstanceIDHandler* handler = gcm_driver_->GetInstanceIDHandler(); |
| 216 DCHECK(handler); |
| 217 return handler; |
| 218 } |
| 219 |
104 void InstanceIDImpl::EnsureIDGenerated() { | 220 void InstanceIDImpl::EnsureIDGenerated() { |
105 if (!id_.empty()) | 221 if (!id_.empty()) |
106 return; | 222 return; |
107 | 223 |
108 // Now produce the ID in the following steps: | 224 // Now produce the ID in the following steps: |
109 | 225 |
110 // 1) Generates the random number in 8 bytes which is required by the server. | 226 // 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 | 227 // We don't want to be strictly cryptographically secure. The server might |
112 // reject the ID if there is a conflict or problem. | 228 // reject the ID if there is a conflict or problem. |
113 uint8 bytes[kInstanceIDByteLength]; | 229 uint8 bytes[kInstanceIDByteLength]; |
(...skipping 10 matching lines...) Expand all Loading... |
124 base::Base64Encode( | 240 base::Base64Encode( |
125 base::StringPiece(reinterpret_cast<const char*>(bytes), sizeof(bytes)), | 241 base::StringPiece(reinterpret_cast<const char*>(bytes), sizeof(bytes)), |
126 &id_); | 242 &id_); |
127 std::replace(id_.begin(), id_.end(), '+', '-'); | 243 std::replace(id_.begin(), id_.end(), '+', '-'); |
128 std::replace(id_.begin(), id_.end(), '/', '_'); | 244 std::replace(id_.begin(), id_.end(), '/', '_'); |
129 id_.erase(std::remove(id_.begin(), id_.end(), '='), id_.end()); | 245 id_.erase(std::remove(id_.begin(), id_.end(), '='), id_.end()); |
130 | 246 |
131 creation_time_ = base::Time::Now(); | 247 creation_time_ = base::Time::Now(); |
132 | 248 |
133 // Save to the persistent store. | 249 // Save to the persistent store. |
134 gcm_driver_->GetInstanceIDStore()->AddInstanceIDData( | 250 GetInstanceIDHandler()->AddInstanceIDData( |
135 app_id(), SerializeAsString()); | 251 app_id(), |
136 } | 252 id_, |
137 | 253 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 } | 254 } |
164 | 255 |
165 } // namespace instance_id | 256 } // namespace instance_id |
OLD | NEW |