blob: 0aeb282022ebc06361d4fbae56f05c8dab798e49 [file] [log] [blame]
[email protected]71c0eb92012-01-03 17:57:301// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]5c9587c2008-12-09 21:20:162// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]e6b5bc22011-09-08 22:01:565#include "chrome/browser/chrome_browser_main_mac.h"
[email protected]1152b7e2009-09-14 03:26:036
[email protected]ce8c16ad2009-08-12 19:00:427#import <Cocoa/Cocoa.h>
[email protected]1152b7e2009-09-14 03:26:038
[email protected]5c9587c2008-12-09 21:20:169#include "base/command_line.h"
[email protected]57999812013-02-24 05:40:5210#include "base/files/file_path.h"
calamityc95d7822015-05-04 02:10:1611#include "base/files/file_util.h"
[email protected]2f1804c2012-01-19 14:59:0712#include "base/mac/bundle_locations.h"
tapted676995d2016-04-18 11:32:2913#import "base/mac/foundation_util.h"
[email protected]0378bf42011-01-01 18:20:1414#include "base/mac/mac_util.h"
[email protected]a8522032013-06-24 22:51:4615#include "base/mac/scoped_nsobject.h"
thakis17c246d12016-07-01 22:28:0916#include "base/mac/sdk_forward_declarations.h"
[email protected]e1cb0e92010-06-15 07:23:5917#include "base/path_service.h"
Christopher Lam32c684522017-07-28 03:05:0218#include "base/task_scheduler/post_task.h"
19#include "base/task_scheduler/task_traits.h"
gabb15e19072016-05-11 20:45:4120#include "base/threading/thread_task_runner_handle.h"
[email protected]3b6aa8b62009-09-15 21:36:1121#import "chrome/browser/app_controller_mac.h"
tapted63829f72014-09-24 23:50:5022#include "chrome/browser/apps/app_shim/app_shim_host_manager_mac.h"
[email protected]e8b6ca02013-07-10 18:00:5123#include "chrome/browser/browser_process.h"
[email protected]aaa47ee2009-11-05 21:53:0124#import "chrome/browser/chrome_browser_application_mac.h"
Christopher Lam32c684522017-07-28 03:05:0225#include "chrome/browser/first_run/first_run.h"
[email protected]c4d501e2012-03-27 20:08:0226#include "chrome/browser/mac/install_from_dmg.h"
kerrnel26eeef02017-03-10 19:03:4327#include "chrome/browser/mac/keychain_reauthorize.h"
[email protected]5950f5712011-06-20 22:15:5228#import "chrome/browser/mac/keystone_glue.h"
[email protected]7d1aaa62014-07-18 02:21:3029#include "chrome/browser/mac/mac_startup_profiler.h"
[email protected]bdad6e62014-05-06 08:47:3730#include "chrome/browser/ui/app_list/app_list_service.h"
[email protected]e1cb0e92010-06-15 07:23:5931#include "chrome/common/chrome_paths.h"
[email protected]d7dbe28c2010-07-29 04:33:4732#include "chrome/common/chrome_switches.h"
scottmgcfa5b01b2015-11-30 23:13:4633#include "components/crash/content/app/crashpad.h"
[email protected]d6147bd2014-06-11 01:58:1934#include "components/metrics/metrics_service.h"
[email protected]4573fbd2011-10-31 20:25:1835#include "content/public/common/main_function_params.h"
[email protected]b39ef1cb2011-10-25 04:46:5536#include "content/public/common/result_codes.h"
[email protected]c051a1b2011-01-21 23:30:1737#include "ui/base/l10n/l10n_util_mac.h"
[email protected]42ce29d2011-01-20 23:19:4638#include "ui/base/resource/resource_bundle.h"
[email protected]63942f22012-05-01 06:11:5239#include "ui/base/resource/resource_handle.h"
[email protected]5c9587c2008-12-09 21:20:1640
calamityc95d7822015-05-04 02:10:1641namespace {
42
43// Writes an undocumented sentinel file that prevents Spotlight from indexing
44// below a particular path in order to reap some power savings.
45void EnsureMetadataNeverIndexFileOnFileThread(
46 const base::FilePath& user_data_dir) {
47 const char kMetadataNeverIndexFilename[] = ".metadata_never_index";
48 base::FilePath metadata_file_path =
49 user_data_dir.Append(kMetadataNeverIndexFilename);
50 if (base::PathExists(metadata_file_path))
51 return;
52
53 if (base::WriteFile(metadata_file_path, nullptr, 0) == -1)
54 DLOG(FATAL) << "Could not write .metadata_never_index file.";
55}
56
57void EnsureMetadataNeverIndexFile(const base::FilePath& user_data_dir) {
Christopher Lam32c684522017-07-28 03:05:0258 base::PostTaskWithTraits(
59 FROM_HERE,
60 {base::MayBlock(), base::TaskPriority::BACKGROUND,
61 base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
calamityc95d7822015-05-04 02:10:1662 base::Bind(&EnsureMetadataNeverIndexFileOnFileThread, user_data_dir));
63}
64
65} // namespace
66
[email protected]e6b5bc22011-09-08 22:01:5667// ChromeBrowserMainPartsMac ---------------------------------------------------
[email protected]1fec64352010-07-27 13:55:2168
[email protected]e6b5bc22011-09-08 22:01:5669ChromeBrowserMainPartsMac::ChromeBrowserMainPartsMac(
[email protected]4573fbd2011-10-31 20:25:1870 const content::MainFunctionParams& parameters)
[email protected]e6b5bc22011-09-08 22:01:5671 : ChromeBrowserMainPartsPosix(parameters) {
[email protected]f967b722011-09-07 00:58:0472}
[email protected]1fec64352010-07-27 13:55:2173
[email protected]39fc5d322012-09-15 10:54:5574ChromeBrowserMainPartsMac::~ChromeBrowserMainPartsMac() {
75}
76
Scott Violet9068b4df2018-01-12 16:44:2177int ChromeBrowserMainPartsMac::PreEarlyInitialization() {
[email protected]769ddfe2014-06-13 23:13:2078 if (base::mac::WasLaunchedAsLoginItemRestoreState()) {
avi3ef9ec9e2014-12-22 22:50:1779 base::CommandLine* singleton_command_line =
80 base::CommandLine::ForCurrentProcess();
[email protected]769ddfe2014-06-13 23:13:2081 singleton_command_line->AppendSwitch(switches::kRestoreLastSession);
82 } else if (base::mac::WasLaunchedAsHiddenLoginItem()) {
avi3ef9ec9e2014-12-22 22:50:1783 base::CommandLine* singleton_command_line =
84 base::CommandLine::ForCurrentProcess();
[email protected]f967b722011-09-07 00:58:0485 singleton_command_line->AppendSwitch(switches::kNoStartupWindow);
86 }
Scott Violet9068b4df2018-01-12 16:44:2187
[email protected]4764efa2013-01-25 17:18:4888 // Tell Cocoa to finish its initialization, which we want to do manually
[email protected]f967b722011-09-07 00:58:0489 // instead of calling NSApplicationMain(). The primary reason is that NSAM()
90 // never returns, which would leave all the objects currently on the stack
91 // in scoped_ptrs hanging and never cleaned up. We then load the main nib
92 // directly. The main event loop is run from common code using the
93 // MessageLoop API, which works out ok for us because it's a wrapper around
94 // CFRunLoop.
95
96 // Initialize NSApplication using the custom subclass.
[email protected]d7de57872011-12-06 23:32:4397 chrome_browser_application_mac::RegisterBrowserCrApp();
[email protected]f967b722011-09-07 00:58:0498
[email protected]a88f6362014-03-18 04:25:3599 // If ui_task is not NULL, the app is actually a browser_test.
[email protected]716476c2011-12-29 00:07:03100 if (!parameters().ui_task) {
[email protected]f967b722011-09-07 00:58:04101 // The browser process only wants to support the language Cocoa will use,
Scott Violet740c2632018-03-09 04:11:42102 // so force the app locale to be overriden with that value. This must
103 // happen before the ResourceBundle is loaded, which happens in
104 // ChromeBrowserMainParts::PreEarlyInitialization().
[email protected]f967b722011-09-07 00:58:04105 l10n_util::OverrideLocaleWithCocoaLocale();
[email protected]91484af2010-08-27 17:55:54106 }
107
Scott Violet740c2632018-03-09 04:11:42108 return ChromeBrowserMainPartsPosix::PreEarlyInitialization();
Scott Violet875789e2018-02-02 07:46:48109}
[email protected]a88f6362014-03-18 04:25:35110
Scott Violet875789e2018-02-02 07:46:48111void ChromeBrowserMainPartsMac::PreMainMessageLoopStart() {
112 MacStartupProfiler::GetInstance()->Profile(
113 MacStartupProfiler::PRE_MAIN_MESSAGE_LOOP_START);
114 ChromeBrowserMainPartsPosix::PreMainMessageLoopStart();
115
116 // ChromeBrowserMainParts should have loaded the resource bundle by this
117 // point (needed to load the nib).
118 CHECK(ui::ResourceBundle::HasSharedInstance());
[email protected]a88f6362014-03-18 04:25:35119
[email protected]c4d501e2012-03-27 20:08:02120 // This is a no-op if the KeystoneRegistration framework is not present.
121 // The framework is only distributed with branded Google Chrome builds.
122 [[KeystoneGlue defaultKeystoneGlue] registerWithKeystone];
123
124 // Disk image installation is sort of a first-run task, so it shares the
[email protected]0a160a1b2013-08-08 22:20:00125 // no first run switches.
[email protected]c4d501e2012-03-27 20:08:02126 //
127 // This needs to be done after the resource bundle is initialized (for
128 // access to localizations in the UI) and after Keystone is initialized
129 // (because the installation may need to promote Keystone) but before the
130 // app controller is set up (and thus before MainMenu.nib is loaded, because
131 // the app controller assumes that a browser has been set up and will crash
132 // upon receipt of certain notifications if no browser exists), before
133 // anyone tries doing anything silly like firing off an import job, and
134 // before anything creating preferences like Local State in order for the
135 // relaunched installed application to still consider itself as first-run.
[email protected]0a160a1b2013-08-08 22:20:00136 if (!first_run::IsFirstRunSuppressed(parsed_command_line())) {
[email protected]c4d501e2012-03-27 20:08:02137 if (MaybeInstallFromDiskImage()) {
138 // The application was installed and the installed copy has been
139 // launched. This process is now obsolete. Exit.
140 exit(0);
141 }
142 }
143
[email protected]f967b722011-09-07 00:58:04144 // Now load the nib (from the right bundle).
[email protected]a8522032013-06-24 22:51:46145 base::scoped_nsobject<NSNib> nib(
146 [[NSNib alloc] initWithNibNamed:@"MainMenu"
147 bundle:base::mac::FrameworkBundle()]);
[email protected]f967b722011-09-07 00:58:04148 // TODO(viettrungluu): crbug.com/20504 - This currently leaks, so if you
149 // change this, you'll probably need to change the Valgrind suppression.
thakis17c246d12016-07-01 22:28:09150 NSArray* top_level_objects = nil;
151 [nib instantiateWithOwner:NSApp topLevelObjects:&top_level_objects];
152 for (NSObject* object : top_level_objects)
153 [object retain];
[email protected]f967b722011-09-07 00:58:04154 // Make sure the app controller has been created.
155 DCHECK([NSApp delegate]);
kerrnel26eeef02017-03-10 19:03:43156
157 // Do Keychain reauthorization. This gets two chances to run. If the first
158 // try doesn't complete successfully (crashes or is interrupted for any
159 // reason), there will be a second chance. Once this step completes
160 // successfully, it should never have to run again.
161 NSString* const keychain_reauthorize_pref =
162 @"KeychainReauthorizeInAppSpring2017";
163 const int kKeychainReauthorizeMaxTries = 2;
164
165 chrome::KeychainReauthorizeIfNeeded(keychain_reauthorize_pref,
166 kKeychainReauthorizeMaxTries);
[email protected]f967b722011-09-07 00:58:04167}
[email protected]03d8d3e92011-09-20 06:07:11168
[email protected]7d1aaa62014-07-18 02:21:30169void ChromeBrowserMainPartsMac::PostMainMessageLoopStart() {
170 MacStartupProfiler::GetInstance()->Profile(
171 MacStartupProfiler::POST_MAIN_MESSAGE_LOOP_START);
[email protected]6ddc10972014-07-29 07:53:33172 ChromeBrowserMainPartsPosix::PostMainMessageLoopStart();
[email protected]7d1aaa62014-07-18 02:21:30173}
174
[email protected]bdad6e62014-05-06 08:47:37175void ChromeBrowserMainPartsMac::PreProfileInit() {
[email protected]7d1aaa62014-07-18 02:21:30176 MacStartupProfiler::GetInstance()->Profile(
177 MacStartupProfiler::PRE_PROFILE_INIT);
[email protected]bdad6e62014-05-06 08:47:37178 ChromeBrowserMainPartsPosix::PreProfileInit();
mlermana312cec2015-01-28 21:13:33179
[email protected]bdad6e62014-05-06 08:47:37180 // This is called here so that the app shim socket is only created after
181 // taking the singleton lock.
182 g_browser_process->platform_part()->app_shim_host_manager()->Init();
mlermana312cec2015-01-28 21:13:33183 AppListService::InitAll(NULL,
184 GetStartupProfilePath(user_data_dir(), parsed_command_line()));
[email protected]bdad6e62014-05-06 08:47:37185}
186
[email protected]e8b6ca02013-07-10 18:00:51187void ChromeBrowserMainPartsMac::PostProfileInit() {
[email protected]7d1aaa62014-07-18 02:21:30188 MacStartupProfiler::GetInstance()->Profile(
189 MacStartupProfiler::POST_PROFILE_INIT);
[email protected]e8b6ca02013-07-10 18:00:51190 ChromeBrowserMainPartsPosix::PostProfileInit();
markd413b2d2015-03-13 07:45:40191
[email protected]e8b6ca02013-07-10 18:00:51192 g_browser_process->metrics_service()->RecordBreakpadRegistration(
markd413b2d2015-03-13 07:45:40193 crash_reporter::GetUploadsEnabled());
calamityc95d7822015-05-04 02:10:16194
Christopher Lam32c684522017-07-28 03:05:02195 if (first_run::IsChromeFirstRun())
196 EnsureMetadataNeverIndexFile(user_data_dir());
bcwhitee9301292015-06-22 15:31:58197
borisv957d52d2016-04-13 18:35:43198 // Activation of Keystone is not automatic but done in response to the
199 // counting and reporting of profiles.
200 KeystoneGlue* glue = [KeystoneGlue defaultKeystoneGlue];
201 if (glue && ![glue isRegisteredAndActive]) {
202 // If profile loading has failed, we still need to handle other tasks
203 // like marking of the product as active.
204 [glue updateProfileCountsWithNumProfiles:0
205 numSignedInProfiles:0];
206 }
[email protected]e8b6ca02013-07-10 18:00:51207}
208
[email protected]03d8d3e92011-09-20 06:07:11209void ChromeBrowserMainPartsMac::DidEndMainMessageLoop() {
tapted676995d2016-04-18 11:32:29210 AppController* appController =
211 base::mac::ObjCCastStrict<AppController>([NSApp delegate]);
[email protected]03d8d3e92011-09-20 06:07:11212 [appController didEndMainMessageLoop];
213}