OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromecast/base/device_capabilities_impl.h" | 5 #include "chromecast/base/device_capabilities_impl.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 |
8 #include <utility> | 9 #include <utility> |
9 | 10 |
10 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/ptr_util.h" |
11 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
12 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
13 #include "base/values.h" | 15 #include "base/values.h" |
14 #include "chromecast/base/serializers.h" | 16 #include "chromecast/base/serializers.h" |
15 | 17 |
16 namespace chromecast { | 18 namespace chromecast { |
17 | 19 |
18 namespace { | 20 namespace { |
19 | 21 |
20 const char kPathSeparator = '.'; | 22 const char kPathSeparator = '.'; |
(...skipping 23 matching lines...) Expand all Loading... |
44 | 46 |
45 } // namespace | 47 } // namespace |
46 | 48 |
47 // static Default Capability Keys | 49 // static Default Capability Keys |
48 const char DeviceCapabilities::kKeyBluetoothSupported[] = "bluetooth_supported"; | 50 const char DeviceCapabilities::kKeyBluetoothSupported[] = "bluetooth_supported"; |
49 const char DeviceCapabilities::kKeyDisplaySupported[] = "display_supported"; | 51 const char DeviceCapabilities::kKeyDisplaySupported[] = "display_supported"; |
50 const char DeviceCapabilities::kKeyHiResAudioSupported[] = | 52 const char DeviceCapabilities::kKeyHiResAudioSupported[] = |
51 "hi_res_audio_supported"; | 53 "hi_res_audio_supported"; |
52 | 54 |
53 // static | 55 // static |
54 scoped_ptr<DeviceCapabilities> DeviceCapabilities::Create() { | 56 std::unique_ptr<DeviceCapabilities> DeviceCapabilities::Create() { |
55 return make_scoped_ptr(new DeviceCapabilitiesImpl); | 57 return base::WrapUnique(new DeviceCapabilitiesImpl); |
56 } | 58 } |
57 | 59 |
58 // static | 60 // static |
59 scoped_ptr<DeviceCapabilities> DeviceCapabilities::CreateForTesting() { | 61 std::unique_ptr<DeviceCapabilities> DeviceCapabilities::CreateForTesting() { |
60 DeviceCapabilities* capabilities = new DeviceCapabilitiesImpl; | 62 DeviceCapabilities* capabilities = new DeviceCapabilitiesImpl; |
61 capabilities->SetCapability( | 63 capabilities->SetCapability( |
62 kKeyBluetoothSupported, | 64 kKeyBluetoothSupported, |
63 make_scoped_ptr(new base::FundamentalValue(false))); | 65 base::WrapUnique(new base::FundamentalValue(false))); |
64 capabilities->SetCapability( | 66 capabilities->SetCapability( |
65 kKeyDisplaySupported, make_scoped_ptr(new base::FundamentalValue(true))); | 67 kKeyDisplaySupported, base::WrapUnique(new base::FundamentalValue(true))); |
66 capabilities->SetCapability( | 68 capabilities->SetCapability( |
67 kKeyHiResAudioSupported, | 69 kKeyHiResAudioSupported, |
68 make_scoped_ptr(new base::FundamentalValue(false))); | 70 base::WrapUnique(new base::FundamentalValue(false))); |
69 return make_scoped_ptr(capabilities); | 71 return base::WrapUnique(capabilities); |
70 } | 72 } |
71 | 73 |
72 scoped_refptr<DeviceCapabilities::Data> DeviceCapabilities::CreateData() { | 74 scoped_refptr<DeviceCapabilities::Data> DeviceCapabilities::CreateData() { |
73 return make_scoped_refptr(new Data); | 75 return make_scoped_refptr(new Data); |
74 } | 76 } |
75 | 77 |
76 scoped_refptr<DeviceCapabilities::Data> DeviceCapabilities::CreateData( | 78 scoped_refptr<DeviceCapabilities::Data> DeviceCapabilities::CreateData( |
77 scoped_ptr<const base::DictionaryValue> dictionary) { | 79 std::unique_ptr<const base::DictionaryValue> dictionary) { |
78 DCHECK(dictionary.get()); | 80 DCHECK(dictionary.get()); |
79 return make_scoped_refptr(new Data(std::move(dictionary))); | 81 return make_scoped_refptr(new Data(std::move(dictionary))); |
80 } | 82 } |
81 | 83 |
82 DeviceCapabilities::Validator::Validator(DeviceCapabilities* capabilities) | 84 DeviceCapabilities::Validator::Validator(DeviceCapabilities* capabilities) |
83 : capabilities_(capabilities) { | 85 : capabilities_(capabilities) { |
84 DCHECK(capabilities); | 86 DCHECK(capabilities); |
85 } | 87 } |
86 | 88 |
87 void DeviceCapabilities::Validator::SetValidatedValue( | 89 void DeviceCapabilities::Validator::SetValidatedValue( |
88 const std::string& path, | 90 const std::string& path, |
89 scoped_ptr<base::Value> new_value) const { | 91 std::unique_ptr<base::Value> new_value) const { |
90 capabilities_->SetValidatedValue(path, std::move(new_value)); | 92 capabilities_->SetValidatedValue(path, std::move(new_value)); |
91 } | 93 } |
92 | 94 |
93 DeviceCapabilities::Data::Data() | 95 DeviceCapabilities::Data::Data() |
94 : dictionary_(new base::DictionaryValue), | 96 : dictionary_(new base::DictionaryValue), |
95 json_string_(SerializeToJson(*dictionary_)) { | 97 json_string_(SerializeToJson(*dictionary_)) { |
96 DCHECK(json_string_.get()); | 98 DCHECK(json_string_.get()); |
97 } | 99 } |
98 | 100 |
99 DeviceCapabilities::Data::Data( | 101 DeviceCapabilities::Data::Data( |
100 scoped_ptr<const base::DictionaryValue> dictionary) | 102 std::unique_ptr<const base::DictionaryValue> dictionary) |
101 : dictionary_(std::move(dictionary)), | 103 : dictionary_(std::move(dictionary)), |
102 json_string_(SerializeToJson(*dictionary_)) { | 104 json_string_(SerializeToJson(*dictionary_)) { |
103 DCHECK(dictionary_.get()); | 105 DCHECK(dictionary_.get()); |
104 DCHECK(json_string_.get()); | 106 DCHECK(json_string_.get()); |
105 } | 107 } |
106 | 108 |
107 DeviceCapabilitiesImpl::Data::~Data() {} | 109 DeviceCapabilitiesImpl::Data::~Data() {} |
108 | 110 |
109 DeviceCapabilitiesImpl::ValidatorInfo::ValidatorInfo(Validator* validator) | 111 DeviceCapabilitiesImpl::ValidatorInfo::ValidatorInfo(Validator* validator) |
110 : validator_(validator), task_runner_(base::ThreadTaskRunnerHandle::Get()) { | 112 : validator_(validator), task_runner_(base::ThreadTaskRunnerHandle::Get()) { |
111 DCHECK(validator_); | 113 DCHECK(validator_); |
112 DCHECK(task_runner_.get()); | 114 DCHECK(task_runner_.get()); |
113 } | 115 } |
114 | 116 |
115 DeviceCapabilitiesImpl::ValidatorInfo::~ValidatorInfo() { | 117 DeviceCapabilitiesImpl::ValidatorInfo::~ValidatorInfo() { |
116 // Check that ValidatorInfo is being destroyed on the same thread that it was | 118 // Check that ValidatorInfo is being destroyed on the same thread that it was |
117 // constructed on. | 119 // constructed on. |
118 DCHECK(task_runner_->BelongsToCurrentThread()); | 120 DCHECK(task_runner_->BelongsToCurrentThread()); |
119 } | 121 } |
120 | 122 |
121 void DeviceCapabilitiesImpl::ValidatorInfo::Validate( | 123 void DeviceCapabilitiesImpl::ValidatorInfo::Validate( |
122 const std::string& path, | 124 const std::string& path, |
123 scoped_ptr<base::Value> proposed_value) const { | 125 std::unique_ptr<base::Value> proposed_value) const { |
124 // Check that we are running Validate on the same thread that ValidatorInfo | 126 // Check that we are running Validate on the same thread that ValidatorInfo |
125 // was constructed on. | 127 // was constructed on. |
126 DCHECK(task_runner_->BelongsToCurrentThread()); | 128 DCHECK(task_runner_->BelongsToCurrentThread()); |
127 validator_->Validate(path, std::move(proposed_value)); | 129 validator_->Validate(path, std::move(proposed_value)); |
128 } | 130 } |
129 | 131 |
130 DeviceCapabilitiesImpl::DeviceCapabilitiesImpl() | 132 DeviceCapabilitiesImpl::DeviceCapabilitiesImpl() |
131 : data_(CreateData()), | 133 : data_(CreateData()), |
132 task_runner_for_writes_(base::ThreadTaskRunnerHandle::Get()), | 134 task_runner_for_writes_(base::ThreadTaskRunnerHandle::Get()), |
133 observer_list_(new base::ObserverListThreadSafe<Observer>) { | 135 observer_list_(new base::ObserverListThreadSafe<Observer>) { |
134 DCHECK(task_runner_for_writes_.get()); | 136 DCHECK(task_runner_for_writes_.get()); |
135 } | 137 } |
136 | 138 |
137 DeviceCapabilitiesImpl::~DeviceCapabilitiesImpl() { | 139 DeviceCapabilitiesImpl::~DeviceCapabilitiesImpl() { |
138 // Make sure that any registered Validators have unregistered at this point | 140 // Make sure that any registered Validators have unregistered at this point |
139 DCHECK(validator_map_.empty()); | 141 DCHECK(validator_map_.empty()); |
140 // Make sure that all observers have been removed at this point | 142 // Make sure that all observers have been removed at this point |
141 observer_list_->AssertEmpty(); | 143 observer_list_->AssertEmpty(); |
142 } | 144 } |
143 | 145 |
144 void DeviceCapabilitiesImpl::Register(const std::string& key, | 146 void DeviceCapabilitiesImpl::Register(const std::string& key, |
145 Validator* validator) { | 147 Validator* validator) { |
146 DCHECK(IsValidRegisterKey(key)); | 148 DCHECK(IsValidRegisterKey(key)); |
147 DCHECK(validator); | 149 DCHECK(validator); |
148 | 150 |
149 base::AutoLock auto_lock(validation_lock_); | 151 base::AutoLock auto_lock(validation_lock_); |
150 bool added = | 152 bool added = |
151 validator_map_.add(key, make_scoped_ptr(new ValidatorInfo(validator))) | 153 validator_map_.add(key, base::WrapUnique(new ValidatorInfo(validator))) |
152 .second; | 154 .second; |
153 // Check that a validator has not already been registered for this key | 155 // Check that a validator has not already been registered for this key |
154 DCHECK(added); | 156 DCHECK(added); |
155 } | 157 } |
156 | 158 |
157 void DeviceCapabilitiesImpl::Unregister(const std::string& key, | 159 void DeviceCapabilitiesImpl::Unregister(const std::string& key, |
158 const Validator* validator) { | 160 const Validator* validator) { |
159 base::AutoLock auto_lock(validation_lock_); | 161 base::AutoLock auto_lock(validation_lock_); |
160 auto validator_it = validator_map_.find(key); | 162 auto validator_it = validator_map_.find(key); |
161 DCHECK(validator_it != validator_map_.end()); | 163 DCHECK(validator_it != validator_map_.end()); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 | 200 |
199 bool DeviceCapabilitiesImpl::HiResAudioSupported() const { | 201 bool DeviceCapabilitiesImpl::HiResAudioSupported() const { |
200 scoped_refptr<Data> data_ref = GetData(); | 202 scoped_refptr<Data> data_ref = GetData(); |
201 bool hi_res_audio_supported = false; | 203 bool hi_res_audio_supported = false; |
202 bool found_key = data_ref->dictionary().GetBoolean(kKeyHiResAudioSupported, | 204 bool found_key = data_ref->dictionary().GetBoolean(kKeyHiResAudioSupported, |
203 &hi_res_audio_supported); | 205 &hi_res_audio_supported); |
204 DCHECK(found_key); | 206 DCHECK(found_key); |
205 return hi_res_audio_supported; | 207 return hi_res_audio_supported; |
206 } | 208 } |
207 | 209 |
208 scoped_ptr<base::Value> DeviceCapabilitiesImpl::GetCapability( | 210 std::unique_ptr<base::Value> DeviceCapabilitiesImpl::GetCapability( |
209 const std::string& path) const { | 211 const std::string& path) const { |
210 scoped_refptr<Data> data_ref = GetData(); | 212 scoped_refptr<Data> data_ref = GetData(); |
211 const base::Value* value = nullptr; | 213 const base::Value* value = nullptr; |
212 bool found_path = data_ref->dictionary().Get(path, &value); | 214 bool found_path = data_ref->dictionary().Get(path, &value); |
213 return found_path ? value->CreateDeepCopy() : scoped_ptr<base::Value>(); | 215 return found_path ? value->CreateDeepCopy() : std::unique_ptr<base::Value>(); |
214 } | 216 } |
215 | 217 |
216 scoped_refptr<DeviceCapabilities::Data> | 218 scoped_refptr<DeviceCapabilities::Data> |
217 DeviceCapabilitiesImpl::GetData() const { | 219 DeviceCapabilitiesImpl::GetData() const { |
218 // Need to acquire lock here when copy constructing data_ otherwise we could | 220 // Need to acquire lock here when copy constructing data_ otherwise we could |
219 // be concurrently be writing to scoped_refptr in SetValidatedValue(), which | 221 // be concurrently be writing to scoped_refptr in SetValidatedValue(), which |
220 // could cause a bad scoped_refptr read. | 222 // could cause a bad scoped_refptr read. |
221 base::AutoLock auto_lock(data_lock_); | 223 base::AutoLock auto_lock(data_lock_); |
222 return data_; | 224 return data_; |
223 } | 225 } |
224 | 226 |
225 void DeviceCapabilitiesImpl::SetCapability( | 227 void DeviceCapabilitiesImpl::SetCapability( |
226 const std::string& path, | 228 const std::string& path, |
227 scoped_ptr<base::Value> proposed_value) { | 229 std::unique_ptr<base::Value> proposed_value) { |
228 DCHECK(proposed_value.get()); | 230 DCHECK(proposed_value.get()); |
229 if (!IsValidPath(path)) { | 231 if (!IsValidPath(path)) { |
230 LOG(DFATAL) << "Invalid capability path encountered for SetCapability()"; | 232 LOG(DFATAL) << "Invalid capability path encountered for SetCapability()"; |
231 return; | 233 return; |
232 } | 234 } |
233 | 235 |
234 { | 236 { |
235 base::AutoLock auto_lock(validation_lock_); | 237 base::AutoLock auto_lock(validation_lock_); |
236 // Check for Validator registered under first key per the Register() | 238 // Check for Validator registered under first key per the Register() |
237 // interface. | 239 // interface. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 observer_list_->AddObserver(observer); | 271 observer_list_->AddObserver(observer); |
270 } | 272 } |
271 | 273 |
272 void DeviceCapabilitiesImpl::RemoveCapabilitiesObserver(Observer* observer) { | 274 void DeviceCapabilitiesImpl::RemoveCapabilitiesObserver(Observer* observer) { |
273 DCHECK(observer); | 275 DCHECK(observer); |
274 observer_list_->RemoveObserver(observer); | 276 observer_list_->RemoveObserver(observer); |
275 } | 277 } |
276 | 278 |
277 void DeviceCapabilitiesImpl::SetValidatedValue( | 279 void DeviceCapabilitiesImpl::SetValidatedValue( |
278 const std::string& path, | 280 const std::string& path, |
279 scoped_ptr<base::Value> new_value) { | 281 std::unique_ptr<base::Value> new_value) { |
280 // All internal writes/modifications of capabilities must occur on same | 282 // All internal writes/modifications of capabilities must occur on same |
281 // thread to avoid race conditions. | 283 // thread to avoid race conditions. |
282 if (!task_runner_for_writes_->BelongsToCurrentThread()) { | 284 if (!task_runner_for_writes_->BelongsToCurrentThread()) { |
283 task_runner_for_writes_->PostTask( | 285 task_runner_for_writes_->PostTask( |
284 FROM_HERE, | 286 FROM_HERE, |
285 base::Bind(&DeviceCapabilitiesImpl::SetValidatedValue, | 287 base::Bind(&DeviceCapabilitiesImpl::SetValidatedValue, |
286 base::Unretained(this), path, base::Passed(&new_value))); | 288 base::Unretained(this), path, base::Passed(&new_value))); |
287 return; | 289 return; |
288 } | 290 } |
289 | 291 |
290 DCHECK(IsValidPath(path)); | 292 DCHECK(IsValidPath(path)); |
291 DCHECK(new_value.get()); | 293 DCHECK(new_value.get()); |
292 | 294 |
293 // We don't need to acquire lock here when reading data_ because we know that | 295 // We don't need to acquire lock here when reading data_ because we know that |
294 // all writes to data_ must occur serially on thread that we're on. | 296 // all writes to data_ must occur serially on thread that we're on. |
295 const base::Value* cur_value = nullptr; | 297 const base::Value* cur_value = nullptr; |
296 bool capability_unchanged = data_->dictionary().Get(path, &cur_value) && | 298 bool capability_unchanged = data_->dictionary().Get(path, &cur_value) && |
297 cur_value->Equals(new_value.get()); | 299 cur_value->Equals(new_value.get()); |
298 if (capability_unchanged) { | 300 if (capability_unchanged) { |
299 VLOG(1) << "Ignoring unchanged capability: " << path; | 301 VLOG(1) << "Ignoring unchanged capability: " << path; |
300 return; | 302 return; |
301 } | 303 } |
302 | 304 |
303 // In this sequence, we create a deep copy, modify the deep copy, and then | 305 // In this sequence, we create a deep copy, modify the deep copy, and then |
304 // do a pointer swap. We do this to have minimal time spent in the | 306 // do a pointer swap. We do this to have minimal time spent in the |
305 // data_lock_. If we were to lock and modify the capabilities | 307 // data_lock_. If we were to lock and modify the capabilities |
306 // dictionary directly, there may be expensive writes that block other | 308 // dictionary directly, there may be expensive writes that block other |
307 // threads. | 309 // threads. |
308 scoped_ptr<base::DictionaryValue> dictionary_deep_copy( | 310 std::unique_ptr<base::DictionaryValue> dictionary_deep_copy( |
309 data_->dictionary().CreateDeepCopy()); | 311 data_->dictionary().CreateDeepCopy()); |
310 dictionary_deep_copy->Set(path, std::move(new_value)); | 312 dictionary_deep_copy->Set(path, std::move(new_value)); |
311 scoped_refptr<Data> new_data(CreateData(std::move(dictionary_deep_copy))); | 313 scoped_refptr<Data> new_data(CreateData(std::move(dictionary_deep_copy))); |
312 | 314 |
313 { | 315 { |
314 base::AutoLock auto_lock(data_lock_); | 316 base::AutoLock auto_lock(data_lock_); |
315 // Using swap instead of assignment operator here because it's a little | 317 // Using swap instead of assignment operator here because it's a little |
316 // faster. Avoids an extra call to AddRef()/Release(). | 318 // faster. Avoids an extra call to AddRef()/Release(). |
317 data_.swap(new_data); | 319 data_.swap(new_data); |
318 } | 320 } |
319 | 321 |
320 // Even though ObserverListThreadSafe notifications are always asynchronous | 322 // Even though ObserverListThreadSafe notifications are always asynchronous |
321 // (posts task even if to same thread), no locks should be held at this point | 323 // (posts task even if to same thread), no locks should be held at this point |
322 // in the code. This is just to be safe that no deadlocks occur if Observers | 324 // in the code. This is just to be safe that no deadlocks occur if Observers |
323 // call DeviceCapabilities methods in OnCapabilitiesChanged(). | 325 // call DeviceCapabilities methods in OnCapabilitiesChanged(). |
324 observer_list_->Notify(FROM_HERE, &Observer::OnCapabilitiesChanged, path); | 326 observer_list_->Notify(FROM_HERE, &Observer::OnCapabilitiesChanged, path); |
325 } | 327 } |
326 | 328 |
327 } // namespace chromecast | 329 } // namespace chromecast |
OLD | NEW |