OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/plugin/host_script_object.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/json/json_reader.h" | |
9 #include "base/json/json_writer.h" | |
10 #include "base/strings/string_util.h" | |
11 #include "base/strings/stringprintf.h" | |
12 #include "base/strings/sys_string_conversions.h" | |
13 #include "base/strings/utf_string_conversions.h" | |
14 #include "remoting/base/auth_token_util.h" | |
15 #include "remoting/base/auto_thread.h" | |
16 #include "remoting/base/logging.h" | |
17 #include "remoting/base/resources.h" | |
18 #include "remoting/base/rsa_key_pair.h" | |
19 #include "remoting/host/chromoting_host_context.h" | |
20 #include "remoting/host/host_config.h" | |
21 #include "remoting/host/pairing_registry_delegate.h" | |
22 #include "remoting/host/pin_hash.h" | |
23 #include "remoting/host/plugin/host_log_handler.h" | |
24 #include "remoting/host/policy_hack/policy_watcher.h" | |
25 #include "remoting/host/service_urls.h" | |
26 #include "third_party/npapi/bindings/npapi.h" | |
27 #include "third_party/npapi/bindings/npfunctions.h" | |
28 #include "third_party/npapi/bindings/npruntime.h" | |
29 | |
30 namespace remoting { | |
31 | |
32 namespace { | |
33 | |
34 const char* kAttrNameAccessCode = "accessCode"; | |
35 const char* kAttrNameAccessCodeLifetime = "accessCodeLifetime"; | |
36 const char* kAttrNameClient = "client"; | |
37 const char* kAttrNameDaemonState = "daemonState"; | |
38 const char* kAttrNameState = "state"; | |
39 const char* kAttrNameLogDebugInfo = "logDebugInfo"; | |
40 const char* kAttrNameOnNatTraversalPolicyChanged = | |
41 "onNatTraversalPolicyChanged"; | |
42 const char* kAttrNameOnStateChanged = "onStateChanged"; | |
43 const char* kAttrNameXmppServerAddress = "xmppServerAddress"; | |
44 const char* kAttrNameXmppServerUseTls = "xmppServerUseTls"; | |
45 const char* kAttrNameDirectoryBotJid = "directoryBotJid"; | |
46 const char* kAttrNameSupportedFeatures = "supportedFeatures"; | |
47 const char* kFuncNameConnect = "connect"; | |
48 const char* kFuncNameDisconnect = "disconnect"; | |
49 const char* kFuncNameLocalize = "localize"; | |
50 const char* kFuncNameClearPairedClients = "clearPairedClients"; | |
51 const char* kFuncNameDeletePairedClient = "deletePairedClient"; | |
52 const char* kFuncNameGetHostName = "getHostName"; | |
53 const char* kFuncNameGetPinHash = "getPinHash"; | |
54 const char* kFuncNameGenerateKeyPair = "generateKeyPair"; | |
55 const char* kFuncNameUpdateDaemonConfig = "updateDaemonConfig"; | |
56 const char* kFuncNameGetDaemonConfig = "getDaemonConfig"; | |
57 const char* kFuncNameGetDaemonVersion = "getDaemonVersion"; | |
58 const char* kFuncNameGetPairedClients = "getPairedClients"; | |
59 const char* kFuncNameGetUsageStatsConsent = "getUsageStatsConsent"; | |
60 const char* kFuncNameInstallHost = "installHost"; | |
61 const char* kFuncNameStartDaemon = "startDaemon"; | |
62 const char* kFuncNameStopDaemon = "stopDaemon"; | |
63 | |
64 // States. | |
65 const char* kAttrNameDisconnected = "DISCONNECTED"; | |
66 const char* kAttrNameStarting = "STARTING"; | |
67 const char* kAttrNameRequestedAccessCode = "REQUESTED_ACCESS_CODE"; | |
68 const char* kAttrNameReceivedAccessCode = "RECEIVED_ACCESS_CODE"; | |
69 const char* kAttrNameConnected = "CONNECTED"; | |
70 const char* kAttrNameDisconnecting = "DISCONNECTING"; | |
71 const char* kAttrNameError = "ERROR"; | |
72 const char* kAttrNameInvalidDomainError = "INVALID_DOMAIN_ERROR"; | |
73 | |
74 // Space separated list of features supported in addition to the base protocol. | |
75 const char* kSupportedFeatures = "pairingRegistry"; | |
76 | |
77 } // namespace | |
78 | |
79 HostNPScriptObject::HostNPScriptObject( | |
80 NPP plugin, | |
81 NPObject* parent, | |
82 scoped_refptr<AutoThreadTaskRunner> plugin_task_runner) | |
83 : plugin_(plugin), | |
84 parent_(parent), | |
85 plugin_task_runner_(plugin_task_runner), | |
86 am_currently_logging_(false), | |
87 state_(kDisconnected), | |
88 weak_factory_(this) { | |
89 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
90 | |
91 weak_ptr_ = weak_factory_.GetWeakPtr(); | |
92 | |
93 // Set the thread task runner for the plugin thread so that timers and other | |
94 // code using |base::ThreadTaskRunnerHandle| could be used on the plugin | |
95 // thread. | |
96 // | |
97 // If component build is used, Chrome and the plugin may end up sharing base | |
98 // binary. This means that the instance of |base::ThreadTaskRunnerHandle| | |
99 // created by Chrome for the current thread is shared as well. This routinely | |
100 // happens in the development setting so the below check for | |
101 // |!base::ThreadTaskRunnerHandle::IsSet()| is a hack/workaround allowing this | |
102 // configuration to work. It lets the plugin to access Chrome's message loop | |
103 // directly via |base::ThreadTaskRunnerHandle|. This is safe as long as both | |
104 // Chrome and the plugin are built from the same version of the sources. | |
105 if (!base::ThreadTaskRunnerHandle::IsSet()) { | |
106 plugin_task_runner_handle_.reset( | |
107 new base::ThreadTaskRunnerHandle(plugin_task_runner_)); | |
108 } | |
109 | |
110 daemon_controller_ = DaemonController::Create(); | |
111 | |
112 ServiceUrls* service_urls = ServiceUrls::GetInstance(); | |
113 bool xmpp_server_valid = net::ParseHostAndPort( | |
114 service_urls->xmpp_server_address(), | |
115 &xmpp_server_config_.host, &xmpp_server_config_.port); | |
116 // For the plugin, this is always the default address, which must be valid. | |
117 DCHECK(xmpp_server_valid); | |
118 xmpp_server_config_.use_tls = service_urls->xmpp_server_use_tls(); | |
119 directory_bot_jid_ = service_urls->directory_bot_jid(); | |
120 | |
121 // Create worker thread for encryption key generation and loading the paired | |
122 // clients. | |
123 worker_thread_ = AutoThread::Create("ChromotingWorkerThread", | |
124 plugin_task_runner_); | |
125 | |
126 pairing_registry_ = CreatePairingRegistry(worker_thread_); | |
127 } | |
128 | |
129 HostNPScriptObject::~HostNPScriptObject() { | |
130 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
131 | |
132 HostLogHandler::UnregisterLoggingScriptObject(this); | |
133 | |
134 // Stop the It2Me host if the caller forgot to. | |
135 if (it2me_host_.get()) { | |
136 it2me_host_->Disconnect(); | |
137 it2me_host_ = NULL; | |
138 } | |
139 } | |
140 | |
141 bool HostNPScriptObject::HasMethod(const std::string& method_name) { | |
142 VLOG(2) << "HasMethod " << method_name; | |
143 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
144 return (method_name == kFuncNameConnect || | |
145 method_name == kFuncNameDisconnect || | |
146 method_name == kFuncNameLocalize || | |
147 method_name == kFuncNameClearPairedClients || | |
148 method_name == kFuncNameDeletePairedClient || | |
149 method_name == kFuncNameGetHostName || | |
150 method_name == kFuncNameGetPinHash || | |
151 method_name == kFuncNameGenerateKeyPair || | |
152 method_name == kFuncNameUpdateDaemonConfig || | |
153 method_name == kFuncNameGetDaemonConfig || | |
154 method_name == kFuncNameGetDaemonVersion || | |
155 method_name == kFuncNameGetPairedClients || | |
156 method_name == kFuncNameGetUsageStatsConsent || | |
157 method_name == kFuncNameInstallHost || | |
158 method_name == kFuncNameStartDaemon || | |
159 method_name == kFuncNameStopDaemon); | |
160 } | |
161 | |
162 bool HostNPScriptObject::InvokeDefault(const NPVariant* args, | |
163 uint32_t arg_count, | |
164 NPVariant* result) { | |
165 VLOG(2) << "InvokeDefault"; | |
166 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
167 SetException("exception during default invocation"); | |
168 return false; | |
169 } | |
170 | |
171 bool HostNPScriptObject::Invoke(const std::string& method_name, | |
172 const NPVariant* args, | |
173 uint32_t arg_count, | |
174 NPVariant* result) { | |
175 VLOG(2) << "Invoke " << method_name; | |
176 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
177 if (method_name == kFuncNameConnect) { | |
178 return Connect(args, arg_count, result); | |
179 } else if (method_name == kFuncNameDisconnect) { | |
180 return Disconnect(args, arg_count, result); | |
181 } else if (method_name == kFuncNameLocalize) { | |
182 return Localize(args, arg_count, result); | |
183 } else if (method_name == kFuncNameClearPairedClients) { | |
184 return ClearPairedClients(args, arg_count, result); | |
185 } else if (method_name == kFuncNameDeletePairedClient) { | |
186 return DeletePairedClient(args, arg_count, result); | |
187 } else if (method_name == kFuncNameGetHostName) { | |
188 return GetHostName(args, arg_count, result); | |
189 } else if (method_name == kFuncNameGetPinHash) { | |
190 return GetPinHash(args, arg_count, result); | |
191 } else if (method_name == kFuncNameGenerateKeyPair) { | |
192 return GenerateKeyPair(args, arg_count, result); | |
193 } else if (method_name == kFuncNameUpdateDaemonConfig) { | |
194 return UpdateDaemonConfig(args, arg_count, result); | |
195 } else if (method_name == kFuncNameGetDaemonConfig) { | |
196 return GetDaemonConfig(args, arg_count, result); | |
197 } else if (method_name == kFuncNameGetDaemonVersion) { | |
198 return GetDaemonVersion(args, arg_count, result); | |
199 } else if (method_name == kFuncNameGetPairedClients) { | |
200 return GetPairedClients(args, arg_count, result); | |
201 } else if (method_name == kFuncNameGetUsageStatsConsent) { | |
202 return GetUsageStatsConsent(args, arg_count, result); | |
203 } else if (method_name == kFuncNameInstallHost) { | |
204 return InstallHost(args, arg_count, result); | |
205 } else if (method_name == kFuncNameStartDaemon) { | |
206 return StartDaemon(args, arg_count, result); | |
207 } else if (method_name == kFuncNameStopDaemon) { | |
208 return StopDaemon(args, arg_count, result); | |
209 } else { | |
210 SetException("Invoke: unknown method " + method_name); | |
211 return false; | |
212 } | |
213 } | |
214 | |
215 bool HostNPScriptObject::HasProperty(const std::string& property_name) { | |
216 VLOG(2) << "HasProperty " << property_name; | |
217 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
218 return (property_name == kAttrNameAccessCode || | |
219 property_name == kAttrNameAccessCodeLifetime || | |
220 property_name == kAttrNameClient || | |
221 property_name == kAttrNameDaemonState || | |
222 property_name == kAttrNameState || | |
223 property_name == kAttrNameLogDebugInfo || | |
224 property_name == kAttrNameOnNatTraversalPolicyChanged || | |
225 property_name == kAttrNameOnStateChanged || | |
226 property_name == kAttrNameDisconnected || | |
227 property_name == kAttrNameStarting || | |
228 property_name == kAttrNameRequestedAccessCode || | |
229 property_name == kAttrNameReceivedAccessCode || | |
230 property_name == kAttrNameConnected || | |
231 property_name == kAttrNameDisconnecting || | |
232 property_name == kAttrNameError || | |
233 property_name == kAttrNameXmppServerAddress || | |
234 property_name == kAttrNameXmppServerUseTls || | |
235 property_name == kAttrNameDirectoryBotJid || | |
236 property_name == kAttrNameSupportedFeatures); | |
237 } | |
238 | |
239 bool HostNPScriptObject::GetProperty(const std::string& property_name, | |
240 NPVariant* result) { | |
241 VLOG(2) << "GetProperty " << property_name; | |
242 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
243 if (!result) { | |
244 SetException("GetProperty: NULL result"); | |
245 return false; | |
246 } | |
247 | |
248 if (property_name == kAttrNameOnNatTraversalPolicyChanged) { | |
249 OBJECT_TO_NPVARIANT(on_nat_traversal_policy_changed_func_.get(), *result); | |
250 return true; | |
251 } else if (property_name == kAttrNameOnStateChanged) { | |
252 OBJECT_TO_NPVARIANT(on_state_changed_func_.get(), *result); | |
253 return true; | |
254 } else if (property_name == kAttrNameLogDebugInfo) { | |
255 OBJECT_TO_NPVARIANT(log_debug_info_func_.get(), *result); | |
256 return true; | |
257 } else if (property_name == kAttrNameState) { | |
258 INT32_TO_NPVARIANT(state_, *result); | |
259 return true; | |
260 } else if (property_name == kAttrNameAccessCode) { | |
261 *result = NPVariantFromString(access_code_); | |
262 return true; | |
263 } else if (property_name == kAttrNameAccessCodeLifetime) { | |
264 INT32_TO_NPVARIANT(access_code_lifetime_.InSeconds(), *result); | |
265 return true; | |
266 } else if (property_name == kAttrNameClient) { | |
267 *result = NPVariantFromString(client_username_); | |
268 return true; | |
269 } else if (property_name == kAttrNameDaemonState) { | |
270 INT32_TO_NPVARIANT(daemon_controller_->GetState(), *result); | |
271 return true; | |
272 } else if (property_name == kAttrNameDisconnected) { | |
273 INT32_TO_NPVARIANT(kDisconnected, *result); | |
274 return true; | |
275 } else if (property_name == kAttrNameStarting) { | |
276 INT32_TO_NPVARIANT(kStarting, *result); | |
277 return true; | |
278 } else if (property_name == kAttrNameRequestedAccessCode) { | |
279 INT32_TO_NPVARIANT(kRequestedAccessCode, *result); | |
280 return true; | |
281 } else if (property_name == kAttrNameReceivedAccessCode) { | |
282 INT32_TO_NPVARIANT(kReceivedAccessCode, *result); | |
283 return true; | |
284 } else if (property_name == kAttrNameConnected) { | |
285 INT32_TO_NPVARIANT(kConnected, *result); | |
286 return true; | |
287 } else if (property_name == kAttrNameDisconnecting) { | |
288 INT32_TO_NPVARIANT(kDisconnecting, *result); | |
289 return true; | |
290 } else if (property_name == kAttrNameError) { | |
291 INT32_TO_NPVARIANT(kError, *result); | |
292 return true; | |
293 } else if (property_name == kAttrNameInvalidDomainError) { | |
294 INT32_TO_NPVARIANT(kInvalidDomainError, *result); | |
295 return true; | |
296 } else if (property_name == kAttrNameXmppServerAddress) { | |
297 *result = NPVariantFromString(base::StringPrintf( | |
298 "%s:%u", xmpp_server_config_.host.c_str(), xmpp_server_config_.port)); | |
299 return true; | |
300 } else if (property_name == kAttrNameXmppServerUseTls) { | |
301 BOOLEAN_TO_NPVARIANT(xmpp_server_config_.use_tls, *result); | |
302 return true; | |
303 } else if (property_name == kAttrNameDirectoryBotJid) { | |
304 *result = NPVariantFromString(directory_bot_jid_); | |
305 return true; | |
306 } else if (property_name == kAttrNameSupportedFeatures) { | |
307 *result = NPVariantFromString(kSupportedFeatures); | |
308 return true; | |
309 } else { | |
310 SetException("GetProperty: unsupported property " + property_name); | |
311 return false; | |
312 } | |
313 } | |
314 | |
315 bool HostNPScriptObject::SetProperty(const std::string& property_name, | |
316 const NPVariant* value) { | |
317 VLOG(2) << "SetProperty " << property_name; | |
318 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
319 | |
320 if (property_name == kAttrNameOnNatTraversalPolicyChanged) { | |
321 if (NPVARIANT_IS_OBJECT(*value)) { | |
322 on_nat_traversal_policy_changed_func_ = NPVARIANT_TO_OBJECT(*value); | |
323 if (it2me_host_.get()) { | |
324 // Ask the It2Me host to notify the web-app of the policy. | |
325 it2me_host_->RequestNatPolicy(); | |
326 } | |
327 return true; | |
328 } else { | |
329 SetException("SetProperty: unexpected type for property " + | |
330 property_name); | |
331 } | |
332 return false; | |
333 } | |
334 | |
335 if (property_name == kAttrNameOnStateChanged) { | |
336 if (NPVARIANT_IS_OBJECT(*value)) { | |
337 on_state_changed_func_ = NPVARIANT_TO_OBJECT(*value); | |
338 return true; | |
339 } else { | |
340 SetException("SetProperty: unexpected type for property " + | |
341 property_name); | |
342 } | |
343 return false; | |
344 } | |
345 | |
346 if (property_name == kAttrNameLogDebugInfo) { | |
347 if (NPVARIANT_IS_OBJECT(*value)) { | |
348 log_debug_info_func_ = NPVARIANT_TO_OBJECT(*value); | |
349 HostLogHandler::RegisterLoggingScriptObject(this); | |
350 return true; | |
351 } else { | |
352 SetException("SetProperty: unexpected type for property " + | |
353 property_name); | |
354 } | |
355 return false; | |
356 } | |
357 | |
358 #if !defined(NDEBUG) | |
359 if (property_name == kAttrNameXmppServerAddress) { | |
360 if (NPVARIANT_IS_STRING(*value)) { | |
361 std::string address = StringFromNPVariant(*value); | |
362 bool xmpp_server_valid = net::ParseHostAndPort( | |
363 address, &xmpp_server_config_.host, &xmpp_server_config_.port); | |
364 if (xmpp_server_valid) { | |
365 return true; | |
366 } else { | |
367 SetException("SetProperty: invalid value for property " + | |
368 property_name); | |
369 } | |
370 } else { | |
371 SetException("SetProperty: unexpected type for property " + | |
372 property_name); | |
373 } | |
374 return false; | |
375 } | |
376 | |
377 if (property_name == kAttrNameXmppServerUseTls) { | |
378 if (NPVARIANT_IS_BOOLEAN(*value)) { | |
379 xmpp_server_config_.use_tls = NPVARIANT_TO_BOOLEAN(*value); | |
380 return true; | |
381 } else { | |
382 SetException("SetProperty: unexpected type for property " + | |
383 property_name); | |
384 } | |
385 return false; | |
386 } | |
387 | |
388 if (property_name == kAttrNameDirectoryBotJid) { | |
389 if (NPVARIANT_IS_STRING(*value)) { | |
390 directory_bot_jid_ = StringFromNPVariant(*value); | |
391 return true; | |
392 } else { | |
393 SetException("SetProperty: unexpected type for property " + | |
394 property_name); | |
395 } | |
396 return false; | |
397 } | |
398 #endif // !defined(NDEBUG) | |
399 | |
400 return false; | |
401 } | |
402 | |
403 bool HostNPScriptObject::RemoveProperty(const std::string& property_name) { | |
404 VLOG(2) << "RemoveProperty " << property_name; | |
405 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
406 return false; | |
407 } | |
408 | |
409 bool HostNPScriptObject::Enumerate(std::vector<std::string>* values) { | |
410 VLOG(2) << "Enumerate"; | |
411 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
412 const char* entries[] = { | |
413 kAttrNameAccessCode, | |
414 kAttrNameState, | |
415 kAttrNameLogDebugInfo, | |
416 kAttrNameOnStateChanged, | |
417 kAttrNameDisconnected, | |
418 kAttrNameStarting, | |
419 kAttrNameRequestedAccessCode, | |
420 kAttrNameReceivedAccessCode, | |
421 kAttrNameConnected, | |
422 kAttrNameDisconnecting, | |
423 kAttrNameError, | |
424 kAttrNameXmppServerAddress, | |
425 kAttrNameXmppServerUseTls, | |
426 kAttrNameDirectoryBotJid, | |
427 kFuncNameConnect, | |
428 kFuncNameDisconnect, | |
429 kFuncNameLocalize, | |
430 kFuncNameClearPairedClients, | |
431 kFuncNameDeletePairedClient, | |
432 kFuncNameGetHostName, | |
433 kFuncNameGetPinHash, | |
434 kFuncNameGenerateKeyPair, | |
435 kFuncNameUpdateDaemonConfig, | |
436 kFuncNameGetDaemonConfig, | |
437 kFuncNameGetDaemonVersion, | |
438 kFuncNameGetPairedClients, | |
439 kFuncNameGetUsageStatsConsent, | |
440 kFuncNameInstallHost, | |
441 kFuncNameStartDaemon, | |
442 kFuncNameStopDaemon | |
443 }; | |
444 for (size_t i = 0; i < arraysize(entries); ++i) { | |
445 values->push_back(entries[i]); | |
446 } | |
447 return true; | |
448 } | |
449 | |
450 // string username, string auth_token | |
451 bool HostNPScriptObject::Connect(const NPVariant* args, | |
452 uint32_t arg_count, | |
453 NPVariant* result) { | |
454 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
455 | |
456 HOST_LOG << "Connecting..."; | |
457 | |
458 if (arg_count != 2) { | |
459 SetException("connect: bad number of arguments"); | |
460 return false; | |
461 } | |
462 | |
463 if (it2me_host_.get()) { | |
464 SetException("connect: can be called only when disconnected"); | |
465 return false; | |
466 } | |
467 | |
468 XmppSignalStrategy::XmppServerConfig xmpp_config = xmpp_server_config_; | |
469 | |
470 xmpp_config.username = StringFromNPVariant(args[0]); | |
471 if (xmpp_config.username.empty()) { | |
472 SetException("connect: bad username argument"); | |
473 return false; | |
474 } | |
475 | |
476 std::string auth_service_with_token = StringFromNPVariant(args[1]); | |
477 ParseAuthTokenWithService(auth_service_with_token, &xmpp_config.auth_token, | |
478 &xmpp_config.auth_service); | |
479 if (xmpp_config.auth_token.empty()) { | |
480 SetException("connect: auth_service_with_token argument has empty token"); | |
481 return false; | |
482 } | |
483 | |
484 // Create a host context to manage the threads for the it2me host. | |
485 // The plugin, rather than the It2MeHost object, owns and maintains the | |
486 // lifetime of the host context. | |
487 host_context_.reset( | |
488 ChromotingHostContext::Create(plugin_task_runner_).release()); | |
489 if (!host_context_) { | |
490 SetException("connect: failed to start threads"); | |
491 return false; | |
492 } | |
493 | |
494 // Create the It2Me host and start connecting. | |
495 scoped_ptr<It2MeHostFactory> factory(new It2MeHostFactory()); | |
496 it2me_host_ = factory->CreateIt2MeHost( | |
497 host_context_.get(), plugin_task_runner_, weak_ptr_, | |
498 xmpp_config, directory_bot_jid_); | |
499 it2me_host_->Connect(); | |
500 | |
501 return true; | |
502 } | |
503 | |
504 bool HostNPScriptObject::Disconnect(const NPVariant* args, | |
505 uint32_t arg_count, | |
506 NPVariant* result) { | |
507 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
508 if (arg_count != 0) { | |
509 SetException("disconnect: bad number of arguments"); | |
510 return false; | |
511 } | |
512 | |
513 if (it2me_host_.get()) { | |
514 it2me_host_->Disconnect(); | |
515 it2me_host_ = NULL; | |
516 } | |
517 | |
518 return true; | |
519 } | |
520 | |
521 bool HostNPScriptObject::Localize(const NPVariant* args, | |
522 uint32_t arg_count, | |
523 NPVariant* result) { | |
524 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
525 if (arg_count != 1) { | |
526 SetException("localize: bad number of arguments"); | |
527 return false; | |
528 } | |
529 | |
530 if (NPVARIANT_IS_OBJECT(args[0])) { | |
531 ScopedRefNPObject localize_func(NPVARIANT_TO_OBJECT(args[0])); | |
532 LocalizeStrings(localize_func.get()); | |
533 return true; | |
534 } else { | |
535 SetException("localize: unexpected type for argument 1"); | |
536 return false; | |
537 } | |
538 } | |
539 | |
540 bool HostNPScriptObject::ClearPairedClients(const NPVariant* args, | |
541 uint32_t arg_count, | |
542 NPVariant* result) { | |
543 if (arg_count != 1) { | |
544 SetException("clearPairedClients: bad number of arguments"); | |
545 return false; | |
546 } | |
547 | |
548 if (!NPVARIANT_IS_OBJECT(args[0])) { | |
549 SetException("clearPairedClients: invalid callback parameter"); | |
550 return false; | |
551 } | |
552 | |
553 scoped_ptr<ScopedRefNPObject> callback_obj( | |
554 new ScopedRefNPObject(ObjectFromNPVariant(args[0]))); | |
555 if (pairing_registry_) { | |
556 pairing_registry_->ClearAllPairings( | |
557 base::Bind(&HostNPScriptObject::InvokeBooleanCallback, weak_ptr_, | |
558 base::Passed(&callback_obj))); | |
559 } else { | |
560 InvokeBooleanCallback(callback_obj.Pass(), false); | |
561 } | |
562 | |
563 return true; | |
564 } | |
565 | |
566 bool HostNPScriptObject::DeletePairedClient(const NPVariant* args, | |
567 uint32_t arg_count, | |
568 NPVariant* result) { | |
569 if (arg_count != 2) { | |
570 SetException("deletePairedClient: bad number of arguments"); | |
571 return false; | |
572 } | |
573 | |
574 if (!NPVARIANT_IS_STRING(args[0])) { | |
575 SetException("deletePairedClient: bad clientId parameter"); | |
576 return false; | |
577 } | |
578 | |
579 if (!NPVARIANT_IS_OBJECT(args[1])) { | |
580 SetException("deletePairedClient: invalid callback parameter"); | |
581 return false; | |
582 } | |
583 | |
584 std::string client_id = StringFromNPVariant(args[0]); | |
585 scoped_ptr<ScopedRefNPObject> callback_obj( | |
586 new ScopedRefNPObject(ObjectFromNPVariant(args[1]))); | |
587 if (pairing_registry_) { | |
588 pairing_registry_->DeletePairing( | |
589 client_id, | |
590 base::Bind(&HostNPScriptObject::InvokeBooleanCallback, | |
591 weak_ptr_, base::Passed(&callback_obj))); | |
592 } else { | |
593 InvokeBooleanCallback(callback_obj.Pass(), false); | |
594 } | |
595 | |
596 return true; | |
597 } | |
598 | |
599 bool HostNPScriptObject::GetHostName(const NPVariant* args, | |
600 uint32_t arg_count, | |
601 NPVariant* result) { | |
602 if (arg_count != 1) { | |
603 SetException("getHostName: bad number of arguments"); | |
604 return false; | |
605 } | |
606 | |
607 ScopedRefNPObject callback_obj(ObjectFromNPVariant(args[0])); | |
608 if (!callback_obj.get()) { | |
609 SetException("getHostName: invalid callback parameter"); | |
610 return false; | |
611 } | |
612 | |
613 NPVariant host_name_val = NPVariantFromString(net::GetHostName()); | |
614 InvokeAndIgnoreResult(callback_obj, &host_name_val, 1); | |
615 g_npnetscape_funcs->releasevariantvalue(&host_name_val); | |
616 | |
617 return true; | |
618 } | |
619 | |
620 bool HostNPScriptObject::GetPinHash(const NPVariant* args, | |
621 uint32_t arg_count, | |
622 NPVariant* result) { | |
623 if (arg_count != 3) { | |
624 SetException("getPinHash: bad number of arguments"); | |
625 return false; | |
626 } | |
627 | |
628 std::string host_id = StringFromNPVariant(args[0]); | |
629 if (host_id.empty()) { | |
630 SetException("getPinHash: bad hostId parameter"); | |
631 return false; | |
632 } | |
633 | |
634 if (!NPVARIANT_IS_STRING(args[1])) { | |
635 SetException("getPinHash: bad pin parameter"); | |
636 return false; | |
637 } | |
638 std::string pin = StringFromNPVariant(args[1]); | |
639 | |
640 ScopedRefNPObject callback_obj(ObjectFromNPVariant(args[2])); | |
641 if (!callback_obj.get()) { | |
642 SetException("getPinHash: invalid callback parameter"); | |
643 return false; | |
644 } | |
645 | |
646 NPVariant pin_hash_val = NPVariantFromString( | |
647 remoting::MakeHostPinHash(host_id, pin)); | |
648 InvokeAndIgnoreResult(callback_obj, &pin_hash_val, 1); | |
649 g_npnetscape_funcs->releasevariantvalue(&pin_hash_val); | |
650 | |
651 return true; | |
652 } | |
653 | |
654 bool HostNPScriptObject::GenerateKeyPair(const NPVariant* args, | |
655 uint32_t arg_count, | |
656 NPVariant* result) { | |
657 if (arg_count != 1) { | |
658 SetException("generateKeyPair: bad number of arguments"); | |
659 return false; | |
660 } | |
661 | |
662 scoped_ptr<ScopedRefNPObject> callback_obj( | |
663 new ScopedRefNPObject(ObjectFromNPVariant(args[0]))); | |
664 if (!callback_obj->get()) { | |
665 SetException("generateKeyPair: invalid callback parameter"); | |
666 return false; | |
667 } | |
668 | |
669 base::Callback<void (const std::string&, | |
670 const std::string&)> wrapped_callback = | |
671 base::Bind(&HostNPScriptObject::InvokeGenerateKeyPairCallback, weak_ptr_, | |
672 base::Passed(&callback_obj)); | |
673 worker_thread_->PostTask( | |
674 FROM_HERE, base::Bind(&HostNPScriptObject::DoGenerateKeyPair, | |
675 plugin_task_runner_, wrapped_callback)); | |
676 return true; | |
677 } | |
678 | |
679 bool HostNPScriptObject::UpdateDaemonConfig(const NPVariant* args, | |
680 uint32_t arg_count, | |
681 NPVariant* result) { | |
682 if (arg_count != 2) { | |
683 SetException("updateDaemonConfig: bad number of arguments"); | |
684 return false; | |
685 } | |
686 | |
687 std::string config_str = StringFromNPVariant(args[0]); | |
688 scoped_ptr<base::Value> config( | |
689 base::JSONReader::Read(config_str, base::JSON_ALLOW_TRAILING_COMMAS)); | |
690 if (config_str.empty() || !config.get() || | |
691 !config->IsType(base::Value::TYPE_DICTIONARY)) { | |
692 SetException("updateDaemonConfig: bad config parameter"); | |
693 return false; | |
694 } | |
695 scoped_ptr<base::DictionaryValue> config_dict( | |
696 reinterpret_cast<base::DictionaryValue*>(config.release())); | |
697 | |
698 scoped_ptr<ScopedRefNPObject> callback_obj( | |
699 new ScopedRefNPObject(ObjectFromNPVariant(args[1]))); | |
700 if (!callback_obj->get()) { | |
701 SetException("updateDaemonConfig: invalid callback parameter"); | |
702 return false; | |
703 } | |
704 | |
705 if (config_dict->HasKey(kHostIdConfigPath) || | |
706 config_dict->HasKey(kXmppLoginConfigPath)) { | |
707 SetException("updateDaemonConfig: trying to update immutable config " | |
708 "parameters"); | |
709 return false; | |
710 } | |
711 | |
712 daemon_controller_->UpdateConfig( | |
713 config_dict.Pass(), | |
714 base::Bind(&HostNPScriptObject::InvokeAsyncResultCallback, weak_ptr_, | |
715 base::Passed(&callback_obj))); | |
716 return true; | |
717 } | |
718 | |
719 bool HostNPScriptObject::GetDaemonConfig(const NPVariant* args, | |
720 uint32_t arg_count, | |
721 NPVariant* result) { | |
722 if (arg_count != 1) { | |
723 SetException("getDaemonConfig: bad number of arguments"); | |
724 return false; | |
725 } | |
726 | |
727 scoped_ptr<ScopedRefNPObject> callback_obj( | |
728 new ScopedRefNPObject(ObjectFromNPVariant(args[0]))); | |
729 if (!callback_obj->get()) { | |
730 SetException("getDaemonConfig: invalid callback parameter"); | |
731 return false; | |
732 } | |
733 | |
734 daemon_controller_->GetConfig( | |
735 base::Bind(&HostNPScriptObject::InvokeGetDaemonConfigCallback, weak_ptr_, | |
736 base::Passed(&callback_obj))); | |
737 return true; | |
738 } | |
739 | |
740 bool HostNPScriptObject::GetDaemonVersion(const NPVariant* args, | |
741 uint32_t arg_count, | |
742 NPVariant* result) { | |
743 if (arg_count != 1) { | |
744 SetException("getDaemonVersion: bad number of arguments"); | |
745 return false; | |
746 } | |
747 | |
748 scoped_ptr<ScopedRefNPObject> callback_obj( | |
749 new ScopedRefNPObject(ObjectFromNPVariant(args[0]))); | |
750 if (!callback_obj->get()) { | |
751 SetException("getDaemonVersion: invalid callback parameter"); | |
752 return false; | |
753 } | |
754 | |
755 daemon_controller_->GetVersion( | |
756 base::Bind(&HostNPScriptObject::InvokeGetDaemonVersionCallback, weak_ptr_, | |
757 base::Passed(&callback_obj))); | |
758 | |
759 return true; | |
760 } | |
761 | |
762 bool HostNPScriptObject::GetPairedClients(const NPVariant* args, | |
763 uint32_t arg_count, | |
764 NPVariant* result) { | |
765 if (arg_count != 1) { | |
766 SetException("getPairedClients: bad number of arguments"); | |
767 return false; | |
768 } | |
769 | |
770 scoped_ptr<ScopedRefNPObject> callback_obj( | |
771 new ScopedRefNPObject(ObjectFromNPVariant(args[0]))); | |
772 if (!callback_obj->get()) { | |
773 SetException("getPairedClients: invalid callback parameter"); | |
774 return false; | |
775 } | |
776 | |
777 if (pairing_registry_) { | |
778 pairing_registry_->GetAllPairings( | |
779 base::Bind(&HostNPScriptObject::InvokeGetPairedClientsCallback, | |
780 weak_ptr_, base::Passed(&callback_obj))); | |
781 } else { | |
782 scoped_ptr<base::ListValue> no_paired_clients(new base::ListValue); | |
783 InvokeGetPairedClientsCallback(callback_obj.Pass(), | |
784 no_paired_clients.Pass()); | |
785 } | |
786 return true; | |
787 } | |
788 | |
789 bool HostNPScriptObject::GetUsageStatsConsent(const NPVariant* args, | |
790 uint32_t arg_count, | |
791 NPVariant* result) { | |
792 if (arg_count != 1) { | |
793 SetException("getUsageStatsConsent: bad number of arguments"); | |
794 return false; | |
795 } | |
796 | |
797 scoped_ptr<ScopedRefNPObject> callback_obj( | |
798 new ScopedRefNPObject(ObjectFromNPVariant(args[0]))); | |
799 if (!callback_obj->get()) { | |
800 SetException("getUsageStatsConsent: invalid callback parameter"); | |
801 return false; | |
802 } | |
803 | |
804 daemon_controller_->GetUsageStatsConsent( | |
805 base::Bind(&HostNPScriptObject::InvokeGetUsageStatsConsentCallback, | |
806 weak_ptr_, base::Passed(&callback_obj))); | |
807 return true; | |
808 } | |
809 | |
810 bool HostNPScriptObject::InstallHost(const NPVariant* args, | |
811 uint32_t arg_count, | |
812 NPVariant* result) { | |
813 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
814 | |
815 if (arg_count != 1) { | |
816 SetException("installHost: bad number of arguments"); | |
817 return false; | |
818 } | |
819 | |
820 scoped_ptr<ScopedRefNPObject> callback_obj( | |
821 new ScopedRefNPObject(ObjectFromNPVariant(args[0]))); | |
822 if (!callback_obj->get()) { | |
823 SetException("installHost: invalid callback parameter"); | |
824 return false; | |
825 } | |
826 | |
827 daemon_controller_->InstallHost( | |
828 base::Bind(&HostNPScriptObject::InvokeAsyncResultCallback, weak_ptr_, | |
829 base::Passed(&callback_obj))); | |
830 return true; | |
831 } | |
832 | |
833 bool HostNPScriptObject::StartDaemon(const NPVariant* args, | |
834 uint32_t arg_count, | |
835 NPVariant* result) { | |
836 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
837 | |
838 if (arg_count != 3) { | |
839 SetException("startDaemon: bad number of arguments"); | |
840 return false; | |
841 } | |
842 | |
843 std::string config_str = StringFromNPVariant(args[0]); | |
844 scoped_ptr<base::Value> config( | |
845 base::JSONReader::Read(config_str, base::JSON_ALLOW_TRAILING_COMMAS)); | |
846 if (config_str.empty() || !config.get() || | |
847 !config->IsType(base::Value::TYPE_DICTIONARY)) { | |
848 SetException("startDaemon: bad config parameter"); | |
849 return false; | |
850 } | |
851 scoped_ptr<base::DictionaryValue> config_dict( | |
852 reinterpret_cast<base::DictionaryValue*>(config.release())); | |
853 | |
854 if (!NPVARIANT_IS_BOOLEAN(args[1])) { | |
855 SetException("startDaemon: invalid consent parameter"); | |
856 return false; | |
857 } | |
858 | |
859 scoped_ptr<ScopedRefNPObject> callback_obj( | |
860 new ScopedRefNPObject(ObjectFromNPVariant(args[2]))); | |
861 if (!callback_obj->get()) { | |
862 SetException("startDaemon: invalid callback parameter"); | |
863 return false; | |
864 } | |
865 | |
866 daemon_controller_->SetConfigAndStart( | |
867 config_dict.Pass(), | |
868 NPVARIANT_TO_BOOLEAN(args[1]), | |
869 base::Bind(&HostNPScriptObject::InvokeAsyncResultCallback, weak_ptr_, | |
870 base::Passed(&callback_obj))); | |
871 return true; | |
872 } | |
873 | |
874 bool HostNPScriptObject::StopDaemon(const NPVariant* args, | |
875 uint32_t arg_count, | |
876 NPVariant* result) { | |
877 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
878 | |
879 if (arg_count != 1) { | |
880 SetException("stopDaemon: bad number of arguments"); | |
881 return false; | |
882 } | |
883 | |
884 scoped_ptr<ScopedRefNPObject> callback_obj( | |
885 new ScopedRefNPObject(ObjectFromNPVariant(args[0]))); | |
886 if (!callback_obj->get()) { | |
887 SetException("stopDaemon: invalid callback parameter"); | |
888 return false; | |
889 } | |
890 | |
891 daemon_controller_->Stop( | |
892 base::Bind(&HostNPScriptObject::InvokeAsyncResultCallback, weak_ptr_, | |
893 base::Passed(&callback_obj))); | |
894 return true; | |
895 } | |
896 | |
897 void HostNPScriptObject::OnStateChanged(It2MeHostState state) { | |
898 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
899 | |
900 state_ = state; | |
901 | |
902 if (state_ == kDisconnected) | |
903 client_username_.clear(); | |
904 | |
905 if (on_state_changed_func_.get()) { | |
906 NPVariant state_var; | |
907 INT32_TO_NPVARIANT(state, state_var); | |
908 InvokeAndIgnoreResult(on_state_changed_func_, &state_var, 1); | |
909 } | |
910 } | |
911 | |
912 void HostNPScriptObject::OnNatPolicyChanged(bool nat_traversal_enabled) { | |
913 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
914 | |
915 if (on_nat_traversal_policy_changed_func_.get()) { | |
916 NPVariant policy; | |
917 BOOLEAN_TO_NPVARIANT(nat_traversal_enabled, policy); | |
918 InvokeAndIgnoreResult(on_nat_traversal_policy_changed_func_, | |
919 &policy, 1); | |
920 } | |
921 } | |
922 | |
923 // Stores the Access Code for the web-app to query. | |
924 void HostNPScriptObject::OnStoreAccessCode( | |
925 const std::string& access_code, base::TimeDelta access_code_lifetime) { | |
926 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
927 | |
928 access_code_ = access_code; | |
929 access_code_lifetime_ = access_code_lifetime; | |
930 } | |
931 | |
932 // Stores the client user's name for the web-app to query. | |
933 void HostNPScriptObject::OnClientAuthenticated( | |
934 const std::string& client_username) { | |
935 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
936 | |
937 client_username_ = client_username; | |
938 } | |
939 | |
940 void HostNPScriptObject::PostLogDebugInfo(const std::string& message) { | |
941 if (plugin_task_runner_->BelongsToCurrentThread()) { | |
942 // Make sure we're not currently processing a log message. | |
943 // We only need to check this if we're on the plugin thread. | |
944 if (am_currently_logging_) | |
945 return; | |
946 } | |
947 | |
948 // Always post (even if we're already on the correct thread) so that debug | |
949 // log messages are shown in the correct order. | |
950 plugin_task_runner_->PostTask( | |
951 FROM_HERE, base::Bind(&HostNPScriptObject::LogDebugInfo, | |
952 weak_ptr_, message)); | |
953 } | |
954 | |
955 void HostNPScriptObject::SetWindow(NPWindow* np_window) { | |
956 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
957 | |
958 daemon_controller_->SetWindow(np_window->window); | |
959 } | |
960 | |
961 void HostNPScriptObject::LocalizeStrings(NPObject* localize_func) { | |
962 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
963 | |
964 // Reload resources for the current locale. The default UI locale is used on | |
965 // Windows. | |
966 #if !defined(OS_WIN) | |
967 base::string16 ui_locale; | |
968 LocalizeString(localize_func, "@@ui_locale", &ui_locale); | |
969 remoting::LoadResources(base::UTF16ToUTF8(ui_locale)); | |
970 #endif // !defined(OS_WIN) | |
971 } | |
972 | |
973 bool HostNPScriptObject::LocalizeString(NPObject* localize_func, | |
974 const char* tag, | |
975 base::string16* result) { | |
976 return LocalizeStringWithSubstitution(localize_func, tag, NULL, result); | |
977 } | |
978 | |
979 bool HostNPScriptObject::LocalizeStringWithSubstitution( | |
980 NPObject* localize_func, | |
981 const char* tag, | |
982 const char* substitution, | |
983 base::string16* result) { | |
984 int argc = substitution ? 2 : 1; | |
985 scoped_ptr<NPVariant[]> args(new NPVariant[argc]); | |
986 STRINGZ_TO_NPVARIANT(tag, args[0]); | |
987 if (substitution) { | |
988 STRINGZ_TO_NPVARIANT(substitution, args[1]); | |
989 } | |
990 NPVariant np_result; | |
991 bool is_good = g_npnetscape_funcs->invokeDefault( | |
992 plugin_, localize_func, args.get(), argc, &np_result); | |
993 if (!is_good) { | |
994 LOG(ERROR) << "Localization failed for " << tag; | |
995 return false; | |
996 } | |
997 std::string translation = StringFromNPVariant(np_result); | |
998 g_npnetscape_funcs->releasevariantvalue(&np_result); | |
999 if (translation.empty()) { | |
1000 LOG(ERROR) << "Missing translation for " << tag; | |
1001 return false; | |
1002 } | |
1003 *result = base::UTF8ToUTF16(translation); | |
1004 return true; | |
1005 } | |
1006 | |
1007 // static | |
1008 void HostNPScriptObject::DoGenerateKeyPair( | |
1009 const scoped_refptr<AutoThreadTaskRunner>& plugin_task_runner, | |
1010 const base::Callback<void (const std::string&, | |
1011 const std::string&)>& callback) { | |
1012 scoped_refptr<RsaKeyPair> key_pair = RsaKeyPair::Generate(); | |
1013 plugin_task_runner->PostTask(FROM_HERE, | |
1014 base::Bind(callback, key_pair->ToString(), | |
1015 key_pair->GetPublicKey())); | |
1016 } | |
1017 | |
1018 void HostNPScriptObject::InvokeGenerateKeyPairCallback( | |
1019 scoped_ptr<ScopedRefNPObject> callback, | |
1020 const std::string& private_key, | |
1021 const std::string& public_key) { | |
1022 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1023 | |
1024 NPVariant params[2]; | |
1025 params[0] = NPVariantFromString(private_key); | |
1026 params[1] = NPVariantFromString(public_key); | |
1027 InvokeAndIgnoreResult(*callback, params, arraysize(params)); | |
1028 g_npnetscape_funcs->releasevariantvalue(&(params[0])); | |
1029 g_npnetscape_funcs->releasevariantvalue(&(params[1])); | |
1030 } | |
1031 | |
1032 void HostNPScriptObject::InvokeAsyncResultCallback( | |
1033 scoped_ptr<ScopedRefNPObject> callback, | |
1034 DaemonController::AsyncResult result) { | |
1035 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1036 | |
1037 NPVariant result_var; | |
1038 INT32_TO_NPVARIANT(static_cast<int32>(result), result_var); | |
1039 InvokeAndIgnoreResult(*callback, &result_var, 1); | |
1040 g_npnetscape_funcs->releasevariantvalue(&result_var); | |
1041 } | |
1042 | |
1043 void HostNPScriptObject::InvokeBooleanCallback( | |
1044 scoped_ptr<ScopedRefNPObject> callback, bool result) { | |
1045 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1046 | |
1047 NPVariant result_var; | |
1048 BOOLEAN_TO_NPVARIANT(result, result_var); | |
1049 InvokeAndIgnoreResult(*callback, &result_var, 1); | |
1050 g_npnetscape_funcs->releasevariantvalue(&result_var); | |
1051 } | |
1052 | |
1053 void HostNPScriptObject::InvokeGetDaemonConfigCallback( | |
1054 scoped_ptr<ScopedRefNPObject> callback, | |
1055 scoped_ptr<base::DictionaryValue> config) { | |
1056 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1057 | |
1058 // There is no easy way to create a dictionary from an NPAPI plugin | |
1059 // so we have to serialize the dictionary to pass it to JavaScript. | |
1060 std::string config_str; | |
1061 if (config.get()) | |
1062 base::JSONWriter::Write(config.get(), &config_str); | |
1063 | |
1064 NPVariant config_val = NPVariantFromString(config_str); | |
1065 InvokeAndIgnoreResult(*callback, &config_val, 1); | |
1066 g_npnetscape_funcs->releasevariantvalue(&config_val); | |
1067 } | |
1068 | |
1069 void HostNPScriptObject::InvokeGetDaemonVersionCallback( | |
1070 scoped_ptr<ScopedRefNPObject> callback, const std::string& version) { | |
1071 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1072 | |
1073 NPVariant version_val = NPVariantFromString(version); | |
1074 InvokeAndIgnoreResult(*callback, &version_val, 1); | |
1075 g_npnetscape_funcs->releasevariantvalue(&version_val); | |
1076 } | |
1077 | |
1078 void HostNPScriptObject::InvokeGetPairedClientsCallback( | |
1079 scoped_ptr<ScopedRefNPObject> callback, | |
1080 scoped_ptr<base::ListValue> paired_clients) { | |
1081 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1082 | |
1083 std::string paired_clients_json; | |
1084 base::JSONWriter::Write(paired_clients.get(), &paired_clients_json); | |
1085 | |
1086 NPVariant paired_clients_val = NPVariantFromString(paired_clients_json); | |
1087 InvokeAndIgnoreResult(*callback, &paired_clients_val, 1); | |
1088 g_npnetscape_funcs->releasevariantvalue(&paired_clients_val); | |
1089 } | |
1090 | |
1091 void HostNPScriptObject::InvokeGetUsageStatsConsentCallback( | |
1092 scoped_ptr<ScopedRefNPObject> callback, | |
1093 const DaemonController::UsageStatsConsent& consent) { | |
1094 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1095 | |
1096 NPVariant params[3]; | |
1097 BOOLEAN_TO_NPVARIANT(consent.supported, params[0]); | |
1098 BOOLEAN_TO_NPVARIANT(consent.allowed, params[1]); | |
1099 BOOLEAN_TO_NPVARIANT(consent.set_by_policy, params[2]); | |
1100 InvokeAndIgnoreResult(*callback, params, arraysize(params)); | |
1101 g_npnetscape_funcs->releasevariantvalue(&(params[0])); | |
1102 g_npnetscape_funcs->releasevariantvalue(&(params[1])); | |
1103 g_npnetscape_funcs->releasevariantvalue(&(params[2])); | |
1104 } | |
1105 | |
1106 void HostNPScriptObject::LogDebugInfo(const std::string& message) { | |
1107 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1108 | |
1109 if (log_debug_info_func_.get()) { | |
1110 am_currently_logging_ = true; | |
1111 NPVariant log_message; | |
1112 STRINGZ_TO_NPVARIANT(message.c_str(), log_message); | |
1113 bool is_good = InvokeAndIgnoreResult(log_debug_info_func_, | |
1114 &log_message, 1); | |
1115 if (!is_good) { | |
1116 LOG(ERROR) << "ERROR - LogDebugInfo failed\n"; | |
1117 } | |
1118 am_currently_logging_ = false; | |
1119 } | |
1120 } | |
1121 | |
1122 bool HostNPScriptObject::InvokeAndIgnoreResult(const ScopedRefNPObject& func, | |
1123 const NPVariant* args, | |
1124 uint32_t arg_count) { | |
1125 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1126 | |
1127 NPVariant np_result; | |
1128 bool is_good = g_npnetscape_funcs->invokeDefault(plugin_, func.get(), args, | |
1129 arg_count, &np_result); | |
1130 if (is_good) | |
1131 g_npnetscape_funcs->releasevariantvalue(&np_result); | |
1132 | |
1133 return is_good; | |
1134 } | |
1135 | |
1136 void HostNPScriptObject::SetException(const std::string& exception_string) { | |
1137 DCHECK(plugin_task_runner_->BelongsToCurrentThread()); | |
1138 | |
1139 g_npnetscape_funcs->setexception(parent_, exception_string.c_str()); | |
1140 HOST_LOG << exception_string; | |
1141 } | |
1142 | |
1143 } // namespace remoting | |
OLD | NEW |