#ifndef MOJO_PUBLIC_SHELL_SERVICE_H_
#define MOJO_PUBLIC_SHELL_SERVICE_H_
#include <vector>
#include "mojo/public/cpp/bindings/error_handler.h"
#include "mojo/public/cpp/bindings/remote_ptr.h"
#include "mojo/public/cpp/system/core.h"
#include "mojo/public/interfaces/shell/shell.mojom.h"
namespace mojo {
namespace internal {
class ServiceFactoryBase {
public:
class Owner : public ShellClient {
public:
Owner(ScopedShellHandle shell_handle);
~Owner();
Shell* shell() { return shell_.get(); }
virtual void AddServiceFactory(
internal::ServiceFactoryBase* service_factory) = 0;
virtual void RemoveServiceFactory(
internal::ServiceFactoryBase* service_factory) = 0;
protected:
void set_service_factory_owner(ServiceFactoryBase* service_factory,
Owner* owner) {
service_factory->owner_ = owner;
}
RemotePtr<Shell> shell_;
};
ServiceFactoryBase() : owner_(NULL) {}
virtual ~ServiceFactoryBase();
Shell* shell() { return owner_->shell(); }
virtual void AcceptConnection(const std::string& url,
ScopedMessagePipeHandle client_handle) = 0;
protected:
Owner* owner_;
};
}
template <class ServiceImpl, typename Context=void>
class ServiceFactory : public internal::ServiceFactoryBase {
public:
ServiceFactory(Context* context = NULL) : context_(context) {}
virtual ~ServiceFactory() {
for (typename ServiceList::iterator it = services_.begin();
it != services_.end(); ++it) {
delete *it;
}
}
virtual void AcceptConnection(const std::string& url,
ScopedMessagePipeHandle client_handle)
MOJO_OVERRIDE {
ServiceImpl* service = new ServiceImpl();
service->Initialize(this, client_handle.Pass());
services_.push_back(service);
}
void RemoveService(ServiceImpl* service) {
for (typename ServiceList::iterator it = services_.begin();
it != services_.end(); ++it) {
if (*it == service) {
services_.erase(it);
delete service;
if (services_.empty())
owner_->RemoveServiceFactory(this);
return;
}
}
}
Context* context() const { return context_; }
private:
typedef std::vector<ServiceImpl*> ServiceList;
ServiceList services_;
Context* context_;
};
template <class ServiceInterface, class ServiceImpl, typename Context=void>
class Service : public ServiceInterface {
public:
virtual ~Service() {}
protected:
Service() : reaper_(this), service_factory_(NULL) {}
void Initialize(ServiceFactory<ServiceImpl, Context>* service_factory,
ScopedMessagePipeHandle client_handle) {
service_factory_ = service_factory;
client_.reset(
MakeScopedHandle(
InterfaceHandle<typename ServiceInterface::_Peer>(
client_handle.release().value())).Pass(),
this,
&reaper_);
}
Shell* shell() { return service_factory_->shell(); }
Context* context() const { return service_factory_->context(); }
typename ServiceInterface::_Peer* client() { return client_.get(); }
private:
class Reaper : public ErrorHandler {
public:
Reaper(Service<ServiceInterface, ServiceImpl, Context>* service)
: service_(service) {}
virtual void OnError() {
service_->service_factory_->RemoveService(
static_cast<ServiceImpl*>(service_));
}
private:
Service<ServiceInterface, ServiceImpl, Context>* service_;
};
friend class ServiceFactory<ServiceImpl, Context>;
Reaper reaper_;
ServiceFactory<ServiceImpl, Context>* service_factory_;
RemotePtr<typename ServiceInterface::_Peer> client_;
};
}
#endif