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/message_loop_proxy.h" | 9 #include "base/message_loop_proxy.h" |
10 #include "base/threading/platform_thread.h" | 10 #include "base/threading/platform_thread.h" |
11 #include "remoting/base/auth_token_util.h" | 11 #include "remoting/base/auth_token_util.h" |
12 #include "remoting/base/util.h" | 12 #include "remoting/base/util.h" |
13 #include "remoting/host/chromoting_host.h" | 13 #include "remoting/host/chromoting_host.h" |
14 #include "remoting/host/chromoting_host_context.h" | 14 #include "remoting/host/chromoting_host_context.h" |
15 #include "remoting/host/desktop_environment.h" | 15 #include "remoting/host/desktop_environment.h" |
16 #include "remoting/host/host_config.h" | 16 #include "remoting/host/host_config.h" |
17 #include "remoting/host/host_key_pair.h" | 17 #include "remoting/host/host_key_pair.h" |
18 #include "remoting/host/in_memory_host_config.h" | 18 #include "remoting/host/in_memory_host_config.h" |
19 #include "remoting/host/plugin/host_plugin_utils.h" | |
20 #include "remoting/host/plugin/policy_hack/nat_policy.h" | 19 #include "remoting/host/plugin/policy_hack/nat_policy.h" |
21 #include "remoting/host/register_support_host_request.h" | 20 #include "remoting/host/register_support_host_request.h" |
22 #include "remoting/host/support_access_verifier.h" | 21 #include "remoting/host/support_access_verifier.h" |
| 22 #include "remoting/host/ui_strings.h" |
23 | 23 |
24 namespace remoting { | 24 namespace remoting { |
25 | 25 |
26 // Supported Javascript interface: | 26 // Supported Javascript interface: |
27 // readonly attribute string accessCode; | 27 // readonly attribute string accessCode; |
28 // readonly attribute int accessCodeLifetime; | 28 // readonly attribute int accessCodeLifetime; |
29 // readonly attribute string client; | 29 // readonly attribute string client; |
30 // readonly attribute int state; | 30 // readonly attribute int state; |
31 // | 31 // |
32 // state: { | 32 // state: { |
33 // DISCONNECTED, | 33 // DISCONNECTED, |
34 // REQUESTED_ACCESS_CODE, | 34 // REQUESTED_ACCESS_CODE, |
35 // RECEIVED_ACCESS_CODE, | 35 // RECEIVED_ACCESS_CODE, |
36 // CONNECTED, | 36 // CONNECTED, |
37 // AFFIRMING_CONNECTION, | 37 // AFFIRMING_CONNECTION, |
38 // ERROR, | 38 // ERROR, |
39 // } | 39 // } |
40 // | 40 // |
41 // attribute Function void logDebugInfo(string); | 41 // attribute Function void logDebugInfo(string); |
42 // attribute Function void onStateChanged(); | 42 // attribute Function void onStateChanged(); |
| 43 // attribute Function string localizeString(string,...); |
43 // | 44 // |
44 // // The |auth_service_with_token| parameter should be in the format | 45 // // The |auth_service_with_token| parameter should be in the format |
45 // // "auth_service:auth_token". An example would be "oauth2:1/2a3912vd". | 46 // // "auth_service:auth_token". An example would be "oauth2:1/2a3912vd". |
46 // void connect(string uid, string auth_service_with_token); | 47 // void connect(string uid, string auth_service_with_token); |
47 // void disconnect(); | 48 // void disconnect(); |
48 | 49 |
49 namespace { | 50 namespace { |
50 | 51 |
51 const char* kAttrNameAccessCode = "accessCode"; | 52 const char* kAttrNameAccessCode = "accessCode"; |
52 const char* kAttrNameAccessCodeLifetime = "accessCodeLifetime"; | 53 const char* kAttrNameAccessCodeLifetime = "accessCodeLifetime"; |
53 const char* kAttrNameClient = "client"; | 54 const char* kAttrNameClient = "client"; |
54 const char* kAttrNameState = "state"; | 55 const char* kAttrNameState = "state"; |
| 56 const char* kAttrNameLocalizeString = "localizeString"; |
55 const char* kAttrNameLogDebugInfo = "logDebugInfo"; | 57 const char* kAttrNameLogDebugInfo = "logDebugInfo"; |
56 const char* kAttrNameOnStateChanged = "onStateChanged"; | 58 const char* kAttrNameOnStateChanged = "onStateChanged"; |
57 const char* kFuncNameConnect = "connect"; | 59 const char* kFuncNameConnect = "connect"; |
58 const char* kFuncNameDisconnect = "disconnect"; | 60 const char* kFuncNameDisconnect = "disconnect"; |
59 | 61 |
60 // States. | 62 // States. |
61 const char* kAttrNameDisconnected = "DISCONNECTED"; | 63 const char* kAttrNameDisconnected = "DISCONNECTED"; |
62 const char* kAttrNameRequestedAccessCode = "REQUESTED_ACCESS_CODE"; | 64 const char* kAttrNameRequestedAccessCode = "REQUESTED_ACCESS_CODE"; |
63 const char* kAttrNameReceivedAccessCode = "RECEIVED_ACCESS_CODE"; | 65 const char* kAttrNameReceivedAccessCode = "RECEIVED_ACCESS_CODE"; |
64 const char* kAttrNameConnected = "CONNECTED"; | 66 const char* kAttrNameConnected = "CONNECTED"; |
65 const char* kAttrNameAffirmingConnection = "AFFIRMING_CONNECTION"; | 67 const char* kAttrNameAffirmingConnection = "AFFIRMING_CONNECTION"; |
66 const char* kAttrNameError = "ERROR"; | 68 const char* kAttrNameError = "ERROR"; |
67 | 69 |
68 const int kMaxLoginAttempts = 5; | 70 const int kMaxLoginAttempts = 5; |
69 | 71 |
70 } // namespace | 72 } // namespace |
71 | 73 |
72 // This flag blocks LOGs to the UI if we're already in the middle of logging | 74 // This flag blocks LOGs to the UI if we're already in the middle of logging |
73 // to the UI. This prevents a potential infinite loop if we encounter an error | 75 // to the UI. This prevents a potential infinite loop if we encounter an error |
74 // while sending the log message to the UI. | 76 // while sending the log message to the UI. |
75 static bool g_logging_to_plugin = false; | 77 static bool g_logging_to_plugin = false; |
76 static HostNPScriptObject* g_logging_scriptable_object = NULL; | 78 static HostNPScriptObject* g_logging_scriptable_object = NULL; |
77 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL; | 79 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL; |
78 | 80 |
79 HostNPScriptObject::HostNPScriptObject(NPP plugin, NPObject* parent) | 81 HostNPScriptObject::HostNPScriptObject(NPP plugin, NPObject* parent) |
80 : plugin_(plugin), | 82 : plugin_(plugin), |
81 parent_(parent), | 83 parent_(parent), |
82 state_(kDisconnected), | 84 state_(kDisconnected), |
83 log_debug_info_func_(NULL), | |
84 on_state_changed_func_(NULL), | |
85 np_thread_id_(base::PlatformThread::CurrentId()), | 85 np_thread_id_(base::PlatformThread::CurrentId()), |
86 failed_login_attempts_(0), | 86 failed_login_attempts_(0), |
87 disconnected_event_(true, false), | 87 disconnected_event_(true, false), |
88 nat_traversal_enabled_(false), | 88 nat_traversal_enabled_(false), |
89 policy_received_(false) { | 89 policy_received_(false) { |
90 // Set up log message handler. | 90 // Set up log message handler. |
91 // Note that this approach doesn't quite support having multiple instances | 91 // Note that this approach doesn't quite support having multiple instances |
92 // of Chromoting running. In that case, the most recently opened tab will | 92 // of Chromoting running. In that case, the most recently opened tab will |
93 // grab all the debug log messages, and when any Chromoting tab is closed | 93 // grab all the debug log messages, and when any Chromoting tab is closed |
94 // the logging handler will go away. | 94 // the logging handler will go away. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 // here because |host_context_| needs to be stopped on the plugin | 128 // here because |host_context_| needs to be stopped on the plugin |
129 // thread, but the plugin thread may not exist after the instance | 129 // thread, but the plugin thread may not exist after the instance |
130 // is destroyed. | 130 // is destroyed. |
131 destructing_.Set(); | 131 destructing_.Set(); |
132 disconnected_event_.Reset(); | 132 disconnected_event_.Reset(); |
133 DisconnectInternal(); | 133 DisconnectInternal(); |
134 disconnected_event_.Wait(); | 134 disconnected_event_.Wait(); |
135 | 135 |
136 // Stop all threads. | 136 // Stop all threads. |
137 host_context_.Stop(); | 137 host_context_.Stop(); |
138 | |
139 if (log_debug_info_func_) { | |
140 g_npnetscape_funcs->releaseobject(log_debug_info_func_); | |
141 } | |
142 if (on_state_changed_func_) { | |
143 g_npnetscape_funcs->releaseobject(on_state_changed_func_); | |
144 } | |
145 } | 138 } |
146 | 139 |
147 bool HostNPScriptObject::Init() { | 140 bool HostNPScriptObject::Init() { |
148 VLOG(2) << "Init"; | 141 VLOG(2) << "Init"; |
149 // TODO(wez): This starts a bunch of threads, which might fail. | 142 // TODO(wez): This starts a bunch of threads, which might fail. |
150 host_context_.Start(); | 143 host_context_.Start(); |
151 nat_policy_.reset( | 144 nat_policy_.reset( |
152 policy_hack::NatPolicy::Create(host_context_.network_message_loop())); | 145 policy_hack::NatPolicy::Create(host_context_.network_message_loop())); |
153 nat_policy_->StartWatching( | 146 nat_policy_->StartWatching( |
154 base::Bind(&HostNPScriptObject::OnNatPolicyUpdate, | 147 base::Bind(&HostNPScriptObject::OnNatPolicyUpdate, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 } | 181 } |
189 } | 182 } |
190 | 183 |
191 bool HostNPScriptObject::HasProperty(const std::string& property_name) { | 184 bool HostNPScriptObject::HasProperty(const std::string& property_name) { |
192 VLOG(2) << "HasProperty " << property_name; | 185 VLOG(2) << "HasProperty " << property_name; |
193 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 186 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
194 return (property_name == kAttrNameAccessCode || | 187 return (property_name == kAttrNameAccessCode || |
195 property_name == kAttrNameAccessCodeLifetime || | 188 property_name == kAttrNameAccessCodeLifetime || |
196 property_name == kAttrNameClient || | 189 property_name == kAttrNameClient || |
197 property_name == kAttrNameState || | 190 property_name == kAttrNameState || |
| 191 property_name == kAttrNameLocalizeString || |
198 property_name == kAttrNameLogDebugInfo || | 192 property_name == kAttrNameLogDebugInfo || |
199 property_name == kAttrNameOnStateChanged || | 193 property_name == kAttrNameOnStateChanged || |
200 property_name == kAttrNameDisconnected || | 194 property_name == kAttrNameDisconnected || |
201 property_name == kAttrNameRequestedAccessCode || | 195 property_name == kAttrNameRequestedAccessCode || |
202 property_name == kAttrNameReceivedAccessCode || | 196 property_name == kAttrNameReceivedAccessCode || |
203 property_name == kAttrNameConnected || | 197 property_name == kAttrNameConnected || |
204 property_name == kAttrNameAffirmingConnection || | 198 property_name == kAttrNameAffirmingConnection || |
205 property_name == kAttrNameError); | 199 property_name == kAttrNameError); |
206 } | 200 } |
207 | 201 |
208 bool HostNPScriptObject::GetProperty(const std::string& property_name, | 202 bool HostNPScriptObject::GetProperty(const std::string& property_name, |
209 NPVariant* result) { | 203 NPVariant* result) { |
210 VLOG(2) << "GetProperty " << property_name; | 204 VLOG(2) << "GetProperty " << property_name; |
211 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 205 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
212 if (!result) { | 206 if (!result) { |
213 SetException("GetProperty: NULL result"); | 207 SetException("GetProperty: NULL result"); |
214 return false; | 208 return false; |
215 } | 209 } |
216 | 210 |
217 if (property_name == kAttrNameOnStateChanged) { | 211 if (property_name == kAttrNameOnStateChanged) { |
218 OBJECT_TO_NPVARIANT(on_state_changed_func_, *result); | 212 OBJECT_TO_NPVARIANT(on_state_changed_func_.get(), *result); |
| 213 return true; |
| 214 } else if (property_name == kAttrNameLocalizeString) { |
| 215 OBJECT_TO_NPVARIANT(localize_func_.get(), *result); |
219 return true; | 216 return true; |
220 } else if (property_name == kAttrNameLogDebugInfo) { | 217 } else if (property_name == kAttrNameLogDebugInfo) { |
221 OBJECT_TO_NPVARIANT(log_debug_info_func_, *result); | 218 OBJECT_TO_NPVARIANT(log_debug_info_func_.get(), *result); |
222 return true; | 219 return true; |
223 } else if (property_name == kAttrNameState) { | 220 } else if (property_name == kAttrNameState) { |
224 INT32_TO_NPVARIANT(state_, *result); | 221 INT32_TO_NPVARIANT(state_, *result); |
225 return true; | 222 return true; |
226 } else if (property_name == kAttrNameAccessCode) { | 223 } else if (property_name == kAttrNameAccessCode) { |
227 *result = NPVariantFromString(access_code_); | 224 *result = NPVariantFromString(access_code_); |
228 return true; | 225 return true; |
229 } else if (property_name == kAttrNameAccessCodeLifetime) { | 226 } else if (property_name == kAttrNameAccessCodeLifetime) { |
230 INT32_TO_NPVARIANT(access_code_lifetime_.InSeconds(), *result); | 227 INT32_TO_NPVARIANT(access_code_lifetime_.InSeconds(), *result); |
231 return true; | 228 return true; |
(...skipping 24 matching lines...) Expand all Loading... |
256 } | 253 } |
257 } | 254 } |
258 | 255 |
259 bool HostNPScriptObject::SetProperty(const std::string& property_name, | 256 bool HostNPScriptObject::SetProperty(const std::string& property_name, |
260 const NPVariant* value) { | 257 const NPVariant* value) { |
261 VLOG(2) << "SetProperty " << property_name; | 258 VLOG(2) << "SetProperty " << property_name; |
262 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 259 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
263 | 260 |
264 if (property_name == kAttrNameOnStateChanged) { | 261 if (property_name == kAttrNameOnStateChanged) { |
265 if (NPVARIANT_IS_OBJECT(*value)) { | 262 if (NPVARIANT_IS_OBJECT(*value)) { |
266 if (on_state_changed_func_) { | |
267 g_npnetscape_funcs->releaseobject(on_state_changed_func_); | |
268 } | |
269 on_state_changed_func_ = NPVARIANT_TO_OBJECT(*value); | 263 on_state_changed_func_ = NPVARIANT_TO_OBJECT(*value); |
270 if (on_state_changed_func_) { | |
271 g_npnetscape_funcs->retainobject(on_state_changed_func_); | |
272 } | |
273 return true; | 264 return true; |
274 } else { | 265 } else { |
275 SetException("SetProperty: unexpected type for property " + | 266 SetException("SetProperty: unexpected type for property " + |
| 267 property_name); |
| 268 } |
| 269 return false; |
| 270 } |
| 271 |
| 272 if (property_name == kAttrNameLocalizeString) { |
| 273 if (NPVARIANT_IS_OBJECT(*value)) { |
| 274 localize_func_ = NPVARIANT_TO_OBJECT(*value); |
| 275 return true; |
| 276 } else { |
| 277 SetException("SetProperty: unexpected type for property " + |
276 property_name); | 278 property_name); |
277 } | 279 } |
278 return false; | 280 return false; |
279 } | 281 } |
280 | 282 |
281 if (property_name == kAttrNameLogDebugInfo) { | 283 if (property_name == kAttrNameLogDebugInfo) { |
282 if (NPVARIANT_IS_OBJECT(*value)) { | 284 if (NPVARIANT_IS_OBJECT(*value)) { |
283 if (log_debug_info_func_) { | |
284 g_npnetscape_funcs->releaseobject(log_debug_info_func_); | |
285 } | |
286 log_debug_info_func_ = NPVARIANT_TO_OBJECT(*value); | 285 log_debug_info_func_ = NPVARIANT_TO_OBJECT(*value); |
287 if (log_debug_info_func_) { | |
288 g_npnetscape_funcs->retainobject(log_debug_info_func_); | |
289 } | |
290 return true; | 286 return true; |
291 } else { | 287 } else { |
292 SetException("SetProperty: unexpected type for property " + | 288 SetException("SetProperty: unexpected type for property " + |
293 property_name); | 289 property_name); |
294 } | 290 } |
295 return false; | 291 return false; |
296 } | 292 } |
297 | 293 |
298 return false; | 294 return false; |
299 } | 295 } |
300 | 296 |
301 bool HostNPScriptObject::RemoveProperty(const std::string& property_name) { | 297 bool HostNPScriptObject::RemoveProperty(const std::string& property_name) { |
302 VLOG(2) << "RemoveProperty " << property_name; | 298 VLOG(2) << "RemoveProperty " << property_name; |
303 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 299 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
304 return false; | 300 return false; |
305 } | 301 } |
306 | 302 |
307 bool HostNPScriptObject::Enumerate(std::vector<std::string>* values) { | 303 bool HostNPScriptObject::Enumerate(std::vector<std::string>* values) { |
308 VLOG(2) << "Enumerate"; | 304 VLOG(2) << "Enumerate"; |
309 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 305 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
310 const char* entries[] = { | 306 const char* entries[] = { |
311 kAttrNameAccessCode, | 307 kAttrNameAccessCode, |
312 kAttrNameState, | 308 kAttrNameState, |
| 309 kAttrNameLocalizeString, |
313 kAttrNameLogDebugInfo, | 310 kAttrNameLogDebugInfo, |
314 kAttrNameOnStateChanged, | 311 kAttrNameOnStateChanged, |
315 kFuncNameConnect, | 312 kFuncNameConnect, |
316 kFuncNameDisconnect, | 313 kFuncNameDisconnect, |
317 kAttrNameDisconnected, | 314 kAttrNameDisconnected, |
318 kAttrNameRequestedAccessCode, | 315 kAttrNameRequestedAccessCode, |
319 kAttrNameReceivedAccessCode, | 316 kAttrNameReceivedAccessCode, |
320 kAttrNameConnected, | 317 kAttrNameConnected, |
321 kAttrNameAffirmingConnection, | 318 kAttrNameAffirmingConnection, |
322 kAttrNameError | 319 kAttrNameError |
(...skipping 20 matching lines...) Expand all Loading... |
343 } | 340 } |
344 | 341 |
345 void HostNPScriptObject::OnClientAuthenticated( | 342 void HostNPScriptObject::OnClientAuthenticated( |
346 remoting::protocol::ConnectionToClient* client) { | 343 remoting::protocol::ConnectionToClient* client) { |
347 DCHECK_NE(base::PlatformThread::CurrentId(), np_thread_id_); | 344 DCHECK_NE(base::PlatformThread::CurrentId(), np_thread_id_); |
348 client_username_ = client->session()->jid(); | 345 client_username_ = client->session()->jid(); |
349 size_t pos = client_username_.find('/'); | 346 size_t pos = client_username_.find('/'); |
350 if (pos != std::string::npos) | 347 if (pos != std::string::npos) |
351 client_username_.replace(pos, std::string::npos, ""); | 348 client_username_.replace(pos, std::string::npos, ""); |
352 LOG(INFO) << "Client " << client_username_ << " connected."; | 349 LOG(INFO) << "Client " << client_username_ << " connected."; |
| 350 LocalizeStrings(); |
353 OnStateChanged(kConnected); | 351 OnStateChanged(kConnected); |
354 } | 352 } |
355 | 353 |
356 void HostNPScriptObject::OnClientDisconnected( | 354 void HostNPScriptObject::OnClientDisconnected( |
357 remoting::protocol::ConnectionToClient* client) { | 355 remoting::protocol::ConnectionToClient* client) { |
358 client_username_.clear(); | 356 client_username_.clear(); |
359 OnStateChanged(kDisconnected); | 357 OnStateChanged(kDisconnected); |
360 } | 358 } |
361 | 359 |
362 void HostNPScriptObject::OnShutdown() { | 360 void HostNPScriptObject::OnShutdown() { |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 if (destructing_.IsSet()) | 580 if (destructing_.IsSet()) |
583 return; | 581 return; |
584 | 582 |
585 if (!host_context_.IsUIThread()) { | 583 if (!host_context_.IsUIThread()) { |
586 host_context_.PostTaskToUIThread( | 584 host_context_.PostTaskToUIThread( |
587 FROM_HERE, base::Bind(&HostNPScriptObject::OnStateChanged, | 585 FROM_HERE, base::Bind(&HostNPScriptObject::OnStateChanged, |
588 base::Unretained(this), state)); | 586 base::Unretained(this), state)); |
589 return; | 587 return; |
590 } | 588 } |
591 state_ = state; | 589 state_ = state; |
592 if (on_state_changed_func_) { | 590 if (on_state_changed_func_.get()) { |
593 VLOG(2) << "Calling state changed " << state; | 591 VLOG(2) << "Calling state changed " << state; |
594 bool is_good = InvokeAndIgnoreResult(on_state_changed_func_, NULL, 0); | 592 bool is_good = InvokeAndIgnoreResult(on_state_changed_func_.get(), NULL, 0); |
595 LOG_IF(ERROR, !is_good) << "OnStateChanged failed"; | 593 LOG_IF(ERROR, !is_good) << "OnStateChanged failed"; |
596 } | 594 } |
597 } | 595 } |
598 | 596 |
599 // static | 597 // static |
600 bool HostNPScriptObject::LogToUI(int severity, const char* file, int line, | 598 bool HostNPScriptObject::LogToUI(int severity, const char* file, int line, |
601 size_t message_start, | 599 size_t message_start, |
602 const std::string& str) { | 600 const std::string& str) { |
603 // The |g_logging_to_plugin| check is to prevent logging to the scriptable | 601 // The |g_logging_to_plugin| check is to prevent logging to the scriptable |
604 // object if we're already in the middle of logging. | 602 // object if we're already in the middle of logging. |
(...skipping 15 matching lines...) Expand all Loading... |
620 if (destructing_.IsSet()) | 618 if (destructing_.IsSet()) |
621 return; | 619 return; |
622 | 620 |
623 if (!host_context_.IsUIThread()) { | 621 if (!host_context_.IsUIThread()) { |
624 host_context_.PostTaskToUIThread( | 622 host_context_.PostTaskToUIThread( |
625 FROM_HERE, base::Bind(&HostNPScriptObject::LogDebugInfo, | 623 FROM_HERE, base::Bind(&HostNPScriptObject::LogDebugInfo, |
626 base::Unretained(this), message)); | 624 base::Unretained(this), message)); |
627 return; | 625 return; |
628 } | 626 } |
629 | 627 |
630 if (log_debug_info_func_) { | 628 if (log_debug_info_func_.get()) { |
631 NPVariant log_message; | 629 NPVariant log_message; |
632 STRINGZ_TO_NPVARIANT(message.c_str(), log_message); | 630 STRINGZ_TO_NPVARIANT(message.c_str(), log_message); |
633 bool is_good = InvokeAndIgnoreResult(log_debug_info_func_, | 631 bool is_good = InvokeAndIgnoreResult(log_debug_info_func_.get(), |
634 &log_message, 1); | 632 &log_message, 1); |
635 LOG_IF(ERROR, !is_good) << "LogDebugInfo failed"; | 633 LOG_IF(ERROR, !is_good) << "LogDebugInfo failed"; |
636 } | 634 } |
637 } | 635 } |
638 | 636 |
639 void HostNPScriptObject::SetException(const std::string& exception_string) { | 637 void HostNPScriptObject::SetException(const std::string& exception_string) { |
640 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 638 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
641 g_npnetscape_funcs->setexception(parent_, exception_string.c_str()); | 639 g_npnetscape_funcs->setexception(parent_, exception_string.c_str()); |
642 LOG(INFO) << exception_string; | 640 LOG(INFO) << exception_string; |
643 } | 641 } |
644 | 642 |
| 643 void HostNPScriptObject::LocalizeStrings() { |
| 644 UiStrings* ui_strings = host_->ui_strings(); |
| 645 std::string direction; |
| 646 LocalizeString("@@bidi_dir", NULL, &direction); |
| 647 ui_strings->direction = |
| 648 direction == "rtl" ? remoting::UiStrings::RTL |
| 649 : remoting::UiStrings::LTR; |
| 650 LocalizeString("productName", NULL, &ui_strings->product_name); |
| 651 LocalizeString("disconnectButton", NULL, &ui_strings->disconnect_button_text); |
| 652 LocalizeString( |
| 653 #if defined(OS_WIN) |
| 654 "disconnectButtonPlusShortcutWindows", |
| 655 #elif defined(OS_MAC) |
| 656 "disconnectButtonPlusShortcutMacOSX", |
| 657 #else |
| 658 "disconnectButtonPlusShortcutLinux", |
| 659 #endif |
| 660 NULL, &ui_strings->disconnect_button_text_plus_shortcut); |
| 661 LocalizeString("continuePrompt", NULL, &ui_strings->continue_prompt); |
| 662 LocalizeString("continueButton", NULL, &ui_strings->continue_button_text); |
| 663 LocalizeString("stopSharingButton", NULL, |
| 664 &ui_strings->stop_sharing_button_text); |
| 665 LocalizeString("messageShared", client_username_.c_str(), |
| 666 &ui_strings->disconnect_message); |
| 667 } |
| 668 |
| 669 bool HostNPScriptObject::LocalizeString(const char* tag, |
| 670 const char* substitution, |
| 671 std::string* result) { |
| 672 NPVariant args[2]; |
| 673 STRINGZ_TO_NPVARIANT(tag, args[0]); |
| 674 int arg_count = 1; |
| 675 if (substitution) { |
| 676 STRINGZ_TO_NPVARIANT(substitution, args[1]); |
| 677 ++arg_count; |
| 678 } |
| 679 NPVariant np_result; |
| 680 bool is_good = g_npnetscape_funcs->invokeDefault( |
| 681 plugin_, localize_func_.get(), &args[0], arg_count, &np_result); |
| 682 if (!is_good) { |
| 683 LOG(ERROR) << "Localization failed for " << tag; |
| 684 return false; |
| 685 } |
| 686 std::string translation = StringFromNPVariant(np_result); |
| 687 g_npnetscape_funcs->releasevariantvalue(&np_result); |
| 688 if (translation.empty()) { |
| 689 LOG(ERROR) << "Missing translation for " << tag; |
| 690 return false; |
| 691 } |
| 692 *result = translation; |
| 693 return true; |
| 694 } |
| 695 |
645 bool HostNPScriptObject::InvokeAndIgnoreResult(NPObject* func, | 696 bool HostNPScriptObject::InvokeAndIgnoreResult(NPObject* func, |
646 const NPVariant* args, | 697 const NPVariant* args, |
647 uint32_t argCount) { | 698 uint32_t argCount) { |
648 NPVariant np_result; | 699 NPVariant np_result; |
649 bool is_good = g_npnetscape_funcs->invokeDefault(plugin_, func, args, | 700 bool is_good = g_npnetscape_funcs->invokeDefault(plugin_, func, args, |
650 argCount, &np_result); | 701 argCount, &np_result); |
651 if (is_good) | 702 if (is_good) |
652 g_npnetscape_funcs->releasevariantvalue(&np_result); | 703 g_npnetscape_funcs->releasevariantvalue(&np_result); |
653 return is_good; | 704 return is_good; |
654 } | 705 } |
(...skipping 13 matching lines...) Expand all Loading... |
668 } | 719 } |
669 | 720 |
670 // static | 721 // static |
671 void HostNPScriptObject::NPTaskSpringboard(void* task) { | 722 void HostNPScriptObject::NPTaskSpringboard(void* task) { |
672 base::Closure* real_task = reinterpret_cast<base::Closure*>(task); | 723 base::Closure* real_task = reinterpret_cast<base::Closure*>(task); |
673 real_task->Run(); | 724 real_task->Run(); |
674 delete real_task; | 725 delete real_task; |
675 } | 726 } |
676 | 727 |
677 } // namespace remoting | 728 } // namespace remoting |
OLD | NEW |