| 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 |