chromium/native_client_sdk/src/examples/api/messaging/messaging.cc

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

#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/instance_handle.h"
#include "ppapi/cpp/message_handler.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_array.h"
#include "ppapi/utility/threading/simple_thread.h"

#ifdef WIN32
#undef PostMessage
// Allow 'this' in initializer list
#pragma warning(disable : 4355)
#endif

class MessageHandler : public pp::MessageHandler {
 public:
  virtual void HandleMessage(pp::InstanceHandle instance,
                             const pp::Var& message_data) {
    if (!message_data.is_array()) {
      return;
    }

    pp::VarArray array(message_data);
    pp::Var response = SumArray(array);

    // Send the response back to JavaScript asynchronously.
    pp::Instance(instance.pp_instance()).PostMessage(response);
  }

  virtual pp::Var HandleBlockingMessage(pp::InstanceHandle instance,
                                        const pp::Var& message_data) {
    if (!message_data.is_array()) {
      // Return an undefined value.
      return pp::Var();
    }

    pp::VarArray array(message_data);

    // Send the response back to JavaScript synchronously.
    return SumArray(array);
  }

  virtual void WasUnregistered(pp::InstanceHandle instance) {}

  pp::Var SumArray(const pp::VarArray& array) {
    int32_t result = 0;
    for (uint32_t i = 0, length = array.GetLength(); i < length; ++i) {
      if (!array.Get(i).is_int()) {
        continue;
      }

      result += array.Get(i).AsInt();
    }

    return pp::Var(result);
  }
};

class Instance : public pp::Instance {
 public:
  explicit Instance(PP_Instance instance)
      : pp::Instance(instance), thread_(this) {}

  virtual bool Init(uint32_t /*argc*/,
                    const char* /*argn*/ [],
                    const char* /*argv*/ []) {
    thread_.Start();

    // The message handler must be registered using a message loop that is not
    // the main thread's messaging loop. This call will fail otherwise.
    RegisterMessageHandler(&message_handler_, thread_.message_loop());
    return true;
  }

 private:
  pp::SimpleThread thread_;
  MessageHandler message_handler_;
};

class Module : public pp::Module {
 public:
  Module() : pp::Module() {}
  virtual ~Module() {}

  virtual pp::Instance* CreateInstance(PP_Instance instance) {
    return new Instance(instance);
  }
};

namespace pp {
Module* CreateModule() { return new ::Module(); }
}  // namespace pp