summaryrefslogtreecommitdiffstats
path: root/mojo
diff options
context:
space:
mode:
authorben <ben@chromium.org>2016-03-10 22:15:00 -0800
committerCommit bot <commit-bot@chromium.org>2016-03-11 06:16:22 +0000
commit191b85068b4db3a79ff4853edef91857e98c68ea (patch)
treeaf88c55a16d5e6f540ec0616011d0cc41089f4f9 /mojo
parent6d73307a343d46cc399268b661ae5ef217b5d3be (diff)
downloadchromium_src-191b85068b4db3a79ff4853edef91857e98c68ea.zip
chromium_src-191b85068b4db3a79ff4853edef91857e98c68ea.tar.gz
chromium_src-191b85068b4db3a79ff4853edef91857e98c68ea.tar.bz2
Implement capability classes:
- pass the union of the interfaces in the "interfaces" list of the capability request and the interfaces implied by all classes present in the request - pass the class names so they can be used for non-interface capability granting R=sky@chromium.org BUG= Review URL: https://codereview.chromium.org/1781913003 Cr-Commit-Position: refs/heads/master@{#380552}
Diffstat (limited to 'mojo')
-rw-r--r--mojo/shell/public/cpp/connection.h5
-rw-r--r--mojo/shell/public/cpp/lib/connection_impl.cc15
-rw-r--r--mojo/shell/public/cpp/lib/connection_impl.h6
-rw-r--r--mojo/shell/public/cpp/lib/connector_impl.cc6
-rw-r--r--mojo/shell/public/cpp/lib/shell_connection.cc2
-rw-r--r--mojo/shell/shell.cc46
-rw-r--r--mojo/shell/tests/connect/BUILD.gn21
-rw-r--r--mojo/shell/tests/connect/connect_test.mojom17
-rw-r--r--mojo/shell/tests/connect/connect_test_app.cc33
-rw-r--r--mojo/shell/tests/connect/connect_test_app_manifest.json6
-rw-r--r--mojo/shell/tests/connect/connect_test_class_app.cc101
-rw-r--r--mojo/shell/tests/connect/connect_test_class_app_manifest.json10
-rw-r--r--mojo/shell/tests/connect/connect_unittest.cc48
13 files changed, 275 insertions, 41 deletions
diff --git a/mojo/shell/public/cpp/connection.h b/mojo/shell/public/cpp/connection.h
index d3b3b8a..edb4073 100644
--- a/mojo/shell/public/cpp/connection.h
+++ b/mojo/shell/public/cpp/connection.h
@@ -82,6 +82,11 @@ class Connection {
mojo::GetInterface(GetRemoteInterfaces(), ptr);
}
+ // Returns true if the remote application has the specified capability class
+ // specified in its manifest. Only valid for inbound connections. Will return
+ // false for outbound connections.
+ virtual bool HasCapabilityClass(const std::string& class_name) const = 0;
+
// Returns the name that was used by the source application to establish a
// connection to the destination application.
//
diff --git a/mojo/shell/public/cpp/lib/connection_impl.cc b/mojo/shell/public/cpp/lib/connection_impl.cc
index d3585e7..5cfed52 100644
--- a/mojo/shell/public/cpp/lib/connection_impl.cc
+++ b/mojo/shell/public/cpp/lib/connection_impl.cc
@@ -25,7 +25,7 @@ ConnectionImpl::ConnectionImpl(
uint32_t remote_id,
shell::mojom::InterfaceProviderPtr remote_interfaces,
shell::mojom::InterfaceProviderRequest local_interfaces,
- const std::set<std::string>& allowed_interfaces,
+ const CapabilityRequest& capability_request,
State initial_state)
: connection_name_(connection_name),
remote_(remote),
@@ -33,9 +33,9 @@ ConnectionImpl::ConnectionImpl(
state_(initial_state),
local_registry_(std::move(local_interfaces), this),
remote_interfaces_(std::move(remote_interfaces)),
- allowed_interfaces_(allowed_interfaces),
- allow_all_interfaces_(allowed_interfaces_.size() == 1 &&
- allowed_interfaces_.count("*") == 1),
+ capability_request_(capability_request),
+ allow_all_interfaces_(capability_request.interfaces.size() == 1 &&
+ capability_request.interfaces.count("*") == 1),
weak_factory_(this) {}
ConnectionImpl::ConnectionImpl()
@@ -53,6 +53,10 @@ shell::mojom::Connector::ConnectCallback ConnectionImpl::GetConnectCallback() {
////////////////////////////////////////////////////////////////////////////////
// ConnectionImpl, Connection implementation:
+bool ConnectionImpl::HasCapabilityClass(const std::string& class_name) const {
+ return capability_request_.classes.count(class_name) > 0;
+}
+
const std::string& ConnectionImpl::GetConnectionName() {
return connection_name_;
}
@@ -85,7 +89,8 @@ void ConnectionImpl::AddConnectionCompletedClosure(const Closure& callback) {
}
bool ConnectionImpl::AllowsInterface(const std::string& interface_name) const {
- return allow_all_interfaces_ || allowed_interfaces_.count(interface_name);
+ return allow_all_interfaces_ ||
+ capability_request_.interfaces.count(interface_name);
}
shell::mojom::InterfaceProvider* ConnectionImpl::GetRemoteInterfaces() {
diff --git a/mojo/shell/public/cpp/lib/connection_impl.h b/mojo/shell/public/cpp/lib/connection_impl.h
index 3247a5a..2c58d86 100644
--- a/mojo/shell/public/cpp/lib/connection_impl.h
+++ b/mojo/shell/public/cpp/lib/connection_impl.h
@@ -11,6 +11,7 @@
#include <string>
#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/shell/public/cpp/capabilities.h"
#include "mojo/shell/public/cpp/connection.h"
#include "mojo/shell/public/cpp/identity.h"
#include "mojo/shell/public/interfaces/connector.mojom.h"
@@ -33,7 +34,7 @@ class ConnectionImpl : public Connection {
uint32_t remote_id,
shell::mojom::InterfaceProviderPtr remote_interfaces,
shell::mojom::InterfaceProviderRequest local_interfaces,
- const std::set<std::string>& allowed_interfaces,
+ const CapabilityRequest& capability_request,
State initial_state);
~ConnectionImpl() override;
@@ -41,6 +42,7 @@ class ConnectionImpl : public Connection {
private:
// Connection:
+ bool HasCapabilityClass(const std::string& class_name) const override;
const std::string& GetConnectionName() override;
const Identity& GetRemoteIdentity() const override;
void SetConnectionLostClosure(const Closure& handler) override;
@@ -68,7 +70,7 @@ class ConnectionImpl : public Connection {
InterfaceRegistry local_registry_;
shell::mojom::InterfaceProviderPtr remote_interfaces_;
- const std::set<std::string> allowed_interfaces_;
+ const CapabilityRequest capability_request_;
const bool allow_all_interfaces_;
base::WeakPtrFactory<ConnectionImpl> weak_factory_;
diff --git a/mojo/shell/public/cpp/lib/connector_impl.cc b/mojo/shell/public/cpp/lib/connector_impl.cc
index 74edbe4..98a7ae5 100644
--- a/mojo/shell/public/cpp/lib/connector_impl.cc
+++ b/mojo/shell/public/cpp/lib/connector_impl.cc
@@ -49,8 +49,8 @@ scoped_ptr<Connection> ConnectorImpl::Connect(ConnectParams* params) {
// TODO(beng): We should filter outgoing interfaces also. The shell must pass
// the manifest CapabilityFilter to the ShellConnection via
// Initialize(), it can be used here.
- std::set<std::string> allowed;
- allowed.insert("*");
+ CapabilityRequest request;
+ request.interfaces.insert("*");
shell::mojom::InterfaceProviderPtr local_interfaces;
shell::mojom::InterfaceProviderRequest local_request =
GetProxy(&local_interfaces);
@@ -60,7 +60,7 @@ scoped_ptr<Connection> ConnectorImpl::Connect(ConnectParams* params) {
scoped_ptr<internal::ConnectionImpl> registry(new internal::ConnectionImpl(
params->target().name(), params->target(),
shell::mojom::kInvalidInstanceID, std::move(remote_interfaces),
- std::move(local_request), allowed, Connection::State::PENDING));
+ std::move(local_request), request, Connection::State::PENDING));
shell::mojom::ShellClientFactoryPtr shell_client_factory;
shell::mojom::PIDReceiverRequest pid_receiver_request;
diff --git a/mojo/shell/public/cpp/lib/shell_connection.cc b/mojo/shell/public/cpp/lib/shell_connection.cc
index 2e2a7ec..b169895 100644
--- a/mojo/shell/public/cpp/lib/shell_connection.cc
+++ b/mojo/shell/public/cpp/lib/shell_connection.cc
@@ -55,7 +55,7 @@ void ShellConnection::AcceptConnection(
scoped_ptr<Connection> registry(new internal::ConnectionImpl(
name, source.To<Identity>(), source_id, std::move(remote_interfaces),
std::move(local_interfaces),
- allowed_capabilities->interfaces.To<std::set<std::string>>(),
+ allowed_capabilities.To<CapabilityRequest>(),
Connection::State::CONNECTED));
if (!client_->AcceptConnection(registry.get()))
return;
diff --git a/mojo/shell/shell.cc b/mojo/shell/shell.cc
index 1daa93a..e5c46b3 100644
--- a/mojo/shell/shell.cc
+++ b/mojo/shell/shell.cc
@@ -55,22 +55,39 @@ CapabilitySpec GetPermissiveCapabilities() {
return capabilities;
}
-CapabilityRequest GetCapabilityRequest(const CapabilitySpec& spec,
- const Identity& identity) {
+CapabilityRequest GetCapabilityRequest(const CapabilitySpec& source_spec,
+ const Identity& target) {
// Start by looking for specs specific to the supplied identity.
- auto it = spec.required.find(identity.name());
- if (it != spec.required.end())
+ auto it = source_spec.required.find(target.name());
+ if (it != source_spec.required.end())
return it->second;
// Fall back to looking for a wildcard rule.
- it = spec.required.find("*");
- if (spec.required.size() == 1 && it != spec.required.end())
+ it = source_spec.required.find("*");
+ if (source_spec.required.size() == 1 && it != source_spec.required.end())
return it->second;
// Finally, nothing is allowed.
return CapabilityRequest();
}
+CapabilityRequest GenerateCapabilityRequestForConnection(
+ const CapabilitySpec& source_spec,
+ const Identity& target,
+ const CapabilitySpec& target_spec) {
+ CapabilityRequest request = GetCapabilityRequest(source_spec, target);
+ // Flatten all interfaces from classes requested by the source into the
+ // allowed interface set in the request.
+ for (const auto& class_name : request.classes) {
+ auto it = target_spec.provided.find(class_name);
+ if (it != target_spec.provided.end()) {
+ for (const auto& interface_name : it->second)
+ request.interfaces.insert(interface_name);
+ }
+ }
+ return request;
+}
+
// Encapsulates a connection to an instance of an application, tracked by the
// shell's Shell.
class Shell::Instance : public mojom::Connector,
@@ -82,13 +99,13 @@ class Shell::Instance : public mojom::Connector,
Instance(mojom::ShellClientPtr shell_client,
mojo::shell::Shell* shell,
const Identity& identity,
- const CapabilitySpec& capabilities)
+ const CapabilitySpec& capability_spec)
: shell_(shell),
id_(GenerateUniqueID()),
identity_(identity),
- capabilities_(capabilities),
- allow_any_application_(capabilities.required.size() == 1 &&
- capabilities.required.count("*") == 1),
+ capability_spec_(capability_spec),
+ allow_any_application_(capability_spec.required.size() == 1 &&
+ capability_spec.required.count("*") == 1),
shell_client_(std::move(shell_client)),
pid_receiver_binding_(this),
weak_factory_(this) {
@@ -117,7 +134,8 @@ class Shell::Instance : public mojom::Connector,
spec.interfaces.insert("*");
Instance* source = shell_->GetExistingInstance(params->source());
if (source) {
- spec = GetCapabilityRequest(source->capabilities_, identity_);
+ spec = GenerateCapabilityRequestForConnection(
+ source->capability_spec_, identity_, capability_spec_);
source_id = source->id();
}
shell_client_->AcceptConnection(
@@ -267,8 +285,8 @@ class Shell::Instance : public mojom::Connector,
bool ValidateCapabilities(const Identity& target,
const ConnectCallback& callback) {
if (allow_any_application_ ||
- capabilities_.required.find(target.name()) !=
- capabilities_.required.end()) {
+ capability_spec_.required.find(target.name()) !=
+ capability_spec_.required.end()) {
return true;
}
LOG(ERROR) << "Capabilities prevented connection from: " <<
@@ -296,7 +314,7 @@ class Shell::Instance : public mojom::Connector,
// process is launched.
const uint32_t id_;
const Identity identity_;
- const CapabilitySpec capabilities_;
+ const CapabilitySpec capability_spec_;
const bool allow_any_application_;
mojom::ShellClientPtr shell_client_;
Binding<mojom::PIDReceiver> pid_receiver_binding_;
diff --git a/mojo/shell/tests/connect/BUILD.gn b/mojo/shell/tests/connect/BUILD.gn
index d2818b2..f55c225 100644
--- a/mojo/shell/tests/connect/BUILD.gn
+++ b/mojo/shell/tests/connect/BUILD.gn
@@ -23,6 +23,7 @@ source_set("connect") {
data_deps = [
":connect_test_app",
+ ":connect_test_class_app",
":connect_test_package",
":manifest",
]
@@ -96,3 +97,23 @@ mojo_application_manifest("connect_test_app_manifest") {
application_name = "connect_test_app"
source = "connect_test_app_manifest.json"
}
+
+mojo_native_application("connect_test_class_app") {
+ testonly = true
+ sources = [
+ "connect_test_class_app.cc",
+ ]
+ deps = [
+ ":connect_test_class_app_manifest",
+ ":interfaces",
+ "//base",
+ "//mojo/common:common_base",
+ "//mojo/shell/public/cpp:sources",
+ "//mojo/shell/public/interfaces",
+ ]
+}
+
+mojo_application_manifest("connect_test_class_app_manifest") {
+ application_name = "connect_test_class_app"
+ source = "connect_test_class_app_manifest.json"
+}
diff --git a/mojo/shell/tests/connect/connect_test.mojom b/mojo/shell/tests/connect/connect_test.mojom
index ba29865..2598f3e 100644
--- a/mojo/shell/tests/connect/connect_test.mojom
+++ b/mojo/shell/tests/connect/connect_test.mojom
@@ -9,12 +9,25 @@ interface ConnectTestService {
GetInstance() => (string instance);
};
-// Interface implemented by a standalone (non-package) app.
+interface ClassInterface {
+ Ping() => (string response);
+};
+
+// Interface implemented by a standalone (non-package) app,
+// mojo:connect_test_app.
interface StandaloneApp {
// Attempts to connect to an application whose name is explicitly allowed by
- // the standalone app's CapabilityFilter, but whose enclosing package is not.
+ // the standalone app's CapabilitySpec, but whose enclosing package is not.
// The connection should be blocked and title should be "uninitialized".
ConnectToAllowedAppInBlockedPackage() => (string title);
+
+ // Connects to mojo:connect_test_class_app & requests ClassInterface from it.
+ // This should be permitted because mojo:connect_test_app requests class
+ // "class" from mojo:connect_test_class_app, which mojo:connect_test_class_app
+ // defines as including ClassInterface.
+ // The response contains the response from ClassInterface::Ping() and
+ // ConnectTestService::GetTitle().
+ ConnectToClassInterface() => (string class_interface_response, string title);
};
struct ConnectionState {
diff --git a/mojo/shell/tests/connect/connect_test_app.cc b/mojo/shell/tests/connect/connect_test_app.cc
index 86ae235..abf51dc 100644
--- a/mojo/shell/tests/connect/connect_test_app.cc
+++ b/mojo/shell/tests/connect/connect_test_app.cc
@@ -17,6 +17,13 @@
namespace mojo {
namespace shell {
+namespace {
+void ReceiveString(std::string* string, base::RunLoop* loop,
+ const std::string& response) {
+ *string = response;
+ loop->Quit();
+}
+}
using GetTitleCallback = test::mojom::ConnectTestService::GetTitleCallback;
@@ -119,6 +126,32 @@ class ConnectTestApp : public ShellClient,
run_loop.Run();
}
}
+ void ConnectToClassInterface(
+ const ConnectToClassInterfaceCallback& callback) override {
+ scoped_ptr<Connection> connection =
+ connector_->Connect("mojo:connect_test_class_app");
+ test::mojom::ClassInterfacePtr class_interface;
+ connection->GetInterface(&class_interface);
+ std::string ping_response;
+ {
+ base::RunLoop loop;
+ class_interface->Ping(base::Bind(&ReceiveString, &ping_response, &loop));
+ base::MessageLoop::ScopedNestableTaskAllower allow(
+ base::MessageLoop::current());
+ loop.Run();
+ }
+ test::mojom::ConnectTestServicePtr service;
+ connection->GetInterface(&service);
+ std::string title_response;
+ {
+ base::RunLoop loop;
+ service->GetTitle(base::Bind(&ReceiveString, &title_response, &loop));
+ base::MessageLoop::ScopedNestableTaskAllower allow(
+ base::MessageLoop::current());
+ loop.Run();
+ }
+ callback.Run(ping_response, title_response);
+ }
// test::mojom::BlockedInterface:
void GetTitleBlocked(const GetTitleBlockedCallback& callback) override {
diff --git a/mojo/shell/tests/connect/connect_test_app_manifest.json b/mojo/shell/tests/connect/connect_test_app_manifest.json
index ae25a53..8b636b9 100644
--- a/mojo/shell/tests/connect/connect_test_app_manifest.json
+++ b/mojo/shell/tests/connect/connect_test_app_manifest.json
@@ -4,7 +4,11 @@
"display_name": "Connect Test App",
"capabilities": {
"required": {
- "mojo:connect_test_a": { "interfaces": ["*"] }
+ "mojo:connect_test_a": { "interfaces": ["*"] },
+ "mojo:connect_test_class_app": {
+ "classes": ["class"],
+ "interfaces": ["mojo.shell.test.mojom.ConnectTestService"]
+ }
}
}
}
diff --git a/mojo/shell/tests/connect/connect_test_class_app.cc b/mojo/shell/tests/connect/connect_test_class_app.cc
new file mode 100644
index 0000000..5b22dbc
--- /dev/null
+++ b/mojo/shell/tests/connect/connect_test_class_app.cc
@@ -0,0 +1,101 @@
+// 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 "base/bind.h"
+#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "mojo/public/c/system/main.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/shell/public/cpp/application_runner.h"
+#include "mojo/shell/public/cpp/connector.h"
+#include "mojo/shell/public/cpp/interface_factory.h"
+#include "mojo/shell/public/cpp/shell_client.h"
+#include "mojo/shell/public/interfaces/connector.mojom.h"
+#include "mojo/shell/tests/connect/connect_test.mojom.h"
+
+namespace mojo {
+namespace shell {
+
+using GetTitleCallback = test::mojom::ConnectTestService::GetTitleCallback;
+
+class ConnectTestClassApp
+ : public ShellClient,
+ public InterfaceFactory<test::mojom::ConnectTestService>,
+ public InterfaceFactory<test::mojom::ClassInterface>,
+ public test::mojom::ConnectTestService,
+ public test::mojom::ClassInterface {
+ public:
+ ConnectTestClassApp() {}
+ ~ConnectTestClassApp() override {}
+
+ private:
+ // mojo::ShellClient:
+ void Initialize(Connector* connector, const Identity& identity,
+ uint32_t id) override {
+ connector_ = connector;
+ identity_ = identity;
+ }
+ bool AcceptConnection(Connection* connection) override {
+ CHECK(connection->HasCapabilityClass("class"));
+ connection->AddInterface<test::mojom::ConnectTestService>(this);
+ connection->AddInterface<test::mojom::ClassInterface>(this);
+ inbound_connections_.insert(connection);
+ connection->SetConnectionLostClosure(
+ base::Bind(&ConnectTestClassApp::OnConnectionError,
+ base::Unretained(this), connection));
+ return true;
+ }
+
+ // InterfaceFactory<test::mojom::ConnectTestService>:
+ void Create(Connection* connection,
+ test::mojom::ConnectTestServiceRequest request) override {
+ bindings_.AddBinding(this, std::move(request));
+ }
+
+ // InterfaceFactory<test::mojom::ClassInterface>:
+ void Create(Connection* connection,
+ test::mojom::ClassInterfaceRequest request) override {
+ class_interface_bindings_.AddBinding(this, std::move(request));
+ }
+
+ // test::mojom::ConnectTestService:
+ void GetTitle(const GetTitleCallback& callback) override {
+ callback.Run("CLASS APP");
+ }
+ void GetInstance(const GetInstanceCallback& callback) override {
+ callback.Run(identity_.instance());
+ }
+
+ // test::mojom::ClassInterface:
+ void Ping(const PingCallback& callback) override {
+ callback.Run("PONG");
+ }
+
+ void OnConnectionError(Connection* connection) {
+ auto it = inbound_connections_.find(connection);
+ DCHECK(it != inbound_connections_.end());
+ inbound_connections_.erase(it);
+ if (inbound_connections_.empty())
+ base::MessageLoop::current()->QuitWhenIdle();
+ }
+
+ Connector* connector_ = nullptr;
+ Identity identity_;
+ std::set<Connection*> inbound_connections_;
+ BindingSet<test::mojom::ConnectTestService> bindings_;
+ BindingSet<test::mojom::ClassInterface> class_interface_bindings_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConnectTestClassApp);
+};
+
+} // namespace shell
+} // namespace mojo
+
+
+MojoResult MojoMain(MojoHandle shell_handle) {
+ MojoResult rv = mojo::ApplicationRunner(
+ new mojo::shell::ConnectTestClassApp).Run(shell_handle);
+ return rv;
+}
diff --git a/mojo/shell/tests/connect/connect_test_class_app_manifest.json b/mojo/shell/tests/connect/connect_test_class_app_manifest.json
new file mode 100644
index 0000000..492f679
--- /dev/null
+++ b/mojo/shell/tests/connect/connect_test_class_app_manifest.json
@@ -0,0 +1,10 @@
+{
+ "manifest_version": 1,
+ "name": "mojo:connect_test_class_app",
+ "display_name": "Connect Test Class App",
+ "capabilities": {
+ "provided": {
+ "class": ["mojo.shell.test.mojom.ClassInterface"]
+ }
+ }
+}
diff --git a/mojo/shell/tests/connect/connect_unittest.cc b/mojo/shell/tests/connect/connect_unittest.cc
index 38aee7a..0c65d9d 100644
--- a/mojo/shell/tests/connect/connect_unittest.cc
+++ b/mojo/shell/tests/connect/connect_unittest.cc
@@ -29,10 +29,18 @@ const char kTestAppName[] = "mojo:connect_test_app";
const char kTestAppAName[] = "mojo:connect_test_a";
const char kTestAppBName[] = "mojo:connect_test_b";
-void ReceiveTitle(std::string* out_name,
- base::RunLoop* loop,
- const String& name) {
- *out_name = name;
+void ReceiveOneString(std::string* out_string,
+ base::RunLoop* loop,
+ const String& in_string) {
+ *out_string = in_string;
+ loop->Quit();
+}
+
+void ReceiveTwoStrings(std::string* out_string_1, std::string* out_string_2,
+ base::RunLoop* loop,
+ const String& in_string_1, const String& in_string_2) {
+ *out_string_1 = in_string_1;
+ *out_string_2 = in_string_2;
loop->Quit();
}
@@ -93,7 +101,8 @@ class ConnectTest : public mojo::test::ShellTest,
connection->GetInterface(&root_service);
base::RunLoop run_loop;
std::string root_name;
- root_service->GetTitle(base::Bind(&ReceiveTitle, &root_name, &run_loop));
+ root_service->GetTitle(
+ base::Bind(&ReceiveOneString, &root_name, &run_loop));
run_loop.Run();
}
@@ -123,7 +132,7 @@ TEST_F(ConnectTest, Connect) {
connection->GetInterface(&service);
base::RunLoop run_loop;
std::string title;
- service->GetTitle(base::Bind(&ReceiveTitle, &title, &run_loop));
+ service->GetTitle(base::Bind(&ReceiveOneString, &title, &run_loop));
run_loop.Run();
EXPECT_EQ("APP", title);
EXPECT_FALSE(connection->IsPending());
@@ -141,14 +150,14 @@ TEST_F(ConnectTest, Instances) {
{
connection_a1->GetInterface(&service_a1);
base::RunLoop loop;
- service_a1->GetInstance(base::Bind(&ReceiveTitle, &instance_a1, &loop));
+ service_a1->GetInstance(base::Bind(&ReceiveOneString, &instance_a1, &loop));
loop.Run();
}
test::mojom::ConnectTestServicePtr service_a2;
{
connection_a2->GetInterface(&service_a2);
base::RunLoop loop;
- service_a2->GetInstance(base::Bind(&ReceiveTitle, &instance_a2, &loop));
+ service_a2->GetInstance(base::Bind(&ReceiveOneString, &instance_a2, &loop));
loop.Run();
}
EXPECT_EQ(instance_a1, instance_a2);
@@ -161,7 +170,7 @@ TEST_F(ConnectTest, Instances) {
{
connection_b->GetInterface(&service_b);
base::RunLoop loop;
- service_b->GetInstance(base::Bind(&ReceiveTitle, &instance_b, &loop));
+ service_b->GetInstance(base::Bind(&ReceiveOneString, &instance_b, &loop));
loop.Run();
}
@@ -188,7 +197,7 @@ TEST_F(ConnectTest, PreferUnresolvedDefaultInstanceName) {
test::mojom::ConnectTestServicePtr service;
connection->GetInterface(&service);
base::RunLoop loop;
- service->GetInstance(base::Bind(&ReceiveTitle, &instance, &loop));
+ service->GetInstance(base::Bind(&ReceiveOneString, &instance, &loop));
loop.Run();
}
EXPECT_EQ(GetNamePath(kTestAppName), instance);
@@ -203,7 +212,7 @@ TEST_F(ConnectTest, BlockedInterface) {
connection->GetInterface(&blocked);
blocked.set_connection_error_handler(base::Bind(&QuitLoop, &run_loop));
std::string title = "unchanged";
- blocked->GetTitleBlocked(base::Bind(&ReceiveTitle, &title, &run_loop));
+ blocked->GetTitleBlocked(base::Bind(&ReceiveOneString, &title, &run_loop));
run_loop.Run();
EXPECT_EQ("unchanged", title);
}
@@ -215,7 +224,7 @@ TEST_F(ConnectTest, PackagedApp) {
connection->GetInterface(&service_a);
base::RunLoop run_loop;
std::string a_name;
- service_a->GetTitle(base::Bind(&ReceiveTitle, &a_name, &run_loop));
+ service_a->GetTitle(base::Bind(&ReceiveOneString, &a_name, &run_loop));
run_loop.Run();
EXPECT_EQ("A", a_name);
EXPECT_FALSE(connection->IsPending());
@@ -234,7 +243,7 @@ TEST_F(ConnectTest, BlockedPackage) {
base::RunLoop run_loop;
std::string title;
standalone_app->ConnectToAllowedAppInBlockedPackage(
- base::Bind(&ReceiveTitle, &title, &run_loop));
+ base::Bind(&ReceiveOneString, &title, &run_loop));
run_loop.Run();
EXPECT_EQ("uninitialized", title);
}
@@ -264,6 +273,19 @@ TEST_F(ConnectTest, BlockedPackagedApplication) {
EXPECT_EQ(mojom::kInvalidInstanceID, connection->GetRemoteInstanceID());
}
+TEST_F(ConnectTest, CapabilityClasses) {
+ scoped_ptr<Connection> connection = connector()->Connect(kTestAppName);
+ test::mojom::StandaloneAppPtr standalone_app;
+ connection->GetInterface(&standalone_app);
+ std::string string1, string2;
+ base::RunLoop loop;
+ standalone_app->ConnectToClassInterface(
+ base::Bind(&ReceiveTwoStrings, &string1, &string2, &loop));
+ loop.Run();
+ EXPECT_EQ("PONG", string1);
+ EXPECT_EQ("CLASS APP", string2);
+}
+
// Tests that we can expose an interface to targets on outbound connections.
// TODO(beng): Currently all interfaces on outbound connections are exposed.
// See ConnectorImpl::Connect().