1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/public/browser/browser_main_runner.h" 6 7 #include "base/allocator/allocator_shim.h" 8 #include "base/base_switches.h" 9 #include "base/command_line.h" 10 #include "base/debug/leak_annotations.h" 11 #include "base/debug/trace_event.h" 12 #include "base/logging.h" 13 #include "base/metrics/histogram.h" 14 #include "base/metrics/statistics_recorder.h" 15 #include "content/browser/browser_main_loop.h" 16 #include "content/browser/browser_shutdown_profile_dumper.h" 17 #include "content/browser/notification_service_impl.h" 18 #include "content/public/common/content_switches.h" 19 #include "content/public/common/main_function_params.h" 20 #include "ui/base/ime/input_method_initializer.h" 21 22 #if defined(OS_WIN) 23 #include "base/win/windows_version.h" 24 #include "ui/base/win/scoped_ole_initializer.h" 25 #endif 26 27 bool g_exited_main_message_loop = false; 28 29 namespace content { 30 31 class BrowserMainRunnerImpl : public BrowserMainRunner { 32 public: 33 BrowserMainRunnerImpl() 34 : initialization_started_(false), is_shutdown_(false) {} 35 36 virtual ~BrowserMainRunnerImpl() { 37 if (initialization_started_ && !is_shutdown_) 38 Shutdown(); 39 } 40 41 virtual int Initialize(const MainFunctionParams& parameters) OVERRIDE { 42 TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize"); 43 // On Android we normally initialize the browser in a series of UI thread 44 // tasks. While this is happening a second request can come from the OS or 45 // another application to start the browser. If this happens then we must 46 // not run these parts of initialization twice. 47 if (!initialization_started_) { 48 initialization_started_ = true; 49 50 #if !defined(OS_IOS) 51 if (parameters.command_line.HasSwitch(switches::kWaitForDebugger)) 52 base::debug::WaitForDebugger(60, true); 53 #endif 54 55 #if defined(OS_WIN) 56 if (base::win::GetVersion() < base::win::VERSION_VISTA) { 57 // When "Extend support of advanced text services to all programs" 58 // (a.k.a. Cicero Unaware Application Support; CUAS) is enabled on 59 // Windows XP and handwriting modules shipped with Office 2003 are 60 // installed, "penjpn.dll" and "skchui.dll" will be loaded and then 61 // crash unless a user installs Office 2003 SP3. To prevent these 62 // modules from being loaded, disable TSF entirely. crbug.com/160914. 63 // TODO(yukawa): Add a high-level wrapper for this instead of calling 64 // Win32 API here directly. 65 ImmDisableTextFrameService(static_cast<DWORD>(-1)); 66 } 67 #endif // OS_WIN 68 69 base::StatisticsRecorder::Initialize(); 70 71 notification_service_.reset(new NotificationServiceImpl); 72 73 #if defined(OS_WIN) 74 // Ole must be initialized before starting message pump, so that TSF 75 // (Text Services Framework) module can interact with the message pump 76 // on Windows 8 Metro mode. 77 ole_initializer_.reset(new ui::ScopedOleInitializer); 78 #endif // OS_WIN 79 80 main_loop_.reset(new BrowserMainLoop(parameters)); 81 82 main_loop_->Init(); 83 84 main_loop_->EarlyInitialization(); 85 86 // Must happen before we try to use a message loop or display any UI. 87 if (!main_loop_->InitializeToolkit()) 88 return 1; 89 90 main_loop_->MainMessageLoopStart(); 91 92 // WARNING: If we get a WM_ENDSESSION, objects created on the stack here 93 // are NOT deleted. If you need something to run during WM_ENDSESSION add it 94 // to browser_shutdown::Shutdown or BrowserProcess::EndSession. 95 96 #if defined(OS_WIN) && !defined(NO_TCMALLOC) 97 // When linking shared libraries, NO_TCMALLOC is defined, and dynamic 98 // allocator selection is not supported. 99 100 // Make this call before going multithreaded, or spawning any 101 // subprocesses. 102 base::allocator::SetupSubprocessAllocator(); 103 #endif 104 ui::InitializeInputMethod(); 105 } 106 main_loop_->CreateStartupTasks(); 107 int result_code = main_loop_->GetResultCode(); 108 if (result_code > 0) 109 return result_code; 110 111 // Return -1 to indicate no early termination. 112 return -1; 113 } 114 115 virtual int Run() OVERRIDE { 116 DCHECK(initialization_started_); 117 DCHECK(!is_shutdown_); 118 main_loop_->RunMainMessageLoopParts(); 119 return main_loop_->GetResultCode(); 120 } 121 122 virtual void Shutdown() OVERRIDE { 123 DCHECK(initialization_started_); 124 DCHECK(!is_shutdown_); 125 #ifdef LEAK_SANITIZER 126 // Invoke leak detection now, to avoid dealing with shutdown-only leaks. 127 // Normally this will have already happened in 128 // BroserProcessImpl::ReleaseModule(), so this call has no effect. This is 129 // only for processes which do not instantiate a BrowserProcess. 130 // If leaks are found, the process will exit here. 131 __lsan_do_leak_check(); 132 #endif 133 // The shutdown tracing got enabled in AttemptUserExit earlier, but someone 134 // needs to write the result to disc. For that a dumper needs to get created 135 // which will dump the traces to disc when it gets destroyed. 136 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 137 scoped_ptr<BrowserShutdownProfileDumper> profiler; 138 if (command_line.HasSwitch(switches::kTraceShutdown)) 139 profiler.reset(new BrowserShutdownProfileDumper()); 140 141 { 142 // The trace event has to stay between profiler creation and destruction. 143 TRACE_EVENT0("shutdown", "BrowserMainRunner"); 144 g_exited_main_message_loop = true; 145 146 main_loop_->ShutdownThreadsAndCleanUp(); 147 148 ui::ShutdownInputMethod(); 149 #if defined(OS_WIN) 150 ole_initializer_.reset(NULL); 151 #endif 152 #if defined(OS_ANDROID) 153 // Forcefully terminates the RunLoop inside MessagePumpForUI, ensuring 154 // proper shutdown for content_browsertests. Shutdown() is not used by 155 // the actual browser. 156 base::MessageLoop::current()->QuitNow(); 157 #endif 158 main_loop_.reset(NULL); 159 160 notification_service_.reset(NULL); 161 162 is_shutdown_ = true; 163 } 164 } 165 166 protected: 167 // True if we have started to initialize the runner. 168 bool initialization_started_; 169 170 // True if the runner has been shut down. 171 bool is_shutdown_; 172 173 scoped_ptr<NotificationServiceImpl> notification_service_; 174 scoped_ptr<BrowserMainLoop> main_loop_; 175 #if defined(OS_WIN) 176 scoped_ptr<ui::ScopedOleInitializer> ole_initializer_; 177 #endif 178 179 DISALLOW_COPY_AND_ASSIGN(BrowserMainRunnerImpl); 180 }; 181 182 // static 183 BrowserMainRunner* BrowserMainRunner::Create() { 184 return new BrowserMainRunnerImpl(); 185 } 186 187 } // namespace content 188