blob: 11d7ff43ffe2eca372f1ea0df596b93a7693d278 [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"
[email protected]e1cb0e92010-06-15 07:23:5916#include "base/path_service.h"
gabb15e19072016-05-11 20:45:4117#include "base/threading/thread_task_runner_handle.h"
[email protected]3b6aa8b62009-09-15 21:36:1118#import "chrome/browser/app_controller_mac.h"
tapted63829f72014-09-24 23:50:5019#include "chrome/browser/apps/app_shim/app_shim_host_manager_mac.h"
[email protected]e8b6ca02013-07-10 18:00:5120#include "chrome/browser/browser_process.h"
[email protected]aaa47ee2009-11-05 21:53:0121#import "chrome/browser/chrome_browser_application_mac.h"
[email protected]c4d501e2012-03-27 20:08:0222#include "chrome/browser/mac/install_from_dmg.h"
[email protected]5950f5712011-06-20 22:15:5223#import "chrome/browser/mac/keystone_glue.h"
[email protected]7d1aaa62014-07-18 02:21:3024#include "chrome/browser/mac/mac_startup_profiler.h"
[email protected]bdad6e62014-05-06 08:47:3725#include "chrome/browser/ui/app_list/app_list_service.h"
[email protected]e1cb0e92010-06-15 07:23:5926#include "chrome/common/chrome_paths.h"
[email protected]d7dbe28c2010-07-29 04:33:4727#include "chrome/common/chrome_switches.h"
scottmgcfa5b01b2015-11-30 23:13:4628#include "components/crash/content/app/crashpad.h"
[email protected]d6147bd2014-06-11 01:58:1929#include "components/metrics/metrics_service.h"
[email protected]4573fbd2011-10-31 20:25:1830#include "content/public/common/main_function_params.h"
[email protected]b39ef1cb2011-10-25 04:46:5531#include "content/public/common/result_codes.h"
[email protected]c051a1b2011-01-21 23:30:1732#include "ui/base/l10n/l10n_util_mac.h"
[email protected]42ce29d2011-01-20 23:19:4633#include "ui/base/resource/resource_bundle.h"
[email protected]63942f22012-05-01 06:11:5234#include "ui/base/resource/resource_handle.h"
[email protected]5c9587c2008-12-09 21:20:1635
calamityc95d7822015-05-04 02:10:1636namespace {
37
38// Writes an undocumented sentinel file that prevents Spotlight from indexing
39// below a particular path in order to reap some power savings.
40void EnsureMetadataNeverIndexFileOnFileThread(
41 const base::FilePath& user_data_dir) {
42 const char kMetadataNeverIndexFilename[] = ".metadata_never_index";
43 base::FilePath metadata_file_path =
44 user_data_dir.Append(kMetadataNeverIndexFilename);
45 if (base::PathExists(metadata_file_path))
46 return;
47
48 if (base::WriteFile(metadata_file_path, nullptr, 0) == -1)
49 DLOG(FATAL) << "Could not write .metadata_never_index file.";
50}
51
52void EnsureMetadataNeverIndexFile(const base::FilePath& user_data_dir) {
53 content::BrowserThread::PostTask(
54 content::BrowserThread::FILE, FROM_HERE,
55 base::Bind(&EnsureMetadataNeverIndexFileOnFileThread, user_data_dir));
56}
57
58} // namespace
59
[email protected]e6b5bc22011-09-08 22:01:5660// ChromeBrowserMainPartsMac ---------------------------------------------------
[email protected]1fec64352010-07-27 13:55:2161
[email protected]e6b5bc22011-09-08 22:01:5662ChromeBrowserMainPartsMac::ChromeBrowserMainPartsMac(
[email protected]4573fbd2011-10-31 20:25:1863 const content::MainFunctionParams& parameters)
[email protected]e6b5bc22011-09-08 22:01:5664 : ChromeBrowserMainPartsPosix(parameters) {
[email protected]f967b722011-09-07 00:58:0465}
[email protected]1fec64352010-07-27 13:55:2166
[email protected]39fc5d322012-09-15 10:54:5567ChromeBrowserMainPartsMac::~ChromeBrowserMainPartsMac() {
68}
69
[email protected]e6b5bc22011-09-08 22:01:5670void ChromeBrowserMainPartsMac::PreEarlyInitialization() {
[email protected]37c722b2011-09-08 22:18:4671 ChromeBrowserMainPartsPosix::PreEarlyInitialization();
[email protected]91484af2010-08-27 17:55:5472
[email protected]769ddfe2014-06-13 23:13:2073 if (base::mac::WasLaunchedAsLoginItemRestoreState()) {
avi3ef9ec9e2014-12-22 22:50:1774 base::CommandLine* singleton_command_line =
75 base::CommandLine::ForCurrentProcess();
[email protected]769ddfe2014-06-13 23:13:2076 singleton_command_line->AppendSwitch(switches::kRestoreLastSession);
77 } else if (base::mac::WasLaunchedAsHiddenLoginItem()) {
avi3ef9ec9e2014-12-22 22:50:1778 base::CommandLine* singleton_command_line =
79 base::CommandLine::ForCurrentProcess();
[email protected]f967b722011-09-07 00:58:0480 singleton_command_line->AppendSwitch(switches::kNoStartupWindow);
81 }
82}
83
[email protected]e6b5bc22011-09-08 22:01:5684void ChromeBrowserMainPartsMac::PreMainMessageLoopStart() {
[email protected]7d1aaa62014-07-18 02:21:3085 MacStartupProfiler::GetInstance()->Profile(
86 MacStartupProfiler::PRE_MAIN_MESSAGE_LOOP_START);
[email protected]37c722b2011-09-08 22:18:4687 ChromeBrowserMainPartsPosix::PreMainMessageLoopStart();
[email protected]f967b722011-09-07 00:58:0488
[email protected]4764efa2013-01-25 17:18:4889 // Tell Cocoa to finish its initialization, which we want to do manually
[email protected]f967b722011-09-07 00:58:0490 // instead of calling NSApplicationMain(). The primary reason is that NSAM()
91 // never returns, which would leave all the objects currently on the stack
92 // in scoped_ptrs hanging and never cleaned up. We then load the main nib
93 // directly. The main event loop is run from common code using the
94 // MessageLoop API, which works out ok for us because it's a wrapper around
95 // CFRunLoop.
96
97 // Initialize NSApplication using the custom subclass.
[email protected]d7de57872011-12-06 23:32:4398 chrome_browser_application_mac::RegisterBrowserCrApp();
[email protected]f967b722011-09-07 00:58:0499
[email protected]a88f6362014-03-18 04:25:35100 // If ui_task is not NULL, the app is actually a browser_test.
[email protected]716476c2011-12-29 00:07:03101 if (!parameters().ui_task) {
[email protected]f967b722011-09-07 00:58:04102 // The browser process only wants to support the language Cocoa will use,
103 // so force the app locale to be overriden with that value.
104 l10n_util::OverrideLocaleWithCocoaLocale();
[email protected]91484af2010-08-27 17:55:54105 }
106
[email protected]a88f6362014-03-18 04:25:35107 // Before we load the nib, we need to start up the resource bundle so we
108 // have the strings avaiable for localization.
109 // TODO(markusheintz): Read preference pref::kApplicationLocale in order
110 // to enforce the application locale.
111 const std::string loaded_locale =
[email protected]4ce2aa62014-08-14 01:05:49112 ui::ResourceBundle::InitSharedInstanceWithLocale(
karandeepbe60fc3c2016-01-21 23:22:42113 std::string(), &resource_delegate_,
114 ui::ResourceBundle::LOAD_COMMON_RESOURCES);
[email protected]a88f6362014-03-18 04:25:35115 CHECK(!loaded_locale.empty()) << "Default locale could not be found";
116
117 base::FilePath resources_pack_path;
118 PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path);
119 ResourceBundle::GetSharedInstance().AddDataPackFromPath(
120 resources_pack_path, ui::SCALE_FACTOR_NONE);
121
[email protected]c4d501e2012-03-27 20:08:02122 // This is a no-op if the KeystoneRegistration framework is not present.
123 // The framework is only distributed with branded Google Chrome builds.
124 [[KeystoneGlue defaultKeystoneGlue] registerWithKeystone];
125
126 // Disk image installation is sort of a first-run task, so it shares the
[email protected]0a160a1b2013-08-08 22:20:00127 // no first run switches.
[email protected]c4d501e2012-03-27 20:08:02128 //
129 // This needs to be done after the resource bundle is initialized (for
130 // access to localizations in the UI) and after Keystone is initialized
131 // (because the installation may need to promote Keystone) but before the
132 // app controller is set up (and thus before MainMenu.nib is loaded, because
133 // the app controller assumes that a browser has been set up and will crash
134 // upon receipt of certain notifications if no browser exists), before
135 // anyone tries doing anything silly like firing off an import job, and
136 // before anything creating preferences like Local State in order for the
137 // relaunched installed application to still consider itself as first-run.
[email protected]0a160a1b2013-08-08 22:20:00138 if (!first_run::IsFirstRunSuppressed(parsed_command_line())) {
[email protected]c4d501e2012-03-27 20:08:02139 if (MaybeInstallFromDiskImage()) {
140 // The application was installed and the installed copy has been
141 // launched. This process is now obsolete. Exit.
142 exit(0);
143 }
144 }
145
[email protected]f967b722011-09-07 00:58:04146 // Now load the nib (from the right bundle).
[email protected]a8522032013-06-24 22:51:46147 base::scoped_nsobject<NSNib> nib(
148 [[NSNib alloc] initWithNibNamed:@"MainMenu"
149 bundle:base::mac::FrameworkBundle()]);
[email protected]f967b722011-09-07 00:58:04150 // TODO(viettrungluu): crbug.com/20504 - This currently leaks, so if you
151 // change this, you'll probably need to change the Valgrind suppression.
152 [nib instantiateNibWithOwner:NSApp topLevelObjects:nil];
153 // Make sure the app controller has been created.
154 DCHECK([NSApp delegate]);
[email protected]1fec64352010-07-27 13:55:21155
[email protected]47077b52014-03-11 15:25:59156 [[NSUserDefaults standardUserDefaults] registerDefaults:@{
157 // Prevent Cocoa from turning command-line arguments into
158 // |-application:openFiles:|, since we already handle them directly.
159 // @"NO" looks like a mistake, but the value really is supposed to be a
160 // string.
ccameronc685e64c2015-05-12 07:05:17161 @"NSTreatUnknownArgumentsAsOpen": @"NO"
[email protected]47077b52014-03-11 15:25:59162 }];
[email protected]f967b722011-09-07 00:58:04163}
[email protected]03d8d3e92011-09-20 06:07:11164
[email protected]7d1aaa62014-07-18 02:21:30165void ChromeBrowserMainPartsMac::PostMainMessageLoopStart() {
166 MacStartupProfiler::GetInstance()->Profile(
167 MacStartupProfiler::POST_MAIN_MESSAGE_LOOP_START);
[email protected]6ddc10972014-07-29 07:53:33168 ChromeBrowserMainPartsPosix::PostMainMessageLoopStart();
[email protected]7d1aaa62014-07-18 02:21:30169}
170
[email protected]bdad6e62014-05-06 08:47:37171void ChromeBrowserMainPartsMac::PreProfileInit() {
[email protected]7d1aaa62014-07-18 02:21:30172 MacStartupProfiler::GetInstance()->Profile(
173 MacStartupProfiler::PRE_PROFILE_INIT);
[email protected]bdad6e62014-05-06 08:47:37174 ChromeBrowserMainPartsPosix::PreProfileInit();
mlermana312cec2015-01-28 21:13:33175
[email protected]bdad6e62014-05-06 08:47:37176 // This is called here so that the app shim socket is only created after
177 // taking the singleton lock.
178 g_browser_process->platform_part()->app_shim_host_manager()->Init();
mlermana312cec2015-01-28 21:13:33179 AppListService::InitAll(NULL,
180 GetStartupProfilePath(user_data_dir(), parsed_command_line()));
[email protected]bdad6e62014-05-06 08:47:37181}
182
[email protected]e8b6ca02013-07-10 18:00:51183void ChromeBrowserMainPartsMac::PostProfileInit() {
[email protected]7d1aaa62014-07-18 02:21:30184 MacStartupProfiler::GetInstance()->Profile(
185 MacStartupProfiler::POST_PROFILE_INIT);
[email protected]e8b6ca02013-07-10 18:00:51186 ChromeBrowserMainPartsPosix::PostProfileInit();
markd413b2d2015-03-13 07:45:40187
[email protected]e8b6ca02013-07-10 18:00:51188 g_browser_process->metrics_service()->RecordBreakpadRegistration(
markd413b2d2015-03-13 07:45:40189 crash_reporter::GetUploadsEnabled());
calamityc95d7822015-05-04 02:10:16190
191 // TODO(calamity): Make this gated on first_run::IsChromeFirstRun() in M45.
192 content::BrowserThread::PostAfterStartupTask(
193 FROM_HERE, base::ThreadTaskRunnerHandle::Get(),
194 base::Bind(&EnsureMetadataNeverIndexFile, user_data_dir()));
bcwhitee9301292015-06-22 15:31:58195
borisv957d52d2016-04-13 18:35:43196 // Activation of Keystone is not automatic but done in response to the
197 // counting and reporting of profiles.
198 KeystoneGlue* glue = [KeystoneGlue defaultKeystoneGlue];
199 if (glue && ![glue isRegisteredAndActive]) {
200 // If profile loading has failed, we still need to handle other tasks
201 // like marking of the product as active.
202 [glue updateProfileCountsWithNumProfiles:0
203 numSignedInProfiles:0];
204 }
[email protected]e8b6ca02013-07-10 18:00:51205}
206
[email protected]03d8d3e92011-09-20 06:07:11207void ChromeBrowserMainPartsMac::DidEndMainMessageLoop() {
tapted676995d2016-04-18 11:32:29208 AppController* appController =
209 base::mac::ObjCCastStrict<AppController>([NSApp delegate]);
[email protected]03d8d3e92011-09-20 06:07:11210 [appController didEndMainMessageLoop];
211}