1b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// found in the LICENSE file.
4b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "remoting/protocol/pairing_registry.h"
6b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
7b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/base64.h"
8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/bind.h"
9b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/guid.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/json/json_string_value_serializer.h"
11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/location.h"
12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/single_thread_task_runner.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/string_number_conversions.h"
14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/thread_task_runner_handle.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/values.h"
16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "crypto/random.h"
17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace remoting {
19b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace protocol {
20b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// How many bytes of random data to use for the shared secret.
22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const int kKeySize = 16;
23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char PairingRegistry::kCreatedTimeKey[] = "createdTime";
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char PairingRegistry::kClientIdKey[] = "clientId";
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char PairingRegistry::kClientNameKey[] = "clientName";
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char PairingRegistry::kSharedSecretKey[] = "sharedSecret";
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)PairingRegistry::Pairing::Pairing() {
30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)PairingRegistry::Pairing::Pairing(const base::Time& created_time,
337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                  const std::string& client_name,
347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                  const std::string& client_id,
357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                  const std::string& shared_secret)
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : created_time_(created_time),
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      client_name_(client_name),
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      client_id_(client_id),
397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      shared_secret_(shared_secret) {
40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)PairingRegistry::Pairing::~Pairing() {
43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)PairingRegistry::Pairing PairingRegistry::Pairing::Create(
46b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& client_name) {
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::Time created_time = base::Time::Now();
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::string client_id = base::GenerateGUID();
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::string shared_secret;
50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  char buffer[kKeySize];
51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  crypto::RandBytes(buffer, arraysize(buffer));
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::Base64Encode(base::StringPiece(buffer, arraysize(buffer)),
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     &shared_secret);
547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return Pairing(created_time, client_name, client_id, shared_secret);
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)PairingRegistry::Pairing PairingRegistry::Pairing::CreateFromValue(
58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const base::DictionaryValue& pairing) {
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string client_name, client_id;
60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  double created_time_value;
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (pairing.GetDouble(kCreatedTimeKey, &created_time_value) &&
62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      pairing.GetString(kClientNameKey, &client_name) &&
63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      pairing.GetString(kClientIdKey, &client_id)) {
64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // The shared secret is optional.
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::string shared_secret;
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    pairing.GetString(kSharedSecretKey, &shared_secret);
67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::Time created_time = base::Time::FromJsTime(created_time_value);
68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Pairing(created_time, client_name, client_id, shared_secret);
69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  LOG(ERROR) << "Failed to load pairing information: unexpected format.";
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return Pairing();
73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochscoped_ptr<base::DictionaryValue> PairingRegistry::Pairing::ToValue() const {
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> pairing(new base::DictionaryValue());
77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  pairing->SetDouble(kCreatedTimeKey, created_time().ToJsTime());
78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  pairing->SetString(kClientNameKey, client_name());
79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  pairing->SetString(kClientIdKey, client_id());
80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!shared_secret().empty())
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    pairing->SetString(kSharedSecretKey, shared_secret());
82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return pairing.Pass();
837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool PairingRegistry::Pairing::operator==(const Pairing& other) const {
867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return created_time_ == other.created_time_ &&
877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)         client_id_ == other.client_id_ &&
887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)         client_name_ == other.client_name_ &&
897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)         shared_secret_ == other.shared_secret_;
907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool PairingRegistry::Pairing::is_valid() const {
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // |shared_secret_| is optional. It will be empty on Windows because the
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // privileged registry key can only be read in the elevated host process.
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return !client_id_.empty();
96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
97b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)PairingRegistry::PairingRegistry(
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner,
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    scoped_ptr<Delegate> delegate)
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : caller_task_runner_(base::ThreadTaskRunnerHandle::Get()),
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      delegate_task_runner_(delegate_task_runner),
103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      delegate_(delegate.Pass()) {
1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(delegate_);
1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)PairingRegistry::Pairing PairingRegistry::CreatePairing(
1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const std::string& client_name) {
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(caller_task_runner_->BelongsToCurrentThread());
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Pairing result = Pairing::Create(client_name);
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddPairing(result);
1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return result;
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void PairingRegistry::GetPairing(const std::string& client_id,
1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                 const GetPairingCallback& callback) {
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(caller_task_runner_->BelongsToCurrentThread());
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
120ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  GetPairingCallback wrapped_callback = base::Bind(
121ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      &PairingRegistry::InvokeGetPairingCallbackAndScheduleNext,
122ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      this, callback);
123ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::Closure request = base::Bind(
124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      &PairingRegistry::DoLoad, this, client_id, wrapped_callback);
125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ServiceOrQueueRequest(request);
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PairingRegistry::GetAllPairings(
129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const GetAllPairingsCallback& callback) {
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(caller_task_runner_->BelongsToCurrentThread());
131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  GetAllPairingsCallback wrapped_callback = base::Bind(
133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      &PairingRegistry::InvokeGetAllPairingsCallbackAndScheduleNext,
134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      this, callback);
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  GetAllPairingsCallback sanitize_callback = base::Bind(
136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      &PairingRegistry::SanitizePairings,
137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      this, wrapped_callback);
138ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::Closure request = base::Bind(
139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      &PairingRegistry::DoLoadAll, this, sanitize_callback);
140ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ServiceOrQueueRequest(request);
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PairingRegistry::DeletePairing(
144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::string& client_id, const DoneCallback& callback) {
145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(caller_task_runner_->BelongsToCurrentThread());
146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DoneCallback wrapped_callback = base::Bind(
148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      &PairingRegistry::InvokeDoneCallbackAndScheduleNext,
149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      this, callback);
150ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::Closure request = base::Bind(
151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      &PairingRegistry::DoDelete, this, client_id, wrapped_callback);
152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ServiceOrQueueRequest(request);
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
155ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PairingRegistry::ClearAllPairings(
156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const DoneCallback& callback) {
157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(caller_task_runner_->BelongsToCurrentThread());
158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DoneCallback wrapped_callback = base::Bind(
160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      &PairingRegistry::InvokeDoneCallbackAndScheduleNext,
161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      this, callback);
162ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::Closure request = base::Bind(
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      &PairingRegistry::DoDeleteAll, this, wrapped_callback);
164ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ServiceOrQueueRequest(request);
1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)PairingRegistry::~PairingRegistry() {
168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
169a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
170a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void PairingRegistry::PostTask(
171a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
172a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const tracked_objects::Location& from_here,
173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const base::Closure& task) {
174a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  task_runner->PostTask(from_here, task);
175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PairingRegistry::AddPairing(const Pairing& pairing) {
178a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DoneCallback wrapped_callback = base::Bind(
179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      &PairingRegistry::InvokeDoneCallbackAndScheduleNext,
180a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      this, DoneCallback());
181ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::Closure request = base::Bind(
182a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      &PairingRegistry::DoSave, this, pairing, wrapped_callback);
183ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ServiceOrQueueRequest(request);
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void PairingRegistry::DoLoadAll(
187a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const protocol::PairingRegistry::GetAllPairingsCallback& callback) {
188a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(delegate_task_runner_->BelongsToCurrentThread());
189a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
190a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<base::ListValue> pairings = delegate_->LoadAll();
191a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  PostTask(caller_task_runner_, FROM_HERE, base::Bind(callback,
192a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                                      base::Passed(&pairings)));
1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
194b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
195a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void PairingRegistry::DoDeleteAll(
196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const protocol::PairingRegistry::DoneCallback& callback) {
197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(delegate_task_runner_->BelongsToCurrentThread());
198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool success = delegate_->DeleteAll();
200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  PostTask(caller_task_runner_, FROM_HERE, base::Bind(callback, success));
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void PairingRegistry::DoLoad(
204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::string& client_id,
205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const protocol::PairingRegistry::GetPairingCallback& callback) {
206a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(delegate_task_runner_->BelongsToCurrentThread());
207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Pairing pairing = delegate_->Load(client_id);
209a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  PostTask(caller_task_runner_, FROM_HERE, base::Bind(callback, pairing));
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void PairingRegistry::DoSave(
213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const protocol::PairingRegistry::Pairing& pairing,
214a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const protocol::PairingRegistry::DoneCallback& callback) {
215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(delegate_task_runner_->BelongsToCurrentThread());
216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool success = delegate_->Save(pairing);
218a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  PostTask(caller_task_runner_, FROM_HERE, base::Bind(callback, success));
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
221a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void PairingRegistry::DoDelete(
222a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::string& client_id,
223a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const protocol::PairingRegistry::DoneCallback& callback) {
224a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(delegate_task_runner_->BelongsToCurrentThread());
225a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
226a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool success = delegate_->Delete(client_id);
227a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  PostTask(caller_task_runner_, FROM_HERE, base::Bind(callback, success));
228ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
229ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
230a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void PairingRegistry::InvokeDoneCallbackAndScheduleNext(
231a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const DoneCallback& callback, bool success) {
232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // CreatePairing doesn't have a callback, so the callback can be null.
233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!callback.is_null())
234ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    callback.Run(success);
235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pending_requests_.pop();
237ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ServiceNextRequest();
238ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
239ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
240ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PairingRegistry::InvokeGetPairingCallbackAndScheduleNext(
241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const GetPairingCallback& callback, Pairing pairing) {
242ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  callback.Run(pairing);
243ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pending_requests_.pop();
244ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ServiceNextRequest();
245ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
246ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PairingRegistry::InvokeGetAllPairingsCallbackAndScheduleNext(
248ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const GetAllPairingsCallback& callback,
249ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    scoped_ptr<base::ListValue> pairings) {
250ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  callback.Run(pairings.Pass());
251ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pending_requests_.pop();
252ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ServiceNextRequest();
253ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
254ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void PairingRegistry::SanitizePairings(const GetAllPairingsCallback& callback,
256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                       scoped_ptr<base::ListValue> pairings) {
257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(caller_task_runner_->BelongsToCurrentThread());
258a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<base::ListValue> sanitized_pairings(new base::ListValue());
260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < pairings->GetSize(); ++i) {
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* pairing_json;
262a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!pairings->GetDictionary(i, &pairing_json)) {
263a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      LOG(WARNING) << "A pairing entry is not a dictionary.";
264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      continue;
265a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
267a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Parse the pairing data.
268a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Pairing pairing = Pairing::CreateFromValue(*pairing_json);
269a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!pairing.is_valid()) {
270a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      LOG(WARNING) << "Could not parse a pairing entry.";
271a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      continue;
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
273a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
274a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Clear the shared secrect and append the pairing data to the list.
275a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Pairing sanitized_pairing(
276a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        pairing.created_time(),
277a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        pairing.client_name(),
278a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        pairing.client_id(),
279a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "");
280a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    sanitized_pairings->Append(sanitized_pairing.ToValue().release());
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  callback.Run(sanitized_pairings.Pass());
284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PairingRegistry::ServiceOrQueueRequest(const base::Closure& request) {
287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  bool servicing_request = !pending_requests_.empty();
288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pending_requests_.push(request);
289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!servicing_request) {
290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ServiceNextRequest();
291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PairingRegistry::ServiceNextRequest() {
295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (pending_requests_.empty())
296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  PostTask(delegate_task_runner_, FROM_HERE, pending_requests_.front());
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
301b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}  // namespace protocol
302b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}  // namespace remoting
303