xref: /aosp_15_r20/external/cronet/base/mac/test/launch_application_test_helper_main.m (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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  NSData* plist_data = [NSPropertyListSerialization
102      dataWithPropertyList:event_dict
103                    format:NSPropertyListXMLFormat_v1_0
104                   options:0
105                     error:nil];
106  [plist_data writeToURL:_fifo_url options:0 error:nil];
107}
108
109@end
110
111__attribute__((visibility("default"))) int main(int argc, char** argv) {
112  [NSApplication sharedApplication];
113
114  NSMutableArray* command_line = [[NSMutableArray alloc] initWithCapacity:argc];
115  for (int i = 0; i < argc; ++i) {
116    [command_line addObject:[NSString stringWithUTF8String:argv[i]]];
117  }
118
119  AppDelegate* delegate =
120      [[AppDelegate alloc] initWithCommandLine:command_line];
121  NSApp.delegate = delegate;
122
123  [NSApp run];
124  return 0;
125}
126