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

Side by Side Diff: chrome/browser/extensions/api/messaging/native_message_process_host.cc

Issue 10818013: Native Messaging! (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: MultiPlatform and UnitTest! Created 8 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
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "chrome/browser/extensions/api/messaging/native_message_process_host.h"
6
7 #include "base/file_path.h"
8 #include "base/logging.h"
9 #include "base/path_service.h"
10 #include "base/pickle.h"
11 #include "base/process_util.h"
12 #include "base/values.h"
13 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
14 #include "chrome/common/chrome_paths.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/common/result_codes.h"
17
18 namespace {
19
20 const int kExitTimeoutMS = 5000;
21 const uint32 kMaxMessageDataLength = 10 * 1024 * 1024;
22 const char kNativeHostsDirectoryName[] = "Native Hosts";
23
24 } // namespace
25
26 namespace extensions {
27
28 NativeMessageProcessHost::NativeMessageProcessHost(
29 base::WeakPtr<Client> weak_client,
30 int destination_port,
31 base::ProcessHandle native_process_handle,
32 FileHandle read_file,
33 FileHandle write_file,
34 bool is_send_message)
35 : weak_client_(weak_client),
36 destination_port_(destination_port),
37 native_process_handle_(native_process_handle),
38 read_file_(read_file),
39 write_file_(write_file),
40 is_send_message_(is_send_message) {
41 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
42 scoped_read_file_.reset(&read_file_);
43 scoped_write_file_.reset(&write_file_);
44 InitIO();
45 }
46
47 NativeMessageProcessHost::~NativeMessageProcessHost() {
48 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
49 // Give the process some time to shutdown, then try and kill it.
50 content::BrowserThread::PostDelayedTask(
51 content::BrowserThread::FILE,
52 FROM_HERE,
53 base::Bind(base::IgnoreResult(&base::KillProcess),
54 native_process_handle_,
55 content::RESULT_CODE_NORMAL_EXIT,
56 false /* don't wait for exit */),
57 base::TimeDelta::FromMilliseconds(kExitTimeoutMS));
58 }
59
60 // static
61 void NativeMessageProcessHost::Create(base::WeakPtr<Client> weak_client,
62 const std::string& native_app_name,
63 const std::string& connection_message,
64 int destination_port,
65 MessageType type,
66 CreateCallback callback) {
67 CreateWithLauncher(weak_client, native_app_name, connection_message,
68 destination_port, type, callback,
69 NativeProcessLauncher());
70 }
71
72 // static
73 void NativeMessageProcessHost::CreateWithLauncher(
74 base::WeakPtr<Client> weak_client,
75 const std::string& native_app_name,
76 const std::string& connection_message,
77 int destination_port,
78 MessageType type,
79 CreateCallback callback,
80 const NativeProcessLauncher& launcher) {
81 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
82 DCHECK(type == TYPE_SEND_MESSAGE_REQUEST || type == TYPE_CONNECT);
83
84 FilePath native_host_program;
85 FilePath native_host_registry;
86 CHECK(PathService::Get(chrome::DIR_USER_DATA, &native_host_registry));
87 native_host_registry =
88 native_host_registry.Append(kNativeHostsDirectoryName);
89 native_host_program = native_host_registry.Append(native_app_name);
90
91 NativeMessageProcessHost* process = NULL;
92
93 // Make sure that the client is not trying to invoke something outside of the
94 // proper directory. Eg. '../../dangerous_something.exe'.
95 if (!file_util::ContainsPath(native_host_registry, native_host_program)) {
96 LOG(ERROR) << "Could not find native host: " << native_app_name;
97 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
98 base::Bind(callback, process));
99 return;
100 }
101
102 FileHandle read_handle;
103 FileHandle write_handle;
104 base::ProcessHandle native_process_handle;
105
106 if (!launcher.LaunchNativeProcess(native_host_program,
107 &native_process_handle,
108 &read_handle,
109 &write_handle)) {
110 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
111 base::Bind(callback, process));
112 return;
113 }
114
115 process = new NativeMessageProcessHost(weak_client, destination_port,
116 native_process_handle, read_handle,
Matt Perry 2012/08/22 00:02:42 indent either 4 spaces or to align with the (
eaugusti 2012/08/31 23:47:13 Done.
117 write_handle,
118 type == TYPE_SEND_MESSAGE_REQUEST);
119
120 process->SendImpl(type, connection_message);
121
122 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
123 base::Bind(callback, process));
Matt Perry 2012/08/22 00:02:42 The good news is that since MessageService uses a
eaugusti 2012/08/31 23:47:13 Nice catch, but we also have to make sure process
124 }
125
126 void NativeMessageProcessHost::SendImpl(MessageType type,
127 const std::string& json) {
128 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
129 WriteMessage(type, json);
130 }
131
132 bool NativeMessageProcessHost::WriteMessage(MessageType type,
133 const std::string& message) {
Matt Perry 2012/08/22 00:02:42 bad indent
eaugusti 2012/08/31 23:47:13 Done.
134 Pickle pickle;
135
136 // Pickles will always pad bytes to 32-bit alignment, so just use a unit32.
137 pickle.WriteUInt32(type);
138
139 // Pickles write the length of a string before it as a uint32.
140 pickle.WriteString(message);
141
142 // Make sure that the pickle doesn't do any unexpected padding.
143 CHECK(8 + message.length() == pickle.payload_size());
144
145 if (!WriteData(write_file_, const_cast<const Pickle*>(&pickle)->payload(),
146 pickle.payload_size())) {
147 LOG(ERROR) << "Error writing message to the native client.";
148 return false;
149 }
150
151 return true;
152 }
153
154 bool NativeMessageProcessHost::ReadMessage(MessageType* type,
155 std::string* message) {
Matt Perry 2012/08/22 00:02:42 bad indent
eaugusti 2012/08/31 23:47:13 Done.
156 // Read the type (uint32) and length (uint32).
157 char message_meta_data[8];
158 if (!ReadData(read_file_, message_meta_data, 8)) {
159 LOG(ERROR) << "Error reading the message type and length.";
160 return false;
161 }
162
163 Pickle pickle;
164 pickle.WriteBytes(message_meta_data, 8);
Matt Perry 2012/08/22 00:02:42 Use "Pickle pickle(message_meta_data, 8)" to avoid
eaugusti 2012/08/31 23:47:13 We can't use that because then Pickle assumes that
165 PickleIterator pickle_it(pickle);
166 uint32 int_type;
167 uint32 data_length;
168 if (!pickle_it.ReadUInt32(&int_type) || !pickle_it.ReadUInt32(&data_length)) {
169 LOG(ERROR) << "Error getting the message type and length from the pickle.";
170 return false;
171 }
172
173 if (int_type < 0 || int_type >= NUM_MESSAGE_TYPES) {
174 LOG(ERROR) << type << " is not a valid message type.";
175 return false;
176 }
177
178 if ((is_send_message_ && (int_type != TYPE_SEND_MESSAGE_RESPONSE)) ||
179 (!is_send_message_ && (int_type != TYPE_CONNECT_MESSAGE))) {
180 LOG(ERROR) << "Recieved a message of type " << int_type << ". "
181 << "Expecting a message of type "
182 << (is_send_message_ ? TYPE_SEND_MESSAGE_RESPONSE :
183 TYPE_CONNECT_MESSAGE);
184 return false;
185 }
186 *type = static_cast<MessageType>(int_type);
187
188 if (data_length > kMaxMessageDataLength) {
189 LOG(ERROR) << data_length << " is too large for the length of a message. "
190 << "Max message size is " << kMaxMessageDataLength;
191 return false;
192 }
193
194 message->resize(data_length, '\0');
195 if (!ReadData(read_file_, &(*message)[0], data_length)) {
196 LOG(ERROR) << "Error reading the json data.";
197 return false;
198 }
199
200 return true;
201 }
202
203 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698