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

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

Issue 10918255: The Windows portion of Native Messagaing (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Less Sleepy Created 8 years, 1 month 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 "chrome/browser/extensions/api/messaging/native_message_process_host.h" 5 #include "chrome/browser/extensions/api/messaging/native_message_process_host.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/file_path.h" 8 #include "base/file_path.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/path_service.h" 10 #include "base/path_service.h"
(...skipping 25 matching lines...) Expand all
36 FileHandle write_file, 36 FileHandle write_file,
37 bool is_send_message) 37 bool is_send_message)
38 : weak_client_ui_(weak_client_ui), 38 : weak_client_ui_(weak_client_ui),
39 destination_port_(destination_port), 39 destination_port_(destination_port),
40 native_process_handle_(native_process_handle), 40 native_process_handle_(native_process_handle),
41 read_file_(read_file), 41 read_file_(read_file),
42 write_file_(write_file), 42 write_file_(write_file),
43 scoped_read_file_(&read_file_), 43 scoped_read_file_(&read_file_),
44 scoped_write_file_(&write_file_), 44 scoped_write_file_(&write_file_),
45 is_send_message_(is_send_message) { 45 is_send_message_(is_send_message) {
46 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); 46 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
47 InitIO(); 47 InitIO();
48 } 48 }
49 49
50 NativeMessageProcessHost::~NativeMessageProcessHost() { 50 NativeMessageProcessHost::~NativeMessageProcessHost() {
51 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); 51 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
52
53 StopIO();
54
52 // Give the process some time to shutdown, then try and kill it. 55 // Give the process some time to shutdown, then try and kill it.
53 content::BrowserThread::PostDelayedTask( 56 content::BrowserThread::PostDelayedTask(
54 content::BrowserThread::FILE, 57 content::BrowserThread::IO,
55 FROM_HERE, 58 FROM_HERE,
56 base::Bind(base::IgnoreResult(&base::KillProcess), 59 base::Bind(base::IgnoreResult(&base::KillProcess),
57 native_process_handle_, 60 native_process_handle_,
58 content::RESULT_CODE_NORMAL_EXIT, 61 content::RESULT_CODE_NORMAL_EXIT,
59 false /* don't wait for exit */), 62 false /* don't wait for exit */),
60 base::TimeDelta::FromMilliseconds(kExitTimeoutMS)); 63 base::TimeDelta::FromMilliseconds(kExitTimeoutMS));
61 } 64 }
62 65
63 // static 66 // static
64 void NativeMessageProcessHost::Create(base::WeakPtr<Client> weak_client_ui, 67 void NativeMessageProcessHost::Create(base::WeakPtr<Client> weak_client_ui,
65 const std::string& native_app_name, 68 const std::string& native_app_name,
66 const std::string& connection_message, 69 const std::string& connection_message,
67 int destination_port, 70 int destination_port,
68 MessageType type, 71 MessageType type,
69 CreateCallback callback) { 72 CreateCallback callback) {
70 NativeProcessLauncher launcher;
71 CreateWithLauncher(weak_client_ui, native_app_name, connection_message, 73 CreateWithLauncher(weak_client_ui, native_app_name, connection_message,
72 destination_port, type, callback, launcher); 74 destination_port, type, callback,
75 scoped_ptr<NativeProcessLauncher>(
76 new NativeProcessLauncher()));
73 } 77 }
74 78
75 // static 79 // static
76 void NativeMessageProcessHost::CreateWithLauncher( 80 void NativeMessageProcessHost::CreateWithLauncher(
77 base::WeakPtr<Client> weak_client_ui, 81 base::WeakPtr<Client> weak_client_ui,
78 const std::string& native_app_name, 82 const std::string& native_app_name,
79 const std::string& connection_message, 83 const std::string& connection_message,
80 int destination_port, 84 int destination_port,
81 MessageType type, 85 MessageType type,
82 CreateCallback callback, 86 CreateCallback callback,
83 const NativeProcessLauncher& launcher) { 87 scoped_ptr<NativeProcessLauncher> launcher) {
84 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); 88 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
85 DCHECK(type == TYPE_SEND_MESSAGE_REQUEST || type == TYPE_CONNECT); 89 DCHECK(type == TYPE_SEND_MESSAGE_REQUEST || type == TYPE_CONNECT);
86 90
87 ScopedHost process; 91 ScopedHost process;
88 if (Feature::GetCurrentChannel() > chrome::VersionInfo::CHANNEL_DEV || 92 if (Feature::GetCurrentChannel() > chrome::VersionInfo::CHANNEL_DEV ||
89 !CommandLine::ForCurrentProcess()->HasSwitch( 93 !CommandLine::ForCurrentProcess()->HasSwitch(
90 switches::kEnableNativeMessaging)) { 94 switches::kEnableNativeMessaging)) {
91 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 95 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
92 base::Bind(callback, 96 base::Bind(callback,
93 base::Passed(&process))); 97 base::Passed(&process)));
94 return; 98 return;
95 } 99 }
96 100
101 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
102 base::Bind(&NativeMessageProcessHost::CheckPathOnFileThread,
103 weak_client_ui,
104 native_app_name,
105 connection_message,
106 destination_port,
107 type,
108 callback,
109 base::Passed(&launcher)));
110 }
111
112 // static
113 void NativeMessageProcessHost::CheckPathOnFileThread(
114 base::WeakPtr<Client> weak_client_ui,
115 const std::string& native_app_name,
116 const std::string& connection_message,
117 int destination_port,
118 MessageType type,
119 CreateCallback callback,
120 scoped_ptr<NativeProcessLauncher> launcher) {
121 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
122 ScopedHost process;
97 FilePath native_host_program; 123 FilePath native_host_program;
98 FilePath native_host_registry; 124 FilePath native_host_registry;
99 CHECK(PathService::Get(chrome::DIR_USER_DATA, &native_host_registry)); 125 CHECK(PathService::Get(chrome::DIR_USER_DATA, &native_host_registry));
100 native_host_registry = 126 native_host_registry =
101 native_host_registry.AppendASCII(kNativeHostsDirectoryName); 127 native_host_registry.AppendASCII(kNativeHostsDirectoryName);
102 native_host_program = native_host_registry.AppendASCII(native_app_name); 128 native_host_program = native_host_registry.AppendASCII(native_app_name);
103 129
104 // Make sure that the client is not trying to invoke something outside of the 130 // Make sure that the client is not trying to invoke something outside of the
105 // proper directory. Eg. '../../dangerous_something.exe'. 131 // proper directory. Eg. '../../dangerous_something.exe'.
106 if (!file_util::ContainsPath(native_host_registry, native_host_program)) { 132 if (!file_util::ContainsPath(native_host_registry, native_host_program)) {
107 LOG(ERROR) << "Could not find native host: " << native_app_name; 133 LOG(ERROR) << "Could not find native host: " << native_app_name;
108 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 134 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
109 base::Bind(callback, 135 base::Bind(callback,
110 base::Passed(&process))); 136 base::Passed(&process)));
111 return; 137 return;
112 } 138 }
113 139
140
141 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
142 base::Bind(&NativeMessageProcessHost::FinalizeCreate,
143 weak_client_ui,
144 connection_message,
145 destination_port,
146 type,
147 callback,
148 base::Passed(&launcher),
149 native_host_program));
150 }
151
152 // static
153 void NativeMessageProcessHost::FinalizeCreate(
154 base::WeakPtr<Client> weak_client_ui,
155 const std::string& connection_message,
156 int destination_port,
157 MessageType type,
158 CreateCallback callback,
159 scoped_ptr<NativeProcessLauncher> launcher,
160 FilePath native_host_program) {
161 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
162 ScopedHost process;
114 FileHandle read_handle; 163 FileHandle read_handle;
115 FileHandle write_handle; 164 FileHandle write_handle;
116 base::ProcessHandle native_process_handle; 165 base::ProcessHandle native_process_handle;
117 166
118 if (!launcher.LaunchNativeProcess(native_host_program, 167 if (!launcher->LaunchNativeProcess(native_host_program,
119 &native_process_handle, 168 &native_process_handle,
120 &read_handle, 169 &read_handle,
121 &write_handle)) { 170 &write_handle)) {
122 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 171 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
123 base::Bind(callback, 172 base::Bind(callback,
124 base::Passed(&process))); 173 base::Passed(&process)));
125 return; 174 return;
126 } 175 }
127 176
128 process.reset(new NativeMessageProcessHost( 177 process.reset(new NativeMessageProcessHost(
129 weak_client_ui, destination_port, native_process_handle, read_handle, 178 weak_client_ui, destination_port, native_process_handle, read_handle,
130 write_handle, type == TYPE_SEND_MESSAGE_REQUEST)); 179 write_handle, type == TYPE_SEND_MESSAGE_REQUEST));
131 180
132 process->SendImpl(type, connection_message); 181 process->SendImpl(type, connection_message);
133 182
134 content::BrowserThread::PostTask( 183 content::BrowserThread::PostTask(
135 content::BrowserThread::UI, FROM_HERE, 184 content::BrowserThread::UI, FROM_HERE,
136 base::Bind(callback, base::Passed(&process))); 185 base::Bind(callback, base::Passed(&process)));
137 } 186 }
138 187
139 void NativeMessageProcessHost::SendImpl(MessageType type, 188 void NativeMessageProcessHost::SendImpl(MessageType type,
140 const std::string& json) { 189 const std::string& json) {
141 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); 190 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
142 191
143 // Make sure that the process has not died. 192 // Make sure that the process has not died.
144 if (base::GetTerminationStatus(native_process_handle_, NULL) != 193 if (native_process_handle_ != base::kNullProcessHandle &&
145 base::TERMINATION_STATUS_STILL_RUNNING) { 194 base::GetTerminationStatus(native_process_handle_, NULL) !=
195 base::TERMINATION_STATUS_STILL_RUNNING) {
146 // Notify the message service that the channel should close. 196 // Notify the message service that the channel should close.
147 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 197 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
148 base::Bind(&Client::CloseChannel, weak_client_ui_, 198 base::Bind(&Client::CloseChannel, weak_client_ui_,
149 destination_port_, true)); 199 destination_port_, true));
150 } 200 }
151 201
152 WriteMessage(type, json); 202 WriteMessage(type, json);
153 } 203 }
154 204
155 bool NativeMessageProcessHost::WriteMessage(MessageType type, 205 bool NativeMessageProcessHost::WriteMessage(MessageType type,
(...skipping 11 matching lines...) Expand all
167 217
168 if (!WriteData(write_file_, const_cast<const Pickle*>(&pickle)->payload(), 218 if (!WriteData(write_file_, const_cast<const Pickle*>(&pickle)->payload(),
169 pickle.payload_size())) { 219 pickle.payload_size())) {
170 LOG(ERROR) << "Error writing message to the native client."; 220 LOG(ERROR) << "Error writing message to the native client.";
171 return false; 221 return false;
172 } 222 }
173 223
174 return true; 224 return true;
175 } 225 }
176 226
177 bool NativeMessageProcessHost::ReadMessage(MessageType* type, 227 bool NativeMessageProcessHost::VerifyMessageMetaData(
178 std::string* message) { 228 const char* message_meta_data,
179 // Read the type (uint32) and length (uint32). 229 MessageType* type,
180 char message_meta_data[8]; 230 uint32* message_length) {
181 if (!ReadData(read_file_, message_meta_data, 8)) {
182 LOG(ERROR) << "Error reading the message type and length.";
183 return false;
184 }
185
186 Pickle pickle; 231 Pickle pickle;
187 pickle.WriteBytes(message_meta_data, 8); 232 pickle.WriteBytes(message_meta_data, 8);
188 PickleIterator pickle_it(pickle); 233 PickleIterator pickle_it(pickle);
189 uint32 uint_type; 234 uint32 uint_type;
190 uint32 data_length; 235 uint32 data_length;
191 if (!pickle_it.ReadUInt32(&uint_type) || 236 if (!pickle_it.ReadUInt32(&uint_type) ||
192 !pickle_it.ReadUInt32(&data_length)) { 237 !pickle_it.ReadUInt32(&data_length)) {
193 LOG(ERROR) << "Error getting the message type and length from the pickle."; 238 LOG(ERROR) << "Error getting the message type and length from the pickle.";
194 return false; 239 return false;
195 } 240 }
196 241
197 if (uint_type >= NUM_MESSAGE_TYPES) { 242 if (uint_type >= NUM_MESSAGE_TYPES) {
198 LOG(ERROR) << type << " is not a valid message type."; 243 LOG(ERROR) << type << " is not a valid message type.";
199 return false; 244 return false;
200 } 245 }
201 246
202 if ((is_send_message_ && (uint_type != TYPE_SEND_MESSAGE_RESPONSE)) || 247 if ((is_send_message_ && (uint_type != TYPE_SEND_MESSAGE_RESPONSE)) ||
203 (!is_send_message_ && (uint_type != TYPE_CONNECT_MESSAGE))) { 248 (!is_send_message_ && (uint_type != TYPE_CONNECT_MESSAGE))) {
204 LOG(ERROR) << "Recieved a message of type " << uint_type << ". " 249 LOG(ERROR) << "Recieved a message of type " << uint_type << ". "
205 << "Expecting a message of type " 250 << "Expecting a message of type "
206 << (is_send_message_ ? TYPE_SEND_MESSAGE_RESPONSE : 251 << (is_send_message_ ? TYPE_SEND_MESSAGE_RESPONSE :
207 TYPE_CONNECT_MESSAGE); 252 TYPE_CONNECT_MESSAGE);
208 return false; 253 return false;
209 } 254 }
210 *type = static_cast<MessageType>(uint_type);
211 255
212 if (data_length > kMaxMessageDataLength) { 256 if (data_length > kMaxMessageDataLength) {
213 LOG(ERROR) << data_length << " is too large for the length of a message. " 257 LOG(ERROR) << data_length << " is too large for the length of a message. "
214 << "Max message size is " << kMaxMessageDataLength; 258 << "Max message size is " << kMaxMessageDataLength;
215 return false; 259 return false;
216 } 260 }
217 261
218 message->resize(data_length, '\0'); 262 *type = static_cast<MessageType>(uint_type);
219 if (!ReadData(read_file_, &(*message)[0], data_length)) { 263 *message_length = data_length;
220 LOG(ERROR) << "Error reading the json data.";
221 return false;
222 }
223 264
224 return true; 265 return true;
225 } 266 }
226 267
227 } // namespace extensions 268 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698