diff options
-rw-r--r-- | chrome/app/chrome_exe_main_win.cc | 12 | ||||
-rw-r--r-- | chrome/app/metro_driver_win.cc | 49 | ||||
-rw-r--r-- | chrome/app/metro_driver_win.h | 33 | ||||
-rw-r--r-- | chrome/chrome_exe.gypi | 2 |
4 files changed, 94 insertions, 2 deletions
diff --git a/chrome/app/chrome_exe_main_win.cc b/chrome/app/chrome_exe_main_win.cc index 0d7ca72..b7dfa57 100644 --- a/chrome/app/chrome_exe_main_win.cc +++ b/chrome/app/chrome_exe_main_win.cc @@ -9,11 +9,12 @@ #include "base/command_line.h" #include "chrome/app/breakpad_win.h" #include "chrome/app/client_util.h" +#include "chrome/app/metro_driver_win.h" #include "content/public/app/startup_helper_win.h" #include "content/public/common/result_codes.h" #include "sandbox/src/sandbox_factory.h" -int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t*, int) { +int RunChrome(HINSTANCE instance) { bool exit_now = true; // We restarted because of a previous crash. Ask user if we should relaunch. if (ShowRestartDialogIfCrashed(&exit_now)) { @@ -36,6 +37,13 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t*, int) { int rc = loader->Launch(instance, &sandbox_info); loader->RelaunchChromeBrowserWithNewCommandLineIfNeeded(); delete loader; - return rc; } + +int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) { + MetroDriver metro_driver; + if (metro_driver.in_metro_mode()) + return metro_driver.RunInMetro(instance, &RunChrome); + // Not in metro mode, proceed as normal. + return RunChrome(instance); +} diff --git a/chrome/app/metro_driver_win.cc b/chrome/app/metro_driver_win.cc new file mode 100644 index 0000000..e8ec6ca --- /dev/null +++ b/chrome/app/metro_driver_win.cc @@ -0,0 +1,49 @@ +// Copyright (c) 2011 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" + +namespace { +// The windows 8 metro driver dll name and entry point. +const char kMetroDriverDll[] = "metro_driver.dll"; +// 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; + // 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 = ::LoadLibraryA(kMetroDriverDll); + ::SetEnvironmentVariableA(kMetroModeEnvVar, metro_dll ? "1" : "0"); + if (!metro_dll) + return; + init_metro_fn_ = + ::GetProcAddress(::GetModuleHandleA(kMetroDriverDll), "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); +} diff --git a/chrome/app/metro_driver_win.h b/chrome/app/metro_driver_win.h new file mode 100644 index 0000000..b99a9af --- /dev/null +++ b/chrome/app/metro_driver_win.h @@ -0,0 +1,33 @@ +// Copyright (c) 2011 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. + +#ifndef CHROME_APP_METRO_DRIVER_WIN_H_ +#define CHROME_APP_METRO_DRIVER_WIN_H_ + +#include <Windows.h> + +// Helper class to manage the metro driver dll. When present in the system, +// the main process thread needs to call InitMetro(), normal execution of +// chrome initialization will continue on a second thread while the main +// thread will be servicing the metro message loop. +class MetroDriver { + public: + typedef int (*MainFn)(HINSTANCE instance); + + MetroDriver(); + // returns true if chrome is being launched in metro. If so we should + // call RunInMetro(). If not then we should just run chrome as usual. + bool in_metro_mode() const { return (NULL != init_metro_fn_); } + + // Enter the metro main function, which will only return when chrome metro + // is closed. Once metro has initialized, the dll creates a new thread + // which runs |main_fn|. This method returns when the chrome metro session + // is closed by the user. + int RunInMetro(HINSTANCE instance, MainFn main_fn); + + private: + void* init_metro_fn_; +}; + +#endif // CHROME_APP_METRO_DRIVER_WIN_H_ diff --git a/chrome/chrome_exe.gypi b/chrome/chrome_exe.gypi index bdae4de..1271a2d 100644 --- a/chrome/chrome_exe.gypi +++ b/chrome/chrome_exe.gypi @@ -24,6 +24,8 @@ 'app/client_util.h', 'app/hard_error_handler_win.cc', 'app/hard_error_handler_win.h', + 'app/metro_driver_win.cc', + 'app/metro_driver_win.h', '../content/app/startup_helper_win.cc', ], 'mac_bundle_resources': [ |