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/client/plugin/chromoting_instance.h" | 5 #include "remoting/client/plugin/chromoting_instance.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "base/stringprintf.h" | 13 #include "base/stringprintf.h" |
14 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
15 #include "base/task.h" | 15 #include "base/task.h" |
16 #include "base/threading/thread.h" | 16 #include "base/threading/thread.h" |
17 // TODO(sergeyu): We should not depend on renderer here. Instead P2P | 17 // TODO(sergeyu): We should not depend on renderer here. Instead P2P |
18 // Pepper API should be used. Remove this dependency. | 18 // Pepper API should be used. Remove this dependency. |
19 // crbug.com/74951 | 19 // crbug.com/74951 |
20 #include "content/renderer/p2p/ipc_network_manager.h" | 20 #include "content/renderer/p2p/ipc_network_manager.h" |
21 #include "content/renderer/p2p/ipc_socket_factory.h" | 21 #include "content/renderer/p2p/ipc_socket_factory.h" |
22 #include "ppapi/cpp/completion_callback.h" | 22 #include "ppapi/cpp/completion_callback.h" |
23 #include "ppapi/cpp/input_event.h" | 23 #include "ppapi/cpp/input_event.h" |
24 #include "ppapi/cpp/rect.h" | 24 #include "ppapi/cpp/rect.h" |
25 // TODO(wez): Remove this when crbug.com/86353 is complete. | 25 // TODO(wez): Remove this when crbug.com/86353 is complete. |
26 #include "ppapi/cpp/private/var_private.h" | 26 #include "ppapi/cpp/private/var_private.h" |
27 #include "remoting/base/task_thread_proxy.h" | |
28 #include "remoting/base/util.h" | |
27 #include "remoting/client/client_config.h" | 29 #include "remoting/client/client_config.h" |
28 #include "remoting/client/chromoting_client.h" | 30 #include "remoting/client/chromoting_client.h" |
29 #include "remoting/client/rectangle_update_decoder.h" | 31 #include "remoting/client/rectangle_update_decoder.h" |
30 #include "remoting/client/plugin/chromoting_scriptable_object.h" | 32 #include "remoting/client/plugin/chromoting_scriptable_object.h" |
31 #include "remoting/client/plugin/pepper_client_logger.h" | |
32 #include "remoting/client/plugin/pepper_input_handler.h" | 33 #include "remoting/client/plugin/pepper_input_handler.h" |
33 #include "remoting/client/plugin/pepper_port_allocator_session.h" | 34 #include "remoting/client/plugin/pepper_port_allocator_session.h" |
34 #include "remoting/client/plugin/pepper_view.h" | 35 #include "remoting/client/plugin/pepper_view.h" |
35 #include "remoting/client/plugin/pepper_view_proxy.h" | 36 #include "remoting/client/plugin/pepper_view_proxy.h" |
36 #include "remoting/client/plugin/pepper_util.h" | 37 #include "remoting/client/plugin/pepper_util.h" |
37 #include "remoting/client/plugin/pepper_xmpp_proxy.h" | 38 #include "remoting/client/plugin/pepper_xmpp_proxy.h" |
38 #include "remoting/jingle_glue/jingle_thread.h" | 39 #include "remoting/jingle_glue/jingle_thread.h" |
39 #include "remoting/proto/auth.pb.h" | 40 #include "remoting/proto/auth.pb.h" |
40 #include "remoting/protocol/connection_to_host.h" | 41 #include "remoting/protocol/connection_to_host.h" |
41 #include "remoting/protocol/host_stub.h" | 42 #include "remoting/protocol/host_stub.h" |
42 // TODO(sergeyu): This is a hack: plugin should not depend on webkit | 43 // TODO(sergeyu): This is a hack: plugin should not depend on webkit |
43 // glue. It is used here to get P2PPacketDispatcher corresponding to | 44 // glue. It is used here to get P2PPacketDispatcher corresponding to |
44 // the current RenderView. Use P2P Pepper API for connection and | 45 // the current RenderView. Use P2P Pepper API for connection and |
45 // remove these includes. | 46 // remove these includes. |
46 // crbug.com/74951 | 47 // crbug.com/74951 |
47 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 48 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
48 #include "webkit/plugins/ppapi/resource_tracker.h" | 49 #include "webkit/plugins/ppapi/resource_tracker.h" |
49 | 50 |
50 namespace remoting { | 51 namespace remoting { |
51 | 52 |
53 // This flag blocks LOGs to the UI if we're already in the middle of logging | |
54 // to the UI. This prevents a potential infinite loop if we encounter an error | |
55 // while sending the log message to the UI. | |
56 static bool g_logging_to_plugin = false; | |
57 static ChromotingInstance* g_logging_instance = NULL; | |
58 static TaskThreadProxy* g_logging_thread_proxy = NULL; | |
Sergey Ulanov
2011/08/02 01:08:32
Don't need this.
garykac
2011/08/02 02:13:31
Done.
| |
59 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL; | |
60 | |
52 const char* ChromotingInstance::kMimeType = "pepper-application/x-chromoting"; | 61 const char* ChromotingInstance::kMimeType = "pepper-application/x-chromoting"; |
53 | 62 |
54 ChromotingInstance::ChromotingInstance(PP_Instance pp_instance) | 63 ChromotingInstance::ChromotingInstance(PP_Instance pp_instance) |
55 : pp::InstancePrivate(pp_instance), | 64 : pp::InstancePrivate(pp_instance), |
56 initialized_(false), | 65 initialized_(false), |
57 scale_to_fit_(false), | 66 scale_to_fit_(false) { |
58 logger_(this) { | |
59 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL); | 67 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL); |
60 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); | 68 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); |
69 | |
70 log_proxy_ = new TaskThreadProxy(MessageLoop::current()); | |
71 | |
72 // Set up log message handler. | |
73 // Note that this approach doesn't quite support having multiple instances | |
74 // of Chromoting running. In that case, the most recently opened tab will | |
75 // grab all the debug log messages, and when any Chromoting tab is closed | |
76 // the logging handler will go away. | |
77 // Since having multiple Chromoting tabs is not a primary use case, and this | |
78 // is just debug logging, we're punting improving debug log support for that | |
79 // case. | |
80 if (g_logging_old_handler == NULL) | |
81 g_logging_old_handler = logging::GetLogMessageHandler(); | |
82 logging::SetLogMessageHandler(&LogToUI); | |
83 g_logging_instance = this; | |
84 g_logging_thread_proxy = log_proxy_.get(); | |
61 } | 85 } |
62 | 86 |
63 ChromotingInstance::~ChromotingInstance() { | 87 ChromotingInstance::~ChromotingInstance() { |
64 DCHECK(CurrentlyOnPluginThread()); | 88 DCHECK(CurrentlyOnPluginThread()); |
65 | 89 |
90 // Detach the log proxy so we don't log anything else to the UI. | |
91 log_proxy_->Detach(); | |
92 | |
93 // Remove log message handler. | |
94 logging::SetLogMessageHandler(g_logging_old_handler); | |
95 g_logging_old_handler = NULL; | |
96 g_logging_instance = NULL; | |
97 g_logging_thread_proxy = NULL; | |
98 | |
66 if (client_.get()) { | 99 if (client_.get()) { |
67 base::WaitableEvent done_event(true, false); | 100 base::WaitableEvent done_event(true, false); |
68 client_->Stop(base::Bind(&base::WaitableEvent::Signal, | 101 client_->Stop(base::Bind(&base::WaitableEvent::Signal, |
69 base::Unretained(&done_event))); | 102 base::Unretained(&done_event))); |
70 done_event.Wait(); | 103 done_event.Wait(); |
71 } | 104 } |
72 | 105 |
73 // Stopping the context shutdown all chromoting threads. This is a requirement | 106 // Stopping the context shutdown all chromoting threads. This is a requirement |
74 // before we can call Detach() on |view_proxy_|. | 107 // before we can call Detach() on |view_proxy_|. |
75 context_.Stop(); | 108 context_.Stop(); |
76 | 109 |
77 view_proxy_->Detach(); | 110 view_proxy_->Detach(); |
78 } | 111 } |
79 | 112 |
80 bool ChromotingInstance::Init(uint32_t argc, | 113 bool ChromotingInstance::Init(uint32_t argc, |
81 const char* argn[], | 114 const char* argn[], |
82 const char* argv[]) { | 115 const char* argv[]) { |
83 CHECK(!initialized_); | 116 CHECK(!initialized_); |
84 initialized_ = true; | 117 initialized_ = true; |
85 | 118 |
86 logger_.VLog(1, "Started ChromotingInstance::Init"); | 119 VLOG(1) << "Started ChromotingInstance::Init"; |
87 | 120 |
88 // Start all the threads. | 121 // Start all the threads. |
89 context_.Start(); | 122 context_.Start(); |
90 | 123 |
91 webkit::ppapi::PluginInstance* plugin_instance = | 124 webkit::ppapi::PluginInstance* plugin_instance = |
92 webkit::ppapi::ResourceTracker::Get()->GetInstance(pp_instance()); | 125 webkit::ppapi::ResourceTracker::Get()->GetInstance(pp_instance()); |
93 | 126 |
94 P2PSocketDispatcher* socket_dispatcher = | 127 P2PSocketDispatcher* socket_dispatcher = |
95 plugin_instance->delegate()->GetP2PSocketDispatcher(); | 128 plugin_instance->delegate()->GetP2PSocketDispatcher(); |
96 IpcNetworkManager* network_manager = NULL; | 129 IpcNetworkManager* network_manager = NULL; |
97 IpcPacketSocketFactory* socket_factory = NULL; | 130 IpcPacketSocketFactory* socket_factory = NULL; |
98 PortAllocatorSessionFactory* session_factory = | 131 PortAllocatorSessionFactory* session_factory = |
99 CreatePepperPortAllocatorSessionFactory(this); | 132 CreatePepperPortAllocatorSessionFactory(this); |
100 | 133 |
101 // If we don't have socket dispatcher for IPC (e.g. P2P API is | 134 // If we don't have socket dispatcher for IPC (e.g. P2P API is |
102 // disabled), then JingleSessionManager will try to use physical sockets. | 135 // disabled), then JingleSessionManager will try to use physical sockets. |
103 if (socket_dispatcher) { | 136 if (socket_dispatcher) { |
104 logger_.VLog(1, "Creating IpcNetworkManager and IpcPacketSocketFactory."); | 137 VLOG(1) << "Creating IpcNetworkManager and IpcPacketSocketFactory."; |
105 network_manager = new IpcNetworkManager(socket_dispatcher); | 138 network_manager = new IpcNetworkManager(socket_dispatcher); |
106 socket_factory = new IpcPacketSocketFactory(socket_dispatcher); | 139 socket_factory = new IpcPacketSocketFactory(socket_dispatcher); |
107 } | 140 } |
108 | 141 |
109 // Create the chromoting objects. | 142 // Create the chromoting objects. |
110 // TODO(sergeyu): Use firewall traversal policy settings here. | 143 // TODO(sergeyu): Use firewall traversal policy settings here. |
111 host_connection_.reset(new protocol::ConnectionToHost( | 144 host_connection_.reset(new protocol::ConnectionToHost( |
112 context_.network_message_loop(), network_manager, socket_factory, | 145 context_.network_message_loop(), network_manager, socket_factory, |
113 session_factory, false)); | 146 session_factory, false)); |
114 view_.reset(new PepperView(this, &context_)); | 147 view_.reset(new PepperView(this, &context_)); |
115 view_proxy_ = new PepperViewProxy(this, view_.get()); | 148 view_proxy_ = new PepperViewProxy(this, view_.get()); |
116 rectangle_decoder_ = new RectangleUpdateDecoder( | 149 rectangle_decoder_ = new RectangleUpdateDecoder( |
117 context_.decode_message_loop(), view_proxy_); | 150 context_.decode_message_loop(), view_proxy_); |
118 input_handler_.reset(new PepperInputHandler(&context_, | 151 input_handler_.reset(new PepperInputHandler(&context_, |
119 host_connection_.get(), | 152 host_connection_.get(), |
120 view_proxy_)); | 153 view_proxy_)); |
121 | 154 |
122 // Default to a medium grey. | 155 // Default to a medium grey. |
123 view_->SetSolidFill(0xFFCDCDCD); | 156 view_->SetSolidFill(0xFFCDCDCD); |
124 | 157 |
125 return true; | 158 return true; |
126 } | 159 } |
127 | 160 |
128 void ChromotingInstance::Connect(const ClientConfig& config) { | 161 void ChromotingInstance::Connect(const ClientConfig& config) { |
129 DCHECK(CurrentlyOnPluginThread()); | 162 DCHECK(CurrentlyOnPluginThread()); |
130 | 163 |
131 client_.reset(new ChromotingClient(config, &context_, host_connection_.get(), | 164 client_.reset(new ChromotingClient(config, &context_, host_connection_.get(), |
132 view_proxy_, rectangle_decoder_.get(), | 165 view_proxy_, rectangle_decoder_.get(), |
133 input_handler_.get(), &logger_, NULL)); | 166 input_handler_.get(), NULL)); |
134 | 167 |
135 logger_.Log(logging::LOG_INFO, "Connecting."); | 168 LOG(INFO) << "Connecting."; |
136 | 169 |
137 // Setup the XMPP Proxy. | 170 // Setup the XMPP Proxy. |
138 ChromotingScriptableObject* scriptable_object = GetScriptableObject(); | 171 ChromotingScriptableObject* scriptable_object = GetScriptableObject(); |
139 scoped_refptr<PepperXmppProxy> xmpp_proxy = | 172 scoped_refptr<PepperXmppProxy> xmpp_proxy = |
140 new PepperXmppProxy(scriptable_object->AsWeakPtr(), | 173 new PepperXmppProxy(scriptable_object->AsWeakPtr(), |
141 context_.jingle_thread()->message_loop()); | 174 context_.jingle_thread()->message_loop()); |
142 scriptable_object->AttachXmppProxy(xmpp_proxy); | 175 scriptable_object->AttachXmppProxy(xmpp_proxy); |
143 | 176 |
144 // Kick off the connection. | 177 // Kick off the connection. |
145 client_->Start(xmpp_proxy); | 178 client_->Start(xmpp_proxy); |
146 | 179 |
147 logger_.Log(logging::LOG_INFO, "Connection status: Initializing"); | 180 LOG(INFO) << "Connection status: Initializing"; |
148 GetScriptableObject()->SetConnectionInfo(STATUS_INITIALIZING, | 181 GetScriptableObject()->SetConnectionInfo(STATUS_INITIALIZING, |
149 QUALITY_UNKNOWN); | 182 QUALITY_UNKNOWN); |
150 } | 183 } |
151 | 184 |
152 void ChromotingInstance::Disconnect() { | 185 void ChromotingInstance::Disconnect() { |
153 DCHECK(CurrentlyOnPluginThread()); | 186 DCHECK(CurrentlyOnPluginThread()); |
154 | 187 |
155 logger_.Log(logging::LOG_INFO, "Disconnecting from host."); | 188 LOG(INFO) << "Disconnecting from host."; |
156 if (client_.get()) { | 189 if (client_.get()) { |
157 // TODO(sergeyu): Should we disconnect asynchronously? | 190 // TODO(sergeyu): Should we disconnect asynchronously? |
158 base::WaitableEvent done_event(true, false); | 191 base::WaitableEvent done_event(true, false); |
159 client_->Stop(base::Bind(&base::WaitableEvent::Signal, | 192 client_->Stop(base::Bind(&base::WaitableEvent::Signal, |
160 base::Unretained(&done_event))); | 193 base::Unretained(&done_event))); |
161 done_event.Wait(); | 194 done_event.Wait(); |
162 } | 195 } |
163 | 196 |
164 GetScriptableObject()->SetConnectionInfo(STATUS_CLOSED, QUALITY_UNKNOWN); | 197 GetScriptableObject()->SetConnectionInfo(STATUS_CLOSED, QUALITY_UNKNOWN); |
165 } | 198 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
212 } | 245 } |
213 | 246 |
214 case PP_INPUTEVENT_TYPE_CONTEXTMENU: { | 247 case PP_INPUTEVENT_TYPE_CONTEXTMENU: { |
215 // We need to return true here or else we'll get a local (plugin) context | 248 // We need to return true here or else we'll get a local (plugin) context |
216 // menu instead of the mouseup event for the right click. | 249 // menu instead of the mouseup event for the right click. |
217 return true; | 250 return true; |
218 } | 251 } |
219 | 252 |
220 case PP_INPUTEVENT_TYPE_KEYDOWN: { | 253 case PP_INPUTEVENT_TYPE_KEYDOWN: { |
221 pp::KeyboardInputEvent key = pp::KeyboardInputEvent(event); | 254 pp::KeyboardInputEvent key = pp::KeyboardInputEvent(event); |
222 logger_.VLog(3, "PP_INPUTEVENT_TYPE_KEYDOWN key=%d", key.GetKeyCode()); | 255 VLOG(3) << "PP_INPUTEVENT_TYPE_KEYDOWN" << " key=" << key.GetKeyCode(); |
223 pih->HandleKeyEvent(true, key); | 256 pih->HandleKeyEvent(true, key); |
224 return true; | 257 return true; |
225 } | 258 } |
226 | 259 |
227 case PP_INPUTEVENT_TYPE_KEYUP: { | 260 case PP_INPUTEVENT_TYPE_KEYUP: { |
228 pp::KeyboardInputEvent key = pp::KeyboardInputEvent(event); | 261 pp::KeyboardInputEvent key = pp::KeyboardInputEvent(event); |
229 logger_.VLog(3, "PP_INPUTEVENT_TYPE_KEYUP key=%d", key.GetKeyCode()); | 262 VLOG(3) << "PP_INPUTEVENT_TYPE_KEYUP" << " key=" << key.GetKeyCode(); |
230 pih->HandleKeyEvent(false, key); | 263 pih->HandleKeyEvent(false, key); |
231 return true; | 264 return true; |
232 } | 265 } |
233 | 266 |
234 case PP_INPUTEVENT_TYPE_CHAR: { | 267 case PP_INPUTEVENT_TYPE_CHAR: { |
235 pih->HandleCharacterEvent(pp::KeyboardInputEvent(event)); | 268 pih->HandleCharacterEvent(pp::KeyboardInputEvent(event)); |
236 return true; | 269 return true; |
237 } | 270 } |
238 | 271 |
239 default: { | 272 default: { |
240 LOG(INFO) << "Unhandled input event: " << event.GetType(); | 273 LOG(INFO) << "Unhandled input event: " << event.GetType(); |
241 break; | 274 break; |
242 } | 275 } |
243 } | 276 } |
244 | 277 |
245 return false; | 278 return false; |
246 } | 279 } |
247 | 280 |
248 ChromotingScriptableObject* ChromotingInstance::GetScriptableObject() { | 281 ChromotingScriptableObject* ChromotingInstance::GetScriptableObject() { |
249 pp::VarPrivate object = GetInstanceObject(); | 282 pp::VarPrivate object = GetInstanceObject(); |
250 if (!object.is_undefined()) { | 283 if (!object.is_undefined()) { |
251 pp::deprecated::ScriptableObject* so = object.AsScriptableObject(); | 284 pp::deprecated::ScriptableObject* so = object.AsScriptableObject(); |
252 DCHECK(so != NULL); | 285 DCHECK(so != NULL); |
253 return static_cast<ChromotingScriptableObject*>(so); | 286 return static_cast<ChromotingScriptableObject*>(so); |
254 } | 287 } |
255 logger_.Log(logging::LOG_ERROR, | 288 LOG(ERROR) << "Unable to get ScriptableObject for Chromoting plugin."; |
256 "Unable to get ScriptableObject for Chromoting plugin."); | |
257 return NULL; | 289 return NULL; |
258 } | 290 } |
259 | 291 |
260 void ChromotingInstance::SubmitLoginInfo(const std::string& username, | 292 void ChromotingInstance::SubmitLoginInfo(const std::string& username, |
261 const std::string& password) { | 293 const std::string& password) { |
262 if (host_connection_->state() != | 294 if (host_connection_->state() != |
263 protocol::ConnectionToHost::STATE_CONNECTED) { | 295 protocol::ConnectionToHost::STATE_CONNECTED) { |
264 logger_.Log(logging::LOG_INFO, | 296 LOG(INFO) << "Client not connected or already authenticated."; |
265 "Client not connected or already authenticated."); | |
266 return; | 297 return; |
267 } | 298 } |
268 | 299 |
269 protocol::LocalLoginCredentials* credentials = | 300 protocol::LocalLoginCredentials* credentials = |
270 new protocol::LocalLoginCredentials(); | 301 new protocol::LocalLoginCredentials(); |
271 credentials->set_type(protocol::PASSWORD); | 302 credentials->set_type(protocol::PASSWORD); |
272 credentials->set_username(username); | 303 credentials->set_username(username); |
273 credentials->set_credential(password.data(), password.length()); | 304 credentials->set_credential(password.data(), password.length()); |
274 | 305 |
275 host_connection_->host_stub()->BeginSessionRequest( | 306 host_connection_->host_stub()->BeginSessionRequest( |
(...skipping 10 matching lines...) Expand all Loading... | |
286 scale_to_fit_ = scale_to_fit; | 317 scale_to_fit_ = scale_to_fit; |
287 if (scale_to_fit) { | 318 if (scale_to_fit) { |
288 rectangle_decoder_->SetScaleRatios(view_->GetHorizontalScaleRatio(), | 319 rectangle_decoder_->SetScaleRatios(view_->GetHorizontalScaleRatio(), |
289 view_->GetVerticalScaleRatio()); | 320 view_->GetVerticalScaleRatio()); |
290 } else { | 321 } else { |
291 rectangle_decoder_->SetScaleRatios(1.0, 1.0); | 322 rectangle_decoder_->SetScaleRatios(1.0, 1.0); |
292 } | 323 } |
293 rectangle_decoder_->RefreshFullFrame(); | 324 rectangle_decoder_->RefreshFullFrame(); |
294 } | 325 } |
295 | 326 |
296 void ChromotingInstance::Log(int severity, const char* format, ...) { | 327 // static |
297 va_list ap; | 328 bool ChromotingInstance::LogToUI(int severity, const char* file, int line, |
298 va_start(ap, format); | 329 size_t message_start, |
299 logger_.va_Log(severity, format, ap); | 330 const std::string& str) { |
300 va_end(ap); | 331 if (g_logging_instance && g_logging_thread_proxy) { |
Sergey Ulanov
2011/08/02 01:08:32
don't need to verify g_logging_thread_proxy
garykac
2011/08/02 02:13:31
Done.
| |
332 std::string message = remoting::GetTimestampString(); | |
333 message += (str.c_str() + message_start); | |
334 //g_logging_instance->LogToUI_CorrectThread(message); | |
335 g_logging_thread_proxy->Call( | |
Sergey Ulanov
2011/08/02 01:08:32
g_logging_instance->log_proxy->Call(...
garykac
2011/08/02 02:13:31
Done.
| |
336 base::Bind(&ChromotingInstance::ProcessLogToUI, | |
337 base::Unretained(g_logging_instance), message)); | |
338 } | |
339 | |
340 if (g_logging_old_handler) | |
341 return (g_logging_old_handler)(severity, file, line, message_start, str); | |
342 return false; | |
301 } | 343 } |
302 | 344 |
303 void ChromotingInstance::VLog(int verboselevel, const char* format, ...) { | 345 void ChromotingInstance::ProcessLogToUI(const std::string& message) { |
304 va_list ap; | 346 if (!g_logging_to_plugin) { |
305 va_start(ap, format); | 347 ChromotingScriptableObject* cso = GetScriptableObject(); |
306 logger_.va_VLog(verboselevel, format, ap); | 348 if (cso) { |
307 va_end(ap); | 349 g_logging_to_plugin = true; |
350 cso->LogDebugInfo(message); | |
351 g_logging_to_plugin = false; | |
352 } | |
353 } | |
308 } | 354 } |
309 | 355 |
310 pp::Var ChromotingInstance::GetInstanceObject() { | 356 pp::Var ChromotingInstance::GetInstanceObject() { |
311 if (instance_object_.is_undefined()) { | 357 if (instance_object_.is_undefined()) { |
312 ChromotingScriptableObject* object = new ChromotingScriptableObject(this); | 358 ChromotingScriptableObject* object = new ChromotingScriptableObject(this); |
313 object->Init(); | 359 object->Init(); |
314 | 360 |
315 // The pp::Var takes ownership of object here. | 361 // The pp::Var takes ownership of object here. |
316 instance_object_ = pp::VarPrivate(this, object); | 362 instance_object_ = pp::VarPrivate(this, object); |
317 } | 363 } |
318 | 364 |
319 return instance_object_; | 365 return instance_object_; |
320 } | 366 } |
321 | 367 |
322 ChromotingStats* ChromotingInstance::GetStats() { | 368 ChromotingStats* ChromotingInstance::GetStats() { |
323 if (!client_.get()) | 369 if (!client_.get()) |
324 return NULL; | 370 return NULL; |
325 return client_->GetStats(); | 371 return client_->GetStats(); |
326 } | 372 } |
327 | 373 |
328 void ChromotingInstance::ReleaseAllKeys() { | 374 void ChromotingInstance::ReleaseAllKeys() { |
329 input_handler_->ReleaseAllKeys(); | 375 input_handler_->ReleaseAllKeys(); |
330 } | 376 } |
331 | 377 |
332 } // namespace remoting | 378 } // namespace remoting |
OLD | NEW |