diff options
-rw-r--r-- | mash/example/window_type_launcher/BUILD.gn | 2 | ||||
-rw-r--r-- | mash/example/window_type_launcher/window_type_launcher.cc | 10 | ||||
-rw-r--r-- | mash/init/BUILD.gn | 1 | ||||
-rw-r--r-- | mash/init/init.cc | 75 | ||||
-rw-r--r-- | mash/init/init.h | 35 | ||||
-rw-r--r-- | mash/init/public/interfaces/BUILD.gn | 2 | ||||
-rw-r--r-- | mash/init/public/interfaces/init.mojom | 10 | ||||
-rw-r--r-- | mash/login/BUILD.gn | 6 | ||||
-rw-r--r-- | mash/login/login.cc | 139 | ||||
-rw-r--r-- | mash/login/login.h | 23 | ||||
-rw-r--r-- | mash/login/main.cc | 2 | ||||
-rw-r--r-- | mash/login/manifest.json | 10 | ||||
-rw-r--r-- | mash/login/public/interfaces/BUILD.gn | 11 | ||||
-rw-r--r-- | mash/login/public/interfaces/login.mojom (renamed from mash/init/public/interfaces/login.mojom) | 6 | ||||
-rw-r--r-- | mash/login/ui.cc | 135 | ||||
-rw-r--r-- | mash/login/ui.h | 69 | ||||
-rw-r--r-- | mojo/shell/shell.cc | 38 | ||||
-rw-r--r-- | mojo/shell/shell.h | 4 | ||||
-rw-r--r-- | ui/views/mus/window_manager_connection.cc | 5 | ||||
-rw-r--r-- | ui/views/mus/window_manager_connection.h | 1 |
20 files changed, 378 insertions, 206 deletions
diff --git a/mash/example/window_type_launcher/BUILD.gn b/mash/example/window_type_launcher/BUILD.gn index 5b0b2f4..245d93d 100644 --- a/mash/example/window_type_launcher/BUILD.gn +++ b/mash/example/window_type_launcher/BUILD.gn @@ -24,7 +24,7 @@ executable("window_type_launcher") { "//base:base_static", "//build/config/sanitizers:deps", "//components/mus/public/interfaces", - "//mash/init/public/interfaces", + "//mash/login/public/interfaces", "//mash/shell/public/interfaces", "//mojo/common:common_base", "//mojo/converters/geometry", diff --git a/mash/example/window_type_launcher/window_type_launcher.cc b/mash/example/window_type_launcher/window_type_launcher.cc index 8286b22..b469395 100644 --- a/mash/example/window_type_launcher/window_type_launcher.cc +++ b/mash/example/window_type_launcher/window_type_launcher.cc @@ -6,7 +6,7 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" -#include "mash/init/public/interfaces/login.mojom.h" +#include "mash/login/public/interfaces/login.mojom.h" #include "mash/shell/public/interfaces/shell.mojom.h" #include "mojo/converters/geometry/geometry_type_converters.h" #include "mojo/shell/public/cpp/connection.h" @@ -283,12 +283,12 @@ class WindowTypeLauncherView : public views::WidgetDelegateView, connector_->ConnectToInterface("mojo:mash_shell", &shell); shell->LockScreen(); } else if (sender == logout_button_) { - mash::init::mojom::LoginPtr login; - connector_->ConnectToInterface("mojo:mash_init", &login); + mash::login::mojom::LoginPtr login; + connector_->ConnectToInterface("mojo:login", &login); login->Logout(); } else if (sender == switch_user_button_) { - mash::init::mojom::LoginPtr login; - connector_->ConnectToInterface("mojo:mash_init", &login); + mash::login::mojom::LoginPtr login; + connector_->ConnectToInterface("mojo:login", &login); login->SwitchUser(); } else if (sender == widgets_button_) { NOTIMPLEMENTED(); diff --git a/mash/init/BUILD.gn b/mash/init/BUILD.gn index 1d79330..900a31e 100644 --- a/mash/init/BUILD.gn +++ b/mash/init/BUILD.gn @@ -21,6 +21,7 @@ mojo_native_application("init") { "//components/mus/public/cpp", "//components/mus/public/interfaces", "//mash/init/public/interfaces", + "//mash/login/public/interfaces", "//mojo/public/cpp/bindings", "//mojo/services/tracing/public/cpp", "//mojo/shell/public/cpp", diff --git a/mash/init/init.cc b/mash/init/init.cc index 20c88be..ffe16a6 100644 --- a/mash/init/init.cc +++ b/mash/init/init.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/guid.h" +#include "mash/login/public/interfaces/login.mojom.h" #include "mojo/shell/public/cpp/connection.h" #include "mojo/shell/public/cpp/connector.h" @@ -20,72 +21,38 @@ void Init::Initialize(mojo::Connector* connector, const mojo::Identity& identity, uint32_t id) { connector_ = connector; - mus_connection_ = connector_->Connect("mojo:mus"); - mus_connection_->GetInterface(&user_access_manager_); - user_access_manager_->SetActiveUser(login_user_id_); - StartWindowManager(); + connector_->Connect("mojo:mus"); StartLogin(); } -bool Init::AcceptConnection(mojo::Connection* connection) { - connection->AddInterface<mojom::Login>(this); - return true; +void Init::StartService(const mojo::String& name, + const mojo::String& user_id) { + DCHECK(user_services_.find(user_id) == user_services_.end()); + mojo::Connector::ConnectParams params(mojo::Identity(name, user_id)); + user_services_[user_id] = connector_->Connect(¶ms); } -void Init::LoginAs(const mojo::String& user_id) { - user_access_manager_->SetActiveUser(user_id); - connections_["mojo:mash_login"].reset(); - connections_["mojo:desktop_wm"].reset(); - mojo::Connector::ConnectParams params( - mojo::Identity("mojo:mash_shell", user_id)); - connector_->Connect(¶ms); -} - -void Init::Logout() { - // TODO(beng): need to kill the user session. - user_access_manager_->SetActiveUser(login_user_id_); - StartWindowManager(); - StartLogin(); -} - -void Init::SwitchUser() { - // This doesn't kill the user session, merely starts the login UI. - user_access_manager_->SetActiveUser(login_user_id_); - StartWindowManager(); - StartLogin(); -} - -void Init::Create(mojo::Connection* connection, mojom::LoginRequest request) { - login_bindings_.AddBinding(this, std::move(request)); +void Init::StopServicesForUser(const mojo::String& user_id) { + // TODO(beng): Make shell cascade shutdown of services. + auto it = user_services_.find(user_id); + if (it != user_services_.end()) + user_services_.erase(it); } -void Init::StartWindowManager() { - mojo::Connector::ConnectParams params( - mojo::Identity("mojo:desktop_wm", login_user_id_)); - StartRestartableService( - ¶ms, - base::Bind(&Init::StartWindowManager, base::Unretained(this))); +void Init::Create(mojo::Connection* connection, mojom::InitRequest request) { + init_bindings_.AddBinding(this, std::move(request)); } void Init::StartLogin() { mojo::Connector::ConnectParams params( - mojo::Identity("mojo:mash_login", login_user_id_)); - StartRestartableService( - ¶ms, + mojo::Identity("mojo:login", login_user_id_)); + login_connection_ = connector_->Connect(¶ms); + login_connection_->AddInterface<mojom::Init>(this); + login_connection_->SetConnectionLostClosure( base::Bind(&Init::StartLogin, base::Unretained(this))); -} - -void Init::StartRestartableService(mojo::Connector::ConnectParams* params, - const base::Closure& restart_callback) { - // TODO(beng): This would be the place to insert logic that counted restarts - // to avoid infinite crash-restart loops. - scoped_ptr<mojo::Connection> connection = connector_->Connect(params); - // Note: |connection| may be null if we've lost our connection to the shell. - if (connection) { - connection->SetConnectionLostClosure(restart_callback); - connection->AddInterface<mojom::Login>(this); - connections_[params->target().name()] = std::move(connection); - } + mash::login::mojom::LoginPtr login; + login_connection_->GetInterface(&login); + login->ShowLoginUI(); } } // namespace init diff --git a/mash/init/init.h b/mash/init/init.h index 7ca8f81..b650f50 100644 --- a/mash/init/init.h +++ b/mash/init/init.h @@ -10,8 +10,7 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" -#include "components/mus/public/interfaces/user_access_manager.mojom.h" -#include "mash/init/public/interfaces/login.mojom.h" +#include "mash/init/public/interfaces/init.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/shell/public/cpp/connector.h" #include "mojo/shell/public/cpp/shell_client.h" @@ -21,11 +20,11 @@ class Connection; } namespace mash { -namespace init{ +namespace init { class Init : public mojo::ShellClient, - public mojom::Login, - public mojo::InterfaceFactory<mojom::Login> { + public mojo::InterfaceFactory<mojom::Init>, + public mojom::Init { public: Init(); ~Init() override; @@ -34,30 +33,22 @@ class Init : public mojo::ShellClient, // mojo::ShellClient: void Initialize(mojo::Connector* connector, const mojo::Identity& identity, uint32_t id) override; - bool AcceptConnection(mojo::Connection* connection) override; - - // mojom::Login: - void LoginAs(const mojo::String& user_id) override; - void Logout() override; - void SwitchUser() override; // mojo::InterfaceFactory<mojom::Login>: void Create(mojo::Connection* connection, - mojom::LoginRequest request) override; + mojom::InitRequest request) override; - void StartWindowManager(); - void StartLogin(); + // mojom::Init: + void StartService(const mojo::String& name, + const mojo::String& user_id) override; + void StopServicesForUser(const mojo::String& user_id) override; - // Starts the application at |url|, running |restart_callback| if the - // connection to the application is closed. - void StartRestartableService(mojo::Connector::ConnectParams* params, - const base::Closure& restart_callback); + void StartLogin(); mojo::Connector* connector_; - std::map<std::string, scoped_ptr<mojo::Connection>> connections_; - mojo::BindingSet<mojom::Login> login_bindings_; - scoped_ptr<mojo::Connection> mus_connection_; - mus::mojom::UserAccessManagerPtr user_access_manager_; + scoped_ptr<mojo::Connection> login_connection_; + mojo::BindingSet<mojom::Init> init_bindings_; + std::map<std::string, scoped_ptr<mojo::Connection>> user_services_; const std::string login_user_id_; DISALLOW_COPY_AND_ASSIGN(Init); diff --git a/mash/init/public/interfaces/BUILD.gn b/mash/init/public/interfaces/BUILD.gn index 0ea747b..0fde619 100644 --- a/mash/init/public/interfaces/BUILD.gn +++ b/mash/init/public/interfaces/BUILD.gn @@ -6,6 +6,6 @@ import("//mojo/public/tools/bindings/mojom.gni") mojom("interfaces") { sources = [ - "login.mojom", + "init.mojom", ] } diff --git a/mash/init/public/interfaces/init.mojom b/mash/init/public/interfaces/init.mojom new file mode 100644 index 0000000..120d4b8 --- /dev/null +++ b/mash/init/public/interfaces/init.mojom @@ -0,0 +1,10 @@ +// 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. + +module mash.init.mojom; + +interface Init { + StartService(string name, string user_id); + StopServicesForUser(string user_id); +}; diff --git a/mash/login/BUILD.gn b/mash/login/BUILD.gn index f728171..bf0bbb9 100644 --- a/mash/login/BUILD.gn +++ b/mash/login/BUILD.gn @@ -9,17 +9,19 @@ import("//mojo/public/tools/bindings/mojom.gni") import("//tools/grit/repack.gni") mojo_native_application("login") { - output_name = "mash_login" sources = [ "login.cc", "login.h", "main.cc", + "ui.cc", + "ui.h", ] deps = [ "//base", "//components/mus/public/cpp", "//mash/init/public/interfaces", + "//mash/login/public/interfaces", "//mash/wm/public/interfaces", "//mojo/public/cpp/bindings", "//mojo/services/tracing/public/cpp", @@ -37,6 +39,6 @@ mojo_native_application("login") { } mojo_application_manifest("manifest") { - application_name = "mash_login" + application_name = "login" source = "manifest.json" } diff --git a/mash/login/login.cc b/mash/login/login.cc index 7604850..05edab5 100644 --- a/mash/login/login.cc +++ b/mash/login/login.cc @@ -4,131 +4,76 @@ #include "mash/login/login.h" -#include "base/guid.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/strings/utf_string_conversions.h" -#include "components/mus/public/cpp/property_type_converters.h" -#include "mash/wm/public/interfaces/container.mojom.h" -#include "mojo/public/cpp/bindings/binding.h" +#include "mash/login/ui.h" +#include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/shell/public/cpp/connector.h" -#include "ui/views/background.h" -#include "ui/views/controls/button/label_button.h" #include "ui/views/mus/aura_init.h" -#include "ui/views/mus/native_widget_mus.h" #include "ui/views/mus/window_manager_connection.h" -#include "ui/views/widget/widget_delegate.h" namespace mash { namespace login { namespace { -class LoginView : public views::WidgetDelegateView, - public views::ButtonListener { +class Login : public mojom::Login { public: - explicit LoginView(Login* login) - : login_(login), - user_id_1_(base::GenerateGUID()), - user_id_2_(base::GenerateGUID()), - login_button_1_( - new views::LabelButton(this, base::ASCIIToUTF16("Timothy"))), - login_button_2_( - new views::LabelButton(this, base::ASCIIToUTF16("Jimothy"))) { - set_background(views::Background::CreateSolidBackground(SK_ColorRED)); - login_button_1_->SetStyle(views::Button::STYLE_BUTTON); - login_button_2_->SetStyle(views::Button::STYLE_BUTTON); - AddChildView(login_button_1_); - AddChildView(login_button_2_); - } - ~LoginView() override {} + Login(mojo::Connector* connector, + LoginController* controller, + const std::string& user_id, + mojom::LoginRequest request) + : connector_(connector), + controller_(controller), + user_id_(user_id), + binding_(this, std::move(request)) {} + ~Login() override {} private: - // Overridden from views::WidgetDelegate: - views::View* GetContentsView() override { return this; } - base::string16 GetWindowTitle() const override { - // TODO(beng): use resources. - return base::ASCIIToUTF16("Login"); + // mojom::Login: + void ShowLoginUI() override { + UI::Show(connector_, controller_); } - - // Overridden from views::View: - void Layout() override { - gfx::Rect button_box = GetLocalBounds(); - button_box.Inset(10, 10); - - gfx::Size ps1 = login_button_1_->GetPreferredSize(); - gfx::Size ps2 = login_button_2_->GetPreferredSize(); - - DCHECK(ps1.height() == ps2.height()); - - // The 10 is inter-button spacing. - button_box.set_x((button_box.width() - ps1.width() - ps2.width() - 10) / 2); - button_box.set_y((button_box.height() - ps1.height()) / 2); - - login_button_1_->SetBounds(button_box.x(), button_box.y(), ps1.width(), - ps1.height()); - login_button_2_->SetBounds(login_button_1_->bounds().right() + 10, - button_box.y(), ps2.width(), ps2.height()); + void Logout() override { + controller_->init()->StopServicesForUser(user_id_); + UI::Show(connector_, controller_); } - - // Overridden from views::ButtonListener: - void ButtonPressed(views::Button* sender, const ui::Event& event) override { - // Login... - mojo::Connector::ConnectParams params("mojo:mash_shell"); - if (sender == login_button_1_) { - login_->login()->LoginAs(user_id_1_); - } else if (sender == login_button_2_) { - login_->login()->LoginAs(user_id_2_); - } else { - NOTREACHED(); - } - base::MessageLoop::current()->QuitWhenIdle(); + void SwitchUser() override { + UI::Show(connector_, controller_); } - Login* login_; - const std::string user_id_1_; - const std::string user_id_2_; - views::LabelButton* login_button_1_; - views::LabelButton* login_button_2_; + mojo::Connector* connector_; + LoginController* controller_; + const std::string user_id_; + mojo::StrongBinding<mojom::Login> binding_; - DISALLOW_COPY_AND_ASSIGN(LoginView); + DISALLOW_COPY_AND_ASSIGN(Login); }; } // namespace -Login::Login() {} -Login::~Login() {} +LoginController::LoginController() {} +LoginController::~LoginController() {} -void Login::Initialize(mojo::Connector* connector, - const mojo::Identity& identity, - uint32_t id) { +void LoginController::Initialize(mojo::Connector* connector, + const mojo::Identity& identity, + uint32_t id) { + connector_ = connector; + login_user_id_ = identity.user_id(); tracing_.Initialize(connector, identity.name()); aura_init_.reset(new views::AuraInit(connector, "views_mus_resources.pak")); - views::WindowManagerConnection::Create(connector); - - views::Widget* widget = new views::Widget; - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params.delegate = new LoginView(this); +} - std::map<std::string, std::vector<uint8_t>> properties; - properties[mash::wm::mojom::kWindowContainer_Property] = - mojo::TypeConverter<const std::vector<uint8_t>, int32_t>::Convert( - static_cast<int32_t>(mash::wm::mojom::Container::LOGIN_WINDOWS)); - mus::Window* window = - views::WindowManagerConnection::Get()->NewWindow(properties); - params.native_widget = new views::NativeWidgetMus( - widget, connector, window, mus::mojom::SurfaceType::DEFAULT); - widget->Init(params); - widget->Show(); +bool LoginController::AcceptConnection(mojo::Connection* connection) { + if (connection->GetRemoteIdentity().name() == "mojo:mash_init") + connection->GetInterface(&init_); + connection->AddInterface<mojom::Login>(this); + return true; } -bool Login::AcceptConnection(mojo::Connection* connection) { - if (connection->GetRemoteIdentity().name() == "mojo:mash_init") { - connection->GetInterface(&login_); - return true; - } - return false; +void LoginController::Create(mojo::Connection* connection, + mojom::LoginRequest request) { + new Login(connector_, this, connection->GetRemoteIdentity().user_id(), + std::move(request)); } } // namespace login diff --git a/mash/login/login.h b/mash/login/login.h index 88216b3..b50837d 100644 --- a/mash/login/login.h +++ b/mash/login/login.h @@ -9,7 +9,8 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" -#include "mash/init/public/interfaces/login.mojom.h" +#include "mash/init/public/interfaces/init.mojom.h" +#include "mash/login/public/interfaces/login.mojom.h" #include "mojo/services/tracing/public/cpp/tracing_impl.h" #include "mojo/shell/public/cpp/shell_client.h" @@ -20,12 +21,14 @@ class AuraInit; namespace mash { namespace login { -class Login : public mojo::ShellClient { +class LoginController : public mojo::ShellClient, + public mojo::InterfaceFactory<mojom::Login> { public: - Login(); - ~Login() override; + LoginController(); + ~LoginController() override; - init::mojom::Login* login() { return login_.get(); } + init::mojom::Init* init() { return init_.get(); } + const std::string& login_user_id() const { return login_user_id_; } private: // mojo::ShellClient: @@ -33,11 +36,17 @@ class Login : public mojo::ShellClient { uint32_t id) override; bool AcceptConnection(mojo::Connection* connection) override; + // mojo::InterfaceFactory<mojom::Login>: + void Create(mojo::Connection* connection, + mojom::LoginRequest request) override; + + mojo::Connector* connector_; + std::string login_user_id_; mojo::TracingImpl tracing_; scoped_ptr<views::AuraInit> aura_init_; - init::mojom::LoginPtr login_; + init::mojom::InitPtr init_; - DISALLOW_COPY_AND_ASSIGN(Login); + DISALLOW_COPY_AND_ASSIGN(LoginController); }; } // namespace login diff --git a/mash/login/main.cc b/mash/login/main.cc index 12b1804..1901dd0 100644 --- a/mash/login/main.cc +++ b/mash/login/main.cc @@ -7,6 +7,6 @@ #include "mojo/shell/public/cpp/application_runner.h" MojoResult MojoMain(MojoHandle shell_handle) { - mojo::ApplicationRunner runner(new mash::login::Login); + mojo::ApplicationRunner runner(new mash::login::LoginController); return runner.Run(shell_handle); } diff --git a/mash/login/manifest.json b/mash/login/manifest.json index bec0be46..b88eaeb 100644 --- a/mash/login/manifest.json +++ b/mash/login/manifest.json @@ -1,5 +1,11 @@ { - "name": "mojo:mash_login", + "manifest_version": 1, + "name": "mojo:login", "display_name": "Login", - "capabilities": { "*": [ "*" ] } + "capabilities": { + "required": { + "*": { "interfaces": [ "*" ] }, + "mojo:shell": { "classes": ["all_users"] } + } + } } diff --git a/mash/login/public/interfaces/BUILD.gn b/mash/login/public/interfaces/BUILD.gn new file mode 100644 index 0000000..0ea747b --- /dev/null +++ b/mash/login/public/interfaces/BUILD.gn @@ -0,0 +1,11 @@ +# 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. + +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "login.mojom", + ] +} diff --git a/mash/init/public/interfaces/login.mojom b/mash/login/public/interfaces/login.mojom index 43661b4..8ddf08e 100644 --- a/mash/init/public/interfaces/login.mojom +++ b/mash/login/public/interfaces/login.mojom @@ -2,12 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module mash.init.mojom; +module mash.login.mojom; interface Login { - // TODO(beng): this should be guarded by a capability class. - LoginAs(string user_id); - + ShowLoginUI(); Logout(); SwitchUser(); }; diff --git a/mash/login/ui.cc b/mash/login/ui.cc new file mode 100644 index 0000000..4a36f56 --- /dev/null +++ b/mash/login/ui.cc @@ -0,0 +1,135 @@ +// 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 "mash/login/ui.h" + +#include "base/guid.h" +#include "base/strings/utf_string_conversions.h" +#include "components/mus/public/cpp/property_type_converters.h" +#include "mash/login/login.h" +#include "mash/wm/public/interfaces/container.mojom.h" +#include "mojo/shell/public/cpp/connector.h" +#include "ui/views/background.h" +#include "ui/views/mus/native_widget_mus.h" +#include "ui/views/mus/window_manager_connection.h" + +namespace mash { +namespace login { + +// static +bool UI::is_showing_ = false; + +// static +void UI::Show(mojo::Connector* connector, LoginController* login_controller) { + // It's possible multiple clients may have a connection to the Login service, + // so make sure that only one login UI can be shown at a time. + if (is_showing_) + return; + + UI* ui = new UI(login_controller, connector); + + // TODO(beng): If this is only done once, it should be done in + // LoginController::Initialize(). However, for as yet unknown reasons it needs + // to be done the first time after UI(). Figure this out. Also, I'm not + // certain the window manager is being killed when this UI is closed. + if (!views::WindowManagerConnection::Exists()) + views::WindowManagerConnection::Create(connector); + + views::Widget* widget = new views::Widget; + views::Widget::InitParams params( + views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); + params.delegate = ui; + + std::map<std::string, std::vector<uint8_t>> properties; + properties[mash::wm::mojom::kWindowContainer_Property] = + mojo::TypeConverter<const std::vector<uint8_t>, int32_t>::Convert( + static_cast<int32_t>(mash::wm::mojom::Container::LOGIN_WINDOWS)); + mus::Window* window = + views::WindowManagerConnection::Get()->NewWindow(properties); + params.native_widget = new views::NativeWidgetMus( + widget, connector, window, mus::mojom::SurfaceType::DEFAULT); + widget->Init(params); + widget->Show(); + + is_showing_ = true; +} + +UI::UI(LoginController* login_controller, mojo::Connector* connector) + : login_controller_(login_controller), + connector_(connector), + user_id_1_("00000000-0000-4000-8000-000000000000"), + user_id_2_("00000000-0000-4000-8000-000000000001"), + login_button_1_( + new views::LabelButton(this, base::ASCIIToUTF16("Timothy"))), + login_button_2_( + new views::LabelButton(this, base::ASCIIToUTF16("Jimothy"))) { + connector_->ConnectToInterface("mojo:mus", &user_access_manager_); + user_access_manager_->SetActiveUser(login_controller->login_user_id()); + StartWindowManager(); + + set_background(views::Background::CreateSolidBackground(SK_ColorRED)); + login_button_1_->SetStyle(views::Button::STYLE_BUTTON); + login_button_2_->SetStyle(views::Button::STYLE_BUTTON); + AddChildView(login_button_1_); + AddChildView(login_button_2_); +} + +UI::~UI() { + // Prevent the window manager from restarting during graceful shutdown. + window_manager_connection_->SetConnectionLostClosure(base::Closure()); + is_showing_ = false; +} + +views::View* UI::GetContentsView() { return this; } + +base::string16 UI::GetWindowTitle() const { + // TODO(beng): use resources. + return base::ASCIIToUTF16("Login"); +} + +void UI::DeleteDelegate() { + delete this; +} + +void UI::Layout() { + gfx::Rect button_box = GetLocalBounds(); + button_box.Inset(10, 10); + + gfx::Size ps1 = login_button_1_->GetPreferredSize(); + gfx::Size ps2 = login_button_2_->GetPreferredSize(); + + DCHECK(ps1.height() == ps2.height()); + + // The 10 is inter-button spacing. + button_box.set_x((button_box.width() - ps1.width() - ps2.width() - 10) / 2); + button_box.set_y((button_box.height() - ps1.height()) / 2); + + login_button_1_->SetBounds(button_box.x(), button_box.y(), ps1.width(), + ps1.height()); + login_button_2_->SetBounds(login_button_1_->bounds().right() + 10, + button_box.y(), ps2.width(), ps2.height()); +} + +void UI::ButtonPressed(views::Button* sender, const ui::Event& event) { + // Login... + if (sender == login_button_1_) { + user_access_manager_->SetActiveUser(user_id_1_); + login_controller_->init()->StartService("mojo:mash_shell", user_id_1_); + } else if (sender == login_button_2_) { + user_access_manager_->SetActiveUser(user_id_2_); + login_controller_->init()->StartService("mojo:mash_shell", user_id_2_); + } else { + NOTREACHED(); + } + GetWidget()->Close(); +} + +void UI::StartWindowManager() { + window_manager_connection_ = connector_->Connect("mojo:desktop_wm"); + window_manager_connection_->SetConnectionLostClosure( + base::Bind(&UI::StartWindowManager, base::Unretained(this))); +} + +} // namespace login +} // namespace mash diff --git a/mash/login/ui.h b/mash/login/ui.h new file mode 100644 index 0000000..4c141c4 --- /dev/null +++ b/mash/login/ui.h @@ -0,0 +1,69 @@ +// 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. + +#ifndef MASH_LOGIN_UI_H_ +#define MASH_LOGIN_UI_H_ + +#include <map> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "components/mus/public/interfaces/user_access_manager.mojom.h" +#include "ui/views/controls/button/label_button.h" +#include "ui/views/widget/widget_delegate.h" + +namespace mojo { +class Connection; +class Connector; +} + +namespace views { +class AuraInit; +} + +namespace mash { +namespace login { + +class LoginController; + +class UI : public views::WidgetDelegateView, + public views::ButtonListener { + public: + static void Show(mojo::Connector* connector, + LoginController* login_controller); + + private: + UI(LoginController* login_controller, mojo::Connector* connector); + ~UI() override; + + // Overridden from views::WidgetDelegate: + views::View* GetContentsView() override; + base::string16 GetWindowTitle() const override; + void DeleteDelegate() override; + + // Overridden from views::View: + void Layout() override; + + // Overridden from views::ButtonListener: + void ButtonPressed(views::Button* sender, const ui::Event& event) override; + + void StartWindowManager(); + + static bool is_showing_; + LoginController* login_controller_; + mojo::Connector* connector_; + const std::string user_id_1_; + const std::string user_id_2_; + views::LabelButton* login_button_1_; + views::LabelButton* login_button_2_; + mus::mojom::UserAccessManagerPtr user_access_manager_; + scoped_ptr<mojo::Connection> window_manager_connection_; + + DISALLOW_COPY_AND_ASSIGN(UI); +}; + +} // namespace login +} // namespace mash + +#endif // MASH_LOGIN_UI_H_ diff --git a/mojo/shell/shell.cc b/mojo/shell/shell.cc index beb0fb7b..6fb4874 100644 --- a/mojo/shell/shell.cc +++ b/mojo/shell/shell.cc @@ -39,6 +39,7 @@ const char kShellName[] = "mojo:shell"; const char kCapabilityClass_UserID[] = "user_id"; const char kCapabilityClass_ClientProcess[] = "client_process"; const char kCapabilityClass_InstanceName[] = "instance_name"; +const char kCapabilityClass_AllUsers[] = "all_users"; void EmptyResolverCallback(const String& resolved_name, const String& resolved_instance, @@ -96,6 +97,13 @@ CapabilityRequest GenerateCapabilityRequestForConnection( return request; } +bool HasClass(const CapabilitySpec& spec, const std::string& class_name) { + auto it = spec.required.find(kShellName); + if (it == spec.required.end()) + return false; + return it->second.classes.find(class_name) != it->second.classes.end(); +} + // Encapsulates a connection to an instance of an application, tracked by the // shell's Shell. class Shell::Instance : public mojom::Connector, @@ -206,6 +214,9 @@ class Shell::Instance : public mojom::Connector, return info; } + const CapabilitySpec& capability_spec() const { + return capability_spec_; + } const Identity& identity() const { return identity_; } uint32_t id() const { return id_; } @@ -289,7 +300,7 @@ class Shell::Instance : public mojom::Connector, const Identity& target, const ConnectCallback& callback) { if (!client_process_connection->is_null()) { - if (!HasClass(kCapabilityClass_ClientProcess)) { + if (!HasClass(capability_spec_, kCapabilityClass_ClientProcess)) { LOG(ERROR) << "Error: Instance: " << identity_.name() << " attempting " << "to register an instance for a process it created for " << "target: " << target.name() << " without the " @@ -327,7 +338,7 @@ class Shell::Instance : public mojom::Connector, // - a non-null client_process_connection. if (target.user_id() != identity_.user_id() && target.user_id() != mojom::kRootUserID && - !HasClass(kCapabilityClass_UserID)) { + !HasClass(capability_spec_, kCapabilityClass_UserID)) { LOG(ERROR) << "Instance: " << identity_.name() << " running as: " << identity_.user_id() << " attempting to connect to: " << target.name() << " as: " << target.user_id() << " without " @@ -338,7 +349,7 @@ class Shell::Instance : public mojom::Connector, } if (!target.instance().empty() && target.instance() != GetNamePath(target.name()) && - !HasClass(kCapabilityClass_InstanceName)) { + !HasClass(capability_spec_, kCapabilityClass_InstanceName)) { LOG(ERROR) << "Instance: " << identity_.name() << " attempting to " << "connect to " << target.name() << " using Instance name: " << target.instance() << " without the " @@ -361,13 +372,6 @@ class Shell::Instance : public mojom::Connector, return false; } - bool HasClass(const std::string& class_name) const { - auto it = capability_spec_.required.find(kShellName); - if (it == capability_spec_.required.end()) - return false; - return it->second.classes.find(class_name) != it->second.classes.end(); - } - uint32_t GenerateUniqueID() const { static uint32_t id = mojom::kInvalidInstanceID; ++id; @@ -563,6 +567,15 @@ Shell::Instance* Shell::GetExistingOrRootInstance( const Identity& identity) const { Instance* instance = GetExistingInstance(identity); if (!instance) { + if (singletons_.find(identity.name()) != singletons_.end()) { + for (auto entry : identity_to_instance_) { + if (entry.first.name() == identity.name() && + entry.first.instance() == identity.instance()) { + return entry.second; + } + } + } + Identity root_identity = identity; root_identity.set_user_id(mojom::kRootUserID); instance = GetExistingInstance(root_identity); @@ -672,6 +685,11 @@ void Shell::OnGotResolvedName(mojom::ShellResolverPtr resolver, if (!capabilities_ptr.is_null()) capabilities = capabilities_ptr.To<CapabilitySpec>(); + // Clients that request "all_users" class from the shell are allowed to + // field connection requests from any user. + if (HasClass(capabilities, kCapabilityClass_AllUsers)) + singletons_.insert(target.name()); + mojom::ClientProcessConnectionPtr client_process_connection = params->TakeClientProcessConnection(); Instance* instance = CreateInstance(target, capabilities); diff --git a/mojo/shell/shell.h b/mojo/shell/shell.h index ca5e211..7128a24 100644 --- a/mojo/shell/shell.h +++ b/mojo/shell/shell.h @@ -179,6 +179,10 @@ class Shell : public ShellClient { IdentityToInstanceMap identity_to_instance_; + // Tracks the names of instances that are allowed to field connection requests + // from all users. + std::set<std::string> singletons_; + IdentityToShellClientFactoryMap shell_client_factories_; // Counter used to assign ids to client factories. uint32_t shell_client_factory_id_counter_; diff --git a/ui/views/mus/window_manager_connection.cc b/ui/views/mus/window_manager_connection.cc index a7841fd..8b6398a 100644 --- a/ui/views/mus/window_manager_connection.cc +++ b/ui/views/mus/window_manager_connection.cc @@ -44,6 +44,11 @@ WindowManagerConnection* WindowManagerConnection::Get() { } // static +bool WindowManagerConnection::Exists() { + return !!lazy_tls_ptr.Pointer()->Get(); +} + +// static void WindowManagerConnection::Reset() { delete Get(); lazy_tls_ptr.Pointer()->Set(nullptr); diff --git a/ui/views/mus/window_manager_connection.h b/ui/views/mus/window_manager_connection.h index 4e16e41..6905989 100644 --- a/ui/views/mus/window_manager_connection.h +++ b/ui/views/mus/window_manager_connection.h @@ -39,6 +39,7 @@ class VIEWS_MUS_EXPORT WindowManagerConnection public: static void Create(mojo::Connector* connector); static WindowManagerConnection* Get(); + static bool Exists(); // Destroys the singleton instance. static void Reset(); |