OLD | NEW |
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 <errno.h> |
10 #include <launch.h> | 10 #include <launch.h> |
(...skipping 15 matching lines...) Expand all Loading... |
26 #include "third_party/jsoncpp/source/include/json/writer.h" | 26 #include "third_party/jsoncpp/source/include/json/writer.h" |
27 #include "third_party/modp_b64/modp_b64.h" | 27 #include "third_party/modp_b64/modp_b64.h" |
28 | 28 |
29 namespace { | 29 namespace { |
30 | 30 |
31 bool GetTemporaryConfigFilePath(std::string* path) { | 31 bool GetTemporaryConfigFilePath(std::string* path) { |
32 NSString* filename = NSTemporaryDirectory(); | 32 NSString* filename = NSTemporaryDirectory(); |
33 if (filename == nil) | 33 if (filename == nil) |
34 return false; | 34 return false; |
35 | 35 |
36 filename = [filename stringByAppendingString:@"/" kServiceName ".json"]; | 36 *path = [[NSString stringWithFormat:@"%@/%s", |
37 *path = [filename UTF8String]; | 37 filename, remoting::kHostConfigFileName] UTF8String]; |
38 return true; | 38 return true; |
39 } | 39 } |
40 | 40 |
41 bool IsConfigValid(const remoting::JsonHostConfig* config) { | 41 bool IsConfigValid(const remoting::JsonHostConfig* config) { |
42 std::string value; | 42 std::string value; |
43 return (config->GetString(remoting::kHostIdConfigPath, &value) && | 43 return (config->GetString(remoting::kHostIdConfigPath, &value) && |
44 config->GetString(remoting::kHostSecretHashConfigPath, &value) && | 44 config->GetString(remoting::kHostSecretHashConfigPath, &value) && |
45 config->GetString(remoting::kXmppLoginConfigPath, &value)); | 45 config->GetString(remoting::kXmppLoginConfigPath, &value)); |
46 } | 46 } |
47 | 47 |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 *pid = line_pid; | 219 *pid = line_pid; |
220 } | 220 } |
221 | 221 |
222 return status; | 222 return status; |
223 } | 223 } |
224 | 224 |
225 } // namespace mac | 225 } // namespace mac |
226 } // namespace base | 226 } // namespace base |
227 | 227 |
228 namespace remoting { | 228 namespace remoting { |
| 229 |
229 JsonHostConfig::JsonHostConfig(const std::string& filename) | 230 JsonHostConfig::JsonHostConfig(const std::string& filename) |
230 : filename_(filename) { | 231 : filename_(filename) { |
231 } | 232 } |
232 | 233 |
233 JsonHostConfig::~JsonHostConfig() { | 234 JsonHostConfig::~JsonHostConfig() { |
234 } | 235 } |
235 | 236 |
236 bool JsonHostConfig::Read() { | 237 bool JsonHostConfig::Read() { |
237 std::ifstream file(filename_.c_str()); | 238 std::ifstream file(filename_.c_str()); |
238 Json::Reader reader; | 239 Json::Reader reader; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 } | 276 } |
276 | 277 |
277 - (void)willSelect { | 278 - (void)willSelect { |
278 have_new_config_ = NO; | 279 have_new_config_ = NO; |
279 awaiting_service_stop_ = NO; | 280 awaiting_service_stop_ = NO; |
280 | 281 |
281 NSDistributedNotificationCenter* center = | 282 NSDistributedNotificationCenter* center = |
282 [NSDistributedNotificationCenter defaultCenter]; | 283 [NSDistributedNotificationCenter defaultCenter]; |
283 [center addObserver:self | 284 [center addObserver:self |
284 selector:@selector(onNewConfigFile:) | 285 selector:@selector(onNewConfigFile:) |
285 name:@kServiceName | 286 name:[NSString stringWithUTF8String:remoting::kServiceName] |
286 object:nil]; | 287 object:nil]; |
287 | 288 |
288 service_status_timer_ = | 289 service_status_timer_ = |
289 [[NSTimer scheduledTimerWithTimeInterval:2.0 | 290 [[NSTimer scheduledTimerWithTimeInterval:2.0 |
290 target:self | 291 target:self |
291 selector:@selector(refreshServiceStatus:) | 292 selector:@selector(refreshServiceStatus:) |
292 userInfo:nil | 293 userInfo:nil |
293 repeats:YES] retain]; | 294 repeats:YES] retain]; |
294 [self updateServiceStatus]; | 295 [self updateServiceStatus]; |
295 [self updateAuthorizationStatus]; | 296 [self updateAuthorizationStatus]; |
(...skipping 11 matching lines...) Expand all Loading... |
307 | 308 |
308 - (void)willUnselect { | 309 - (void)willUnselect { |
309 NSDistributedNotificationCenter* center = | 310 NSDistributedNotificationCenter* center = |
310 [NSDistributedNotificationCenter defaultCenter]; | 311 [NSDistributedNotificationCenter defaultCenter]; |
311 [center removeObserver:self]; | 312 [center removeObserver:self]; |
312 | 313 |
313 [service_status_timer_ invalidate]; | 314 [service_status_timer_ invalidate]; |
314 [service_status_timer_ release]; | 315 [service_status_timer_ release]; |
315 service_status_timer_ = nil; | 316 service_status_timer_ = nil; |
316 | 317 |
317 [self notifyPlugin:kUpdateFailedNotificationName]; | 318 [self notifyPlugin:UPDATE_FAILED_NOTIFICATION_NAME]; |
318 } | 319 } |
319 | 320 |
320 - (void)applyConfiguration:(id)sender | 321 - (void)applyConfiguration:(id)sender |
321 pin:(NSString*)pin { | 322 pin:(NSString*)pin { |
322 if (!have_new_config_) { | 323 if (!have_new_config_) { |
323 // It shouldn't be possible to hit the button if there is no config to | 324 // It shouldn't be possible to hit the button if there is no config to |
324 // apply, but check anyway just in case it happens somehow. | 325 // apply, but check anyway just in case it happens somehow. |
325 return; | 326 return; |
326 } | 327 } |
327 | 328 |
(...skipping 23 matching lines...) Expand all Loading... |
351 // Ensure the authorization token is up-to-date before using it. | 352 // Ensure the authorization token is up-to-date before using it. |
352 [self updateAuthorizationStatus]; | 353 [self updateAuthorizationStatus]; |
353 [self updateUI]; | 354 [self updateUI]; |
354 if (!is_pane_unlocked_) | 355 if (!is_pane_unlocked_) |
355 return; | 356 return; |
356 | 357 |
357 if (![self runHelperAsRootWithCommand:"--disable" | 358 if (![self runHelperAsRootWithCommand:"--disable" |
358 inputData:""]) { | 359 inputData:""]) { |
359 NSLog(@"Failed to run the helper tool"); | 360 NSLog(@"Failed to run the helper tool"); |
360 [self showError]; | 361 [self showError]; |
361 [self notifyPlugin: kUpdateFailedNotificationName]; | 362 [self notifyPlugin:UPDATE_FAILED_NOTIFICATION_NAME]; |
362 return; | 363 return; |
363 } | 364 } |
364 | 365 |
365 // Stop the launchd job. This cannot easily be done by the helper tool, | 366 // Stop the launchd job. This cannot easily be done by the helper tool, |
366 // since the launchd job runs in the current user's context. | 367 // since the launchd job runs in the current user's context. |
367 [self sendJobControlMessage:LAUNCH_KEY_STOPJOB]; | 368 [self sendJobControlMessage:LAUNCH_KEY_STOPJOB]; |
368 awaiting_service_stop_ = YES; | 369 awaiting_service_stop_ = YES; |
369 } | 370 } |
370 | 371 |
371 - (void)onNewConfigFile:(NSNotification*)notification { | 372 - (void)onNewConfigFile:(NSNotification*)notification { |
372 [self checkInstalledVersion]; | 373 [self checkInstalledVersion]; |
373 if (!restart_pending_or_canceled_) | 374 if (!restart_pending_or_canceled_) |
374 [self readNewConfig]; | 375 [self readNewConfig]; |
375 | 376 |
376 [self updateUI]; | 377 [self updateUI]; |
377 } | 378 } |
378 | 379 |
379 - (void)refreshServiceStatus:(NSTimer*)timer { | 380 - (void)refreshServiceStatus:(NSTimer*)timer { |
380 BOOL was_running = is_service_running_; | 381 BOOL was_running = is_service_running_; |
381 [self updateServiceStatus]; | 382 [self updateServiceStatus]; |
382 if (awaiting_service_stop_ && !is_service_running_) { | 383 if (awaiting_service_stop_ && !is_service_running_) { |
383 awaiting_service_stop_ = NO; | 384 awaiting_service_stop_ = NO; |
384 [self notifyPlugin:kUpdateSucceededNotificationName]; | 385 [self notifyPlugin:UPDATE_SUCCEEDED_NOTIFICATION_NAME]; |
385 } | 386 } |
386 | 387 |
387 if (was_running != is_service_running_) | 388 if (was_running != is_service_running_) |
388 [self updateUI]; | 389 [self updateUI]; |
389 } | 390 } |
390 | 391 |
391 - (void)authorizationViewDidAuthorize:(SFAuthorizationView*)view { | 392 - (void)authorizationViewDidAuthorize:(SFAuthorizationView*)view { |
392 [self updateAuthorizationStatus]; | 393 [self updateAuthorizationStatus]; |
393 [self updateUI]; | 394 [self updateUI]; |
394 } | 395 } |
395 | 396 |
396 - (void)authorizationViewDidDeauthorize:(SFAuthorizationView*)view { | 397 - (void)authorizationViewDidDeauthorize:(SFAuthorizationView*)view { |
397 [self updateAuthorizationStatus]; | 398 [self updateAuthorizationStatus]; |
398 [self updateUI]; | 399 [self updateUI]; |
399 } | 400 } |
400 | 401 |
401 - (void)updateServiceStatus { | 402 - (void)updateServiceStatus { |
402 pid_t job_pid = base::mac::PIDForJob(kServiceName); | 403 pid_t job_pid = base::mac::PIDForJob(remoting::kServiceName); |
403 is_service_running_ = (job_pid > 0); | 404 is_service_running_ = (job_pid > 0); |
404 } | 405 } |
405 | 406 |
406 - (void)updateAuthorizationStatus { | 407 - (void)updateAuthorizationStatus { |
407 is_pane_unlocked_ = [authorization_view_ updateStatus:authorization_view_]; | 408 is_pane_unlocked_ = [authorization_view_ updateStatus:authorization_view_]; |
408 } | 409 } |
409 | 410 |
410 - (void)readNewConfig { | 411 - (void)readNewConfig { |
411 std::string file; | 412 std::string file; |
412 if (!GetTemporaryConfigFilePath(&file)) { | 413 if (!GetTemporaryConfigFilePath(&file)) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 NSLog(@"Failed to run the helper tool"); | 519 NSLog(@"Failed to run the helper tool"); |
519 [self showError]; | 520 [self showError]; |
520 return; | 521 return; |
521 } | 522 } |
522 | 523 |
523 have_new_config_ = NO; | 524 have_new_config_ = NO; |
524 | 525 |
525 // If the service is running, send a signal to cause it to reload its | 526 // If the service is running, send a signal to cause it to reload its |
526 // configuration, otherwise start the service. | 527 // configuration, otherwise start the service. |
527 if (is_service_running_) { | 528 if (is_service_running_) { |
528 pid_t job_pid = base::mac::PIDForJob(kServiceName); | 529 pid_t job_pid = base::mac::PIDForJob(remoting::kServiceName); |
529 if (job_pid > 0) { | 530 if (job_pid > 0) { |
530 kill(job_pid, SIGHUP); | 531 kill(job_pid, SIGHUP); |
531 } else { | 532 } else { |
532 NSLog(@"Failed to obtain PID of service " kServiceName); | 533 NSLog(@"Failed to obtain PID of service %s", remoting::kServiceName); |
533 [self showError]; | 534 [self showError]; |
534 } | 535 } |
535 } else { | 536 } else { |
536 [self sendJobControlMessage:LAUNCH_KEY_STARTJOB]; | 537 [self sendJobControlMessage:LAUNCH_KEY_STARTJOB]; |
537 } | 538 } |
538 | 539 |
539 // Broadcast a distributed notification to inform the plugin that the | 540 // Broadcast a distributed notification to inform the plugin that the |
540 // configuration has been applied. | 541 // configuration has been applied. |
541 [self notifyPlugin: kUpdateSucceededNotificationName]; | 542 [self notifyPlugin:UPDATE_SUCCEEDED_NOTIFICATION_NAME]; |
542 } | 543 } |
543 | 544 |
544 - (BOOL)runHelperAsRootWithCommand:(const char*)command | 545 - (BOOL)runHelperAsRootWithCommand:(const char*)command |
545 inputData:(const std::string&)input_data { | 546 inputData:(const std::string&)input_data { |
546 AuthorizationRef authorization = | 547 AuthorizationRef authorization = |
547 [[authorization_view_ authorization] authorizationRef]; | 548 [[authorization_view_ authorization] authorizationRef]; |
548 if (!authorization) { | 549 if (!authorization) { |
549 NSLog(@"Failed to obtain authorizationRef"); | 550 NSLog(@"Failed to obtain authorizationRef"); |
550 return NO; | 551 return NO; |
551 } | 552 } |
552 | 553 |
553 // TODO(lambroslambrou): Replace the deprecated ExecuteWithPrivileges | 554 // TODO(lambroslambrou): Replace the deprecated ExecuteWithPrivileges |
554 // call with a launchd-based helper tool, which is more secure. | 555 // call with a launchd-based helper tool, which is more secure. |
555 // http://crbug.com/120903 | 556 // http://crbug.com/120903 |
556 const char* arguments[] = { command, NULL }; | 557 const char* arguments[] = { command, NULL }; |
557 FILE* pipe = NULL; | 558 FILE* pipe = NULL; |
558 pid_t pid; | 559 pid_t pid; |
559 OSStatus status = base::mac::ExecuteWithPrivilegesAndGetPID( | 560 OSStatus status = base::mac::ExecuteWithPrivilegesAndGetPID( |
560 authorization, | 561 authorization, |
561 remoting::kHostHelperTool, | 562 remoting::kHostHelperScriptPath, |
562 kAuthorizationFlagDefaults, | 563 kAuthorizationFlagDefaults, |
563 arguments, | 564 arguments, |
564 &pipe, | 565 &pipe, |
565 &pid); | 566 &pid); |
566 if (status != errAuthorizationSuccess) { | 567 if (status != errAuthorizationSuccess) { |
567 NSLog(@"AuthorizationExecuteWithPrivileges: %s (%d)", | 568 NSLog(@"AuthorizationExecuteWithPrivileges: %s (%d)", |
568 GetMacOSStatusErrorString(status), static_cast<int>(status)); | 569 GetMacOSStatusErrorString(status), static_cast<int>(status)); |
569 return NO; | 570 return NO; |
570 } | 571 } |
571 if (pid == -1) { | 572 if (pid == -1) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 error = YES; | 612 error = YES; |
612 } | 613 } |
613 | 614 |
614 // No more cleanup needed. | 615 // No more cleanup needed. |
615 if (error) | 616 if (error) |
616 return NO; | 617 return NO; |
617 | 618 |
618 if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 0) { | 619 if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 0) { |
619 return YES; | 620 return YES; |
620 } else { | 621 } else { |
621 NSLog(@"%s failed with exit status %d", remoting::kHostHelperTool, | 622 NSLog(@"%s failed with exit status %d", remoting::kHostHelperScriptPath, |
622 exit_status); | 623 exit_status); |
623 return NO; | 624 return NO; |
624 } | 625 } |
625 } | 626 } |
626 | 627 |
627 - (BOOL)sendJobControlMessage:(const char*)launch_key { | 628 - (BOOL)sendJobControlMessage:(const char*)launch_key { |
628 base::mac::ScopedLaunchData response( | 629 base::mac::ScopedLaunchData response( |
629 base::mac::MessageForJob(kServiceName, launch_key)); | 630 base::mac::MessageForJob(remoting::kServiceName, launch_key)); |
630 if (!response) { | 631 if (!response) { |
631 NSLog(@"Failed to send message to launchd"); | 632 NSLog(@"Failed to send message to launchd"); |
632 [self showError]; | 633 [self showError]; |
633 return NO; | 634 return NO; |
634 } | 635 } |
635 | 636 |
636 // Expect a response of type LAUNCH_DATA_ERRNO. | 637 // Expect a response of type LAUNCH_DATA_ERRNO. |
637 launch_data_type_t type = launch_data_get_type(response.get()); | 638 launch_data_type_t type = launch_data_get_type(response.get()); |
638 if (type != LAUNCH_DATA_ERRNO) { | 639 if (type != LAUNCH_DATA_ERRNO) { |
639 NSLog(@"launchd returned unexpected type: %d", type); | 640 NSLog(@"launchd returned unexpected type: %d", type); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 std::string file; | 736 std::string file; |
736 if (!GetTemporaryConfigFilePath(&file)) { | 737 if (!GetTemporaryConfigFilePath(&file)) { |
737 // There's no point in alerting the user here. The same error would | 738 // There's no point in alerting the user here. The same error would |
738 // happen when the pane is eventually restarted, so the user would be | 739 // happen when the pane is eventually restarted, so the user would be |
739 // alerted at that time. | 740 // alerted at that time. |
740 NSLog(@"Failed to get path of configuration data."); | 741 NSLog(@"Failed to get path of configuration data."); |
741 return; | 742 return; |
742 } | 743 } |
743 | 744 |
744 remove(file.c_str()); | 745 remove(file.c_str()); |
745 [self notifyPlugin:kUpdateFailedNotificationName]; | 746 [self notifyPlugin:UPDATE_FAILED_NOTIFICATION_NAME]; |
746 } | 747 } |
747 } | 748 } |
748 | 749 |
749 - (void)restartSystemPreferences { | 750 - (void)restartSystemPreferences { |
750 NSTask* task = [[NSTask alloc] init]; | 751 NSTask* task = [[NSTask alloc] init]; |
751 NSString* command = | 752 NSString* command = |
752 [NSString stringWithUTF8String:remoting::kHostHelperTool]; | 753 [NSString stringWithUTF8String:remoting::kHostHelperScriptPath]; |
753 NSArray* arguments = [NSArray arrayWithObjects:@"--relaunch-prefpane", nil]; | 754 NSArray* arguments = [NSArray arrayWithObjects:@"--relaunch-prefpane", nil]; |
754 [task setLaunchPath:command]; | 755 [task setLaunchPath:command]; |
755 [task setArguments:arguments]; | 756 [task setArguments:arguments]; |
756 [task setStandardInput:[NSPipe pipe]]; | 757 [task setStandardInput:[NSPipe pipe]]; |
757 [task launch]; | 758 [task launch]; |
758 [task release]; | 759 [task release]; |
759 [NSApp terminate:nil]; | 760 [NSApp terminate:nil]; |
760 } | 761 } |
761 | 762 |
762 @end | 763 @end |
OLD | NEW |