Commit 301463ed authored by Fabrice de Gans-Riberi's avatar Fabrice de Gans-Riberi Committed by Commit Bot

[fuchsia] Add "debug" ServiceDirectory support.

Bug: 920920
Change-Id: If3d67f02111cced48e7483b8d952a4ef00c40037
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1614688
Commit-Queue: Fabrice de Gans-Riberi <fdegans@chromium.org>
Reviewed-by: default avatarWez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#660701}
parent 58bbffd4
......@@ -10,6 +10,7 @@
#include <zircon/processargs.h>
#include "base/fuchsia/fuchsia_logging.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop_current.h"
#include "base/no_destructor.h"
......@@ -27,8 +28,11 @@ ServiceDirectory::~ServiceDirectory() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(services_.empty());
zx_status_t status = svc_dir_destroy(svc_dir_);
ZX_DCHECK(status == ZX_OK, status);
// Only the root ServiceDirectory "owns" svc_dir_.
if (!sub_directory_) {
zx_status_t status = svc_dir_destroy(svc_dir_);
ZX_DCHECK(status == ZX_OK, status);
}
}
// static
......@@ -48,6 +52,8 @@ void ServiceDirectory::Initialize(
svc_dir_create(async_get_default_dispatcher(),
request.TakeChannel().release(), &svc_dir_);
ZX_CHECK(status == ZX_OK, status);
debug_ = WrapUnique(new ServiceDirectory(svc_dir_, "debug"));
}
void ServiceDirectory::AddServiceUnsafe(
......@@ -60,21 +66,29 @@ void ServiceDirectory::AddServiceUnsafe(
std::string name_str = name.as_string();
services_[name_str] = connect_callback;
// Publish to "svc".
zx_status_t status =
svc_dir_add_service(svc_dir_, "svc", name_str.c_str(), this,
&ServiceDirectory::HandleConnectRequest);
ZX_DCHECK(status == ZX_OK, status);
// Publish to "public" for compatibility.
status = svc_dir_add_service(svc_dir_, "public", name_str.c_str(), this,
&ServiceDirectory::HandleConnectRequest);
ZX_DCHECK(status == ZX_OK, status);
// Publish to the legacy "flat" namespace, which is required by some clients.
status = svc_dir_add_service(svc_dir_, nullptr, name_str.c_str(), this,
&ServiceDirectory::HandleConnectRequest);
ZX_DCHECK(status == ZX_OK, status);
if (sub_directory_) {
zx_status_t status =
svc_dir_add_service(svc_dir_, sub_directory_, name_str.c_str(), this,
&ServiceDirectory::HandleConnectRequest);
ZX_DCHECK(status == ZX_OK, status);
} else {
// Publish to "svc".
zx_status_t status =
svc_dir_add_service(svc_dir_, "svc", name_str.c_str(), this,
&ServiceDirectory::HandleConnectRequest);
ZX_DCHECK(status == ZX_OK, status);
// Publish to "public" for compatibility.
status = svc_dir_add_service(svc_dir_, "public", name_str.c_str(), this,
&ServiceDirectory::HandleConnectRequest);
ZX_DCHECK(status == ZX_OK, status);
// Publish to the legacy "flat" namespace, which is required by some
// clients.
status = svc_dir_add_service(svc_dir_, nullptr, name_str.c_str(), this,
&ServiceDirectory::HandleConnectRequest);
ZX_DCHECK(status == ZX_OK, status);
}
}
void ServiceDirectory::RemoveService(StringPiece name) {
......@@ -87,14 +101,20 @@ void ServiceDirectory::RemoveService(StringPiece name) {
DCHECK(it != services_.end());
services_.erase(it);
// Unregister from "svc", "public", and flat namespace.
zx_status_t status =
svc_dir_remove_service(svc_dir_, "svc", name_str.c_str());
ZX_DCHECK(status == ZX_OK, status);
status = svc_dir_remove_service(svc_dir_, "public", name_str.c_str());
ZX_DCHECK(status == ZX_OK, status);
status = svc_dir_remove_service(svc_dir_, nullptr, name_str.c_str());
ZX_DCHECK(status == ZX_OK, status);
if (sub_directory_) {
zx_status_t status =
svc_dir_remove_service(svc_dir_, sub_directory_, name_str.c_str());
ZX_DCHECK(status == ZX_OK, status);
} else {
// Unregister from "svc", "public", and flat namespace.
zx_status_t status =
svc_dir_remove_service(svc_dir_, "svc", name_str.c_str());
ZX_DCHECK(status == ZX_OK, status);
status = svc_dir_remove_service(svc_dir_, "public", name_str.c_str());
ZX_DCHECK(status == ZX_OK, status);
status = svc_dir_remove_service(svc_dir_, nullptr, name_str.c_str());
ZX_DCHECK(status == ZX_OK, status);
}
}
void ServiceDirectory::RemoveAllServices() {
......@@ -119,5 +139,12 @@ void ServiceDirectory::HandleConnectRequest(void* context,
it->second.Run(zx::channel(service_request));
}
ServiceDirectory::ServiceDirectory(svc_dir_t* svc_dir, const char* name) {
DCHECK(svc_dir);
svc_dir_ = svc_dir;
sub_directory_ = name;
}
} // namespace fuchsia
} // namespace base
......@@ -31,6 +31,8 @@ namespace fuchsia {
// implementation is destroyed. GetDefault() should be used to get the default
// ServiceDirectory for the current process. The default instance exports
// services via a channel supplied at process creation time.
// Debug services are published to a "debug" sub-directory only accessible by
// other services via the Hub.
//
// Not thread-safe. All methods must be called on the thread that created the
// object.
......@@ -71,6 +73,9 @@ class BASE_EXPORT ServiceDirectory {
void RemoveService(StringPiece name);
void RemoveAllServices();
// Returns the debug ServiceDirectory.
ServiceDirectory* debug() const { return debug_.get(); }
// Passes requests for |name| through to a generic |connect_callback|.
// This is used only when proxying requests for interfaces not known at
// compile-time. Use the type-safe APIs above whenever possible.
......@@ -78,6 +83,9 @@ class BASE_EXPORT ServiceDirectory {
RepeatingCallback<void(zx::channel)> connect_callback);
private:
// Sub-directory constructor.
ServiceDirectory(svc_dir_t* svc_dir, const char* name);
// Called by |svc_dir_| to handle service requests.
static void HandleConnectRequest(void* context,
const char* service_name,
......@@ -85,9 +93,17 @@ class BASE_EXPORT ServiceDirectory {
THREAD_CHECKER(thread_checker_);
// Owned by the root directory.
svc_dir_t* svc_dir_ = nullptr;
flat_map<std::string, RepeatingCallback<void(zx::channel)>> services_;
// The debug sub-directory. Empty if this is a sub-directory.
std::unique_ptr<ServiceDirectory> debug_;
// If mon-null, this directory represents a sub-directory of the root
// ServiceDirectory.
const char* sub_directory_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ServiceDirectory);
};
......
......@@ -31,6 +31,15 @@ ServiceDirectoryTestBase::ServiceDirectoryTestBase() {
public_service_directory_client_ =
std::make_unique<ServiceDirectoryClient>(std::move(svc_directory));
// Create the ServiceDirectoryClient, connected to the "debug" sub-directory.
fidl::InterfaceHandle<::fuchsia::io::Directory> debug_directory;
CHECK_EQ(fdio_service_connect_at(
directory.channel().get(), "/debug/.",
debug_directory.NewRequest().TakeChannel().release()),
ZX_OK);
debug_service_directory_client_ =
std::make_unique<ServiceDirectoryClient>(std::move(debug_directory));
// Create the ServiceDirectoryClient, connected to the "public" sub-directory
// (same contents as "svc", provided for compatibility).
fidl::InterfaceHandle<::fuchsia::io::Directory> public_directory;
......
......@@ -35,6 +35,7 @@ class ServiceDirectoryTestBase : public testing::Test {
service_binding_;
std::unique_ptr<ServiceDirectoryClient> public_service_directory_client_;
std::unique_ptr<ServiceDirectoryClient> debug_service_directory_client_;
std::unique_ptr<ServiceDirectoryClient>
legacy_public_service_directory_client_;
std::unique_ptr<ServiceDirectoryClient> root_service_directory_client_;
......
......@@ -96,5 +96,23 @@ TEST_F(ServiceDirectoryTest, NoService) {
VerifyTestInterface(&stub, ZX_ERR_PEER_CLOSED);
}
// Verify that we can connect to a debug service.
TEST_F(ServiceDirectoryTest, ConnectDebugService) {
// Remove the public service binding.
service_binding_.reset();
// Publish the test service to the "debug" directory.
ScopedServiceBinding<testfidl::TestInterface> debug_service_binding(
service_directory_->debug(), &test_service_);
auto debug_stub = debug_service_directory_client_
->ConnectToService<testfidl::TestInterface>();
VerifyTestInterface(&debug_stub, ZX_OK);
auto release_stub = public_service_directory_client_
->ConnectToService<testfidl::TestInterface>();
VerifyTestInterface(&release_stub, ZX_ERR_PEER_CLOSED);
}
} // namespace fuchsia
} // namespace base
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment