Files
tubestation/browser/extensions/mortar/host/rpc.h

613 lines
17 KiB
C++

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __rpc_h__
#define __rpc_h__
#include <cmath>
#include <cstring>
#include <iomanip>
#include <map>
#include <string>
#include <sstream>
#include "json/json.h"
extern void Fail(const char *reason, const char *data);
#ifdef INTERPOSE
const void* RealGetInterface(const char* interfaceName);
void Logging_PP_CompletionCallback(void* user_data, int32_t result);
void Logging_PPB_Audio_Callback_1_0(void* sample_buffer,
uint32_t buffer_size_in_bytes,
void* user_data);
struct Logging_PPB_Audio_Callback_1_0_holder {
PPB_Audio_Callback_1_0 func;
void* user_data;
};
struct Logging_PPP_Class_Deprecated_holder {
const PPP_Class_Deprecated* _real_PPP_Class_Deprecated;
const void* object;
};
extern const PPP_Class_Deprecated _interpose_PPP_Class_Deprecated_1_0;
#else // INTERPOSE
void ToHost(std::stringstream &s, bool abortIfNonMainThread);
std::string ToHostWithResult(std::stringstream &s, bool abortIfNonMainThread);
enum RPCType {
WithResult,
NoResult
};
enum RPCThread {
MainThreadOnly,
MaybeNonMainThread
};
template<RPCThread rpcThread>
void RPC(std::stringstream &s) {
return ToHost(s, rpcThread == MainThreadOnly);
}
template<RPCThread rpcThread>
std::string RPCWithResult(std::stringstream &s) {
return ToHostWithResult(s, rpcThread == MainThreadOnly);
}
#endif // INTERPOSE
typedef float float_t;
typedef double double_t;
typedef const void* mem_t;
typedef void* const * mem_ptr_t;
typedef const char* str_t;
typedef const char* cstr_t;
typedef int GLint;
typedef unsigned int GLuint;
typedef unsigned int GLenum;
typedef unsigned int GLbitfield;
typedef unsigned char GLboolean;
typedef float GLclampf;
typedef float GLfloat;
typedef long int GLintptr;
typedef int GLsizei;
typedef long int GLsizeiptr;
typedef const GLint * GLint_ptr_t;
typedef const GLuint * GLuint_ptr_t;
typedef const GLenum * GLenum_ptr_t;
typedef const GLboolean * GLboolean_ptr_t;
typedef const GLfloat * GLfloat_ptr_t;
typedef const GLsizei * GLsizei_ptr_t;
typedef const GLubyte * GLubyte_ptr_t;
#ifdef _WIN32
#include<windows.h>
typedef HANDLE PP_FileHandle;
#else
typedef int PP_FileHandle;
#endif
struct PPP_MessageHandler_0_2;
static void BeginProps(std::stringstream &s) {
s << '{';
}
static void EndProps(std::stringstream &s) {
s << '}';
}
static void BeginProp(std::stringstream &s, const std::string &key) {
if (s.str().back() != '{')
s << ',';
s << '"' << key << "\":";
}
static void AddProp(std::stringstream &s, const std::string &key, const std::string &value) {
BeginProp(s, key);
s << value;
}
static void BeginElements(std::stringstream &s) {
s << '[';
}
static void EndElements(std::stringstream &s) {
s << ']';
}
static void BeginElement(std::stringstream &s) {
if (s.str().back() != '[')
s << ',';
}
static void AddElement(std::stringstream &s, const std::string &value) {
BeginElement(s);
s << value;
}
// Define how to send certain primitive types to the browser.
template <typename T>
static const std::string ToString(const T *value) {
std::stringstream x;
x << *value;
return x.str();
}
static void WriteEscapedChar(std::stringstream& x, const char value)
{
switch (value) {
case '\\':
x << "\\\\";
return;
case '"':
x << "\\" << value;
return;
}
unsigned int v = (unsigned int)value;
if (v <= 0x001f) {
x << "\\u" << std::setw(4) << std::setfill('0') << std::hex << v;
} else {
x << value;
}
}
template <typename T>
static void WriteString(std::stringstream& x, const T *value, size_t length) {
const char* start = *value;
const char* end = start + length;
size_t pos = 0;
while (start != end) {
WriteEscapedChar(x, *(start++));
}
}
template <typename T>
static const std::string StringToQuotedString(const T *value, size_t length) {
std::stringstream x;
x << '"';
WriteString(x, value, length);
x << '"';
return x.str();
}
template <typename T>
static const std::string StringToQuotedString(const T *value) {
return StringToQuotedString(value, strlen(*value));
}
static const std::string StringToQuotedString(const char *value) {
return StringToQuotedString(&value, 1);
}
template <typename T>
static const std::string PointerToString(T *value) {
std::stringstream x;
if (!value) {
x << "null";
} else {
x << (std::intptr_t)value;
}
return x.str();
}
#define DEFINE_TOSTRING_FORWARD_REF_TO_POINTER(T) \
static const std::string ToString_##T(const T &value) { \
return ToString_##T(&value); \
}
#define DEFINE_TOSTRING(T) \
static const std::string ToString_##T(const T *value) { \
return ToString(value); \
} \
DEFINE_TOSTRING_FORWARD_REF_TO_POINTER(T)
#define DEFINE_INT_TOSTRING(T) \
static const std::string ToString_##T(const T *value) { \
std::stringstream x; \
x << std::dec << (int)*value; \
return x.str(); \
} \
DEFINE_TOSTRING_FORWARD_REF_TO_POINTER(T)
#define DEFINE_UNSIGNED_INT_TOSTRING(T) \
static const std::string ToString_##T(const T *value) { \
std::stringstream x; \
x << std::dec << (unsigned int)*value; \
return x.str(); \
} \
DEFINE_TOSTRING_FORWARD_REF_TO_POINTER(T)
#define DEFINE_FLOAT_TOSTRING(T) \
static const std::string ToString_##T(const T *value) { \
switch (std::fpclassify(*value)) { \
case FP_INFINITE: \
case FP_NAN: \
return "null"; \
default: \
return ToString(value); \
} \
} \
DEFINE_TOSTRING_FORWARD_REF_TO_POINTER(T)
#define DEFINE_POINTER_TOSTRING(T) \
static const std::string ToString_##T(const T *value) { \
return PointerToString(*value); \
} \
DEFINE_TOSTRING_FORWARD_REF_TO_POINTER(T)
#define DEFINE_STRING_TOSTRING(T) \
static const std::string ToString_##T(const T *value) { \
return StringToQuotedString(value); \
} \
DEFINE_TOSTRING_FORWARD_REF_TO_POINTER(T)
DEFINE_STRING_TOSTRING(char)
DEFINE_INT_TOSTRING(int8_t)
DEFINE_INT_TOSTRING(int32_t)
DEFINE_INT_TOSTRING(int64_t)
DEFINE_UNSIGNED_INT_TOSTRING(uint8_t)
DEFINE_UNSIGNED_INT_TOSTRING(uint16_t)
DEFINE_UNSIGNED_INT_TOSTRING(uint32_t)
DEFINE_UNSIGNED_INT_TOSTRING(uint64_t)
DEFINE_FLOAT_TOSTRING(float_t)
DEFINE_FLOAT_TOSTRING(double_t)
DEFINE_POINTER_TOSTRING(mem_t)
DEFINE_TOSTRING(mem_ptr_t)
DEFINE_STRING_TOSTRING(str_t)
static const std::string ToString_str_t(const str_t *value, size_t length) {
return StringToQuotedString(value, length);
}
static const std::string ToString_str_t(const str_t &value, size_t length) {
return StringToQuotedString(&value, length);
}
DEFINE_STRING_TOSTRING(cstr_t)
DEFINE_TOSTRING(GLint)
DEFINE_TOSTRING(GLuint)
DEFINE_TOSTRING(GLenum)
DEFINE_TOSTRING(GLbitfield)
static const std::string ToString_GLboolean(const GLboolean *value) {
std::stringstream x;
x << (*value ? "true" : "false");
return x.str();
}
DEFINE_TOSTRING_FORWARD_REF_TO_POINTER(GLboolean)
DEFINE_TOSTRING(GLfloat)
DEFINE_TOSTRING(GLclampf)
DEFINE_TOSTRING(GLintptr)
DEFINE_TOSTRING(GLsizei)
DEFINE_TOSTRING(GLsizeiptr)
DEFINE_TOSTRING(GLuint_ptr_t)
DEFINE_TOSTRING(GLenum_ptr_t)
DEFINE_TOSTRING(GLboolean_ptr_t)
DEFINE_POINTER_TOSTRING(GLint_ptr_t)
DEFINE_POINTER_TOSTRING(GLfloat_ptr_t)
DEFINE_TOSTRING(GLsizei_ptr_t)
DEFINE_TOSTRING(PP_FileHandle)
#ifdef INTERPOSE
static const std::string ToString_GLubyte_ptr_t(const GLubyte *value) {
std::stringstream x;
x << (const char*)value;
return x.str();
}
static const std::string ToString_uint16_ptr_t(const uint16_ptr_t value) {
return "";
}
extern const std::string ToString_PP_DirContents_Dev(const PP_DirContents_Dev *v);
static const std::string ToString_PP_DirContents_Dev(PP_DirContents_Dev **value) {
if (!value && !*value) {
return "{}";
}
return ToString_PP_DirContents_Dev(*value);
}
#endif
// Define how to emit client objects that the client sends to the host. We just want
// to send a pointer value here, not actually unpack the struct.
static const std::string ToString_PPP_MessageHandler(const PPP_MessageHandler_0_2 *value) {
std::stringstream x;
x << value;
return x.str();
}
static const std::string ToString_PPP_Class_Deprecated(const PPP_Class_Deprecated *value) {
return PointerToString(value);
}
class JSONIterator {
JSON::Parser parser;
JSON::Parser::iterator iterator;
JSON::Parser::iterator end;
public:
JSONIterator(const std::string& json)
{
if (parser.parse(json) <= 0) {
Fail("Fatal: failed to parse '%s'\n", json.c_str());
}
iterator = parser.begin();
end = parser.end();
}
bool isValid() const {
return iterator != end;
}
operator const JSON::Token&() const {
return *iterator;
}
void skip() {
++iterator;
}
const JSON::Token& getCurrentAndGotoNext() {
const JSON::Token& token = *iterator;
++iterator;
return token;
}
const JSON::Token& getCurrentPrimitiveAndGotoNext()
{
const JSON::Token& token = getCurrentAndGotoNext();
if (!token.isPrimitive()) {
Fail("Expected primitive", "");
};
return token;
}
const JSON::Token& getCurrentStringAndGotoNext()
{
const JSON::Token& token = getCurrentAndGotoNext();
if (!token.isString()) {
Fail("Expected string", "");
};
return token;
}
const void expectObjectAndGotoFirstProperty()
{
if (!getCurrentAndGotoNext().isObject()) {
Fail("Expected object", "");
}
if (!iterator->isString()) {
Fail("Expected string", "");
}
}
const size_t expectArrayAndGotoFirstItem()
{
const JSON::Token& token = getCurrentAndGotoNext();
if (!token.isArray()) {
Fail("Expected array", "");
}
return token.children();
}
};
template <typename T>
struct OutParam
{
typedef typename std::conditional<std::is_pointer<T>::value, typename std::remove_pointer<T>::type, T>::type nopointer;
typedef typename std::remove_const<nopointer>::type noconst;
typedef typename std::conditional<std::is_pointer<T>::value, typename std::add_pointer<noconst>::type, noconst>::type type;
};
static void FromJSON_int(JSONIterator& iterator, long int& value)
{
value = atol(iterator.getCurrentPrimitiveAndGotoNext().value().c_str());
}
static void FromJSON_uintptr(JSONIterator& iterator, std::uintptr_t& value)
{
long long pointer = std::atoll(iterator.getCurrentPrimitiveAndGotoNext().value().c_str());
value = static_cast<std::uintptr_t>(pointer);
}
template <typename T>
static void PointerValueFromJSON(JSONIterator& iterator, T*& value) {
std::uintptr_t pointer;
FromJSON_uintptr(iterator, pointer);
value = (T*)pointer;
}
static void FromJSON_charArray(JSONIterator& iterator, char* value, size_t count)
{
const JSON::Token& token = iterator.getCurrentStringAndGotoNext();
std::strncpy(value, token.value().c_str(), count);
}
// FIXME Check range?
#define DEFINE_FROMJSON_INT(T) \
static void FromJSON_##T(JSONIterator& iterator, OutParam<T>::type& value) { \
long int v; \
FromJSON_int(iterator, v); \
value = v; \
}
#define DEFINE_FROMJSON_FLOAT(T) \
static void FromJSON_##T(JSONIterator& iterator, OutParam<T>::type& value) \
{ \
value = atof(iterator.getCurrentPrimitiveAndGotoNext().value().c_str()); \
}
DEFINE_FROMJSON_INT(int8_t)
DEFINE_FROMJSON_INT(int32_t)
DEFINE_FROMJSON_INT(int64_t)
DEFINE_FROMJSON_INT(uint8_t)
DEFINE_FROMJSON_INT(uint16_t)
DEFINE_FROMJSON_INT(uint32_t)
DEFINE_FROMJSON_INT(uint64_t)
DEFINE_FROMJSON_FLOAT(float_t)
DEFINE_FROMJSON_FLOAT(double_t)
static void FromJSON_mem_t(JSONIterator& iterator, OutParam<mem_t>::type& value)
{
PointerValueFromJSON(iterator, value);
}
static void FromJSON_mem_ptr_t(JSONIterator& iterator, OutParam<mem_ptr_t>::type& value)
{
const JSON::Token& token = iterator.getCurrentAndGotoNext();
Fail("UNIMPLEMENTED: %s\n", "FromJSON_mem_ptr_t");
}
static void FromJSON_str_t(JSONIterator& iterator, OutParam<str_t>::type& value)
{
const JSON::Token& token = iterator.getCurrentAndGotoNext();
if (token.isString()) {
size_t length = 0;
std::string tokenValue = token.value();
for (std::string::iterator it = tokenValue.begin(); it != tokenValue.cend(); ++it) {
++length;
if (*it == '\\' && it + 1 != tokenValue.cend()) {
std::string::iterator next = it + 1;
switch (*next) {
case '\"':
case '/':
case '\\':
tokenValue.erase(it);
break;
case 'b':
tokenValue.replace(it, next + 1, "\b");
break;
case 'f':
tokenValue.replace(it, next + 1, "\f");
break;
case 'r':
tokenValue.replace(it, next + 1, "\r");
break;
case 'n':
tokenValue.replace(it, next + 1, "\n");
break;
case 't':
tokenValue.replace(it, next + 1, "\t");
break;
case 'u':
if (tokenValue.cend() - next >= 5) {
if (*(next + 1) == '0' &&
*(next + 2) == '0') {
unsigned int v;
std::stringstream x;
x << *(next + 3) << *(next + 4);
x >> std::hex >> v;
// Handle Control characters code units
// from U+0000 to U+001F.
if ( v < 0x0020) {
tokenValue.replace(it, next + 5, 1, v);
break;
}
}
Fail("Need to handle unicode escapes in strings: %s.",
tokenValue.c_str());
}
}
}
}
value = (char*) malloc(length + 1);
std::memcpy(value, tokenValue.c_str(), length + 1);
return;
}
if (!token.isArray()) {
Fail("Expected array", "");
return;
}
size_t size = token.children();
char* buff = new char[size];
for (size_t i = 0; i < size; ++i) {
buff[i] = iterator.getCurrentAndGotoNext().value()[0];
}
value = buff;
}
static void FromJSON_str_t(JSONIterator& iterator, str_t& value)
{
return FromJSON_str_t(iterator, const_cast<OutParam<str_t>::type&>(value));
}
static void FromJSON_cstr_t(JSONIterator& iterator, cstr_t& value)
{
value = strdup(iterator.getCurrentStringAndGotoNext().value().c_str());
}
DEFINE_FROMJSON_INT(GLint)
DEFINE_FROMJSON_INT(GLuint)
static void FromJSON_GLenum(JSONIterator& iterator, OutParam<GLenum>::type& value)
{
const JSON::Token& token = iterator.getCurrentAndGotoNext();
Fail("UNIMPLEMENTED: %s\n", "FromJSON_GLenum");
}
static void FromJSON_GLbitfield(JSONIterator& iterator, OutParam<GLbitfield>::type& value)
{
const JSON::Token& token = iterator.getCurrentAndGotoNext();
Fail("UNIMPLEMENTED: %s\n", "FromJSON_GLbitfield");
}
DEFINE_FROMJSON_INT(GLboolean)
static void FromJSON_GLfloat(JSONIterator& iterator, OutParam<GLfloat>::type& value)
{
const JSON::Token& token = iterator.getCurrentAndGotoNext();
Fail("UNIMPLEMENTED: %s\n", "FromJSON_GLfloat");
}
static void FromJSON_GLclampf(JSONIterator& iterator, OutParam<GLclampf>::type& value)
{
const JSON::Token& token = iterator.getCurrentAndGotoNext();
Fail("UNIMPLEMENTED: %s\n", "FromJSON_GLclampf");
}
static void FromJSON_GLintptr(JSONIterator& iterator, OutParam<GLintptr>::type& value)
{
const JSON::Token& token = iterator.getCurrentAndGotoNext();
Fail("UNIMPLEMENTED: %s\n", "FromJSON_GLintptr");
}
DEFINE_FROMJSON_INT(GLsizei)
static void FromJSON_GLboolean_ptr_t(JSONIterator& iterator, OutParam<GLboolean_ptr_t>::type& value)
{
const JSON::Token& token = iterator.getCurrentAndGotoNext();
Fail("UNIMPLEMENTED: %s\n", "FromJSON_GLboolean_ptr_t");
}
static void FromJSON_GLenum_ptr_t(JSONIterator& iterator, OutParam<GLenum_ptr_t>::type& value)
{
const JSON::Token& token = iterator.getCurrentAndGotoNext();
Fail("UNIMPLEMENTED: %s\n", "FromJSON_GLenum_ptr_t");
}
static void FromJSON_GLfloat_ptr_t(JSONIterator& iterator,OutParam<GLfloat_ptr_t>::type& value)
{
const JSON::Token& token = iterator.getCurrentAndGotoNext();
Fail("UNIMPLEMENTED: %s\n", "FromJSON_GLfloat_ptr_t");
}
static void FromJSON_GLint_ptr_t(JSONIterator& iterator, OutParam<GLint_ptr_t>::type& value)
{
return FromJSON_GLint(iterator, *value);
Fail("UNIMPLEMENTED: %s\n", "FromJSON_GLint_ptr_t");
}
static void FromJSON_GLsizei_ptr_t(JSONIterator& iterator, OutParam<GLsizei_ptr_t>::type& value)
{
if (!value) {
iterator.skip();
} else {
FromJSON_GLsizei(iterator, *value);
}
}
static void FromJSON_GLubyte_ptr_t(JSONIterator& iterator, OutParam<GLubyte_ptr_t>::type& value)
{
const JSON::Token& token = iterator.getCurrentStringAndGotoNext();
std::string tokenValue = token.value();
size_t size = tokenValue.size();
value = new GLubyte[size];
std::memcpy(value, tokenValue.data(), size);
}
static void FromJSON_GLuint_ptr_t(JSONIterator& iterator, OutParam<GLuint_ptr_t>::type& value)
{
const JSON::Token& token = iterator.getCurrentAndGotoNext();
Fail("UNIMPLEMENTED: %s\n", "FromJSON_GLuint_ptr_t");
}
#ifdef _WIN32
static void FromJSON_PP_FileHandle(JSONIterator& iterator, PP_FileHandle& value)
{
PointerValueFromJSON(iterator, value);
}
#else
DEFINE_FROMJSON_INT(PP_FileHandle)
#endif
static void FromJSON_uint16_ptr_t(JSONIterator& iterator, uint16_ptr_t& value)
{
PointerValueFromJSON(iterator, value);
}
struct PP_Flash_Menu;
void FromJSON_PP_Flash_Menu(JSONIterator& iterator, PP_Flash_Menu &value);
void FromJSON_PP_Flash_Menu(JSONIterator& iterator, PP_Flash_Menu *&value);
struct PP_DirEntry_Dev;
struct PP_DirContents_Dev;
void FromJSON_PP_DirEntry_Dev(JSONIterator& iterator, PP_DirEntry_Dev &value);
void FromJSON_PP_DirContents_Dev(JSONIterator& iterator, PP_DirContents_Dev *&value);
#endif