1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import <Cocoa/Cocoa.h>
7 #include "base/files/file_path.h"
8 #include "base/mac/scoped_nsobject.h"
9 #include "base/path_service.h"
10 #include "content/public/browser/plugin_service.h"
11 #include "content/public/common/content_paths.h"
12 #include "content/shell/browser/shell_browser_context.h"
13 #include "ui/views_content_client/views_content_client.h"
14 #include "ui/views_content_client/views_content_client_main_parts.h"
16 // A simple NSApplicationDelegate that provides a basic mainMenu and can
17 // activate a task when the application has finished loading.
18 @interface ViewsContentClientAppController : NSObject<NSApplicationDelegate> {
23 // Set the task to run after receiving -applicationDidFinishLaunching:.
24 - (void)setTask:(const base::Closure&)task;
32 class ViewsContentClientMainPartsMac : public ViewsContentClientMainParts {
34 ViewsContentClientMainPartsMac(
35 const content::MainFunctionParams& content_params,
36 ViewsContentClient* views_content_client);
37 ~ViewsContentClientMainPartsMac() override;
39 // content::BrowserMainParts:
40 void PreMainMessageLoopRun() override;
43 base::scoped_nsobject<ViewsContentClientAppController> app_controller_;
45 DISALLOW_COPY_AND_ASSIGN(ViewsContentClientMainPartsMac);
48 ViewsContentClientMainPartsMac::ViewsContentClientMainPartsMac(
49 const content::MainFunctionParams& content_params,
50 ViewsContentClient* views_content_client)
51 : ViewsContentClientMainParts(content_params, views_content_client) {
52 // Cache the child process path to avoid triggering an AssertIOAllowed.
53 base::FilePath child_process_exe;
54 PathService::Get(content::CHILD_PROCESS_EXE, &child_process_exe);
56 // Disable plugin discovery since NPAPI plugin support on Mac requires this to
57 // be done in a utility process type which isn't bundled with this executable.
58 content::PluginService::GetInstance()->DisablePluginsDiscoveryForTesting();
60 app_controller_.reset([[ViewsContentClientAppController alloc] init]);
61 [[NSApplication sharedApplication] setDelegate:app_controller_];
64 void ViewsContentClientMainPartsMac::PreMainMessageLoopRun() {
65 ViewsContentClientMainParts::PreMainMessageLoopRun();
67 // On Mac, the task must be deferred to applicationDidFinishLaunching. If not,
68 // the widget can activate, but (even if configured) the mainMenu won't be
69 // ready to switch over in the OSX UI, so it will look strange.
70 NSWindow* window_context = nil;
71 [app_controller_ setTask:base::Bind(views_content_client()->task(),
72 base::Unretained(browser_context()),
73 base::Unretained(window_context))];
76 ViewsContentClientMainPartsMac::~ViewsContentClientMainPartsMac() {
77 [[NSApplication sharedApplication] setDelegate:nil];
83 ViewsContentClientMainParts* ViewsContentClientMainParts::Create(
84 const content::MainFunctionParams& content_params,
85 ViewsContentClient* views_content_client) {
87 new ViewsContentClientMainPartsMac(content_params, views_content_client);
92 @implementation ViewsContentClientAppController
94 - (void)setTask:(const base::Closure&)task {
98 - (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
99 // To get key events, the application needs to have an activation policy.
100 // Unbundled apps (i.e. those without an Info.plist) default to
101 // NSApplicationActivationPolicyProhibited.
102 [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
104 // Create a basic mainMenu object using the executable filename.
105 base::scoped_nsobject<NSMenu> mainMenu([[NSMenu alloc] initWithTitle:@""]);
106 NSMenuItem* appMenuItem =
107 [mainMenu addItemWithTitle:@"" action:NULL keyEquivalent:@""];
108 [NSApp setMainMenu:mainMenu];
110 base::scoped_nsobject<NSMenu> appMenu([[NSMenu alloc] initWithTitle:@""]);
111 NSString* appName = [[NSProcessInfo processInfo] processName];
112 // TODO(tapted): Localize "Quit" if this is ever used for a released binary.
113 // At the time of writing, ui_strings.grd has "Close" but not "Quit".
114 NSString* quitTitle = [@"Quit " stringByAppendingString:appName];
115 [appMenu addItemWithTitle:quitTitle
116 action:@selector(terminate:)
118 [appMenuItem setSubmenu:appMenu];