blob: e7381ae8ac12b82c7f535e57d02dcb4888bdd2f5 [file] [log] [blame]
[email protected]f573ed6b2012-02-10 15:58:521// 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"
[email protected]1cefd4b2013-11-20 21:55:4010#include "base/debug/leak_annotations.h"
[email protected]f573ed6b2012-02-10 15:58:5211#include "base/debug/trace_event.h"
12#include "base/logging.h"
13#include "base/metrics/histogram.h"
[email protected]567d30e2012-07-13 21:48:2914#include "base/metrics/statistics_recorder.h"
[email protected]f573ed6b2012-02-10 15:58:5215#include "content/browser/browser_main_loop.h"
[email protected]89af4002013-09-06 07:47:0716#include "content/browser/browser_shutdown_profile_dumper.h"
[email protected]f573ed6b2012-02-10 15:58:5217#include "content/browser/notification_service_impl.h"
[email protected]f573ed6b2012-02-10 15:58:5218#include "content/public/common/content_switches.h"
19#include "content/public/common/main_function_params.h"
[email protected]749bf6432013-06-12 16:00:0820#include "ui/base/ime/input_method_initializer.h"
[email protected]f573ed6b2012-02-10 15:58:5221
22#if defined(OS_WIN)
rsleevi25e2bc0a2014-09-24 03:12:5523#include "base/win/win_util.h"
[email protected]b68b51e2012-11-15 01:10:4524#include "base/win/windows_version.h"
rsleevi25e2bc0a2014-09-24 03:12:5525#include "net/cert/sha256_legacy_support_win.h"
26#include "sandbox/win/src/sidestep/preamble_patcher.h"
anantaacfcfce2014-10-15 01:14:1127#include "skia/ext/fontmgr_default_win.h"
28#include "third_party/skia/include/ports/SkFontMgr.h"
29#include "third_party/skia/include/ports/SkTypeface_win.h"
[email protected]10208ea2013-06-06 20:08:0330#include "ui/base/win/scoped_ole_initializer.h"
ananta9fd57542014-10-30 00:14:4331#include "ui/gfx/platform_font_win.h"
anantaacfcfce2014-10-15 01:14:1132#include "ui/gfx/switches.h"
33#include "ui/gfx/win/direct_write.h"
[email protected]f573ed6b2012-02-10 15:58:5234#endif
35
36bool g_exited_main_message_loop = false;
37
[email protected]46488322012-10-30 03:22:2038namespace content {
[email protected]eb398192012-10-22 20:16:1939
rsleevi25e2bc0a2014-09-24 03:12:5540#if defined(OS_WIN)
41namespace {
42
43// Pointer to the original CryptVerifyCertificateSignatureEx function.
44net::sha256_interception::CryptVerifyCertificateSignatureExFunc
45 g_real_crypt_verify_signature_stub = NULL;
46
47// Stub function that is called whenever the Crypt32 function
48// CryptVerifyCertificateSignatureEx is called. It just defers to net to perform
49// the actual verification.
50BOOL WINAPI CryptVerifyCertificateSignatureExStub(
51 HCRYPTPROV_LEGACY provider,
52 DWORD encoding_type,
53 DWORD subject_type,
54 void* subject_data,
55 DWORD issuer_type,
56 void* issuer_data,
57 DWORD flags,
58 void* extra) {
59 return net::sha256_interception::CryptVerifyCertificateSignatureExHook(
60 g_real_crypt_verify_signature_stub, provider, encoding_type, subject_type,
61 subject_data, issuer_type, issuer_data, flags, extra);
62}
63
64// If necessary, install an interception
65void InstallSha256LegacyHooks() {
66#if defined(_WIN64)
67 // Interception on x64 is not supported.
68 return;
69#else
70 if (base::win::MaybeHasSHA256Support())
71 return;
72
73 net::sha256_interception::CryptVerifyCertificateSignatureExFunc
74 cert_verify_signature_ptr = reinterpret_cast<
75 net::sha256_interception::CryptVerifyCertificateSignatureExFunc>(
76 ::GetProcAddress(::GetModuleHandle(L"crypt32.dll"),
77 "CryptVerifyCertificateSignatureEx"));
78 CHECK(cert_verify_signature_ptr);
79
80 DWORD old_protect = 0;
81 if (!::VirtualProtect(cert_verify_signature_ptr, 5, PAGE_EXECUTE_READWRITE,
82 &old_protect)) {
83 return;
84 }
85
86 g_real_crypt_verify_signature_stub =
87 reinterpret_cast<
88 net::sha256_interception::CryptVerifyCertificateSignatureExFunc>(
89 VirtualAllocEx(::GetCurrentProcess(), NULL,
90 sidestep::kMaxPreambleStubSize, MEM_COMMIT,
91 PAGE_EXECUTE_READWRITE));
92 if (g_real_crypt_verify_signature_stub == NULL) {
93 CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect,
94 &old_protect));
95 return;
96 }
97
98 sidestep::SideStepError patch_result =
99 sidestep::PreamblePatcher::Patch(
100 cert_verify_signature_ptr, CryptVerifyCertificateSignatureExStub,
101 g_real_crypt_verify_signature_stub, sidestep::kMaxPreambleStubSize);
102 if (patch_result != sidestep::SIDESTEP_SUCCESS) {
103 CHECK(::VirtualFreeEx(::GetCurrentProcess(),
104 g_real_crypt_verify_signature_stub, 0,
105 MEM_RELEASE));
106 CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect,
107 &old_protect));
108 return;
109 }
110
111 DWORD dummy = 0;
112 CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect, &dummy));
113 CHECK(::VirtualProtect(g_real_crypt_verify_signature_stub,
114 sidestep::kMaxPreambleStubSize, old_protect,
115 &old_protect));
116#endif // _WIN64
117}
118
anantaacfcfce2014-10-15 01:14:11119void MaybeEnableDirectWriteFontRendering() {
120 if (gfx::win::ShouldUseDirectWrite() &&
121 CommandLine::ForCurrentProcess()->HasSwitch(
122 switches::kEnableDirectWriteForUI) &&
ananta9fd57542014-10-30 00:14:43123 !CommandLine::ForCurrentProcess()->HasSwitch(
124 switches::kDisableHarfBuzzRenderText)) {
125 typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
126 HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll");
127 if (!dwrite_dll)
128 return;
129
130 DWriteCreateFactoryProc dwrite_create_factory_proc =
131 reinterpret_cast<DWriteCreateFactoryProc>(
132 GetProcAddress(dwrite_dll, "DWriteCreateFactory"));
133 // Not finding the DWriteCreateFactory function indicates a corrupt dll.
134 CHECK(dwrite_create_factory_proc);
135
136 IDWriteFactory* factory = NULL;
137
138 CHECK(SUCCEEDED(
139 dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_SHARED,
140 __uuidof(IDWriteFactory),
141 reinterpret_cast<IUnknown**>(&factory))));
142 SetDefaultSkiaFactory(SkFontMgr_New_DirectWrite(factory));
143 gfx::PlatformFontWin::set_direct_write_factory(factory);
anantaacfcfce2014-10-15 01:14:11144 }
145}
146
rsleevi25e2bc0a2014-09-24 03:12:55147} // namespace
148
149#endif // OS_WIN
150
[email protected]46488322012-10-30 03:22:20151class BrowserMainRunnerImpl : public BrowserMainRunner {
[email protected]f573ed6b2012-02-10 15:58:52152 public:
[email protected]232e09d2013-08-27 15:29:56153 BrowserMainRunnerImpl()
154 : initialization_started_(false), is_shutdown_(false) {}
[email protected]f573ed6b2012-02-10 15:58:52155
dchengc2282aa2014-10-21 12:07:58156 ~BrowserMainRunnerImpl() override {
[email protected]232e09d2013-08-27 15:29:56157 if (initialization_started_ && !is_shutdown_)
[email protected]f573ed6b2012-02-10 15:58:52158 Shutdown();
159 }
160
dchengc2282aa2014-10-21 12:07:58161 int Initialize(const MainFunctionParams& parameters) override {
[email protected]232e09d2013-08-27 15:29:56162 TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize");
163 // On Android we normally initialize the browser in a series of UI thread
164 // tasks. While this is happening a second request can come from the OS or
165 // another application to start the browser. If this happens then we must
166 // not run these parts of initialization twice.
167 if (!initialization_started_) {
168 initialization_started_ = true;
[email protected]f573ed6b2012-02-10 15:58:52169
[email protected]7951bca42013-06-17 20:01:30170#if !defined(OS_IOS)
[email protected]232e09d2013-08-27 15:29:56171 if (parameters.command_line.HasSwitch(switches::kWaitForDebugger))
172 base::debug::WaitForDebugger(60, true);
[email protected]7951bca42013-06-17 20:01:30173#endif
174
[email protected]091e96262012-09-12 15:35:10175#if defined(OS_WIN)
[email protected]b4b591bc2014-02-03 11:45:05176 if (base::win::GetVersion() < base::win::VERSION_VISTA) {
[email protected]232e09d2013-08-27 15:29:56177 // When "Extend support of advanced text services to all programs"
178 // (a.k.a. Cicero Unaware Application Support; CUAS) is enabled on
179 // Windows XP and handwriting modules shipped with Office 2003 are
180 // installed, "penjpn.dll" and "skchui.dll" will be loaded and then
[email protected]b4b591bc2014-02-03 11:45:05181 // crash unless a user installs Office 2003 SP3. To prevent these
182 // modules from being loaded, disable TSF entirely. crbug.com/160914.
[email protected]232e09d2013-08-27 15:29:56183 // TODO(yukawa): Add a high-level wrapper for this instead of calling
184 // Win32 API here directly.
185 ImmDisableTextFrameService(static_cast<DWORD>(-1));
186 }
rsleevi25e2bc0a2014-09-24 03:12:55187 InstallSha256LegacyHooks();
[email protected]091e96262012-09-12 15:35:10188#endif // OS_WIN
189
[email protected]232e09d2013-08-27 15:29:56190 base::StatisticsRecorder::Initialize();
[email protected]c4805102012-03-02 23:34:32191
[email protected]232e09d2013-08-27 15:29:56192 notification_service_.reset(new NotificationServiceImpl);
[email protected]f573ed6b2012-02-10 15:58:52193
[email protected]962a8482013-01-15 03:42:56194#if defined(OS_WIN)
[email protected]232e09d2013-08-27 15:29:56195 // Ole must be initialized before starting message pump, so that TSF
196 // (Text Services Framework) module can interact with the message pump
197 // on Windows 8 Metro mode.
198 ole_initializer_.reset(new ui::ScopedOleInitializer);
anantaacfcfce2014-10-15 01:14:11199 // Enable DirectWrite font rendering if needed.
200 MaybeEnableDirectWriteFontRendering();
[email protected]962a8482013-01-15 03:42:56201#endif // OS_WIN
202
[email protected]232e09d2013-08-27 15:29:56203 main_loop_.reset(new BrowserMainLoop(parameters));
[email protected]f573ed6b2012-02-10 15:58:52204
[email protected]232e09d2013-08-27 15:29:56205 main_loop_->Init();
[email protected]f573ed6b2012-02-10 15:58:52206
[email protected]232e09d2013-08-27 15:29:56207 main_loop_->EarlyInitialization();
[email protected]f573ed6b2012-02-10 15:58:52208
[email protected]232e09d2013-08-27 15:29:56209 // Must happen before we try to use a message loop or display any UI.
[email protected]d957b102014-04-25 20:17:19210 if (!main_loop_->InitializeToolkit())
211 return 1;
[email protected]f573ed6b2012-02-10 15:58:52212
[email protected]232e09d2013-08-27 15:29:56213 main_loop_->MainMessageLoopStart();
[email protected]f573ed6b2012-02-10 15:58:52214
[email protected]232e09d2013-08-27 15:29:56215// WARNING: If we get a WM_ENDSESSION, objects created on the stack here
216// are NOT deleted. If you need something to run during WM_ENDSESSION add it
217// to browser_shutdown::Shutdown or BrowserProcess::EndSession.
[email protected]f573ed6b2012-02-10 15:58:52218
[email protected]749bf6432013-06-12 16:00:08219#if defined(OS_WIN) && !defined(NO_TCMALLOC)
[email protected]232e09d2013-08-27 15:29:56220 // When linking shared libraries, NO_TCMALLOC is defined, and dynamic
221 // allocator selection is not supported.
[email protected]f573ed6b2012-02-10 15:58:52222
[email protected]232e09d2013-08-27 15:29:56223 // Make this call before going multithreaded, or spawning any
224 // subprocesses.
225 base::allocator::SetupSubprocessAllocator();
[email protected]f573ed6b2012-02-10 15:58:52226#endif
[email protected]232e09d2013-08-27 15:29:56227 ui::InitializeInputMethod();
228 }
[email protected]57624ab2013-08-01 16:01:51229 main_loop_->CreateStartupTasks();
[email protected]f573ed6b2012-02-10 15:58:52230 int result_code = main_loop_->GetResultCode();
231 if (result_code > 0)
232 return result_code;
[email protected]f573ed6b2012-02-10 15:58:52233
234 // Return -1 to indicate no early termination.
235 return -1;
236 }
237
dchengc2282aa2014-10-21 12:07:58238 int Run() override {
[email protected]232e09d2013-08-27 15:29:56239 DCHECK(initialization_started_);
[email protected]f573ed6b2012-02-10 15:58:52240 DCHECK(!is_shutdown_);
241 main_loop_->RunMainMessageLoopParts();
242 return main_loop_->GetResultCode();
243 }
244
dchengc2282aa2014-10-21 12:07:58245 void Shutdown() override {
[email protected]232e09d2013-08-27 15:29:56246 DCHECK(initialization_started_);
[email protected]f573ed6b2012-02-10 15:58:52247 DCHECK(!is_shutdown_);
[email protected]1cefd4b2013-11-20 21:55:40248#ifdef LEAK_SANITIZER
249 // Invoke leak detection now, to avoid dealing with shutdown-only leaks.
250 // Normally this will have already happened in
251 // BroserProcessImpl::ReleaseModule(), so this call has no effect. This is
252 // only for processes which do not instantiate a BrowserProcess.
253 // If leaks are found, the process will exit here.
254 __lsan_do_leak_check();
255#endif
[email protected]cec95632014-07-02 18:01:50256 // If startup tracing has not been finished yet, replace it's dumper
257 // with special version, which would save trace file on exit (i.e.
258 // startup tracing becomes a version of shutdown tracing).
259 scoped_ptr<BrowserShutdownProfileDumper> startup_profiler;
260 if (main_loop_->is_tracing_startup()) {
261 main_loop_->StopStartupTracingTimer();
262 if (main_loop_->startup_trace_file() !=
263 base::FilePath().AppendASCII("none")) {
264 startup_profiler.reset(
265 new BrowserShutdownProfileDumper(main_loop_->startup_trace_file()));
266 }
267 }
268
[email protected]89af4002013-09-06 07:47:07269 // The shutdown tracing got enabled in AttemptUserExit earlier, but someone
270 // needs to write the result to disc. For that a dumper needs to get created
271 // which will dump the traces to disc when it gets destroyed.
[email protected]479278702014-08-11 20:32:09272 const base::CommandLine& command_line =
273 *base::CommandLine::ForCurrentProcess();
[email protected]cec95632014-07-02 18:01:50274 scoped_ptr<BrowserShutdownProfileDumper> shutdown_profiler;
275 if (command_line.HasSwitch(switches::kTraceShutdown)) {
276 shutdown_profiler.reset(new BrowserShutdownProfileDumper(
277 BrowserShutdownProfileDumper::GetShutdownProfileFileName()));
278 }
[email protected]f573ed6b2012-02-10 15:58:52279
[email protected]89af4002013-09-06 07:47:07280 {
281 // The trace event has to stay between profiler creation and destruction.
282 TRACE_EVENT0("shutdown", "BrowserMainRunner");
283 g_exited_main_message_loop = true;
[email protected]f573ed6b2012-02-10 15:58:52284
[email protected]89af4002013-09-06 07:47:07285 main_loop_->ShutdownThreadsAndCleanUp();
[email protected]f573ed6b2012-02-10 15:58:52286
[email protected]89af4002013-09-06 07:47:07287 ui::ShutdownInputMethod();
288 #if defined(OS_WIN)
289 ole_initializer_.reset(NULL);
290 #endif
[email protected]d2cdd962014-06-18 09:04:32291 #if defined(OS_ANDROID)
292 // Forcefully terminates the RunLoop inside MessagePumpForUI, ensuring
293 // proper shutdown for content_browsertests. Shutdown() is not used by
294 // the actual browser.
295 base::MessageLoop::current()->QuitNow();
296 #endif
[email protected]89af4002013-09-06 07:47:07297 main_loop_.reset(NULL);
[email protected]f573ed6b2012-02-10 15:58:52298
[email protected]89af4002013-09-06 07:47:07299 notification_service_.reset(NULL);
300
301 is_shutdown_ = true;
302 }
[email protected]f573ed6b2012-02-10 15:58:52303 }
304
305 protected:
[email protected]232e09d2013-08-27 15:29:56306 // True if we have started to initialize the runner.
307 bool initialization_started_;
[email protected]f573ed6b2012-02-10 15:58:52308
309 // True if the runner has been shut down.
310 bool is_shutdown_;
311
[email protected]f573ed6b2012-02-10 15:58:52312 scoped_ptr<NotificationServiceImpl> notification_service_;
[email protected]46488322012-10-30 03:22:20313 scoped_ptr<BrowserMainLoop> main_loop_;
[email protected]f573ed6b2012-02-10 15:58:52314#if defined(OS_WIN)
[email protected]e000ac92012-10-01 18:20:48315 scoped_ptr<ui::ScopedOleInitializer> ole_initializer_;
[email protected]f573ed6b2012-02-10 15:58:52316#endif
[email protected]f573ed6b2012-02-10 15:58:52317
318 DISALLOW_COPY_AND_ASSIGN(BrowserMainRunnerImpl);
319};
320
[email protected]f573ed6b2012-02-10 15:58:52321// static
322BrowserMainRunner* BrowserMainRunner::Create() {
323 return new BrowserMainRunnerImpl();
324}
325
326} // namespace content