summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mash/example/window_type_launcher/BUILD.gn2
-rw-r--r--mash/example/window_type_launcher/window_type_launcher.cc10
-rw-r--r--mash/init/BUILD.gn1
-rw-r--r--mash/init/init.cc75
-rw-r--r--mash/init/init.h35
-rw-r--r--mash/init/public/interfaces/BUILD.gn2
-rw-r--r--mash/init/public/interfaces/init.mojom10
-rw-r--r--mash/login/BUILD.gn6
-rw-r--r--mash/login/login.cc139
-rw-r--r--mash/login/login.h23
-rw-r--r--mash/login/main.cc2
-rw-r--r--mash/login/manifest.json10
-rw-r--r--mash/login/public/interfaces/BUILD.gn11
-rw-r--r--mash/login/public/interfaces/login.mojom (renamed from mash/init/public/interfaces/login.mojom)6
-rw-r--r--mash/login/ui.cc135
-rw-r--r--mash/login/ui.h69
-rw-r--r--mojo/shell/shell.cc38
-rw-r--r--mojo/shell/shell.h4
-rw-r--r--ui/views/mus/window_manager_connection.cc5
-rw-r--r--ui/views/mus/window_manager_connection.h1
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(&params);
}
-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(&params);
-}
-
-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(
- &params,
- 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(
- &params,
+ mojo::Identity("mojo:login", login_user_id_));
+ login_connection_ = connector_->Connect(&params);
+ 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();