#include "ppapi/c/ppb_instance.h"
#include "ppapi/c/ppb_messaging.h"
#include "ppapi/c/ppb_var.h"
+#include "ppapi/c/ppb_var_array.h"
+#include "ppapi/c/ppb_var_dictionary.h"
#include "ppapi/c/ppp.h"
#include "ppapi/c/ppp_instance.h"
#include "ppapi/c/ppp_messaging.h"
#include "handlers.h"
#include "queue.h"
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-
#if defined(WIN32)
#define va_copy(d, s) ((d) = (s))
#endif
HandleFunc function;
} FuncNameMapping;
-static PP_Instance g_instance = 0;
-static PPB_GetInterface get_browser_interface = NULL;
-static PPB_Messaging* ppb_messaging_interface = NULL;
-static PPB_Var* ppb_var_interface = NULL;
+PP_Instance g_instance = 0;
+PPB_GetInterface g_get_browser_interface = NULL;
+PPB_Messaging* g_ppb_messaging = NULL;
+PPB_Var* g_ppb_var = NULL;
+PPB_VarArray* g_ppb_var_array = NULL;
+PPB_VarDictionary* g_ppb_var_dictionary = NULL;
static FuncNameMapping g_function_map[] = {
- {"fopen", HandleFopen},
- {"fwrite", HandleFwrite},
- {"fread", HandleFread},
- {"fseek", HandleFseek},
- {"fclose", HandleFclose},
- {"stat", HandleStat},
- {"opendir", HandleOpendir},
- {"readdir", HandleReaddir},
- {"closedir", HandleClosedir},
- {"mkdir", HandleMkdir},
- {"rmdir", HandleRmdir},
- {"chdir", HandleChdir},
- {"getcwd", HandleGetcwd},
- {"gethostbyname", HandleGethostbyname},
- {"connect", HandleConnect},
- {"send", HandleSend},
- {"recv", HandleRecv},
- {"close", HandleClose},
- {NULL, NULL},
+ {"fopen", HandleFopen},
+ {"fwrite", HandleFwrite},
+ {"fread", HandleFread},
+ {"fseek", HandleFseek},
+ {"fclose", HandleFclose},
+ {"fflush", HandleFflush},
+ {"stat", HandleStat},
+ {"opendir", HandleOpendir},
+ {"readdir", HandleReaddir},
+ {"closedir", HandleClosedir},
+ {"mkdir", HandleMkdir},
+ {"rmdir", HandleRmdir},
+ {"chdir", HandleChdir},
+ {"getcwd", HandleGetcwd},
+ {"getaddrinfo", HandleGetaddrinfo},
+ {"gethostbyname", HandleGethostbyname},
+ {"connect", HandleConnect},
+ {"send", HandleSend},
+ {"recv", HandleRecv},
+ {"close", HandleClose},
+ {NULL, NULL},
};
/** A handle to the thread the handles messages. */
* @return A new PP_Var with the contents of |str|.
*/
struct PP_Var CStrToVar(const char* str) {
- if (ppb_var_interface != NULL) {
- return ppb_var_interface->VarFromUtf8(str, strlen(str));
- }
- return PP_MakeUndefined();
+ return g_ppb_var->VarFromUtf8(str, strlen(str));
}
/**
* @return A new PP_Var.
*/
struct PP_Var PrintfToVar(const char* format, ...) {
- if (ppb_var_interface != NULL) {
- char* string;
- va_list args;
- struct PP_Var var;
-
- va_start(args, format);
- string = VprintfToNewString(format, args);
- va_end(args);
+ char* string;
+ va_list args;
+ struct PP_Var var;
- var = ppb_var_interface->VarFromUtf8(string, strlen(string));
- free(string);
+ va_start(args, format);
+ string = VprintfToNewString(format, args);
+ va_end(args);
- return var;
- }
+ var = g_ppb_var->VarFromUtf8(string, strlen(string));
+ free(string);
- return PP_MakeUndefined();
+ return var;
}
/**
* @param[in] length The length of |buffer|.
* @return The number of characters written.
*/
-uint32_t VarToCStr(struct PP_Var var, char* buffer, uint32_t length) {
- if (ppb_var_interface != NULL) {
- uint32_t var_length;
- const char* str = ppb_var_interface->VarToUtf8(var, &var_length);
- /* str is NOT NULL-terminated. Copy using memcpy. */
- uint32_t min_length = MIN(var_length, length - 1);
- memcpy(buffer, str, min_length);
- buffer[min_length] = 0;
-
- return min_length;
+const char* VarToCStr(struct PP_Var var) {
+ uint32_t length;
+ const char* str = g_ppb_var->VarToUtf8(var, &length);
+ if (str == NULL) {
+ return NULL;
}
- return 0;
+ /* str is NOT NULL-terminated. Copy using memcpy. */
+ char* new_str = (char*)malloc(length + 1);
+ memcpy(new_str, str, length);
+ new_str[length] = 0;
+ return new_str;
+}
+
+/**
+ * Get a value from a Dictionary, given a string key.
+ * @param[in] dict The dictionary to look in.
+ * @param[in] key The key to look up.
+ * @return PP_Var The value at |key| in the |dict|. If the key doesn't exist,
+ * return a PP_Var with the undefined value.
+ */
+struct PP_Var GetDictVar(struct PP_Var dict, const char* key) {
+ struct PP_Var key_var = CStrToVar(key);
+ struct PP_Var value = g_ppb_var_dictionary->Get(dict, key_var);
+ g_ppb_var->Release(key_var);
+ return value;
+}
+
+/**
+ * Send a newly-created PP_Var to JavaScript, then release it.
+ * @param[in] var The PP_Var to send.
+ */
+static void PostMessageVar(struct PP_Var var) {
+ g_ppb_messaging->PostMessage(g_instance, var);
+ g_ppb_var->Release(var);
}
/**
* Given a message from JavaScript, parse it for functions and parameters.
*
* The format of the message is:
- * function, param1, param2, param3, etc.
- * where each element is separated by the \1 character.
- *
- * e.g.
- * "function\1first parameter\1second parameter"
+ * {
+ * "cmd": <function name>,
+ * "args": [<arg0>, <arg1>, ...]
+ * }
*
- * How to use:
- * char* function;
- * char* params[4];
- * int num_params = ParseMessage(msg, &function, ¶ms, 4);
- *
- * @param[in, out] message The message to parse. This string is modified
- * in-place.
+ * @param[in] message The message to parse.
* @param[out] out_function The function name.
- * @param[out] out_params An array of strings, one for each parameter parsed.
- * @param[in] max_params The maximum number of parameters to parse.
- * @return The number of parameters parsed.
+ * @param[out] out_params A PP_Var array.
+ * @return 0 if successful, otherwise 1.
*/
-static size_t ParseMessage(char* message,
- char** out_function,
- char** out_params,
- size_t max_params) {
- char* separator;
- char* param_start;
- size_t num_params = 0;
-
- /* Parse the message: function\1param1\1param2\1param3,... */
- *out_function = &message[0];
-
- separator = strchr(message, 1);
- if (!separator) {
- return num_params;
+static int ParseMessage(struct PP_Var message,
+ const char** out_function,
+ struct PP_Var* out_params) {
+ if (message.type != PP_VARTYPE_DICTIONARY) {
+ return 1;
}
- *separator = 0; /* NULL-terminate function. */
-
- while (separator && num_params < max_params) {
- param_start = separator + 1;
- separator = strchr(param_start, 1);
- if (separator) {
- *separator = 0;
- out_params[num_params++] = param_start;
- }
+ struct PP_Var cmd_value = GetDictVar(message, "cmd");
+ *out_function = VarToCStr(cmd_value);
+ g_ppb_var->Release(cmd_value);
+ if (cmd_value.type != PP_VARTYPE_STRING) {
+ return 1;
}
- out_params[num_params++] = param_start;
+ *out_params = GetDictVar(message, "args");
+ if (out_params->type != PP_VARTYPE_ARRAY) {
+ return 1;
+ }
- return num_params;
+ return 0;
}
/**
*
* @param[in] message The message to parse and handle.
*/
-static void HandleMessage(char* message) {
- char* function_name;
- char* params[MAX_PARAMS];
- size_t num_params;
- char* output = NULL;
- int result;
- HandleFunc function;
-
- num_params = ParseMessage(message, &function_name, ¶ms[0], MAX_PARAMS);
+static void HandleMessage(struct PP_Var message) {
+ const char* function_name;
+ struct PP_Var params;
+ if (ParseMessage(message, &function_name, ¶ms)) {
+ PostMessageVar(CStrToVar("Error: Unable to parse message"));
+ return;
+ }
- function = GetFunctionByName(function_name);
+ HandleFunc function = GetFunctionByName(function_name);
if (!function) {
/* Function name wasn't found. Error. */
- ppb_messaging_interface->PostMessage(
- g_instance,
+ PostMessageVar(
PrintfToVar("Error: Unknown function \"%s\"", function_name));
return;
}
/* Function name was found, call it. */
- result = (*function)(num_params, ¶ms[0], &output);
+ struct PP_Var result_var;
+ const char* error;
+ int result = (*function)(params, &result_var, &error);
if (result != 0) {
/* Error. */
struct PP_Var var;
- if (output != NULL) {
- var = PrintfToVar("Error: \"%s\" failed: %d: %s.", function_name,
- result, output);
- free(output);
+ if (error != NULL) {
+ var = PrintfToVar("Error: \"%s\" failed: %s.", function_name, error);
+ free((void*)error);
} else {
- var = PrintfToVar(
- "Error: \"%s\" failed: %d.", function_name, result);
+ var = PrintfToVar("Error: \"%s\" failed.", function_name);
}
/* Post the error to JavaScript, so the user can see it. */
- ppb_messaging_interface->PostMessage(g_instance, var);
+ PostMessageVar(var);
return;
}
- if (output != NULL) {
- /* Function returned an output string. Send it to JavaScript. */
- ppb_messaging_interface->PostMessage(g_instance, CStrToVar(output));
- free(output);
- }
+ /* Function returned an output dictionary. Send it to JavaScript. */
+ PostMessageVar(result_var);
+ g_ppb_var->Release(result_var);
}
/**
*/
void* HandleMessageThread(void* user_data) {
while (1) {
- char* message = DequeueMessage();
+ struct PP_Var message = DequeueMessage();
HandleMessage(message);
- free(message);
+ g_ppb_var->Release(message);
}
}
const char* argn[],
const char* argv[]) {
g_instance = instance;
- nacl_io_init_ppapi(instance, get_browser_interface);
+ nacl_io_init_ppapi(instance, g_get_browser_interface);
// By default, nacl_io mounts / to pass through to the original NaCl
// filesystem (which doesn't do much). Let's remount it to a memfs
return PP_TRUE;
}
-static void Instance_DidDestroy(PP_Instance instance) {}
+static void Instance_DidDestroy(PP_Instance instance) {
+}
static void Instance_DidChangeView(PP_Instance instance,
- PP_Resource view_resource) {}
+ PP_Resource view_resource) {
+}
-static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
+static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {
+}
static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
PP_Resource url_loader) {
static void Messaging_HandleMessage(PP_Instance instance,
struct PP_Var message) {
- char buffer[1024];
- VarToCStr(message, &buffer[0], 1024);
- if (!EnqueueMessage(strdup(buffer))) {
- struct PP_Var var;
- var = PrintfToVar(
- "Warning: dropped message \"%s\" because the queue was full.", message);
- ppb_messaging_interface->PostMessage(g_instance, var);
+ g_ppb_var->AddRef(message);
+ if (!EnqueueMessage(message)) {
+ g_ppb_var->Release(message);
+ PostMessageVar(
+ PrintfToVar("Warning: dropped message because the queue was full."));
}
}
+#define GET_INTERFACE(var, type, name) \
+ var = (type*)(get_browser(name)); \
+ if (!var) { \
+ printf("Unable to get interface " name "\n"); \
+ return PP_ERROR_FAILED; \
+ }
+
PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
PPB_GetInterface get_browser) {
- get_browser_interface = get_browser;
- ppb_messaging_interface =
- (PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
- ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
+ g_get_browser_interface = get_browser;
+ GET_INTERFACE(g_ppb_messaging, PPB_Messaging, PPB_MESSAGING_INTERFACE);
+ GET_INTERFACE(g_ppb_var, PPB_Var, PPB_VAR_INTERFACE);
+ GET_INTERFACE(g_ppb_var_array, PPB_VarArray, PPB_VAR_ARRAY_INTERFACE);
+ GET_INTERFACE(
+ g_ppb_var_dictionary, PPB_VarDictionary, PPB_VAR_DICTIONARY_INTERFACE);
return PP_OK;
}
PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
static PPP_Instance instance_interface = {
- &Instance_DidCreate,
- &Instance_DidDestroy,
- &Instance_DidChangeView,
- &Instance_DidChangeFocus,
- &Instance_HandleDocumentLoad,
+ &Instance_DidCreate,
+ &Instance_DidDestroy,
+ &Instance_DidChangeView,
+ &Instance_DidChangeFocus,
+ &Instance_HandleDocumentLoad,
};
return &instance_interface;
} else if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) {
static PPP_Messaging messaging_interface = {
- &Messaging_HandleMessage,
+ &Messaging_HandleMessage,
};
return &messaging_interface;
}
return NULL;
}
-PP_EXPORT void PPP_ShutdownModule() {}
+PP_EXPORT void PPP_ShutdownModule() {
+}