OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/browser/devtools/devtools_targets_ui.h" | 5 #include "chrome/browser/devtools/devtools_targets_ui.h" |
6 | 6 |
7 #include "base/memory/weak_ptr.h" | 7 #include "base/memory/weak_ptr.h" |
8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "content/public/browser/worker_service.h" | 23 #include "content/public/browser/worker_service.h" |
24 #include "content/public/browser/worker_service_observer.h" | 24 #include "content/public/browser/worker_service_observer.h" |
25 #include "content/public/common/process_type.h" | 25 #include "content/public/common/process_type.h" |
26 #include "net/base/escape.h" | 26 #include "net/base/escape.h" |
27 | 27 |
28 using content::BrowserThread; | 28 using content::BrowserThread; |
29 | 29 |
30 namespace { | 30 namespace { |
31 | 31 |
32 const char kTargetSourceField[] = "source"; | 32 const char kTargetSourceField[] = "source"; |
33 const char kTargetSourceRenderer[] = "renderers"; | 33 const char kTargetSourceLocal[] = "local"; |
34 const char kTargetSourceWorker[] = "workers"; | 34 const char kTargetSourceRemote[] = "remote"; |
35 const char kTargetSourceAdb[] = "adb"; | |
36 | 35 |
37 const char kTargetIdField[] = "id"; | 36 const char kTargetIdField[] = "id"; |
38 const char kTargetTypeField[] = "type"; | 37 const char kTargetTypeField[] = "type"; |
39 const char kAttachedField[] = "attached"; | 38 const char kAttachedField[] = "attached"; |
40 const char kUrlField[] = "url"; | 39 const char kUrlField[] = "url"; |
41 const char kNameField[] = "name"; | 40 const char kNameField[] = "name"; |
42 const char kFaviconUrlField[] = "faviconUrl"; | 41 const char kFaviconUrlField[] = "faviconUrl"; |
43 const char kDescriptionField[] = "description"; | 42 const char kDescriptionField[] = "description"; |
44 | 43 |
45 const char kGuestList[] = "guests"; | 44 const char kGuestList[] = "guests"; |
(...skipping 27 matching lines...) Expand all Loading... |
73 delay); | 72 delay); |
74 } | 73 } |
75 | 74 |
76 private: | 75 private: |
77 void Fire() { callback_.Run(); } | 76 void Fire() { callback_.Run(); } |
78 | 77 |
79 base::Closure callback_; | 78 base::Closure callback_; |
80 base::WeakPtrFactory<CancelableTimer> weak_factory_; | 79 base::WeakPtrFactory<CancelableTimer> weak_factory_; |
81 }; | 80 }; |
82 | 81 |
83 // RenderViewHostTargetsUIHandler --------------------------------------------- | |
84 | |
85 class RenderViewHostTargetsUIHandler | |
86 : public DevToolsTargetsUIHandler, | |
87 public content::NotificationObserver { | |
88 public: | |
89 explicit RenderViewHostTargetsUIHandler(const Callback& callback); | |
90 virtual ~RenderViewHostTargetsUIHandler(); | |
91 | |
92 private: | |
93 // content::NotificationObserver overrides. | |
94 virtual void Observe(int type, | |
95 const content::NotificationSource& source, | |
96 const content::NotificationDetails& details) OVERRIDE; | |
97 | |
98 void UpdateTargets(); | |
99 | |
100 content::NotificationRegistrar notification_registrar_; | |
101 scoped_ptr<CancelableTimer> timer_; | |
102 }; | |
103 | |
104 RenderViewHostTargetsUIHandler::RenderViewHostTargetsUIHandler( | |
105 const Callback& callback) | |
106 : DevToolsTargetsUIHandler(kTargetSourceRenderer, callback) { | |
107 notification_registrar_.Add(this, | |
108 content::NOTIFICATION_WEB_CONTENTS_CONNECTED, | |
109 content::NotificationService::AllSources()); | |
110 notification_registrar_.Add(this, | |
111 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, | |
112 content::NotificationService::AllSources()); | |
113 notification_registrar_.Add(this, | |
114 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
115 content::NotificationService::AllSources()); | |
116 UpdateTargets(); | |
117 } | |
118 | |
119 RenderViewHostTargetsUIHandler::~RenderViewHostTargetsUIHandler() { | |
120 notification_registrar_.RemoveAll(); | |
121 } | |
122 | |
123 void RenderViewHostTargetsUIHandler::Observe( | |
124 int type, | |
125 const content::NotificationSource& source, | |
126 const content::NotificationDetails& details) { | |
127 const int kUpdateDelay = 100; | |
128 timer_.reset( | |
129 new CancelableTimer( | |
130 base::Bind(&RenderViewHostTargetsUIHandler::UpdateTargets, | |
131 base::Unretained(this)), | |
132 base::TimeDelta::FromMilliseconds(kUpdateDelay))); | |
133 } | |
134 | |
135 void RenderViewHostTargetsUIHandler::UpdateTargets() { | |
136 base::ListValue list_value; | |
137 | |
138 std::map<std::string, base::DictionaryValue*> id_to_descriptor; | |
139 | |
140 DevToolsTargetImpl::List targets = | |
141 DevToolsTargetImpl::EnumerateWebContentsTargets(); | |
142 | |
143 STLDeleteValues(&targets_); | |
144 for (DevToolsTargetImpl::List::iterator it = targets.begin(); | |
145 it != targets.end(); ++it) { | |
146 DevToolsTargetImpl* target = *it; | |
147 targets_[target->GetId()] = target; | |
148 id_to_descriptor[target->GetId()] = Serialize(*target); | |
149 } | |
150 | |
151 for (TargetMap::iterator it(targets_.begin()); it != targets_.end(); ++it) { | |
152 DevToolsTargetImpl* target = it->second; | |
153 base::DictionaryValue* descriptor = id_to_descriptor[target->GetId()]; | |
154 | |
155 std::string parent_id = target->GetParentId(); | |
156 if (parent_id.empty() || id_to_descriptor.count(parent_id) == 0) { | |
157 list_value.Append(descriptor); | |
158 } else { | |
159 base::DictionaryValue* parent = id_to_descriptor[parent_id]; | |
160 base::ListValue* guests = NULL; | |
161 if (!parent->GetList(kGuestList, &guests)) { | |
162 guests = new base::ListValue(); | |
163 parent->Set(kGuestList, guests); | |
164 } | |
165 guests->Append(descriptor); | |
166 } | |
167 } | |
168 | |
169 SendSerializedTargets(list_value); | |
170 } | |
171 | |
172 // WorkerObserver ------------------------------------------------------------- | 82 // WorkerObserver ------------------------------------------------------------- |
173 | 83 |
174 class WorkerObserver | 84 class WorkerObserver |
175 : public content::WorkerServiceObserver, | 85 : public content::WorkerServiceObserver, |
176 public base::RefCountedThreadSafe<WorkerObserver> { | 86 public base::RefCountedThreadSafe<WorkerObserver> { |
177 public: | 87 public: |
178 WorkerObserver() {} | 88 WorkerObserver() {} |
179 | 89 |
180 void Start(DevToolsTargetImpl::Callback callback) { | 90 void Start(base::Closure callback) { |
181 DCHECK(callback_.is_null()); | 91 DCHECK(callback_.is_null()); |
182 DCHECK(!callback.is_null()); | 92 DCHECK(!callback.is_null()); |
183 callback_ = callback; | 93 callback_ = callback; |
184 BrowserThread::PostTask( | 94 BrowserThread::PostTask( |
185 BrowserThread::IO, FROM_HERE, | 95 BrowserThread::IO, FROM_HERE, |
186 base::Bind(&WorkerObserver::StartOnIOThread, this)); | 96 base::Bind(&WorkerObserver::StartOnIOThread, this)); |
187 } | 97 } |
188 | 98 |
189 void Stop() { | 99 void Stop() { |
190 DCHECK(!callback_.is_null()); | 100 DCHECK(!callback_.is_null()); |
191 callback_ = DevToolsTargetImpl::Callback(); | 101 callback_ = base::Closure(); |
192 BrowserThread::PostTask( | 102 BrowserThread::PostTask( |
193 BrowserThread::IO, FROM_HERE, | 103 BrowserThread::IO, FROM_HERE, |
194 base::Bind(&WorkerObserver::StopOnIOThread, this)); | 104 base::Bind(&WorkerObserver::StopOnIOThread, this)); |
195 } | 105 } |
196 | 106 |
197 void Enumerate() { | |
198 BrowserThread::PostTask( | |
199 BrowserThread::IO, FROM_HERE, | |
200 base::Bind(&WorkerObserver::EnumerateOnIOThread, | |
201 this)); | |
202 } | |
203 | |
204 private: | 107 private: |
205 friend class base::RefCountedThreadSafe<WorkerObserver>; | 108 friend class base::RefCountedThreadSafe<WorkerObserver>; |
206 virtual ~WorkerObserver() {} | 109 virtual ~WorkerObserver() {} |
207 | 110 |
208 // content::WorkerServiceObserver overrides: | 111 // content::WorkerServiceObserver overrides: |
209 virtual void WorkerCreated( | 112 virtual void WorkerCreated( |
210 const GURL& url, | 113 const GURL& url, |
211 const base::string16& name, | 114 const base::string16& name, |
212 int process_id, | 115 int process_id, |
213 int route_id) OVERRIDE { | 116 int route_id) OVERRIDE { |
214 EnumerateOnIOThread(); | 117 NotifyOnIOThread(); |
215 } | 118 } |
216 | 119 |
217 virtual void WorkerDestroyed(int process_id, int route_id) OVERRIDE { | 120 virtual void WorkerDestroyed(int process_id, int route_id) OVERRIDE { |
218 EnumerateOnIOThread(); | 121 NotifyOnIOThread(); |
219 } | 122 } |
220 | 123 |
221 void StartOnIOThread() { | 124 void StartOnIOThread() { |
222 content::WorkerService::GetInstance()->AddObserver(this); | 125 content::WorkerService::GetInstance()->AddObserver(this); |
223 EnumerateOnIOThread(); | |
224 } | 126 } |
225 | 127 |
226 void StopOnIOThread() { | 128 void StopOnIOThread() { |
227 content::WorkerService::GetInstance()->RemoveObserver(this); | 129 content::WorkerService::GetInstance()->RemoveObserver(this); |
228 } | 130 } |
229 | 131 |
230 void EnumerateOnIOThread() { | 132 void NotifyOnIOThread() { |
231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
232 DevToolsTargetImpl::EnumerateWorkerTargets( | 134 BrowserThread::PostTask( |
233 base::Bind(&WorkerObserver::RespondOnUIThread, this)); | 135 BrowserThread::UI, FROM_HERE, |
| 136 base::Bind(&WorkerObserver::NotifyOnUIThread, this)); |
234 } | 137 } |
235 | 138 |
236 void RespondOnUIThread(const DevToolsTargetImpl::List& targets) { | 139 void NotifyOnUIThread() { |
237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
238 if (callback_.is_null()) | 141 if (callback_.is_null()) |
239 return; | 142 return; |
240 callback_.Run(targets); | 143 callback_.Run(); |
241 } | 144 } |
242 | 145 |
243 DevToolsTargetImpl::Callback callback_; | 146 // Accessed on UI thread. |
| 147 base::Closure callback_; |
244 }; | 148 }; |
245 | 149 |
246 // WorkerTargetsUIHandler ----------------------------------------------------- | 150 // LocalTargetsUIHandler --------------------------------------------- |
247 | 151 |
248 class WorkerTargetsUIHandler | 152 class LocalTargetsUIHandler |
249 : public DevToolsTargetsUIHandler { | 153 : public DevToolsTargetsUIHandler, |
| 154 public content::NotificationObserver { |
250 public: | 155 public: |
251 explicit WorkerTargetsUIHandler(const Callback& callback); | 156 explicit LocalTargetsUIHandler(const Callback& callback); |
252 virtual ~WorkerTargetsUIHandler(); | 157 virtual ~LocalTargetsUIHandler(); |
253 | 158 |
254 private: | 159 private: |
255 void UpdateTargets(const DevToolsTargetImpl::List& targets); | 160 // content::NotificationObserver overrides. |
| 161 virtual void Observe(int type, |
| 162 const content::NotificationSource& source, |
| 163 const content::NotificationDetails& details) OVERRIDE; |
256 | 164 |
| 165 void ScheduleUpdate(); |
| 166 void UpdateTargets(); |
| 167 void SendTargets(const DevToolsTargetImpl::List& targets); |
| 168 |
| 169 content::NotificationRegistrar notification_registrar_; |
| 170 scoped_ptr<CancelableTimer> timer_; |
257 scoped_refptr<WorkerObserver> observer_; | 171 scoped_refptr<WorkerObserver> observer_; |
| 172 base::WeakPtrFactory<LocalTargetsUIHandler> weak_factory_; |
258 }; | 173 }; |
259 | 174 |
260 WorkerTargetsUIHandler::WorkerTargetsUIHandler(const Callback& callback) | 175 LocalTargetsUIHandler::LocalTargetsUIHandler( |
261 : DevToolsTargetsUIHandler(kTargetSourceWorker, callback), | 176 const Callback& callback) |
262 observer_(new WorkerObserver()) { | 177 : DevToolsTargetsUIHandler(kTargetSourceLocal, callback), |
263 observer_->Start(base::Bind(&WorkerTargetsUIHandler::UpdateTargets, | 178 observer_(new WorkerObserver()), |
| 179 weak_factory_(this) { |
| 180 notification_registrar_.Add(this, |
| 181 content::NOTIFICATION_WEB_CONTENTS_CONNECTED, |
| 182 content::NotificationService::AllSources()); |
| 183 notification_registrar_.Add(this, |
| 184 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, |
| 185 content::NotificationService::AllSources()); |
| 186 notification_registrar_.Add(this, |
| 187 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 188 content::NotificationService::AllSources()); |
| 189 observer_->Start(base::Bind(&LocalTargetsUIHandler::ScheduleUpdate, |
264 base::Unretained(this))); | 190 base::Unretained(this))); |
| 191 UpdateTargets(); |
265 } | 192 } |
266 | 193 |
267 WorkerTargetsUIHandler::~WorkerTargetsUIHandler() { | 194 LocalTargetsUIHandler::~LocalTargetsUIHandler() { |
| 195 notification_registrar_.RemoveAll(); |
268 observer_->Stop(); | 196 observer_->Stop(); |
269 } | 197 } |
270 | 198 |
271 void WorkerTargetsUIHandler::UpdateTargets( | 199 void LocalTargetsUIHandler::Observe( |
| 200 int type, |
| 201 const content::NotificationSource& source, |
| 202 const content::NotificationDetails& details) { |
| 203 ScheduleUpdate(); |
| 204 } |
| 205 |
| 206 void LocalTargetsUIHandler::ScheduleUpdate() { |
| 207 const int kUpdateDelay = 100; |
| 208 timer_.reset( |
| 209 new CancelableTimer( |
| 210 base::Bind(&LocalTargetsUIHandler::UpdateTargets, |
| 211 base::Unretained(this)), |
| 212 base::TimeDelta::FromMilliseconds(kUpdateDelay))); |
| 213 } |
| 214 |
| 215 void LocalTargetsUIHandler::UpdateTargets() { |
| 216 DevToolsTargetImpl::EnumerateAllTargets(base::Bind( |
| 217 &LocalTargetsUIHandler::SendTargets, |
| 218 weak_factory_.GetWeakPtr())); |
| 219 } |
| 220 |
| 221 void LocalTargetsUIHandler::SendTargets( |
272 const DevToolsTargetImpl::List& targets) { | 222 const DevToolsTargetImpl::List& targets) { |
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
274 base::ListValue list_value; | 223 base::ListValue list_value; |
| 224 std::map<std::string, base::DictionaryValue*> id_to_descriptor; |
| 225 |
275 STLDeleteValues(&targets_); | 226 STLDeleteValues(&targets_); |
276 for (DevToolsTargetImpl::List::const_iterator it = targets.begin(); | 227 for (DevToolsTargetImpl::List::const_iterator it = targets.begin(); |
277 it != targets.end(); ++it) { | 228 it != targets.end(); ++it) { |
278 DevToolsTargetImpl* target = *it; | 229 DevToolsTargetImpl* target = *it; |
279 list_value.Append(Serialize(*target)); | 230 if (target->GetType() == DevToolsTargetImpl::kTargetTypeServiceWorker) |
| 231 continue; |
280 targets_[target->GetId()] = target; | 232 targets_[target->GetId()] = target; |
| 233 id_to_descriptor[target->GetId()] = Serialize(*target); |
281 } | 234 } |
| 235 |
| 236 for (TargetMap::iterator it(targets_.begin()); it != targets_.end(); ++it) { |
| 237 DevToolsTargetImpl* target = it->second; |
| 238 if (target->GetType() == DevToolsTargetImpl::kTargetTypeServiceWorker) |
| 239 continue; |
| 240 base::DictionaryValue* descriptor = id_to_descriptor[target->GetId()]; |
| 241 |
| 242 std::string parent_id = target->GetParentId(); |
| 243 if (parent_id.empty() || id_to_descriptor.count(parent_id) == 0) { |
| 244 list_value.Append(descriptor); |
| 245 } else { |
| 246 base::DictionaryValue* parent = id_to_descriptor[parent_id]; |
| 247 base::ListValue* guests = NULL; |
| 248 if (!parent->GetList(kGuestList, &guests)) { |
| 249 guests = new base::ListValue(); |
| 250 parent->Set(kGuestList, guests); |
| 251 } |
| 252 guests->Append(descriptor); |
| 253 } |
| 254 } |
| 255 |
282 SendSerializedTargets(list_value); | 256 SendSerializedTargets(list_value); |
283 } | 257 } |
284 | 258 |
285 // AdbTargetsUIHandler -------------------------------------------------------- | 259 // AdbTargetsUIHandler -------------------------------------------------------- |
286 | 260 |
287 class AdbTargetsUIHandler | 261 class AdbTargetsUIHandler |
288 : public DevToolsTargetsUIHandler, | 262 : public DevToolsTargetsUIHandler, |
289 public DevToolsAndroidBridge::DeviceListListener { | 263 public DevToolsAndroidBridge::DeviceListListener { |
290 public: | 264 public: |
291 AdbTargetsUIHandler(const Callback& callback, Profile* profile); | 265 AdbTargetsUIHandler(const Callback& callback, Profile* profile); |
(...skipping 13 matching lines...) Expand all Loading... |
305 | 279 |
306 Profile* profile_; | 280 Profile* profile_; |
307 | 281 |
308 typedef std::map<std::string, | 282 typedef std::map<std::string, |
309 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> > RemoteBrowsers; | 283 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> > RemoteBrowsers; |
310 RemoteBrowsers remote_browsers_; | 284 RemoteBrowsers remote_browsers_; |
311 }; | 285 }; |
312 | 286 |
313 AdbTargetsUIHandler::AdbTargetsUIHandler(const Callback& callback, | 287 AdbTargetsUIHandler::AdbTargetsUIHandler(const Callback& callback, |
314 Profile* profile) | 288 Profile* profile) |
315 : DevToolsTargetsUIHandler(kTargetSourceAdb, callback), | 289 : DevToolsTargetsUIHandler(kTargetSourceRemote, callback), |
316 profile_(profile) { | 290 profile_(profile) { |
317 DevToolsAndroidBridge* android_bridge = | 291 DevToolsAndroidBridge* android_bridge = |
318 DevToolsAndroidBridge::Factory::GetForProfile(profile_); | 292 DevToolsAndroidBridge::Factory::GetForProfile(profile_); |
319 if (android_bridge) | 293 if (android_bridge) |
320 android_bridge->AddDeviceListListener(this); | 294 android_bridge->AddDeviceListListener(this); |
321 } | 295 } |
322 | 296 |
323 AdbTargetsUIHandler::~AdbTargetsUIHandler() { | 297 AdbTargetsUIHandler::~AdbTargetsUIHandler() { |
324 DevToolsAndroidBridge* android_bridge = | 298 DevToolsAndroidBridge* android_bridge = |
325 DevToolsAndroidBridge::Factory::GetForProfile(profile_); | 299 DevToolsAndroidBridge::Factory::GetForProfile(profile_); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 : source_id_(source_id), | 416 : source_id_(source_id), |
443 callback_(callback) { | 417 callback_(callback) { |
444 } | 418 } |
445 | 419 |
446 DevToolsTargetsUIHandler::~DevToolsTargetsUIHandler() { | 420 DevToolsTargetsUIHandler::~DevToolsTargetsUIHandler() { |
447 STLDeleteValues(&targets_); | 421 STLDeleteValues(&targets_); |
448 } | 422 } |
449 | 423 |
450 // static | 424 // static |
451 scoped_ptr<DevToolsTargetsUIHandler> | 425 scoped_ptr<DevToolsTargetsUIHandler> |
452 DevToolsTargetsUIHandler::CreateForRenderers( | 426 DevToolsTargetsUIHandler::CreateForLocal( |
453 const DevToolsTargetsUIHandler::Callback& callback) { | 427 const DevToolsTargetsUIHandler::Callback& callback) { |
454 return scoped_ptr<DevToolsTargetsUIHandler>( | 428 return scoped_ptr<DevToolsTargetsUIHandler>( |
455 new RenderViewHostTargetsUIHandler(callback)); | 429 new LocalTargetsUIHandler(callback)); |
456 } | 430 } |
457 | 431 |
458 // static | 432 // static |
459 scoped_ptr<DevToolsTargetsUIHandler> | |
460 DevToolsTargetsUIHandler::CreateForWorkers( | |
461 const DevToolsTargetsUIHandler::Callback& callback) { | |
462 return scoped_ptr<DevToolsTargetsUIHandler>( | |
463 new WorkerTargetsUIHandler(callback)); | |
464 } | |
465 | |
466 // static | |
467 scoped_ptr<DevToolsTargetsUIHandler> | 433 scoped_ptr<DevToolsTargetsUIHandler> |
468 DevToolsTargetsUIHandler::CreateForAdb( | 434 DevToolsTargetsUIHandler::CreateForAdb( |
469 const DevToolsTargetsUIHandler::Callback& callback, Profile* profile) { | 435 const DevToolsTargetsUIHandler::Callback& callback, Profile* profile) { |
470 return scoped_ptr<DevToolsTargetsUIHandler>( | 436 return scoped_ptr<DevToolsTargetsUIHandler>( |
471 new AdbTargetsUIHandler(callback, profile)); | 437 new AdbTargetsUIHandler(callback, profile)); |
472 } | 438 } |
473 | 439 |
474 DevToolsTargetImpl* DevToolsTargetsUIHandler::GetTarget( | 440 DevToolsTargetImpl* DevToolsTargetsUIHandler::GetTarget( |
475 const std::string& target_id) { | 441 const std::string& target_id) { |
476 TargetMap::iterator it = targets_.find(target_id); | 442 TargetMap::iterator it = targets_.find(target_id); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 base::StringPrintf("%d", it->first), it->second); | 507 base::StringPrintf("%d", it->first), it->second); |
542 } | 508 } |
543 | 509 |
544 std::string device_id = base::StringPrintf( | 510 std::string device_id = base::StringPrintf( |
545 kAdbDeviceIdFormat, | 511 kAdbDeviceIdFormat, |
546 sit->first.c_str()); | 512 sit->first.c_str()); |
547 result.Set(device_id, device_status_dict); | 513 result.Set(device_id, device_status_dict); |
548 } | 514 } |
549 callback_.Run(result); | 515 callback_.Run(result); |
550 } | 516 } |
OLD | NEW |