blob: aba9d654a5ca1f8df4743ae5a0ff13d32d6dc16e [file] [log] [blame]
Avi Drissman4a8573c2022-09-09 19:35:541// Copyright 2017 The Chromium Authors
Leonard Greyfe15df92017-12-08 17:09:532// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/process_singleton.h"
6
7#include <Carbon/Carbon.h>
8#include <CoreServices/CoreServices.h>
9
10#include "base/mac/scoped_aedesc.h"
11
12namespace {
13
Leonard Grey883d1082017-12-13 15:06:1114// Extracts the URL from |event| and forwards it to an already-running Chromium
15// process.
Leonard Greyfe15df92017-12-08 17:09:5316OSErr HandleGURLEvent(const AppleEvent* event,
17 AppleEvent* reply,
18 SRefCon handler_refcon) {
Leonard Greyfe15df92017-12-08 17:09:5319 pid_t forwarding_pid = *(reinterpret_cast<pid_t*>(handler_refcon));
20 base::mac::ScopedAEDesc<> other_process_pid;
21 // Create an address descriptor for the running process.
22 AECreateDesc(typeKernelProcessID, &forwarding_pid, sizeof(forwarding_pid),
23 other_process_pid.OutPointer());
24
Leonard Grey883d1082017-12-13 15:06:1125 OSErr status = noErr;
26 base::mac::ScopedAEDesc<> event_copy;
27 status = AECreateAppleEvent(kInternetEventClass, kAEGetURL, other_process_pid,
28 kAutoGenerateReturnID, kAnyTransactionID,
29 event_copy.OutPointer());
30 if (status != noErr)
31 return status;
Leonard Greyfe15df92017-12-08 17:09:5332
Leonard Grey883d1082017-12-13 15:06:1133 base::mac::ScopedAEDesc<> url;
34 // A GURL event's direct object is the URL as a descriptor with type
35 // TEXT.
36 status =
37 AEGetParamDesc(event, keyDirectObject, typeWildCard, url.OutPointer());
38 if (status != noErr)
39 return status;
40
41 status = AEPutParamDesc(event_copy.OutPointer(), keyDirectObject, url);
42 if (status != noErr)
43 return status;
44
Leonard Greye69253f2018-01-12 20:23:5445 status = AESendMessage(event_copy, reply, kAENoReply, kNoTimeOut);
46 if (status != noErr)
47 return status;
48
49 // Activate the running instance
50 base::mac::ScopedAEDesc<> activate_event;
51 status = AECreateAppleEvent(kAEMiscStandards, kAEActivate, other_process_pid,
52 kAutoGenerateReturnID, kAnyTransactionID,
53 activate_event.OutPointer());
54 if (status != noErr)
55 return status;
56
57 return AESendMessage(activate_event, reply, kAENoReply, kNoTimeOut);
Leonard Greyfe15df92017-12-08 17:09:5358}
59
60} // namespace
61
62bool ProcessSingleton::WaitForAndForwardOpenURLEvent(
63 pid_t event_destination_pid) {
64 AEEventHandlerProcPtr handler = NewAEEventHandlerUPP(HandleGURLEvent);
65 if (AEInstallEventHandler(kInternetEventClass, kAEGetURL, handler,
66 &event_destination_pid, false) != noErr) {
67 DisposeAEEventHandlerUPP(handler);
68 return false;
69 }
70 bool result = false;
71 const EventTypeSpec spec = {kEventClassAppleEvent, kEventAppleEvent};
72 EventRef event_ref;
73 if (ReceiveNextEvent(1, &spec, kEventDurationNanosecond, true, &event_ref) ==
74 noErr) {
75 OSStatus processed = AEProcessEvent(event_ref);
76 ReleaseEvent(event_ref);
77 result = processed == noErr;
78 }
79 AERemoveEventHandler(kInternetEventClass, kAEGetURL, handler, false);
80 DisposeAEEventHandlerUPP(handler);
81 return result;
82}