| Index: remoting/protocol/pairing_registry.cc
 | 
| diff --git a/remoting/protocol/pairing_registry.cc b/remoting/protocol/pairing_registry.cc
 | 
| index 6c9cc66ac3504c9ce18ac5acb0407b07ea9cf136..558c3026a5344c0481a35e798263960766be0932 100644
 | 
| --- a/remoting/protocol/pairing_registry.cc
 | 
| +++ b/remoting/protocol/pairing_registry.cc
 | 
| @@ -7,8 +7,18 @@
 | 
|  #include "base/base64.h"
 | 
|  #include "base/bind.h"
 | 
|  #include "base/guid.h"
 | 
| +#include "base/json/json_string_value_serializer.h"
 | 
| +#include "base/strings/string_number_conversions.h"
 | 
| +#include "base/values.h"
 | 
|  #include "crypto/random.h"
 | 
|  
 | 
| +namespace {
 | 
| +const char kCreatedTimeKey[] = "created-time";
 | 
| +const char kClientIdKey[] = "client-id";
 | 
| +const char kClientNameKey[] = "client-name";
 | 
| +const char kSharedSecretKey[] = "shared-secret";
 | 
| +}  // namespace
 | 
| +
 | 
|  namespace remoting {
 | 
|  namespace protocol {
 | 
|  
 | 
| @@ -68,30 +78,101 @@ PairingRegistry::Pairing PairingRegistry::CreatePairing(
 | 
|      const std::string& client_name) {
 | 
|    DCHECK(CalledOnValidThread());
 | 
|    Pairing result = Pairing::Create(client_name);
 | 
| -  delegate_->AddPairing(result, AddPairingCallback());
 | 
| +  AddPairing(result);
 | 
|    return result;
 | 
|  }
 | 
|  
 | 
|  void PairingRegistry::GetPairing(const std::string& client_id,
 | 
|                                   const GetPairingCallback& callback) {
 | 
|    DCHECK(CalledOnValidThread());
 | 
| -  delegate_->GetPairing(client_id, callback);
 | 
| +  delegate_->Load(
 | 
| +      base::Bind(&PairingRegistry::DoGetPairing, this, client_id, callback));
 | 
| +}
 | 
| +
 | 
| +void PairingRegistry::AddPairing(const Pairing& pairing) {
 | 
| +  delegate_->Load(
 | 
| +      base::Bind(&PairingRegistry::MergePairingAndSave, this, pairing));
 | 
| +}
 | 
| +
 | 
| +void PairingRegistry::MergePairingAndSave(const Pairing& pairing,
 | 
| +                                          const std::string& pairings_json) {
 | 
| +  DCHECK(CalledOnValidThread());
 | 
| +  PairedClients clients = DecodeJson(pairings_json);
 | 
| +  clients[pairing.client_id()] = pairing;
 | 
| +  std::string new_pairings_json = EncodeJson(clients);
 | 
| +  delegate_->Save(new_pairings_json, SaveCallback());
 | 
|  }
 | 
|  
 | 
| -void NotImplementedPairingRegistryDelegate::AddPairing(
 | 
| -    const PairingRegistry::Pairing& new_paired_client,
 | 
| -    const PairingRegistry::AddPairingCallback& callback) {
 | 
| -  NOTIMPLEMENTED();
 | 
| -  if (!callback.is_null()) {
 | 
| -    callback.Run(false);
 | 
| +void PairingRegistry::DoGetPairing(const std::string& client_id,
 | 
| +                                   const GetPairingCallback& callback,
 | 
| +                                   const std::string& pairings_json) {
 | 
| +  PairedClients clients = DecodeJson(pairings_json);
 | 
| +  Pairing result = clients[client_id];
 | 
| +  callback.Run(result);
 | 
| +}
 | 
| +
 | 
| +PairingRegistry::PairedClients PairingRegistry::DecodeJson(
 | 
| +    const std::string& pairings_json) {
 | 
| +  PairedClients result;
 | 
| +
 | 
| +  if (pairings_json.empty()) {
 | 
| +    return result;
 | 
| +  }
 | 
| +
 | 
| +  JSONStringValueSerializer registry(pairings_json);
 | 
| +  int error_code;
 | 
| +  std::string error_message;
 | 
| +  scoped_ptr<base::Value> root(
 | 
| +      registry.Deserialize(&error_code, &error_message));
 | 
| +  if (!root) {
 | 
| +    LOG(ERROR) << "Failed to load paired clients: " << error_message
 | 
| +               << " (" << error_code << ").";
 | 
| +    return result;
 | 
|    }
 | 
| +
 | 
| +  base::ListValue* root_list = NULL;
 | 
| +  if (!root->GetAsList(&root_list)) {
 | 
| +    LOG(ERROR) << "Failed to load paired clients: root node is not a list.";
 | 
| +    return result;
 | 
| +  }
 | 
| +
 | 
| +  for (size_t i = 0; i < root_list->GetSize(); ++i) {
 | 
| +    base::DictionaryValue* pairing = NULL;
 | 
| +    std::string client_name, client_id, shared_secret;
 | 
| +    double created_time_value;
 | 
| +    if (root_list->GetDictionary(i, &pairing) &&
 | 
| +        pairing->GetDouble(kCreatedTimeKey, &created_time_value) &&
 | 
| +        pairing->GetString(kClientNameKey, &client_name) &&
 | 
| +        pairing->GetString(kClientIdKey, &client_id) &&
 | 
| +        pairing->GetString(kSharedSecretKey, &shared_secret)) {
 | 
| +      base::Time created_time = base::Time::FromJsTime(created_time_value);
 | 
| +      result[client_id] = Pairing(
 | 
| +          created_time, client_name, client_id, shared_secret);
 | 
| +    } else {
 | 
| +      LOG(ERROR) << "Paired client " << i << " has unexpected format.";
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  return result;
 | 
|  }
 | 
|  
 | 
| -void NotImplementedPairingRegistryDelegate::GetPairing(
 | 
| -    const std::string& client_id,
 | 
| -    const PairingRegistry::GetPairingCallback& callback) {
 | 
| -  NOTIMPLEMENTED();
 | 
| -  callback.Run(PairingRegistry::Pairing());
 | 
| +std::string PairingRegistry::EncodeJson(const PairedClients& clients) {
 | 
| +  base::ListValue root;
 | 
| +  for (PairedClients::const_iterator i = clients.begin();
 | 
| +       i != clients.end(); ++i) {
 | 
| +    base::DictionaryValue* pairing = new base::DictionaryValue();
 | 
| +    pairing->SetDouble(kCreatedTimeKey, i->second.created_time().ToJsTime());
 | 
| +    pairing->SetString(kClientNameKey, i->second.client_name());
 | 
| +    pairing->SetString(kClientIdKey, i->second.client_id());
 | 
| +    pairing->SetString(kSharedSecretKey, i->second.shared_secret());
 | 
| +    root.Append(pairing);
 | 
| +  }
 | 
| +
 | 
| +  std::string result;
 | 
| +  JSONStringValueSerializer serializer(&result);
 | 
| +  serializer.Serialize(root);
 | 
| +
 | 
| +  return result;
 | 
|  }
 | 
|  
 | 
|  }  // namespace protocol
 | 
| 
 |