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

Side by Side Diff: chrome/app_shim/chrome_main_app_mode_mac.mm

Issue 2416313002: Prepare chrome_main_app_mode_mac.mm for 10.9 (Closed)
Patch Set: nit Created 4 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 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 // On Mac, one can't make shortcuts with command-line arguments. Instead, we 5 // On Mac, one can't make shortcuts with command-line arguments. Instead, we
6 // produce small app bundles which locate the Chromium framework and load it, 6 // produce small app bundles which locate the Chromium framework and load it,
7 // passing the appropriate data. This is the entry point into the framework for 7 // passing the appropriate data. This is the entry point into the framework for
8 // those app bundles. 8 // those app bundles.
9 9
10 #import <Cocoa/Cocoa.h> 10 #import <Cocoa/Cocoa.h>
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 // A ReplyEventHandler is a helper class to send an Apple Event to a process 473 // A ReplyEventHandler is a helper class to send an Apple Event to a process
474 // and call a callback when the reply returns. 474 // and call a callback when the reply returns.
475 // 475 //
476 // This is used to 'ping' the main Chrome process -- once Chrome has sent back 476 // This is used to 'ping' the main Chrome process -- once Chrome has sent back
477 // an Apple Event reply, it's guaranteed that it has opened the IPC channel 477 // an Apple Event reply, it's guaranteed that it has opened the IPC channel
478 // that the app shim will connect to. 478 // that the app shim will connect to.
479 @interface ReplyEventHandler : NSObject { 479 @interface ReplyEventHandler : NSObject {
480 base::Callback<void(bool)> onReply_; 480 base::Callback<void(bool)> onReply_;
481 AEDesc replyEvent_; 481 AEDesc replyEvent_;
482 } 482 }
483 // Sends an Apple Event to the process identified by |psn|, and calls |replyFn| 483 // Sends an Apple Event to the process identified by the bundle identifier,
484 // when the reply is received. Internally this creates a ReplyEventHandler, 484 // and calls |replyFn| when the reply is received. Internally this
485 // which will delete itself once the reply event has been received. 485 // creates a ReplyEventHandler, which will delete itself once the reply event
486 + (void)pingProcess:(const ProcessSerialNumber&)psn 486 // has been received.
487 andCall:(base::Callback<void(bool)>)replyFn; 487 + (void)pingProcessAndCall:(base::Callback<void(bool)>)replyFn;
488 @end 488 @end
489 489
490 @interface ReplyEventHandler (PrivateMethods) 490 @interface ReplyEventHandler (PrivateMethods)
491 // Initialise the reply event handler. Doesn't register any handlers until 491 // Initialise the reply event handler. Doesn't register any handlers until
492 // |-pingProcess:| is called. |replyFn| is the function to be called when the 492 // |-pingProcess:| is called. |replyFn| is the function to be called when the
493 // Apple Event reply arrives. 493 // Apple Event reply arrives.
494 - (id)initWithCallback:(base::Callback<void(bool)>)replyFn; 494 - (id)initWithCallback:(base::Callback<void(bool)>)replyFn;
495 495
496 // Sends an Apple Event ping to the process identified by |psn| and registers 496 // Sends an Apple Event ping to the process identified by the bundle
497 // to listen for a reply. 497 // identifier and registers to listen for a reply.
498 - (void)pingProcess:(const ProcessSerialNumber&)psn; 498 - (void)pingProcess;
499 499
500 // Called when a response is received from the target process for the ping sent 500 // Called when a response is received from the target process for the ping sent
501 // by |-pingProcess:|. 501 // by |-pingProcess:|.
502 - (void)message:(NSAppleEventDescriptor*)event 502 - (void)message:(NSAppleEventDescriptor*)event
503 withReply:(NSAppleEventDescriptor*)reply; 503 withReply:(NSAppleEventDescriptor*)reply;
504 504
505 // Calls |onReply_|, passing it |success| to specify whether the ping was 505 // Calls |onReply_|, passing it |success| to specify whether the ping was
506 // successful. 506 // successful.
507 - (void)closeWithSuccess:(bool)success; 507 - (void)closeWithSuccess:(bool)success;
508 @end 508 @end
509 509
510 @implementation ReplyEventHandler 510 @implementation ReplyEventHandler
511 + (void)pingProcess:(const ProcessSerialNumber&)psn 511 + (void)pingProcessAndCall:(base::Callback<void(bool)>)replyFn {
512 andCall:(base::Callback<void(bool)>)replyFn {
513 // The object will release itself when the reply arrives, or possibly earlier 512 // The object will release itself when the reply arrives, or possibly earlier
514 // if an unrecoverable error occurs. 513 // if an unrecoverable error occurs.
515 ReplyEventHandler* handler = 514 ReplyEventHandler* handler =
516 [[ReplyEventHandler alloc] initWithCallback:replyFn]; 515 [[ReplyEventHandler alloc] initWithCallback:replyFn];
517 [handler pingProcess:psn]; 516 [handler pingProcess];
518 } 517 }
519 @end 518 @end
520 519
521 @implementation ReplyEventHandler (PrivateMethods) 520 @implementation ReplyEventHandler (PrivateMethods)
522 - (id)initWithCallback:(base::Callback<void(bool)>)replyFn { 521 - (id)initWithCallback:(base::Callback<void(bool)>)replyFn {
523 if ((self = [super init])) { 522 if ((self = [super init])) {
524 onReply_ = replyFn; 523 onReply_ = replyFn;
525 } 524 }
526 return self; 525 return self;
527 } 526 }
528 527
529 - (void)pingProcess:(const ProcessSerialNumber&)psn { 528 - (void)pingProcess {
530 // Register the reply listener. 529 // Register the reply listener.
531 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; 530 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager];
532 [em setEventHandler:self 531 [em setEventHandler:self
533 andSelector:@selector(message:withReply:) 532 andSelector:@selector(message:withReply:)
534 forEventClass:'aevt' 533 forEventClass:kCoreEventClass
535 andEventID:'ansr']; 534 andEventID:kAEAnswer];
535
536 // Craft the Apple Event to send. 536 // Craft the Apple Event to send.
537 NSString* chromeBundleId = [base::mac::OuterBundle() bundleIdentifier];
537 NSAppleEventDescriptor* target = [NSAppleEventDescriptor 538 NSAppleEventDescriptor* target = [NSAppleEventDescriptor
538 descriptorWithDescriptorType:typeProcessSerialNumber 539 descriptorWithDescriptorType:typeApplicationBundleID
539 bytes:&psn 540 data:[chromeBundleId
540 length:sizeof(psn)]; 541 dataUsingEncoding:NSUTF8StringEncoding]];
541 NSAppleEventDescriptor* initial_event = 542
542 [NSAppleEventDescriptor 543 NSAppleEventDescriptor* initialEvent = [NSAppleEventDescriptor
543 appleEventWithEventClass:app_mode::kAEChromeAppClass 544 appleEventWithEventClass:app_mode::kAEChromeAppClass
544 eventID:app_mode::kAEChromeAppPing 545 eventID:app_mode::kAEChromeAppPing
545 targetDescriptor:target 546 targetDescriptor:target
546 returnID:kAutoGenerateReturnID 547 returnID:kAutoGenerateReturnID
547 transactionID:kAnyTransactionID]; 548 transactionID:kAnyTransactionID];
548 549
549 // Note that AESendMessage effectively ignores kAEDefaultTimeout, because this 550 // Note that AESendMessage effectively ignores kAEDefaultTimeout, because this
550 // call does not pass kAEWantReceipt (which is deprecated and unsupported on 551 // call does not pass kAEWantReceipt (which is deprecated and unsupported on
551 // Mac). Instead, rely on OnPingChromeTimeout(). 552 // Mac). Instead, rely on OnPingChromeTimeout().
552 OSStatus status = AESendMessage( 553 OSStatus status = AESendMessage([initialEvent aeDesc], &replyEvent_,
553 [initial_event aeDesc], &replyEvent_, kAEQueueReply, kAEDefaultTimeout); 554 kAEQueueReply, kAEDefaultTimeout);
554 if (status != noErr) { 555 if (status != noErr) {
555 OSSTATUS_LOG(ERROR, status) << "AESendMessage"; 556 OSSTATUS_LOG(ERROR, status) << "AESendMessage";
556 [self closeWithSuccess:false]; 557 [self closeWithSuccess:false];
557 } 558 }
558 } 559 }
559 560
560 - (void)message:(NSAppleEventDescriptor*)event 561 - (void)message:(NSAppleEventDescriptor*)event
561 withReply:(NSAppleEventDescriptor*)reply { 562 withReply:(NSAppleEventDescriptor*)reply {
562 [self closeWithSuccess:true]; 563 [self closeWithSuccess:true];
563 } 564 }
564 565
565 - (void)closeWithSuccess:(bool)success { 566 - (void)closeWithSuccess:(bool)success {
566 onReply_.Run(success); 567 onReply_.Run(success);
567 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; 568 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager];
568 [em removeEventHandlerForEventClass:'aevt' andEventID:'ansr']; 569 [em removeEventHandlerForEventClass:kCoreEventClass andEventID:kAEAnswer];
569 [self release]; 570 [self release];
570 } 571 }
571 @end 572 @end
572 573
573 //----------------------------------------------------------------------------- 574 //-----------------------------------------------------------------------------
574 575
575 extern "C" { 576 extern "C" {
576 577
577 // |ChromeAppModeStart()| is the point of entry into the framework from the app 578 // |ChromeAppModeStart()| is the point of entry into the framework from the app
578 // mode loader. There are cases where the Chromium framework may have changed in 579 // mode loader. There are cases where the Chromium framework may have changed in
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 AppShimController controller; 662 AppShimController controller;
662 base::MessageLoopForUI main_message_loop; 663 base::MessageLoopForUI main_message_loop;
663 base::PlatformThread::SetName("CrAppShimMain"); 664 base::PlatformThread::SetName("CrAppShimMain");
664 665
665 // In tests, launching Chrome does nothing, and we won't get a ping response, 666 // In tests, launching Chrome does nothing, and we won't get a ping response,
666 // so just assume the socket exists. 667 // so just assume the socket exists.
667 if (pid == -1 && 668 if (pid == -1 &&
668 !base::CommandLine::ForCurrentProcess()->HasSwitch( 669 !base::CommandLine::ForCurrentProcess()->HasSwitch(
669 app_mode::kLaunchedForTest)) { 670 app_mode::kLaunchedForTest)) {
670 // Launch Chrome if it isn't already running. 671 // Launch Chrome if it isn't already running.
671 ProcessSerialNumber psn;
672 base::CommandLine command_line(base::CommandLine::NO_PROGRAM); 672 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
673 command_line.AppendSwitch(switches::kSilentLaunch); 673 command_line.AppendSwitch(switches::kSilentLaunch);
674 674
675 // If the shim is the app launcher, pass --show-app-list when starting a new 675 // If the shim is the app launcher, pass --show-app-list when starting a new
676 // Chrome process to inform startup codepaths and load the correct profile. 676 // Chrome process to inform startup codepaths and load the correct profile.
677 if (info->app_mode_id == app_mode::kAppListModeId) { 677 if (info->app_mode_id == app_mode::kAppListModeId) {
678 command_line.AppendSwitch(switches::kShowAppList); 678 command_line.AppendSwitch(switches::kShowAppList);
679 } else { 679 } else {
680 command_line.AppendSwitchPath(switches::kProfileDirectory, 680 command_line.AppendSwitchPath(switches::kProfileDirectory,
681 info->profile_dir); 681 info->profile_dir);
682 } 682 }
683 683
684 base::Process app = base::mac::OpenApplicationWithPath( 684 base::Process app = base::mac::OpenApplicationWithPath(
685 base::mac::OuterBundlePath(), command_line, NSWorkspaceLaunchDefault); 685 base::mac::OuterBundlePath(), command_line, NSWorkspaceLaunchDefault);
686 686 if (!app.IsValid())
687 // TODO(crbug.com/652563): Do not use deprecated GetProcessForPID. Change
688 // |ReplyEventHandler| to take |pid_t| instead of |ProcessSerialNumber|.
689 if (!app.IsValid() || GetProcessForPID(app.Pid(), &psn) != noErr)
690 return 1; 687 return 1;
691 688
692 base::Callback<void(bool)> on_ping_chrome_reply = 689 base::Callback<void(bool)> on_ping_chrome_reply = base::Bind(
693 base::Bind(&AppShimController::OnPingChromeReply, 690 &AppShimController::OnPingChromeReply, base::Unretained(&controller));
694 base::Unretained(&controller));
695 691
696 // This code abuses the fact that Apple Events sent before the process is 692 // This code abuses the fact that Apple Events sent before the process is
697 // fully initialized don't receive a reply until its run loop starts. Once 693 // fully initialized don't receive a reply until its run loop starts. Once
698 // the reply is received, Chrome will have opened its IPC port, guaranteed. 694 // the reply is received, Chrome will have opened its IPC port, guaranteed.
699 [ReplyEventHandler pingProcess:psn 695 [ReplyEventHandler pingProcessAndCall:on_ping_chrome_reply];
700 andCall:on_ping_chrome_reply];
701 696
702 main_message_loop.task_runner()->PostDelayedTask( 697 main_message_loop.task_runner()->PostDelayedTask(
703 FROM_HERE, base::Bind(&AppShimController::OnPingChromeTimeout, 698 FROM_HERE, base::Bind(&AppShimController::OnPingChromeTimeout,
704 base::Unretained(&controller)), 699 base::Unretained(&controller)),
705 base::TimeDelta::FromSeconds(kPingChromeTimeoutSeconds)); 700 base::TimeDelta::FromSeconds(kPingChromeTimeoutSeconds));
706 } else { 701 } else {
707 // Chrome already running. Proceed to init. This could still fail if Chrome 702 // Chrome already running. Proceed to init. This could still fail if Chrome
708 // is still starting up or shutting down, but the process will exit quickly, 703 // is still starting up or shutting down, but the process will exit quickly,
709 // which is preferable to waiting for the Apple Event to timeout after one 704 // which is preferable to waiting for the Apple Event to timeout after one
710 // minute. 705 // minute.
711 main_message_loop.task_runner()->PostTask( 706 main_message_loop.task_runner()->PostTask(
712 FROM_HERE, 707 FROM_HERE,
713 base::Bind(&AppShimController::Init, base::Unretained(&controller))); 708 base::Bind(&AppShimController::Init, base::Unretained(&controller)));
714 } 709 }
715 710
716 base::RunLoop().Run(); 711 base::RunLoop().Run();
717 return 0; 712 return 0;
718 } 713 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698