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