Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / remoting / host / pairing_registry_delegate_win.cc
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_win.h"
6
7 #include "base/json/json_string_value_serializer.h"
8 #include "base/logging.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "base/win/registry.h"
12
13 namespace remoting {
14
15 namespace {
16
17 // Duplicates a registry key handle (returned by RegCreateXxx/RegOpenXxx).
18 // The returned handle cannot be inherited and has the same permissions as
19 // the source one.
20 bool DuplicateKeyHandle(HKEY source, base::win::RegKey* dest) {
21   HANDLE handle;
22   if (!DuplicateHandle(GetCurrentProcess(),
23                        source,
24                        GetCurrentProcess(),
25                        &handle,
26                        0,
27                        FALSE,
28                        DUPLICATE_SAME_ACCESS)) {
29     PLOG(ERROR) << "Failed to duplicate a registry key handle";
30     return false;
31   }
32
33   dest->Set(reinterpret_cast<HKEY>(handle));
34   return true;
35 }
36
37 // Reads value |value_name| from |key| as a JSON string and returns it as
38 // |base::Value|.
39 scoped_ptr<base::DictionaryValue> ReadValue(const base::win::RegKey& key,
40                                             const wchar_t* value_name) {
41   // presubmit: allow wstring
42   std::wstring value_json;
43   LONG result = key.ReadValue(value_name, &value_json);
44   if (result != ERROR_SUCCESS) {
45     SetLastError(result);
46     PLOG(ERROR) << "Cannot read value '" << value_name << "'";
47     return nullptr;
48   }
49
50   // Parse the value.
51   std::string value_json_utf8 = base::WideToUTF8(value_json);
52   JSONStringValueSerializer serializer(&value_json_utf8);
53   int error_code;
54   std::string error_message;
55   scoped_ptr<base::Value> value(serializer.Deserialize(&error_code,
56                                                        &error_message));
57   if (!value) {
58     LOG(ERROR) << "Failed to parse '" << value_name << "': " << error_message
59                << " (" << error_code << ").";
60     return nullptr;
61   }
62
63   if (!value->IsType(base::Value::TYPE_DICTIONARY)) {
64     LOG(ERROR) << "Failed to parse '" << value_name << "': not a dictionary.";
65     return nullptr;
66   }
67
68   return make_scoped_ptr(static_cast<base::DictionaryValue*>(value.release()));
69 }
70
71 // Serializes |value| into a JSON string and writes it as value |value_name|
72 // under |key|.
73 bool WriteValue(base::win::RegKey& key,
74                 const wchar_t* value_name,
75                 scoped_ptr<base::DictionaryValue> value) {
76   std::string value_json_utf8;
77   JSONStringValueSerializer serializer(&value_json_utf8);
78   if (!serializer.Serialize(*value)) {
79     LOG(ERROR) << "Failed to serialize '" << value_name << "'";
80     return false;
81   }
82
83   // presubmit: allow wstring
84   std::wstring value_json = base::UTF8ToWide(value_json_utf8);
85   LONG result = key.WriteValue(value_name, value_json.c_str());
86   if (result != ERROR_SUCCESS) {
87     SetLastError(result);
88     PLOG(ERROR) << "Cannot write value '" << value_name << "'";
89     return false;
90   }
91
92   return true;
93 }
94
95 }  // namespace
96
97 using protocol::PairingRegistry;
98
99 PairingRegistryDelegateWin::PairingRegistryDelegateWin() {
100 }
101
102 PairingRegistryDelegateWin::~PairingRegistryDelegateWin() {
103 }
104
105 bool PairingRegistryDelegateWin::SetRootKeys(HKEY privileged,
106                                              HKEY unprivileged) {
107   DCHECK(!privileged_.Valid());
108   DCHECK(!unprivileged_.Valid());
109   DCHECK(unprivileged);
110
111   if (!DuplicateKeyHandle(unprivileged, &unprivileged_))
112     return false;
113
114   if (privileged) {
115     if (!DuplicateKeyHandle(privileged, &privileged_))
116       return false;
117   }
118
119   return true;
120 }
121
122 scoped_ptr<base::ListValue> PairingRegistryDelegateWin::LoadAll() {
123   scoped_ptr<base::ListValue> pairings(new base::ListValue());
124
125   // Enumerate and parse all values under the unprivileged key.
126   DWORD count = unprivileged_.GetValueCount();
127   for (DWORD index = 0; index < count; ++index) {
128     // presubmit: allow wstring
129     std::wstring value_name;
130     LONG result = unprivileged_.GetValueNameAt(index, &value_name);
131     if (result != ERROR_SUCCESS) {
132       SetLastError(result);
133       PLOG(ERROR) << "Cannot get the name of value " << index;
134       continue;
135     }
136
137     PairingRegistry::Pairing pairing = Load(base::WideToUTF8(value_name));
138     if (pairing.is_valid())
139       pairings->Append(pairing.ToValue().release());
140   }
141
142   return pairings.Pass();
143 }
144
145 bool PairingRegistryDelegateWin::DeleteAll() {
146   if (!privileged_.Valid()) {
147     LOG(ERROR) << "Cannot delete pairings: the delegate is read-only.";
148     return false;
149   }
150
151   // Enumerate and delete the values in the privileged and unprivileged keys
152   // separately in case they get out of sync.
153   bool success = true;
154   DWORD count = unprivileged_.GetValueCount();
155   while (count > 0) {
156     // presubmit: allow wstring
157     std::wstring value_name;
158     LONG result = unprivileged_.GetValueNameAt(0, &value_name);
159     if (result == ERROR_SUCCESS)
160       result = unprivileged_.DeleteValue(value_name.c_str());
161
162     success = success && (result == ERROR_SUCCESS);
163     count = unprivileged_.GetValueCount();
164   }
165
166   count = privileged_.GetValueCount();
167   while (count > 0) {
168     // presubmit: allow wstring
169     std::wstring value_name;
170     LONG result = privileged_.GetValueNameAt(0, &value_name);
171     if (result == ERROR_SUCCESS)
172       result = privileged_.DeleteValue(value_name.c_str());
173
174     success = success && (result == ERROR_SUCCESS);
175     count = privileged_.GetValueCount();
176   }
177
178   return success;
179 }
180
181 PairingRegistry::Pairing PairingRegistryDelegateWin::Load(
182     const std::string& client_id) {
183   // presubmit: allow wstring
184   std::wstring value_name = base::UTF8ToWide(client_id);
185
186   // Read unprivileged fields first.
187   scoped_ptr<base::DictionaryValue> pairing = ReadValue(unprivileged_,
188                                                         value_name.c_str());
189   if (!pairing)
190     return PairingRegistry::Pairing();
191
192   // Read the shared secret.
193   if (privileged_.Valid()) {
194     scoped_ptr<base::DictionaryValue> secret = ReadValue(privileged_,
195                                                          value_name.c_str());
196     if (!secret)
197       return PairingRegistry::Pairing();
198
199     // Merge the two dictionaries.
200     pairing->MergeDictionary(secret.get());
201   }
202
203   return PairingRegistry::Pairing::CreateFromValue(*pairing);
204 }
205
206 bool PairingRegistryDelegateWin::Save(const PairingRegistry::Pairing& pairing) {
207   if (!privileged_.Valid()) {
208     LOG(ERROR) << "Cannot save pairing entry '" << pairing.client_id()
209                 << "': the delegate is read-only.";
210     return false;
211   }
212
213   // Convert pairing to JSON.
214   scoped_ptr<base::DictionaryValue> pairing_json = pairing.ToValue();
215
216   // Extract the shared secret to a separate dictionary.
217   scoped_ptr<base::Value> secret_key;
218   CHECK(pairing_json->Remove(PairingRegistry::kSharedSecretKey, &secret_key));
219   scoped_ptr<base::DictionaryValue> secret_json(new base::DictionaryValue());
220   secret_json->Set(PairingRegistry::kSharedSecretKey, secret_key.release());
221
222   // presubmit: allow wstring
223   std::wstring value_name = base::UTF8ToWide(pairing.client_id());
224
225   // Write pairing to the registry.
226   if (!WriteValue(privileged_, value_name.c_str(), secret_json.Pass()) ||
227       !WriteValue(unprivileged_, value_name.c_str(), pairing_json.Pass())) {
228     return false;
229   }
230
231   return true;
232 }
233
234 bool PairingRegistryDelegateWin::Delete(const std::string& client_id) {
235   if (!privileged_.Valid()) {
236     LOG(ERROR) << "Cannot delete pairing entry '" << client_id
237                 << "': the delegate is read-only.";
238     return false;
239   }
240
241   // presubmit: allow wstring
242   std::wstring value_name = base::UTF8ToWide(client_id);
243   LONG result = privileged_.DeleteValue(value_name.c_str());
244   if (result != ERROR_SUCCESS &&
245       result != ERROR_FILE_NOT_FOUND &&
246       result != ERROR_PATH_NOT_FOUND) {
247     SetLastError(result);
248     PLOG(ERROR) << "Cannot delete pairing entry '" << client_id << "'";
249     return false;
250   }
251
252   result = unprivileged_.DeleteValue(value_name.c_str());
253   if (result != ERROR_SUCCESS &&
254       result != ERROR_FILE_NOT_FOUND &&
255       result != ERROR_PATH_NOT_FOUND) {
256     SetLastError(result);
257     PLOG(ERROR) << "Cannot delete pairing entry '" << client_id << "'";
258     return false;
259   }
260
261   return true;
262 }
263
264 scoped_ptr<PairingRegistry::Delegate> CreatePairingRegistryDelegate() {
265   return make_scoped_ptr(new PairingRegistryDelegateWin());
266 }
267
268 }  // namespace remoting