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

Side by Side Diff: remoting/host/me2me_preference_pane.mm

Issue 10383204: Build pref-pane as universal binary on Mac OS X (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 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/remoting.gyp » ('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) 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 #import "remoting/host/me2me_preference_pane.h" 5 #import "remoting/host/me2me_preference_pane.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 #include <CommonCrypto/CommonHMAC.h> 8 #include <CommonCrypto/CommonHMAC.h>
9 #include <errno.h>
9 #include <launch.h> 10 #include <launch.h>
10 #import <PreferencePanes/PreferencePanes.h> 11 #import <PreferencePanes/PreferencePanes.h>
11 #import <SecurityInterface/SFAuthorizationView.h> 12 #import <SecurityInterface/SFAuthorizationView.h>
13 #include <stdlib.h>
12 #include <unistd.h> 14 #include <unistd.h>
13 15
14 #include <fstream> 16 #include <fstream>
15 17
16 #include "base/eintr_wrapper.h" 18 #include "base/eintr_wrapper.h"
17 #include "base/logging.h"
18 #include "base/mac/authorization_util.h"
19 #include "base/mac/foundation_util.h"
20 #include "base/mac/launchd.h"
21 #include "base/mac/mac_logging.h"
22 #include "base/mac/scoped_launch_data.h" 19 #include "base/mac/scoped_launch_data.h"
23 #include "base/memory/scoped_ptr.h" 20 #include "base/memory/scoped_ptr.h"
24 #include "base/stringprintf.h"
25 #include "base/sys_string_conversions.h"
26 #include "remoting/host/host_config.h" 21 #include "remoting/host/host_config.h"
27 #import "remoting/host/me2me_preference_pane_confirm_pin.h" 22 #import "remoting/host/me2me_preference_pane_confirm_pin.h"
28 #import "remoting/host/me2me_preference_pane_disable.h" 23 #import "remoting/host/me2me_preference_pane_disable.h"
29 #include "third_party/jsoncpp/source/include/json/reader.h" 24 #include "third_party/jsoncpp/source/include/json/reader.h"
30 #include "third_party/jsoncpp/source/include/json/writer.h" 25 #include "third_party/jsoncpp/source/include/json/writer.h"
31 #include "third_party/modp_b64/modp_b64.h" 26 #include "third_party/modp_b64/modp_b64.h"
32 27
33 namespace { 28 namespace {
34 // The name of the Remoting Host service that is registered with launchd. 29 // The name of the Remoting Host service that is registered with launchd.
35 #define kServiceName "org.chromium.chromoting" 30 #define kServiceName "org.chromium.chromoting"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 const std::string& host_secret_hash) { 63 const std::string& host_secret_hash) {
69 // TODO(lambroslambrou): Once the "base" target supports building for 64-bit 64 // TODO(lambroslambrou): Once the "base" target supports building for 64-bit
70 // on Mac OS X, remove this code and replace it with |VerifyHostPinHash()| 65 // on Mac OS X, remove this code and replace it with |VerifyHostPinHash()|
71 // from host/pin_hash.h. 66 // from host/pin_hash.h.
72 size_t separator = host_secret_hash.find(':'); 67 size_t separator = host_secret_hash.find(':');
73 if (separator == std::string::npos) 68 if (separator == std::string::npos)
74 return false; 69 return false;
75 70
76 std::string method = host_secret_hash.substr(0, separator); 71 std::string method = host_secret_hash.substr(0, separator);
77 if (method != "hmac") { 72 if (method != "hmac") {
78 LOG(ERROR) << "Authentication method '" << method << "' not supported"; 73 NSLog(@"Authentication method '%s' not supported", method.c_str());
79 return false; 74 return false;
80 } 75 }
81 76
82 std::string hash_base64 = host_secret_hash.substr(separator + 1); 77 std::string hash_base64 = host_secret_hash.substr(separator + 1);
83 78
84 // Convert |hash_base64| to |hash|, based on code from base/base64.cc. 79 // Convert |hash_base64| to |hash|, based on code from base/base64.cc.
85 int hash_base64_size = static_cast<int>(hash_base64.size()); 80 int hash_base64_size = static_cast<int>(hash_base64.size());
86 std::string hash; 81 std::string hash;
87 hash.resize(modp_b64_decode_len(hash_base64_size)); 82 hash.resize(modp_b64_decode_len(hash_base64_size));
88 83
89 // modp_b64_decode_len() returns at least 1, so hash[0] is safe here. 84 // modp_b64_decode_len() returns at least 1, so hash[0] is safe here.
90 int hash_size = modp_b64_decode(&(hash[0]), hash_base64.data(), 85 int hash_size = modp_b64_decode(&(hash[0]), hash_base64.data(),
91 hash_base64_size); 86 hash_base64_size);
92 if (hash_size < 0) { 87 if (hash_size < 0) {
93 LOG(ERROR) << "Failed to parse host_secret_hash"; 88 NSLog(@"Failed to parse host_secret_hash");
94 return false; 89 return false;
95 } 90 }
96 hash.resize(hash_size); 91 hash.resize(hash_size);
97 92
98 std::string computed_hash; 93 std::string computed_hash;
99 computed_hash.resize(CC_SHA256_DIGEST_LENGTH); 94 computed_hash.resize(CC_SHA256_DIGEST_LENGTH);
100 95
101 CCHmac(kCCHmacAlgSHA256, 96 CCHmac(kCCHmacAlgSHA256,
102 host_id.data(), host_id.size(), 97 host_id.data(), host_id.size(),
103 pin.data(), pin.size(), 98 pin.data(), pin.size(),
104 &(computed_hash[0])); 99 &(computed_hash[0]));
105 100
106 // Normally, a constant-time comparison function would be used, but it is 101 // Normally, a constant-time comparison function would be used, but it is
107 // unnecessary here as the "secret" is already readable by the user 102 // unnecessary here as the "secret" is already readable by the user
108 // supplying input to this routine. 103 // supplying input to this routine.
109 return computed_hash == hash; 104 return computed_hash == hash;
110 } 105 }
111 106
112 } // namespace 107 } // namespace
113 108
109 // These methods are copied from base/mac, but with the logging changed to use
110 // NSLog().
111 //
112 // TODO(lambroslambrou): Once the "base" target supports building for 64-bit
113 // on Mac OS X, remove these implementations and use the ones in base/mac.
114 namespace base {
115 namespace mac {
116
117 // MessageForJob sends a single message to launchd with a simple dictionary
118 // mapping |operation| to |job_label|, and returns the result of calling
119 // launch_msg to send that message. On failure, returns NULL. The caller
120 // assumes ownership of the returned launch_data_t object.
121 launch_data_t MessageForJob(const std::string& job_label,
122 const char* operation) {
123 // launch_data_alloc returns something that needs to be freed.
124 ScopedLaunchData message(launch_data_alloc(LAUNCH_DATA_DICTIONARY));
125 if (!message) {
126 NSLog(@"launch_data_alloc");
127 return NULL;
128 }
129
130 // launch_data_new_string returns something that needs to be freed, but
131 // the dictionary will assume ownership when launch_data_dict_insert is
132 // called, so put it in a scoper and .release() it when given to the
133 // dictionary.
134 ScopedLaunchData job_label_launchd(launch_data_new_string(job_label.c_str()));
135 if (!job_label_launchd) {
136 NSLog(@"launch_data_new_string");
137 return NULL;
138 }
139
140 if (!launch_data_dict_insert(message,
141 job_label_launchd.release(),
142 operation)) {
143 return NULL;
144 }
145
146 return launch_msg(message);
147 }
148
149 pid_t PIDForJob(const std::string& job_label) {
150 ScopedLaunchData response(MessageForJob(job_label, LAUNCH_KEY_GETJOB));
151 if (!response) {
152 return -1;
153 }
154
155 launch_data_type_t response_type = launch_data_get_type(response);
156 if (response_type != LAUNCH_DATA_DICTIONARY) {
157 if (response_type == LAUNCH_DATA_ERRNO) {
158 NSLog(@"PIDForJob: error %d", launch_data_get_errno(response));
159 } else {
160 NSLog(@"PIDForJob: expected dictionary, got %d", response_type);
161 }
162 return -1;
163 }
164
165 launch_data_t pid_data = launch_data_dict_lookup(response,
166 LAUNCH_JOBKEY_PID);
167 if (!pid_data)
168 return 0;
169
170 if (launch_data_get_type(pid_data) != LAUNCH_DATA_INTEGER) {
171 NSLog(@"PIDForJob: expected integer");
172 return -1;
173 }
174
175 return launch_data_get_integer(pid_data);
176 }
177
178 OSStatus ExecuteWithPrivilegesAndGetPID(AuthorizationRef authorization,
179 const char* tool_path,
180 AuthorizationFlags options,
181 const char** arguments,
182 FILE** pipe,
183 pid_t* pid) {
184 // pipe may be NULL, but this function needs one. In that case, use a local
185 // pipe.
186 FILE* local_pipe;
187 FILE** pipe_pointer;
188 if (pipe) {
189 pipe_pointer = pipe;
190 } else {
191 pipe_pointer = &local_pipe;
192 }
193
194 // AuthorizationExecuteWithPrivileges wants |char* const*| for |arguments|,
195 // but it doesn't actually modify the arguments, and that type is kind of
196 // silly and callers probably aren't dealing with that. Put the cast here
197 // to make things a little easier on callers.
198 OSStatus status = AuthorizationExecuteWithPrivileges(authorization,
199 tool_path,
200 options,
201 (char* const*)arguments,
202 pipe_pointer);
203 if (status != errAuthorizationSuccess) {
204 return status;
205 }
206
207 long line_pid = -1;
208 size_t line_length = 0;
209 char* line_c = fgetln(*pipe_pointer, &line_length);
210 if (line_c) {
211 if (line_length > 0 && line_c[line_length - 1] == '\n') {
212 // line_c + line_length is the start of the next line if there is one.
213 // Back up one character.
214 --line_length;
215 }
216 std::string line(line_c, line_length);
217
218 // The version in base/mac used base::StringToInt() here.
219 line_pid = strtol(line.c_str(), NULL, 10);
220 if (line_pid == 0) {
221 NSLog(@"ExecuteWithPrivilegesAndGetPid: funny line: %s", line.c_str());
222 line_pid = -1;
223 }
224 } else {
225 NSLog(@"ExecuteWithPrivilegesAndGetPid: no line");
226 }
227
228 if (!pipe) {
229 fclose(*pipe_pointer);
230 }
231
232 if (pid) {
233 *pid = line_pid;
234 }
235
236 return status;
237 }
238
239 } // namespace mac
240 } // namespace base
241
114 namespace remoting { 242 namespace remoting {
115 JsonHostConfig::JsonHostConfig(const std::string& filename) 243 JsonHostConfig::JsonHostConfig(const std::string& filename)
116 : filename_(filename) { 244 : filename_(filename) {
117 } 245 }
118 246
119 JsonHostConfig::~JsonHostConfig() { 247 JsonHostConfig::~JsonHostConfig() {
120 } 248 }
121 249
122 bool JsonHostConfig::Read() { 250 bool JsonHostConfig::Read() {
123 std::ifstream file(filename_.c_str()); 251 std::ifstream file(filename_.c_str());
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 if (!have_new_config_) { 336 if (!have_new_config_) {
209 // It shouldn't be possible to hit the button if there is no config to 337 // It shouldn't be possible to hit the button if there is no config to
210 // apply, but check anyway just in case it happens somehow. 338 // apply, but check anyway just in case it happens somehow.
211 return; 339 return;
212 } 340 }
213 341
214 // Ensure the authorization token is up-to-date before using it. 342 // Ensure the authorization token is up-to-date before using it.
215 [self updateAuthorizationStatus]; 343 [self updateAuthorizationStatus];
216 [self updateUI]; 344 [self updateUI];
217 345
218 std::string pin_utf8 = base::SysNSStringToUTF8(pin); 346 std::string pin_utf8 = [pin UTF8String];
219 std::string host_id, host_secret_hash; 347 std::string host_id, host_secret_hash;
220 bool result = (config_->GetString(remoting::kHostIdConfigPath, &host_id) && 348 bool result = (config_->GetString(remoting::kHostIdConfigPath, &host_id) &&
221 config_->GetString(remoting::kHostSecretHashConfigPath, 349 config_->GetString(remoting::kHostSecretHashConfigPath,
222 &host_secret_hash)); 350 &host_secret_hash));
223 DCHECK(result); 351 if (!result) {
352 [self showError];
353 return;
354 }
224 if (!IsPinValid(pin_utf8, host_id, host_secret_hash)) { 355 if (!IsPinValid(pin_utf8, host_id, host_secret_hash)) {
225 [self showIncorrectPinMessage]; 356 [self showIncorrectPinMessage];
226 return; 357 return;
227 } 358 }
228 359
229 [self applyNewServiceConfig]; 360 [self applyNewServiceConfig];
230 [self updateUI]; 361 [self updateUI];
231 } 362 }
232 363
233 - (void)onDisable:(id)sender { 364 - (void)onDisable:(id)sender {
234 // Ensure the authorization token is up-to-date before using it. 365 // Ensure the authorization token is up-to-date before using it.
235 [self updateAuthorizationStatus]; 366 [self updateAuthorizationStatus];
236 [self updateUI]; 367 [self updateUI];
237 if (!is_pane_unlocked_) 368 if (!is_pane_unlocked_)
238 return; 369 return;
239 370
240 if (![self runHelperAsRootWithCommand:"--disable" 371 if (![self runHelperAsRootWithCommand:"--disable"
241 inputData:""]) { 372 inputData:""]) {
242 LOG(ERROR) << "Failed to run the helper tool"; 373 NSLog(@"Failed to run the helper tool");
243 [self showError]; 374 [self showError];
244 [self notifyPlugin: kUpdateFailedNotificationName]; 375 [self notifyPlugin: kUpdateFailedNotificationName];
245 return; 376 return;
246 } 377 }
247 378
248 // Stop the launchd job. This cannot easily be done by the helper tool, 379 // Stop the launchd job. This cannot easily be done by the helper tool,
249 // since the launchd job runs in the current user's context. 380 // since the launchd job runs in the current user's context.
250 [self sendJobControlMessage:LAUNCH_KEY_STOPJOB]; 381 [self sendJobControlMessage:LAUNCH_KEY_STOPJOB];
251 awaiting_service_stop_ = YES; 382 awaiting_service_stop_ = YES;
252 } 383 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 is_service_running_ = (job_pid > 0); 417 is_service_running_ = (job_pid > 0);
287 } 418 }
288 419
289 - (void)updateAuthorizationStatus { 420 - (void)updateAuthorizationStatus {
290 is_pane_unlocked_ = [authorization_view_ updateStatus:authorization_view_]; 421 is_pane_unlocked_ = [authorization_view_ updateStatus:authorization_view_];
291 } 422 }
292 423
293 - (void)readNewConfig { 424 - (void)readNewConfig {
294 std::string file; 425 std::string file;
295 if (!GetTemporaryConfigFilePath(&file)) { 426 if (!GetTemporaryConfigFilePath(&file)) {
296 LOG(ERROR) << "Failed to get path of configuration data."; 427 NSLog(@"Failed to get path of configuration data.");
297 [self showError]; 428 [self showError];
298 return; 429 return;
299 } 430 }
300 if (access(file.c_str(), F_OK) != 0) 431 if (access(file.c_str(), F_OK) != 0)
301 return; 432 return;
302 433
303 scoped_ptr<remoting::JsonHostConfig> new_config_( 434 scoped_ptr<remoting::JsonHostConfig> new_config_(
304 new remoting::JsonHostConfig(file)); 435 new remoting::JsonHostConfig(file));
305 if (!new_config_->Read()) { 436 if (!new_config_->Read()) {
306 // Report the error, because the file exists but couldn't be read. The 437 // Report the error, because the file exists but couldn't be read. The
307 // case of non-existence is normal and expected. 438 // case of non-existence is normal and expected.
308 LOG(ERROR) << "Error reading configuration data from " << file.c_str(); 439 NSLog(@"Error reading configuration data from %s", file.c_str());
309 [self showError]; 440 [self showError];
310 return; 441 return;
311 } 442 }
312 remove(file.c_str()); 443 remove(file.c_str());
313 if (!IsConfigValid(new_config_.get())) { 444 if (!IsConfigValid(new_config_.get())) {
314 LOG(ERROR) << "Invalid configuration data read."; 445 NSLog(@"Invalid configuration data read.");
315 [self showError]; 446 [self showError];
316 return; 447 return;
317 } 448 }
318 449
319 config_.swap(new_config_); 450 config_.swap(new_config_);
320 have_new_config_ = YES; 451 have_new_config_ = YES;
321 452
322 [confirm_pin_view_ resetPin]; 453 [confirm_pin_view_ resetPin];
323 } 454 }
324 455
(...skipping 20 matching lines...) Expand all
345 message = @"Remote connections to this computer are disabled."; 476 message = @"Remote connections to this computer are disabled.";
346 } 477 }
347 } 478 }
348 [status_message_ setStringValue:message]; 479 [status_message_ setStringValue:message];
349 480
350 std::string email; 481 std::string email;
351 if (config_.get()) { 482 if (config_.get()) {
352 bool result = config_->GetString(remoting::kXmppLoginConfigPath, &email); 483 bool result = config_->GetString(remoting::kXmppLoginConfigPath, &email);
353 484
354 // The config has already been checked by |IsConfigValid|. 485 // The config has already been checked by |IsConfigValid|.
355 DCHECK(result); 486 if (!result) {
487 [self showError];
488 return;
489 }
356 } 490 }
357
358 [disable_view_ setEnabled:(is_pane_unlocked_ && is_service_running_ && 491 [disable_view_ setEnabled:(is_pane_unlocked_ && is_service_running_ &&
359 !restart_pending_or_canceled_)]; 492 !restart_pending_or_canceled_)];
360 [confirm_pin_view_ setEnabled:(is_pane_unlocked_ && 493 [confirm_pin_view_ setEnabled:(is_pane_unlocked_ &&
361 !restart_pending_or_canceled_)]; 494 !restart_pending_or_canceled_)];
362 [confirm_pin_view_ setEmail:base::SysUTF8ToNSString(email)]; 495 [confirm_pin_view_ setEmail:[NSString stringWithUTF8String:email.c_str()]];
363 NSString* applyButtonText = is_service_running_ ? @"Confirm" : @"Enable"; 496 NSString* applyButtonText = is_service_running_ ? @"Confirm" : @"Enable";
364 [confirm_pin_view_ setButtonText:applyButtonText]; 497 [confirm_pin_view_ setButtonText:applyButtonText];
365 498
366 if (restart_pending_or_canceled_) 499 if (restart_pending_or_canceled_)
367 [authorization_view_ setEnabled:NO]; 500 [authorization_view_ setEnabled:NO];
368 } 501 }
369 502
370 - (void)showError { 503 - (void)showError {
371 NSAlert* alert = [[NSAlert alloc] init]; 504 NSAlert* alert = [[NSAlert alloc] init];
372 [alert setMessageText:@"An unexpected error occurred."]; 505 [alert setMessageText:@"An unexpected error occurred."];
(...skipping 16 matching lines...) Expand all
389 contextInfo:nil]; 522 contextInfo:nil];
390 [alert release]; 523 [alert release];
391 } 524 }
392 525
393 - (void)applyNewServiceConfig { 526 - (void)applyNewServiceConfig {
394 [self updateServiceStatus]; 527 [self updateServiceStatus];
395 std::string serialized_config = config_->GetSerializedData(); 528 std::string serialized_config = config_->GetSerializedData();
396 const char* command = is_service_running_ ? "--save-config" : "--enable"; 529 const char* command = is_service_running_ ? "--save-config" : "--enable";
397 if (![self runHelperAsRootWithCommand:command 530 if (![self runHelperAsRootWithCommand:command
398 inputData:serialized_config]) { 531 inputData:serialized_config]) {
399 LOG(ERROR) << "Failed to run the helper tool"; 532 NSLog(@"Failed to run the helper tool");
400 [self showError]; 533 [self showError];
401 return; 534 return;
402 } 535 }
403 536
404 have_new_config_ = NO; 537 have_new_config_ = NO;
405 538
406 // If the service is running, send a signal to cause it to reload its 539 // If the service is running, send a signal to cause it to reload its
407 // configuration, otherwise start the service. 540 // configuration, otherwise start the service.
408 if (is_service_running_) { 541 if (is_service_running_) {
409 pid_t job_pid = base::mac::PIDForJob(kServiceName); 542 pid_t job_pid = base::mac::PIDForJob(kServiceName);
410 if (job_pid > 0) { 543 if (job_pid > 0) {
411 kill(job_pid, SIGHUP); 544 kill(job_pid, SIGHUP);
412 } else { 545 } else {
413 LOG(ERROR) << "Failed to obtain PID of service " << kServiceName; 546 NSLog(@"Failed to obtain PID of service " kServiceName);
414 [self showError]; 547 [self showError];
415 } 548 }
416 } else { 549 } else {
417 [self sendJobControlMessage:LAUNCH_KEY_STARTJOB]; 550 [self sendJobControlMessage:LAUNCH_KEY_STARTJOB];
418 } 551 }
419 552
420 // Broadcast a distributed notification to inform the plugin that the 553 // Broadcast a distributed notification to inform the plugin that the
421 // configuration has been applied. 554 // configuration has been applied.
422 [self notifyPlugin: kUpdateSucceededNotificationName]; 555 [self notifyPlugin: kUpdateSucceededNotificationName];
423 } 556 }
424 557
425 - (BOOL)runHelperAsRootWithCommand:(const char*)command 558 - (BOOL)runHelperAsRootWithCommand:(const char*)command
426 inputData:(const std::string&)input_data { 559 inputData:(const std::string&)input_data {
427 AuthorizationRef authorization = 560 AuthorizationRef authorization =
428 [[authorization_view_ authorization] authorizationRef]; 561 [[authorization_view_ authorization] authorizationRef];
429 if (!authorization) { 562 if (!authorization) {
430 LOG(ERROR) << "Failed to obtain authorizationRef"; 563 NSLog(@"Failed to obtain authorizationRef");
431 return NO; 564 return NO;
432 } 565 }
433 566
434 // TODO(lambroslambrou): Replace the deprecated ExecuteWithPrivileges 567 // TODO(lambroslambrou): Replace the deprecated ExecuteWithPrivileges
435 // call with a launchd-based helper tool, which is more secure. 568 // call with a launchd-based helper tool, which is more secure.
436 // http://crbug.com/120903 569 // http://crbug.com/120903
437 const char* arguments[] = { command, NULL }; 570 const char* arguments[] = { command, NULL };
438 FILE* pipe = NULL; 571 FILE* pipe = NULL;
439 pid_t pid; 572 pid_t pid;
440 OSStatus status = base::mac::ExecuteWithPrivilegesAndGetPID( 573 OSStatus status = base::mac::ExecuteWithPrivilegesAndGetPID(
441 authorization, 574 authorization,
442 kHelperTool, 575 kHelperTool,
443 kAuthorizationFlagDefaults, 576 kAuthorizationFlagDefaults,
444 arguments, 577 arguments,
445 &pipe, 578 &pipe,
446 &pid); 579 &pid);
447 if (status != errAuthorizationSuccess) { 580 if (status != errAuthorizationSuccess) {
448 OSSTATUS_LOG(ERROR, status) << "AuthorizationExecuteWithPrivileges"; 581 NSLog(@"AuthorizationExecuteWithPrivileges: %s (%d)",
582 GetMacOSStatusErrorString(status), static_cast<int>(status));
449 return NO; 583 return NO;
450 } 584 }
451 if (pid == -1) { 585 if (pid == -1) {
452 LOG(ERROR) << "Failed to get child PID"; 586 NSLog(@"Failed to get child PID");
453 if (pipe) 587 if (pipe)
454 fclose(pipe); 588 fclose(pipe);
455 589
456 return NO; 590 return NO;
457 } 591 }
458 if (!pipe) { 592 if (!pipe) {
459 LOG(ERROR) << "Unexpected NULL pipe"; 593 NSLog(@"Unexpected NULL pipe");
460 return NO; 594 return NO;
461 } 595 }
462 596
463 // Some cleanup is needed (closing the pipe and waiting for the child 597 // Some cleanup is needed (closing the pipe and waiting for the child
464 // process), so flag any errors before returning. 598 // process), so flag any errors before returning.
465 BOOL error = NO; 599 BOOL error = NO;
466 600
467 if (!input_data.empty()) { 601 if (!input_data.empty()) {
468 size_t bytes_written = fwrite(input_data.data(), sizeof(char), 602 size_t bytes_written = fwrite(input_data.data(), sizeof(char),
469 input_data.size(), pipe); 603 input_data.size(), pipe);
470 // According to the fwrite manpage, a partial count is returned only if a 604 // According to the fwrite manpage, a partial count is returned only if a
471 // write error has occurred. 605 // write error has occurred.
472 if (bytes_written != input_data.size()) { 606 if (bytes_written != input_data.size()) {
473 LOG(ERROR) << "Failed to write data to child process"; 607 NSLog(@"Failed to write data to child process");
474 error = YES; 608 error = YES;
475 } 609 }
476 } 610 }
477 611
478 // In all cases, fclose() should be called with the returned FILE*. In the 612 // In all cases, fclose() should be called with the returned FILE*. In the
479 // case of sending data to the child, this needs to be done before calling 613 // case of sending data to the child, this needs to be done before calling
480 // waitpid(), since the child reads until EOF on its stdin, so calling 614 // waitpid(), since the child reads until EOF on its stdin, so calling
481 // waitpid() first would result in deadlock. 615 // waitpid() first would result in deadlock.
482 if (fclose(pipe) != 0) { 616 if (fclose(pipe) != 0) {
483 PLOG(ERROR) << "fclose"; 617 NSLog(@"fclose failed with error %d", errno);
484 error = YES; 618 error = YES;
485 } 619 }
486 620
487 int exit_status; 621 int exit_status;
488 pid_t wait_result = HANDLE_EINTR(waitpid(pid, &exit_status, 0)); 622 pid_t wait_result = HANDLE_EINTR(waitpid(pid, &exit_status, 0));
489 if (wait_result != pid) { 623 if (wait_result != pid) {
490 PLOG(ERROR) << "waitpid"; 624 NSLog(@"waitpid failed with error %d", errno);
491 error = YES; 625 error = YES;
492 } 626 }
493 627
494 // No more cleanup needed. 628 // No more cleanup needed.
495 if (error) 629 if (error)
496 return NO; 630 return NO;
497 631
498 if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 0) { 632 if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 0) {
499 return YES; 633 return YES;
500 } else { 634 } else {
501 LOG(ERROR) << kHelperTool << " failed with exit status " << exit_status; 635 NSLog(@"%s failed with exit status %d", kHelperTool, exit_status);
502 return NO; 636 return NO;
503 } 637 }
504 } 638 }
505 639
506 - (BOOL)sendJobControlMessage:(const char*)launch_key { 640 - (BOOL)sendJobControlMessage:(const char*)launch_key {
507 base::mac::ScopedLaunchData response( 641 base::mac::ScopedLaunchData response(
508 base::mac::MessageForJob(kServiceName, launch_key)); 642 base::mac::MessageForJob(kServiceName, launch_key));
509 if (!response) { 643 if (!response) {
510 LOG(ERROR) << "Failed to send message to launchd"; 644 NSLog(@"Failed to send message to launchd");
511 [self showError]; 645 [self showError];
512 return NO; 646 return NO;
513 } 647 }
514 648
515 // Expect a response of type LAUNCH_DATA_ERRNO. 649 // Expect a response of type LAUNCH_DATA_ERRNO.
516 launch_data_type_t type = launch_data_get_type(response.get()); 650 launch_data_type_t type = launch_data_get_type(response.get());
517 if (type != LAUNCH_DATA_ERRNO) { 651 if (type != LAUNCH_DATA_ERRNO) {
518 LOG(ERROR) << "launchd returned unexpected type: " << type; 652 NSLog(@"launchd returned unexpected type: %d", type);
519 [self showError]; 653 [self showError];
520 return NO; 654 return NO;
521 } 655 }
522 656
523 int error = launch_data_get_errno(response.get()); 657 int error = launch_data_get_errno(response.get());
524 if (error) { 658 if (error) {
525 LOG(ERROR) << "launchd returned error: " << error; 659 NSLog(@"launchd returned error: %d", error);
526 [self showError]; 660 [self showError];
527 return NO; 661 return NO;
528 } 662 }
529 return YES; 663 return YES;
530 } 664 }
531 665
532 - (void)notifyPlugin:(const char*)message { 666 - (void)notifyPlugin:(const char*)message {
533 NSDistributedNotificationCenter* center = 667 NSDistributedNotificationCenter* center =
534 [NSDistributedNotificationCenter defaultCenter]; 668 [NSDistributedNotificationCenter defaultCenter];
535 NSString* name = [NSString stringWithUTF8String:message]; 669 NSString* name = [NSString stringWithUTF8String:message];
(...skipping 13 matching lines...) Expand all
549 NSString* this_version = [this_plist objectForKey:@"CFBundleVersion"]; 683 NSString* this_version = [this_plist objectForKey:@"CFBundleVersion"];
550 684
551 NSString* bundle_path = [this_bundle bundlePath]; 685 NSString* bundle_path = [this_bundle bundlePath];
552 NSString* plist_path = 686 NSString* plist_path =
553 [bundle_path stringByAppendingString:@"/Contents/Info.plist"]; 687 [bundle_path stringByAppendingString:@"/Contents/Info.plist"];
554 NSDictionary* disk_plist = 688 NSDictionary* disk_plist =
555 [NSDictionary dictionaryWithContentsOfFile:plist_path]; 689 [NSDictionary dictionaryWithContentsOfFile:plist_path];
556 NSString* disk_version = [disk_plist objectForKey:@"CFBundleVersion"]; 690 NSString* disk_version = [disk_plist objectForKey:@"CFBundleVersion"];
557 691
558 if (disk_version == nil) { 692 if (disk_version == nil) {
559 LOG(ERROR) << "Failed to get installed version information"; 693 NSLog(@"Failed to get installed version information");
560 [self showError]; 694 [self showError];
561 return; 695 return;
562 } 696 }
563 697
564 if ([this_version isEqualToString:disk_version]) 698 if ([this_version isEqualToString:disk_version])
565 return; 699 return;
566 700
567 restart_pending_or_canceled_ = YES; 701 restart_pending_or_canceled_ = YES;
568 [self updateUI]; 702 [self updateUI];
569 } 703 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 743
610 // If there is a new config file, delete it and notify the web-app of 744 // If there is a new config file, delete it and notify the web-app of
611 // failure to apply the config. Otherwise, the web-app will remain in a 745 // failure to apply the config. Otherwise, the web-app will remain in a
612 // spinning state until System Preferences eventually gets restarted and 746 // spinning state until System Preferences eventually gets restarted and
613 // the user visits this pane again. 747 // the user visits this pane again.
614 std::string file; 748 std::string file;
615 if (!GetTemporaryConfigFilePath(&file)) { 749 if (!GetTemporaryConfigFilePath(&file)) {
616 // There's no point in alerting the user here. The same error would 750 // There's no point in alerting the user here. The same error would
617 // happen when the pane is eventually restarted, so the user would be 751 // happen when the pane is eventually restarted, so the user would be
618 // alerted at that time. 752 // alerted at that time.
619 LOG(ERROR) << "Failed to get path of configuration data."; 753 NSLog(@"Failed to get path of configuration data.");
620 return; 754 return;
621 } 755 }
622 if (access(file.c_str(), F_OK) != 0) 756 if (access(file.c_str(), F_OK) != 0)
623 return; 757 return;
624 758
625 remove(file.c_str()); 759 remove(file.c_str());
626 [self notifyPlugin:kUpdateFailedNotificationName]; 760 [self notifyPlugin:kUpdateFailedNotificationName];
627 } 761 }
628 } 762 }
629 763
630 - (void)restartSystemPreferences { 764 - (void)restartSystemPreferences {
631 NSTask* task = [[NSTask alloc] init]; 765 NSTask* task = [[NSTask alloc] init];
632 NSArray* arguments = [NSArray arrayWithObjects:@"--relaunch-prefpane", nil]; 766 NSArray* arguments = [NSArray arrayWithObjects:@"--relaunch-prefpane", nil];
633 [task setLaunchPath:[NSString stringWithUTF8String:kHelperTool]]; 767 [task setLaunchPath:[NSString stringWithUTF8String:kHelperTool]];
634 [task setArguments:arguments]; 768 [task setArguments:arguments];
635 [task setStandardInput:[NSPipe pipe]]; 769 [task setStandardInput:[NSPipe pipe]];
636 [task launch]; 770 [task launch];
637 [task release]; 771 [task release];
638 [NSApp terminate:nil]; 772 [NSApp terminate:nil];
639 } 773 }
640 774
641 @end 775 @end
OLDNEW
« no previous file with comments | « no previous file | remoting/remoting.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698