OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "remoting/host/native_messaging/native_messaging_channel.h" | |
6 | |
7 #include "base/basictypes.h" | |
8 #include "base/bind.h" | |
9 #include "base/callback.h" | |
10 #include "base/callback_helpers.h" | |
11 #include "base/location.h" | |
12 #include "base/values.h" | |
13 | |
14 #if defined(OS_POSIX) | |
15 #include <unistd.h> | |
16 #endif | |
17 | |
18 namespace { | |
19 | |
20 base::File DuplicatePlatformFile(base::File file) { | |
21 base::PlatformFile result; | |
22 #if defined(OS_WIN) | |
23 if (!DuplicateHandle(GetCurrentProcess(), | |
24 file.TakePlatformFile(), | |
25 GetCurrentProcess(), | |
26 &result, | |
27 0, | |
28 FALSE, | |
29 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { | |
30 PLOG(ERROR) << "Failed to duplicate handle " << file.GetPlatformFile(); | |
31 return base::File(); | |
32 } | |
33 return base::File(result); | |
34 #elif defined(OS_POSIX) | |
35 result = dup(file.GetPlatformFile()); | |
36 return base::File(result); | |
37 #else | |
38 #error Not implemented. | |
39 #endif | |
40 } | |
41 | |
42 } // namespace | |
43 | |
44 namespace remoting { | |
45 | |
46 NativeMessagingChannel::NativeMessagingChannel( | |
47 base::File input, | |
48 base::File output) | |
49 : native_messaging_reader_(DuplicatePlatformFile(input.Pass())), | |
50 native_messaging_writer_(new NativeMessagingWriter( | |
51 DuplicatePlatformFile(output.Pass()))), | |
52 weak_factory_(this) { | |
53 weak_ptr_ = weak_factory_.GetWeakPtr(); | |
54 } | |
55 | |
56 NativeMessagingChannel::~NativeMessagingChannel() { | |
57 } | |
58 | |
59 void NativeMessagingChannel::Start(const SendMessageCallback& received_message, | |
60 const base::Closure& quit_closure) { | |
61 DCHECK(CalledOnValidThread()); | |
62 DCHECK(received_message_.is_null()); | |
63 DCHECK(quit_closure_.is_null()); | |
64 | |
65 received_message_ = received_message; | |
66 quit_closure_ = quit_closure; | |
67 | |
68 native_messaging_reader_.Start( | |
69 base::Bind(&NativeMessagingChannel::ProcessMessage, weak_ptr_), | |
70 base::Bind(&NativeMessagingChannel::Shutdown, weak_ptr_)); | |
71 } | |
72 | |
73 void NativeMessagingChannel::ProcessMessage(scoped_ptr<base::Value> message) { | |
74 DCHECK(CalledOnValidThread()); | |
75 | |
76 if (message->GetType() != base::Value::TYPE_DICTIONARY) { | |
77 LOG(ERROR) << "Expected DictionaryValue"; | |
78 Shutdown(); | |
79 return; | |
80 } | |
81 | |
82 scoped_ptr<base::DictionaryValue> message_dict( | |
83 static_cast<base::DictionaryValue*>(message.release())); | |
84 received_message_.Run(message_dict.Pass()); | |
85 } | |
86 | |
87 void NativeMessagingChannel::SendMessage( | |
88 scoped_ptr<base::DictionaryValue> message) { | |
89 DCHECK(CalledOnValidThread()); | |
90 | |
91 bool success = message && native_messaging_writer_; | |
92 if (success) | |
93 success = native_messaging_writer_->WriteMessage(*message); | |
94 | |
95 if (!success) { | |
96 // Close the write pipe so no more responses will be sent. | |
97 native_messaging_writer_.reset(); | |
98 Shutdown(); | |
99 } | |
100 } | |
101 | |
102 void NativeMessagingChannel::Shutdown() { | |
103 DCHECK(CalledOnValidThread()); | |
104 | |
105 if (!quit_closure_.is_null()) | |
106 base::ResetAndReturn(&quit_closure_).Run(); | |
107 } | |
108 | |
109 } // namespace remoting | |
OLD | NEW |