File: views_content_client_main_parts_mac.mm

package info (click to toggle)
chromium 120.0.6099.224-1~deb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,112,112 kB
  • sloc: cpp: 32,907,025; ansic: 8,148,123; javascript: 3,679,536; python: 2,031,248; asm: 959,718; java: 804,675; xml: 617,256; sh: 111,417; objc: 100,835; perl: 88,443; cs: 53,032; makefile: 29,579; fortran: 24,137; php: 21,162; tcl: 21,147; sql: 20,809; ruby: 17,735; pascal: 12,864; yacc: 8,045; lisp: 3,388; lex: 1,323; ada: 727; awk: 329; jsp: 267; csh: 117; exp: 43; sed: 37
file content (144 lines) | stat: -rw-r--r-- 5,236 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import <Cocoa/Cocoa.h>

#include <utility>

#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/path_service.h"
#include "content/public/browser/context_factory.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/result_codes.h"
#include "content/shell/browser/shell_application_mac.h"
#include "content/shell/browser/shell_browser_context.h"
#include "ui/views/test/test_views_delegate.h"
#include "ui/views_content_client/views_content_client.h"
#include "ui/views_content_client/views_content_client_main_parts.h"

// A simple NSApplicationDelegate that provides a basic mainMenu and can
// activate a task when the application has finished loading.
@interface ViewsContentClientAppController : NSObject <NSApplicationDelegate> {
 @private
  base::OnceClosure _onApplicationDidFinishLaunching;
}

// Set the task to run after receiving -applicationDidFinishLaunching:.
- (void)setOnApplicationDidFinishLaunching:(base::OnceClosure)task;

@end

namespace ui {

namespace {

class ViewsContentClientMainPartsMac : public ViewsContentClientMainParts {
 public:
  explicit ViewsContentClientMainPartsMac(
      ViewsContentClient* views_content_client);

  ViewsContentClientMainPartsMac(const ViewsContentClientMainPartsMac&) =
      delete;
  ViewsContentClientMainPartsMac& operator=(
      const ViewsContentClientMainPartsMac&) = delete;

  ~ViewsContentClientMainPartsMac() override;

  // content::BrowserMainParts:
  int PreMainMessageLoopRun() override;

 private:
  ViewsContentClientAppController* __strong app_controller_;
};

ViewsContentClientMainPartsMac::ViewsContentClientMainPartsMac(
    ViewsContentClient* views_content_client)
    : ViewsContentClientMainParts(views_content_client) {
  // Cache the child process path to avoid triggering an AssertIOAllowed.
  base::FilePath child_process_exe;
  base::PathService::Get(content::CHILD_PROCESS_EXE, &child_process_exe);

  app_controller_ = [[ViewsContentClientAppController alloc] init];
  NSApplication.sharedApplication.delegate = app_controller_;
}

int ViewsContentClientMainPartsMac::PreMainMessageLoopRun() {
  ViewsContentClientMainParts::PreMainMessageLoopRun();

  views_delegate()->set_context_factory(content::GetContextFactory());

  // On Mac, the task must be deferred to applicationDidFinishLaunching. If not,
  // the widget can activate, but (even if configured) the mainMenu won't be
  // ready to switch over in the OSX UI, so it will look strange.
  NSWindow* window_context = nil;
  [app_controller_
      setOnApplicationDidFinishLaunching:
          base::BindOnce(&ViewsContentClient::OnPreMainMessageLoopRun,
                         base::Unretained(views_content_client()),
                         base::Unretained(browser_context()),
                         base::Unretained(window_context))];

  return content::RESULT_CODE_NORMAL_EXIT;
}

ViewsContentClientMainPartsMac::~ViewsContentClientMainPartsMac() {
  NSApplication.sharedApplication.delegate = nil;
}

}  // namespace

// static
std::unique_ptr<ViewsContentClientMainParts>
ViewsContentClientMainParts::Create(ViewsContentClient* views_content_client) {
  return std::make_unique<ViewsContentClientMainPartsMac>(views_content_client);
}

// static
void ViewsContentClientMainParts::PreBrowserMain() {
  // Simply instantiating an instance of ShellCrApplication serves to register
  // it as the application class. Do make sure that no other code has done this
  // first, though.
  CHECK_EQ(NSApp, nil);
  [ShellCrApplication sharedApplication];
}

}  // namespace ui

@implementation ViewsContentClientAppController

- (void)setOnApplicationDidFinishLaunching:(base::OnceClosure)task {
  _onApplicationDidFinishLaunching = std::move(task);
}

- (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
  // To get key events, the application needs to have an activation policy.
  // Unbundled apps (i.e. those without an Info.plist) default to
  // NSApplicationActivationPolicyProhibited.
  [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];

  // Create a basic mainMenu object using the executable filename.
  NSMenu* mainMenu = [[NSMenu alloc] initWithTitle:@""];
  NSMenuItem* appMenuItem = [mainMenu addItemWithTitle:@""
                                                action:nullptr
                                         keyEquivalent:@""];
  [NSApp setMainMenu:mainMenu];

  NSMenu* appMenu = [[NSMenu alloc] initWithTitle:@""];
  NSString* appName = NSProcessInfo.processInfo.processName;
  // TODO(tapted): Localize "Quit" if this is ever used for a released binary.
  // At the time of writing, ui_strings.grd has "Close" but not "Quit".
  NSString* quitTitle = [@"Quit " stringByAppendingString:appName];
  [appMenu addItemWithTitle:quitTitle
                     action:@selector(terminate:)
              keyEquivalent:@"q"];
  [appMenuItem setSubmenu:appMenu];

  CHECK([NSApp isKindOfClass:[ShellCrApplication class]]);

  std::move(_onApplicationDidFinishLaunching).Run();
}

@end