chromium/services/service_manager/public/java/src/org/chromium/services/service_manager/InterfaceRegistry.java

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.services.service_manager;

import org.chromium.mojo.bindings.Interface;
import org.chromium.mojo.system.MessagePipeHandle;
import org.chromium.mojo.system.MojoException;
import org.chromium.service_manager.mojom.InterfaceProvider;

import java.util.HashMap;
import java.util.Map;

/**
 * A registry where interfaces may be registered to be exposed to another application.
 *
 * To use, define a class that implements your specific interface. Then
 * implement an InterfaceFactory that creates instances of your implementation
 * and register that on the registry with a Manager for the interface like this:
 *
 *   registry.addInterface(InterfaceType.MANAGER, factory);
 */
public class InterfaceRegistry implements InterfaceProvider {
    private final Map<String, InterfaceBinder> mBinders = new HashMap<String, InterfaceBinder>();

    public <I extends Interface> void addInterface(
            Interface.Manager<I, ? extends Interface.Proxy> manager, InterfaceFactory<I> factory) {
        mBinders.put(manager.getName(), new InterfaceBinder<I>(manager, factory));
    }

    public static InterfaceRegistry create(MessagePipeHandle pipe) {
        InterfaceRegistry registry = new InterfaceRegistry();
        InterfaceProvider.MANAGER.bind(registry, pipe);
        return registry;
    }

    @Override
    public void getInterface(String name, MessagePipeHandle pipe) {
        InterfaceBinder binder = mBinders.get(name);
        if (binder == null) {
            return;
        }
        binder.bindToMessagePipe(pipe);
    }

    @Override
    public void close() {
        mBinders.clear();
    }

    @Override
    public void onConnectionError(MojoException e) {
        close();
    }

    InterfaceRegistry() {}

    private static class InterfaceBinder<I extends Interface> {
        private Interface.Manager<I, ? extends Interface.Proxy> mManager;
        private InterfaceFactory<I> mFactory;

        public InterfaceBinder(
                Interface.Manager<I, ? extends Interface.Proxy> manager,
                InterfaceFactory<I> factory) {
            mManager = manager;
            mFactory = factory;
        }

        public void bindToMessagePipe(MessagePipeHandle pipe) {
            I impl = mFactory.createImpl();
            if (impl == null) {
                pipe.close();
                return;
            }
            mManager.bind(impl, pipe);
        }
    }
}