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