Home | History | Annotate | Download | only in host
      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
      3 // found in the LICENSE file.
      4 
      5 #include "remoting/host/pairing_registry_delegate_linux.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/file_util.h"
      9 #include "base/files/file_enumerator.h"
     10 #include "base/files/important_file_writer.h"
     11 #include "base/json/json_file_value_serializer.h"
     12 #include "base/json/json_string_value_serializer.h"
     13 #include "base/location.h"
     14 #include "base/strings/stringprintf.h"
     15 #include "base/values.h"
     16 #include "remoting/host/branding.h"
     17 
     18 namespace {
     19 
     20 // The pairing registry path relative to the configuration directory.
     21 const char kRegistryDirectory[] = "paired-clients";
     22 
     23 const char kPairingFilenameFormat[] = "%s.json";
     24 const char kPairingFilenamePattern[] = "*.json";
     25 
     26 }  // namespace
     27 
     28 namespace remoting {
     29 
     30 using protocol::PairingRegistry;
     31 
     32 PairingRegistryDelegateLinux::PairingRegistryDelegateLinux() {
     33 }
     34 
     35 PairingRegistryDelegateLinux::~PairingRegistryDelegateLinux() {
     36 }
     37 
     38 scoped_ptr<base::ListValue> PairingRegistryDelegateLinux::LoadAll() {
     39   scoped_ptr<base::ListValue> pairings(new base::ListValue());
     40 
     41   // Enumerate all pairing files in the pairing registry.
     42   base::FilePath registry_path = GetRegistryPath();
     43   base::FileEnumerator enumerator(registry_path, false,
     44                                   base::FileEnumerator::FILES,
     45                                   kPairingFilenamePattern);
     46   for (base::FilePath pairing_file = enumerator.Next(); !pairing_file.empty();
     47        pairing_file = enumerator.Next()) {
     48     // Read the JSON containing pairing data.
     49     JSONFileValueSerializer serializer(pairing_file);
     50     int error_code;
     51     std::string error_message;
     52     scoped_ptr<base::Value> pairing_json(
     53         serializer.Deserialize(&error_code, &error_message));
     54     if (!pairing_json) {
     55       LOG(WARNING) << "Failed to load '" << pairing_file.value() << "' ("
     56                    << error_code << ").";
     57       continue;
     58     }
     59 
     60     pairings->Append(pairing_json.release());
     61   }
     62 
     63   return pairings.Pass();
     64 }
     65 
     66 bool PairingRegistryDelegateLinux::DeleteAll() {
     67   // Delete all pairing files in the pairing registry.
     68   base::FilePath registry_path = GetRegistryPath();
     69   base::FileEnumerator enumerator(registry_path, false,
     70                                   base::FileEnumerator::FILES,
     71                                   kPairingFilenamePattern);
     72 
     73   bool success = true;
     74   for (base::FilePath pairing_file = enumerator.Next(); !pairing_file.empty();
     75        pairing_file = enumerator.Next()) {
     76     success = success && base::DeleteFile(pairing_file, false);
     77   }
     78 
     79   return success;
     80 }
     81 
     82 PairingRegistry::Pairing PairingRegistryDelegateLinux::Load(
     83     const std::string& client_id) {
     84   base::FilePath registry_path = GetRegistryPath();
     85   base::FilePath pairing_file = registry_path.Append(
     86       base::StringPrintf(kPairingFilenameFormat, client_id.c_str()));
     87 
     88   JSONFileValueSerializer serializer(pairing_file);
     89   int error_code;
     90   std::string error_message;
     91   scoped_ptr<base::Value> pairing(
     92       serializer.Deserialize(&error_code, &error_message));
     93   if (!pairing) {
     94     LOG(WARNING) << "Failed to load pairing information: " << error_message
     95                  << " (" << error_code << ").";
     96     return PairingRegistry::Pairing();
     97   }
     98 
     99   base::DictionaryValue* pairing_dictionary;
    100   if (!pairing->GetAsDictionary(&pairing_dictionary)) {
    101     LOG(WARNING) << "Failed to parse pairing information: not a dictionary.";
    102     return PairingRegistry::Pairing();
    103   }
    104 
    105   return PairingRegistry::Pairing::CreateFromValue(*pairing_dictionary);
    106 }
    107 
    108 bool PairingRegistryDelegateLinux::Save(
    109     const PairingRegistry::Pairing& pairing) {
    110   base::FilePath registry_path = GetRegistryPath();
    111   base::File::Error error;
    112   if (!base::CreateDirectoryAndGetError(registry_path, &error)) {
    113     LOG(ERROR) << "Could not create pairing registry directory: " << error;
    114     return false;
    115   }
    116 
    117   std::string pairing_json;
    118   JSONStringValueSerializer serializer(&pairing_json);
    119   if (!serializer.Serialize(*pairing.ToValue())) {
    120     LOG(ERROR) << "Failed to serialize pairing data for "
    121                << pairing.client_id();
    122     return false;
    123   }
    124 
    125   base::FilePath pairing_file = registry_path.Append(
    126       base::StringPrintf(kPairingFilenameFormat, pairing.client_id().c_str()));
    127   if (!base::ImportantFileWriter::WriteFileAtomically(pairing_file,
    128                                                       pairing_json)) {
    129     LOG(ERROR) << "Could not save pairing data for " << pairing.client_id();
    130     return false;
    131   }
    132 
    133   return true;
    134 }
    135 
    136 bool PairingRegistryDelegateLinux::Delete(const std::string& client_id) {
    137   base::FilePath registry_path = GetRegistryPath();
    138   base::FilePath pairing_file = registry_path.Append(
    139       base::StringPrintf(kPairingFilenameFormat, client_id.c_str()));
    140 
    141   return base::DeleteFile(pairing_file, false);
    142 }
    143 
    144 base::FilePath PairingRegistryDelegateLinux::GetRegistryPath() {
    145   if (!registry_path_for_testing_.empty()) {
    146     return registry_path_for_testing_;
    147   }
    148 
    149   base::FilePath config_dir = remoting::GetConfigDir();
    150   return config_dir.Append(kRegistryDirectory);
    151 }
    152 
    153 void PairingRegistryDelegateLinux::SetRegistryPathForTesting(
    154     const base::FilePath& registry_path) {
    155   registry_path_for_testing_ = registry_path;
    156 }
    157 
    158 
    159 scoped_ptr<PairingRegistry::Delegate> CreatePairingRegistryDelegate() {
    160   return scoped_ptr<PairingRegistry::Delegate>(
    161       new PairingRegistryDelegateLinux());
    162 }
    163 
    164 }  // namespace remoting
    165