// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "metro_driver_win.h"
#include <string.h>
#include "chrome/app/client_util.h"
#include "chrome/common/chrome_constants.h"
namespace {
// This environment variable controls the loading of the metro driver DLL.
const char* kMetroModeEnvVar = "CHROME_METRO_DLL";
typedef int (*InitMetro)(LPTHREAD_START_ROUTINE thread_proc, void* context);
struct Context {
MetroDriver::MainFn fn;
HINSTANCE instance;
};
DWORD WINAPI MainThread(void* param) {
Context* context = reinterpret_cast<Context*>(param);
int rv = context->fn(context->instance);
delete context;
return rv;
}
} // namespace
MetroDriver::MetroDriver() : init_metro_fn_(NULL) {
if (0 != ::GetEnvironmentVariableA(kMetroModeEnvVar, NULL, 0))
return;
// The metro activation always has the |ServerName| parameter. If we dont
// see it, we are being launched in desktop mode.
if (!wcsstr(::GetCommandLineW(), L" -ServerName:DefaultBrowserServer")) {
::SetEnvironmentVariableA(kMetroModeEnvVar, "0");
return;
}
// We haven't tried to load the metro driver, this probably means we are the
// browser. Find it or not we set the environment variable because we don't
// want to keep trying in the child processes.
HMODULE metro_dll = ::LoadLibraryW(chrome::kMetroDriverDll);
if (!metro_dll) {
// It is not next to the build output, so this must be an actual deployment
// and in that case we need the mainloader to find the current version
// directory.
string16 version(GetCurrentModuleVersion());
if (!version.empty()) {
std::wstring exe_path(GetExecutablePath());
exe_path.append(version).append(L"\\").append(chrome::kMetroDriverDll);
metro_dll = ::LoadLibraryW(exe_path.c_str());
}
}
// We set the environment variable always, so we don't keep trying in
// the child processes.
::SetEnvironmentVariableA(kMetroModeEnvVar, metro_dll ? "1" : "0");
if (!metro_dll)
return;
init_metro_fn_ = ::GetProcAddress(metro_dll, "InitMetro");
}
int MetroDriver::RunInMetro(HINSTANCE instance, MainFn main_fn) {
Context* context = new Context;
context->fn = main_fn;
context->instance = instance;
return reinterpret_cast<InitMetro>(init_metro_fn_)(&MainThread, context);
}