Home | History | Annotate | Download | only in app
      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 "metro_driver_win.h"
      6 
      7 #include <string.h>
      8 
      9 #include "chrome/app/client_util.h"
     10 #include "chrome/common/chrome_constants.h"
     11 
     12 namespace {
     13 // This environment variable controls the loading of the metro driver DLL.
     14 const char* kMetroModeEnvVar = "CHROME_METRO_DLL";
     15 
     16 typedef int (*InitMetro)(LPTHREAD_START_ROUTINE thread_proc, void* context);
     17 
     18 struct Context {
     19   MetroDriver::MainFn fn;
     20   HINSTANCE instance;
     21 };
     22 
     23 DWORD WINAPI MainThread(void* param) {
     24   Context* context = reinterpret_cast<Context*>(param);
     25   int rv = context->fn(context->instance);
     26   delete context;
     27   return rv;
     28 }
     29 
     30 }  // namespace
     31 
     32 MetroDriver::MetroDriver() : init_metro_fn_(NULL) {
     33   if (0 != ::GetEnvironmentVariableA(kMetroModeEnvVar, NULL, 0))
     34     return;
     35   // The metro activation always has the |ServerName| parameter. If we dont
     36   // see it, we are being launched in desktop mode.
     37   if (!wcsstr(::GetCommandLineW(), L" -ServerName:DefaultBrowserServer")) {
     38     ::SetEnvironmentVariableA(kMetroModeEnvVar, "0");
     39     return;
     40   }
     41   // We haven't tried to load the metro driver, this probably means we are the
     42   // browser. Find it or not we set the environment variable because we don't
     43   // want to keep trying in the child processes.
     44   HMODULE metro_dll = ::LoadLibraryW(chrome::kMetroDriverDll);
     45   if (!metro_dll) {
     46     // It is not next to the build output, so this must be an actual deployment
     47     // and in that case we need the mainloader to find the current version
     48     // directory.
     49     string16 version(GetCurrentModuleVersion());
     50     if (!version.empty()) {
     51       std::wstring exe_path(GetExecutablePath());
     52       exe_path.append(version).append(L"\\").append(chrome::kMetroDriverDll);
     53       metro_dll = ::LoadLibraryW(exe_path.c_str());
     54     }
     55   }
     56   // We set the environment variable always, so we don't keep trying in
     57   // the child processes.
     58   ::SetEnvironmentVariableA(kMetroModeEnvVar, metro_dll ? "1" : "0");
     59   if (!metro_dll)
     60     return;
     61   init_metro_fn_ = ::GetProcAddress(metro_dll, "InitMetro");
     62 }
     63 
     64 int MetroDriver::RunInMetro(HINSTANCE instance, MainFn main_fn) {
     65   Context* context = new Context;
     66   context->fn = main_fn;
     67   context->instance = instance;
     68 
     69   return reinterpret_cast<InitMetro>(init_metro_fn_)(&MainThread, context);
     70 }
     71