Change next_proto member type.
[chromium-blink-merge.git] / content / browser / browser_main_runner.cc
blob2975ef864747646aec4a2fa68028d0c697b1bb66
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.
5 #include "content/public/browser/browser_main_runner.h"
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"
22 #if defined(OS_WIN)
23 #include "base/win/win_util.h"
24 #include "base/win/windows_version.h"
25 #include "net/cert/sha256_legacy_support_win.h"
26 #include "sandbox/win/src/sidestep/preamble_patcher.h"
27 #include "ui/base/win/scoped_ole_initializer.h"
28 #include "ui/gfx/switches.h"
29 #include "ui/gfx/win/direct_write.h"
30 #endif
32 bool g_exited_main_message_loop = false;
34 namespace content {
36 #if defined(OS_WIN)
37 namespace {
39 // Pointer to the original CryptVerifyCertificateSignatureEx function.
40 net::sha256_interception::CryptVerifyCertificateSignatureExFunc
41 g_real_crypt_verify_signature_stub = NULL;
43 // Stub function that is called whenever the Crypt32 function
44 // CryptVerifyCertificateSignatureEx is called. It just defers to net to perform
45 // the actual verification.
46 BOOL WINAPI CryptVerifyCertificateSignatureExStub(
47 HCRYPTPROV_LEGACY provider,
48 DWORD encoding_type,
49 DWORD subject_type,
50 void* subject_data,
51 DWORD issuer_type,
52 void* issuer_data,
53 DWORD flags,
54 void* extra) {
55 return net::sha256_interception::CryptVerifyCertificateSignatureExHook(
56 g_real_crypt_verify_signature_stub, provider, encoding_type, subject_type,
57 subject_data, issuer_type, issuer_data, flags, extra);
60 // If necessary, install an interception
61 void InstallSha256LegacyHooks() {
62 #if defined(_WIN64)
63 // Interception on x64 is not supported.
64 return;
65 #else
66 if (base::win::MaybeHasSHA256Support())
67 return;
69 net::sha256_interception::CryptVerifyCertificateSignatureExFunc
70 cert_verify_signature_ptr = reinterpret_cast<
71 net::sha256_interception::CryptVerifyCertificateSignatureExFunc>(
72 ::GetProcAddress(::GetModuleHandle(L"crypt32.dll"),
73 "CryptVerifyCertificateSignatureEx"));
74 CHECK(cert_verify_signature_ptr);
76 DWORD old_protect = 0;
77 if (!::VirtualProtect(cert_verify_signature_ptr, 5, PAGE_EXECUTE_READWRITE,
78 &old_protect)) {
79 return;
82 g_real_crypt_verify_signature_stub =
83 reinterpret_cast<
84 net::sha256_interception::CryptVerifyCertificateSignatureExFunc>(
85 VirtualAllocEx(::GetCurrentProcess(), NULL,
86 sidestep::kMaxPreambleStubSize, MEM_COMMIT,
87 PAGE_EXECUTE_READWRITE));
88 if (g_real_crypt_verify_signature_stub == NULL) {
89 CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect,
90 &old_protect));
91 return;
94 sidestep::SideStepError patch_result =
95 sidestep::PreamblePatcher::Patch(
96 cert_verify_signature_ptr, CryptVerifyCertificateSignatureExStub,
97 g_real_crypt_verify_signature_stub, sidestep::kMaxPreambleStubSize);
98 if (patch_result != sidestep::SIDESTEP_SUCCESS) {
99 CHECK(::VirtualFreeEx(::GetCurrentProcess(),
100 g_real_crypt_verify_signature_stub, 0,
101 MEM_RELEASE));
102 CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect,
103 &old_protect));
104 return;
107 DWORD dummy = 0;
108 CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect, &dummy));
109 CHECK(::VirtualProtect(g_real_crypt_verify_signature_stub,
110 sidestep::kMaxPreambleStubSize, old_protect,
111 &old_protect));
112 #endif // _WIN64
115 } // namespace
117 #endif // OS_WIN
119 class BrowserMainRunnerImpl : public BrowserMainRunner {
120 public:
121 BrowserMainRunnerImpl()
122 : initialization_started_(false), is_shutdown_(false) {}
124 ~BrowserMainRunnerImpl() override {
125 if (initialization_started_ && !is_shutdown_)
126 Shutdown();
129 int Initialize(const MainFunctionParams& parameters) override {
130 TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize");
131 // On Android we normally initialize the browser in a series of UI thread
132 // tasks. While this is happening a second request can come from the OS or
133 // another application to start the browser. If this happens then we must
134 // not run these parts of initialization twice.
135 if (!initialization_started_) {
136 initialization_started_ = true;
138 #if !defined(OS_IOS)
139 if (parameters.command_line.HasSwitch(switches::kWaitForDebugger))
140 base::debug::WaitForDebugger(60, true);
141 #endif
143 #if defined(OS_WIN)
144 if (base::win::GetVersion() < base::win::VERSION_VISTA) {
145 // When "Extend support of advanced text services to all programs"
146 // (a.k.a. Cicero Unaware Application Support; CUAS) is enabled on
147 // Windows XP and handwriting modules shipped with Office 2003 are
148 // installed, "penjpn.dll" and "skchui.dll" will be loaded and then
149 // crash unless a user installs Office 2003 SP3. To prevent these
150 // modules from being loaded, disable TSF entirely. crbug.com/160914.
151 // TODO(yukawa): Add a high-level wrapper for this instead of calling
152 // Win32 API here directly.
153 ImmDisableTextFrameService(static_cast<DWORD>(-1));
155 InstallSha256LegacyHooks();
156 #endif // OS_WIN
158 base::StatisticsRecorder::Initialize();
160 notification_service_.reset(new NotificationServiceImpl);
162 #if defined(OS_WIN)
163 // Ole must be initialized before starting message pump, so that TSF
164 // (Text Services Framework) module can interact with the message pump
165 // on Windows 8 Metro mode.
166 ole_initializer_.reset(new ui::ScopedOleInitializer);
167 // Enable DirectWrite font rendering if needed.
168 gfx::win::MaybeInitializeDirectWrite();
169 #endif // OS_WIN
171 main_loop_.reset(new BrowserMainLoop(parameters));
173 main_loop_->Init();
175 main_loop_->EarlyInitialization();
177 // Must happen before we try to use a message loop or display any UI.
178 if (!main_loop_->InitializeToolkit())
179 return 1;
181 main_loop_->MainMessageLoopStart();
183 // WARNING: If we get a WM_ENDSESSION, objects created on the stack here
184 // are NOT deleted. If you need something to run during WM_ENDSESSION add it
185 // to browser_shutdown::Shutdown or BrowserProcess::EndSession.
187 #if defined(OS_WIN) && !defined(NO_TCMALLOC)
188 // When linking shared libraries, NO_TCMALLOC is defined, and dynamic
189 // allocator selection is not supported.
191 // Make this call before going multithreaded, or spawning any
192 // subprocesses.
193 base::allocator::SetupSubprocessAllocator();
194 #endif
195 ui::InitializeInputMethod();
197 main_loop_->CreateStartupTasks();
198 int result_code = main_loop_->GetResultCode();
199 if (result_code > 0)
200 return result_code;
202 // Return -1 to indicate no early termination.
203 return -1;
206 int Run() override {
207 DCHECK(initialization_started_);
208 DCHECK(!is_shutdown_);
209 main_loop_->RunMainMessageLoopParts();
210 return main_loop_->GetResultCode();
213 void Shutdown() override {
214 DCHECK(initialization_started_);
215 DCHECK(!is_shutdown_);
216 #ifdef LEAK_SANITIZER
217 // Invoke leak detection now, to avoid dealing with shutdown-only leaks.
218 // Normally this will have already happened in
219 // BroserProcessImpl::ReleaseModule(), so this call has no effect. This is
220 // only for processes which do not instantiate a BrowserProcess.
221 // If leaks are found, the process will exit here.
222 __lsan_do_leak_check();
223 #endif
224 // If startup tracing has not been finished yet, replace it's dumper
225 // with special version, which would save trace file on exit (i.e.
226 // startup tracing becomes a version of shutdown tracing).
227 scoped_ptr<BrowserShutdownProfileDumper> startup_profiler;
228 if (main_loop_->is_tracing_startup()) {
229 main_loop_->StopStartupTracingTimer();
230 if (main_loop_->startup_trace_file() !=
231 base::FilePath().AppendASCII("none")) {
232 startup_profiler.reset(
233 new BrowserShutdownProfileDumper(main_loop_->startup_trace_file()));
237 // The shutdown tracing got enabled in AttemptUserExit earlier, but someone
238 // needs to write the result to disc. For that a dumper needs to get created
239 // which will dump the traces to disc when it gets destroyed.
240 const base::CommandLine& command_line =
241 *base::CommandLine::ForCurrentProcess();
242 scoped_ptr<BrowserShutdownProfileDumper> shutdown_profiler;
243 if (command_line.HasSwitch(switches::kTraceShutdown)) {
244 shutdown_profiler.reset(new BrowserShutdownProfileDumper(
245 BrowserShutdownProfileDumper::GetShutdownProfileFileName()));
249 // The trace event has to stay between profiler creation and destruction.
250 TRACE_EVENT0("shutdown", "BrowserMainRunner");
251 g_exited_main_message_loop = true;
253 main_loop_->ShutdownThreadsAndCleanUp();
255 ui::ShutdownInputMethod();
256 #if defined(OS_WIN)
257 ole_initializer_.reset(NULL);
258 #endif
259 #if defined(OS_ANDROID)
260 // Forcefully terminates the RunLoop inside MessagePumpForUI, ensuring
261 // proper shutdown for content_browsertests. Shutdown() is not used by
262 // the actual browser.
263 if (base::MessageLoop::current()->is_running())
264 base::MessageLoop::current()->QuitNow();
265 #endif
266 main_loop_.reset(NULL);
268 notification_service_.reset(NULL);
270 is_shutdown_ = true;
274 protected:
275 // True if we have started to initialize the runner.
276 bool initialization_started_;
278 // True if the runner has been shut down.
279 bool is_shutdown_;
281 scoped_ptr<NotificationServiceImpl> notification_service_;
282 scoped_ptr<BrowserMainLoop> main_loop_;
283 #if defined(OS_WIN)
284 scoped_ptr<ui::ScopedOleInitializer> ole_initializer_;
285 #endif
287 DISALLOW_COPY_AND_ASSIGN(BrowserMainRunnerImpl);
290 // static
291 BrowserMainRunner* BrowserMainRunner::Create() {
292 return new BrowserMainRunnerImpl();
295 } // namespace content