Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: chrome/browser/chrome_browser_main.cc

Issue 8477004: Have content/ create and destroy its own threads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix official build, avoid DCHECK in official Linux/ChromeOS builds. Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/chrome_browser_main.h ('k') | chrome/browser/chromeos/input_method/xkeyboard.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chrome_browser_main.h" 5 #include "chrome/browser/chrome_browser_main.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 #include "chrome/browser/profiles/profile.h" 69 #include "chrome/browser/profiles/profile.h"
70 #include "chrome/browser/profiles/profile_manager.h" 70 #include "chrome/browser/profiles/profile_manager.h"
71 #include "chrome/browser/search_engines/search_engine_type.h" 71 #include "chrome/browser/search_engines/search_engine_type.h"
72 #include "chrome/browser/search_engines/template_url.h" 72 #include "chrome/browser/search_engines/template_url.h"
73 #include "chrome/browser/search_engines/template_url_service.h" 73 #include "chrome/browser/search_engines/template_url_service.h"
74 #include "chrome/browser/search_engines/template_url_service_factory.h" 74 #include "chrome/browser/search_engines/template_url_service_factory.h"
75 #include "chrome/browser/service/service_process_control.h" 75 #include "chrome/browser/service/service_process_control.h"
76 #include "chrome/browser/shell_integration.h" 76 #include "chrome/browser/shell_integration.h"
77 #include "chrome/browser/translate/translate_manager.h" 77 #include "chrome/browser/translate/translate_manager.h"
78 #include "chrome/browser/ui/browser.h" 78 #include "chrome/browser/ui/browser.h"
79 #include "chrome/browser/ui/browser_init.h"
80 #include "chrome/browser/ui/webui/chrome_url_data_manager_backend.h" 79 #include "chrome/browser/ui/webui/chrome_url_data_manager_backend.h"
81 #include "chrome/browser/web_resource/gpu_blacklist_updater.h" 80 #include "chrome/browser/web_resource/gpu_blacklist_updater.h"
82 #include "chrome/common/child_process_logging.h" 81 #include "chrome/common/child_process_logging.h"
83 #include "chrome/common/chrome_constants.h" 82 #include "chrome/common/chrome_constants.h"
84 #include "chrome/common/chrome_paths.h" 83 #include "chrome/common/chrome_paths.h"
85 #include "chrome/common/chrome_result_codes.h" 84 #include "chrome/common/chrome_result_codes.h"
86 #include "chrome/common/chrome_switches.h" 85 #include "chrome/common/chrome_switches.h"
87 #include "chrome/common/chrome_version_info.h" 86 #include "chrome/common/chrome_version_info.h"
88 #include "chrome/common/env_vars.h" 87 #include "chrome/common/env_vars.h"
89 #include "chrome/common/json_pref_store.h" 88 #include "chrome/common/json_pref_store.h"
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 net::URLRequestThrottlerManager::GetInstance()->set_enable_thread_checks( 303 net::URLRequestThrottlerManager::GetInstance()->set_enable_thread_checks(
305 true); 304 true);
306 305
307 // TODO(joi): Passing the NetLog here is temporary; once I switch the 306 // TODO(joi): Passing the NetLog here is temporary; once I switch the
308 // URLRequestThrottlerManager to be part of the URLRequestContext it will 307 // URLRequestThrottlerManager to be part of the URLRequestContext it will
309 // come from there. Doing it this way for now (2011/5/12) to try to fail 308 // come from there. Doing it this way for now (2011/5/12) to try to fail
310 // fast in case A/B experiment gives unexpected results. 309 // fast in case A/B experiment gives unexpected results.
311 net::URLRequestThrottlerManager::GetInstance()->set_net_log(net_log); 310 net::URLRequestThrottlerManager::GetInstance()->set_net_log(net_log);
312 } 311 }
313 312
314 // Creates key child threads. We need to do this explicitly since
315 // BrowserThread::PostTask silently deletes a posted task if the target message
316 // loop isn't created.
317 void CreateChildThreads(BrowserProcessImpl* process) {
318 process->db_thread();
319 process->file_thread();
320 process->process_launcher_thread();
321 process->cache_thread();
322 process->io_thread();
323 #if defined(OS_CHROMEOS)
324 process->web_socket_proxy_thread();
325 #endif
326 // Create watchdog thread after creating all other threads because it will
327 // watch the other threads and they must be running.
328 process->watchdog_thread();
329 }
330
331 // Returns the new local state object, guaranteed non-NULL. 313 // Returns the new local state object, guaranteed non-NULL.
332 PrefService* InitializeLocalState(const CommandLine& parsed_command_line, 314 PrefService* InitializeLocalState(const CommandLine& parsed_command_line,
333 bool is_first_run) { 315 bool is_first_run) {
334 FilePath local_state_path; 316 FilePath local_state_path;
335 PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path); 317 PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
336 bool local_state_file_exists = file_util::PathExists(local_state_path); 318 bool local_state_file_exists = file_util::PathExists(local_state_path);
337 319
338 // Load local state. This includes the application locale so we know which 320 // Load local state. This includes the application locale so we know which
339 // locale dll to load. 321 // locale dll to load.
340 PrefService* local_state = g_browser_process->local_state(); 322 PrefService* local_state = g_browser_process->local_state();
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 ChromeBrowserMainParts::ChromeBrowserMainParts( 662 ChromeBrowserMainParts::ChromeBrowserMainParts(
681 const content::MainFunctionParams& parameters) 663 const content::MainFunctionParams& parameters)
682 : parameters_(parameters), 664 : parameters_(parameters),
683 parsed_command_line_(parameters.command_line), 665 parsed_command_line_(parameters.command_line),
684 result_code_(content::RESULT_CODE_NORMAL_EXIT), 666 result_code_(content::RESULT_CODE_NORMAL_EXIT),
685 shutdown_watcher_(new ShutdownWatcherHelper()), 667 shutdown_watcher_(new ShutdownWatcherHelper()),
686 record_search_engine_(false), 668 record_search_engine_(false),
687 translate_manager_(NULL), 669 translate_manager_(NULL),
688 profile_(NULL), 670 profile_(NULL),
689 run_message_loop_(true), 671 run_message_loop_(true),
690 notify_result_(ProcessSingleton::PROCESS_NONE) { 672 notify_result_(ProcessSingleton::PROCESS_NONE),
673 is_first_run_(false),
674 first_run_ui_bypass_(false),
675 metrics_(NULL),
676 local_state_(NULL),
677 restart_last_session_(false) {
691 // If we're running tests (ui_task is non-null). 678 // If we're running tests (ui_task is non-null).
692 if (parameters.ui_task) 679 if (parameters.ui_task)
693 browser_defaults::enable_help_app = false; 680 browser_defaults::enable_help_app = false;
694 } 681 }
695 682
696 ChromeBrowserMainParts::~ChromeBrowserMainParts() { 683 ChromeBrowserMainParts::~ChromeBrowserMainParts() {
697 for (int i = static_cast<int>(chrome_extra_parts_.size())-1; i >= 0; --i) 684 for (int i = static_cast<int>(chrome_extra_parts_.size())-1; i >= 0; --i)
698 delete chrome_extra_parts_[i]; 685 delete chrome_extra_parts_[i];
699 chrome_extra_parts_.clear(); 686 chrome_extra_parts_.clear();
700 } 687 }
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
1200 void ChromeBrowserMainParts::PreMainMessageLoopStart() { 1187 void ChromeBrowserMainParts::PreMainMessageLoopStart() {
1201 for (size_t i = 0; i < chrome_extra_parts_.size(); ++i) 1188 for (size_t i = 0; i < chrome_extra_parts_.size(); ++i)
1202 chrome_extra_parts_[i]->PreMainMessageLoopStart(); 1189 chrome_extra_parts_[i]->PreMainMessageLoopStart();
1203 } 1190 }
1204 1191
1205 void ChromeBrowserMainParts::PostMainMessageLoopStart() { 1192 void ChromeBrowserMainParts::PostMainMessageLoopStart() {
1206 for (size_t i = 0; i < chrome_extra_parts_.size(); ++i) 1193 for (size_t i = 0; i < chrome_extra_parts_.size(); ++i)
1207 chrome_extra_parts_[i]->PostMainMessageLoopStart(); 1194 chrome_extra_parts_[i]->PostMainMessageLoopStart();
1208 } 1195 }
1209 1196
1210 void ChromeBrowserMainParts::PreMainMessageLoopRun() { 1197 void ChromeBrowserMainParts::PreCreateThreads() {
1211 result_code_ = PreMainMessageLoopRunImpl(); 1198 result_code_ = PreCreateThreadsImpl();
1212 1199
1213 for (size_t i = 0; i < chrome_extra_parts_.size(); ++i) 1200 for (size_t i = 0; i < chrome_extra_parts_.size(); ++i)
1214 chrome_extra_parts_[i]->PreMainMessageLoopRun(); 1201 chrome_extra_parts_[i]->PreMainMessageLoopRun();
1215 } 1202 }
1216 1203
1217 int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { 1204 void ChromeBrowserMainParts::PreStartThread(
1205 content::BrowserThread::ID thread_id) {
1206 browser_process_->PreStartThread(thread_id);
1207 }
1208
1209 void ChromeBrowserMainParts::PostStartThread(
1210 content::BrowserThread::ID thread_id) {
1211 browser_process_->PostStartThread(thread_id);
1212 switch (thread_id) {
1213 case BrowserThread::FILE:
1214 // Now the command line has been mutated based on about:flags,
1215 // and the file thread has been started, we can set up metrics
1216 // and initialize field trials.
1217 metrics_ = SetupMetricsAndFieldTrials(local_state_);
1218
1219 #if defined(USE_LINUX_BREAKPAD)
1220 // Needs to be called after we have chrome::DIR_USER_DATA and
1221 // g_browser_process. This happens in PreCreateThreads.
1222 g_browser_process->file_thread()->message_loop()->PostTask(
1223 FROM_HERE, new GetLinuxDistroTask());
1224
1225 if (IsCrashReportingEnabled(local_state_))
1226 InitCrashReporter();
1227 #endif
1228 break;
1229
1230 default:
1231 break;
1232 }
1233 }
1234
1235 void ChromeBrowserMainParts::PreMainMessageLoopRun() {
1236 result_code_ = PreMainMessageLoopRunImpl();
1237 }
1238
1239 int ChromeBrowserMainParts::PreCreateThreadsImpl() {
1218 run_message_loop_ = false; 1240 run_message_loop_ = false;
1219 FilePath user_data_dir;
1220 #if defined(OS_WIN) 1241 #if defined(OS_WIN)
1221 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); 1242 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_);
1222 #else 1243 #else
1223 // Getting the user data dir can fail if the directory isn't 1244 // Getting the user data dir can fail if the directory isn't
1224 // creatable, for example; on Windows in code below we bring up a 1245 // creatable, for example; on Windows in code below we bring up a
1225 // dialog prompting the user to pick a different directory. 1246 // dialog prompting the user to pick a different directory.
1226 // However, ProcessSingleton needs a real user_data_dir on Mac/Linux, 1247 // However, ProcessSingleton needs a real user_data_dir on Mac/Linux,
1227 // so it's better to fail here than fail mysteriously elsewhere. 1248 // so it's better to fail here than fail mysteriously elsewhere.
1228 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) 1249 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_))
1229 << "Must be able to get user data directory!"; 1250 << "Must be able to get user data directory!";
1230 #endif 1251 #endif
1231 1252
1232 process_singleton_.reset(new ProcessSingleton(user_data_dir)); 1253 process_singleton_.reset(new ProcessSingleton(user_data_dir_));
1233 1254
1234 bool is_first_run = FirstRun::IsChromeFirstRun() || 1255 is_first_run_ = FirstRun::IsChromeFirstRun() ||
1235 parsed_command_line().HasSwitch(switches::kFirstRun); 1256 parsed_command_line().HasSwitch(switches::kFirstRun);
1236 1257
1237 if (parsed_command_line().HasSwitch(switches::kImport) || 1258 if (parsed_command_line().HasSwitch(switches::kImport) ||
1238 parsed_command_line().HasSwitch(switches::kImportFromFile)) { 1259 parsed_command_line().HasSwitch(switches::kImportFromFile)) {
1239 // We use different BrowserProcess when importing so no GoogleURLTracker is 1260 // We use different BrowserProcess when importing so no GoogleURLTracker is
1240 // instantiated (as it makes a net::URLRequest and we don't have an IO 1261 // instantiated (as it makes a net::URLRequest and we don't have an IO
1241 // thread, see bug #1292702). 1262 // thread, see bug #1292702).
1242 browser_process_.reset(new FirstRunBrowserProcess(parsed_command_line())); 1263 browser_process_.reset(new FirstRunBrowserProcess(parsed_command_line()));
1243 is_first_run = false; 1264 is_first_run_ = false;
1244 } else { 1265 } else {
1245 browser_process_.reset(new BrowserProcessImpl(parsed_command_line())); 1266 browser_process_.reset(new BrowserProcessImpl(parsed_command_line()));
1246 } 1267 }
1247 1268
1248 if (parsed_command_line().HasSwitch(switches::kEnableProfiling)) { 1269 if (parsed_command_line().HasSwitch(switches::kEnableProfiling)) {
1249 // User wants to override default tracking status. 1270 // User wants to override default tracking status.
1250 std::string flag = 1271 std::string flag =
1251 parsed_command_line().GetSwitchValueASCII(switches::kEnableProfiling); 1272 parsed_command_line().GetSwitchValueASCII(switches::kEnableProfiling);
1252 bool enabled = flag.compare("0") != 0; 1273 bool enabled = flag.compare("0") != 0;
1253 tracked_objects::ThreadData::InitializeAndSetTrackingStatus(enabled); 1274 tracked_objects::ThreadData::InitializeAndSetTrackingStatus(enabled);
1254 } 1275 }
1255 1276
1256 // This forces the TabCloseableStateWatcher to be created and, on chromeos, 1277 // This forces the TabCloseableStateWatcher to be created and, on chromeos,
1257 // register for the notifications it needs to track the closeable state of 1278 // register for the notifications it needs to track the closeable state of
1258 // tabs. 1279 // tabs.
1259 g_browser_process->tab_closeable_state_watcher(); 1280 g_browser_process->tab_closeable_state_watcher();
1260 1281
1261 PrefService* local_state = InitializeLocalState(parsed_command_line(), 1282 local_state_ = InitializeLocalState(parsed_command_line(),
1262 is_first_run); 1283 is_first_run_);
1263
1264 #if defined(USE_LINUX_BREAKPAD)
1265 // Needs to be called after we have chrome::DIR_USER_DATA and
1266 // g_browser_process.
1267 g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
1268 new GetLinuxDistroTask());
1269
1270 if (IsCrashReportingEnabled(local_state))
1271 InitCrashReporter();
1272 #endif
1273 1284
1274 // If we're running tests (ui_task is non-null), then the ResourceBundle 1285 // If we're running tests (ui_task is non-null), then the ResourceBundle
1275 // has already been initialized. 1286 // has already been initialized.
1276 if (parameters().ui_task) { 1287 if (parameters().ui_task) {
1277 g_browser_process->SetApplicationLocale("en-US"); 1288 g_browser_process->SetApplicationLocale("en-US");
1278 } else { 1289 } else {
1279 // Mac starts it earlier in |PreMainMessageLoopStart()| (because it is 1290 // Mac starts it earlier in |PreMainMessageLoopStart()| (because it is
1280 // needed when loading the MainMenu.nib and the language doesn't depend on 1291 // needed when loading the MainMenu.nib and the language doesn't depend on
1281 // anything since it comes from Cocoa. 1292 // anything since it comes from Cocoa.
1282 #if defined(OS_MACOSX) 1293 #if defined(OS_MACOSX)
1283 g_browser_process->SetApplicationLocale(l10n_util::GetLocaleOverride()); 1294 g_browser_process->SetApplicationLocale(l10n_util::GetLocaleOverride());
1284 #else 1295 #else
1285 const std::string locale = 1296 const std::string locale =
1286 local_state->GetString(prefs::kApplicationLocale); 1297 local_state_->GetString(prefs::kApplicationLocale);
1287 // On a POSIX OS other than ChromeOS, the parameter that is passed to the 1298 // On a POSIX OS other than ChromeOS, the parameter that is passed to the
1288 // method InitSharedInstance is ignored. 1299 // method InitSharedInstance is ignored.
1289 const std::string loaded_locale = 1300 const std::string loaded_locale =
1290 ResourceBundle::InitSharedInstance(locale); 1301 ResourceBundle::InitSharedInstance(locale);
1291 if (loaded_locale.empty() && 1302 if (loaded_locale.empty() &&
1292 !parsed_command_line().HasSwitch(switches::kNoErrorDialogs)) { 1303 !parsed_command_line().HasSwitch(switches::kNoErrorDialogs)) {
1293 ShowMissingLocaleMessageBox(); 1304 ShowMissingLocaleMessageBox();
1294 return chrome::RESULT_CODE_MISSING_DATA; 1305 return chrome::RESULT_CODE_MISSING_DATA;
1295 } 1306 }
1296 CHECK(!loaded_locale.empty()) << "Locale could not be found for " << locale; 1307 CHECK(!loaded_locale.empty()) << "Locale could not be found for " << locale;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1336 // This needs to be called after the locale has been set. 1347 // This needs to be called after the locale has been set.
1337 RegisterTranslateableItems(); 1348 RegisterTranslateableItems();
1338 #endif 1349 #endif
1339 1350
1340 browser_init_.reset(new BrowserInit); 1351 browser_init_.reset(new BrowserInit);
1341 1352
1342 // On first run, we need to process the predictor preferences before the 1353 // On first run, we need to process the predictor preferences before the
1343 // browser's profile_manager object is created, but after ResourceBundle 1354 // browser's profile_manager object is created, but after ResourceBundle
1344 // is initialized. 1355 // is initialized.
1345 master_prefs_.reset(new FirstRun::MasterPrefs); 1356 master_prefs_.reset(new FirstRun::MasterPrefs);
1346 bool first_run_ui_bypass = false; // True to skip first run UI. 1357 first_run_ui_bypass_ = false; // True to skip first run UI.
1347 if (is_first_run) { 1358 if (is_first_run_) {
1348 first_run_ui_bypass = 1359 first_run_ui_bypass_ = !FirstRun::ProcessMasterPreferences(
1349 !FirstRun::ProcessMasterPreferences(user_data_dir, master_prefs_.get()); 1360 user_data_dir_, master_prefs_.get());
1350 AddFirstRunNewTabs(browser_init_.get(), master_prefs_->new_tabs); 1361 AddFirstRunNewTabs(browser_init_.get(), master_prefs_->new_tabs);
1351 1362
1352 // If we are running in App mode, we do not want to show the importer 1363 // If we are running in App mode, we do not want to show the importer
1353 // (first run) UI. 1364 // (first run) UI.
1354 if (!first_run_ui_bypass && 1365 if (!first_run_ui_bypass_ &&
1355 (parsed_command_line().HasSwitch(switches::kApp) || 1366 (parsed_command_line().HasSwitch(switches::kApp) ||
1356 parsed_command_line().HasSwitch(switches::kAppId) || 1367 parsed_command_line().HasSwitch(switches::kAppId) ||
1357 parsed_command_line().HasSwitch(switches::kNoFirstRun))) 1368 parsed_command_line().HasSwitch(switches::kNoFirstRun)))
1358 first_run_ui_bypass = true; 1369 first_run_ui_bypass_ = true;
1359 } 1370 }
1360 1371
1361 // TODO(viettrungluu): why don't we run this earlier? 1372 // TODO(viettrungluu): why don't we run this earlier?
1362 if (!parsed_command_line().HasSwitch(switches::kNoErrorDialogs)) 1373 if (!parsed_command_line().HasSwitch(switches::kNoErrorDialogs))
1363 WarnAboutMinimumSystemRequirements(); 1374 WarnAboutMinimumSystemRequirements();
1364 1375
1365 // Enable print preview once for supported platforms. 1376 // Enable print preview once for supported platforms.
1366 #if defined(GOOGLE_CHROME_BUILD) 1377 #if defined(GOOGLE_CHROME_BUILD)
1367 local_state->RegisterBooleanPref(prefs::kPrintingPrintPreviewEnabledOnce, 1378 local_state_->RegisterBooleanPref(prefs::kPrintingPrintPreviewEnabledOnce,
1368 false, 1379 false,
1369 PrefService::UNSYNCABLE_PREF); 1380 PrefService::UNSYNCABLE_PREF);
1370 if (!local_state->GetBoolean(prefs::kPrintingPrintPreviewEnabledOnce)) { 1381 if (!local_state_->GetBoolean(prefs::kPrintingPrintPreviewEnabledOnce)) {
1371 local_state->SetBoolean(prefs::kPrintingPrintPreviewEnabledOnce, true); 1382 local_state_->SetBoolean(prefs::kPrintingPrintPreviewEnabledOnce, true);
1372 about_flags::SetExperimentEnabled(local_state, "print-preview", true); 1383 about_flags::SetExperimentEnabled(local_state_, "print-preview", true);
1373 } 1384 }
1374 #endif 1385 #endif
1375 1386
1376 // Convert active labs into switches. Modifies the current command line. 1387 // Convert active labs into switches. Modifies the current command line.
1377 about_flags::ConvertFlagsToSwitches(local_state, 1388 about_flags::ConvertFlagsToSwitches(local_state_,
1378 CommandLine::ForCurrentProcess()); 1389 CommandLine::ForCurrentProcess());
1379 1390
1380 // Reset the command line in the crash report details, since we may have 1391 // Reset the command line in the crash report details, since we may have
1381 // just changed it to include experiments. 1392 // just changed it to include experiments.
1382 child_process_logging::SetCommandLine(CommandLine::ForCurrentProcess()); 1393 child_process_logging::SetCommandLine(CommandLine::ForCurrentProcess());
1383 1394
1384 InitializeNetworkOptions(parsed_command_line()); 1395 InitializeNetworkOptions(parsed_command_line());
1385 InitializeURLRequestThrottlerManager(browser_process_->net_log()); 1396 InitializeURLRequestThrottlerManager(browser_process_->net_log());
1386 1397
1387 // Initialize histogram synchronizer system. This is a singleton and is used 1398 // Initialize histogram synchronizer system. This is a singleton and is used
1388 // for posting tasks via NewRunnableMethod. Its deleted when it goes out of 1399 // for posting tasks via NewRunnableMethod. Its deleted when it goes out of
1389 // scope. Even though NewRunnableMethod does AddRef and Release, the object 1400 // scope. Even though NewRunnableMethod does AddRef and Release, the object
1390 // will not be deleted after the Task is executed. 1401 // will not be deleted after the Task is executed.
1391 histogram_synchronizer_ = new HistogramSynchronizer(); 1402 histogram_synchronizer_ = new HistogramSynchronizer();
1392 tracking_synchronizer_ = new chrome_browser_metrics::TrackingSynchronizer(); 1403 tracking_synchronizer_ = new chrome_browser_metrics::TrackingSynchronizer();
1393 1404
1394 // Now the command line has been mutated based on about:flags, we can
1395 // set up metrics and initialize field trials.
1396 MetricsService* metrics = SetupMetricsAndFieldTrials(local_state);
1397
1398 #if defined(USE_WEBKIT_COMPOSITOR) 1405 #if defined(USE_WEBKIT_COMPOSITOR)
1399 // We need to ensure WebKit has been initialized before we start the WebKit 1406 // We need to ensure WebKit has been initialized before we start the WebKit
1400 // compositor. This is done by the ResourceDispatcherHost on creation. 1407 // compositor. This is done by the ResourceDispatcherHost on creation.
1401 g_browser_process->resource_dispatcher_host(); 1408 g_browser_process->resource_dispatcher_host();
1402 #endif 1409 #endif
1403 1410
1404 // Now that all preferences have been registered, set the install date 1411 // Now that all preferences have been registered, set the install date
1405 // for the uninstall metrics if this is our first run. This only actually 1412 // for the uninstall metrics if this is our first run. This only actually
1406 // gets used if the user has metrics reporting enabled at uninstall time. 1413 // gets used if the user has metrics reporting enabled at uninstall time.
1407 int64 install_date = 1414 int64 install_date =
1408 local_state->GetInt64(prefs::kUninstallMetricsInstallDate); 1415 local_state_->GetInt64(prefs::kUninstallMetricsInstallDate);
1409 if (install_date == 0) { 1416 if (install_date == 0) {
1410 local_state->SetInt64(prefs::kUninstallMetricsInstallDate, 1417 local_state_->SetInt64(prefs::kUninstallMetricsInstallDate,
1411 base::Time::Now().ToTimeT()); 1418 base::Time::Now().ToTimeT());
1412 } 1419 }
1413 1420
1414 #if defined(OS_MACOSX) 1421 #if defined(OS_MACOSX)
1415 // Get the Keychain API to register for distributed notifications on the main 1422 // Get the Keychain API to register for distributed notifications on the main
1416 // thread, which has a proper CFRunloop, instead of later on the I/O thread, 1423 // thread, which has a proper CFRunloop, instead of later on the I/O thread,
1417 // which doesn't. This ensures those notifications will get delivered 1424 // which doesn't. This ensures those notifications will get delivered
1418 // properly. See issue 37766. 1425 // properly. See issue 37766.
1419 // (Note that the callback mask here is empty. I don't want to register for 1426 // (Note that the callback mask here is empty. I don't want to register for
1420 // any callbacks, I just want to initialize the mechanism.) 1427 // any callbacks, I just want to initialize the mechanism.)
1421 SecKeychainAddCallback(&KeychainCallback, 0, NULL); 1428 SecKeychainAddCallback(&KeychainCallback, 0, NULL);
1422 #endif 1429 #endif
1423 1430
1424 CreateChildThreads(browser_process_.get()); 1431 return content::RESULT_CODE_NORMAL_EXIT;
1432 }
1433
1434 int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
1435 // Create watchdog thread after creating all other threads because it will
1436 // watch the other threads and they must be running.
1437 browser_process_->watchdog_thread();
1425 1438
1426 #if defined(OS_CHROMEOS) 1439 #if defined(OS_CHROMEOS)
1427 // Now that the file thread exists we can record our stats. 1440 // Now that the file thread exists we can record our stats.
1428 chromeos::BootTimesLoader::Get()->RecordChromeMainStats(); 1441 chromeos::BootTimesLoader::Get()->RecordChromeMainStats();
1429 1442
1430 #if defined(TOOLKIT_USES_GTK) 1443 #if defined(TOOLKIT_USES_GTK)
1431 // Read locale-specific GTK resource information. 1444 // Read locale-specific GTK resource information.
1432 std::string gtkrc = l10n_util::GetStringUTF8(IDS_LOCALE_GTKRC); 1445 std::string gtkrc = l10n_util::GetStringUTF8(IDS_LOCALE_GTKRC);
1433 if (!gtkrc.empty()) 1446 if (!gtkrc.empty())
1434 gtk_rc_parse_string(gtkrc.c_str()); 1447 gtk_rc_parse_string(gtkrc.c_str());
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1564 // initialization code sees policy settings. 1577 // initialization code sees policy settings.
1565 g_browser_process->browser_policy_connector()->InitializeUserPolicy( 1578 g_browser_process->browser_policy_connector()->InitializeUserPolicy(
1566 username, false /* wait_for_policy_fetch */); 1579 username, false /* wait_for_policy_fetch */);
1567 } else if (parsed_command_line().HasSwitch(switches::kLoginManager)) { 1580 } else if (parsed_command_line().HasSwitch(switches::kLoginManager)) {
1568 // Initialize status area mode early on. 1581 // Initialize status area mode early on.
1569 chromeos::StatusAreaViewChromeos:: 1582 chromeos::StatusAreaViewChromeos::
1570 SetScreenMode(chromeos::StatusAreaViewChromeos::LOGIN_MODE_WEBUI); 1583 SetScreenMode(chromeos::StatusAreaViewChromeos::LOGIN_MODE_WEBUI);
1571 } 1584 }
1572 #endif 1585 #endif
1573 1586
1574 if (is_first_run) { 1587 if (is_first_run_) {
1575 // Warn the ProfileManager that an import process will run, possibly 1588 // Warn the ProfileManager that an import process will run, possibly
1576 // locking the WebDataService directory of the next Profile created. 1589 // locking the WebDataService directory of the next Profile created.
1577 g_browser_process->profile_manager()->SetWillImport(); 1590 g_browser_process->profile_manager()->SetWillImport();
1578 } 1591 }
1579 1592
1580 profile_ = CreateProfile(parameters(), user_data_dir, parsed_command_line()); 1593 profile_ = CreateProfile(parameters(), user_data_dir_, parsed_command_line());
1581 if (!profile_) 1594 if (!profile_)
1582 return content::RESULT_CODE_NORMAL_EXIT; 1595 return content::RESULT_CODE_NORMAL_EXIT;
1583 1596
1584 // Autoload any profiles which are running background apps. 1597 // Autoload any profiles which are running background apps.
1585 // TODO(rlp): Do this on a separate thread. See http://crbug.com/99075. 1598 // TODO(rlp): Do this on a separate thread. See http://crbug.com/99075.
1586 if (!BackgroundModeManager::IsBackgroundModePermanentlyDisabled( 1599 if (!BackgroundModeManager::IsBackgroundModePermanentlyDisabled(
1587 &parsed_command_line())) { 1600 &parsed_command_line())) {
1588 g_browser_process->profile_manager()->AutoloadProfiles(); 1601 g_browser_process->profile_manager()->AutoloadProfiles();
1589 } 1602 }
1590 // Post-profile init --------------------------------------------------------- 1603 // Post-profile init ---------------------------------------------------------
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1654 // TODO(stevenjb): Move ChromeOS login code into PostProfileInitialized(). 1667 // TODO(stevenjb): Move ChromeOS login code into PostProfileInitialized().
1655 // (Requires making ChromeBrowserMainPartsChromeos a non "main" Parts). 1668 // (Requires making ChromeBrowserMainPartsChromeos a non "main" Parts).
1656 for (size_t i = 0; i < chrome_extra_parts_.size(); ++i) 1669 for (size_t i = 0; i < chrome_extra_parts_.size(); ++i)
1657 chrome_extra_parts_[i]->PostProfileInitialized(); 1670 chrome_extra_parts_[i]->PostProfileInitialized();
1658 1671
1659 // Show the First Run UI if this is the first time Chrome has been run on 1672 // Show the First Run UI if this is the first time Chrome has been run on
1660 // this computer, or we're being compelled to do so by a command line flag. 1673 // this computer, or we're being compelled to do so by a command line flag.
1661 // Note that this be done _after_ the PrefService is initialized and all 1674 // Note that this be done _after_ the PrefService is initialized and all
1662 // preferences are registered, since some of the code that the importer 1675 // preferences are registered, since some of the code that the importer
1663 // touches reads preferences. 1676 // touches reads preferences.
1664 if (is_first_run) { 1677 if (is_first_run_) {
1665 if (!first_run_ui_bypass) { 1678 if (!first_run_ui_bypass_) {
1666 FirstRun::AutoImport(profile_, 1679 FirstRun::AutoImport(profile_,
1667 master_prefs_->homepage_defined, 1680 master_prefs_->homepage_defined,
1668 master_prefs_->do_import_items, 1681 master_prefs_->do_import_items,
1669 master_prefs_->dont_import_items, 1682 master_prefs_->dont_import_items,
1670 master_prefs_->run_search_engine_experiment, 1683 master_prefs_->run_search_engine_experiment,
1671 master_prefs_->randomize_search_engine_experiment, 1684 master_prefs_->randomize_search_engine_experiment,
1672 master_prefs_->make_chrome_default, 1685 master_prefs_->make_chrome_default,
1673 process_singleton_.get()); 1686 process_singleton_.get());
1674 #if defined(OS_POSIX) 1687 #if defined(OS_POSIX)
1675 // On Windows, the download is tagged with enable/disable stats so there 1688 // On Windows, the download is tagged with enable/disable stats so there
1676 // is no need for this code. 1689 // is no need for this code.
1677 1690
1678 // If stats reporting was turned on by the first run dialog then toggle 1691 // If stats reporting was turned on by the first run dialog then toggle
1679 // the pref. 1692 // the pref.
1680 if (GoogleUpdateSettings::GetCollectStatsConsent()) 1693 if (GoogleUpdateSettings::GetCollectStatsConsent())
1681 local_state->SetBoolean(prefs::kMetricsReportingEnabled, true); 1694 local_state_->SetBoolean(prefs::kMetricsReportingEnabled, true);
1682 #endif // OS_POSIX 1695 #endif // OS_POSIX
1683 } // if (!first_run_ui_bypass) 1696 } // if (!first_run_ui_bypass_)
1684 1697
1685 Browser::SetNewHomePagePrefs(profile_->GetPrefs()); 1698 Browser::SetNewHomePagePrefs(profile_->GetPrefs());
1686 g_browser_process->profile_manager()->OnImportFinished(profile_); 1699 g_browser_process->profile_manager()->OnImportFinished(profile_);
1687 } // if (is_first_run) 1700 } // if (is_first_run_)
1688 1701
1689 #if defined(OS_WIN) 1702 #if defined(OS_WIN)
1690 // Sets things up so that if we crash from this point on, a dialog will 1703 // Sets things up so that if we crash from this point on, a dialog will
1691 // popup asking the user to restart chrome. It is done this late to avoid 1704 // popup asking the user to restart chrome. It is done this late to avoid
1692 // testing against a bunch of special cases that are taken care early on. 1705 // testing against a bunch of special cases that are taken care early on.
1693 ChromeBrowserMainPartsWin::PrepareRestartOnCrashEnviroment( 1706 ChromeBrowserMainPartsWin::PrepareRestartOnCrashEnviroment(
1694 parsed_command_line()); 1707 parsed_command_line());
1695 1708
1696 // Registers Chrome with the Windows Restart Manager, which will restore the 1709 // Registers Chrome with the Windows Restart Manager, which will restore the
1697 // Chrome session when the computer is restarted after a system update. 1710 // Chrome session when the computer is restarted after a system update.
(...skipping 24 matching lines...) Expand all
1722 } 1735 }
1723 1736
1724 bool google_search_homepage = false; 1737 bool google_search_homepage = false;
1725 PrefService* pref_service = profile_->GetPrefs(); 1738 PrefService* pref_service = profile_->GetPrefs();
1726 if (pref_service) { 1739 if (pref_service) {
1727 std::string homepage = pref_service->GetString(prefs::kHomePage); 1740 std::string homepage = pref_service->GetString(prefs::kHomePage);
1728 google_search_homepage = 1741 google_search_homepage =
1729 homepage == GoogleURLTracker::kDefaultGoogleHomepage; 1742 homepage == GoogleURLTracker::kDefaultGoogleHomepage;
1730 } 1743 }
1731 1744
1732 RLZTracker::InitRlzDelayed(is_first_run, master_prefs_->ping_delay, 1745 RLZTracker::InitRlzDelayed(is_first_run_, master_prefs_->ping_delay,
1733 google_search_default, google_search_homepage); 1746 google_search_default, google_search_homepage);
1734 1747
1735 // Prime the RLZ cache for the home page access point so that its avaiable 1748 // Prime the RLZ cache for the home page access point so that its avaiable
1736 // for the startup page if needed (i.e., when the startup page is set to 1749 // for the startup page if needed (i.e., when the startup page is set to
1737 // the home page). 1750 // the home page).
1738 RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_HOME_PAGE, NULL); 1751 RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_HOME_PAGE, NULL);
1739 #endif // GOOGLE_CHROME_BUILD 1752 #endif // GOOGLE_CHROME_BUILD
1740 #endif // OS_WIN 1753 #endif // OS_WIN
1741 1754
1742 // Start watching for hangs during startup. We disarm this hang detector when 1755 // Start watching for hangs during startup. We disarm this hang detector when
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1792 1805
1793 #if defined(OS_WIN) && !defined(GOOGLE_CHROME_BUILD) 1806 #if defined(OS_WIN) && !defined(GOOGLE_CHROME_BUILD)
1794 if (parsed_command_line().HasSwitch(switches::kDebugPrint)) { 1807 if (parsed_command_line().HasSwitch(switches::kDebugPrint)) {
1795 FilePath path = 1808 FilePath path =
1796 parsed_command_line().GetSwitchValuePath(switches::kDebugPrint); 1809 parsed_command_line().GetSwitchValuePath(switches::kDebugPrint);
1797 printing::PrintedDocument::set_debug_dump_path(path); 1810 printing::PrintedDocument::set_debug_dump_path(path);
1798 } 1811 }
1799 #endif 1812 #endif
1800 1813
1801 HandleTestParameters(parsed_command_line()); 1814 HandleTestParameters(parsed_command_line());
1802 RecordBreakpadStatusUMA(metrics); 1815 RecordBreakpadStatusUMA(metrics_);
1803 about_flags::RecordUMAStatistics(local_state); 1816 about_flags::RecordUMAStatistics(local_state_);
1804 LanguageUsageMetrics::RecordAcceptLanguages( 1817 LanguageUsageMetrics::RecordAcceptLanguages(
1805 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); 1818 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
1806 LanguageUsageMetrics::RecordApplicationLanguage( 1819 LanguageUsageMetrics::RecordApplicationLanguage(
1807 g_browser_process->GetApplicationLocale()); 1820 g_browser_process->GetApplicationLocale());
1808 1821
1809 #if defined(OS_WIN) 1822 #if defined(OS_WIN)
1810 fragmentation_checker::RecordFragmentationMetricForCurrentModule(); 1823 fragmentation_checker::RecordFragmentationMetricForCurrentModule();
1811 #endif 1824 #endif
1812 1825
1813 #if defined(OS_CHROMEOS) 1826 #if defined(OS_CHROMEOS)
1814 metrics->StartExternalMetrics(); 1827 metrics_->StartExternalMetrics();
1815 1828
1816 // Initialize the audio handler on ChromeOS. 1829 // Initialize the audio handler on ChromeOS.
1817 chromeos::AudioHandler::Initialize(); 1830 chromeos::AudioHandler::Initialize();
1818 1831
1819 // Listen for system key events so that the user will be able to adjust the 1832 // Listen for system key events so that the user will be able to adjust the
1820 // volume on the login screen, if Chrome is running on Chrome OS 1833 // volume on the login screen, if Chrome is running on Chrome OS
1821 // (i.e. not Linux desktop), and in non-test mode. 1834 // (i.e. not Linux desktop), and in non-test mode.
1822 if (chromeos::system::runtime_environment::IsRunningOnChromeOS() && 1835 if (chromeos::system::runtime_environment::IsRunningOnChromeOS() &&
1823 !parameters().ui_task) { // ui_task is non-NULL when running tests. 1836 !parameters().ui_task) { // ui_task is non-NULL when running tests.
1824 chromeos::SystemKeyEventListener::Initialize(); 1837 chromeos::SystemKeyEventListener::Initialize();
(...skipping 12 matching lines...) Expand all
1837 return content::RESULT_CODE_NORMAL_EXIT; 1850 return content::RESULT_CODE_NORMAL_EXIT;
1838 return chrome::RESULT_CODE_UNINSTALL_EXTENSION_ERROR; 1851 return chrome::RESULT_CODE_UNINSTALL_EXTENSION_ERROR;
1839 } 1852 }
1840 1853
1841 // Start watching for a hang. 1854 // Start watching for a hang.
1842 MetricsService::LogNeedForCleanShutdown(); 1855 MetricsService::LogNeedForCleanShutdown();
1843 1856
1844 #if defined(OS_WIN) 1857 #if defined(OS_WIN)
1845 // We check this here because if the profile is OTR (chromeos possibility) 1858 // We check this here because if the profile is OTR (chromeos possibility)
1846 // it won't still be accessible after browser is destroyed. 1859 // it won't still be accessible after browser is destroyed.
1847 record_search_engine_ = is_first_run && !profile_->IsOffTheRecord(); 1860 record_search_engine_ = is_first_run_ && !profile_->IsOffTheRecord();
1848 #endif 1861 #endif
1849 1862
1850 // ChildProcess:: is a misnomer unless you consider context. Use 1863 // ChildProcess:: is a misnomer unless you consider context. Use
1851 // of --wait-for-debugger only makes sense when Chrome itself is a 1864 // of --wait-for-debugger only makes sense when Chrome itself is a
1852 // child process (e.g. when launched by PyAuto). 1865 // child process (e.g. when launched by PyAuto).
1853 if (parsed_command_line().HasSwitch(switches::kWaitForDebugger)) { 1866 if (parsed_command_line().HasSwitch(switches::kWaitForDebugger)) {
1854 ChildProcess::WaitForDebugger("Browser"); 1867 ChildProcess::WaitForDebugger("Browser");
1855 } 1868 }
1856 1869
1857 #if defined(OS_CHROMEOS) 1870 #if defined(OS_CHROMEOS)
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1893 parameters().ui_task->Run(); 1906 parameters().ui_task->Run();
1894 delete parameters().ui_task; 1907 delete parameters().ui_task;
1895 run_message_loop_ = false; 1908 run_message_loop_ = false;
1896 } else { 1909 } else {
1897 // Most general initialization is behind us, but opening a 1910 // Most general initialization is behind us, but opening a
1898 // tab and/or session restore and such is still to be done. 1911 // tab and/or session restore and such is still to be done.
1899 base::TimeTicks browser_open_start = base::TimeTicks::Now(); 1912 base::TimeTicks browser_open_start = base::TimeTicks::Now();
1900 1913
1901 // We are in regular browser boot sequence. Open initial tabs and enter the 1914 // We are in regular browser boot sequence. Open initial tabs and enter the
1902 // main message loop. 1915 // main message loop.
1916 int result_code;
1903 if (browser_init_->Start(parsed_command_line(), FilePath(), profile_, 1917 if (browser_init_->Start(parsed_command_line(), FilePath(), profile_,
1904 &result_code_)) { 1918 &result_code)) {
1905 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) 1919 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
1906 // Initialize autoupdate timer. Timer callback costs basically nothing 1920 // Initialize autoupdate timer. Timer callback costs basically nothing
1907 // when browser is not in persistent mode, so it's OK to let it ride on 1921 // when browser is not in persistent mode, so it's OK to let it ride on
1908 // the main thread. This needs to be done here because we don't want 1922 // the main thread. This needs to be done here because we don't want
1909 // to start the timer when Chrome is run inside a test harness. 1923 // to start the timer when Chrome is run inside a test harness.
1910 g_browser_process->StartAutoupdateTimer(); 1924 g_browser_process->StartAutoupdateTimer();
1911 #endif 1925 #endif
1912 1926
1913 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 1927 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1914 // On Linux, the running exe will be updated if an upgrade becomes 1928 // On Linux, the running exe will be updated if an upgrade becomes
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
2061 // The XInput2 event listener needs to be shut down earlier than when 2075 // The XInput2 event listener needs to be shut down earlier than when
2062 // Singletons are finally destroyed in AtExitManager. 2076 // Singletons are finally destroyed in AtExitManager.
2063 chromeos::XInputHierarchyChangedEventListener::GetInstance()->Stop(); 2077 chromeos::XInputHierarchyChangedEventListener::GetInstance()->Stop();
2064 2078
2065 // chromeos::SystemKeyEventListener::Shutdown() is always safe to call, 2079 // chromeos::SystemKeyEventListener::Shutdown() is always safe to call,
2066 // even if Initialize() wasn't called. 2080 // even if Initialize() wasn't called.
2067 chromeos::SystemKeyEventListener::Shutdown(); 2081 chromeos::SystemKeyEventListener::Shutdown();
2068 chromeos::AudioHandler::Shutdown(); 2082 chromeos::AudioHandler::Shutdown();
2069 #endif 2083 #endif
2070 2084
2085 restart_last_session_ = browser_shutdown::ShutdownPreThreadsStop();
2086 browser_process_->StartTearDown();
2087 }
2088
2089 void ChromeBrowserMainParts::PreStopThread(BrowserThread::ID identifier) {
2090 browser_process_->PreStopThread(identifier);
2091 }
2092
2093 void ChromeBrowserMainParts::PostStopThread(BrowserThread::ID identifier) {
2094 browser_process_->PostStopThread(identifier);
2095 }
2096
2097 void ChromeBrowserMainParts::PostDestroyThreads() {
2071 // browser_shutdown takes care of deleting browser_process, so we need to 2098 // browser_shutdown takes care of deleting browser_process, so we need to
2072 // release it. 2099 // release it.
2073 ignore_result(browser_process_.release()); 2100 ignore_result(browser_process_.release());
2074 browser_shutdown::Shutdown(); 2101 browser_shutdown::ShutdownPostThreadsStop(restart_last_session_);
2075 master_prefs_.reset(); 2102 master_prefs_.reset();
2076 process_singleton_.reset(); 2103 process_singleton_.reset();
2077 2104
2078 // We need to do this check as late as possible, but due to modularity, this 2105 // We need to do this check as late as possible, but due to modularity, this
2079 // may be the last point in Chrome. This would be more effective if done at 2106 // may be the last point in Chrome. This would be more effective if done at
2080 // a higher level on the stack, so that it is impossible for an early return 2107 // a higher level on the stack, so that it is impossible for an early return
2081 // to bypass this code. Perhaps we need a *final* hook that is called on all 2108 // to bypass this code. Perhaps we need a *final* hook that is called on all
2082 // paths from content/browser/browser_main. 2109 // paths from content/browser/browser_main.
2083 CHECK(MetricsService::UmaMetricsProperlyShutdown()); 2110 CHECK(MetricsService::UmaMetricsProperlyShutdown());
2084 2111
(...skipping 29 matching lines...) Expand all
2114 if (env->GetVar(chrome::kPreReadEnvironmentVariable, &pre_read) && 2141 if (env->GetVar(chrome::kPreReadEnvironmentVariable, &pre_read) &&
2115 (pre_read == "0" || pre_read == "1")) { 2142 (pre_read == "0" || pre_read == "1")) {
2116 std::string uma_name(name); 2143 std::string uma_name(name);
2117 uma_name += "_PreRead"; 2144 uma_name += "_PreRead";
2118 uma_name += pre_read == "1" ? "Enabled" : "Disabled"; 2145 uma_name += pre_read == "1" ? "Enabled" : "Disabled";
2119 AddPreReadHistogramTime(uma_name.c_str(), time); 2146 AddPreReadHistogramTime(uma_name.c_str(), time);
2120 } 2147 }
2121 #endif 2148 #endif
2122 #endif 2149 #endif
2123 } 2150 }
OLDNEW
« no previous file with comments | « chrome/browser/chrome_browser_main.h ('k') | chrome/browser/chromeos/input_method/xkeyboard.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698