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/sys_string_conversions.h" | 10 #include "base/sys_string_conversions.h" |
11 #include "base/threading/platform_thread.h" | 11 #include "base/threading/platform_thread.h" |
12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
13 #include "remoting/base/auth_token_util.h" | 13 #include "remoting/base/auth_token_util.h" |
14 #include "remoting/base/util.h" | |
15 #include "remoting/host/chromoting_host.h" | 14 #include "remoting/host/chromoting_host.h" |
16 #include "remoting/host/chromoting_host_context.h" | 15 #include "remoting/host/chromoting_host_context.h" |
17 #include "remoting/host/desktop_environment.h" | 16 #include "remoting/host/desktop_environment.h" |
18 #include "remoting/host/host_config.h" | 17 #include "remoting/host/host_config.h" |
19 #include "remoting/host/host_key_pair.h" | 18 #include "remoting/host/host_key_pair.h" |
20 #include "remoting/host/in_memory_host_config.h" | 19 #include "remoting/host/in_memory_host_config.h" |
20 #include "remoting/host/plugin/host_log_handler.h" | |
21 #include "remoting/host/plugin/policy_hack/nat_policy.h" | 21 #include "remoting/host/plugin/policy_hack/nat_policy.h" |
22 #include "remoting/host/register_support_host_request.h" | 22 #include "remoting/host/register_support_host_request.h" |
23 #include "remoting/host/support_access_verifier.h" | 23 #include "remoting/host/support_access_verifier.h" |
24 #include "remoting/host/ui_strings.h" | 24 #include "remoting/host/ui_strings.h" |
25 | 25 |
26 namespace remoting { | 26 namespace remoting { |
27 | 27 |
28 // Supported Javascript interface: | 28 // Supported Javascript interface: |
29 // readonly attribute string accessCode; | 29 // readonly attribute string accessCode; |
30 // readonly attribute int accessCodeLifetime; | 30 // readonly attribute int accessCodeLifetime; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 const char* kAttrNameRequestedAccessCode = "REQUESTED_ACCESS_CODE"; | 66 const char* kAttrNameRequestedAccessCode = "REQUESTED_ACCESS_CODE"; |
67 const char* kAttrNameReceivedAccessCode = "RECEIVED_ACCESS_CODE"; | 67 const char* kAttrNameReceivedAccessCode = "RECEIVED_ACCESS_CODE"; |
68 const char* kAttrNameConnected = "CONNECTED"; | 68 const char* kAttrNameConnected = "CONNECTED"; |
69 const char* kAttrNameAffirmingConnection = "AFFIRMING_CONNECTION"; | 69 const char* kAttrNameAffirmingConnection = "AFFIRMING_CONNECTION"; |
70 const char* kAttrNameError = "ERROR"; | 70 const char* kAttrNameError = "ERROR"; |
71 | 71 |
72 const int kMaxLoginAttempts = 5; | 72 const int kMaxLoginAttempts = 5; |
73 | 73 |
74 } // namespace | 74 } // namespace |
75 | 75 |
76 // This flag blocks LOGs to the UI if we're already in the middle of logging | |
77 // to the UI. This prevents a potential infinite loop if we encounter an error | |
78 // while sending the log message to the UI. | |
79 static bool g_logging_to_plugin = false; | |
80 static HostNPScriptObject* g_logging_scriptable_object = NULL; | |
81 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL; | |
82 | |
83 HostNPScriptObject::HostNPScriptObject( | 76 HostNPScriptObject::HostNPScriptObject( |
84 NPP plugin, | 77 NPP plugin, |
85 NPObject* parent, | 78 NPObject* parent, |
86 PluginMessageLoopProxy::Delegate* plugin_thread_delegate) | 79 PluginMessageLoopProxy::Delegate* plugin_thread_delegate) |
87 : plugin_(plugin), | 80 : plugin_(plugin), |
88 parent_(parent), | 81 parent_(parent), |
89 state_(kDisconnected), | 82 state_(kDisconnected), |
90 np_thread_id_(base::PlatformThread::CurrentId()), | 83 np_thread_id_(base::PlatformThread::CurrentId()), |
91 plugin_message_loop_proxy_( | 84 plugin_message_loop_proxy_( |
92 new PluginMessageLoopProxy(plugin_thread_delegate)), | 85 new PluginMessageLoopProxy(plugin_thread_delegate)), |
93 host_context_(plugin_message_loop_proxy_), | 86 host_context_(plugin_message_loop_proxy_), |
94 failed_login_attempts_(0), | 87 failed_login_attempts_(0), |
95 disconnected_event_(true, false), | 88 disconnected_event_(true, false), |
96 nat_traversal_enabled_(false), | 89 nat_traversal_enabled_(false), |
97 policy_received_(false) { | 90 policy_received_(false) { |
98 // Set up log message handler. | |
99 // Note that this approach doesn't quite support having multiple instances | |
100 // of Chromoting running. In that case, the most recently opened tab will | |
101 // grab all the debug log messages, and when any Chromoting tab is closed | |
102 // the logging handler will go away. | |
103 // Since having multiple Chromoting tabs is not a primary use case, and this | |
104 // is just debug logging, we're punting improving debug log support for that | |
105 // case. | |
106 if (g_logging_old_handler == NULL) | |
107 g_logging_old_handler = logging::GetLogMessageHandler(); | |
108 logging::SetLogMessageHandler(&LogToUI); | |
109 g_logging_scriptable_object = this; | |
110 } | 91 } |
111 | 92 |
112 HostNPScriptObject::~HostNPScriptObject() { | 93 HostNPScriptObject::~HostNPScriptObject() { |
113 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 94 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
114 | 95 |
115 // Shutdown DesktopEnvironment first so that it doesn't try to post | 96 // Shutdown DesktopEnvironment first so that it doesn't try to post |
116 // tasks on the UI thread while we are stopping the host. | 97 // tasks on the UI thread while we are stopping the host. |
117 desktop_environment_->Shutdown(); | 98 desktop_environment_->Shutdown(); |
118 | 99 |
119 logging::SetLogMessageHandler(g_logging_old_handler); | 100 HostLogHandler::UnregisterLoggingScriptObject(this); |
120 g_logging_old_handler = NULL; | |
121 g_logging_scriptable_object = NULL; | |
122 | 101 |
123 plugin_message_loop_proxy_->Detach(); | 102 plugin_message_loop_proxy_->Detach(); |
124 | 103 |
125 // Stop listening for policy updates. | 104 // Stop listening for policy updates. |
126 if (nat_policy_.get()) { | 105 if (nat_policy_.get()) { |
127 base::WaitableEvent nat_policy_stopped_(true, false); | 106 base::WaitableEvent nat_policy_stopped_(true, false); |
128 nat_policy_->StopWatching(&nat_policy_stopped_); | 107 nat_policy_->StopWatching(&nat_policy_stopped_); |
129 nat_policy_stopped_.Wait(); | 108 nat_policy_stopped_.Wait(); |
130 nat_policy_.reset(); | 109 nat_policy_.reset(); |
131 } | 110 } |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
281 } else { | 260 } else { |
282 SetException("SetProperty: unexpected type for property " + | 261 SetException("SetProperty: unexpected type for property " + |
283 property_name); | 262 property_name); |
284 } | 263 } |
285 return false; | 264 return false; |
286 } | 265 } |
287 | 266 |
288 if (property_name == kAttrNameLogDebugInfo) { | 267 if (property_name == kAttrNameLogDebugInfo) { |
289 if (NPVARIANT_IS_OBJECT(*value)) { | 268 if (NPVARIANT_IS_OBJECT(*value)) { |
290 log_debug_info_func_ = NPVARIANT_TO_OBJECT(*value); | 269 log_debug_info_func_ = NPVARIANT_TO_OBJECT(*value); |
270 HostLogHandler::RegisterLoggingScriptObject(this); | |
291 return true; | 271 return true; |
292 } else { | 272 } else { |
293 SetException("SetProperty: unexpected type for property " + | 273 SetException("SetProperty: unexpected type for property " + |
294 property_name); | 274 property_name); |
295 } | 275 } |
296 return false; | 276 return false; |
297 } | 277 } |
298 | 278 |
299 return false; | 279 return false; |
300 } | 280 } |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
595 return; | 575 return; |
596 } | 576 } |
597 state_ = state; | 577 state_ = state; |
598 if (on_state_changed_func_.get()) { | 578 if (on_state_changed_func_.get()) { |
599 VLOG(2) << "Calling state changed " << state; | 579 VLOG(2) << "Calling state changed " << state; |
600 bool is_good = InvokeAndIgnoreResult(on_state_changed_func_.get(), NULL, 0); | 580 bool is_good = InvokeAndIgnoreResult(on_state_changed_func_.get(), NULL, 0); |
601 LOG_IF(ERROR, !is_good) << "OnStateChanged failed"; | 581 LOG_IF(ERROR, !is_good) << "OnStateChanged failed"; |
602 } | 582 } |
603 } | 583 } |
604 | 584 |
605 // static | 585 void HostNPScriptObject::PostLogDebugInfo(const std::string& message) { |
606 bool HostNPScriptObject::LogToUI(int severity, const char* file, int line, | 586 // Always post (even if we're already on the correct thread) so that debug |
607 size_t message_start, | 587 // log messages aren't shown out of order. |
608 const std::string& str) { | 588 plugin_message_loop_proxy_->PostTask( |
609 // The |g_logging_to_plugin| check is to prevent logging to the scriptable | 589 FROM_HERE, base::Bind(&HostNPScriptObject::LogDebugInfo, |
610 // object if we're already in the middle of logging. | 590 base::Unretained(this), message)); |
611 // This can occur if we try to log an error while we're in the scriptable | |
612 // object logging code. | |
613 if (g_logging_scriptable_object && !g_logging_to_plugin) { | |
614 g_logging_to_plugin = true; | |
615 std::string message = remoting::GetTimestampString(); | |
616 message += (str.c_str() + message_start); | |
617 g_logging_scriptable_object->LogDebugInfo(message); | |
618 g_logging_to_plugin = false; | |
619 } | |
620 if (g_logging_old_handler) | |
621 return (g_logging_old_handler)(severity, file, line, message_start, str); | |
622 return false; | |
623 } | 591 } |
624 | 592 |
625 void HostNPScriptObject::LogDebugInfo(const std::string& message) { | 593 void HostNPScriptObject::LogDebugInfo(const std::string& message) { |
626 if (!plugin_message_loop_proxy_->BelongsToCurrentThread()) { | |
627 plugin_message_loop_proxy_->PostTask( | |
628 FROM_HERE, base::Bind(&HostNPScriptObject::LogDebugInfo, | |
629 base::Unretained(this), message)); | |
630 return; | |
631 } | |
632 | |
633 if (log_debug_info_func_.get()) { | 594 if (log_debug_info_func_.get()) { |
634 NPVariant log_message; | 595 NPVariant log_message; |
635 STRINGZ_TO_NPVARIANT(message.c_str(), log_message); | 596 STRINGZ_TO_NPVARIANT(message.c_str(), log_message); |
636 bool is_good = InvokeAndIgnoreResult(log_debug_info_func_.get(), | 597 bool is_good = InvokeAndIgnoreResult(log_debug_info_func_.get(), |
637 &log_message, 1); | 598 &log_message, 1); |
638 LOG_IF(ERROR, !is_good) << "LogDebugInfo failed"; | 599 if (!is_good) { |
600 // Note that we can't use LOG here because we're currently in the middle | |
601 // of handling a LOG message. | |
602 printf("ERROR - LogDebugInfo failed\n"); | |
Wez
2011/08/30 05:20:02
If we place a check around the invokation to prote
garykac
2011/08/31 00:59:00
Our log message handler is asynchronous, so any fl
| |
603 } | |
639 } | 604 } |
640 } | 605 } |
641 | 606 |
642 void HostNPScriptObject::SetException(const std::string& exception_string) { | 607 void HostNPScriptObject::SetException(const std::string& exception_string) { |
643 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 608 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
644 g_npnetscape_funcs->setexception(parent_, exception_string.c_str()); | 609 g_npnetscape_funcs->setexception(parent_, exception_string.c_str()); |
645 LOG(INFO) << exception_string; | 610 LOG(INFO) << exception_string; |
646 } | 611 } |
647 | 612 |
648 void HostNPScriptObject::LocalizeStrings() { | 613 void HostNPScriptObject::LocalizeStrings() { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
700 uint32_t argCount) { | 665 uint32_t argCount) { |
701 NPVariant np_result; | 666 NPVariant np_result; |
702 bool is_good = g_npnetscape_funcs->invokeDefault(plugin_, func, args, | 667 bool is_good = g_npnetscape_funcs->invokeDefault(plugin_, func, args, |
703 argCount, &np_result); | 668 argCount, &np_result); |
704 if (is_good) | 669 if (is_good) |
705 g_npnetscape_funcs->releasevariantvalue(&np_result); | 670 g_npnetscape_funcs->releasevariantvalue(&np_result); |
706 return is_good; | 671 return is_good; |
707 } | 672 } |
708 | 673 |
709 } // namespace remoting | 674 } // namespace remoting |
OLD | NEW |