summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/chrome_exe_main_win.cc12
-rw-r--r--chrome/app/metro_driver_win.cc49
-rw-r--r--chrome/app/metro_driver_win.h33
-rw-r--r--chrome/chrome_exe.gypi2
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': [