OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/host/plugin/host_script_object.h" | 5 #include "remoting/host/plugin/host_script_object.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/threading/platform_thread.h" | 9 #include "base/threading/platform_thread.h" |
10 #include "remoting/base/auth_token_util.h" | 10 #include "remoting/base/auth_token_util.h" |
11 #include "remoting/base/util.h" | 11 #include "remoting/base/util.h" |
12 #include "remoting/host/chromoting_host.h" | 12 #include "remoting/host/chromoting_host.h" |
13 #include "remoting/host/chromoting_host_context.h" | 13 #include "remoting/host/chromoting_host_context.h" |
14 #include "remoting/host/desktop_environment.h" | 14 #include "remoting/host/desktop_environment.h" |
15 #include "remoting/host/host_config.h" | 15 #include "remoting/host/host_config.h" |
16 #include "remoting/host/host_key_pair.h" | 16 #include "remoting/host/host_key_pair.h" |
17 #include "remoting/host/in_memory_host_config.h" | 17 #include "remoting/host/in_memory_host_config.h" |
18 #include "remoting/host/plugin/host_plugin_utils.h" | |
19 #include "remoting/host/register_support_host_request.h" | 18 #include "remoting/host/register_support_host_request.h" |
20 #include "remoting/host/support_access_verifier.h" | 19 #include "remoting/host/support_access_verifier.h" |
| 20 #include "remoting/host/ui_strings.h" |
21 | 21 |
22 namespace remoting { | 22 namespace remoting { |
23 | 23 |
24 // Supported Javascript interface: | 24 // Supported Javascript interface: |
25 // readonly attribute string accessCode; | 25 // readonly attribute string accessCode; |
26 // readonly attribute int accessCodeLifetime; | 26 // readonly attribute int accessCodeLifetime; |
27 // readonly attribute string client; | 27 // readonly attribute string client; |
28 // readonly attribute int state; | 28 // readonly attribute int state; |
29 // | 29 // |
30 // state: { | 30 // state: { |
31 // DISCONNECTED, | 31 // DISCONNECTED, |
32 // REQUESTED_ACCESS_CODE, | 32 // REQUESTED_ACCESS_CODE, |
33 // RECEIVED_ACCESS_CODE, | 33 // RECEIVED_ACCESS_CODE, |
34 // CONNECTED, | 34 // CONNECTED, |
35 // AFFIRMING_CONNECTION, | 35 // AFFIRMING_CONNECTION, |
36 // ERROR, | 36 // ERROR, |
37 // } | 37 // } |
38 // | 38 // |
39 // attribute Function void logDebugInfo(string); | 39 // attribute Function void logDebugInfo(string); |
40 // attribute Function void onStateChanged(); | 40 // attribute Function void onStateChanged(); |
| 41 // attribute Function string localize(string,...); |
41 // | 42 // |
42 // // The |auth_service_with_token| parameter should be in the format | 43 // // The |auth_service_with_token| parameter should be in the format |
43 // // "auth_service:auth_token". An example would be "oauth2:1/2a3912vd". | 44 // // "auth_service:auth_token". An example would be "oauth2:1/2a3912vd". |
44 // void connect(string uid, string auth_service_with_token); | 45 // void connect(string uid, string auth_service_with_token); |
45 // void disconnect(); | 46 // void disconnect(); |
46 | 47 |
47 namespace { | 48 namespace { |
48 | 49 |
49 const char* kAttrNameAccessCode = "accessCode"; | 50 const char* kAttrNameAccessCode = "accessCode"; |
50 const char* kAttrNameAccessCodeLifetime = "accessCodeLifetime"; | 51 const char* kAttrNameAccessCodeLifetime = "accessCodeLifetime"; |
51 const char* kAttrNameClient = "client"; | 52 const char* kAttrNameClient = "client"; |
52 const char* kAttrNameState = "state"; | 53 const char* kAttrNameState = "state"; |
| 54 const char* kAttrNameLocalize = "localize"; |
53 const char* kAttrNameLogDebugInfo = "logDebugInfo"; | 55 const char* kAttrNameLogDebugInfo = "logDebugInfo"; |
54 const char* kAttrNameOnStateChanged = "onStateChanged"; | 56 const char* kAttrNameOnStateChanged = "onStateChanged"; |
55 const char* kFuncNameConnect = "connect"; | 57 const char* kFuncNameConnect = "connect"; |
56 const char* kFuncNameDisconnect = "disconnect"; | 58 const char* kFuncNameDisconnect = "disconnect"; |
57 | 59 |
58 // States. | 60 // States. |
59 const char* kAttrNameDisconnected = "DISCONNECTED"; | 61 const char* kAttrNameDisconnected = "DISCONNECTED"; |
60 const char* kAttrNameRequestedAccessCode = "REQUESTED_ACCESS_CODE"; | 62 const char* kAttrNameRequestedAccessCode = "REQUESTED_ACCESS_CODE"; |
61 const char* kAttrNameReceivedAccessCode = "RECEIVED_ACCESS_CODE"; | 63 const char* kAttrNameReceivedAccessCode = "RECEIVED_ACCESS_CODE"; |
62 const char* kAttrNameConnected = "CONNECTED"; | 64 const char* kAttrNameConnected = "CONNECTED"; |
63 const char* kAttrNameAffirmingConnection = "AFFIRMING_CONNECTION"; | 65 const char* kAttrNameAffirmingConnection = "AFFIRMING_CONNECTION"; |
64 const char* kAttrNameError = "ERROR"; | 66 const char* kAttrNameError = "ERROR"; |
65 | 67 |
66 const int kMaxLoginAttempts = 5; | 68 const int kMaxLoginAttempts = 5; |
67 | 69 |
68 } // namespace | 70 } // namespace |
69 | 71 |
70 // This flag blocks LOGs to the UI if we're already in the middle of logging | 72 // This flag blocks LOGs to the UI if we're already in the middle of logging |
71 // to the UI. This prevents a potential infinite loop if we encounter an error | 73 // to the UI. This prevents a potential infinite loop if we encounter an error |
72 // while sending the log message to the UI. | 74 // while sending the log message to the UI. |
73 static bool g_logging_to_plugin = false; | 75 static bool g_logging_to_plugin = false; |
74 static HostNPScriptObject* g_logging_scriptable_object = NULL; | 76 static HostNPScriptObject* g_logging_scriptable_object = NULL; |
75 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL; | 77 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL; |
76 | 78 |
77 HostNPScriptObject::HostNPScriptObject(NPP plugin, NPObject* parent) | 79 HostNPScriptObject::HostNPScriptObject(NPP plugin, NPObject* parent) |
78 : plugin_(plugin), | 80 : plugin_(plugin), |
79 parent_(parent), | 81 parent_(parent), |
80 state_(kDisconnected), | 82 state_(kDisconnected), |
81 log_debug_info_func_(NULL), | |
82 on_state_changed_func_(NULL), | |
83 np_thread_id_(base::PlatformThread::CurrentId()), | 83 np_thread_id_(base::PlatformThread::CurrentId()), |
84 failed_login_attempts_(0), | 84 failed_login_attempts_(0), |
85 disconnected_event_(true, false) { | 85 disconnected_event_(true, false) { |
86 // Set up log message handler. | 86 // Set up log message handler. |
87 // Note that this approach doesn't quite support having multiple instances | 87 // Note that this approach doesn't quite support having multiple instances |
88 // of Chromoting running. In that case, the most recently opened tab will | 88 // of Chromoting running. In that case, the most recently opened tab will |
89 // grab all the debug log messages, and when any Chromoting tab is closed | 89 // grab all the debug log messages, and when any Chromoting tab is closed |
90 // the logging handler will go away. | 90 // the logging handler will go away. |
91 // Since having multiple Chromoting tabs is not a primary use case, and this | 91 // Since having multiple Chromoting tabs is not a primary use case, and this |
92 // is just debug logging, we're punting improving debug log support for that | 92 // is just debug logging, we're punting improving debug log support for that |
(...skipping 23 matching lines...) Expand all Loading... |
116 // here because |host_context_| needs to be stopped on the plugin | 116 // here because |host_context_| needs to be stopped on the plugin |
117 // thread, but the plugin thread may not exist after the instance | 117 // thread, but the plugin thread may not exist after the instance |
118 // is destroyed. | 118 // is destroyed. |
119 destructing_.Set(); | 119 destructing_.Set(); |
120 disconnected_event_.Reset(); | 120 disconnected_event_.Reset(); |
121 DisconnectInternal(); | 121 DisconnectInternal(); |
122 disconnected_event_.Wait(); | 122 disconnected_event_.Wait(); |
123 | 123 |
124 // Stop all threads. | 124 // Stop all threads. |
125 host_context_.Stop(); | 125 host_context_.Stop(); |
126 | |
127 if (log_debug_info_func_) { | |
128 g_npnetscape_funcs->releaseobject(log_debug_info_func_); | |
129 } | |
130 if (on_state_changed_func_) { | |
131 g_npnetscape_funcs->releaseobject(on_state_changed_func_); | |
132 } | |
133 } | 126 } |
134 | 127 |
135 bool HostNPScriptObject::Init() { | 128 bool HostNPScriptObject::Init() { |
136 VLOG(2) << "Init"; | 129 VLOG(2) << "Init"; |
137 // TODO(wez): This starts a bunch of threads, which might fail. | 130 // TODO(wez): This starts a bunch of threads, which might fail. |
138 host_context_.Start(); | 131 host_context_.Start(); |
139 return true; | 132 return true; |
140 } | 133 } |
141 | 134 |
142 bool HostNPScriptObject::HasMethod(const std::string& method_name) { | 135 bool HostNPScriptObject::HasMethod(const std::string& method_name) { |
(...skipping 28 matching lines...) Expand all Loading... |
171 } | 164 } |
172 } | 165 } |
173 | 166 |
174 bool HostNPScriptObject::HasProperty(const std::string& property_name) { | 167 bool HostNPScriptObject::HasProperty(const std::string& property_name) { |
175 VLOG(2) << "HasProperty " << property_name; | 168 VLOG(2) << "HasProperty " << property_name; |
176 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 169 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
177 return (property_name == kAttrNameAccessCode || | 170 return (property_name == kAttrNameAccessCode || |
178 property_name == kAttrNameAccessCodeLifetime || | 171 property_name == kAttrNameAccessCodeLifetime || |
179 property_name == kAttrNameClient || | 172 property_name == kAttrNameClient || |
180 property_name == kAttrNameState || | 173 property_name == kAttrNameState || |
| 174 property_name == kAttrNameLocalize || |
181 property_name == kAttrNameLogDebugInfo || | 175 property_name == kAttrNameLogDebugInfo || |
182 property_name == kAttrNameOnStateChanged || | 176 property_name == kAttrNameOnStateChanged || |
183 property_name == kAttrNameDisconnected || | 177 property_name == kAttrNameDisconnected || |
184 property_name == kAttrNameRequestedAccessCode || | 178 property_name == kAttrNameRequestedAccessCode || |
185 property_name == kAttrNameReceivedAccessCode || | 179 property_name == kAttrNameReceivedAccessCode || |
186 property_name == kAttrNameConnected || | 180 property_name == kAttrNameConnected || |
187 property_name == kAttrNameAffirmingConnection || | 181 property_name == kAttrNameAffirmingConnection || |
188 property_name == kAttrNameError); | 182 property_name == kAttrNameError); |
189 } | 183 } |
190 | 184 |
191 bool HostNPScriptObject::GetProperty(const std::string& property_name, | 185 bool HostNPScriptObject::GetProperty(const std::string& property_name, |
192 NPVariant* result) { | 186 NPVariant* result) { |
193 VLOG(2) << "GetProperty " << property_name; | 187 VLOG(2) << "GetProperty " << property_name; |
194 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 188 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
195 if (!result) { | 189 if (!result) { |
196 SetException("GetProperty: NULL result"); | 190 SetException("GetProperty: NULL result"); |
197 return false; | 191 return false; |
198 } | 192 } |
199 | 193 |
200 if (property_name == kAttrNameOnStateChanged) { | 194 if (property_name == kAttrNameOnStateChanged) { |
201 OBJECT_TO_NPVARIANT(on_state_changed_func_, *result); | 195 OBJECT_TO_NPVARIANT(on_state_changed_func_.get(), *result); |
| 196 return true; |
| 197 } else if (property_name == kAttrNameLocalize) { |
| 198 OBJECT_TO_NPVARIANT(localize_func_.get(), *result); |
202 return true; | 199 return true; |
203 } else if (property_name == kAttrNameLogDebugInfo) { | 200 } else if (property_name == kAttrNameLogDebugInfo) { |
204 OBJECT_TO_NPVARIANT(log_debug_info_func_, *result); | 201 OBJECT_TO_NPVARIANT(log_debug_info_func_.get(), *result); |
205 return true; | 202 return true; |
206 } else if (property_name == kAttrNameState) { | 203 } else if (property_name == kAttrNameState) { |
207 INT32_TO_NPVARIANT(state_, *result); | 204 INT32_TO_NPVARIANT(state_, *result); |
208 return true; | 205 return true; |
209 } else if (property_name == kAttrNameAccessCode) { | 206 } else if (property_name == kAttrNameAccessCode) { |
210 *result = NPVariantFromString(access_code_); | 207 *result = NPVariantFromString(access_code_); |
211 return true; | 208 return true; |
212 } else if (property_name == kAttrNameAccessCodeLifetime) { | 209 } else if (property_name == kAttrNameAccessCodeLifetime) { |
213 INT32_TO_NPVARIANT(access_code_lifetime_.InSeconds(), *result); | 210 INT32_TO_NPVARIANT(access_code_lifetime_.InSeconds(), *result); |
214 return true; | 211 return true; |
(...skipping 24 matching lines...) Expand all Loading... |
239 } | 236 } |
240 } | 237 } |
241 | 238 |
242 bool HostNPScriptObject::SetProperty(const std::string& property_name, | 239 bool HostNPScriptObject::SetProperty(const std::string& property_name, |
243 const NPVariant* value) { | 240 const NPVariant* value) { |
244 VLOG(2) << "SetProperty " << property_name; | 241 VLOG(2) << "SetProperty " << property_name; |
245 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 242 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
246 | 243 |
247 if (property_name == kAttrNameOnStateChanged) { | 244 if (property_name == kAttrNameOnStateChanged) { |
248 if (NPVARIANT_IS_OBJECT(*value)) { | 245 if (NPVARIANT_IS_OBJECT(*value)) { |
249 if (on_state_changed_func_) { | 246 on_state_changed_func_.replace(NPVARIANT_TO_OBJECT(*value)); |
250 g_npnetscape_funcs->releaseobject(on_state_changed_func_); | |
251 } | |
252 on_state_changed_func_ = NPVARIANT_TO_OBJECT(*value); | |
253 if (on_state_changed_func_) { | |
254 g_npnetscape_funcs->retainobject(on_state_changed_func_); | |
255 } | |
256 return true; | 247 return true; |
257 } else { | 248 } else { |
258 SetException("SetProperty: unexpected type for property " + | 249 SetException("SetProperty: unexpected type for property " + |
| 250 property_name); |
| 251 } |
| 252 return false; |
| 253 } |
| 254 |
| 255 if (property_name == kAttrNameLocalize) { |
| 256 if (NPVARIANT_IS_OBJECT(*value)) { |
| 257 localize_func_.replace(NPVARIANT_TO_OBJECT(*value)); |
| 258 return true; |
| 259 } else { |
| 260 SetException("SetProperty: unexpected type for property " + |
259 property_name); | 261 property_name); |
260 } | 262 } |
261 return false; | 263 return false; |
262 } | 264 } |
263 | 265 |
264 if (property_name == kAttrNameLogDebugInfo) { | 266 if (property_name == kAttrNameLogDebugInfo) { |
265 if (NPVARIANT_IS_OBJECT(*value)) { | 267 if (NPVARIANT_IS_OBJECT(*value)) { |
266 if (log_debug_info_func_) { | 268 log_debug_info_func_.replace(NPVARIANT_TO_OBJECT(*value)); |
267 g_npnetscape_funcs->releaseobject(log_debug_info_func_); | |
268 } | |
269 log_debug_info_func_ = NPVARIANT_TO_OBJECT(*value); | |
270 if (log_debug_info_func_) { | |
271 g_npnetscape_funcs->retainobject(log_debug_info_func_); | |
272 } | |
273 return true; | 269 return true; |
274 } else { | 270 } else { |
275 SetException("SetProperty: unexpected type for property " + | 271 SetException("SetProperty: unexpected type for property " + |
276 property_name); | 272 property_name); |
277 } | 273 } |
278 return false; | 274 return false; |
279 } | 275 } |
280 | 276 |
281 return false; | 277 return false; |
282 } | 278 } |
283 | 279 |
284 bool HostNPScriptObject::RemoveProperty(const std::string& property_name) { | 280 bool HostNPScriptObject::RemoveProperty(const std::string& property_name) { |
285 VLOG(2) << "RemoveProperty " << property_name; | 281 VLOG(2) << "RemoveProperty " << property_name; |
286 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 282 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
287 return false; | 283 return false; |
288 } | 284 } |
289 | 285 |
290 bool HostNPScriptObject::Enumerate(std::vector<std::string>* values) { | 286 bool HostNPScriptObject::Enumerate(std::vector<std::string>* values) { |
291 VLOG(2) << "Enumerate"; | 287 VLOG(2) << "Enumerate"; |
292 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 288 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
293 const char* entries[] = { | 289 const char* entries[] = { |
294 kAttrNameAccessCode, | 290 kAttrNameAccessCode, |
295 kAttrNameState, | 291 kAttrNameState, |
| 292 kAttrNameLocalize, |
296 kAttrNameLogDebugInfo, | 293 kAttrNameLogDebugInfo, |
297 kAttrNameOnStateChanged, | 294 kAttrNameOnStateChanged, |
298 kFuncNameConnect, | 295 kFuncNameConnect, |
299 kFuncNameDisconnect, | 296 kFuncNameDisconnect, |
300 kAttrNameDisconnected, | 297 kAttrNameDisconnected, |
301 kAttrNameRequestedAccessCode, | 298 kAttrNameRequestedAccessCode, |
302 kAttrNameReceivedAccessCode, | 299 kAttrNameReceivedAccessCode, |
303 kAttrNameConnected, | 300 kAttrNameConnected, |
304 kAttrNameAffirmingConnection, | 301 kAttrNameAffirmingConnection, |
305 kAttrNameError | 302 kAttrNameError |
(...skipping 20 matching lines...) Expand all Loading... |
326 } | 323 } |
327 | 324 |
328 void HostNPScriptObject::OnClientAuthenticated( | 325 void HostNPScriptObject::OnClientAuthenticated( |
329 remoting::protocol::ConnectionToClient* client) { | 326 remoting::protocol::ConnectionToClient* client) { |
330 DCHECK_NE(base::PlatformThread::CurrentId(), np_thread_id_); | 327 DCHECK_NE(base::PlatformThread::CurrentId(), np_thread_id_); |
331 client_username_ = client->session()->jid(); | 328 client_username_ = client->session()->jid(); |
332 size_t pos = client_username_.find('/'); | 329 size_t pos = client_username_.find('/'); |
333 if (pos != std::string::npos) | 330 if (pos != std::string::npos) |
334 client_username_.replace(pos, std::string::npos, ""); | 331 client_username_.replace(pos, std::string::npos, ""); |
335 LOG(INFO) << "Client " << client_username_ << " connected."; | 332 LOG(INFO) << "Client " << client_username_ << " connected."; |
| 333 UiStrings* ui_strings = host_->ui_strings(); |
| 334 std::string direction; |
| 335 Localize("@@bidi_dir", NULL, &direction); |
| 336 ui_strings->direction = |
| 337 direction == "rtl" ? remoting::UiStrings::RTL |
| 338 : remoting::UiStrings::LTR; |
| 339 Localize("productName", NULL, &ui_strings->productName); |
| 340 Localize("disconnectButton", NULL, &ui_strings->disconnectButtonText); |
| 341 Localize( |
| 342 #if defined(OS_WIN) |
| 343 "disconnectButtonShortcutWindows", |
| 344 #elif defined(OS_MAC) |
| 345 "disconnectButtonShortcutMacOSX", |
| 346 #else |
| 347 "disconnectButtonShortcutLinux", |
| 348 #endif |
| 349 NULL, &ui_strings->disconnectButtonShortcut); |
| 350 Localize("continuePrompt", NULL, &ui_strings->continuePrompt); |
| 351 Localize("continueButton", NULL, &ui_strings->continueButtonText); |
| 352 Localize("stopSharingButton", NULL, &ui_strings->stopSharingButtonText); |
| 353 Localize("messageShared", client_username_.c_str(), |
| 354 &ui_strings->disconnectMessage); |
336 OnStateChanged(kConnected); | 355 OnStateChanged(kConnected); |
337 } | 356 } |
338 | 357 |
339 void HostNPScriptObject::OnClientDisconnected( | 358 void HostNPScriptObject::OnClientDisconnected( |
340 remoting::protocol::ConnectionToClient* client) { | 359 remoting::protocol::ConnectionToClient* client) { |
341 client_username_.clear(); | 360 client_username_.clear(); |
342 OnStateChanged(kDisconnected); | 361 OnStateChanged(kDisconnected); |
343 } | 362 } |
344 | 363 |
345 void HostNPScriptObject::OnShutdown() { | 364 void HostNPScriptObject::OnShutdown() { |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 if (destructing_.IsSet()) | 535 if (destructing_.IsSet()) |
517 return; | 536 return; |
518 | 537 |
519 if (!host_context_.IsUIThread()) { | 538 if (!host_context_.IsUIThread()) { |
520 host_context_.PostTaskToUIThread( | 539 host_context_.PostTaskToUIThread( |
521 FROM_HERE, base::Bind(&HostNPScriptObject::OnStateChanged, | 540 FROM_HERE, base::Bind(&HostNPScriptObject::OnStateChanged, |
522 base::Unretained(this), state)); | 541 base::Unretained(this), state)); |
523 return; | 542 return; |
524 } | 543 } |
525 state_ = state; | 544 state_ = state; |
526 if (on_state_changed_func_) { | 545 if (on_state_changed_func_.get()) { |
527 VLOG(2) << "Calling state changed " << state; | 546 VLOG(2) << "Calling state changed " << state; |
528 bool is_good = InvokeAndIgnoreResult(on_state_changed_func_, NULL, 0); | 547 bool is_good = InvokeAndIgnoreResult(on_state_changed_func_.get(), NULL, 0); |
529 LOG_IF(ERROR, !is_good) << "OnStateChanged failed"; | 548 LOG_IF(ERROR, !is_good) << "OnStateChanged failed"; |
530 } | 549 } |
531 } | 550 } |
532 | 551 |
533 // static | 552 // static |
534 bool HostNPScriptObject::LogToUI(int severity, const char* file, int line, | 553 bool HostNPScriptObject::LogToUI(int severity, const char* file, int line, |
535 size_t message_start, | 554 size_t message_start, |
536 const std::string& str) { | 555 const std::string& str) { |
537 // The |g_logging_to_plugin| check is to prevent logging to the scriptable | 556 // The |g_logging_to_plugin| check is to prevent logging to the scriptable |
538 // object if we're already in the middle of logging. | 557 // object if we're already in the middle of logging. |
(...skipping 15 matching lines...) Expand all Loading... |
554 if (destructing_.IsSet()) | 573 if (destructing_.IsSet()) |
555 return; | 574 return; |
556 | 575 |
557 if (!host_context_.IsUIThread()) { | 576 if (!host_context_.IsUIThread()) { |
558 host_context_.PostTaskToUIThread( | 577 host_context_.PostTaskToUIThread( |
559 FROM_HERE, base::Bind(&HostNPScriptObject::LogDebugInfo, | 578 FROM_HERE, base::Bind(&HostNPScriptObject::LogDebugInfo, |
560 base::Unretained(this), message)); | 579 base::Unretained(this), message)); |
561 return; | 580 return; |
562 } | 581 } |
563 | 582 |
564 if (log_debug_info_func_) { | 583 if (log_debug_info_func_.get()) { |
565 NPVariant log_message; | 584 NPVariant log_message; |
566 STRINGZ_TO_NPVARIANT(message.c_str(), log_message); | 585 STRINGZ_TO_NPVARIANT(message.c_str(), log_message); |
567 bool is_good = InvokeAndIgnoreResult(log_debug_info_func_, | 586 bool is_good = InvokeAndIgnoreResult(log_debug_info_func_.get(), |
568 &log_message, 1); | 587 &log_message, 1); |
569 LOG_IF(ERROR, !is_good) << "LogDebugInfo failed"; | 588 LOG_IF(ERROR, !is_good) << "LogDebugInfo failed"; |
570 } | 589 } |
571 } | 590 } |
572 | 591 |
573 void HostNPScriptObject::SetException(const std::string& exception_string) { | 592 void HostNPScriptObject::SetException(const std::string& exception_string) { |
574 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 593 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
575 g_npnetscape_funcs->setexception(parent_, exception_string.c_str()); | 594 g_npnetscape_funcs->setexception(parent_, exception_string.c_str()); |
576 LOG(INFO) << exception_string; | 595 LOG(INFO) << exception_string; |
577 } | 596 } |
578 | 597 |
| 598 bool HostNPScriptObject::Localize(const char* tag, const char* parameter, |
| 599 std::string* result) { |
| 600 NPVariant args[2]; |
| 601 STRINGZ_TO_NPVARIANT(tag, args[0]); |
| 602 if (parameter) { |
| 603 STRINGZ_TO_NPVARIANT(parameter, args[1]); |
| 604 } |
| 605 NPVariant np_result; |
| 606 bool is_good = g_npnetscape_funcs->invokeDefault( |
| 607 plugin_, localize_func_.get(), &args[0], parameter ? 2 : 1, &np_result); |
| 608 if (!is_good) { |
| 609 LOG(ERROR) << "Localization failed for " << tag; |
| 610 return false; |
| 611 } |
| 612 std::string translation = StringFromNPVariant(np_result); |
| 613 g_npnetscape_funcs->releasevariantvalue(&np_result); |
| 614 if (translation.empty()) { |
| 615 LOG(ERROR) << "Missing translation for " << tag; |
| 616 return false; |
| 617 } |
| 618 *result = translation; |
| 619 return true; |
| 620 } |
| 621 |
579 bool HostNPScriptObject::InvokeAndIgnoreResult(NPObject* func, | 622 bool HostNPScriptObject::InvokeAndIgnoreResult(NPObject* func, |
580 const NPVariant* args, | 623 const NPVariant* args, |
581 uint32_t argCount) { | 624 uint32_t argCount) { |
582 NPVariant np_result; | 625 NPVariant np_result; |
583 bool is_good = g_npnetscape_funcs->invokeDefault(plugin_, func, args, | 626 bool is_good = g_npnetscape_funcs->invokeDefault(plugin_, func, args, |
584 argCount, &np_result); | 627 argCount, &np_result); |
585 if (is_good) | 628 if (is_good) |
586 g_npnetscape_funcs->releasevariantvalue(&np_result); | 629 g_npnetscape_funcs->releasevariantvalue(&np_result); |
587 return is_good; | 630 return is_good; |
588 } | 631 } |
(...skipping 13 matching lines...) Expand all Loading... |
602 } | 645 } |
603 | 646 |
604 // static | 647 // static |
605 void HostNPScriptObject::NPTaskSpringboard(void* task) { | 648 void HostNPScriptObject::NPTaskSpringboard(void* task) { |
606 base::Closure* real_task = reinterpret_cast<base::Closure*>(task); | 649 base::Closure* real_task = reinterpret_cast<base::Closure*>(task); |
607 real_task->Run(); | 650 real_task->Run(); |
608 delete real_task; | 651 delete real_task; |
609 } | 652 } |
610 | 653 |
611 } // namespace remoting | 654 } // namespace remoting |
OLD | NEW |