15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_main_runner.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/allocator/allocator_shim.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_switches.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/debug/leak_annotations.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/statistics_recorder.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/browser_main_loop.h"
1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/browser/browser_shutdown_profile_dumper.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/notification_service_impl.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/main_function_params.h"
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/base/ime/input_method_initializer.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/win/win_util.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/windows_version.h"
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/cert/sha256_legacy_support_win.h"
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "sandbox/win/src/sidestep/preamble_patcher.h"
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/base/win/scoped_ole_initializer.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_exited_main_message_loop = false;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_WIN)
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace {
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Pointer to the original CryptVerifyCertificateSignatureEx function.
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinet::sha256_interception::CryptVerifyCertificateSignatureExFunc
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    g_real_crypt_verify_signature_stub = NULL;
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Stub function that is called whenever the Crypt32 function
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// CryptVerifyCertificateSignatureEx is called. It just defers to net to perform
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// the actual verification.
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBOOL WINAPI CryptVerifyCertificateSignatureExStub(
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    HCRYPTPROV_LEGACY provider,
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DWORD encoding_type,
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DWORD subject_type,
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* subject_data,
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DWORD issuer_type,
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* issuer_data,
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DWORD flags,
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* extra) {
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return net::sha256_interception::CryptVerifyCertificateSignatureExHook(
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      g_real_crypt_verify_signature_stub, provider, encoding_type, subject_type,
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      subject_data, issuer_type, issuer_data, flags, extra);
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// If necessary, install an interception
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid InstallSha256LegacyHooks() {
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(_WIN64)
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Interception on x64 is not supported.
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return;
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (base::win::MaybeHasSHA256Support())
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::sha256_interception::CryptVerifyCertificateSignatureExFunc
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      cert_verify_signature_ptr = reinterpret_cast<
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          net::sha256_interception::CryptVerifyCertificateSignatureExFunc>(
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              ::GetProcAddress(::GetModuleHandle(L"crypt32.dll"),
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               "CryptVerifyCertificateSignatureEx"));
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(cert_verify_signature_ptr);
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DWORD old_protect = 0;
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!::VirtualProtect(cert_verify_signature_ptr, 5, PAGE_EXECUTE_READWRITE,
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        &old_protect)) {
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_real_crypt_verify_signature_stub =
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      reinterpret_cast<
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          net::sha256_interception::CryptVerifyCertificateSignatureExFunc>(
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              VirtualAllocEx(::GetCurrentProcess(), NULL,
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             sidestep::kMaxPreambleStubSize, MEM_COMMIT,
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             PAGE_EXECUTE_READWRITE));
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (g_real_crypt_verify_signature_stub == NULL) {
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect,
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                           &old_protect));
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  sidestep::SideStepError patch_result =
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      sidestep::PreamblePatcher::Patch(
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          cert_verify_signature_ptr, CryptVerifyCertificateSignatureExStub,
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          g_real_crypt_verify_signature_stub, sidestep::kMaxPreambleStubSize);
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (patch_result != sidestep::SIDESTEP_SUCCESS) {
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CHECK(::VirtualFreeEx(::GetCurrentProcess(),
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          g_real_crypt_verify_signature_stub, 0,
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          MEM_RELEASE));
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect,
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                           &old_protect));
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DWORD dummy = 0;
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect, &dummy));
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(::VirtualProtect(g_real_crypt_verify_signature_stub,
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         sidestep::kMaxPreambleStubSize, old_protect,
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         &old_protect));
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif  // _WIN64
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif  // OS_WIN
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BrowserMainRunnerImpl : public BrowserMainRunner {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  BrowserMainRunnerImpl()
120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      : initialization_started_(false), is_shutdown_(false) {}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~BrowserMainRunnerImpl() {
123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (initialization_started_ && !is_shutdown_)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Shutdown();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
127424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual int Initialize(const MainFunctionParams& parameters) OVERRIDE {
128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize");
129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // On Android we normally initialize the browser in a series of UI thread
130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // tasks. While this is happening a second request can come from the OS or
131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // another application to start the browser. If this happens then we must
132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // not run these parts of initialization twice.
133424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (!initialization_started_) {
134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      initialization_started_ = true;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if !defined(OS_IOS)
137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (parameters.command_line.HasSwitch(switches::kWaitForDebugger))
138424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::debug::WaitForDebugger(60, true);
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (base::win::GetVersion() < base::win::VERSION_VISTA) {
143424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        // When "Extend support of advanced text services to all programs"
144424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        // (a.k.a. Cicero Unaware Application Support; CUAS) is enabled on
145424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        // Windows XP and handwriting modules shipped with Office 2003 are
146424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        // installed, "penjpn.dll" and "skchui.dll" will be loaded and then
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // crash unless a user installs Office 2003 SP3. To prevent these
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // modules from being loaded, disable TSF entirely. crbug.com/160914.
149424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        // TODO(yukawa): Add a high-level wrapper for this instead of calling
150424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        // Win32 API here directly.
151424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        ImmDisableTextFrameService(static_cast<DWORD>(-1));
152424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      }
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      InstallSha256LegacyHooks();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_WIN
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
156424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::StatisticsRecorder::Initialize();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
158424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      notification_service_.reset(new NotificationServiceImpl);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Ole must be initialized before starting message pump, so that TSF
162424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // (Text Services Framework) module can interact with the message pump
163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // on Windows 8 Metro mode.
164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      ole_initializer_.reset(new ui::ScopedOleInitializer);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // OS_WIN
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
167424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      main_loop_.reset(new BrowserMainLoop(parameters));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
169424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      main_loop_->Init();
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
171424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      main_loop_->EarlyInitialization();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
173424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Must happen before we try to use a message loop or display any UI.
1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (!main_loop_->InitializeToolkit())
1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        return 1;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      main_loop_->MainMessageLoopStart();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
179424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// WARNING: If we get a WM_ENDSESSION, objects created on the stack here
180424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// are NOT deleted. If you need something to run during WM_ENDSESSION add it
181424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// to browser_shutdown::Shutdown or BrowserProcess::EndSession.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_WIN) && !defined(NO_TCMALLOC)
184424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // When linking shared libraries, NO_TCMALLOC is defined, and dynamic
185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // allocator selection is not supported.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
187424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Make this call before going multithreaded, or spawning any
188424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // subprocesses.
189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::allocator::SetupSubprocessAllocator();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
191424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      ui::InitializeInputMethod();
192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    main_loop_->CreateStartupTasks();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result_code = main_loop_->GetResultCode();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result_code > 0)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result_code;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Return -1 to indicate no early termination.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int Run() OVERRIDE {
203424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    DCHECK(initialization_started_);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!is_shutdown_);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    main_loop_->RunMainMessageLoopParts();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return main_loop_->GetResultCode();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Shutdown() OVERRIDE {
210424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    DCHECK(initialization_started_);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!is_shutdown_);
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#ifdef LEAK_SANITIZER
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Invoke leak detection now, to avoid dealing with shutdown-only leaks.
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Normally this will have already happened in
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // BroserProcessImpl::ReleaseModule(), so this call has no effect. This is
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // only for processes which do not instantiate a BrowserProcess.
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // If leaks are found, the process will exit here.
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    __lsan_do_leak_check();
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // If startup tracing has not been finished yet, replace it's dumper
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // with special version, which would save trace file on exit (i.e.
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // startup tracing becomes a version of shutdown tracing).
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<BrowserShutdownProfileDumper> startup_profiler;
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (main_loop_->is_tracing_startup()) {
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      main_loop_->StopStartupTracingTimer();
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (main_loop_->startup_trace_file() !=
227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          base::FilePath().AppendASCII("none")) {
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        startup_profiler.reset(
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            new BrowserShutdownProfileDumper(main_loop_->startup_trace_file()));
230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // The shutdown tracing got enabled in AttemptUserExit earlier, but someone
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // needs to write the result to disc. For that a dumper needs to get created
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // which will dump the traces to disc when it gets destroyed.
2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const base::CommandLine& command_line =
2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        *base::CommandLine::ForCurrentProcess();
238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<BrowserShutdownProfileDumper> shutdown_profiler;
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (command_line.HasSwitch(switches::kTraceShutdown)) {
240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      shutdown_profiler.reset(new BrowserShutdownProfileDumper(
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          BrowserShutdownProfileDumper::GetShutdownProfileFileName()));
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    {
24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // The trace event has to stay between profiler creation and destruction.
24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      TRACE_EVENT0("shutdown", "BrowserMainRunner");
24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      g_exited_main_message_loop = true;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      main_loop_->ShutdownThreadsAndCleanUp();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ui::ShutdownInputMethod();
25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  #if defined(OS_WIN)
25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ole_initializer_.reset(NULL);
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  #endif
255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  #if defined(OS_ANDROID)
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // Forcefully terminates the RunLoop inside MessagePumpForUI, ensuring
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // proper shutdown for content_browsertests. Shutdown() is not used by
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // the actual browser.
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      base::MessageLoop::current()->QuitNow();
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  #endif
26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      main_loop_.reset(NULL);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      notification_service_.reset(NULL);
26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      is_shutdown_ = true;
26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
270424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // True if we have started to initialize the runner.
271424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  bool initialization_started_;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the runner has been shut down.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_shutdown_;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<NotificationServiceImpl> notification_service_;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BrowserMainLoop> main_loop_;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::ScopedOleInitializer> ole_initializer_;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BrowserMainRunnerImpl);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserMainRunner* BrowserMainRunner::Create() {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new BrowserMainRunnerImpl();
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
291