blob: 9b0a62877bc87d17d087ec03dbb9330be1d72fe7 [file] [log] [blame]
[email protected]c4ff4952010-01-08 19:12:471// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]1152b7e2009-09-14 03:26:035#include "chrome/browser/browser_main.h"
[email protected]5c9587c2008-12-09 21:20:166
[email protected]1bcdb532009-01-16 17:47:577#include <algorithm>
[email protected]01109dcf2010-03-27 00:56:438#include <string>
9#include <vector>
[email protected]a1a130f7d2009-01-09 20:28:4410
[email protected]097ae5a2009-11-26 19:48:3411#include "app/hi_res_timer_manager.h"
[email protected]a92b8642009-05-05 23:38:5612#include "app/l10n_util.h"
[email protected]9929da92009-05-05 02:05:1113#include "app/resource_bundle.h"
[email protected]097ae5a2009-11-26 19:48:3414#include "app/system_monitor.h"
[email protected]e2cc2e62010-08-28 00:26:3715#include "base/at_exit.h"
[email protected]1bcdb532009-01-16 17:47:5716#include "base/command_line.h"
[email protected]58580352010-10-26 04:07:5017#include "base/debug/trace_event.h"
[email protected]f805fe82010-08-03 22:47:1018#include "base/file_path.h"
[email protected]1bcdb532009-01-16 17:47:5719#include "base/file_util.h"
[email protected]c2818d42010-10-18 02:47:3920#include "base/mac/scoped_nsautorelease_pool.h"
[email protected]835d7c82010-10-14 04:38:3821#include "base/metrics/field_trial.h"
22#include "base/metrics/histogram.h"
[email protected]1bcdb532009-01-16 17:47:5723#include "base/path_service.h"
[email protected]206d3c42010-01-19 23:59:2024#include "base/platform_thread.h"
[email protected]1bcdb532009-01-16 17:47:5725#include "base/process_util.h"
[email protected]e83326f2010-07-31 17:29:2526#include "base/string_number_conversions.h"
[email protected]1bcdb532009-01-16 17:47:5727#include "base/string_piece.h"
[email protected]4e5ae20f2010-09-24 04:52:1128#include "base/string_split.h"
[email protected]1bcdb532009-01-16 17:47:5729#include "base/string_util.h"
[email protected]4efe77c2009-07-18 03:25:3230#include "base/sys_string_conversions.h"
[email protected]6b5f21d2009-04-13 17:01:3531#include "base/time.h"
[email protected]be1ce6a72010-08-03 14:35:2232#include "base/utf_string_conversions.h"
[email protected]1bcdb532009-01-16 17:47:5733#include "base/values.h"
[email protected]01109dcf2010-03-27 00:56:4334#include "build/build_config.h"
[email protected]f8abf722010-07-07 19:46:2435#include "chrome/browser/browser.h"
[email protected]1bcdb532009-01-16 17:47:5736#include "chrome/browser/browser_main_win.h"
[email protected]a814d8632009-01-31 20:18:5237#include "chrome/browser/browser_init.h"
[email protected]37858e52010-08-26 00:22:0238#include "chrome/browser/prefs/browser_prefs.h"
[email protected]1bcdb532009-01-16 17:47:5739#include "chrome/browser/browser_process.h"
[email protected]b112a4c2009-02-01 20:24:0140#include "chrome/browser/browser_process_impl.h"
[email protected]7f0ebc92009-02-05 18:34:2141#include "chrome/browser/browser_shutdown.h"
[email protected]ed7e6dd2010-10-12 02:02:4542#include "chrome/browser/browser_thread.h"
[email protected]62c185a2009-02-16 16:59:0543#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
[email protected]f7e615a2009-06-26 19:50:5244#include "chrome/browser/extensions/extension_protocols.h"
[email protected]c5ae74ab2010-04-15 18:14:3745#include "chrome/browser/extensions/extensions_service.h"
[email protected]6aeac8342010-10-01 20:21:1846#include "chrome/browser/extensions/extensions_startup.h"
[email protected]820735792010-07-29 23:40:0147#include "chrome/browser/first_run/first_run.h"
[email protected]86230b92009-11-23 20:38:3848#include "chrome/browser/jankometer.h"
[email protected]7c927b62010-02-24 09:54:1349#include "chrome/browser/metrics/histogram_synchronizer.h"
[email protected]679082052010-07-21 21:30:1350#include "chrome/browser/metrics/metrics_log.h"
[email protected]dc6f4962009-02-13 01:25:5051#include "chrome/browser/metrics/metrics_service.h"
[email protected]81070042010-08-31 02:42:3652#include "chrome/browser/net/blob_url_request_job_factory.h"
[email protected]929935b2010-09-28 00:40:1153#include "chrome/browser/net/predictor_api.h"
[email protected]06fb1852010-09-28 04:52:1054#include "chrome/browser/net/metadata_url_request.h"
[email protected]6eb8bc812009-06-18 21:32:2755#include "chrome/browser/net/sdch_dictionary_fetcher.h"
[email protected]7c7377a2009-11-11 06:59:3856#include "chrome/browser/net/websocket_experiment/websocket_experiment_runner.h"
[email protected]fd49e2d2009-02-20 17:21:3057#include "chrome/browser/plugin_service.h"
[email protected]37858e52010-08-26 00:22:0258#include "chrome/browser/prefs/pref_service.h"
59#include "chrome/browser/prefs/pref_value_store.h"
[email protected]17543d62010-10-07 22:37:3860#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
[email protected]e3db4fab2009-04-21 21:47:4061#include "chrome/browser/process_singleton.h"
[email protected]cec1b8d2010-03-24 00:21:3462#include "chrome/browser/profile.h"
[email protected]f7011fcb2009-01-28 21:54:3263#include "chrome/browser/profile_manager.h"
[email protected]5c238752009-06-13 10:29:0764#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
[email protected]23872902010-10-26 03:43:5965#include "chrome/browser/search_engines/search_engine_type.h"
[email protected]8b62334b2010-08-31 22:37:1166#include "chrome/browser/search_engines/template_url.h"
[email protected]96b3c5c2010-04-16 20:30:1467#include "chrome/browser/search_engines/template_url_model.h"
[email protected]e96bf0c52010-08-23 23:20:5768#include "chrome/browser/service/service_process_control.h"
69#include "chrome/browser/service/service_process_control_manager.h"
[email protected]1bcdb532009-01-16 17:47:5770#include "chrome/browser/shell_integration.h"
[email protected]509acb8e2010-07-01 20:35:3171#include "chrome/browser/translate/translate_manager.h"
[email protected]332e1212010-06-23 22:49:4972#include "chrome/common/child_process.h"
[email protected]1bcdb532009-01-16 17:47:5773#include "chrome/common/chrome_constants.h"
74#include "chrome/common/chrome_paths.h"
75#include "chrome/common/chrome_switches.h"
[email protected]1b084b5e2010-08-03 07:58:1976#include "chrome/common/env_vars.h"
[email protected]ea587b02010-05-21 15:01:3577#include "chrome/common/json_pref_store.h"
[email protected]1bcdb532009-01-16 17:47:5778#include "chrome/common/jstemplate_builder.h"
[email protected]30f547c2010-08-04 01:00:0179#include "chrome/common/logging_chrome.h"
[email protected]1bcdb532009-01-16 17:47:5780#include "chrome/common/main_function_params.h"
[email protected]64d50ed2009-09-22 21:05:4781#include "chrome/common/net/net_resource_provider.h"
[email protected]1bcdb532009-01-16 17:47:5782#include "chrome/common/pref_names.h"
[email protected]74d1bb02009-03-03 00:41:2383#include "chrome/common/result_codes.h"
[email protected]1e7377d2009-05-28 20:23:0684#include "chrome/installer/util/google_update_settings.h"
[email protected]cd1c7832009-07-06 20:19:2985#include "chrome/installer/util/master_preferences.h"
[email protected]ea500fc62010-03-22 21:34:2986#include "grit/app_locale_settings.h"
[email protected]34ac8f32009-02-22 23:03:2787#include "grit/chromium_strings.h"
88#include "grit/generated_resources.h"
[email protected]47accfd62009-05-14 18:46:2189#include "net/base/cookie_monster.h"
[email protected]698cccb12009-03-11 18:47:2490#include "net/base/net_module.h"
[email protected]66761b952010-06-25 21:30:3891#include "net/base/network_change_notifier.h"
[email protected]65041fa2010-05-21 06:56:5392#include "net/http/http_network_layer.h"
[email protected]8e6441ca2010-08-19 05:56:3893#include "net/http/http_stream_factory.h"
[email protected]1fa47592009-07-27 22:45:0094#include "net/socket/client_socket_pool_base.h"
[email protected]2431756e2010-09-29 20:26:1395#include "net/socket/client_socket_pool_manager.h"
[email protected]7f7e92392010-10-26 18:29:2996#include "net/socket/tcp_client_socket.h"
[email protected]f90a3a5e2010-10-25 05:17:2497#include "net/spdy/spdy_session.h"
[email protected]4a5e1782010-03-05 20:49:0298#include "net/spdy/spdy_session_pool.h"
[email protected]1bcdb532009-01-16 17:47:5799
[email protected]ba80aa72009-09-23 22:12:23100#if defined(USE_LINUX_BREAKPAD)
[email protected]7a2ee202009-10-28 22:54:47101#include "base/linux_util.h"
[email protected]9a5d2a52009-05-22 03:37:45102#include "chrome/app/breakpad_linux.h"
103#endif
104
[email protected]25d47c7b2010-02-03 20:13:06105#if defined(OS_POSIX) && !defined(OS_MACOSX)
[email protected]c6032e82010-09-13 20:06:05106#include "chrome/browser/browser_main_gtk.h"
[email protected]16d51df2010-03-02 09:16:44107#include "chrome/browser/gtk/gtk_util.h"
[email protected]ba80aa72009-09-23 22:12:23108#endif
109
[email protected]d4fe1fbc2010-05-19 17:36:06110#if defined(OS_CHROMEOS)
111#include "chrome/browser/chromeos/boot_times_loader.h"
112#endif
113
[email protected]022614ef92008-12-30 20:50:01114// TODO(port): several win-only methods have been pulled out of this, but
[email protected]5c9587c2008-12-09 21:20:16115// BrowserMain() as a whole needs to be broken apart so that it's usable by
[email protected]022614ef92008-12-30 20:50:01116// other platforms. For now, it's just a stub. This is a serious work in
[email protected]5c9587c2008-12-09 21:20:16117// progress and should not be taken as an indication of a real refactoring.
118
119#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29120#include <windows.h>
[email protected]1e7377d2009-05-28 20:23:06121#include <commctrl.h>
initial.commit09911bf2008-07-26 23:55:29122#include <shellapi.h>
123
[email protected]ea500fc62010-03-22 21:34:29124#include "app/l10n_util_win.h"
[email protected]4a0765a2009-05-08 23:12:25125#include "app/win_util.h"
[email protected]ac262c9f2008-10-19 17:45:21126#include "chrome/browser/browser_trial.h"
[email protected]cd1adc22009-01-16 01:29:22127#include "chrome/browser/metrics/user_metrics.h"
[email protected]f870a322009-01-16 21:47:27128#include "chrome/browser/net/url_fixer_upper.h"
initial.commit09911bf2008-07-26 23:55:29129#include "chrome/browser/rlz/rlz.h"
[email protected]fb8f5e92008-09-13 19:40:50130#include "chrome/browser/views/user_data_dir_dialog.h"
[email protected]6e643432010-03-10 18:32:14131#include "chrome/common/sandbox_policy.h"
[email protected]68c921f2008-10-15 21:37:46132#include "chrome/installer/util/helper.h"
133#include "chrome/installer/util/install_util.h"
[email protected]67da235a2008-10-24 16:18:27134#include "chrome/installer/util/shell_util.h"
[email protected]68c921f2008-10-15 21:37:46135#include "chrome/installer/util/version.h"
[email protected]c6ac8412010-08-13 16:43:03136#include "gfx/platform_font_win.h"
initial.commit09911bf2008-07-26 23:55:29137#include "net/base/net_util.h"
[email protected]60889422008-09-23 01:18:16138#include "net/base/sdch_manager.h"
[email protected]8ff1d422009-07-07 21:31:39139#include "printing/printed_document.h"
[email protected]1bcdb532009-01-16 17:47:57140#include "sandbox/src/sandbox.h"
[email protected]7f0ebc92009-02-05 18:34:21141#endif // defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29142
[email protected]0a357e632010-04-02 21:26:58143#if defined(OS_MACOSX)
[email protected]a1e1d4902010-04-02 22:02:30144#include <Security/Security.h>
[email protected]0a357e632010-04-02 21:26:58145#include "chrome/browser/cocoa/install_from_dmg.h"
[email protected]3dd6f5e2010-06-01 20:28:03146#endif
147
[email protected]fc9c69bf2009-08-27 01:10:44148#if defined(TOOLKIT_VIEWS)
[email protected]a5176da2009-07-02 16:21:17149#include "chrome/browser/views/chrome_views_delegate.h"
[email protected]148d1052009-07-31 22:53:37150#include "views/focus/accelerator_handler.h"
[email protected]dd092152009-05-18 21:20:33151#endif
152
[email protected]2125f7df2009-08-21 01:47:41153#if defined(OS_CHROMEOS)
[email protected]268b02f2010-02-04 21:07:15154#include "chrome/browser/chromeos/cros/cros_library.h"
[email protected]a39c2d12010-05-14 23:48:27155#include "chrome/browser/chromeos/cros/screen_lock_library.h"
[email protected]c7db33a2010-10-06 18:57:25156#include "chrome/browser/chromeos/cros_settings_provider_stats.h"
[email protected]368ad4ca2010-06-15 16:07:45157#include "chrome/browser/chromeos/customization_document.h"
[email protected]5ccaa412009-11-13 22:00:16158#include "chrome/browser/chromeos/external_metrics.h"
[email protected]617fd0d2010-08-04 20:05:17159#include "chrome/browser/chromeos/login/authenticator.h"
160#include "chrome/browser/chromeos/login/login_utils.h"
[email protected]a39c2d12010-05-14 23:48:27161#include "chrome/browser/chromeos/login/screen_locker.h"
[email protected]ddf8a4b02010-03-22 23:08:30162#include "chrome/browser/chromeos/login/user_manager.h"
[email protected]08e6f6d2009-12-14 17:42:12163#include "chrome/browser/views/browser_dialogs.h"
[email protected]2125f7df2009-08-21 01:47:41164#endif
165
[email protected]f8abf722010-07-07 19:46:24166// BrowserMainParts ------------------------------------------------------------
167
168BrowserMainParts::BrowserMainParts(const MainFunctionParams& parameters)
169 : parameters_(parameters),
170 parsed_command_line_(parameters.command_line_) {
171}
172
[email protected]1fec64352010-07-27 13:55:21173BrowserMainParts::~BrowserMainParts() {
174}
175
176// BrowserMainParts: |EarlyInitialization()| and related -----------------------
[email protected]f8abf722010-07-07 19:46:24177
178void BrowserMainParts::EarlyInitialization() {
179 PreEarlyInitialization();
180
[email protected]bba38232010-08-06 22:55:46181 // Note: make sure to call ConnectionFieldTrial() before
182 // ProxyConnectionsFieldTrial().
[email protected]f8abf722010-07-07 19:46:24183 ConnectionFieldTrial();
184 SocketTimeoutFieldTrial();
[email protected]78a258a2010-08-02 16:34:26185 ProxyConnectionsFieldTrial();
[email protected]f8abf722010-07-07 19:46:24186 SpdyFieldTrial();
[email protected]8a3125a712010-08-09 18:58:51187 PrefetchFieldTrial();
[email protected]06d94042010-08-25 01:45:22188 ConnectBackupJobsFieldTrial();
[email protected]d7dbe28c2010-07-29 04:33:47189 InitializeSSL();
[email protected]f8abf722010-07-07 19:46:24190
[email protected]b24713592010-08-11 19:50:02191 if (parsed_command_line().HasSwitch(switches::kEnableDNSSECCerts))
192 net::SSLConfigService::EnableDNSSEC();
[email protected]a0deaecf2010-08-18 23:39:52193 if (parsed_command_line().HasSwitch(switches::kDisableSSLFalseStart))
194 net::SSLConfigService::DisableFalseStart();
[email protected]944a0a12010-08-19 20:02:28195 if (parsed_command_line().HasSwitch(switches::kAllowSSLMITMProxies))
196 net::SSLConfigService::AllowMITMProxies();
[email protected]4d52f192010-10-11 17:00:30197 if (parsed_command_line().HasSwitch(switches::kEnableSnapStart))
198 net::SSLConfigService::EnableSnapStart();
[email protected]b24713592010-08-11 19:50:02199
[email protected]7f7e92392010-10-26 18:29:29200 if (parsed_command_line().HasSwitch(switches::kEnableTcpFastOpen))
201 net::set_tcp_fastopen_enabled(true);
202
[email protected]f8abf722010-07-07 19:46:24203 PostEarlyInitialization();
204}
205
206// This is an A/B test for the maximum number of persistent connections per
207// host. Currently Chrome, Firefox, and IE8 have this value set at 6. Safari
208// uses 4, and Fasterfox (a plugin for Firefox that supposedly configures it to
209// run faster) uses 8. We would like to see how much of an effect this value has
210// on browsing. Too large a value might cause us to run into SYN flood detection
211// mechanisms.
212void BrowserMainParts::ConnectionFieldTrial() {
[email protected]835d7c82010-10-14 04:38:38213 const base::FieldTrial::Probability kConnectDivisor = 100;
214 const base::FieldTrial::Probability kConnectProbability = 1; // 1% prob.
[email protected]f8abf722010-07-07 19:46:24215
[email protected]835d7c82010-10-14 04:38:38216 scoped_refptr<base::FieldTrial> connect_trial =
217 new base::FieldTrial("ConnCountImpact", kConnectDivisor);
[email protected]f8abf722010-07-07 19:46:24218
[email protected]58d2d2d2010-08-05 22:46:33219 const int connect_5 = connect_trial->AppendGroup("conn_count_5",
[email protected]81c3bae2010-07-27 20:13:51220 kConnectProbability);
[email protected]58d2d2d2010-08-05 22:46:33221 const int connect_7 = connect_trial->AppendGroup("conn_count_7",
[email protected]81c3bae2010-07-27 20:13:51222 kConnectProbability);
[email protected]58d2d2d2010-08-05 22:46:33223 const int connect_8 = connect_trial->AppendGroup("conn_count_8",
[email protected]81c3bae2010-07-27 20:13:51224 kConnectProbability);
[email protected]58d2d2d2010-08-05 22:46:33225 const int connect_9 = connect_trial->AppendGroup("conn_count_9",
[email protected]bdf40d12010-07-28 01:29:41226 kConnectProbability);
227 // This (6) is the current default value. Having this group declared here
228 // makes it straightforward to modify |kConnectProbability| such that the same
229 // probability value will be assigned to all the other groups, while
230 // preserving the remainder of the of probability space to the default value.
[email protected]58d2d2d2010-08-05 22:46:33231 const int connect_6 = connect_trial->AppendGroup("conn_count_6",
[email protected]835d7c82010-10-14 04:38:38232 base::FieldTrial::kAllRemainingProbability);
[email protected]f8abf722010-07-07 19:46:24233
[email protected]81c3bae2010-07-27 20:13:51234 const int connect_trial_group = connect_trial->group();
[email protected]f8abf722010-07-07 19:46:24235
[email protected]81c3bae2010-07-27 20:13:51236 if (connect_trial_group == connect_5) {
[email protected]2431756e2010-09-29 20:26:13237 net::ClientSocketPoolManager::set_max_sockets_per_group(5);
[email protected]81c3bae2010-07-27 20:13:51238 } else if (connect_trial_group == connect_6) {
[email protected]2431756e2010-09-29 20:26:13239 net::ClientSocketPoolManager::set_max_sockets_per_group(6);
[email protected]81c3bae2010-07-27 20:13:51240 } else if (connect_trial_group == connect_7) {
[email protected]2431756e2010-09-29 20:26:13241 net::ClientSocketPoolManager::set_max_sockets_per_group(7);
[email protected]81c3bae2010-07-27 20:13:51242 } else if (connect_trial_group == connect_8) {
[email protected]2431756e2010-09-29 20:26:13243 net::ClientSocketPoolManager::set_max_sockets_per_group(8);
[email protected]81c3bae2010-07-27 20:13:51244 } else if (connect_trial_group == connect_9) {
[email protected]2431756e2010-09-29 20:26:13245 net::ClientSocketPoolManager::set_max_sockets_per_group(9);
[email protected]f8abf722010-07-07 19:46:24246 } else {
247 NOTREACHED();
248 }
249}
250
251// A/B test for determining a value for unused socket timeout. Currently the
252// timeout defaults to 10 seconds. Having this value set too low won't allow us
253// to take advantage of idle sockets. Setting it to too high could possibly
254// result in more ERR_CONNECT_RESETs, requiring one RTT to receive the RST
255// packet and possibly another RTT to re-establish the connection.
256void BrowserMainParts::SocketTimeoutFieldTrial() {
[email protected]835d7c82010-10-14 04:38:38257 const base::FieldTrial::Probability kIdleSocketTimeoutDivisor = 100;
[email protected]780f8492010-09-16 04:12:15258 // 1% probability for all experimental settings.
[email protected]835d7c82010-10-14 04:38:38259 const base::FieldTrial::Probability kSocketTimeoutProbability = 1;
[email protected]f8abf722010-07-07 19:46:24260
[email protected]835d7c82010-10-14 04:38:38261 scoped_refptr<base::FieldTrial> socket_timeout_trial =
262 new base::FieldTrial("IdleSktToImpact", kIdleSocketTimeoutDivisor);
[email protected]f8abf722010-07-07 19:46:24263
264 const int socket_timeout_5 =
[email protected]58d2d2d2010-08-05 22:46:33265 socket_timeout_trial->AppendGroup("idle_timeout_5",
[email protected]81c3bae2010-07-27 20:13:51266 kSocketTimeoutProbability);
[email protected]780f8492010-09-16 04:12:15267 const int socket_timeout_10 =
268 socket_timeout_trial->AppendGroup("idle_timeout_10",
269 kSocketTimeoutProbability);
[email protected]f8abf722010-07-07 19:46:24270 const int socket_timeout_20 =
[email protected]58d2d2d2010-08-05 22:46:33271 socket_timeout_trial->AppendGroup("idle_timeout_20",
[email protected]81c3bae2010-07-27 20:13:51272 kSocketTimeoutProbability);
[email protected]f8abf722010-07-07 19:46:24273 const int socket_timeout_60 =
[email protected]58d2d2d2010-08-05 22:46:33274 socket_timeout_trial->AppendGroup("idle_timeout_60",
[email protected]835d7c82010-10-14 04:38:38275 base::FieldTrial::kAllRemainingProbability);
[email protected]f8abf722010-07-07 19:46:24276
[email protected]81c3bae2010-07-27 20:13:51277 const int idle_to_trial_group = socket_timeout_trial->group();
[email protected]f8abf722010-07-07 19:46:24278
[email protected]81c3bae2010-07-27 20:13:51279 if (idle_to_trial_group == socket_timeout_5) {
[email protected]f8abf722010-07-07 19:46:24280 net::ClientSocketPool::set_unused_idle_socket_timeout(5);
[email protected]81c3bae2010-07-27 20:13:51281 } else if (idle_to_trial_group == socket_timeout_10) {
[email protected]f8abf722010-07-07 19:46:24282 net::ClientSocketPool::set_unused_idle_socket_timeout(10);
[email protected]81c3bae2010-07-27 20:13:51283 } else if (idle_to_trial_group == socket_timeout_20) {
[email protected]f8abf722010-07-07 19:46:24284 net::ClientSocketPool::set_unused_idle_socket_timeout(20);
[email protected]81c3bae2010-07-27 20:13:51285 } else if (idle_to_trial_group == socket_timeout_60) {
[email protected]f8abf722010-07-07 19:46:24286 net::ClientSocketPool::set_unused_idle_socket_timeout(60);
287 } else {
288 NOTREACHED();
289 }
290}
291
[email protected]78a258a2010-08-02 16:34:26292void BrowserMainParts::ProxyConnectionsFieldTrial() {
[email protected]835d7c82010-10-14 04:38:38293 const base::FieldTrial::Probability kProxyConnectionsDivisor = 100;
[email protected]78a258a2010-08-02 16:34:26294 // 25% probability
[email protected]835d7c82010-10-14 04:38:38295 const base::FieldTrial::Probability kProxyConnectionProbability = 1;
[email protected]78a258a2010-08-02 16:34:26296
[email protected]835d7c82010-10-14 04:38:38297 scoped_refptr<base::FieldTrial> proxy_connection_trial =
298 new base::FieldTrial("ProxyConnectionImpact", kProxyConnectionsDivisor);
[email protected]78a258a2010-08-02 16:34:26299
[email protected]bba38232010-08-06 22:55:46300 // The number of max sockets per group cannot be greater than the max number
[email protected]8fa6f7d92010-09-14 16:29:33301 // of sockets per proxy server. We tried using 8, and it can easily
302 // lead to total browser stalls.
[email protected]78a258a2010-08-02 16:34:26303 const int proxy_connections_16 =
[email protected]97546492010-08-09 05:14:49304 proxy_connection_trial->AppendGroup("proxy_connections_16",
[email protected]78a258a2010-08-02 16:34:26305 kProxyConnectionProbability);
306 const int proxy_connections_64 =
[email protected]97546492010-08-09 05:14:49307 proxy_connection_trial->AppendGroup("proxy_connections_64",
[email protected]78a258a2010-08-02 16:34:26308 kProxyConnectionProbability);
309
310 // This (32 connections per proxy server) is the current default value.
311 // Declaring it here allows us to easily re-assign the probability space while
312 // maintaining that the default group always has the remainder of the "share",
313 // which allows for cleaner and quicker changes down the line if needed.
314 const int proxy_connections_32 =
[email protected]97546492010-08-09 05:14:49315 proxy_connection_trial->AppendGroup("proxy_connections_32",
[email protected]835d7c82010-10-14 04:38:38316 base::FieldTrial::kAllRemainingProbability);
[email protected]78a258a2010-08-02 16:34:26317
318 const int proxy_connections_trial_group = proxy_connection_trial->group();
319
[email protected]8fa6f7d92010-09-14 16:29:33320 if (proxy_connections_trial_group == proxy_connections_16) {
[email protected]2431756e2010-09-29 20:26:13321 net::ClientSocketPoolManager::set_max_sockets_per_proxy_server(16);
[email protected]78a258a2010-08-02 16:34:26322 } else if (proxy_connections_trial_group == proxy_connections_32) {
[email protected]2431756e2010-09-29 20:26:13323 net::ClientSocketPoolManager::set_max_sockets_per_proxy_server(32);
[email protected]78a258a2010-08-02 16:34:26324 } else if (proxy_connections_trial_group == proxy_connections_64) {
[email protected]2431756e2010-09-29 20:26:13325 net::ClientSocketPoolManager::set_max_sockets_per_proxy_server(64);
[email protected]78a258a2010-08-02 16:34:26326 } else {
327 NOTREACHED();
328 }
329}
330
[email protected]f8abf722010-07-07 19:46:24331// When --use-spdy not set, users will be in A/B test for spdy.
[email protected]789d04a2010-07-15 21:15:13332// group A (npn_with_spdy): this means npn and spdy are enabled. In case server
333// supports spdy, browser will use spdy.
334// group B (npn_with_http): this means npn is enabled but spdy won't be used.
335// Http is still used for all requests.
336// default group: no npn or spdy is involved. The "old" non-spdy
337// chrome behavior.
[email protected]f8abf722010-07-07 19:46:24338void BrowserMainParts::SpdyFieldTrial() {
339 bool is_spdy_trial = false;
340 if (parsed_command_line().HasSwitch(switches::kUseSpdy)) {
341 std::string spdy_mode =
342 parsed_command_line().GetSwitchValueASCII(switches::kUseSpdy);
343 net::HttpNetworkLayer::EnableSpdy(spdy_mode);
344 } else {
[email protected]835d7c82010-10-14 04:38:38345 const base::FieldTrial::Probability kSpdyDivisor = 100;
346 // 10% to preclude SPDY.
347 base::FieldTrial::Probability npnhttp_probability = 10;
348 scoped_refptr<base::FieldTrial> trial =
349 new base::FieldTrial("SpdyImpact", kSpdyDivisor);
[email protected]f8abf722010-07-07 19:46:24350 // npn with only http support, no spdy.
[email protected]780f8492010-09-16 04:12:15351 int npn_http_grp = trial->AppendGroup("npn_with_http", npnhttp_probability);
[email protected]f8abf722010-07-07 19:46:24352 // npn with spdy support.
[email protected]780f8492010-09-16 04:12:15353 int npn_spdy_grp = trial->AppendGroup("npn_with_spdy",
[email protected]835d7c82010-10-14 04:38:38354 base::FieldTrial::kAllRemainingProbability);
[email protected]f8abf722010-07-07 19:46:24355 int trial_grp = trial->group();
356 if (trial_grp == npn_http_grp) {
357 is_spdy_trial = true;
358 net::HttpNetworkLayer::EnableSpdy("npn-http");
359 } else if (trial_grp == npn_spdy_grp) {
360 is_spdy_trial = true;
361 net::HttpNetworkLayer::EnableSpdy("npn");
362 } else {
363 CHECK(!is_spdy_trial);
364 }
365 }
[email protected]f90a3a5e2010-10-25 05:17:24366 if (parsed_command_line().HasSwitch(switches::kMaxSpdyConcurrentStreams)) {
367 int value = 0;
368 base::StringToInt(parsed_command_line().GetSwitchValueASCII(
369 switches::kMaxSpdyConcurrentStreams),
370 &value);
371 if (value > 0)
372 net::SpdySession::set_max_concurrent_streams(value);
373 }
[email protected]f8abf722010-07-07 19:46:24374}
375
[email protected]8a3125a712010-08-09 18:58:51376// If neither --enable-content-prefetch or --disable-content-prefetch
[email protected]780f8492010-09-16 04:12:15377// is set, users will not be in an A/B test for prefetching.
[email protected]8a3125a712010-08-09 18:58:51378void BrowserMainParts::PrefetchFieldTrial() {
379 if (parsed_command_line().HasSwitch(switches::kEnableContentPrefetch))
380 ResourceDispatcherHost::set_is_prefetch_enabled(true);
381 else if (parsed_command_line().HasSwitch(switches::kDisableContentPrefetch)) {
382 ResourceDispatcherHost::set_is_prefetch_enabled(false);
383 } else {
[email protected]835d7c82010-10-14 04:38:38384 const base::FieldTrial::Probability kPrefetchDivisor = 1000;
385 const base::FieldTrial::Probability no_prefetch_probability = 500;
386 scoped_refptr<base::FieldTrial> trial =
387 new base::FieldTrial("Prefetch", kPrefetchDivisor);
[email protected]8a3125a712010-08-09 18:58:51388 trial->AppendGroup("ContentPrefetchDisabled", no_prefetch_probability);
389 const int yes_prefetch_grp =
390 trial->AppendGroup("ContentPrefetchEnabled",
[email protected]835d7c82010-10-14 04:38:38391 base::FieldTrial::kAllRemainingProbability);
[email protected]8a3125a712010-08-09 18:58:51392 const int trial_grp = trial->group();
393 ResourceDispatcherHost::set_is_prefetch_enabled(
394 trial_grp == yes_prefetch_grp);
395 }
396}
397
[email protected]06d94042010-08-25 01:45:22398// If neither --enable-connect-backup-jobs or --disable-connect-backup-jobs is
399// specified, run an A/B test for automatically establishing backup TCP
400// connections when a certain timeout value is exceeded.
401void BrowserMainParts::ConnectBackupJobsFieldTrial() {
402 if (parsed_command_line().HasSwitch(switches::kEnableConnectBackupJobs)) {
403 net::internal::ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(
404 true);
405 } else if (parsed_command_line().HasSwitch(
406 switches::kDisableConnectBackupJobs)) {
407 net::internal::ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(
408 false);
409 } else {
[email protected]835d7c82010-10-14 04:38:38410 const base::FieldTrial::Probability kConnectBackupJobsDivisor = 100;
411 // 1% probability.
412 const base::FieldTrial::Probability kConnectBackupJobsProbability = 1;
413 scoped_refptr<base::FieldTrial> trial =
414 new base::FieldTrial("ConnnectBackupJobs",
415 kConnectBackupJobsDivisor);
[email protected]780f8492010-09-16 04:12:15416 trial->AppendGroup("ConnectBackupJobsDisabled",
417 kConnectBackupJobsProbability);
[email protected]06d94042010-08-25 01:45:22418 const int connect_backup_jobs_enabled =
419 trial->AppendGroup("ConnectBackupJobsEnabled",
[email protected]835d7c82010-10-14 04:38:38420 base::FieldTrial::kAllRemainingProbability);
[email protected]06d94042010-08-25 01:45:22421 const int trial_group = trial->group();
422 net::internal::ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(
423 trial_group == connect_backup_jobs_enabled);
424 }
425}
426
[email protected]1fec64352010-07-27 13:55:21427// BrowserMainParts: |MainMessageLoopStart()| and related ----------------------
428
429void BrowserMainParts::MainMessageLoopStart() {
430 PreMainMessageLoopStart();
431
432 main_message_loop_.reset(new MessageLoop(MessageLoop::TYPE_UI));
433
434 // TODO(viettrungluu): should these really go before setting the thread name?
435 system_monitor_.reset(new SystemMonitor);
436 hi_res_timer_manager_.reset(new HighResolutionTimerManager);
437 network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
438
439 InitializeMainThread();
440
441 PostMainMessageLoopStart();
442}
443
444void BrowserMainParts::InitializeMainThread() {
445 const char* kThreadName = "CrBrowserMain";
446 PlatformThread::SetName(kThreadName);
447 main_message_loop().set_thread_name(kThreadName);
448
449 // Register the main thread by instantiating it, but don't call any methods.
[email protected]d04e7662010-10-10 22:24:48450 main_thread_.reset(new BrowserThread(BrowserThread::UI,
451 MessageLoop::current()));
[email protected]1fec64352010-07-27 13:55:21452}
453
[email protected]f8abf722010-07-07 19:46:24454// -----------------------------------------------------------------------------
455// TODO(viettrungluu): move more/rest of BrowserMain() into above structure
456
initial.commit09911bf2008-07-26 23:55:29457namespace {
458
459// This function provides some ways to test crash and assertion handling
460// behavior of the program.
[email protected]9bade092009-11-13 17:04:42461void HandleTestParameters(const CommandLine& command_line) {
initial.commit09911bf2008-07-26 23:55:29462 // This parameter causes an assertion.
463 if (command_line.HasSwitch(switches::kBrowserAssertTest)) {
464 DCHECK(false);
465 }
466
467 // This parameter causes a null pointer crash (crash reporter trigger).
468 if (command_line.HasSwitch(switches::kBrowserCrashTest)) {
469 int* bad_pointer = NULL;
470 *bad_pointer = 0;
471 }
[email protected]9bade092009-11-13 17:04:42472
473#if defined(OS_CHROMEOS)
474 // Test loading libcros and exit. We return 0 if the library could be loaded,
475 // and 1 if it can't be. This is for validation that the library is installed
476 // and versioned properly for Chrome to find.
477 if (command_line.HasSwitch(switches::kTestLoadLibcros))
[email protected]62c7ef32010-03-23 23:44:24478 exit(!chromeos::CrosLibrary::Get()->EnsureLoaded());
[email protected]9bade092009-11-13 17:04:42479#endif
initial.commit09911bf2008-07-26 23:55:29480}
481
[email protected]d4515eb2009-01-30 00:40:43482void RunUIMessageLoop(BrowserProcess* browser_process) {
[email protected]a872ea1f2010-08-11 04:45:33483 TRACE_EVENT_BEGIN("BrowserMain:MESSAGE_LOOP", 0, "");
484
[email protected]148d1052009-07-31 22:53:37485#if defined(TOOLKIT_VIEWS)
[email protected]047f6222009-07-29 23:34:56486 views::AcceleratorHandler accelerator_handler;
487 MessageLoopForUI::current()->Run(&accelerator_handler);
[email protected]25d47c7b2010-02-03 20:13:06488#elif defined(USE_X11)
[email protected]148d1052009-07-31 22:53:37489 MessageLoopForUI::current()->Run(NULL);
[email protected]d4515eb2009-01-30 00:40:43490#elif defined(OS_POSIX)
491 MessageLoopForUI::current()->Run();
492#endif
[email protected]a872ea1f2010-08-11 04:45:33493
494 TRACE_EVENT_END("BrowserMain:MESSAGE_LOOP", 0, "");
[email protected]d4515eb2009-01-30 00:40:43495}
496
[email protected]1188a6c2009-05-09 00:27:42497void AddFirstRunNewTabs(BrowserInit* browser_init,
[email protected]f9886382010-03-10 04:45:54498 const std::vector<GURL>& new_tabs) {
499 for (std::vector<GURL>::const_iterator it = new_tabs.begin();
[email protected]201028d2010-02-12 21:28:01500 it != new_tabs.end(); ++it) {
[email protected]f9886382010-03-10 04:45:54501 if (it->is_valid())
502 browser_init->AddFirstRunTab(*it);
[email protected]1188a6c2009-05-09 00:27:42503 }
504}
[email protected]1188a6c2009-05-09 00:27:42505
[email protected]ba80aa72009-09-23 22:12:23506#if defined(USE_LINUX_BREAKPAD)
507class GetLinuxDistroTask : public Task {
508 public:
509 explicit GetLinuxDistroTask() {}
510
511 virtual void Run() {
512 base::GetLinuxDistro(); // Initialize base::linux_distro if needed.
513 }
514
515 DISALLOW_COPY_AND_ASSIGN(GetLinuxDistroTask);
516};
517#endif // USE_LINUX_BREAKPAD
[email protected]ea500fc62010-03-22 21:34:29518
[email protected]7e59cff2010-03-23 16:12:40519void InitializeNetworkOptions(const CommandLine& parsed_command_line) {
520 if (parsed_command_line.HasSwitch(switches::kEnableFileCookies)) {
521 // Enable cookie storage for file:// URLs. Must do this before the first
522 // Profile (and therefore the first CookieMonster) is created.
523 net::CookieMonster::EnableFileScheme();
524 }
525
[email protected]7e59cff2010-03-23 16:12:40526 if (parsed_command_line.HasSwitch(switches::kIgnoreCertificateErrors))
[email protected]8e6441ca2010-08-19 05:56:38527 net::HttpStreamFactory::set_ignore_certificate_errors(true);
[email protected]7e59cff2010-03-23 16:12:40528
[email protected]b6a50182010-05-12 22:47:14529 if (parsed_command_line.HasSwitch(switches::kHostRules))
[email protected]8e6441ca2010-08-19 05:56:38530 net::HttpStreamFactory::SetHostMappingRules(
[email protected]b6a50182010-05-12 22:47:14531 parsed_command_line.GetSwitchValueASCII(switches::kHostRules));
532
[email protected]7e59cff2010-03-23 16:12:40533 if (parsed_command_line.HasSwitch(switches::kMaxSpdySessionsPerDomain)) {
[email protected]e83326f2010-07-31 17:29:25534 int value;
535 base::StringToInt(parsed_command_line.GetSwitchValueASCII(
536 switches::kMaxSpdySessionsPerDomain),
537 &value);
[email protected]7e59cff2010-03-23 16:12:40538 net::SpdySessionPool::set_max_sessions_per_domain(value);
539 }
540}
541
[email protected]34f73fb2010-03-24 20:50:34542// Creates key child threads. We need to do this explicitly since
[email protected]d04e7662010-10-10 22:24:48543// BrowserThread::PostTask silently deletes a posted task if the target message
[email protected]34f73fb2010-03-24 20:50:34544// loop isn't created.
545void CreateChildThreads(BrowserProcessImpl* process) {
546 process->db_thread();
547 process->file_thread();
548 process->process_launcher_thread();
[email protected]875ee822010-05-18 20:58:01549 process->cache_thread();
[email protected]34f73fb2010-03-24 20:50:34550 process->io_thread();
551}
552
[email protected]7e59cff2010-03-23 16:12:40553// Returns the new local state object, guaranteed non-NULL.
554PrefService* InitializeLocalState(const CommandLine& parsed_command_line,
555 bool is_first_run) {
556 FilePath local_state_path;
557 PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
558 bool local_state_file_exists = file_util::PathExists(local_state_path);
559
560 // Load local state. This includes the application locale so we know which
561 // locale dll to load.
562 PrefService* local_state = g_browser_process->local_state();
563 DCHECK(local_state);
564
565 // Initialize ResourceBundle which handles files loaded from external
566 // sources. This has to be done before uninstall code path and before prefs
567 // are registered.
[email protected]20ce516d2010-06-18 02:20:04568 local_state->RegisterStringPref(prefs::kApplicationLocale, "");
[email protected]c7db33a2010-10-06 18:57:25569#if !defined(OS_CHROMEOS)
[email protected]7e59cff2010-03-23 16:12:40570 local_state->RegisterBooleanPref(prefs::kMetricsReportingEnabled,
571 GoogleUpdateSettings::GetCollectStatsConsent());
[email protected]c7db33a2010-10-06 18:57:25572#endif // !defined(OS_CHROMEOS)
[email protected]7e59cff2010-03-23 16:12:40573
574 if (is_first_run) {
575#if defined(OS_WIN)
576 // During first run we read the google_update registry key to find what
577 // language the user selected when downloading the installer. This
578 // becomes our default language in the prefs.
579 // Other platforms obey the system locale.
580 std::wstring install_lang;
[email protected]ddd231e2010-06-29 20:35:19581 if (GoogleUpdateSettings::GetLanguage(&install_lang)) {
582 local_state->SetString(prefs::kApplicationLocale,
583 WideToASCII(install_lang));
584 }
[email protected]7e59cff2010-03-23 16:12:40585#endif // defined(OS_WIN)
586 }
587
588 // If the local state file for the current profile doesn't exist and the
589 // parent profile command line flag is present, then we should inherit some
590 // local state from the parent profile.
591 // Checking that the local state file for the current profile doesn't exist
592 // is the most robust way to determine whether we need to inherit or not
593 // since the parent profile command line flag can be present even when the
594 // current profile is not a new one, and in that case we do not want to
595 // inherit and reset the user's setting.
596 if (!local_state_file_exists &&
597 parsed_command_line.HasSwitch(switches::kParentProfile)) {
598 FilePath parent_profile =
599 parsed_command_line.GetSwitchValuePath(switches::kParentProfile);
[email protected]d8b08c92010-06-07 13:13:28600 scoped_ptr<PrefService> parent_local_state(
[email protected]a9c23a52010-08-04 09:13:44601 PrefService::CreatePrefService(parent_profile, NULL));
[email protected]d8b08c92010-06-07 13:13:28602 parent_local_state->RegisterStringPref(prefs::kApplicationLocale,
[email protected]20ce516d2010-06-18 02:20:04603 std::string());
[email protected]7e59cff2010-03-23 16:12:40604 // Right now, we only inherit the locale setting from the parent profile.
605 local_state->SetString(
606 prefs::kApplicationLocale,
[email protected]d8b08c92010-06-07 13:13:28607 parent_local_state->GetString(prefs::kApplicationLocale));
[email protected]7e59cff2010-03-23 16:12:40608 }
609
610 return local_state;
611}
612
[email protected]60626da2010-03-25 17:06:53613// Windows-specific initialization code for the sandbox broker services. This
614// is just a NOP on non-Windows platforms to reduce ifdefs later on.
615void InitializeBrokerServices(const MainFunctionParams& parameters,
616 const CommandLine& parsed_command_line) {
617#if defined(OS_WIN)
618 sandbox::BrokerServices* broker_services =
619 parameters.sandbox_info_.BrokerServices();
620 if (broker_services) {
621 sandbox::InitBrokerServices(broker_services);
622 if (!parsed_command_line.HasSwitch(switches::kNoSandbox)) {
623 bool use_winsta = !parsed_command_line.HasSwitch(
624 switches::kDisableAltWinstation);
625 // Precreate the desktop and window station used by the renderers.
626 sandbox::TargetPolicy* policy = broker_services->CreatePolicy();
627 sandbox::ResultCode result = policy->CreateAlternateDesktop(use_winsta);
628 CHECK(sandbox::SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION != result);
629 policy->Release();
630 }
631 }
632#endif
633}
634
635// Initializes the metrics service with the configuration for this process,
636// returning the created service (guaranteed non-NULL).
[email protected]838e1a92010-03-25 17:47:45637MetricsService* InitializeMetrics(const CommandLine& parsed_command_line,
638 const PrefService* local_state) {
[email protected]60626da2010-03-25 17:06:53639#if defined(OS_WIN)
640 if (InstallUtil::IsChromeFrameProcess())
641 MetricsLog::set_version_extension("-F");
642#elif defined(ARCH_CPU_64_BITS)
643 MetricsLog::set_version_extension("-64");
644#endif // defined(OS_WIN)
645
646 MetricsService* metrics = g_browser_process->metrics_service();
647
648 if (parsed_command_line.HasSwitch(switches::kMetricsRecordingOnly)) {
649 // If we're testing then we don't care what the user preference is, we turn
650 // on recording, but not reporting, otherwise tests fail.
651 metrics->StartRecordingOnly();
652 } else {
653 // If the user permits metrics reporting with the checkbox in the
654 // prefs, we turn on recording. We disable metrics completely for
655 // non-official builds.
656#if defined(GOOGLE_CHROME_BUILD)
[email protected]c7db33a2010-10-06 18:57:25657#if defined(OS_CHROMEOS)
658 bool enabled = chromeos::MetricsCrosSettingsProvider::GetMetricsStatus();
659#else
[email protected]60626da2010-03-25 17:06:53660 bool enabled = local_state->GetBoolean(prefs::kMetricsReportingEnabled);
[email protected]c7db33a2010-10-06 18:57:25661#endif // #if defined(OS_CHROMEOS)
[email protected]60626da2010-03-25 17:06:53662 metrics->SetUserPermitsUpload(enabled);
[email protected]f48ef032010-05-20 04:53:11663 if (enabled) {
[email protected]60626da2010-03-25 17:06:53664 metrics->Start();
[email protected]f48ef032010-05-20 04:53:11665 chrome_browser_net_websocket_experiment::
666 WebSocketExperimentRunner::Start();
667 }
[email protected]60626da2010-03-25 17:06:53668#endif
669 }
670
671 return metrics;
672}
673
[email protected]20271f32010-03-26 03:04:51674// Initializes the profile, possibly doing some user prompting to pick a
675// fallback profile. Returns the newly created profile, or NULL if startup
676// should not continue.
677Profile* CreateProfile(const MainFunctionParams& parameters,
678 const FilePath& user_data_dir) {
679 Profile* profile = g_browser_process->profile_manager()->GetDefaultProfile(
680 user_data_dir);
681 if (profile)
682 return profile;
683
684#if defined(OS_WIN)
685 // Ideally, we should be able to run w/o access to disk. For now, we
686 // prompt the user to pick a different user-data-dir and restart chrome
687 // with the new dir.
688 // http://code.google.com/p/chromium/issues/detail?id=11510
689 FilePath new_user_data_dir = UserDataDirDialog::RunUserDataDirDialog(
690 user_data_dir);
691 if (!parameters.ui_task && browser_shutdown::delete_resources_on_shutdown) {
692 // Only delete the resources if we're not running tests. If we're running
693 // tests the resources need to be reused as many places in the UI cache
694 // SkBitmaps from the ResourceBundle.
695 ResourceBundle::CleanupSharedInstance();
696 }
697
698 if (!new_user_data_dir.empty()) {
699 // Because of the way CommandLine parses, it's sufficient to append a new
700 // --user-data-dir switch. The last flag of the same name wins.
701 // TODO(tc): It would be nice to remove the flag we don't want, but that
702 // sounds risky if we parse differently than CommandLineToArgvW.
703 CommandLine new_command_line = parameters.command_line_;
[email protected]4f08c83f2010-07-29 23:02:34704 new_command_line.AppendSwitchPath(switches::kUserDataDir,
705 new_user_data_dir);
[email protected]20271f32010-03-26 03:04:51706 base::LaunchApp(new_command_line, false, false, NULL);
707 }
708#else
709 // TODO(port): fix this. See comments near the definition of
710 // user_data_dir. It is better to CHECK-fail here than it is to
711 // silently exit because of missing code in the above test.
712 CHECK(profile) << "Cannot get default profile.";
713#endif
714
715 return NULL;
716}
717
[email protected]ea500fc62010-03-22 21:34:29718#if defined(OS_WIN)
719
720// gfx::Font callbacks
721void AdjustUIFont(LOGFONT* logfont) {
722 l10n_util::AdjustUIFont(logfont);
723}
724
725int GetMinimumFontSize() {
[email protected]b1a71cc2010-08-03 15:21:27726 int min_font_size;
727 base::StringToInt(l10n_util::GetStringUTF16(IDS_MINIMUM_UI_FONT_SIZE),
728 &min_font_size);
729 return min_font_size;
[email protected]ea500fc62010-03-22 21:34:29730}
731
[email protected]c9e1715c2010-09-09 04:36:52732#elif defined(OS_CHROMEOS)
733// Changes the UI font if non-default font name is specified in
734// IDS_UI_FONT_FAMILY_CROS. This is necessary as the default font
735// specified in /etc/gtk-2.0/gtrkc may not work well for some languages
736// For instance, ChromeDroidSans does not work well for Japanese users,
737// since Chinese glyphs are used for Kanji characters.
738void MaybeChangeUIFont() {
739 const std::string font_name =
740 l10n_util::GetStringUTF8(IDS_UI_FONT_FAMILY_CROS);
741 // The font name should not be empty here, but just in case.
742 if (font_name == "default" || font_name.empty()) {
743 return;
744 }
745 gtk_util::SetGtkFont(font_name);
746}
[email protected]ea500fc62010-03-22 21:34:29747#endif
[email protected]7e59cff2010-03-23 16:12:40748
749#if defined(TOOLKIT_GTK)
750void InitializeToolkit() {
751 // It is important for this to happen before the first run dialog, as it
752 // styles the dialog as well.
753 gtk_util::InitRCStyles();
754}
755#elif defined(TOOLKIT_VIEWS)
756void InitializeToolkit() {
757 // The delegate needs to be set before any UI is created so that windows
758 // display the correct icon.
759 if (!views::ViewsDelegate::views_delegate)
760 views::ViewsDelegate::views_delegate = new ChromeViewsDelegate;
761
762#if defined(OS_WIN)
[email protected]c6ac8412010-08-13 16:43:03763 gfx::PlatformFontWin::adjust_font_callback = &AdjustUIFont;
764 gfx::PlatformFontWin::get_minimum_font_size_callback = &GetMinimumFontSize;
[email protected]20271f32010-03-26 03:04:51765
766 // Init common control sex.
767 INITCOMMONCONTROLSEX config;
768 config.dwSize = sizeof(config);
769 config.dwICC = ICC_WIN95_CLASSES;
770 InitCommonControlsEx(&config);
[email protected]7e59cff2010-03-23 16:12:40771#endif
772}
773#else
774void InitializeToolkit() {
775}
776#endif
777
[email protected]34f73fb2010-03-24 20:50:34778#if defined(OS_CHROMEOS)
[email protected]368ad4ca2010-06-15 16:07:45779
[email protected]617fd0d2010-08-04 20:05:17780// Class is used to login using passed username and password.
781// The instance will be deleted upon success or failure.
782class StubLogin : public chromeos::LoginStatusConsumer {
783 public:
784 explicit StubLogin(std::string username, std::string password) {
785 authenticator_ = chromeos::LoginUtils::Get()->CreateAuthenticator(this);
786 authenticator_.get()->AuthenticateToLogin(
787 g_browser_process->profile_manager()->GetDefaultProfile(),
788 username,
789 password,
790 std::string(),
791 std::string());
792 }
793
[email protected]99074c52010-08-19 18:44:19794 void OnLoginFailure(const chromeos::LoginFailure& error) {
795 LOG(ERROR) << "Login Failure: " << error.GetErrorString();
[email protected]617fd0d2010-08-04 20:05:17796 delete this;
797 }
798
799 void OnLoginSuccess(const std::string& username,
[email protected]22b337442010-10-05 16:27:37800 const GaiaAuthConsumer::ClientLoginResult& credentials,
801 bool pending_requests) {
[email protected]617fd0d2010-08-04 20:05:17802 chromeos::LoginUtils::Get()->CompleteLogin(username, credentials);
803 delete this;
804 }
805
806 scoped_refptr<chromeos::Authenticator> authenticator_;
807};
808
[email protected]34f73fb2010-03-24 20:50:34809void OptionallyRunChromeOSLoginManager(const CommandLine& parsed_command_line) {
810 if (parsed_command_line.HasSwitch(switches::kLoginManager)) {
811 std::string first_screen =
812 parsed_command_line.GetSwitchValueASCII(switches::kLoginScreen);
813 std::string size_arg =
814 parsed_command_line.GetSwitchValueASCII(
815 switches::kLoginScreenSize);
816 gfx::Size size(0, 0);
817 // Allow the size of the login window to be set explicitly. If not set,
818 // default to the entire screen. This is mostly useful for testing.
819 if (size_arg.size()) {
820 std::vector<std::string> dimensions;
[email protected]76eb0242010-10-14 00:35:36821 base::SplitString(size_arg, ',', &dimensions);
[email protected]e83326f2010-07-31 17:29:25822 if (dimensions.size() == 2) {
823 int width, height;
824 if (base::StringToInt(dimensions[0], &width) &&
825 base::StringToInt(dimensions[1], &height))
826 size.SetSize(width, height);
827 }
[email protected]34f73fb2010-03-24 20:50:34828 }
829 browser::ShowLoginWizard(first_screen, size);
[email protected]617fd0d2010-08-04 20:05:17830 } else if (parsed_command_line.HasSwitch(switches::kLoginUser) &&
831 parsed_command_line.HasSwitch(switches::kLoginPassword)) {
[email protected]cddf7b382010-10-21 22:17:38832 chromeos::BootTimesLoader::Get()->RecordLoginAttempted();
[email protected]617fd0d2010-08-04 20:05:17833 new StubLogin(
834 parsed_command_line.GetSwitchValueASCII(switches::kLoginUser),
835 parsed_command_line.GetSwitchValueASCII(switches::kLoginPassword));
[email protected]34f73fb2010-03-24 20:50:34836 }
837}
[email protected]368ad4ca2010-06-15 16:07:45838
[email protected]34f73fb2010-03-24 20:50:34839#else
[email protected]368ad4ca2010-06-15 16:07:45840
[email protected]34f73fb2010-03-24 20:50:34841void OptionallyRunChromeOSLoginManager(const CommandLine& parsed_command_line) {
842 // Dummy empty function for non-ChromeOS builds to avoid extra ifdefs below.
843}
[email protected]368ad4ca2010-06-15 16:07:45844
[email protected]368ad4ca2010-06-15 16:07:45845#endif // defined(OS_CHROMEOS)
[email protected]34f73fb2010-03-24 20:50:34846
[email protected]e457f742010-04-02 17:25:43847#if defined(OS_MACOSX)
848OSStatus KeychainCallback(SecKeychainEvent keychain_event,
849 SecKeychainCallbackInfo *info, void *context) {
850 return noErr;
851}
852#endif
853
initial.commit09911bf2008-07-26 23:55:29854} // namespace
855
[email protected]617fd0d2010-08-04 20:05:17856#if defined(OS_CHROMEOS)
857// Allows authenticator to be invoked without adding refcounting. The instances
858// will delete themselves upon completion.
859DISABLE_RUNNABLE_METHOD_REFCOUNT(StubLogin);
860#endif
861
[email protected]3cdacd42010-04-30 18:55:53862#if defined(OS_WIN)
863#define DLLEXPORT __declspec(dllexport)
864
865// We use extern C for the prototype DLLEXPORT to avoid C++ name mangling.
866extern "C" {
867DLLEXPORT void __cdecl RelaunchChromeBrowserWithNewCommandLineIfNeeded();
868}
869
870DLLEXPORT void __cdecl RelaunchChromeBrowserWithNewCommandLineIfNeeded() {
[email protected]e2cc2e62010-08-28 00:26:37871 // Need an instance of AtExitManager to handle singleton creations and
872 // deletions. We need this new instance because, the old instance created
873 // in ChromeMain() got destructed when the function returned.
874 base::AtExitManager exit_manager;
[email protected]3cdacd42010-04-30 18:55:53875 Upgrade::RelaunchChromeBrowserWithNewCommandLineIfNeeded();
876}
877#endif
878
[email protected]a16579a2010-10-14 18:41:55879#if defined(USE_LINUX_BREAKPAD)
880bool IsMetricsReportingEnabled(const PrefService* local_state) {
881 // Check whether we should initialize the crash reporter. It may be disabled
882 // through configuration policy or user preference. The kHeadless environment
883 // variable overrides the decision, but only if the crash service is under
884 // control of the user. The CHROME_HEADLESS environment variable is used by QA
885 // testing infrastructure to switch on generation of crash reports.
886#if defined(OS_CHROMEOS)
887 bool breakpad_enabled =
888 chromeos::MetricsCrosSettingsProvider::GetMetricsStatus();
889#else
890 const PrefService::Preference* metrics_reporting_enabled =
891 local_state->FindPreference(prefs::kMetricsReportingEnabled);
892 CHECK(metrics_reporting_enabled);
893 bool breakpad_enabled =
894 local_state->GetBoolean(prefs::kMetricsReportingEnabled);
895 if (!breakpad_enabled && metrics_reporting_enabled->IsUserModifiable())
896 breakpad_enabled = getenv(env_vars::kHeadless) != NULL;
897#endif // #if defined(OS_CHROMEOS)
898 return breakpad_enabled;
899}
900#endif // #if defined(USE_LINUX_BREAKPAD)
901
initial.commit09911bf2008-07-26 23:55:29902// Main routine for running as the Browser process.
[email protected]a1a130f7d2009-01-09 20:28:44903int BrowserMain(const MainFunctionParams& parameters) {
[email protected]a872ea1f2010-08-11 04:45:33904 TRACE_EVENT_BEGIN("BrowserMain", 0, "");
[email protected]f8abf722010-07-07 19:46:24905 scoped_ptr<BrowserMainParts>
906 parts(BrowserMainParts::CreateBrowserMainParts(parameters));
907
908 parts->EarlyInitialization();
[email protected]1fec64352010-07-27 13:55:21909 parts->MainMessageLoopStart();
[email protected]f8abf722010-07-07 19:46:24910
[email protected]1fec64352010-07-27 13:55:21911 // WARNING: If we get a WM_ENDSESSION, objects created on the stack here
initial.commit09911bf2008-07-26 23:55:29912 // are NOT deleted. If you need something to run during WM_ENDSESSION add it
913 // to browser_shutdown::Shutdown or BrowserProcess::EndSession.
914
[email protected]d7dbe28c2010-07-29 04:33:47915 // !!!!!!!!!! READ ME !!!!!!!!!!
916 // I (viettrungluu) am in the process of refactoring |BrowserMain()|. If you
917 // need to add something above this comment, read the documentation in
918 // browser_main.h. If you need to add something below, please do the
919 // following:
920 // - Figure out where you should add your code. Do NOT just pick a random
921 // location "which works".
922 // - Document the dependencies apart from compile-time-checkable ones. What
923 // must happen before your new code is executed? Does your new code need to
924 // run before something else? Are there performance reasons for executing
925 // your code at that point?
926 // - If you need to create a (persistent) object, heap allocate it and keep a
927 // |scoped_ptr| to it rather than allocating it on the stack. Otherwise
928 // I'll have to convert your code when I refactor.
929 // - Unless your new code is just a couple of lines, factor it out into a
930 // function with a well-defined purpose. Do NOT just add it inline in
931 // |BrowserMain()|.
932 // Thanks!
initial.commit09911bf2008-07-26 23:55:29933
[email protected]1fec64352010-07-27 13:55:21934 // TODO(viettrungluu): put the remainder into BrowserMainParts
935 const CommandLine& parsed_command_line = parameters.command_line_;
[email protected]c2818d42010-10-18 02:47:39936 base::mac::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool_;
[email protected]206d3c42010-01-19 23:59:20937
[email protected]f7011fcb2009-01-28 21:54:32938 FilePath user_data_dir;
[email protected]0c298a52009-09-25 21:33:52939#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29940 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
[email protected]0c298a52009-09-25 21:33:52941#else
942 // Getting the user data dir can fail if the directory isn't
943 // creatable, for example; on Windows in code below we bring up a
944 // dialog prompting the user to pick a different directory.
945 // However, ProcessSingleton needs a real user_data_dir on Mac/Linux,
946 // so it's better to fail here than fail mysteriously elsewhere.
947 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
948 << "Must be able to get user data directory!";
949#endif
950
[email protected]7c47ae3e2009-02-18 00:34:21951 ProcessSingleton process_singleton(user_data_dir);
initial.commit09911bf2008-07-26 23:55:29952
[email protected]1d1a51b2009-01-29 23:25:08953 bool is_first_run = FirstRun::IsChromeFirstRun() ||
954 parsed_command_line.HasSwitch(switches::kFirstRun);
[email protected]1d1a51b2009-01-29 23:25:08955
[email protected]914511712009-11-23 19:42:33956 scoped_ptr<BrowserProcessImpl> browser_process;
[email protected]02aae3f2010-03-22 22:31:27957 if (parsed_command_line.HasSwitch(switches::kImport) ||
958 parsed_command_line.HasSwitch(switches::kImportFromFile)) {
initial.commit09911bf2008-07-26 23:55:29959 // We use different BrowserProcess when importing so no GoogleURLTracker is
960 // instantiated (as it makes a URLRequest and we don't have an IO thread,
961 // see bug #1292702).
962 browser_process.reset(new FirstRunBrowserProcess(parsed_command_line));
[email protected]1d1a51b2009-01-29 23:25:08963 is_first_run = false;
initial.commit09911bf2008-07-26 23:55:29964 } else {
965 browser_process.reset(new BrowserProcessImpl(parsed_command_line));
966 }
967
968 // BrowserProcessImpl's constructor should set g_browser_process.
969 DCHECK(g_browser_process);
970
[email protected]0b4d3382010-07-14 16:13:04971 // This forces the TabCloseableStateWatcher to be created and, on chromeos,
972 // register for the notifications it needs to track the closeable state of
973 // tabs.
974 g_browser_process->tab_closeable_state_watcher();
975
[email protected]60626da2010-03-25 17:06:53976 // The broker service initialization needs to run early because it will
977 // initialize the sandbox broker, which requires the process to swap its
978 // window station. During this time all the UI will be broken. This has to
979 // run before threads and windows are created.
980 InitializeBrokerServices(parameters, parsed_command_line);
[email protected]ff608eb2009-05-20 16:05:56981
[email protected]a2dd1a602010-09-20 23:09:27982 // Initialize histogram statistics gathering system.
[email protected]835d7c82010-10-14 04:38:38983 base::StatisticsRecorder statistics;
[email protected]a2dd1a602010-09-20 23:09:27984
[email protected]7e59cff2010-03-23 16:12:40985 PrefService* local_state = InitializeLocalState(parsed_command_line,
986 is_first_run);
[email protected]f2530062008-12-03 23:52:03987
[email protected]1b084b5e2010-08-03 07:58:19988#if defined(USE_LINUX_BREAKPAD)
989 // Needs to be called after we have chrome::DIR_USER_DATA and
990 // g_browser_process.
991 g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
992 new GetLinuxDistroTask());
993
[email protected]a16579a2010-10-14 18:41:55994 if (IsMetricsReportingEnabled(local_state))
[email protected]1b084b5e2010-08-03 07:58:19995 InitCrashReporter();
996#endif
997
[email protected]7e59cff2010-03-23 16:12:40998 InitializeToolkit(); // Must happen before we try to display any UI.
[email protected]f2530062008-12-03 23:52:03999
[email protected]d4515eb2009-01-30 00:40:431000 // If we're running tests (ui_task is non-null), then the ResourceBundle
1001 // has already been initialized.
[email protected]ce4b6a92009-12-10 00:04:481002 if (parameters.ui_task) {
[email protected]f1b6de22010-03-06 12:13:471003 g_browser_process->SetApplicationLocale("en-US");
[email protected]ce4b6a92009-12-10 00:04:481004 } else {
[email protected]1fec64352010-07-27 13:55:211005 // Mac starts it earlier in |PreMainMessageLoopStart()| (because it is
1006 // needed when loading the MainMenu.nib and the language doesn't depend on
1007 // anything since it comes from Cocoa.
[email protected]ce4b6a92009-12-10 00:04:481008#if defined(OS_MACOSX)
[email protected]f1b6de22010-03-06 12:13:471009 g_browser_process->SetApplicationLocale(l10n_util::GetLocaleOverride());
[email protected]ce4b6a92009-12-10 00:04:481010#else
[email protected]d90de1c02010-07-19 19:50:481011 // On a POSIX OS other than ChromeOS, the parameter that is passed to the
1012 // method InitSharedInstance is ignored.
[email protected]ce4b6a92009-12-10 00:04:481013 std::string app_locale = ResourceBundle::InitSharedInstance(
[email protected]ff622aa2010-08-04 17:07:461014 local_state->GetString(prefs::kApplicationLocale));
[email protected]f1b6de22010-03-06 12:13:471015 g_browser_process->SetApplicationLocale(app_locale);
[email protected]e1cb0e92010-06-15 07:23:591016
1017 FilePath resources_pack_path;
1018 PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path);
1019 ResourceBundle::AddDataPackToSharedInstance(resources_pack_path);
[email protected]885b7272009-08-12 20:33:051020#endif // !defined(OS_MACOSX)
[email protected]ce4b6a92009-12-10 00:04:481021 }
initial.commit09911bf2008-07-26 23:55:291022
[email protected]0f13d432010-07-22 21:30:301023#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
1024 // gdk_pixbuf_loader_write always fails on chromeos device.
1025 // Disabling for chromeos as well because chromeos is not using them.
1026 // http://crosbug.com/4996 .
[email protected]d0646f32009-08-27 00:58:461027 gtk_util::SetDefaultWindowIcon();
1028#endif
1029
[email protected]5d39e3142009-12-17 05:54:101030 std::string try_chrome =
1031 parsed_command_line.GetSwitchValueASCII(switches::kTryChromeAgain);
[email protected]c4b3858c2009-09-09 19:35:311032 if (!try_chrome.empty()) {
[email protected]28de7d942010-02-23 01:43:041033#if defined(OS_WIN)
[email protected]b1a71cc2010-08-03 15:21:271034 int try_chrome_int;
1035 base::StringToInt(try_chrome, &try_chrome_int);
1036 Upgrade::TryResult answer = Upgrade::ShowTryChromeDialog(try_chrome_int);
[email protected]37a24e02009-06-12 21:34:141037 if (answer == Upgrade::TD_NOT_NOW)
[email protected]42d7510c2009-12-19 01:48:301038 return ResultCodes::NORMAL_EXIT_CANCEL;
[email protected]37a24e02009-06-12 21:34:141039 if (answer == Upgrade::TD_UNINSTALL_CHROME)
[email protected]3c30f4c12009-06-19 22:55:471040 return ResultCodes::NORMAL_EXIT_EXP2;
[email protected]28de7d942010-02-23 01:43:041041#else
1042 // We don't support retention experiments on Mac or Linux.
1043 return ResultCodes::NORMAL_EXIT;
1044#endif // defined(OS_WIN)
[email protected]37a24e02009-06-12 21:34:141045 }
[email protected]37a24e02009-06-12 21:34:141046
[email protected]1188a6c2009-05-09 00:27:421047 BrowserInit browser_init;
1048
[email protected]74be069e82010-06-25 00:12:491049 // On first run, we need to process the predictor preferences before the
[email protected]34f73fb2010-03-24 20:50:341050 // browser's profile_manager object is created, but after ResourceBundle
1051 // is initialized.
[email protected]2858bbf2010-10-05 23:46:021052 FirstRun::MasterPrefs master_prefs;
[email protected]34f73fb2010-03-24 20:50:341053 bool first_run_ui_bypass = false; // True to skip first run UI.
[email protected]fe247ac2009-03-19 00:10:481054 if (is_first_run) {
[email protected]a53915592010-02-26 20:21:401055 first_run_ui_bypass =
[email protected]f8512882010-05-27 00:47:561056 !FirstRun::ProcessMasterPreferences(user_data_dir, &master_prefs);
[email protected]34f73fb2010-03-24 20:50:341057 AddFirstRunNewTabs(&browser_init, master_prefs.new_tabs);
[email protected]fe247ac2009-03-19 00:10:481058
1059 // If we are running in App mode, we do not want to show the importer
1060 // (first run) UI.
[email protected]6cf2af2e2009-05-05 20:17:251061 if (!first_run_ui_bypass &&
1062 (parsed_command_line.HasSwitch(switches::kApp) ||
[email protected]34f73fb2010-03-24 20:50:341063 parsed_command_line.HasSwitch(switches::kNoFirstRun)))
[email protected]fe247ac2009-03-19 00:10:481064 first_run_ui_bypass = true;
1065 }
1066
[email protected]f8abf722010-07-07 19:46:241067 // TODO(viettrungluu): why don't we run this earlier?
[email protected]34f73fb2010-03-24 20:50:341068 if (!parsed_command_line.HasSwitch(switches::kNoErrorDialogs))
1069 WarnAboutMinimumSystemRequirements();
initial.commit09911bf2008-07-26 23:55:291070
[email protected]7e59cff2010-03-23 16:12:401071 InitializeNetworkOptions(parsed_command_line);
[email protected]4a5e1782010-03-05 20:49:021072
[email protected]c9a3ef82009-05-28 22:02:461073 // Initialize histogram synchronizer system. This is a singleton and is used
1074 // for posting tasks via NewRunnableMethod. Its deleted when it goes out of
1075 // scope. Even though NewRunnableMethod does AddRef and Release, the object
1076 // will not be deleted after the Task is executed.
1077 scoped_refptr<HistogramSynchronizer> histogram_synchronizer =
1078 new HistogramSynchronizer();
1079
[email protected]9acc48602009-11-30 21:18:511080 // Initialize the prefs of the local state.
1081 browser::RegisterLocalState(local_state);
initial.commit09911bf2008-07-26 23:55:291082
[email protected]6b5f21d2009-04-13 17:01:351083 // Now that all preferences have been registered, set the install date
1084 // for the uninstall metrics if this is our first run. This only actually
1085 // gets used if the user has metrics reporting enabled at uninstall time.
1086 int64 install_date =
1087 local_state->GetInt64(prefs::kUninstallMetricsInstallDate);
1088 if (install_date == 0) {
1089 local_state->SetInt64(prefs::kUninstallMetricsInstallDate,
1090 base::Time::Now().ToTimeT());
1091 }
1092
[email protected]e457f742010-04-02 17:25:431093#if defined(OS_MACOSX)
1094 // Get the Keychain API to register for distributed notifications on the main
1095 // thread, which has a proper CFRunloop, instead of later on the I/O thread,
1096 // which doesn't. This ensures those notifications will get delivered
1097 // properly. See issue 37766.
1098 // (Note that the callback mask here is empty. I don't want to register for
1099 // any callbacks, I just want to initialize the mechanism.)
1100 SecKeychainAddCallback(&KeychainCallback, 0, NULL);
1101#endif
1102
[email protected]34f73fb2010-03-24 20:50:341103 CreateChildThreads(browser_process.get());
[email protected]61e95722009-11-25 06:54:111104
[email protected]d4fe1fbc2010-05-19 17:36:061105#if defined(OS_CHROMEOS)
1106 // Now that the file thread exists we can record our stats.
[email protected]445a9712010-07-21 15:55:481107 chromeos::BootTimesLoader::Get()->RecordChromeMainStats();
[email protected]c9e1715c2010-09-09 04:36:521108 // Change the UI font if necessary. This has to be done after
1109 // InitSharedInstance() is called, as it depends on resource data.
1110 MaybeChangeUIFont();
[email protected]d4fe1fbc2010-05-19 17:36:061111#endif
1112
initial.commit09911bf2008-07-26 23:55:291113 // Record last shutdown time into a histogram.
1114 browser_shutdown::ReadLastShutdownInfo();
[email protected]04999e62009-09-25 01:27:311115
[email protected]01109dcf2010-03-27 00:56:431116#if defined(OS_WIN)
[email protected]04999e62009-09-25 01:27:311117 // On Windows, we use our startup as an opportunity to do upgrade/uninstall
1118 // tasks. Those care whether the browser is already running. On Linux/Mac,
1119 // upgrade/uninstall happen separately.
1120 bool already_running = Upgrade::IsBrowserAlreadyRunning();
initial.commit09911bf2008-07-26 23:55:291121
1122 // If the command line specifies 'uninstall' then we need to work here
1123 // unless we detect another chrome browser running.
[email protected]53c38d232009-02-13 20:52:181124 if (parsed_command_line.HasSwitch(switches::kUninstall))
1125 return DoUninstallTasks(already_running);
[email protected]04999e62009-09-25 01:27:311126#endif
initial.commit09911bf2008-07-26 23:55:291127
1128 if (parsed_command_line.HasSwitch(switches::kHideIcons) ||
[email protected]201028d2010-02-12 21:28:011129 parsed_command_line.HasSwitch(switches::kShowIcons))
initial.commit09911bf2008-07-26 23:55:291130 return HandleIconsCommands(parsed_command_line);
[email protected]201028d2010-02-12 21:28:011131 if (parsed_command_line.HasSwitch(switches::kMakeDefaultBrowser)) {
1132 return ShellIntegration::SetAsDefaultBrowser() ?
1133 ResultCodes::NORMAL_EXIT : ResultCodes::SHELL_INTEGRATION_FAILED;
initial.commit09911bf2008-07-26 23:55:291134 }
1135
[email protected]6aeac8342010-10-01 20:21:181136 // If the command line specifies --pack-extension, attempt the pack extension
1137 // startup action and exit.
1138 if (parsed_command_line.HasSwitch(switches::kPackExtension)) {
1139 extensions_startup::HandlePackExtension(parsed_command_line);
1140 return ResultCodes::NORMAL_EXIT;
1141 }
1142
[email protected]5425d062010-04-11 23:16:021143#if !defined(OS_MACOSX)
1144 // In environments other than Mac OS X we support import of settings
1145 // from other browsers. In case this process is a short-lived "import"
1146 // process that another browser runs just to import the settings, we
1147 // don't want to be checking for another browser process, by design.
[email protected]a788ae12010-06-21 20:41:061148 if (!(parsed_command_line.HasSwitch(switches::kImport) ||
1149 parsed_command_line.HasSwitch(switches::kImportFromFile))) {
[email protected]bd48c2b02010-04-09 20:32:421150#endif
[email protected]5425d062010-04-11 23:16:021151 // When another process is running, use that process instead of starting a
1152 // new one. NotifyOtherProcess will currently give the other process up to
1153 // 20 seconds to respond. Note that this needs to be done before we attempt
1154 // to read the profile.
[email protected]4a44bc32010-05-28 22:22:441155 switch (process_singleton.NotifyOtherProcessOrCreate()) {
[email protected]5425d062010-04-11 23:16:021156 case ProcessSingleton::PROCESS_NONE:
1157 // No process already running, fall through to starting a new one.
1158 break;
[email protected]bd48c2b02010-04-09 20:32:421159
[email protected]5425d062010-04-11 23:16:021160 case ProcessSingleton::PROCESS_NOTIFIED:
1161#if defined(OS_POSIX) && !defined(OS_MACOSX)
1162 printf("%s\n", base::SysWideToNativeMB(
1163 l10n_util::GetString(IDS_USED_EXISTING_BROWSER)).c_str());
1164#endif
1165 return ResultCodes::NORMAL_EXIT;
[email protected]bd48c2b02010-04-09 20:32:421166
[email protected]5425d062010-04-11 23:16:021167 case ProcessSingleton::PROFILE_IN_USE:
1168 return ResultCodes::PROFILE_IN_USE;
1169
[email protected]4a44bc32010-05-28 22:22:441170 case ProcessSingleton::LOCK_ERROR:
1171 LOG(ERROR) << "Failed to create a ProcessSingleton for your profile "
1172 "directory. This means that running multiple instances "
1173 "would start multiple browser processes rather than "
1174 "opening a new window in the existing process. Aborting "
1175 "now to avoid profile corruption.";
1176 return ResultCodes::PROFILE_IN_USE;
1177
[email protected]5425d062010-04-11 23:16:021178 default:
1179 NOTREACHED();
1180 }
1181#if !defined(OS_MACOSX) // closing brace for if
[email protected]bd48c2b02010-04-09 20:32:421182 }
[email protected]5425d062010-04-11 23:16:021183#endif
[email protected]bd48c2b02010-04-09 20:32:421184
[email protected]20271f32010-03-26 03:04:511185 // Profile creation ----------------------------------------------------------
[email protected]08e6f6d2009-12-14 17:42:121186
[email protected]d7e4b59d62010-04-22 21:36:231187#if defined(OS_CHROMEOS)
[email protected]617fd0d2010-08-04 20:05:171188 // Stub out chromeos implementations.
1189 if (parsed_command_line.HasSwitch(switches::kStubCros))
1190 chromeos::CrosLibrary::Get()->GetTestApi()->SetUseStubImpl();
1191
[email protected]4f519322010-06-02 22:16:391192 // Initialize the screen locker now so that it can receive
1193 // LOGIN_USER_CHANGED notification from UserManager.
1194 chromeos::ScreenLocker::InitClass();
1195
[email protected]1172ba72010-05-21 22:21:111196 // This forces the ProfileManager to be created and register for the
1197 // notification it needs to track the logged in user.
1198 g_browser_process->profile_manager()->GetDefaultProfile();
[email protected]d7e4b59d62010-04-22 21:36:231199
[email protected]e4d285a2010-08-05 21:33:021200 // There are two use cases for kLoginUser:
1201 // 1) if passed in tandem with kLoginPassword, to drive a "StubLogin"
1202 // 2) if passed alone, to signal that the indicated user has already
1203 // logged in and we should behave accordingly.
1204 // This handles case 2.
1205 if (parsed_command_line.HasSwitch(switches::kLoginUser) &&
1206 !parsed_command_line.HasSwitch(switches::kLoginPassword)) {
[email protected]d7e4b59d62010-04-22 21:36:231207 std::string username =
1208 parsed_command_line.GetSwitchValueASCII(switches::kLoginUser);
[email protected]8e96e502010-10-21 20:57:121209 VLOG(1) << "Relaunching browser for user: " << username;
[email protected]d7e4b59d62010-04-22 21:36:231210 chromeos::UserManager::Get()->UserLoggedIn(username);
[email protected]30f547c2010-08-04 01:00:011211
1212 // Redirect logs.
1213 FilePath user_data_dir;
1214 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
1215 ProfileManager* profile_manager = g_browser_process->profile_manager();
1216 // The default profile will have been changed because the ProfileManager
1217 // will process the notification that the UserManager sends out.
1218
1219 logging::RedirectChromeLogging(
1220 user_data_dir.Append(profile_manager->GetCurrentProfileDir()),
1221 *(CommandLine::ForCurrentProcess()),
1222 logging::DELETE_OLD_LOG_FILE);
[email protected]d7e4b59d62010-04-22 21:36:231223 }
1224#endif
1225
[email protected]c6032e82010-09-13 20:06:051226#if defined(USE_X11)
1227 SetBrowserX11ErrorHandlers();
1228#endif
1229
[email protected]1a47d7e2010-10-15 00:37:241230 // Modifies the current command line based on active experiments on
1231 // about:flags.
[email protected]20271f32010-03-26 03:04:511232 Profile* profile = CreateProfile(parameters, user_data_dir);
1233 if (!profile)
[email protected]9acc48602009-11-30 21:18:511234 return ResultCodes::NORMAL_EXIT;
[email protected]20271f32010-03-26 03:04:511235
1236 // Post-profile init ---------------------------------------------------------
[email protected]9acc48602009-11-30 21:18:511237
1238 PrefService* user_prefs = profile->GetPrefs();
1239 DCHECK(user_prefs);
1240
[email protected]26332c62010-03-30 19:11:401241 // Tests should be able to tune login manager before showing it.
1242 // Thus only show login manager in normal (non-testing) mode.
1243 if (!parameters.ui_task) {
1244 OptionallyRunChromeOSLoginManager(parsed_command_line);
1245 }
[email protected]cf80fae2010-02-26 10:35:211246
[email protected]272709ca2010-04-01 00:24:471247#if !defined(OS_MACOSX)
initial.commit09911bf2008-07-26 23:55:291248 // Importing other browser settings is done in a browser-like process
1249 // that exits when this task has finished.
[email protected]3ef4755e2010-09-27 20:25:041250 // TODO(port): Port the Mac's IPC-based implementation to other platforms to
1251 // replace this implementation. http://crbug.com/22142
[email protected]02aae3f2010-03-22 22:31:271252 if (parsed_command_line.HasSwitch(switches::kImport) ||
[email protected]272709ca2010-04-01 00:24:471253 parsed_command_line.HasSwitch(switches::kImportFromFile)) {
[email protected]6cd5bff2008-10-31 23:44:541254 return FirstRun::ImportNow(profile, parsed_command_line);
[email protected]272709ca2010-04-01 00:24:471255 }
[email protected]7da7f3432009-10-28 20:12:081256#endif
initial.commit09911bf2008-07-26 23:55:291257
[email protected]04999e62009-09-25 01:27:311258#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:291259 // Do the tasks if chrome has been upgraded while it was last running.
[email protected]bd48c2b02010-04-09 20:32:421260 if (!already_running && Upgrade::DoUpgradeTasks(parsed_command_line))
initial.commit09911bf2008-07-26 23:55:291261 return ResultCodes::NORMAL_EXIT;
[email protected]04999e62009-09-25 01:27:311262#endif
initial.commit09911bf2008-07-26 23:55:291263
[email protected]68c921f2008-10-15 21:37:461264 // Check if there is any machine level Chrome installed on the current
1265 // machine. If yes and the current Chrome process is user level, we do not
1266 // allow the user level Chrome to run. So we notify the user and uninstall
1267 // user level Chrome.
1268 // Note this check should only happen here, after all the checks above
1269 // (uninstall, resource bundle initialization, other chrome browser
1270 // processes etc).
1271 if (CheckMachineLevelInstall())
1272 return ResultCodes::MACHINE_LEVEL_INSTALL_EXISTS;
1273
[email protected]7e0831b2010-02-01 08:45:151274 // Create the TranslateManager singleton.
[email protected]509acb8e2010-07-01 20:35:311275 Singleton<TranslateManager>::get();
[email protected]7e0831b2010-02-01 08:45:151276
[email protected]0a357e632010-04-02 21:26:581277#if defined(OS_MACOSX)
1278 if (!parsed_command_line.HasSwitch(switches::kNoFirstRun)) {
1279 // Disk image installation is sort of a first-run task, so it shares the
1280 // kNoFirstRun switch.
1281 if (MaybeInstallFromDiskImage()) {
1282 // The application was installed and the installed copy has been
1283 // launched. This process is now obsolete. Exit.
1284 return ResultCodes::NORMAL_EXIT;
1285 }
1286 }
1287#endif
1288
initial.commit09911bf2008-07-26 23:55:291289 // Show the First Run UI if this is the first time Chrome has been run on
1290 // this computer, or we're being compelled to do so by a command line flag.
1291 // Note that this be done _after_ the PrefService is initialized and all
1292 // preferences are registered, since some of the code that the importer
1293 // touches reads preferences.
[email protected]79117172009-08-28 16:11:441294 if (is_first_run) {
1295 if (!first_run_ui_bypass) {
[email protected]2f24d292010-07-16 16:16:521296 FirstRun::AutoImport(profile,
1297 master_prefs.homepage_defined,
1298 master_prefs.do_import_items,
1299 master_prefs.dont_import_items,
1300 master_prefs.run_search_engine_experiment,
1301 master_prefs.randomize_search_engine_experiment,
[email protected]79e165f2010-09-01 15:57:501302 master_prefs.make_chrome_default,
[email protected]2f24d292010-07-16 16:16:521303 &process_singleton);
[email protected]5ee921c2009-07-28 19:21:251304#if defined(OS_POSIX)
[email protected]79117172009-08-28 16:11:441305 // On Windows, the download is tagged with enable/disable stats so there
1306 // is no need for this code.
[email protected]5ee921c2009-07-28 19:21:251307
[email protected]79117172009-08-28 16:11:441308 // If stats reporting was turned on by the first run dialog then toggle
1309 // the pref.
1310 if (GoogleUpdateSettings::GetCollectStatsConsent())
1311 local_state->SetBoolean(prefs::kMetricsReportingEnabled, true);
[email protected]5ee921c2009-07-28 19:21:251312#endif // OS_POSIX
[email protected]2f24d292010-07-16 16:16:521313 } // if (!first_run_ui_bypass)
[email protected]a53915592010-02-26 20:21:401314
[email protected]79117172009-08-28 16:11:441315 Browser::SetNewHomePagePrefs(user_prefs);
initial.commit09911bf2008-07-26 23:55:291316 }
1317
1318 // Sets things up so that if we crash from this point on, a dialog will
1319 // popup asking the user to restart chrome. It is done this late to avoid
1320 // testing against a bunch of special cases that are taken care early on.
1321 PrepareRestartOnCrashEnviroment(parsed_command_line);
1322
[email protected]74be069e82010-06-25 00:12:491323 // Initialize and maintain network predictor module, which handles DNS
1324 // pre-resolution, as well as TCP/IP connection pre-warming.
1325 // This also registers an observer to discard data when closing incognito
1326 // mode.
[email protected]d4612642010-08-11 22:46:571327 bool preconnect_enabled = true; // Default status (easy to change!).
1328 if (parsed_command_line.HasSwitch(switches::kDisablePreconnect))
1329 preconnect_enabled = false;
1330 else if (parsed_command_line.HasSwitch(switches::kEnablePreconnect))
1331 preconnect_enabled = true;
[email protected]74be069e82010-06-25 00:12:491332 chrome_browser_net::PredictorInit dns_prefetch(
[email protected]760d970a2010-05-18 00:39:181333 user_prefs,
1334 local_state,
[email protected]e326922d2010-09-03 09:08:101335 preconnect_enabled);
[email protected]0d8fa3ec2009-04-08 04:22:441336
[email protected]1933eb202009-02-19 18:23:251337#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:291338 win_util::ScopedCOMInitializer com_initializer;
1339
[email protected]58b64332010-08-13 16:09:391340#if defined(GOOGLE_CHROME_BUILD)
initial.commit09911bf2008-07-26 23:55:291341 // Init the RLZ library. This just binds the dll and schedules a task on the
1342 // file thread to be run sometime later. If this is the first run we record
1343 // the installation event.
[email protected]1c262172010-06-10 15:25:461344 RLZTracker::InitRlzDelayed(is_first_run, master_prefs.ping_delay);
[email protected]698cccb12009-03-11 18:47:241345#endif
[email protected]58b64332010-08-13 16:09:391346#endif
initial.commit09911bf2008-07-26 23:55:291347
[email protected]64d50ed2009-09-22 21:05:471348 // Configure the network module so it has access to resources.
1349 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
initial.commit09911bf2008-07-26 23:55:291350
[email protected]60e448982009-05-06 04:21:161351 // Register our global network handler for chrome:// and
[email protected]9527f9c2009-01-29 18:35:421352 // chrome-extension:// URLs.
initial.commit09911bf2008-07-26 23:55:291353 RegisterURLRequestChromeJob();
[email protected]8f704c82009-01-08 21:47:411354 RegisterExtensionProtocols();
[email protected]540c14972009-07-13 16:03:491355 RegisterMetadataURLRequestHandler();
[email protected]81070042010-08-31 02:42:361356 RegisterBlobURLRequestJobFactory();
[email protected]ac262c9f2008-10-19 17:45:211357
[email protected]3dd1f6d52008-09-15 18:28:091358 // In unittest mode, this will do nothing. In normal mode, this will create
[email protected]8b62334b2010-08-31 22:37:111359 // the global GoogleURLTracker and IntranetRedirectDetector instances, which
[email protected]c4ff4952010-01-08 19:12:471360 // will promptly go to sleep for five and seven seconds, respectively (to
1361 // avoid slowing startup), and wake up afterwards to see if they should do
1362 // anything else.
[email protected]3dd1f6d52008-09-15 18:28:091363 //
1364 // A simpler way of doing all this would be to have some function which could
[email protected]c4ff4952010-01-08 19:12:471365 // give the time elapsed since startup, and simply have these objects check
1366 // that when asked to initialize themselves, but this doesn't seem to exist.
[email protected]3dd1f6d52008-09-15 18:28:091367 //
[email protected]c4ff4952010-01-08 19:12:471368 // These can't be created in the BrowserProcessImpl constructor because they
1369 // need to read prefs that get set after that runs.
[email protected]3dd1f6d52008-09-15 18:28:091370 browser_process->google_url_tracker();
[email protected]c4ff4952010-01-08 19:12:471371 browser_process->intranet_redirect_detector();
initial.commit09911bf2008-07-26 23:55:291372
[email protected]cec1b8d2010-03-24 00:21:341373 // Do initialize the plug-in service (and related preferences).
1374 PluginService::InitGlobalInstance(profile);
initial.commit09911bf2008-07-26 23:55:291375
[email protected]60889422008-09-23 01:18:161376 // Prepare for memory caching of SDCH dictionaries.
[email protected]e695fbd62009-06-30 16:31:541377 // Perform A/B test to measure global impact of SDCH support.
1378 // Set up a field trial to see what disabling SDCH does to latency of page
1379 // layout globally.
[email protected]835d7c82010-10-14 04:38:381380 base::FieldTrial::Probability kSDCH_DIVISOR = 1000;
1381 base::FieldTrial::Probability kSDCH_DISABLE_PROBABILITY = 1; // 0.1% prob.
1382 scoped_refptr<base::FieldTrial> sdch_trial =
1383 new base::FieldTrial("GlobalSdch", kSDCH_DIVISOR);
[email protected]e695fbd62009-06-30 16:31:541384
[email protected]5156c3cf2009-07-09 17:23:111385 // Use default of "" so that all domains are supported.
1386 std::string sdch_supported_domain("");
[email protected]60889422008-09-23 01:18:161387 if (parsed_command_line.HasSwitch(switches::kSdchFilter)) {
[email protected]5156c3cf2009-07-09 17:23:111388 sdch_supported_domain =
[email protected]5d39e3142009-12-17 05:54:101389 parsed_command_line.GetSwitchValueASCII(switches::kSdchFilter);
[email protected]e695fbd62009-06-30 16:31:541390 } else {
[email protected]58d2d2d2010-08-05 22:46:331391 sdch_trial->AppendGroup("global_disable_sdch",
[email protected]e12d50592010-01-06 17:35:191392 kSDCH_DISABLE_PROBABILITY);
[email protected]58d2d2d2010-08-05 22:46:331393 int sdch_enabled = sdch_trial->AppendGroup("global_enable_sdch",
[email protected]835d7c82010-10-14 04:38:381394 base::FieldTrial::kAllRemainingProbability);
[email protected]5156c3cf2009-07-09 17:23:111395 if (sdch_enabled != sdch_trial->group())
1396 sdch_supported_domain = "never_enabled_sdch_for_any_domain";
[email protected]60889422008-09-23 01:18:161397 }
[email protected]e695fbd62009-06-30 16:31:541398
[email protected]5156c3cf2009-07-09 17:23:111399 SdchManager sdch_manager; // Singleton database.
1400 sdch_manager.set_sdch_fetcher(new SdchDictionaryFetcher);
1401 sdch_manager.EnableSdchSupport(sdch_supported_domain);
[email protected]60889422008-09-23 01:18:161402
[email protected]838e1a92010-03-25 17:47:451403 MetricsService* metrics = InitializeMetrics(parsed_command_line, local_state);
initial.commit09911bf2008-07-26 23:55:291404 InstallJankometer(parsed_command_line);
1405
[email protected]e1504d82009-07-03 15:27:151406#if defined(OS_WIN) && !defined(GOOGLE_CHROME_BUILD)
initial.commit09911bf2008-07-26 23:55:291407 if (parsed_command_line.HasSwitch(switches::kDebugPrint)) {
[email protected]884fbb72010-08-04 01:47:551408 FilePath path =
1409 parsed_command_line.GetSwitchValuePath(switches::kDebugPrint);
[email protected]d9d42992010-09-13 19:39:191410 printing::PrintedDocument::set_debug_dump_path(path);
initial.commit09911bf2008-07-26 23:55:291411 }
[email protected]1bcdb532009-01-16 17:47:571412#endif
initial.commit09911bf2008-07-26 23:55:291413
[email protected]9bade092009-11-13 17:04:421414 HandleTestParameters(parsed_command_line);
[email protected]34f73fb2010-03-24 20:50:341415 RecordBreakpadStatusUMA(metrics);
[email protected]3cf4f0992009-02-03 23:00:301416
[email protected]6641bf662009-08-21 00:34:091417 // Stat the directory with the inspector's files so that we can know if we
1418 // should display the entry in the context menu or not.
1419 browser_process->CheckForInspectorFiles();
1420
[email protected]5ccaa412009-11-13 22:00:161421#if defined(OS_CHROMEOS)
[email protected]29cf16772010-04-21 15:13:471422 metrics->StartExternalMetrics();
[email protected]5ccaa412009-11-13 22:00:161423#endif
1424
[email protected]b3d62312b12010-10-14 21:10:181425 // Initialize extension event routers. Note that on Chrome OS, this will
1426 // not succeed if the user has not logged in yet, in which case the
1427 // event routers are initialized in LoginUtilsImpl::CompleteLogin instead.
[email protected]1172ba72010-05-21 22:21:111428 if (profile->GetExtensionsService()) {
1429 // This will initialize bookmarks. Call it after bookmark import is done.
1430 // See issue 40144.
1431 profile->GetExtensionsService()->InitEventRouters();
1432 }
[email protected]c5ae74ab2010-04-15 18:14:371433
[email protected]6aeac8342010-10-01 20:21:181434 // The extension service may be available at this point. If the command line
1435 // specifies --uninstall-extension, attempt the uninstall extension startup
1436 // action.
1437 if (parsed_command_line.HasSwitch(switches::kUninstallExtension)) {
1438 if (extensions_startup::HandleUninstallExtension(parsed_command_line,
1439 profile)) {
1440 return ResultCodes::NORMAL_EXIT;
1441 } else {
1442 return ResultCodes::UNINSTALL_EXTENSION_ERROR;
1443 }
1444 }
1445
[email protected]15406b6a2010-04-21 00:35:011446#if defined(OS_WIN)
[email protected]8a9c63e2010-04-19 21:27:551447 // We check this here because if the profile is OTR (chromeos possibility)
1448 // it won't still be accessible after browser is destroyed.
1449 bool record_search_engine = is_first_run && !profile->IsOffTheRecord();
[email protected]15406b6a2010-04-21 00:35:011450#endif
[email protected]8a9c63e2010-04-19 21:27:551451
[email protected]332e1212010-06-23 22:49:491452 // ChildProcess:: is a misnomer unless you consider context. Use
1453 // of --wait-for-debugger only makes sense when Chrome itself is a
1454 // child process (e.g. when launched by PyAuto).
1455 if (parsed_command_line.HasSwitch(switches::kWaitForDebugger)) {
1456 ChildProcess::WaitForDebugger(L"Browser");
1457 }
1458
[email protected]e96bf0c52010-08-23 23:20:571459 // If remoting or cloud print proxy is enabled and setup has been completed
1460 // we start the service process here.
1461 // The prerequisite for running the service process is that we have IO, UI
1462 // and PROCESS_LAUNCHER threads up and running.
1463 // TODO(hclam): Need to check for cloud print proxy too.
1464 if (parsed_command_line.HasSwitch(switches::kEnableRemoting)) {
1465 if (user_prefs->GetBoolean(prefs::kRemotingHasSetupCompleted)) {
1466 ServiceProcessControl* control = ServiceProcessControlManager::instance()
[email protected]de2658d52010-10-05 19:48:581467 ->GetProcessControl(profile);
[email protected]ed453c0a2010-10-18 21:47:171468 control->Launch(NULL, NULL);
[email protected]e96bf0c52010-08-23 23:20:571469 }
1470 }
1471
[email protected]17543d62010-10-07 22:37:381472 // Create the instance of the cloud print proxy service so that it can launch
1473 // the service process if needed. This is needed because the service process
1474 // might have shutdown because an update was available.
1475 profile->GetCloudPrintProxyService();
1476
initial.commit09911bf2008-07-26 23:55:291477 int result_code = ResultCodes::NORMAL_EXIT;
[email protected]d4515eb2009-01-30 00:40:431478 if (parameters.ui_task) {
[email protected]4a8bca52009-05-07 23:37:591479 // We are in test mode. Run one task and enter the main message loop.
1480 if (pool)
1481 pool->Recycle();
[email protected]64f19312010-04-13 22:30:011482 parameters.ui_task->Run();
1483 delete parameters.ui_task;
[email protected]4a8bca52009-05-07 23:37:591484 } else {
[email protected]30f894b2009-12-22 05:06:201485 // We are in regular browser boot sequence. Open initial stabs and enter
1486 // the main message loop.
[email protected]f805fe82010-08-03 22:47:101487 if (browser_init.Start(parsed_command_line, FilePath(), profile,
[email protected]4a8bca52009-05-07 23:37:591488 &result_code)) {
[email protected]3cdacd42010-04-30 18:55:531489#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
[email protected]bd48c2b02010-04-09 20:32:421490 // Initialize autoupdate timer. Timer callback costs basically nothing
1491 // when browser is not in persistent mode, so it's OK to let it ride on
1492 // the main thread. This needs to be done here because we don't want
1493 // to start the timer when Chrome is run inside a test harness.
1494 g_browser_process->StartAutoupdateTimer();
1495#endif
1496
[email protected]3cdacd42010-04-30 18:55:531497#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1498 // On Linux, the running exe will be updated if an upgrade becomes
1499 // available while the browser is running. We need to save the last
1500 // modified time of the exe, so we can compare to determine if there is
1501 // an upgrade while the browser is kept alive by a persistent extension.
1502 Upgrade::SaveLastModifiedTimeOfExe();
1503#endif
1504
[email protected]bf7eb2f92010-06-28 22:55:551505 // Record now as the last successful chrome start.
[email protected]fc097922010-01-28 00:41:041506 GoogleUpdateSettings::SetLastRunTime();
[email protected]4a8bca52009-05-07 23:37:591507 // Call Recycle() here as late as possible, before going into the loop
1508 // because Start() will add things to it while creating the main window.
1509 if (pool)
1510 pool->Recycle();
1511 RunUIMessageLoop(browser_process.get());
1512 }
initial.commit09911bf2008-07-26 23:55:291513 }
[email protected]96b3c5c2010-04-16 20:30:141514
[email protected]15406b6a2010-04-21 00:35:011515#if defined(OS_WIN)
[email protected]96b3c5c2010-04-16 20:30:141516 // If it's the first run, log the search engine chosen. We wait until
1517 // shutdown because otherwise we can't be sure the user has finished
1518 // selecting a search engine through the dialog reached from the first run
1519 // bubble link.
[email protected]15406b6a2010-04-21 00:35:011520 if (FirstRun::InSearchExperimentLocale() && record_search_engine) {
[email protected]96b3c5c2010-04-16 20:30:141521 const TemplateURL* default_search_engine =
1522 profile->GetTemplateURLModel()->GetDefaultSearchProvider();
[email protected]32cba2b2010-10-19 06:19:481523 // The default engine can be NULL if the administrator has disabled
1524 // default search.
[email protected]23872902010-10-26 03:43:591525 SearchEngineType search_engine_type =
[email protected]32cba2b2010-10-19 06:19:481526 default_search_engine ? default_search_engine->search_engine_type() :
[email protected]23872902010-10-26 03:43:591527 SEARCH_ENGINE_OTHER;
[email protected]bf7eb2f92010-06-28 22:55:551528 // Record the search engine chosen.
[email protected]96b3c5c2010-04-16 20:30:141529 if (master_prefs.run_search_engine_experiment) {
1530 UMA_HISTOGRAM_ENUMERATION(
1531 "Chrome.SearchSelectExperiment",
[email protected]32cba2b2010-10-19 06:19:481532 search_engine_type,
[email protected]23872902010-10-26 03:43:591533 SEARCH_ENGINE_MAX);
[email protected]bf7eb2f92010-06-28 22:55:551534 // If the selection has been randomized, also record the winner by slot.
1535 if (master_prefs.randomize_search_engine_experiment) {
1536 size_t engine_pos = profile->GetTemplateURLModel()->
1537 GetSearchEngineDialogSlot();
1538 if (engine_pos < 4) {
1539 std::string experiment_type = "Chrome.SearchSelectExperimentSlot";
1540 // Nicer in UMA if slots are 1-based.
1541 experiment_type.push_back('1' + engine_pos);
1542 UMA_HISTOGRAM_ENUMERATION(
1543 experiment_type,
[email protected]32cba2b2010-10-19 06:19:481544 search_engine_type,
[email protected]23872902010-10-26 03:43:591545 SEARCH_ENGINE_MAX);
[email protected]bf7eb2f92010-06-28 22:55:551546 } else {
1547 NOTREACHED() << "Invalid search engine selection slot.";
1548 }
1549 }
[email protected]96b3c5c2010-04-16 20:30:141550 } else {
1551 UMA_HISTOGRAM_ENUMERATION(
1552 "Chrome.SearchSelectExempt",
[email protected]32cba2b2010-10-19 06:19:481553 search_engine_type,
[email protected]23872902010-10-26 03:43:591554 SEARCH_ENGINE_MAX);
[email protected]96b3c5c2010-04-16 20:30:141555 }
1556 }
[email protected]15406b6a2010-04-21 00:35:011557#endif
[email protected]96b3c5c2010-04-16 20:30:141558
[email protected]7c7377a2009-11-11 06:59:381559 chrome_browser_net_websocket_experiment::WebSocketExperimentRunner::Stop();
initial.commit09911bf2008-07-26 23:55:291560
[email protected]9f20a6d02009-08-21 01:18:371561 process_singleton.Cleanup();
1562
[email protected]60626da2010-03-25 17:06:531563 metrics->Stop();
initial.commit09911bf2008-07-26 23:55:291564
1565 // browser_shutdown takes care of deleting browser_process, so we need to
1566 // release it.
[email protected]d22d8732010-05-04 19:24:421567 ignore_result(browser_process.release());
initial.commit09911bf2008-07-26 23:55:291568 browser_shutdown::Shutdown();
1569
[email protected]a872ea1f2010-08-11 04:45:331570 TRACE_EVENT_END("BrowserMain", 0, 0);
initial.commit09911bf2008-07-26 23:55:291571 return result_code;
1572}