diff options
Diffstat (limited to 'chromium/content/app/content_main_runner.cc')
-rw-r--r-- | chromium/content/app/content_main_runner.cc | 261 |
1 files changed, 115 insertions, 146 deletions
diff --git a/chromium/content/app/content_main_runner.cc b/chromium/content/app/content_main_runner.cc index 776417d58f9..38bf1cb3260 100644 --- a/chromium/content/app/content_main_runner.cc +++ b/chromium/content/app/content_main_runner.cc @@ -16,6 +16,7 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" #include "base/metrics/stats_table.h" #include "base/path_service.h" #include "base/process/launch.h" @@ -26,15 +27,13 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "content/browser/browser_main.h" -#include "content/browser/gpu/gpu_process_host.h" #include "content/common/set_process_title.h" #include "content/common/url_schemes.h" #include "content/gpu/in_process_gpu_thread.h" +#include "content/public/app/content_main.h" #include "content/public/app/content_main_delegate.h" #include "content/public/app/startup_helper_win.h" #include "content/public/browser/content_browser_client.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/utility_process_host.h" #include "content/public/common/content_client.h" #include "content/public/common/content_constants.h" #include "content/public/common/content_paths.h" @@ -44,13 +43,16 @@ #include "content/renderer/in_process_renderer_thread.h" #include "content/utility/in_process_utility_thread.h" #include "crypto/nss_util.h" +#include "ipc/ipc_descriptors.h" #include "ipc/ipc_switches.h" #include "media/base/media.h" #include "sandbox/win/src/sandbox_types.h" #include "ui/base/ui_base_paths.h" #include "ui/base/ui_base_switches.h" -#include "ui/gfx/win/dpi.h" -#include "webkit/common/user_agent/user_agent.h" + +#if defined(OS_ANDROID) +#include "content/public/common/content_descriptors.h" +#endif #if defined(USE_TCMALLOC) #include "third_party/tcmalloc/chromium/src/gperftools/malloc_extension.h" @@ -61,16 +63,23 @@ #endif #if !defined(OS_IOS) +#include "content/app/mojo/mojo_init.h" +#include "content/browser/gpu/gpu_process_host.h" +#include "content/browser/renderer_host/render_process_host_impl.h" +#include "content/browser/utility_process_host_impl.h" #include "content/public/plugin/content_plugin_client.h" #include "content/public/renderer/content_renderer_client.h" #include "content/public/utility/content_utility_client.h" #endif #if defined(OS_WIN) -#include <atlbase.h> -#include <atlapp.h> #include <malloc.h> #include <cstring> + +#include "base/strings/string_number_conversions.h" +#include "ui/base/win/atl_module.h" +#include "ui/base/win/dpi_setup.h" +#include "ui/gfx/win/dpi.h" #elif defined(OS_MACOSX) #include "base/mac/scoped_nsautorelease_pool.h" #if !defined(OS_IOS) @@ -104,7 +113,9 @@ int tc_set_new_mode(int mode); namespace content { extern int GpuMain(const content::MainFunctionParams&); #if defined(ENABLE_PLUGINS) +#if !defined(OS_LINUX) extern int PluginMain(const content::MainFunctionParams&); +#endif extern int PpapiPluginMain(const MainFunctionParams&); extern int PpapiBrokerMain(const MainFunctionParams&); #endif @@ -113,64 +124,6 @@ extern int UtilityMain(const MainFunctionParams&); extern int WorkerMain(const MainFunctionParams&); } // namespace content -namespace { -#if defined(OS_WIN) -// In order to have Theme support, we need to connect to the theme service. -// This needs to be done before we lock down the process. Officially this -// can be done with OpenThemeData() but it fails unless you pass a valid -// window at least the first time. Interestingly, the very act of creating a -// window also sets the connection to the theme service. -void EnableThemeSupportOnAllWindowStations() { - HDESK desktop_handle = ::OpenInputDesktop(0, FALSE, READ_CONTROL); - if (desktop_handle) { - // This means we are running in an input desktop, which implies WinSta0. - ::CloseDesktop(desktop_handle); - return; - } - - HWINSTA current_station = ::GetProcessWindowStation(); - DCHECK(current_station); - - HWINSTA winsta0 = ::OpenWindowStationA("WinSta0", FALSE, GENERIC_READ); - if (!winsta0) { - DVLOG(0) << "Unable to open to WinSta0, we: "<< ::GetLastError(); - return; - } - if (!::SetProcessWindowStation(winsta0)) { - // Could not set the alternate window station. There is a possibility - // that the theme wont be correctly initialized. - NOTREACHED() << "Unable to switch to WinSta0, we: "<< ::GetLastError(); - ::CloseWindowStation(winsta0); - return; - } - - HWND window = ::CreateWindowExW(0, L"Static", L"", WS_POPUP | WS_DISABLED, - CW_USEDEFAULT, 0, 0, 0, HWND_MESSAGE, NULL, - ::GetModuleHandleA(NULL), NULL); - if (!window) { - DLOG(WARNING) << "failed to enable theme support"; - } else { - ::DestroyWindow(window); - window = NULL; - } - - // Revert the window station. - if (!::SetProcessWindowStation(current_station)) { - // We failed to switch back to the secure window station. This might - // confuse the process enough that we should kill it now. - LOG(FATAL) << "Failed to restore alternate window station"; - } - - if (!::CloseWindowStation(winsta0)) { - // We might be leaking a winsta0 handle. This is a security risk, but - // since we allow fail over to no desktop protection in low memory - // condition, this is not a big risk. - NOTREACHED(); - } -} -#endif // defined(OS_WIN) -} // namespace - namespace content { base::LazyInstance<ContentBrowserClient> @@ -186,8 +139,6 @@ base::LazyInstance<ContentUtilityClient> #if defined(OS_WIN) -static CAppModule _Module; - #endif // defined(OS_WIN) #if defined(OS_POSIX) && !defined(OS_IOS) @@ -238,11 +189,11 @@ void CommonSubprocessInit(const std::string& process_type) { #endif } +// Only needed on Windows for creating stats tables. +#if defined(OS_WIN) static base::ProcessId GetBrowserPid(const CommandLine& command_line) { base::ProcessId browser_pid = base::GetCurrentProcId(); -#if !defined(OS_IOS) if (command_line.HasSwitch(switches::kProcessChannelID)) { -#if defined(OS_WIN) || defined(OS_MACOSX) std::string channel_name = command_line.GetSwitchValueASCII(switches::kProcessChannelID); @@ -250,27 +201,10 @@ static base::ProcessId GetBrowserPid(const CommandLine& command_line) { base::StringToInt(channel_name, &browser_pid_int); browser_pid = static_cast<base::ProcessId>(browser_pid_int); DCHECK_NE(browser_pid_int, 0); -#elif defined(OS_ANDROID) - // On Android, the browser process isn't the parent. A bunch - // of work will be required before callers of this routine will - // get what they want. - // - // Note: On Linux, base::GetParentProcessId() is defined in - // process_util_linux.cc. Note that *_linux.cc is excluded from - // Android builds but a special exception is made in base.gypi - // for a few files including process_util_linux.cc. - LOG(ERROR) << "GetBrowserPid() not implemented for Android()."; -#elif defined(OS_POSIX) - // On linux, we're in a process forked from the zygote here; so we need the - // parent's parent process' id. - browser_pid = - base::GetParentProcessId( - base::GetParentProcessId(base::GetCurrentProcId())); -#endif } -#endif // !OS_IOS return browser_pid; } +#endif static void InitializeStatsTable(const CommandLine& command_line) { // Initialize the Stats Counters table. With this initialized, @@ -281,11 +215,25 @@ static void InitializeStatsTable(const CommandLine& command_line) { if (command_line.HasSwitch(switches::kEnableStatsTable)) { // NOTIMPLEMENTED: we probably need to shut this down correctly to avoid // leaking shared memory regions on posix platforms. - std::string statsfile = +#if defined(OS_POSIX) + // Stats table is in the global file descriptors table on Posix. + base::GlobalDescriptors* global_descriptors = + base::GlobalDescriptors::GetInstance(); + base::FileDescriptor table_ident; + if (global_descriptors->MaybeGet(kStatsTableSharedMemFd) != -1) { + // Open the shared memory file descriptor passed by the browser process. + table_ident = base::FileDescriptor( + global_descriptors->Get(kStatsTableSharedMemFd), false); + } +#elif defined(OS_WIN) + // Stats table is in a named segment on Windows. Use the PID to make this + // unique on the system. + std::string table_ident = base::StringPrintf("%s-%u", kStatsFilename, static_cast<unsigned int>(GetBrowserPid(command_line))); - base::StatsTable* stats_table = new base::StatsTable(statsfile, - kStatsMaxThreads, kStatsMaxCounters); +#endif + base::StatsTable* stats_table = + new base::StatsTable(table_ident, kStatsMaxThreads, kStatsMaxCounters); base::StatsTable::set_current(stats_table); } } @@ -355,9 +303,9 @@ int RunZygote(const MainFunctionParams& main_function_params, { switches::kUtilityProcess, UtilityMain }, }; - scoped_ptr<ZygoteForkDelegate> zygote_fork_delegate; + ScopedVector<ZygoteForkDelegate> zygote_fork_delegates; if (delegate) { - zygote_fork_delegate.reset(delegate->ZygoteStarting()); + delegate->ZygoteStarting(&zygote_fork_delegates); // Each Renderer we spawn will re-attempt initialization of the media // libraries, at which point failure will be detected and handled, so // we do not need to cope with initialization failures here. @@ -367,7 +315,7 @@ int RunZygote(const MainFunctionParams& main_function_params, } // This function call can return multiple times, once per fork(). - if (!ZygoteMain(main_function_params, zygote_fork_delegate.get())) + if (!ZygoteMain(main_function_params, zygote_fork_delegates.Pass())) return 1; if (delegate) delegate->ZygoteForked(); @@ -379,14 +327,6 @@ int RunZygote(const MainFunctionParams& main_function_params, command_line.GetSwitchValueASCII(switches::kProcessType); ContentClientInitializer::Set(process_type, delegate); - // If a custom user agent was passed on the command line, we need - // to (re)set it now, rather than using the default one the zygote - // initialized. - if (command_line.HasSwitch(switches::kUserAgent)) { - webkit_glue::SetUserAgent( - command_line.GetSwitchValueASCII(switches::kUserAgent), true); - } - // The StatsTable must be initialized in each process; we already // initialized for the browser process, now we need to initialize // within the new processes as well. @@ -410,9 +350,9 @@ int RunZygote(const MainFunctionParams& main_function_params, #if !defined(OS_IOS) static void RegisterMainThreadFactories() { #if !defined(CHROME_MULTIPLE_DLL_BROWSER) - UtilityProcessHost::RegisterUtilityMainThreadFactory( + UtilityProcessHostImpl::RegisterUtilityMainThreadFactory( CreateInProcessUtilityThread); - RenderProcessHost::RegisterRendererMainThreadFactory( + RenderProcessHostImpl::RegisterRendererMainThreadFactory( CreateInProcessRendererThread); GpuProcessHost::RegisterGpuMainThreadFactory( CreateInProcessGpuThread); @@ -442,7 +382,9 @@ int RunNamedProcessTypeMain( #endif #if !defined(CHROME_MULTIPLE_DLL_BROWSER) #if defined(ENABLE_PLUGINS) +#if !defined(OS_LINUX) { switches::kPluginProcess, PluginMain }, +#endif { switches::kWorkerProcess, WorkerMain }, { switches::kPpapiPluginProcess, PpapiPluginMain }, { switches::kPpapiBrokerProcess, PpapiBrokerMain }, @@ -497,7 +439,8 @@ class ContentMainRunnerImpl : public ContentMainRunner { : is_initialized_(false), is_shutdown_(false), completed_basic_startup_(false), - delegate_(NULL) { + delegate_(NULL), + ui_task_(NULL) { #if defined(OS_WIN) memset(&sandbox_info_, 0, sizeof(sandbox_info_)); #endif @@ -533,22 +476,15 @@ class ContentMainRunnerImpl : public ContentMainRunner { } #endif -#if defined(OS_WIN) - virtual int Initialize(HINSTANCE instance, - sandbox::SandboxInterfaceInfo* sandbox_info, - ContentMainDelegate* delegate) OVERRIDE { - // argc/argv are ignored on Windows; see command_line.h for details. - int argc = 0; - char** argv = NULL; + virtual int Initialize(const ContentMainParams& params) OVERRIDE { + ui_task_ = params.ui_task; +#if defined(OS_WIN) RegisterInvalidParamHandler(); - _Module.Init(NULL, static_cast<HINSTANCE>(instance)); + ui::win::CreateATLModuleIfNeeded(); - sandbox_info_ = *sandbox_info; + sandbox_info_ = *params.sandbox_info; #else // !OS_WIN - virtual int Initialize(int argc, - const char** argv, - ContentMainDelegate* delegate) OVERRIDE { #if defined(OS_ANDROID) // See note at the initialization of ExitManager, below; basically, @@ -590,7 +526,7 @@ class ContentMainRunnerImpl : public ContentMainRunner { MallocExtension::GetBytesAllocatedOnCurrentThread, tracked_objects::TIME_SOURCE_TYPE_TCMALLOC); } -#endif +#endif // !OS_MACOSX && USE_TCMALLOC // On Android, // - setlocale() is not supported. @@ -618,7 +554,7 @@ class ContentMainRunnerImpl : public ContentMainRunner { #endif // !OS_WIN is_initialized_ = true; - delegate_ = delegate; + delegate_ = params.delegate; base::EnableTerminationOnHeapCorruption(); base::EnableTerminationOnOutOfMemory(); @@ -629,7 +565,12 @@ class ContentMainRunnerImpl : public ContentMainRunner { // A consequence of this is that you can't use the ctor/dtor-based // TRACE_EVENT methods on Linux or iOS builds till after we set this up. #if !defined(OS_ANDROID) && !defined(OS_IOS) - exit_manager_.reset(new base::AtExitManager); + if (!ui_task_) { + // When running browser tests, don't create a second AtExitManager as that + // interfers with shutdown when objects created before ContentMain is + // called are destructed when it returns. + exit_manager_.reset(new base::AtExitManager); + } #endif // !OS_ANDROID && !OS_IOS #if defined(OS_MACOSX) @@ -643,11 +584,25 @@ class ContentMainRunnerImpl : public ContentMainRunner { // On Android, the command line is initialized when library is loaded and // we have already started our TRACE_EVENT0. #if !defined(OS_ANDROID) + // argc/argv are ignored on Windows and Android; see command_line.h for + // details. + int argc = 0; + const char** argv = NULL; + +#if !defined(OS_WIN) + argc = params.argc; + argv = params.argv; +#endif + CommandLine::Init(argc, argv); + +#if !defined(OS_IOS) + SetProcessTitleFromCommandLine(argv); +#endif #endif // !OS_ANDROID int exit_code; - if (delegate && delegate->BasicStartupComplete(&exit_code)) + if (delegate_ && delegate_->BasicStartupComplete(&exit_code)) return exit_code; completed_basic_startup_ = true; @@ -656,6 +611,11 @@ class ContentMainRunnerImpl : public ContentMainRunner { std::string process_type = command_line.GetSwitchValueASCII(switches::kProcessType); +#if !defined(OS_IOS) + // Initialize mojo here so that services can be registered. + InitializeMojo(); +#endif + if (!GetContentClient()) SetContentClient(&empty_content_client_); ContentClientInitializer::Set(process_type, delegate_); @@ -673,6 +633,7 @@ class ContentMainRunnerImpl : public ContentMainRunner { command_line.GetSwitchValueASCII(switches::kTraceStartup)); base::debug::TraceLog::GetInstance()->SetEnabled( category_filter, + base::debug::TraceLog::RECORDING_MODE, base::debug::TraceLog::RECORD_UNTIL_FULL); } #if !defined(OS_ANDROID) @@ -688,22 +649,32 @@ class ContentMainRunnerImpl : public ContentMainRunner { // It's important not to allocate the ports for processes which don't // register with the power monitor - see crbug.com/88867. if (process_type.empty() || - (delegate && - delegate->ProcessRegistersWithSystemProcess(process_type))) { + (delegate_ && + delegate_->ProcessRegistersWithSystemProcess(process_type))) { base::PowerMonitorDeviceSource::AllocateSystemIOPorts(); } if (!process_type.empty() && - (!delegate || delegate->ShouldSendMachPort(process_type))) { + (!delegate_ || delegate_->ShouldSendMachPort(process_type))) { MachBroker::ChildSendTaskPortToParent(); } #elif defined(OS_WIN) if (command_line.HasSwitch(switches::kEnableHighResolutionTime)) base::TimeTicks::SetNowIsHighResNowIfSupported(); - // This must be done early enough since some helper functions like - // IsTouchEnabled, needed to load resources, may call into the theme dll. - EnableThemeSupportOnAllWindowStations(); + bool init_device_scale_factor = true; + if (command_line.HasSwitch(switches::kDeviceScaleFactor)) { + std::string scale_factor_string = command_line.GetSwitchValueASCII( + switches::kDeviceScaleFactor); + double scale_factor = 0; + if (base::StringToDouble(scale_factor_string, &scale_factor)) { + init_device_scale_factor = false; + gfx::InitDeviceScaleFactor(scale_factor); + } + } + if (init_device_scale_factor) + ui::win::InitDeviceScaleFactor(); + SetupCRT(command_line); #endif @@ -733,30 +704,31 @@ class ContentMainRunnerImpl : public ContentMainRunner { RegisterPathProvider(); RegisterContentSchemes(true); +#if defined(OS_ANDROID) + int icudata_fd = base::GlobalDescriptors::GetInstance()->MaybeGet( + kAndroidICUDataDescriptor); + if (icudata_fd != -1) + CHECK(base::i18n::InitializeICUWithFileDescriptor(icudata_fd)); + else + CHECK(base::i18n::InitializeICU()); +#else CHECK(base::i18n::InitializeICU()); +#endif InitializeStatsTable(command_line); - if (delegate) - delegate->PreSandboxStartup(); - - // Set any custom user agent passed on the command line now so the string - // doesn't change between calls to webkit_glue::GetUserAgent(), otherwise it - // defaults to the user agent set during SetContentClient(). - if (command_line.HasSwitch(switches::kUserAgent)) { - webkit_glue::SetUserAgent( - command_line.GetSwitchValueASCII(switches::kUserAgent), true); - } + if (delegate_) + delegate_->PreSandboxStartup(); if (!process_type.empty()) CommonSubprocessInit(process_type); #if defined(OS_WIN) - CHECK(InitializeSandbox(sandbox_info)); + CHECK(InitializeSandbox(params.sandbox_info)); #elif defined(OS_MACOSX) && !defined(OS_IOS) if (process_type == switches::kRendererProcess || process_type == switches::kPpapiPluginProcess || - (delegate && delegate->DelaySandboxInitialization(process_type))) { + (delegate_ && delegate_->DelaySandboxInitialization(process_type))) { // On OS X the renderer sandbox needs to be initialized later in the // startup sequence in RendererMainPlatformDelegate::EnableSandbox(). } else { @@ -764,12 +736,8 @@ class ContentMainRunnerImpl : public ContentMainRunner { } #endif - if (delegate) - delegate->SandboxInitialized(process_type); - -#if defined(OS_POSIX) && !defined(OS_IOS) - SetProcessTitleFromCommandLine(argv); -#endif + if (delegate_) + delegate_->SandboxInitialized(process_type); // Return -1 to indicate no early termination. return -1; @@ -783,6 +751,7 @@ class ContentMainRunnerImpl : public ContentMainRunner { command_line.GetSwitchValueASCII(switches::kProcessType); MainFunctionParams main_params(command_line); + main_params.ui_task = ui_task_; #if defined(OS_WIN) main_params.sandbox_info = &sandbox_info_; #elif defined(OS_MACOSX) @@ -812,8 +781,6 @@ class ContentMainRunnerImpl : public ContentMainRunner { #ifdef _CRTDBG_MAP_ALLOC _CrtDumpMemoryLeaks(); #endif // _CRTDBG_MAP_ALLOC - - _Module.Term(); #endif // OS_WIN #if defined(OS_MACOSX) @@ -849,6 +816,8 @@ class ContentMainRunnerImpl : public ContentMainRunner { scoped_ptr<base::mac::ScopedNSAutoreleasePool> autorelease_pool_; #endif + base::Closure* ui_task_; + DISALLOW_COPY_AND_ASSIGN(ContentMainRunnerImpl); }; |