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

Side by Side Diff: remoting/host/host_plugin.cc

Issue 7210025: Split host plugin into multiple files. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge gary's changes Created 9 years, 6 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
« no previous file with comments | « no previous file | remoting/host/host_plugin_utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <stdio.h> 5 #include <stdio.h>
6 #include <string.h> 6 #include <string.h>
7 7
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/at_exit.h" 11 #include "base/at_exit.h"
12 #include "base/base_paths.h"
13 #include "base/basictypes.h" 12 #include "base/basictypes.h"
14 #include "base/bind.h"
15 #include "base/file_path.h"
16 #include "base/logging.h" 13 #include "base/logging.h"
17 #include "base/message_loop.h"
18 #include "base/path_service.h"
19 #include "base/rand_util.h"
20 #include "base/stringize_macros.h" 14 #include "base/stringize_macros.h"
21 #include "base/task.h" 15 #include "remoting/host/host_plugin_utils.h"
22 #include "base/threading/platform_thread.h" 16 #include "remoting/host/host_script_object.h"
23 #include "base/threading/thread.h"
24 #include "base/synchronization/cancellation_flag.h"
25 #include "remoting/base/auth_token_util.h"
26 #include "remoting/host/chromoting_host.h"
27 #include "remoting/host/chromoting_host_context.h"
28 #include "remoting/host/host_config.h"
29 #include "remoting/host/host_key_pair.h"
30 #include "remoting/host/host_status_observer.h"
31 #include "remoting/host/in_memory_host_config.h"
32 #include "remoting/host/register_support_host_request.h"
33 #include "remoting/host/support_access_verifier.h"
34 #include "third_party/npapi/bindings/npapi.h" 17 #include "third_party/npapi/bindings/npapi.h"
35 #include "third_party/npapi/bindings/npfunctions.h" 18 #include "third_party/npapi/bindings/npfunctions.h"
36 #include "third_party/npapi/bindings/npruntime.h" 19 #include "third_party/npapi/bindings/npruntime.h"
37 20
38 // Symbol export is handled with a separate def file on Windows. 21 // Symbol export is handled with a separate def file on Windows.
39 #if defined (__GNUC__) && __GNUC__ >= 4 22 #if defined (__GNUC__) && __GNUC__ >= 4
40 #define EXPORT __attribute__((visibility("default"))) 23 #define EXPORT __attribute__((visibility("default")))
41 #else 24 #else
42 #define EXPORT 25 #define EXPORT
43 #endif 26 #endif
44 27
45 #if defined(OS_WIN) 28 #if defined(OS_WIN)
46 // TODO(wez): libvpx expects these 64-bit division functions to be provided 29 // TODO(wez): libvpx expects these 64-bit division functions to be provided
47 // by libgcc.a, which we aren't linked against. These implementations can 30 // by libgcc.a, which we aren't linked against. These implementations can
48 // be removed once we have native MSVC libvpx builds for Windows. 31 // be removed once we have native MSVC libvpx builds for Windows.
49 extern "C" { 32 extern "C" {
50 33
51 int64_t __cdecl __divdi3(int64_t a, int64_t b) { 34 int64_t __cdecl __divdi3(int64_t a, int64_t b) {
52 return a / b; 35 return a / b;
53 } 36 }
54 uint64_t __cdecl __udivdi3(uint64_t a, uint64_t b) { 37 uint64_t __cdecl __udivdi3(uint64_t a, uint64_t b) {
55 return a / b; 38 return a / b;
56 } 39 }
57 40
58 } 41 }
59 #endif 42 #endif
60 43
61 // Supported Javascript interface: 44 using remoting::g_npnetscape_funcs;
62 // readonly attribute string accessCode; 45 using remoting::HostNPScriptObject;
63 // readonly attribute int state; 46 using remoting::StringFromNPIdentifier;
64 //
65 // state: {
66 // DISCONNECTED,
67 // REQUESTED_ACCESS_CODE,
68 // RECEIVED_ACCESS_CODE,
69 // CONNECTED,
70 // AFFIRMING_CONNECTION,
71 // ERROR,
72 // }
73 //
74 // attribute Function void logDebugInfo(string);
75 // attribute Function void onStateChanged();
76 //
77 // // The |auth_service_with_token| parameter should be in the format
78 // // "auth_service:auth_token". An example would be "oauth2:1/2a3912vd".
79 // void connect(string uid, string auth_service_with_token);
80 // void disconnect();
81
82 47
83 namespace { 48 namespace {
84 49
85 const char* kAttrNameAccessCode = "accessCode";
86 const char* kAttrNameState = "state";
87 const char* kAttrNameLogDebugInfo = "logDebugInfo";
88 const char* kAttrNameOnStateChanged = "onStateChanged";
89 const char* kFuncNameConnect = "connect";
90 const char* kFuncNameDisconnect = "disconnect";
91
92 // States.
93 const char* kAttrNameDisconnected = "DISCONNECTED";
94 const char* kAttrNameRequestedAccessCode = "REQUESTED_ACCESS_CODE";
95 const char* kAttrNameReceivedAccessCode = "RECEIVED_ACCESS_CODE";
96 const char* kAttrNameConnected = "CONNECTED";
97 const char* kAttrNameAffirmingConnection = "AFFIRMING_CONNECTION";
98 const char* kAttrNameError = "ERROR";
99
100 const int kMaxLoginAttempts = 5;
101
102 // Global netscape functions initialized in NP_Initialize.
103 NPNetscapeFuncs* g_npnetscape_funcs = NULL;
104
105 // Global AtExitManager, created in NP_Initialize and destroyed in NP_Shutdown.
106 base::AtExitManager* g_at_exit_manager = NULL; 50 base::AtExitManager* g_at_exit_manager = NULL;
107 51
108 // The name and description are returned by GetValue, but are also 52 // The name and description are returned by GetValue, but are also
109 // combined with the MIME type to satisfy GetMIMEDescription, so we 53 // combined with the MIME type to satisfy GetMIMEDescription, so we
110 // use macros here to allow that to happen at compile-time. 54 // use macros here to allow that to happen at compile-time.
111 #define HOST_PLUGIN_NAME "Remoting Host Plugin" 55 #define HOST_PLUGIN_NAME "Remoting Host Plugin"
112 #define HOST_PLUGIN_DESCRIPTION "Remoting Host Plugin" 56 #define HOST_PLUGIN_DESCRIPTION "Remoting Host Plugin"
113 57
114 // Convert an NPIdentifier into a std::string.
115 std::string StringFromNPIdentifier(NPIdentifier identifier) {
116 if (!g_npnetscape_funcs->identifierisstring(identifier))
117 return std::string();
118 NPUTF8* np_string = g_npnetscape_funcs->utf8fromidentifier(identifier);
119 std::string string(np_string);
120 g_npnetscape_funcs->memfree(np_string);
121 return string;
122 }
123
124 // Convert an NPVariant into a std::string.
125 std::string StringFromNPVariant(const NPVariant& variant) {
126 if (!NPVARIANT_IS_STRING(variant))
127 return std::string();
128 const NPString& np_string = NPVARIANT_TO_STRING(variant);
129 return std::string(np_string.UTF8Characters, np_string.UTF8Length);
130 }
131
132 // Convert a std::string into an NPVariant.
133 // Caller is responsible for making sure that NPN_ReleaseVariantValue is
134 // called on returned value.
135 NPVariant NPVariantFromString(const std::string& val) {
136 size_t len = val.length();
137 NPUTF8* chars =
138 reinterpret_cast<NPUTF8*>(g_npnetscape_funcs->memalloc(len + 1));
139 strcpy(chars, val.c_str());
140 NPVariant variant;
141 STRINGN_TO_NPVARIANT(chars, len, variant);
142 return variant;
143 }
144
145 // Convert an NPVariant into an NSPObject.
146 NPObject* ObjectFromNPVariant(const NPVariant& variant) {
147 if (!NPVARIANT_IS_OBJECT(variant))
148 return NULL;
149 return NPVARIANT_TO_OBJECT(variant);
150 }
151
152 // NPAPI plugin implementation for remoting host script object.
153 // HostNPScriptObject creates threads that are required to run
154 // ChromotingHost and starts/stops the host on those threads. When
155 // destroyed it sychronously shuts down the host and all threads.
156 class HostNPScriptObject : public remoting::HostStatusObserver {
157 public:
158 HostNPScriptObject(NPP plugin, NPObject* parent)
159 : plugin_(plugin),
160 parent_(parent),
161 state_(kDisconnected),
162 log_debug_info_func_(NULL),
163 on_state_changed_func_(NULL),
164 np_thread_id_(base::PlatformThread::CurrentId()),
165 failed_login_attempts_(0),
166 disconnected_event_(true, false) {
167 VLOG(2) << "HostNPScriptObject";
168 host_context_.SetUITaskPostFunction(base::Bind(
169 &HostNPScriptObject::PostTaskToNPThread, base::Unretained(this)));
170 }
171
172 ~HostNPScriptObject() {
173 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
174
175 // Disconnect synchronously. We cannot disconnect asynchronously
176 // here because |host_context_| needs to be stopped on the plugin
177 // thread, but the plugin thread may not exist after the instance
178 // is destroyed.
179 destructing_.Set();
180 disconnected_event_.Reset();
181 DisconnectInternal();
182 disconnected_event_.Wait();
183
184 host_context_.Stop();
185 if (log_debug_info_func_) {
186 g_npnetscape_funcs->releaseobject(log_debug_info_func_);
187 }
188 if (on_state_changed_func_) {
189 g_npnetscape_funcs->releaseobject(on_state_changed_func_);
190 }
191 }
192
193 bool Init() {
194 VLOG(2) << "Init";
195 // TODO(wez): This starts a bunch of threads, which might fail.
196 host_context_.Start();
197 return true;
198 }
199
200 bool HasMethod(const std::string& method_name) {
201 VLOG(2) << "HasMethod " << method_name;
202 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
203 return (method_name == kFuncNameConnect ||
204 method_name == kFuncNameDisconnect);
205 }
206
207 bool InvokeDefault(const NPVariant* args,
208 uint32_t argCount,
209 NPVariant* result) {
210 VLOG(2) << "InvokeDefault";
211 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
212 SetException("exception during default invocation");
213 return false;
214 }
215
216 bool Invoke(const std::string& method_name,
217 const NPVariant* args,
218 uint32_t argCount,
219 NPVariant* result) {
220 VLOG(2) << "Invoke " << method_name;
221 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
222 if (method_name == kFuncNameConnect) {
223 return Connect(args, argCount, result);
224 } else if (method_name == kFuncNameDisconnect) {
225 return Disconnect(args, argCount, result);
226 } else {
227 SetException("Invoke: unknown method " + method_name);
228 return false;
229 }
230 }
231
232 bool HasProperty(const std::string& property_name) {
233 VLOG(2) << "HasProperty " << property_name;
234 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
235 return (property_name == kAttrNameAccessCode ||
236 property_name == kAttrNameState ||
237 property_name == kAttrNameLogDebugInfo ||
238 property_name == kAttrNameOnStateChanged ||
239 property_name == kAttrNameDisconnected ||
240 property_name == kAttrNameRequestedAccessCode ||
241 property_name == kAttrNameReceivedAccessCode ||
242 property_name == kAttrNameConnected ||
243 property_name == kAttrNameAffirmingConnection ||
244 property_name == kAttrNameError);
245 }
246
247 bool GetProperty(const std::string& property_name, NPVariant* result) {
248 VLOG(2) << "GetProperty " << property_name;
249 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
250 if (!result) {
251 SetException("GetProperty: NULL result");
252 return false;
253 }
254
255 if (property_name == kAttrNameOnStateChanged) {
256 OBJECT_TO_NPVARIANT(on_state_changed_func_, *result);
257 return true;
258 } else if (property_name == kAttrNameLogDebugInfo) {
259 OBJECT_TO_NPVARIANT(log_debug_info_func_, *result);
260 return true;
261 } else if (property_name == kAttrNameState) {
262 INT32_TO_NPVARIANT(state_, *result);
263 return true;
264 } else if (property_name == kAttrNameAccessCode) {
265 *result = NPVariantFromString(access_code_);
266 return true;
267 } else if (property_name == kAttrNameDisconnected) {
268 INT32_TO_NPVARIANT(kDisconnected, *result);
269 return true;
270 } else if (property_name == kAttrNameRequestedAccessCode) {
271 INT32_TO_NPVARIANT(kRequestedAccessCode, *result);
272 return true;
273 } else if (property_name == kAttrNameReceivedAccessCode) {
274 INT32_TO_NPVARIANT(kReceivedAccessCode, *result);
275 return true;
276 } else if (property_name == kAttrNameConnected) {
277 INT32_TO_NPVARIANT(kConnected, *result);
278 return true;
279 } else if (property_name == kAttrNameAffirmingConnection) {
280 INT32_TO_NPVARIANT(kAffirmingConnection, *result);
281 return true;
282 } else if (property_name == kAttrNameError) {
283 INT32_TO_NPVARIANT(kError, *result);
284 return true;
285 } else {
286 SetException("GetProperty: unsupported property " + property_name);
287 return false;
288 }
289 }
290
291 bool SetProperty(const std::string& property_name, const NPVariant* value) {
292 VLOG(2) << "SetProperty " << property_name;
293 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
294
295 if (property_name == kAttrNameOnStateChanged) {
296 if (NPVARIANT_IS_OBJECT(*value)) {
297 if (on_state_changed_func_) {
298 g_npnetscape_funcs->releaseobject(on_state_changed_func_);
299 }
300 on_state_changed_func_ = NPVARIANT_TO_OBJECT(*value);
301 if (on_state_changed_func_) {
302 g_npnetscape_funcs->retainobject(on_state_changed_func_);
303 }
304 return true;
305 } else {
306 SetException("SetProperty: unexpected type for property " +
307 property_name);
308 }
309 return false;
310 }
311
312 if (property_name == kAttrNameLogDebugInfo) {
313 if (NPVARIANT_IS_OBJECT(*value)) {
314 if (log_debug_info_func_) {
315 g_npnetscape_funcs->releaseobject(log_debug_info_func_);
316 }
317 log_debug_info_func_ = NPVARIANT_TO_OBJECT(*value);
318 if (log_debug_info_func_) {
319 g_npnetscape_funcs->retainobject(log_debug_info_func_);
320 }
321 return true;
322 } else {
323 SetException("SetProperty: unexpected type for property " +
324 property_name);
325 }
326 return false;
327 }
328
329 return false;
330 }
331
332 bool RemoveProperty(const std::string& property_name) {
333 VLOG(2) << "RemoveProperty " << property_name;
334 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
335 return false;
336 }
337
338 bool Enumerate(std::vector<std::string>* values) {
339 VLOG(2) << "Enumerate";
340 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
341 const char* entries[] = {
342 kAttrNameAccessCode,
343 kAttrNameState,
344 kAttrNameLogDebugInfo,
345 kAttrNameOnStateChanged,
346 kFuncNameConnect,
347 kFuncNameDisconnect,
348 kAttrNameDisconnected,
349 kAttrNameRequestedAccessCode,
350 kAttrNameReceivedAccessCode,
351 kAttrNameConnected,
352 kAttrNameAffirmingConnection,
353 kAttrNameError
354 };
355 for (size_t i = 0; i < arraysize(entries); ++i) {
356 values->push_back(entries[i]);
357 }
358 return true;
359 }
360
361 // remoting::HostStatusObserver implementation.
362 virtual void OnSignallingConnected(remoting::SignalStrategy* signal_strategy,
363 const std::string& full_jid) OVERRIDE {
364 OnStateChanged(kConnected);
365 }
366
367 virtual void OnSignallingDisconnected() OVERRIDE {
368 }
369
370 virtual void OnAccessDenied() OVERRIDE {
371 DCHECK_EQ(MessageLoop::current(), host_context_.network_message_loop());
372
373 ++failed_login_attempts_;
374 if (failed_login_attempts_ == kMaxLoginAttempts)
375 DisconnectInternal();
376 }
377
378 virtual void OnShutdown() OVERRIDE {
379 DCHECK_EQ(MessageLoop::current(), host_context_.main_message_loop());
380
381 OnStateChanged(kDisconnected);
382 }
383
384 private:
385 enum State {
386 kDisconnected,
387 kRequestedAccessCode,
388 kReceivedAccessCode,
389 kConnected,
390 kAffirmingConnection,
391 kError
392 };
393
394 // Start connection. args are:
395 // string uid, string auth_token
396 // No result.
397 bool Connect(const NPVariant* args, uint32_t argCount, NPVariant* result);
398
399 // Disconnect. No arguments or result.
400 bool Disconnect(const NPVariant* args, uint32_t argCount, NPVariant* result);
401
402 // Call LogDebugInfo handler if there is one.
403 void LogDebugInfo(const std::string& message);
404
405 // Call OnStateChanged handler if there is one.
406 void OnStateChanged(State state);
407
408 // Callbacks invoked during session setup.
409 void OnReceivedSupportID(remoting::SupportAccessVerifier* access_verifier,
410 bool success,
411 const std::string& support_id);
412
413 // Helper functions that run on main thread. Can be called on any
414 // other thread.
415 void ConnectInternal(const std::string& uid,
416 const std::string& auth_token,
417 const std::string& auth_service);
418 void DisconnectInternal();
419
420 // Callback for ChromotingHost::Shutdown().
421 void OnShutdownFinished();
422
423 // Call a JavaScript function wrapped as an NPObject.
424 // If result is non-null, the result of the call will be stored in it.
425 // Caller is responsible for releasing result if they ask for it.
426 static bool CallJSFunction(NPObject* func,
427 const NPVariant* args,
428 uint32_t argCount,
429 NPVariant* result);
430
431 // Posts a task on the main NP thread.
432 void PostTaskToNPThread(const tracked_objects::Location& from_here,
433 Task* task);
434
435 // Utility function for PostTaskToNPThread.
436 static void NPTaskSpringboard(void* task);
437
438 // Set an exception for the current call.
439 void SetException(const std::string& exception_string);
440
441 NPP plugin_;
442 NPObject* parent_;
443 int state_;
444 std::string access_code_;
445 NPObject* log_debug_info_func_;
446 NPObject* on_state_changed_func_;
447 base::PlatformThreadId np_thread_id_;
448
449 scoped_ptr<remoting::RegisterSupportHostRequest> register_request_;
450 scoped_refptr<remoting::ChromotingHost> host_;
451 scoped_refptr<remoting::MutableHostConfig> host_config_;
452 remoting::ChromotingHostContext host_context_;
453 int failed_login_attempts_;
454
455 base::WaitableEvent disconnected_event_;
456 base::CancellationFlag destructing_;
457 };
458
459 // string uid, string auth_token
460 bool HostNPScriptObject::Connect(const NPVariant* args,
461 uint32_t arg_count,
462 NPVariant* result) {
463 LogDebugInfo("Connecting...");
464
465 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
466 if (arg_count != 2) {
467 SetException("connect: bad number of arguments");
468 return false;
469 }
470
471 std::string uid = StringFromNPVariant(args[0]);
472 if (uid.empty()) {
473 SetException("connect: bad uid argument");
474 return false;
475 }
476
477 std::string auth_service_with_token = StringFromNPVariant(args[1]);
478 std::string auth_token;
479 std::string auth_service;
480 remoting::ParseAuthTokenWithService(auth_service_with_token, &auth_token,
481 &auth_service);
482 if (auth_token.empty()) {
483 SetException("connect: auth_service_with_token argument has empty token");
484 return false;
485 }
486
487 ConnectInternal(uid, auth_token, auth_service);
488
489 return true;
490 }
491
492 void HostNPScriptObject::ConnectInternal(
493 const std::string& uid,
494 const std::string& auth_token,
495 const std::string& auth_service) {
496 if (MessageLoop::current() != host_context_.main_message_loop()) {
497 host_context_.main_message_loop()->PostTask(
498 FROM_HERE,
499 NewRunnableMethod(this, &HostNPScriptObject::ConnectInternal,
500 uid, auth_token, auth_service));
501 return;
502 }
503 // Store the supplied user ID and token to the Host configuration.
504 scoped_refptr<remoting::MutableHostConfig> host_config =
505 new remoting::InMemoryHostConfig;
506 host_config->SetString(remoting::kXmppLoginConfigPath, uid);
507 host_config->SetString(remoting::kXmppAuthTokenConfigPath, auth_token);
508 host_config->SetString(remoting::kXmppAuthServiceConfigPath, auth_service);
509
510 // Create an access verifier and fetch the host secret.
511 scoped_ptr<remoting::SupportAccessVerifier> access_verifier;
512 access_verifier.reset(new remoting::SupportAccessVerifier);
513
514 // Generate a key pair for the Host to use.
515 // TODO(wez): Move this to the worker thread.
516 remoting::HostKeyPair host_key_pair;
517 host_key_pair.Generate();
518 host_key_pair.Save(host_config);
519
520 // Request registration of the host for support.
521 scoped_ptr<remoting::RegisterSupportHostRequest> register_request(
522 new remoting::RegisterSupportHostRequest());
523 if (!register_request->Init(
524 host_config.get(),
525 base::Bind(&HostNPScriptObject::OnReceivedSupportID,
526 base::Unretained(this),
527 access_verifier.get()))) {
528 OnStateChanged(kDisconnected);
529 return;
530 }
531
532 // Create the Host.
533 scoped_refptr<remoting::ChromotingHost> host =
534 remoting::ChromotingHost::Create(&host_context_, host_config,
535 access_verifier.release());
536 host->AddStatusObserver(this);
537 host->AddStatusObserver(register_request.get());
538 host->set_it2me(true);
539
540 // Nothing went wrong, so lets save the host, config and request.
541 host_ = host;
542 host_config_ = host_config;
543 register_request_.reset(register_request.release());
544
545 // Start the Host.
546 host_->Start();
547
548 OnStateChanged(kRequestedAccessCode);
549 return;
550 }
551
552 bool HostNPScriptObject::Disconnect(const NPVariant* args,
553 uint32_t arg_count,
554 NPVariant* result) {
555 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
556 if (arg_count != 0) {
557 SetException("disconnect: bad number of arguments");
558 return false;
559 }
560
561 DisconnectInternal();
562
563 return true;
564 }
565
566 void HostNPScriptObject::DisconnectInternal() {
567 if (MessageLoop::current() != host_context_.main_message_loop()) {
568 host_context_.main_message_loop()->PostTask(
569 FROM_HERE,
570 NewRunnableMethod(this, &HostNPScriptObject::DisconnectInternal));
571 return;
572 }
573
574 if (!host_) {
575 disconnected_event_.Signal();
576 return;
577 }
578
579 host_->Shutdown(
580 NewRunnableMethod(this, &HostNPScriptObject::OnShutdownFinished));
581 }
582
583 void HostNPScriptObject::OnShutdownFinished() {
584 DCHECK_EQ(MessageLoop::current(), host_context_.main_message_loop());
585
586 host_ = NULL;
587 register_request_.reset();
588 host_config_ = NULL;
589 disconnected_event_.Signal();
590 }
591
592 void HostNPScriptObject::OnReceivedSupportID(
593 remoting::SupportAccessVerifier* access_verifier,
594 bool success,
595 const std::string& support_id) {
596 CHECK_NE(base::PlatformThread::CurrentId(), np_thread_id_);
597
598 if (!success) {
599 // TODO(wez): Replace the success/fail flag with full error reporting.
600 DisconnectInternal();
601 return;
602 }
603
604 // Inform the AccessVerifier of our Support-Id, for authentication.
605 access_verifier->OnIT2MeHostRegistered(success, support_id);
606
607 // Combine the Support Id with the Host Id to make the Access Code.
608 // TODO(wez): Locking, anyone?
609 access_code_ = support_id + "-" + access_verifier->host_secret();
610
611 // Let the caller know that life is good.
612 OnStateChanged(kReceivedAccessCode);
613 }
614
615 void HostNPScriptObject::OnStateChanged(State state) {
616 if (destructing_.IsSet()) {
617 return;
618 }
619
620 if (!host_context_.IsUIThread()) {
621 host_context_.PostToUIThread(
622 FROM_HERE,
623 NewRunnableMethod(this, &HostNPScriptObject::OnStateChanged, state));
624 return;
625 }
626 state_ = state;
627 if (on_state_changed_func_) {
628 VLOG(2) << "Calling state changed " << state;
629 bool is_good = CallJSFunction(on_state_changed_func_, NULL, 0, NULL);
630 LOG_IF(ERROR, !is_good) << "OnStateChangedNP failed";
631 }
632 }
633
634 void HostNPScriptObject::LogDebugInfo(const std::string& message) {
635 if (!host_context_.IsUIThread()) {
636 host_context_.PostToUIThread(
637 FROM_HERE,
638 NewRunnableMethod(this, &HostNPScriptObject::LogDebugInfo, message));
639 return;
640 }
641 if (log_debug_info_func_) {
642 NPVariant* arg = new NPVariant();
643 LOG(INFO) << "Logging: " << message;
644 STRINGZ_TO_NPVARIANT(message.c_str(), *arg);
645 bool is_good = CallJSFunction(log_debug_info_func_, arg, 1, NULL);
646 LOG_IF(ERROR, !is_good) << "LogDebugInfo failed";
647 }
648 }
649
650 void HostNPScriptObject::SetException(const std::string& exception_string) {
651 CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
652 g_npnetscape_funcs->setexception(parent_, exception_string.c_str());
653 LogDebugInfo(exception_string);
654 }
655
656 bool HostNPScriptObject::CallJSFunction(NPObject* func,
657 const NPVariant* args,
658 uint32_t argCount,
659 NPVariant* result) {
660 NPVariant np_result;
661 bool is_good = func->_class->invokeDefault(func, args, argCount, &np_result);
662 if (is_good) {
663 if (result) {
664 *result = np_result;
665 } else {
666 g_npnetscape_funcs->releasevariantvalue(&np_result);
667 }
668 }
669 return is_good;
670 }
671
672 void HostNPScriptObject::PostTaskToNPThread(
673 const tracked_objects::Location& from_here, Task* task) {
674 // The NPAPI functions cannot make use of |from_here|, but this method is
675 // passed as a callback to ChromotingHostContext, so it needs to have the
676 // appropriate signature.
677
678 // Can be called from any thread.
679 g_npnetscape_funcs->pluginthreadasynccall(plugin_,
680 &NPTaskSpringboard,
681 task);
682 }
683
684 void HostNPScriptObject::NPTaskSpringboard(void* task) {
685 Task* real_task = reinterpret_cast<Task*>(task);
686 real_task->Run();
687 delete real_task;
688 }
689
690 // NPAPI plugin implementation for remoting host. 58 // NPAPI plugin implementation for remoting host.
691 // Documentation for most of the calls in this class can be found here: 59 // Documentation for most of the calls in this class can be found here:
692 // https://developer.mozilla.org/en/Gecko_Plugin_API_Reference/Scripting_plugins 60 // https://developer.mozilla.org/en/Gecko_Plugin_API_Reference/Scripting_plugins
693 class HostNPPlugin { 61 class HostNPPlugin {
694 public: 62 public:
695 // |mode| is the display mode of plug-in. Values: 63 // |mode| is the display mode of plug-in. Values:
696 // NP_EMBED: (1) Instance was created by an EMBED tag and shares the browser 64 // NP_EMBED: (1) Instance was created by an EMBED tag and shares the browser
697 // window with other content. 65 // window with other content.
698 // NP_FULL: (2) Instance was created by a separate file and is the primary 66 // NP_FULL: (2) Instance was created by a separate file and is the primary
699 // content in the window. 67 // content in the window.
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
997 return NPERR_NO_ERROR; 365 return NPERR_NO_ERROR;
998 } 366 }
999 367
1000 NPError SetWindow(NPP instance, NPWindow* pNPWindow) { 368 NPError SetWindow(NPP instance, NPWindow* pNPWindow) {
1001 VLOG(2) << "SetWindow"; 369 VLOG(2) << "SetWindow";
1002 return NPERR_NO_ERROR; 370 return NPERR_NO_ERROR;
1003 } 371 }
1004 372
1005 } // namespace 373 } // namespace
1006 374
1007 DISABLE_RUNNABLE_METHOD_REFCOUNT(HostNPScriptObject);
1008
1009 #if defined(OS_WIN) 375 #if defined(OS_WIN)
1010 HMODULE g_hModule = NULL; 376 HMODULE g_hModule = NULL;
1011 377
1012 BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) { 378 BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
1013 switch (dwReason) { 379 switch (dwReason) {
1014 case DLL_PROCESS_ATTACH: 380 case DLL_PROCESS_ATTACH:
1015 g_hModule = hModule; 381 g_hModule = hModule;
1016 DisableThreadLibraryCalls(hModule); 382 DisableThreadLibraryCalls(hModule);
1017 break; 383 break;
1018 case DLL_PROCESS_DETACH: 384 case DLL_PROCESS_DETACH:
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 } 445 }
1080 446
1081 EXPORT NPError API_CALL NP_GetValue(void* npp, 447 EXPORT NPError API_CALL NP_GetValue(void* npp,
1082 NPPVariable variable, 448 NPPVariable variable,
1083 void* value) { 449 void* value) {
1084 return GetValue((NPP)npp, variable, value); 450 return GetValue((NPP)npp, variable, value);
1085 } 451 }
1086 #endif 452 #endif
1087 453
1088 } // extern "C" 454 } // extern "C"
OLDNEW
« no previous file with comments | « no previous file | remoting/host/host_plugin_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698