IPDL/Five minute example

This page walks you through the steps of creating an IPDL protocol and writing the C++ code that implements the required interfaces. This guide walks you through the steps taken to implement the testing code in ipc/test-harness. You are encouraged to follow this guide step-by-step and change the code in ipc/test-harness as you follow along.

Write the IPDL specification

Put this in the file ipc/test-harness/Test.ipdl.

namespace mozilla {
namespace test {

sync protocol Test
{
both:
    sync Ping() returns (int status);

parent:
    GetValue(String key);
    GetValues(StringArray keys);
    sync SetValue(String key, String val) returns (bool ok);

child:
    TellValue(String key, String val);
    TellValues(StringArray keys, StringArray vals);

state START:
    recv Ping goto START;
    send Ping goto START;

    recv SetValue goto HAVE_VALUES;

state HAVE_VALUES:
    recv Ping goto HAVE_VALUES;
    send Ping goto HAVE_VALUES;

    recv SetValue goto HAVE_VALUES;

    recv GetValue goto TELLING_VALUE;
    recv GetValues goto TELLING_VALUES;

state TELLING_VALUE:
    send TellValue goto HAVE_VALUES;
state TELLING_VALUES:
    send TellValues goto HAVE_VALUES;
};

} // namespace test
} // namespace mozilla

Hook the IPDL file into our build system

  • Add ipc/test-harness to the IPDLDIRS variable in ipc/ipdl/Makefile.in
  • Create the file ipc/test-harness/ipdl.mk and add the following text to it.
IPDLSRCS = \
  Test.ipdl \
  $(NULL)

Create the C++ implementation stubs

  • Run
ipc/test-harness$ python ../ipdl.py -d /tmp Test.ipdl
  • Open /tmp/mozilla/test/TestProtocolParent.h. Look for the text "Skeleton implementation of abstract actor class."
    • copy the "Header file contents" into the file ipc/test-harness/TestParent.h
    • make the TestParent constructor and destructor public
    • copy the "C++ file contents" into ipc/test-harness/TestParent.cpp
    • globally replace the text ActorImpl with TestParent in both files.
    • set up namespaces as you wish. The checked-in example puts TestParent in the mozilla::test namespace.
  • Repeat the above step for TestProtocolChild.h and TestChild.(h, cpp)

Hook the C++ stubs into your build configuration

This is beyond the scope of this guide. See ipc/test-harness/Makefile.in for an example.

It's a good idea to check now that everything compiles.

Create the subprocess class

This class is instantiated in the main process, and launches and tracks the actual child process.

Create the files ipc/test-harness/TestProcessParent.h and ipc/test-harness/TestProcessParent.cpp with the following content.

// TestProcessParent.h
#ifndef mozilla_test_TestProcessParent_h
#define mozilla_test_TestProcessParent_h 1

#include "mozilla/ipc/GeckoChildProcessHost.h"

namespace mozilla {
namespace test {

class TestProcessParent : mozilla::ipc::GeckoChildProcessHost
{
public:
    TestProcessParent();
    ~TestProcessParent();

    /**
     * Asynchronously launch the plugin process.
     */
    // Could override parent Launch, but don't need to here
    //bool Launch();

private:
    DISALLOW_EVIL_CONSTRUCTORS(TestProcessParent);
};

} // namespace plugins
} // namespace mozilla
#endif // ifndef mozilla_test_TestProcessParent_h
// TestProcessParent.cpp
#include "mozilla/test/TestProcessParent.h"
using mozilla::ipc::GeckoChildProcessHost;

namespace mozilla {
namespace test {

TestProcessParent::TestProcessParent() :
    GeckoChildProcessHost(GeckoChildProcess_TestHarness)
{
}

TestProcessParent::~TestProcessParent()
{
}

} // namespace test
} // namespace mozilla

Now open nsXULAppAPI.h and add the new value GeckoChildProcess_TestHarness to the enumeration GeckoChildProcessType. (Yes, this sucks. Sorry.)

Hook this new code into your build system and verify that everything still compiles.

Create the child process's main thread

Create the files ipc/test-harness/TestThreadChild.h and ipc/test-harness/TestThreadChild.cpp with the following content.