Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: remoting/client/plugin/chromoting_instance.cc

Issue 7355011: Modify Chromoting logging to hook into base logging. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review comments + thread proxy Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698