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 "components/gcm_driver/gcm_driver_desktop.h" | 13 #include "components/gcm_driver/gcm_driver_desktop.h" |
13 #include "crypto/random.h" | 14 #include "crypto/random.h" |
14 | 15 |
15 namespace instance_id { | 16 namespace instance_id { |
16 | 17 |
17 // static | 18 // static |
18 InstanceID* InstanceID::Create(const std::string& app_id, | 19 InstanceID* InstanceID::Create(const std::string& app_id, |
19 gcm::GCMDriver* gcm_driver) { | 20 gcm::GCMDriver* gcm_driver) { |
20 return new InstanceIDImpl(app_id, gcm_driver); | 21 return new InstanceIDImpl(app_id, gcm_driver); |
21 } | 22 } |
22 | 23 |
23 InstanceIDImpl::InstanceIDImpl(const std::string& app_id, | 24 InstanceIDImpl::InstanceIDImpl(const std::string& app_id, |
24 gcm::GCMDriver* gcm_driver) | 25 gcm::GCMDriver* gcm_driver) |
25 : InstanceID(app_id), | 26 : InstanceID(app_id), |
26 gcm_driver_(gcm_driver) { | 27 gcm_driver_(gcm_driver), |
| 28 load_from_store_(false), |
| 29 weak_ptr_factory_(this) { |
| 30 gcm_driver_->GetInstanceIDStore()->GetInstanceIDData( |
| 31 app_id, |
| 32 base::Bind(&InstanceIDImpl::GetInstanceIDDataCompleted, |
| 33 weak_ptr_factory_.GetWeakPtr())); |
27 } | 34 } |
28 | 35 |
29 InstanceIDImpl::~InstanceIDImpl() { | 36 InstanceIDImpl::~InstanceIDImpl() { |
30 } | 37 } |
31 | 38 |
32 std::string InstanceIDImpl::GetID() { | 39 void InstanceIDImpl::GetID(const GetIDCallback& callback) { |
33 EnsureIDGenerated(); | 40 if (!delayed_task_controller_.CanRunTaskWithoutDelay()) { |
34 return id_; | 41 delayed_task_controller_.AddTask( |
| 42 base::Bind(&InstanceIDImpl::DoGetID, |
| 43 weak_ptr_factory_.GetWeakPtr(), |
| 44 callback)); |
| 45 return; |
| 46 } |
| 47 |
| 48 DoGetID(callback); |
35 } | 49 } |
36 | 50 |
37 base::Time InstanceIDImpl::GetCreationTime() { | 51 void InstanceIDImpl::DoGetID(const GetIDCallback& callback) { |
38 return creation_time_; | 52 EnsureIDGenerated(); |
| 53 callback.Run(id_); |
| 54 } |
| 55 |
| 56 void InstanceIDImpl::GetCreationTime(const GetCreationTimeCallback& callback) { |
| 57 if (!delayed_task_controller_.CanRunTaskWithoutDelay()) { |
| 58 delayed_task_controller_.AddTask( |
| 59 base::Bind(&InstanceIDImpl::DoGetCreationTime, |
| 60 weak_ptr_factory_.GetWeakPtr(), |
| 61 callback)); |
| 62 return; |
| 63 } |
| 64 |
| 65 DoGetCreationTime(callback); |
| 66 } |
| 67 |
| 68 void InstanceIDImpl::DoGetCreationTime( |
| 69 const GetCreationTimeCallback& callback) { |
| 70 callback.Run(creation_time_); |
39 } | 71 } |
40 | 72 |
41 void InstanceIDImpl::GetToken( | 73 void InstanceIDImpl::GetToken( |
42 const std::string& authorized_entity, | 74 const std::string& authorized_entity, |
43 const std::string& scope, | 75 const std::string& scope, |
44 const std::map<std::string, std::string>& options, | 76 const std::map<std::string, std::string>& options, |
45 const GetTokenCallback& callback) { | 77 const GetTokenCallback& callback) { |
46 NOTIMPLEMENTED(); | 78 NOTIMPLEMENTED(); |
47 } | 79 } |
48 | 80 |
49 void InstanceIDImpl::DeleteToken(const std::string& authorized_entity, | 81 void InstanceIDImpl::DeleteToken(const std::string& authorized_entity, |
50 const std::string& scope, | 82 const std::string& scope, |
51 const DeleteTokenCallback& callback) { | 83 const DeleteTokenCallback& callback) { |
52 NOTIMPLEMENTED(); | 84 NOTIMPLEMENTED(); |
53 } | 85 } |
54 | 86 |
55 void InstanceIDImpl::DeleteID(const DeleteIDCallback& callback) { | 87 void InstanceIDImpl::DeleteID(const DeleteIDCallback& callback) { |
56 // TODO(jianli): Delete the ID from the store. | 88 gcm_driver_->GetInstanceIDStore()->RemoveInstanceIDData(app_id()); |
| 89 |
57 id_.clear(); | 90 id_.clear(); |
58 creation_time_ = base::Time(); | 91 creation_time_ = base::Time(); |
59 | 92 |
60 base::MessageLoop::current()->PostTask( | 93 base::MessageLoop::current()->PostTask( |
61 FROM_HERE, | 94 FROM_HERE, |
62 base::Bind(callback, InstanceID::SUCCESS)); | 95 base::Bind(callback, InstanceID::SUCCESS)); |
63 } | 96 } |
64 | 97 |
| 98 void InstanceIDImpl::GetInstanceIDDataCompleted( |
| 99 const std::string& instance_id_data) { |
| 100 Deserialize(instance_id_data); |
| 101 delayed_task_controller_.SetReady(); |
| 102 } |
| 103 |
65 void InstanceIDImpl::EnsureIDGenerated() { | 104 void InstanceIDImpl::EnsureIDGenerated() { |
66 if (!id_.empty()) | 105 if (!id_.empty()) |
67 return; | 106 return; |
68 | 107 |
69 // Now produce the ID in the following steps: | 108 // Now produce the ID in the following steps: |
70 | 109 |
71 // 1) Generates the random number in 8 bytes which is required by the server. | 110 // 1) Generates the random number in 8 bytes which is required by the server. |
72 // We don't want to be strictly cryptographically secure. The server might | 111 // We don't want to be strictly cryptographically secure. The server might |
73 // reject the ID if there is a conflict or problem. | 112 // reject the ID if there is a conflict or problem. |
74 uint8 bytes[kInstanceIDByteLength]; | 113 uint8 bytes[kInstanceIDByteLength]; |
75 crypto::RandBytes(bytes, sizeof(bytes)); | 114 crypto::RandBytes(bytes, sizeof(bytes)); |
76 | 115 |
77 // 2) Transforms the first 4 bits to 0x7. Note that this is required by the | 116 // 2) Transforms the first 4 bits to 0x7. Note that this is required by the |
78 // server. | 117 // server. |
79 bytes[0] &= 0x0f; | 118 bytes[0] &= 0x0f; |
80 bytes[0] |= 0x70; | 119 bytes[0] |= 0x70; |
81 | 120 |
82 // 3) Encode the value in Android-compatible base64 scheme: | 121 // 3) Encode the value in Android-compatible base64 scheme: |
83 // * URL safe: '/' replaced by '_' and '+' replaced by '-'. | 122 // * URL safe: '/' replaced by '_' and '+' replaced by '-'. |
84 // * No padding: any trailing '=' will be removed. | 123 // * No padding: any trailing '=' will be removed. |
85 base::Base64Encode( | 124 base::Base64Encode( |
86 base::StringPiece(reinterpret_cast<const char*>(bytes), sizeof(bytes)), | 125 base::StringPiece(reinterpret_cast<const char*>(bytes), sizeof(bytes)), |
87 &id_); | 126 &id_); |
88 std::replace(id_.begin(), id_.end(), '+', '-'); | 127 std::replace(id_.begin(), id_.end(), '+', '-'); |
89 std::replace(id_.begin(), id_.end(), '/', '_'); | 128 std::replace(id_.begin(), id_.end(), '/', '_'); |
90 id_.erase(std::remove(id_.begin(), id_.end(), '='), id_.end()); | 129 id_.erase(std::remove(id_.begin(), id_.end(), '='), id_.end()); |
91 | 130 |
92 creation_time_ = base::Time::Now(); | 131 creation_time_ = base::Time::Now(); |
93 | 132 |
94 // TODO(jianli): Save the ID to the store. | 133 // Save to the persistent store. |
| 134 gcm_driver_->GetInstanceIDStore()->AddInstanceIDData( |
| 135 app_id(), SerializeAsString()); |
| 136 } |
| 137 |
| 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); |
95 } | 163 } |
96 | 164 |
97 } // namespace instance_id | 165 } // namespace instance_id |
OLD | NEW |