Home | History | Annotate | Download | only in renderer
      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