Index: chrome/app/mash/mash_runner.cc |
diff --git a/chrome/app/mash/mash_runner.cc b/chrome/app/mash/mash_runner.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..787afc7b2f6c3646272e224ac3b74e075d5c88ca |
--- /dev/null |
+++ b/chrome/app/mash/mash_runner.cc |
@@ -0,0 +1,236 @@ |
+// Copyright 2016 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 "chrome/app/mash/mash_runner.h" |
+ |
+#include "ash/mus/sysui_application.h" |
+#include "base/at_exit.h" |
+#include "base/bind.h" |
+#include "base/command_line.h" |
+#include "base/debug/debugger.h" |
+#include "base/i18n/icu_util.h" |
+#include "base/logging.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/process/launch.h" |
+#include "components/mus/mus_app.h" |
+#include "components/resource_provider/resource_provider_app.h" |
+#include "content/public/common/content_switches.h" |
+#include "mash/quick_launch/quick_launch_application.h" |
+#include "mash/shell/shell_application_delegate.h" |
+#include "mash/wm/window_manager_application.h" |
+#include "mojo/common/mojo_scheme_register.h" |
+#include "mojo/public/cpp/bindings/weak_binding_set.h" |
+#include "mojo/shell/background/background_shell.h" |
+#include "mojo/shell/identity.h" |
+#include "mojo/shell/native_runner_delegate.h" |
+#include "mojo/shell/public/cpp/shell_client.h" |
+#include "mojo/shell/public/cpp/shell_connection.h" |
+#include "mojo/shell/public/interfaces/shell_client_factory.mojom.h" |
+#include "mojo/shell/runner/common/switches.h" |
+#include "mojo/shell/runner/host/child_process_base.h" |
+#include "url/gurl.h" |
+#include "url/url_util.h" |
+ |
+#if defined(OS_LINUX) |
+#include "components/font_service/font_service_app.h" |
+#endif |
+ |
+using mojo::shell::mojom::ShellClientFactory; |
+ |
+namespace { |
+ |
+// kProcessType used to identify child processes. |
+const char* kMashChild = "mash-child"; |
+ |
+// ShellClient responsible for starting the appropriate app. |
+class DefaultShellClient : public mojo::ShellClient, |
+ public ShellClientFactory, |
+ public mojo::InterfaceFactory<ShellClientFactory> { |
+ public: |
+ DefaultShellClient() {} |
+ ~DefaultShellClient() override {} |
+ |
+ // mojo::ShellClient: |
+ bool AcceptConnection(mojo::Connection* connection) override { |
+ connection->AddInterface<ShellClientFactory>(this); |
+ return true; |
+ } |
+ |
+ // mojo::InterfaceFactory<ShellClientFactory> |
+ void Create(mojo::Connection* connection, |
+ mojo::InterfaceRequest<ShellClientFactory> request) override { |
+ shell_client_factory_bindings_.AddBinding(this, std::move(request)); |
+ } |
+ |
+ // ShellClientFactory: |
+ void CreateShellClient(mojo::shell::mojom::ShellClientRequest request, |
+ const mojo::String& mojo_url) override { |
+ const GURL url = GURL(std::string(mojo_url)); |
+ if (shell_client_) { |
+ LOG(ERROR) << "request to create additional app " << url; |
+ return; |
+ } |
+ shell_client_ = CreateShellClient(url); |
+ if (shell_client_) { |
+ shell_connection_.reset( |
+ new mojo::ShellConnection(shell_client_.get(), std::move(request))); |
+ return; |
+ } |
+ LOG(ERROR) << "unknown url " << url; |
+ NOTREACHED(); |
+ } |
+ |
+ private: |
+ // TODO(sky): move this into mash. |
+ scoped_ptr<mojo::ShellClient> CreateShellClient(const GURL& url) { |
+ if (url == GURL("mojo:ash_sysui")) |
+ return make_scoped_ptr(new ash::sysui::SysUIApplication); |
+ if (url == GURL("mojo:desktop_wm")) |
+ return make_scoped_ptr(new mash::wm::WindowManagerApplication); |
+ if (url == GURL("mojo:mash_shell")) |
+ return make_scoped_ptr(new mash::shell::ShellApplicationDelegate); |
+ if (url == GURL("mojo:mus")) |
+ return make_scoped_ptr(new mus::MandolineUIServicesApp); |
+ if (url == GURL("mojo:quick_launch")) |
+ return make_scoped_ptr(new mash::quick_launch::QuickLaunchApplication); |
+ if (url == GURL("mojo:resource_provider")) { |
+ return make_scoped_ptr( |
+ new resource_provider::ResourceProviderApp("mojo:resource_provider")); |
+ } |
+#if defined(OS_LINUX) |
+ if (url == GURL("mojo:font_service")) |
+ return make_scoped_ptr(new font_service::FontServiceApp); |
+#endif |
+ return nullptr; |
+ } |
+ |
+ mojo::WeakBindingSet<ShellClientFactory> shell_client_factory_bindings_; |
+ scoped_ptr<mojo::ShellClient> shell_client_; |
+ scoped_ptr<mojo::ShellConnection> shell_connection_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DefaultShellClient); |
+}; |
+ |
+bool IsChild() { |
+ return base::CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kProcessType) && |
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
+ switches::kProcessType) == kMashChild; |
+} |
+ |
+// Convert the command line program from chrome_mash to chrome. This is |
+// necessary as the shell will attempt to start chrome_mash. We want chrome. |
+void ChangeChromeMashToChrome(base::CommandLine* command_line) { |
+ base::FilePath exe_path(command_line->GetProgram()); |
+#if defined(OS_WIN) |
+ exe_path = exe_path.DirName().Append(FILE_PATH_LITERAL("chrome.exe")); |
+#else |
+ exe_path = exe_path.DirName().Append(FILE_PATH_LITERAL("chrome")); |
+#endif |
+ command_line->SetProgram(exe_path); |
+} |
+ |
+class NativeRunnerDelegateImpl : public mojo::shell::NativeRunnerDelegate { |
+ public: |
+ NativeRunnerDelegateImpl() {} |
+ ~NativeRunnerDelegateImpl() override {} |
+ |
+ private: |
+ // mojo::shell::NativeRunnerDelegate: |
+ void AdjustCommandLineArgumentsForTarget( |
+ const mojo::shell::Identity& target, |
+ base::CommandLine* command_line) override { |
+ if (target.url() != GURL("exe:chrome")) { |
+ if (target.url() == GURL("exe:chrome_mash")) |
+ ChangeChromeMashToChrome(command_line); |
+ command_line->AppendSwitchASCII(switches::kProcessType, kMashChild); |
+#if defined(OS_WIN) |
+ command_line->AppendArg(switches::kPrefetchArgumentOther); |
+#endif |
+ return; |
+ } |
+ |
+ base::CommandLine::StringVector argv(command_line->argv()); |
+ auto iter = |
+ std::find(argv.begin(), argv.end(), FILE_PATH_LITERAL("--mash")); |
+ if (iter != argv.end()) |
+ argv.erase(iter); |
+ *command_line = base::CommandLine(argv); |
+ } |
+ |
+ DISALLOW_COPY_AND_ASSIGN(NativeRunnerDelegateImpl); |
+}; |
+ |
+} // namespace |
+ |
+MashRunner::MashRunner() {} |
+ |
+MashRunner::~MashRunner() {} |
+ |
+void MashRunner::Run() { |
+ if (IsChild()) |
+ RunChild(); |
+ else |
+ RunMain(); |
+} |
+ |
+void MashRunner::RunMain() { |
+ // TODO(sky): refactor backgroundshell so can supply own context, we |
+ // shouldn't we using context as it has a lot of stuff we don't really want |
+ // in chrome. |
+ NativeRunnerDelegateImpl native_runner_delegate; |
+ mojo::shell::BackgroundShell background_shell; |
+ background_shell.Init(&native_runner_delegate); |
+ shell_client_.reset(new DefaultShellClient); |
+ shell_connection_.reset(new mojo::ShellConnection( |
+ shell_client_.get(), |
+ background_shell.CreateShellClientRequest(GURL("exe:chrome_mash")))); |
+ shell_connection_->WaitForInitialize(); |
+ static_cast<mojo::Shell*>(shell_connection_.get()) |
+ ->Connect("mojo:mash_shell"); |
+ base::MessageLoop::current()->Run(); |
+} |
+ |
+void MashRunner::RunChild() { |
+ base::i18n::InitializeICU(); |
+ mojo::shell::ChildProcessMain( |
+ base::Bind(&MashRunner::StartChildApp, base::Unretained(this))); |
+} |
+ |
+void MashRunner::StartChildApp( |
+ mojo::shell::mojom::ShellClientRequest client_request) { |
+ // TODO(sky): use MessagePumpMojo. |
+ base::MessageLoop message_loop(base::MessageLoop::TYPE_UI); |
+ shell_client_.reset(new DefaultShellClient); |
+ shell_connection_.reset(new mojo::ShellConnection(shell_client_.get(), |
+ std::move(client_request))); |
+ message_loop.Run(); |
+} |
+ |
+int MashMain() { |
+#if defined(OS_WIN) |
+ base::RouteStdioToConsole(false); |
+#endif |
+ // TODO(sky): wire this up correctly. |
+ logging::LoggingSettings settings; |
+ settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; |
+ logging::InitLogging(settings); |
+ // To view log output with IDs and timestamps use "adb logcat -v threadtime". |
+ logging::SetLogItems(false, // Process ID |
+ false, // Thread ID |
+ false, // Timestamp |
+ false); // Tick count |
+ |
+ mojo::RegisterMojoSchemes(); |
+ // TODO(sky): use MessagePumpMojo. |
+ scoped_ptr<base::MessageLoop> message_loop; |
+#if defined(OS_LINUX) |
+ base::AtExitManager exit_manager; |
+#endif |
+ if (!IsChild()) |
+ message_loop.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI)); |
+ MashRunner mash_runner; |
+ mash_runner.Run(); |
+ return 0; |
+} |