• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2023 The Chromium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This is a helper application for launch_application_unittest.mm. This
6// application records several events by writing them to a named pipe;
7// the unit tests then use this information to verify that this helper was
8// launched in the correct manner.
9// The named pipe this writes to is equal to the name of the app bundle,
10// with .app replaced by .fifo.
11
12#import <Cocoa/Cocoa.h>
13
14@interface AppDelegate : NSObject <NSApplicationDelegate>
15@end
16
17@implementation AppDelegate {
18  NSArray* _command_line;
19  NSURL* _fifo_url;
20  NSRunningApplication* _running_app;
21}
22
23- (instancetype)initWithCommandLine:(NSArray*)command_line {
24  self = [super init];
25  if (self) {
26    _command_line = command_line;
27    NSURL* bundle_url = NSBundle.mainBundle.bundleURL;
28    _fifo_url = [bundle_url.URLByDeletingLastPathComponent
29        URLByAppendingPathComponent:
30            [bundle_url.lastPathComponent
31                stringByReplacingOccurrencesOfString:@".app"
32                                          withString:@".fifo"]];
33    _running_app = NSRunningApplication.currentApplication;
34    [_running_app addObserver:self
35                   forKeyPath:@"activationPolicy"
36                      options:NSKeyValueObservingOptionNew
37                      context:nil];
38  }
39  return self;
40}
41
42- (void)dealloc {
43  [_running_app removeObserver:self forKeyPath:@"activationPolicy" context:nil];
44}
45
46- (void)observeValueForKeyPath:(NSString*)keyPath
47                      ofObject:(id)object
48                        change:(NSDictionary*)change
49                       context:(void*)context {
50  [self
51      addLaunchEvent:@"activationPolicyChanged"
52            withData:@{
53              @"activationPolicy" : change[@"new"],
54              @"processIdentifier" :
55                  @(NSRunningApplication.currentApplication.processIdentifier),
56            }];
57}
58
59- (void)applicationDidFinishLaunching:(NSNotification*)notification {
60  [self
61      addLaunchEvent:@"applicationDidFinishLaunching"
62            withData:@{
63              @"activationPolicy" : @(NSApp.activationPolicy),
64              @"commandLine" : _command_line,
65              @"processIdentifier" :
66                  @(NSRunningApplication.currentApplication.processIdentifier),
67            }];
68}
69
70- (void)application:(NSApplication*)app openURLs:(NSArray<NSURL*>*)urls {
71  [app replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
72
73  NSMutableArray* url_specs =
74      [[NSMutableArray alloc] initWithCapacity:urls.count];
75  for (NSURL* url in urls) {
76    [url_specs addObject:url.absoluteString];
77  }
78  [self
79      addLaunchEvent:@"openURLs"
80            withData:@{
81              @"activationPolicy" : @(NSApp.activationPolicy),
82              @"processIdentifier" :
83                  @(NSRunningApplication.currentApplication.processIdentifier),
84              @"urls" : url_specs,
85            }];
86}
87
88- (void)addLaunchEvent:(NSString*)event {
89  [self addLaunchEvent:event withData:nil];
90}
91
92- (void)addLaunchEvent:(NSString*)event withData:(NSDictionary*)data {
93  NSLog(@"Logging %@ with data %@", event, data);
94  NSDictionary* event_dict = @{
95    @"name" : event,
96    @"data" : data,
97  };
98  // It is important to write this dictionary to the named pipe non-atomically,
99  // as otherwise the write would replace the named pipe with a regular file
100  // rather than writing to the pipe.
101  [event_dict writeToURL:_fifo_url atomically:NO];
102}
103
104@end
105
106__attribute__((visibility("default"))) int main(int argc, char** argv) {
107  [NSApplication sharedApplication];
108
109  NSMutableArray* command_line = [[NSMutableArray alloc] initWithCapacity:argc];
110  for (int i = 0; i < argc; ++i) {
111    [command_line addObject:[NSString stringWithUTF8String:argv[i]]];
112  }
113
114  AppDelegate* delegate =
115      [[AppDelegate alloc] initWithCommandLine:command_line];
116  NSApp.delegate = delegate;
117
118  [NSApp run];
119  return 0;
120}
121