OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "remoting/protocol/pairing_registry.h" | 5 #include "remoting/protocol/pairing_registry.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/guid.h" | 9 #include "base/guid.h" |
10 #include "base/json/json_string_value_serializer.h" | 10 #include "base/json/json_string_value_serializer.h" |
| 11 #include "base/location.h" |
| 12 #include "base/single_thread_task_runner.h" |
11 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/thread_task_runner_handle.h" |
12 #include "base/values.h" | 15 #include "base/values.h" |
13 #include "crypto/random.h" | 16 #include "crypto/random.h" |
14 | 17 |
15 namespace remoting { | 18 namespace remoting { |
16 namespace protocol { | 19 namespace protocol { |
17 | 20 |
18 // How many bytes of random data to use for the shared secret. | 21 // How many bytes of random data to use for the shared secret. |
19 const int kKeySize = 16; | 22 const int kKeySize = 16; |
20 | 23 |
21 const char PairingRegistry::kCreatedTimeKey[] = "createdTime"; | 24 const char PairingRegistry::kCreatedTimeKey[] = "createdTime"; |
22 const char PairingRegistry::kClientIdKey[] = "clientId"; | 25 const char PairingRegistry::kClientIdKey[] = "clientId"; |
23 const char PairingRegistry::kClientNameKey[] = "clientName"; | 26 const char PairingRegistry::kClientNameKey[] = "clientName"; |
24 const char PairingRegistry::kSharedSecretKey[] = "sharedSecret"; | 27 const char PairingRegistry::kSharedSecretKey[] = "sharedSecret"; |
25 | 28 |
26 PairingRegistry::Pairing::Pairing() { | 29 PairingRegistry::Pairing::Pairing() { |
27 } | 30 } |
28 | 31 |
29 PairingRegistry::Pairing::Pairing(const base::Time& created_time, | 32 PairingRegistry::Pairing::Pairing(const base::Time& created_time, |
30 const std::string& client_name, | 33 const std::string& client_name, |
31 const std::string& client_id, | 34 const std::string& client_id, |
32 const std::string& shared_secret) | 35 const std::string& shared_secret) |
33 : created_time_(created_time), | 36 : created_time_(created_time), |
34 client_name_(client_name), | 37 client_name_(client_name), |
35 client_id_(client_id), | 38 client_id_(client_id), |
36 shared_secret_(shared_secret) { | 39 shared_secret_(shared_secret) { |
37 } | 40 } |
38 | 41 |
| 42 PairingRegistry::Pairing::~Pairing() { |
| 43 } |
| 44 |
39 PairingRegistry::Pairing PairingRegistry::Pairing::Create( | 45 PairingRegistry::Pairing PairingRegistry::Pairing::Create( |
40 const std::string& client_name) { | 46 const std::string& client_name) { |
41 base::Time created_time = base::Time::Now(); | 47 base::Time created_time = base::Time::Now(); |
42 std::string client_id = base::GenerateGUID(); | 48 std::string client_id = base::GenerateGUID(); |
43 std::string shared_secret; | 49 std::string shared_secret; |
44 char buffer[kKeySize]; | 50 char buffer[kKeySize]; |
45 crypto::RandBytes(buffer, arraysize(buffer)); | 51 crypto::RandBytes(buffer, arraysize(buffer)); |
46 if (!base::Base64Encode(base::StringPiece(buffer, arraysize(buffer)), | 52 if (!base::Base64Encode(base::StringPiece(buffer, arraysize(buffer)), |
47 &shared_secret)) { | 53 &shared_secret)) { |
48 LOG(FATAL) << "Base64Encode failed."; | 54 LOG(FATAL) << "Base64Encode failed."; |
49 } | 55 } |
50 return Pairing(created_time, client_name, client_id, shared_secret); | 56 return Pairing(created_time, client_name, client_id, shared_secret); |
51 } | 57 } |
52 | 58 |
53 PairingRegistry::Pairing::~Pairing() { | 59 PairingRegistry::Pairing PairingRegistry::Pairing::CreateFromValue( |
| 60 const base::Value& pairing_json) { |
| 61 const base::DictionaryValue* pairing = NULL; |
| 62 if (!pairing_json.GetAsDictionary(&pairing)) { |
| 63 LOG(ERROR) << "Failed to load pairing information: not a dictionary."; |
| 64 return Pairing(); |
| 65 } |
| 66 |
| 67 std::string client_name, client_id; |
| 68 double created_time_value; |
| 69 if (pairing->GetDouble(kCreatedTimeKey, &created_time_value) && |
| 70 pairing->GetString(kClientNameKey, &client_name) && |
| 71 pairing->GetString(kClientIdKey, &client_id)) { |
| 72 // The shared secret is optional. |
| 73 std::string shared_secret; |
| 74 pairing->GetString(kSharedSecretKey, &shared_secret); |
| 75 base::Time created_time = base::Time::FromJsTime(created_time_value); |
| 76 return Pairing(created_time, client_name, client_id, shared_secret); |
| 77 } |
| 78 |
| 79 LOG(ERROR) << "Failed to load pairing information: unexpected format."; |
| 80 return Pairing(); |
| 81 } |
| 82 |
| 83 scoped_ptr<base::Value> PairingRegistry::Pairing::ToValue() const { |
| 84 scoped_ptr<base::DictionaryValue> pairing(new base::DictionaryValue()); |
| 85 pairing->SetDouble(kCreatedTimeKey, created_time().ToJsTime()); |
| 86 pairing->SetString(kClientNameKey, client_name()); |
| 87 pairing->SetString(kClientIdKey, client_id()); |
| 88 if (!shared_secret().empty()) |
| 89 pairing->SetString(kSharedSecretKey, shared_secret()); |
| 90 return pairing.PassAs<base::Value>(); |
54 } | 91 } |
55 | 92 |
56 bool PairingRegistry::Pairing::operator==(const Pairing& other) const { | 93 bool PairingRegistry::Pairing::operator==(const Pairing& other) const { |
57 return created_time_ == other.created_time_ && | 94 return created_time_ == other.created_time_ && |
58 client_id_ == other.client_id_ && | 95 client_id_ == other.client_id_ && |
59 client_name_ == other.client_name_ && | 96 client_name_ == other.client_name_ && |
60 shared_secret_ == other.shared_secret_; | 97 shared_secret_ == other.shared_secret_; |
61 } | 98 } |
62 | 99 |
63 bool PairingRegistry::Pairing::is_valid() const { | 100 bool PairingRegistry::Pairing::is_valid() const { |
64 return !client_id_.empty() && !shared_secret_.empty(); | 101 return !client_id_.empty() && !shared_secret_.empty(); |
65 } | 102 } |
66 | 103 |
67 PairingRegistry::PairingRegistry(scoped_ptr<Delegate> delegate) | 104 PairingRegistry::PairingRegistry( |
68 : delegate_(delegate.Pass()) { | 105 scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner, |
| 106 scoped_ptr<Delegate> delegate) |
| 107 : caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 108 delegate_task_runner_(delegate_task_runner), |
| 109 delegate_(delegate.Pass()) { |
69 DCHECK(delegate_); | 110 DCHECK(delegate_); |
70 } | 111 } |
71 | 112 |
72 PairingRegistry::~PairingRegistry() { | |
73 } | |
74 | |
75 PairingRegistry::Pairing PairingRegistry::CreatePairing( | 113 PairingRegistry::Pairing PairingRegistry::CreatePairing( |
76 const std::string& client_name) { | 114 const std::string& client_name) { |
77 DCHECK(CalledOnValidThread()); | 115 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 116 |
78 Pairing result = Pairing::Create(client_name); | 117 Pairing result = Pairing::Create(client_name); |
79 AddPairing(result); | 118 AddPairing(result); |
80 return result; | 119 return result; |
81 } | 120 } |
82 | 121 |
83 void PairingRegistry::GetPairing(const std::string& client_id, | 122 void PairingRegistry::GetPairing(const std::string& client_id, |
84 const GetPairingCallback& callback) { | 123 const GetPairingCallback& callback) { |
85 DCHECK(CalledOnValidThread()); | 124 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 125 |
86 GetPairingCallback wrapped_callback = base::Bind( | 126 GetPairingCallback wrapped_callback = base::Bind( |
87 &PairingRegistry::InvokeGetPairingCallbackAndScheduleNext, | 127 &PairingRegistry::InvokeGetPairingCallbackAndScheduleNext, |
88 this, callback); | 128 this, callback); |
89 LoadCallback load_callback = base::Bind( | |
90 &PairingRegistry::DoGetPairing, this, client_id, wrapped_callback); | |
91 // |Unretained| and |get| are both safe here because the delegate is owned | |
92 // by the pairing registry and so is guaranteed to exist when the request | |
93 // is serviced. | |
94 base::Closure request = base::Bind( | 129 base::Closure request = base::Bind( |
95 &PairingRegistry::Delegate::Load, | 130 &PairingRegistry::DoLoad, this, client_id, wrapped_callback); |
96 base::Unretained(delegate_.get()), load_callback); | |
97 ServiceOrQueueRequest(request); | 131 ServiceOrQueueRequest(request); |
98 } | 132 } |
99 | 133 |
100 void PairingRegistry::GetAllPairings( | 134 void PairingRegistry::GetAllPairings( |
101 const GetAllPairingsCallback& callback) { | 135 const GetAllPairingsCallback& callback) { |
102 DCHECK(CalledOnValidThread()); | 136 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 137 |
103 GetAllPairingsCallback wrapped_callback = base::Bind( | 138 GetAllPairingsCallback wrapped_callback = base::Bind( |
104 &PairingRegistry::InvokeGetAllPairingsCallbackAndScheduleNext, | 139 &PairingRegistry::InvokeGetAllPairingsCallbackAndScheduleNext, |
105 this, callback); | 140 this, callback); |
106 LoadCallback load_callback = base::Bind( | 141 GetAllPairingsCallback sanitize_callback = base::Bind( |
107 &PairingRegistry::SanitizePairings, this, wrapped_callback); | 142 &PairingRegistry::SanitizePairings, |
| 143 this, wrapped_callback); |
108 base::Closure request = base::Bind( | 144 base::Closure request = base::Bind( |
109 &PairingRegistry::Delegate::Load, | 145 &PairingRegistry::DoLoadAll, this, sanitize_callback); |
110 base::Unretained(delegate_.get()), load_callback); | |
111 ServiceOrQueueRequest(request); | 146 ServiceOrQueueRequest(request); |
112 } | 147 } |
113 | 148 |
114 void PairingRegistry::DeletePairing( | 149 void PairingRegistry::DeletePairing( |
115 const std::string& client_id, const SaveCallback& callback) { | 150 const std::string& client_id, const DoneCallback& callback) { |
116 DCHECK(CalledOnValidThread()); | 151 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
117 SaveCallback wrapped_callback = base::Bind( | 152 |
118 &PairingRegistry::InvokeSaveCallbackAndScheduleNext, | 153 DoneCallback wrapped_callback = base::Bind( |
| 154 &PairingRegistry::InvokeDoneCallbackAndScheduleNext, |
119 this, callback); | 155 this, callback); |
120 LoadCallback load_callback = base::Bind( | |
121 &PairingRegistry::DoDeletePairing, this, client_id, wrapped_callback); | |
122 base::Closure request = base::Bind( | 156 base::Closure request = base::Bind( |
123 &PairingRegistry::Delegate::Load, | 157 &PairingRegistry::DoDelete, this, client_id, wrapped_callback); |
124 base::Unretained(delegate_.get()), load_callback); | |
125 ServiceOrQueueRequest(request); | 158 ServiceOrQueueRequest(request); |
126 } | 159 } |
127 | 160 |
128 void PairingRegistry::ClearAllPairings( | 161 void PairingRegistry::ClearAllPairings( |
129 const SaveCallback& callback) { | 162 const DoneCallback& callback) { |
130 DCHECK(CalledOnValidThread()); | 163 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
131 SaveCallback wrapped_callback = base::Bind( | 164 |
132 &PairingRegistry::InvokeSaveCallbackAndScheduleNext, | 165 DoneCallback wrapped_callback = base::Bind( |
| 166 &PairingRegistry::InvokeDoneCallbackAndScheduleNext, |
133 this, callback); | 167 this, callback); |
134 base::Closure request = base::Bind( | 168 base::Closure request = base::Bind( |
135 &PairingRegistry::Delegate::Save, | 169 &PairingRegistry::DoDeleteAll, this, wrapped_callback); |
136 base::Unretained(delegate_.get()), | |
137 EncodeJson(PairedClients()), | |
138 wrapped_callback); | |
139 ServiceOrQueueRequest(request); | 170 ServiceOrQueueRequest(request); |
140 } | 171 } |
141 | 172 |
| 173 PairingRegistry::~PairingRegistry() { |
| 174 } |
| 175 |
| 176 void PairingRegistry::PostTask( |
| 177 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 178 const tracked_objects::Location& from_here, |
| 179 const base::Closure& task) { |
| 180 task_runner->PostTask(from_here, task); |
| 181 } |
| 182 |
142 void PairingRegistry::AddPairing(const Pairing& pairing) { | 183 void PairingRegistry::AddPairing(const Pairing& pairing) { |
143 SaveCallback callback = base::Bind( | 184 DoneCallback wrapped_callback = base::Bind( |
144 &PairingRegistry::InvokeSaveCallbackAndScheduleNext, | 185 &PairingRegistry::InvokeDoneCallbackAndScheduleNext, |
145 this, SaveCallback()); | 186 this, DoneCallback()); |
146 LoadCallback load_callback = base::Bind( | |
147 &PairingRegistry::MergePairingAndSave, this, pairing, callback); | |
148 base::Closure request = base::Bind( | 187 base::Closure request = base::Bind( |
149 &PairingRegistry::Delegate::Load, | 188 &PairingRegistry::DoSave, this, pairing, wrapped_callback); |
150 base::Unretained(delegate_.get()), load_callback); | |
151 ServiceOrQueueRequest(request); | 189 ServiceOrQueueRequest(request); |
152 } | 190 } |
153 | 191 |
154 void PairingRegistry::MergePairingAndSave(const Pairing& pairing, | 192 void PairingRegistry::DoLoadAll( |
155 const SaveCallback& callback, | 193 const protocol::PairingRegistry::GetAllPairingsCallback& callback) { |
156 const std::string& pairings_json) { | 194 DCHECK(delegate_task_runner_->BelongsToCurrentThread()); |
157 DCHECK(CalledOnValidThread()); | 195 |
158 PairedClients clients = DecodeJson(pairings_json); | 196 scoped_ptr<base::ListValue> pairings = delegate_->LoadAll(); |
159 clients[pairing.client_id()] = pairing; | 197 PostTask(caller_task_runner_, FROM_HERE, base::Bind(callback, |
160 std::string new_pairings_json = EncodeJson(clients); | 198 base::Passed(&pairings))); |
161 delegate_->Save(new_pairings_json, callback); | |
162 } | 199 } |
163 | 200 |
164 void PairingRegistry::DoGetPairing(const std::string& client_id, | 201 void PairingRegistry::DoDeleteAll( |
165 const GetPairingCallback& callback, | 202 const protocol::PairingRegistry::DoneCallback& callback) { |
166 const std::string& pairings_json) { | 203 DCHECK(delegate_task_runner_->BelongsToCurrentThread()); |
167 PairedClients clients = DecodeJson(pairings_json); | 204 |
168 Pairing result = clients[client_id]; | 205 bool success = delegate_->DeleteAll(); |
169 callback.Run(result); | 206 PostTask(caller_task_runner_, FROM_HERE, base::Bind(callback, success)); |
170 } | 207 } |
171 | 208 |
172 void PairingRegistry::SanitizePairings(const GetAllPairingsCallback& callback, | 209 void PairingRegistry::DoLoad( |
173 const std::string& pairings_json) { | 210 const std::string& client_id, |
174 PairedClients clients = DecodeJson(pairings_json); | 211 const protocol::PairingRegistry::GetPairingCallback& callback) { |
175 callback.Run(ConvertToListValue(clients, false)); | 212 DCHECK(delegate_task_runner_->BelongsToCurrentThread()); |
| 213 |
| 214 Pairing pairing = delegate_->Load(client_id); |
| 215 PostTask(caller_task_runner_, FROM_HERE, base::Bind(callback, pairing)); |
176 } | 216 } |
177 | 217 |
178 void PairingRegistry::DoDeletePairing(const std::string& client_id, | 218 void PairingRegistry::DoSave( |
179 const SaveCallback& callback, | 219 const protocol::PairingRegistry::Pairing& pairing, |
180 const std::string& pairings_json) { | 220 const protocol::PairingRegistry::DoneCallback& callback) { |
181 PairedClients clients = DecodeJson(pairings_json); | 221 DCHECK(delegate_task_runner_->BelongsToCurrentThread()); |
182 clients.erase(client_id); | 222 |
183 std::string new_pairings_json = EncodeJson(clients); | 223 bool success = delegate_->Save(pairing); |
184 delegate_->Save(new_pairings_json, callback); | 224 PostTask(caller_task_runner_, FROM_HERE, base::Bind(callback, success)); |
185 } | 225 } |
186 | 226 |
187 void PairingRegistry::InvokeLoadCallbackAndScheduleNext( | 227 void PairingRegistry::DoDelete( |
188 const LoadCallback& callback, const std::string& pairings_json) { | 228 const std::string& client_id, |
189 callback.Run(pairings_json); | 229 const protocol::PairingRegistry::DoneCallback& callback) { |
| 230 DCHECK(delegate_task_runner_->BelongsToCurrentThread()); |
| 231 |
| 232 bool success = delegate_->Delete(client_id); |
| 233 PostTask(caller_task_runner_, FROM_HERE, base::Bind(callback, success)); |
| 234 } |
| 235 |
| 236 void PairingRegistry::InvokeDoneCallbackAndScheduleNext( |
| 237 const DoneCallback& callback, bool success) { |
| 238 // CreatePairing doesn't have a callback, so the callback can be null. |
| 239 if (!callback.is_null()) |
| 240 callback.Run(success); |
| 241 |
190 pending_requests_.pop(); | 242 pending_requests_.pop(); |
191 ServiceNextRequest(); | 243 ServiceNextRequest(); |
192 } | 244 } |
193 | |
194 void PairingRegistry::InvokeSaveCallbackAndScheduleNext( | |
195 const SaveCallback& callback, bool success) { | |
196 // CreatePairing doesn't have a callback, so the callback can be null. | |
197 if (!callback.is_null()) { | |
198 callback.Run(success); | |
199 } | |
200 pending_requests_.pop(); | |
201 ServiceNextRequest(); | |
202 } | |
203 | 245 |
204 void PairingRegistry::InvokeGetPairingCallbackAndScheduleNext( | 246 void PairingRegistry::InvokeGetPairingCallbackAndScheduleNext( |
205 const GetPairingCallback& callback, Pairing pairing) { | 247 const GetPairingCallback& callback, Pairing pairing) { |
206 callback.Run(pairing); | 248 callback.Run(pairing); |
207 pending_requests_.pop(); | 249 pending_requests_.pop(); |
208 ServiceNextRequest(); | 250 ServiceNextRequest(); |
209 } | 251 } |
210 | 252 |
211 void PairingRegistry::InvokeGetAllPairingsCallbackAndScheduleNext( | 253 void PairingRegistry::InvokeGetAllPairingsCallbackAndScheduleNext( |
212 const GetAllPairingsCallback& callback, | 254 const GetAllPairingsCallback& callback, |
213 scoped_ptr<base::ListValue> pairings) { | 255 scoped_ptr<base::ListValue> pairings) { |
214 callback.Run(pairings.Pass()); | 256 callback.Run(pairings.Pass()); |
215 pending_requests_.pop(); | 257 pending_requests_.pop(); |
216 ServiceNextRequest(); | 258 ServiceNextRequest(); |
217 } | 259 } |
218 | 260 |
219 // static | 261 void PairingRegistry::SanitizePairings(const GetAllPairingsCallback& callback, |
220 PairingRegistry::PairedClients PairingRegistry::DecodeJson( | 262 scoped_ptr<base::ListValue> pairings) { |
221 const std::string& pairings_json) { | 263 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
222 PairedClients result; | |
223 | 264 |
224 if (pairings_json.empty()) { | 265 scoped_ptr<base::ListValue> sanitized_pairings(new base::ListValue()); |
225 return result; | 266 for (size_t i = 0; i < pairings->GetSize(); ++i) { |
| 267 DictionaryValue* pairing_json; |
| 268 if (!pairings->GetDictionary(i, &pairing_json)) { |
| 269 LOG(WARNING) << "A pairing entry is not a dictionary."; |
| 270 continue; |
| 271 } |
| 272 |
| 273 // Parse the pairing data. |
| 274 Pairing pairing = Pairing::CreateFromValue(*pairing_json); |
| 275 if (!pairing.is_valid()) { |
| 276 LOG(WARNING) << "Could not parse a pairing entry."; |
| 277 continue; |
| 278 } |
| 279 |
| 280 // Clear the shared secrect and append the pairing data to the list. |
| 281 Pairing sanitized_pairing( |
| 282 pairing.created_time(), |
| 283 pairing.client_name(), |
| 284 pairing.client_id(), |
| 285 ""); |
| 286 sanitized_pairings->Append(sanitized_pairing.ToValue().release()); |
226 } | 287 } |
227 | 288 |
228 JSONStringValueSerializer registry(pairings_json); | 289 callback.Run(sanitized_pairings.Pass()); |
229 int error_code; | |
230 std::string error_message; | |
231 scoped_ptr<base::Value> root( | |
232 registry.Deserialize(&error_code, &error_message)); | |
233 if (!root) { | |
234 LOG(ERROR) << "Failed to load paired clients: " << error_message | |
235 << " (" << error_code << ")."; | |
236 return result; | |
237 } | |
238 | |
239 base::ListValue* root_list = NULL; | |
240 if (!root->GetAsList(&root_list)) { | |
241 LOG(ERROR) << "Failed to load paired clients: root node is not a list."; | |
242 return result; | |
243 } | |
244 | |
245 for (size_t i = 0; i < root_list->GetSize(); ++i) { | |
246 base::DictionaryValue* pairing = NULL; | |
247 std::string client_name, client_id, shared_secret; | |
248 double created_time_value; | |
249 if (root_list->GetDictionary(i, &pairing) && | |
250 pairing->GetDouble(kCreatedTimeKey, &created_time_value) && | |
251 pairing->GetString(kClientNameKey, &client_name) && | |
252 pairing->GetString(kClientIdKey, &client_id) && | |
253 pairing->GetString(kSharedSecretKey, &shared_secret)) { | |
254 base::Time created_time = base::Time::FromJsTime(created_time_value); | |
255 result[client_id] = Pairing( | |
256 created_time, client_name, client_id, shared_secret); | |
257 } else { | |
258 LOG(ERROR) << "Paired client " << i << " has unexpected format."; | |
259 } | |
260 } | |
261 | |
262 return result; | |
263 } | 290 } |
264 | 291 |
265 void PairingRegistry::ServiceOrQueueRequest(const base::Closure& request) { | 292 void PairingRegistry::ServiceOrQueueRequest(const base::Closure& request) { |
266 bool servicing_request = !pending_requests_.empty(); | 293 bool servicing_request = !pending_requests_.empty(); |
267 pending_requests_.push(request); | 294 pending_requests_.push(request); |
268 if (!servicing_request) { | 295 if (!servicing_request) { |
269 ServiceNextRequest(); | 296 ServiceNextRequest(); |
270 } | 297 } |
271 } | 298 } |
272 | 299 |
273 void PairingRegistry::ServiceNextRequest() { | 300 void PairingRegistry::ServiceNextRequest() { |
274 if (pending_requests_.empty()) { | 301 if (pending_requests_.empty()) |
275 return; | 302 return; |
276 } | |
277 base::Closure request = pending_requests_.front(); | |
278 request.Run(); | |
279 } | |
280 | 303 |
281 // static | 304 PostTask(delegate_task_runner_, FROM_HERE, pending_requests_.front()); |
282 std::string PairingRegistry::EncodeJson(const PairedClients& clients) { | |
283 scoped_ptr<base::ListValue> root = ConvertToListValue(clients, true); | |
284 std::string result; | |
285 JSONStringValueSerializer serializer(&result); | |
286 serializer.Serialize(*root); | |
287 | |
288 return result; | |
289 } | |
290 | |
291 // static | |
292 scoped_ptr<base::ListValue> PairingRegistry::ConvertToListValue( | |
293 const PairedClients& clients, | |
294 bool include_shared_secrets) { | |
295 scoped_ptr<base::ListValue> root(new base::ListValue()); | |
296 for (PairedClients::const_iterator i = clients.begin(); | |
297 i != clients.end(); ++i) { | |
298 base::DictionaryValue* pairing = new base::DictionaryValue(); | |
299 pairing->SetDouble(kCreatedTimeKey, i->second.created_time().ToJsTime()); | |
300 pairing->SetString(kClientNameKey, i->second.client_name()); | |
301 pairing->SetString(kClientIdKey, i->second.client_id()); | |
302 if (include_shared_secrets) { | |
303 pairing->SetString(kSharedSecretKey, i->second.shared_secret()); | |
304 } | |
305 root->Append(pairing); | |
306 } | |
307 return root.Pass(); | |
308 } | 305 } |
309 | 306 |
310 } // namespace protocol | 307 } // namespace protocol |
311 } // namespace remoting | 308 } // namespace remoting |
OLD | NEW |