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 <stdint.h>
6 
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/command_line.h"
10 #include "base/time/time.h"
11 #include "build/build_config.h"
12 #include "chrome/app/chrome_main_delegate.h"
13 #include "chrome/common/buildflags.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/profiler/main_thread_stack_sampling_profiler.h"
16 #include "content/public/app/content_main.h"
17 #include "content/public/common/content_switches.h"
18 #include "headless/public/headless_shell.h"
19 #include "ui/gfx/switches.h"
20 
21 #if defined(OS_MAC)
22 #include "chrome/app/chrome_main_mac.h"
23 #endif
24 
25 #if defined(OS_WIN)
26 #include <timeapi.h>
27 
28 #include "base/base_switches.h"
29 #include "base/debug/dump_without_crashing.h"
30 #include "base/files/file_util.h"
31 #include "base/metrics/histogram_functions.h"
32 #include "base/win/win_util.h"
33 #include "chrome/chrome_elf/chrome_elf_main.h"
34 #include "chrome/common/chrome_constants.h"
35 #include "chrome/install_static/initialize_from_primary_module.h"
36 #include "chrome/install_static/install_details.h"
37 
38 #define DLLEXPORT __declspec(dllexport)
39 
40 // We use extern C for the prototype DLLEXPORT to avoid C++ name mangling.
41 extern "C" {
42 DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance,
43                                  sandbox::SandboxInterfaceInfo* sandbox_info,
44                                  int64_t exe_entry_point_ticks,
45                                  base::PrefetchResultCode prefetch_result_code);
46 }
47 #elif defined(OS_POSIX)
48 extern "C" {
49 __attribute__((visibility("default")))
50 int ChromeMain(int argc, const char** argv);
51 }
52 #endif
53 
54 #if defined(OS_WIN)
ChromeMain(HINSTANCE instance,sandbox::SandboxInterfaceInfo * sandbox_info,int64_t exe_entry_point_ticks,base::PrefetchResultCode prefetch_result_code)55 DLLEXPORT int __cdecl ChromeMain(
56     HINSTANCE instance,
57     sandbox::SandboxInterfaceInfo* sandbox_info,
58     int64_t exe_entry_point_ticks,
59     base::PrefetchResultCode prefetch_result_code) {
60 #elif defined(OS_POSIX)
61 int ChromeMain(int argc, const char** argv) {
62   int64_t exe_entry_point_ticks = 0;
63 #endif
64 
65 #if defined(OS_WIN)
66   base::UmaHistogramEnumeration("Windows.ChromeDllPrefetchResult",
67                                 prefetch_result_code);
68   install_static::InitializeFromPrimaryModule();
69 #endif
70 
71   ChromeMainDelegate chrome_main_delegate(
72       base::TimeTicks::FromInternalValue(exe_entry_point_ticks));
73   content::ContentMainParams params(&chrome_main_delegate);
74 
75 #if defined(OS_WIN)
76   // The process should crash when going through abnormal termination, but we
77   // must be sure to reset this setting when ChromeMain returns normally.
78   auto crash_on_detach_resetter = base::ScopedClosureRunner(
79       base::BindOnce(&base::win::SetShouldCrashOnProcessDetach,
80                      base::win::ShouldCrashOnProcessDetach()));
81   base::win::SetShouldCrashOnProcessDetach(true);
82   base::win::SetAbortBehaviorForCrashReporting();
83   params.instance = instance;
84   params.sandbox_info = sandbox_info;
85 
86   // Pass chrome_elf's copy of DumpProcessWithoutCrash resolved via load-time
87   // dynamic linking.
88   base::debug::SetDumpWithoutCrashingFunction(&DumpProcessWithoutCrash);
89 
90   // Verify that chrome_elf and this module (chrome.dll and chrome_child.dll)
91   // have the same version.
92   if (install_static::InstallDetails::Get().VersionMismatch())
93     base::debug::DumpWithoutCrashing();
94 #else
95   params.argc = argc;
96   params.argv = argv;
97   base::CommandLine::Init(params.argc, params.argv);
98 #endif  // defined(OS_WIN)
99   base::CommandLine::Init(0, nullptr);
100   const base::CommandLine* command_line(base::CommandLine::ForCurrentProcess());
101   ALLOW_UNUSED_LOCAL(command_line);
102 
103 #if defined(OS_WIN)
104   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
105           ::switches::kRaiseTimerFrequency)) {
106     // Raise the timer interrupt frequency and leave it raised.
107     timeBeginPeriod(1);
108   }
109 #endif
110 
111 #if defined(OS_MAC)
112   SetUpBundleOverrides();
113 #endif
114 
115   // Start the sampling profiler as early as possible - namely, once the command
116   // line data is available. Allocated as an object on the stack to ensure that
117   // the destructor runs on shutdown, which is important to avoid the profiler
118   // thread's destruction racing with main thread destruction.
119   MainThreadStackSamplingProfiler scoped_sampling_profiler;
120 
121   // Chrome-specific process modes.
122 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_MAC) || defined(OS_BSD) || \
123     defined(OS_WIN)
124   if (command_line->HasSwitch(switches::kHeadless)) {
125     return headless::HeadlessShellMain(params);
126   }
127 #endif  // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_MAC) || defined(OS_BSD) ||
128         // defined(OS_WIN)
129 
130   int rv = content::ContentMain(params);
131 
132   return rv;
133 }
134