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 | 24 |
25 namespace remoting { | 25 namespace remoting { |
26 | 26 |
27 // Supported Javascript interface: | 27 // Supported Javascript interface: |
28 // readonly attribute string accessCode; | 28 // readonly attribute string accessCode; |
29 // readonly attribute int accessCodeLifetime; | 29 // readonly attribute int accessCodeLifetime; |
30 // readonly attribute string client; | 30 // readonly attribute string client; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 const char* kAttrNameRequestedAccessCode = "REQUESTED_ACCESS_CODE"; | 65 const char* kAttrNameRequestedAccessCode = "REQUESTED_ACCESS_CODE"; |
66 const char* kAttrNameReceivedAccessCode = "RECEIVED_ACCESS_CODE"; | 66 const char* kAttrNameReceivedAccessCode = "RECEIVED_ACCESS_CODE"; |
67 const char* kAttrNameConnected = "CONNECTED"; | 67 const char* kAttrNameConnected = "CONNECTED"; |
68 const char* kAttrNameAffirmingConnection = "AFFIRMING_CONNECTION"; | 68 const char* kAttrNameAffirmingConnection = "AFFIRMING_CONNECTION"; |
69 const char* kAttrNameError = "ERROR"; | 69 const char* kAttrNameError = "ERROR"; |
70 | 70 |
71 const int kMaxLoginAttempts = 5; | 71 const int kMaxLoginAttempts = 5; |
72 | 72 |
73 } // namespace | 73 } // namespace |
74 | 74 |
75 // This flag blocks LOGs to the UI if we're already in the middle of logging | |
76 // to the UI. This prevents a potential infinite loop if we encounter an error | |
77 // while sending the log message to the UI. | |
78 static bool g_logging_to_plugin = false; | |
79 static HostNPScriptObject* g_logging_scriptable_object = NULL; | |
80 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL; | |
81 | |
82 HostNPScriptObject::HostNPScriptObject( | 75 HostNPScriptObject::HostNPScriptObject( |
83 NPP plugin, | 76 NPP plugin, |
84 NPObject* parent, | 77 NPObject* parent, |
85 PluginMessageLoopProxy::Delegate* plugin_thread_delegate) | 78 PluginMessageLoopProxy::Delegate* plugin_thread_delegate) |
86 : plugin_(plugin), | 79 : plugin_(plugin), |
87 parent_(parent), | 80 parent_(parent), |
88 state_(kDisconnected), | 81 state_(kDisconnected), |
89 np_thread_id_(base::PlatformThread::CurrentId()), | 82 np_thread_id_(base::PlatformThread::CurrentId()), |
90 plugin_message_loop_proxy_( | 83 plugin_message_loop_proxy_( |
91 new PluginMessageLoopProxy(plugin_thread_delegate)), | 84 new PluginMessageLoopProxy(plugin_thread_delegate)), |
92 host_context_(plugin_message_loop_proxy_), | 85 host_context_(plugin_message_loop_proxy_), |
93 failed_login_attempts_(0), | 86 failed_login_attempts_(0), |
94 disconnected_event_(true, false), | 87 disconnected_event_(true, false), |
95 nat_traversal_enabled_(false), | 88 nat_traversal_enabled_(false), |
96 policy_received_(false) { | 89 policy_received_(false) { |
97 // Set up log message handler. | |
98 // Note that this approach doesn't quite support having multiple instances | |
99 // of Chromoting running. In that case, the most recently opened tab will | |
100 // grab all the debug log messages, and when any Chromoting tab is closed | |
101 // the logging handler will go away. | |
102 // Since having multiple Chromoting tabs is not a primary use case, and this | |
103 // is just debug logging, we're punting improving debug log support for that | |
104 // case. | |
105 if (g_logging_old_handler == NULL) | |
106 g_logging_old_handler = logging::GetLogMessageHandler(); | |
107 logging::SetLogMessageHandler(&LogToUI); | |
108 g_logging_scriptable_object = this; | |
109 } | 90 } |
110 | 91 |
111 HostNPScriptObject::~HostNPScriptObject() { | 92 HostNPScriptObject::~HostNPScriptObject() { |
112 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 93 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
113 | 94 |
114 // Shutdown DesktopEnvironment first so that it doesn't try to post | 95 // Shutdown DesktopEnvironment first so that it doesn't try to post |
115 // tasks on the UI thread while we are stopping the host. | 96 // tasks on the UI thread while we are stopping the host. |
116 desktop_environment_->Shutdown(); | 97 desktop_environment_->Shutdown(); |
117 | 98 |
118 logging::SetLogMessageHandler(g_logging_old_handler); | 99 HostLogHandler::UnregisterLoggingScriptObject(this); |
119 g_logging_old_handler = NULL; | |
120 g_logging_scriptable_object = NULL; | |
121 | 100 |
122 plugin_message_loop_proxy_->Detach(); | 101 plugin_message_loop_proxy_->Detach(); |
123 | 102 |
124 // Stop listening for policy updates. | 103 // Stop listening for policy updates. |
125 if (nat_policy_.get()) { | 104 if (nat_policy_.get()) { |
126 base::WaitableEvent nat_policy_stopped_(true, false); | 105 base::WaitableEvent nat_policy_stopped_(true, false); |
127 nat_policy_->StopWatching(&nat_policy_stopped_); | 106 nat_policy_->StopWatching(&nat_policy_stopped_); |
128 nat_policy_stopped_.Wait(); | 107 nat_policy_stopped_.Wait(); |
129 nat_policy_.reset(); | 108 nat_policy_.reset(); |
130 } | 109 } |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
268 } else { | 247 } else { |
269 SetException("SetProperty: unexpected type for property " + | 248 SetException("SetProperty: unexpected type for property " + |
270 property_name); | 249 property_name); |
271 } | 250 } |
272 return false; | 251 return false; |
273 } | 252 } |
274 | 253 |
275 if (property_name == kAttrNameLogDebugInfo) { | 254 if (property_name == kAttrNameLogDebugInfo) { |
276 if (NPVARIANT_IS_OBJECT(*value)) { | 255 if (NPVARIANT_IS_OBJECT(*value)) { |
277 log_debug_info_func_ = NPVARIANT_TO_OBJECT(*value); | 256 log_debug_info_func_ = NPVARIANT_TO_OBJECT(*value); |
257 HostLogHandler::RegisterLoggingScriptObject(this); | |
278 return true; | 258 return true; |
279 } else { | 259 } else { |
280 SetException("SetProperty: unexpected type for property " + | 260 SetException("SetProperty: unexpected type for property " + |
281 property_name); | 261 property_name); |
282 } | 262 } |
283 return false; | 263 return false; |
284 } | 264 } |
285 | 265 |
286 return false; | 266 return false; |
287 } | 267 } |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
604 return; | 584 return; |
605 } | 585 } |
606 state_ = state; | 586 state_ = state; |
607 if (on_state_changed_func_.get()) { | 587 if (on_state_changed_func_.get()) { |
608 VLOG(2) << "Calling state changed " << state; | 588 VLOG(2) << "Calling state changed " << state; |
609 bool is_good = InvokeAndIgnoreResult(on_state_changed_func_.get(), NULL, 0); | 589 bool is_good = InvokeAndIgnoreResult(on_state_changed_func_.get(), NULL, 0); |
610 LOG_IF(ERROR, !is_good) << "OnStateChanged failed"; | 590 LOG_IF(ERROR, !is_good) << "OnStateChanged failed"; |
611 } | 591 } |
612 } | 592 } |
613 | 593 |
614 // static | 594 void HostNPScriptObject::PostLogDebugInfo(const std::string& message) { |
615 bool HostNPScriptObject::LogToUI(int severity, const char* file, int line, | 595 // Always post (even if we're already on the correct thread) so that debug |
616 size_t message_start, | 596 // log messages aren't shown out of order. |
617 const std::string& str) { | 597 plugin_message_loop_proxy_->PostTask( |
618 // The |g_logging_to_plugin| check is to prevent logging to the scriptable | 598 FROM_HERE, base::Bind(&HostNPScriptObject::LogDebugInfo, |
619 // object if we're already in the middle of logging. | 599 base::Unretained(this), message)); |
620 // This can occur if we try to log an error while we're in the scriptable | |
621 // object logging code. | |
622 if (g_logging_scriptable_object && !g_logging_to_plugin) { | |
623 g_logging_to_plugin = true; | |
624 std::string message = remoting::GetTimestampString(); | |
625 message += (str.c_str() + message_start); | |
626 g_logging_scriptable_object->LogDebugInfo(message); | |
627 g_logging_to_plugin = false; | |
628 } | |
629 if (g_logging_old_handler) | |
630 return (g_logging_old_handler)(severity, file, line, message_start, str); | |
631 return false; | |
632 } | 600 } |
633 | 601 |
634 void HostNPScriptObject::LogDebugInfo(const std::string& message) { | 602 void HostNPScriptObject::LogDebugInfo(const std::string& message) { |
635 if (!plugin_message_loop_proxy_->BelongsToCurrentThread()) { | |
636 plugin_message_loop_proxy_->PostTask( | |
637 FROM_HERE, base::Bind(&HostNPScriptObject::LogDebugInfo, | |
638 base::Unretained(this), message)); | |
639 return; | |
640 } | |
641 | |
642 if (log_debug_info_func_.get()) { | 603 if (log_debug_info_func_.get()) { |
643 NPVariant log_message; | 604 NPVariant log_message; |
644 STRINGZ_TO_NPVARIANT(message.c_str(), log_message); | 605 STRINGZ_TO_NPVARIANT(message.c_str(), log_message); |
645 bool is_good = InvokeAndIgnoreResult(log_debug_info_func_.get(), | 606 bool is_good = InvokeAndIgnoreResult(log_debug_info_func_.get(), |
646 &log_message, 1); | 607 &log_message, 1); |
647 LOG_IF(ERROR, !is_good) << "LogDebugInfo failed"; | 608 if (!is_good) { |
609 // Note that we can't use LOG here because we're currently in the middle | |
610 // of handling a LOG message. | |
611 printf("ERROR - LogDebugInfo failed\n"); | |
Wez
2011/08/31 01:30:16
We could LOG if we have a boolean member of HostNP
garykac
2011/08/31 23:59:46
We'd have to only read the flag when we're on the
| |
612 } | |
648 } | 613 } |
649 } | 614 } |
650 | 615 |
651 void HostNPScriptObject::SetException(const std::string& exception_string) { | 616 void HostNPScriptObject::SetException(const std::string& exception_string) { |
652 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); | 617 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); |
653 g_npnetscape_funcs->setexception(parent_, exception_string.c_str()); | 618 g_npnetscape_funcs->setexception(parent_, exception_string.c_str()); |
654 LOG(INFO) << exception_string; | 619 LOG(INFO) << exception_string; |
655 } | 620 } |
656 | 621 |
657 void HostNPScriptObject::LocalizeStrings(NPObject* localize_func) { | 622 void HostNPScriptObject::LocalizeStrings(NPObject* localize_func) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
714 uint32_t argCount) { | 679 uint32_t argCount) { |
715 NPVariant np_result; | 680 NPVariant np_result; |
716 bool is_good = g_npnetscape_funcs->invokeDefault(plugin_, func, args, | 681 bool is_good = g_npnetscape_funcs->invokeDefault(plugin_, func, args, |
717 argCount, &np_result); | 682 argCount, &np_result); |
718 if (is_good) | 683 if (is_good) |
719 g_npnetscape_funcs->releasevariantvalue(&np_result); | 684 g_npnetscape_funcs->releasevariantvalue(&np_result); |
720 return is_good; | 685 return is_good; |
721 } | 686 } |
722 | 687 |
723 } // namespace remoting | 688 } // namespace remoting |
OLD | NEW |