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 "content/renderer/renderer_main_platform_delegate.h" 6 7 #include "base/command_line.h" 8 #include "base/logging.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/strings/string16.h" 11 #include "base/win/win_util.h" 12 #include "content/public/common/content_switches.h" 13 #include "content/public/common/injection_test_win.h" 14 #include "content/public/renderer/render_thread.h" 15 #include "content/renderer/render_thread_impl.h" 16 #include "sandbox/win/src/sandbox.h" 17 #include "skia/ext/vector_platform_device_emf_win.h" 18 #include "third_party/icu/source/i18n/unicode/timezone.h" 19 #include "third_party/skia/include/ports/SkTypeface_win.h" 20 21 #ifdef ENABLE_VTUNE_JIT_INTERFACE 22 #include "v8/src/third_party/vtune/v8-vtune.h" 23 #endif 24 25 namespace content { 26 namespace { 27 28 // Windows-only skia sandbox support 29 void SkiaPreCacheFont(const LOGFONT& logfont) { 30 RenderThread* render_thread = RenderThread::Get(); 31 if (render_thread) { 32 render_thread->PreCacheFont(logfont); 33 } 34 } 35 36 void SkiaPreCacheFontCharacters(const LOGFONT& logfont, 37 const wchar_t* text, 38 unsigned int text_length) { 39 RenderThreadImpl* render_thread_impl = RenderThreadImpl::current(); 40 if (render_thread_impl) { 41 render_thread_impl->PreCacheFontCharacters(logfont, 42 string16(text, text_length)); 43 } 44 } 45 46 void InitExitInterceptions() { 47 // If code subsequently tries to exit using exit(), _exit(), abort(), or 48 // ExitProcess(), force a crash (since otherwise these would be silent 49 // terminations and fly under the radar). 50 base::win::SetShouldCrashOnProcessDetach(true); 51 base::win::SetAbortBehaviorForCrashReporting(); 52 } 53 54 #if !defined(NDEBUG) 55 LRESULT CALLBACK WindowsHookCBT(int code, WPARAM w_param, LPARAM l_param) { 56 CHECK_NE(code, HCBT_CREATEWND) 57 << "Should not be creating windows in the renderer!"; 58 return CallNextHookEx(NULL, code, w_param, l_param); 59 } 60 #endif // !NDEBUG 61 62 63 } // namespace 64 65 RendererMainPlatformDelegate::RendererMainPlatformDelegate( 66 const MainFunctionParams& parameters) 67 : parameters_(parameters), 68 sandbox_test_module_(NULL) { 69 } 70 71 RendererMainPlatformDelegate::~RendererMainPlatformDelegate() { 72 } 73 74 void RendererMainPlatformDelegate::PlatformInitialize() { 75 #if !defined(NDEBUG) 76 // Install a check that we're not creating windows in the renderer. See 77 // http://crbug.com/230122 for background. TODO(scottmg): Ideally this would 78 // check all threads in the renderer, but it currently only checks the main 79 // thread. 80 PCHECK( 81 SetWindowsHookEx(WH_CBT, WindowsHookCBT, NULL, ::GetCurrentThreadId())); 82 #endif // !NDEBUG 83 84 InitExitInterceptions(); 85 86 const CommandLine& command_line = parameters_.command_line; 87 88 #ifdef ENABLE_VTUNE_JIT_INTERFACE 89 if (command_line.HasSwitch(switches::kEnableVtune)) 90 vTune::InitializeVtuneForV8(); 91 #endif 92 93 // Be mindful of what resources you acquire here. They can be used by 94 // malicious code if the renderer gets compromised. 95 bool no_sandbox = command_line.HasSwitch(switches::kNoSandbox); 96 97 if (!no_sandbox) { 98 // ICU DateFormat class (used in base/time_format.cc) needs to get the 99 // Olson timezone ID by accessing the registry keys under 100 // HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones. 101 // After TimeZone::createDefault is called once here, the timezone ID is 102 // cached and there's no more need to access the registry. If the sandbox 103 // is disabled, we don't have to make this dummy call. 104 scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault()); 105 SkTypeface_SetEnsureLOGFONTAccessibleProc(SkiaPreCacheFont); 106 skia::SetSkiaEnsureTypefaceCharactersAccessible( 107 SkiaPreCacheFontCharacters); 108 } 109 } 110 111 void RendererMainPlatformDelegate::PlatformUninitialize() { 112 // At this point we are shutting down in a normal code path, so undo our 113 // hack to crash on exit. 114 base::win::SetShouldCrashOnProcessDetach(false); 115 } 116 117 bool RendererMainPlatformDelegate::InitSandboxTests(bool no_sandbox) { 118 const CommandLine& command_line = parameters_.command_line; 119 120 DVLOG(1) << "Started renderer with " << command_line.GetCommandLineString(); 121 122 sandbox::TargetServices* target_services = 123 parameters_.sandbox_info->target_services; 124 125 if (target_services && !no_sandbox) { 126 std::wstring test_dll_name = 127 command_line.GetSwitchValueNative(switches::kTestSandbox); 128 if (!test_dll_name.empty()) { 129 sandbox_test_module_ = LoadLibrary(test_dll_name.c_str()); 130 DCHECK(sandbox_test_module_); 131 if (!sandbox_test_module_) { 132 return false; 133 } 134 } 135 } 136 return true; 137 } 138 139 bool RendererMainPlatformDelegate::EnableSandbox() { 140 sandbox::TargetServices* target_services = 141 parameters_.sandbox_info->target_services; 142 143 if (target_services) { 144 // Cause advapi32 to load before the sandbox is turned on. 145 unsigned int dummy_rand; 146 rand_s(&dummy_rand); 147 // Warm up language subsystems before the sandbox is turned on. 148 ::GetUserDefaultLangID(); 149 ::GetUserDefaultLCID(); 150 151 target_services->LowerToken(); 152 return true; 153 } 154 return false; 155 } 156 157 void RendererMainPlatformDelegate::RunSandboxTests(bool no_sandbox) { 158 if (sandbox_test_module_) { 159 RunRendererTests run_security_tests = 160 reinterpret_cast<RunRendererTests>(GetProcAddress(sandbox_test_module_, 161 kRenderTestCall)); 162 DCHECK(run_security_tests); 163 if (run_security_tests) { 164 int test_count = 0; 165 DVLOG(1) << "Running renderer security tests"; 166 BOOL result = run_security_tests(&test_count); 167 CHECK(result) << "Test number " << test_count << " has failed."; 168 } 169 } 170 } 171 172 } // namespace content 173