process_singleton_mac.mm 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. // Copyright 2017 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. #include "chrome/browser/process_singleton.h"
  5. #include <Carbon/Carbon.h>
  6. #include <CoreServices/CoreServices.h>
  7. #include "base/mac/scoped_aedesc.h"
  8. namespace {
  9. // Extracts the URL from |event| and forwards it to an already-running Chromium
  10. // process.
  11. OSErr HandleGURLEvent(const AppleEvent* event,
  12. AppleEvent* reply,
  13. SRefCon handler_refcon) {
  14. pid_t forwarding_pid = *(reinterpret_cast<pid_t*>(handler_refcon));
  15. base::mac::ScopedAEDesc<> other_process_pid;
  16. // Create an address descriptor for the running process.
  17. AECreateDesc(typeKernelProcessID, &forwarding_pid, sizeof(forwarding_pid),
  18. other_process_pid.OutPointer());
  19. OSErr status = noErr;
  20. base::mac::ScopedAEDesc<> event_copy;
  21. status = AECreateAppleEvent(kInternetEventClass, kAEGetURL, other_process_pid,
  22. kAutoGenerateReturnID, kAnyTransactionID,
  23. event_copy.OutPointer());
  24. if (status != noErr)
  25. return status;
  26. base::mac::ScopedAEDesc<> url;
  27. // A GURL event's direct object is the URL as a descriptor with type
  28. // TEXT.
  29. status =
  30. AEGetParamDesc(event, keyDirectObject, typeWildCard, url.OutPointer());
  31. if (status != noErr)
  32. return status;
  33. status = AEPutParamDesc(event_copy.OutPointer(), keyDirectObject, url);
  34. if (status != noErr)
  35. return status;
  36. status = AESendMessage(event_copy, reply, kAENoReply, kNoTimeOut);
  37. if (status != noErr)
  38. return status;
  39. // Activate the running instance
  40. base::mac::ScopedAEDesc<> activate_event;
  41. status = AECreateAppleEvent(kAEMiscStandards, kAEActivate, other_process_pid,
  42. kAutoGenerateReturnID, kAnyTransactionID,
  43. activate_event.OutPointer());
  44. if (status != noErr)
  45. return status;
  46. return AESendMessage(activate_event, reply, kAENoReply, kNoTimeOut);
  47. }
  48. } // namespace
  49. bool ProcessSingleton::WaitForAndForwardOpenURLEvent(
  50. pid_t event_destination_pid) {
  51. AEEventHandlerProcPtr handler = NewAEEventHandlerUPP(HandleGURLEvent);
  52. if (AEInstallEventHandler(kInternetEventClass, kAEGetURL, handler,
  53. &event_destination_pid, false) != noErr) {
  54. DisposeAEEventHandlerUPP(handler);
  55. return false;
  56. }
  57. bool result = false;
  58. const EventTypeSpec spec = {kEventClassAppleEvent, kEventAppleEvent};
  59. EventRef event_ref;
  60. if (ReceiveNextEvent(1, &spec, kEventDurationNanosecond, true, &event_ref) ==
  61. noErr) {
  62. OSStatus processed = AEProcessEvent(event_ref);
  63. ReleaseEvent(event_ref);
  64. result = processed == noErr;
  65. }
  66. AERemoveEventHandler(kInternetEventClass, kAEGetURL, handler, false);
  67. DisposeAEEventHandlerUPP(handler);
  68. return result;
  69. }