| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/process_singleton.h" |
| |
| #include <Carbon/Carbon.h> |
| #include <CoreServices/CoreServices.h> |
| |
| #include "base/mac/scoped_aedesc.h" |
| |
| namespace { |
| |
| // Extracts the URL from |event| and forwards it to an already-running Chromium |
| // process. |
| OSErr HandleGURLEvent(const AppleEvent* event, |
| AppleEvent* reply, |
| SRefCon handler_refcon) { |
| pid_t forwarding_pid = *(reinterpret_cast<pid_t*>(handler_refcon)); |
| base::mac::ScopedAEDesc<> other_process_pid; |
| // Create an address descriptor for the running process. |
| AECreateDesc(typeKernelProcessID, &forwarding_pid, sizeof(forwarding_pid), |
| other_process_pid.OutPointer()); |
| |
| OSErr status = noErr; |
| base::mac::ScopedAEDesc<> event_copy; |
| status = AECreateAppleEvent(kInternetEventClass, kAEGetURL, other_process_pid, |
| kAutoGenerateReturnID, kAnyTransactionID, |
| event_copy.OutPointer()); |
| if (status != noErr) |
| return status; |
| |
| base::mac::ScopedAEDesc<> url; |
| // A GURL event's direct object is the URL as a descriptor with type |
| // TEXT. |
| status = |
| AEGetParamDesc(event, keyDirectObject, typeWildCard, url.OutPointer()); |
| if (status != noErr) |
| return status; |
| |
| status = AEPutParamDesc(event_copy.OutPointer(), keyDirectObject, url); |
| if (status != noErr) |
| return status; |
| |
| status = AESendMessage(event_copy, reply, kAENoReply, kNoTimeOut); |
| if (status != noErr) |
| return status; |
| |
| // Activate the running instance |
| base::mac::ScopedAEDesc<> activate_event; |
| status = AECreateAppleEvent(kAEMiscStandards, kAEActivate, other_process_pid, |
| kAutoGenerateReturnID, kAnyTransactionID, |
| activate_event.OutPointer()); |
| if (status != noErr) |
| return status; |
| |
| return AESendMessage(activate_event, reply, kAENoReply, kNoTimeOut); |
| } |
| |
| } // namespace |
| |
| bool ProcessSingleton::WaitForAndForwardOpenURLEvent( |
| pid_t event_destination_pid) { |
| AEEventHandlerProcPtr handler = NewAEEventHandlerUPP(HandleGURLEvent); |
| if (AEInstallEventHandler(kInternetEventClass, kAEGetURL, handler, |
| &event_destination_pid, false) != noErr) { |
| DisposeAEEventHandlerUPP(handler); |
| return false; |
| } |
| bool result = false; |
| const EventTypeSpec spec = {kEventClassAppleEvent, kEventAppleEvent}; |
| EventRef event_ref; |
| if (ReceiveNextEvent(1, &spec, kEventDurationNanosecond, true, &event_ref) == |
| noErr) { |
| OSStatus processed = AEProcessEvent(event_ref); |
| ReleaseEvent(event_ref); |
| result = processed == noErr; |
| } |
| AERemoveEventHandler(kInternetEventClass, kAEGetURL, handler, false); |
| DisposeAEEventHandlerUPP(handler); |
| return result; |
| } |