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