#include "native_client/tests/ppapi_geturl/module.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include "native_client/src/include/nacl_macros.h"
#include "native_client/src/include/portability.h"
#include "native_client/src/shared/platform/nacl_check.h"
#include "native_client/tests/ppapi_geturl/url_load_request.h"
#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppp_instance.h"
#include "ppapi/c/ppp_messaging.h"
namespace {
const char* const kLoadUrlMethodId = "loadUrl";
const char* const kTrueStringValue = "1";
const char* const kFalseStringValue = "0";
static const char kArgumentSeparator = '|';
const std::string BoolToString(bool bool_value) {
return bool_value ? kTrueStringValue : kFalseStringValue;
}
PPP_Instance instance_interface;
PPP_Messaging messaging_interface;
Module* singleton_ = NULL;
}
PP_Bool Instance_DidCreate(PP_Instance ,
uint32_t ,
const char* [],
const char* []) {
printf("--- Instance_DidCreate\n");
return PP_TRUE;
}
void Instance_DidDestroy(PP_Instance ) {
printf("--- Instance_DidDestroy\n");
}
void Instance_DidChangeView(PP_Instance , PP_Resource ) {
}
void Instance_DidChangeFocus(PP_Instance ,
PP_Bool ) {
}
PP_Bool Instance_HandleDocumentLoad(PP_Instance ,
PP_Resource ) {
return PP_FALSE;
}
void Messaging_HandleMessage(PP_Instance instance, struct PP_Var var_message) {
if (var_message.type != PP_VARTYPE_STRING)
return;
std::string message = Module::Get()->VarToStr(var_message);
printf("--- Messaging_HandleMessage(%s)\n", message.c_str());
if (message.find(kLoadUrlMethodId) != 0)
return;
size_t url_pos = message.find_first_of(kArgumentSeparator);
if (url_pos == std::string::npos || url_pos + 1 >= message.length())
return;
size_t as_file_pos = message.find_first_of(kArgumentSeparator, url_pos + 1);
if (as_file_pos == std::string::npos || as_file_pos + 1 >= message.length())
return;
size_t url_length = as_file_pos - url_pos;
if (url_length == 0)
return;
std::string url = message.substr(url_pos + 1, url_length - 1);
bool stream_as_file = message.compare(as_file_pos + 1,
1,
kTrueStringValue) == 0;
printf("--- Messaging_HandleMessage(method='%s', "
"url='%s', "
"stream_as_file='%s')\n",
message.c_str(),
url.c_str(),
stream_as_file ? "true" : "false");
fflush(stdout);
UrlLoadRequest* url_load_request = new UrlLoadRequest(instance);
if (NULL == url_load_request) {
Module::Get()->ReportResult(instance,
url.c_str(),
stream_as_file,
"LoadUrl: memory allocation failed",
false);
return;
}
url_load_request->set_delete_this_after_report();
url_load_request->Load(stream_as_file, url);
}
Module* Module::Create(PP_Module module_id,
PPB_GetInterface get_browser_interface) {
if (NULL == singleton_) {
singleton_ = new Module(module_id, get_browser_interface);
}
return singleton_;
}
Module* Module::Get() {
return singleton_;
}
void Module::Free() {
delete singleton_;
singleton_ = NULL;
}
Module::Module(PP_Module module_id, PPB_GetInterface get_browser_interface)
: module_id_(module_id),
get_browser_interface_(get_browser_interface),
ppb_core_interface_(NULL),
ppb_messaging_interface_(NULL),
ppb_var_interface_(NULL) {
printf("--- Module::Module\n");
memset(&instance_interface, 0, sizeof(instance_interface));
instance_interface.DidCreate = Instance_DidCreate;
instance_interface.DidDestroy = Instance_DidDestroy;
instance_interface.DidChangeView = Instance_DidChangeView;
instance_interface.DidChangeFocus = Instance_DidChangeFocus;
instance_interface.HandleDocumentLoad = Instance_HandleDocumentLoad;
memset(&messaging_interface, 0, sizeof(messaging_interface));
messaging_interface.HandleMessage = Messaging_HandleMessage;
ppb_core_interface_ =
static_cast<const PPB_Core*>(
GetBrowserInterface(PPB_CORE_INTERFACE));
ppb_messaging_interface_ =
static_cast<const PPB_Messaging*>(
GetBrowserInterface(PPB_MESSAGING_INTERFACE));
ppb_var_interface_ =
static_cast<const PPB_Var*>(
GetBrowserInterface(PPB_VAR_INTERFACE));
}
const void* Module::GetPluginInterface(const char* interface_name) {
printf("--- Module::GetPluginInterface(%s)\n", interface_name);
if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0)
return &instance_interface;
if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0)
return &messaging_interface;
return NULL;
}
const void* Module::GetBrowserInterface(const char* interface_name) {
if (NULL == get_browser_interface_)
return NULL;
return (*get_browser_interface_)(interface_name);
}
char* Module::VarToCStr(const PP_Var& var) {
Module* module = Get();
if (NULL == module)
return NULL;
const PPB_Var* ppb_var = module->ppb_var_interface();
if (NULL == ppb_var)
return NULL;
uint32_t len = 0;
const char* pp_str = ppb_var->VarToUtf8(var, &len);
if (NULL == pp_str)
return NULL;
char* str = static_cast<char*>(malloc(len + 1));
if (NULL == str)
return NULL;
memcpy(str, pp_str, len);
str[len] = 0;
return str;
}
std::string Module::VarToStr(const PP_Var& var) {
std::string str;
char* cstr = VarToCStr(var);
if (NULL != cstr) {
str = cstr;
free(cstr);
}
return str;
}
PP_Var Module::StrToVar(const char* str) {
Module* module = Get();
if (NULL == module)
return PP_MakeUndefined();
const PPB_Var* ppb_var = module->ppb_var_interface();
if (NULL != ppb_var)
return ppb_var->VarFromUtf8(str, strlen(str));
return PP_MakeUndefined();
}
PP_Var Module::StrToVar(const std::string& str) {
return Module::StrToVar(str.c_str());
}
std::string Module::ErrorCodeToStr(int32_t error_code) {
switch (error_code) {
case PP_OK: return "PP_OK";
case PP_OK_COMPLETIONPENDING: return "PP_OK_COMPLETIONPENDING";
case PP_ERROR_FAILED: return "PP_ERROR_FAILED";
case PP_ERROR_ABORTED: return "PP_ERROR_ABORTED";
case PP_ERROR_BADARGUMENT: return "PP_ERROR_BADARGUMENT";
case PP_ERROR_BADRESOURCE: return "PP_ERROR_BADRESOURCE";
case PP_ERROR_NOINTERFACE: return "PP_ERROR_NOINTERFACE";
case PP_ERROR_NOACCESS: return "PP_ERROR_NOACCESS";
case PP_ERROR_NOMEMORY: return "PP_ERROR_NOMEMORY";
case PP_ERROR_NOSPACE: return "PP_ERROR_NOSPACE";
case PP_ERROR_NOQUOTA: return "PP_ERROR_NOQUOTA";
case PP_ERROR_INPROGRESS: return "PP_ERROR_INPROGRESS";
case PP_ERROR_FILENOTFOUND: return "PP_ERROR_FILENOTFOUND";
case PP_ERROR_FILEEXISTS: return "PP_ERROR_FILEEXISTS";
case PP_ERROR_FILETOOBIG: return "PP_ERROR_FILETOOBIG";
case PP_ERROR_FILECHANGED: return "PP_ERROR_FILECHANGED";
case PP_ERROR_TIMEDOUT: return "PP_ERROR_TIMEDOUT";
}
return "N/A";
}
void Module::ReportResult(PP_Instance pp_instance,
const char* url,
bool as_file,
const char* text,
bool success) {
printf("--- ReportResult('%s', as_file=%d, '%s', success=%d)\n",
url, as_file, text, success);
std::string result(url);
result += kArgumentSeparator;
result += BoolToString(as_file);
result += kArgumentSeparator;
result += text;
result += kArgumentSeparator;
result += BoolToString(success);
printf("--- ReportResult posts result string:\n\t%s\n", result.c_str());
struct PP_Var var_result = StrToVar(result);
ppb_messaging_interface()->PostMessage(pp_instance, var_result);
if (var_result.type == PP_VARTYPE_STRING) {
ppb_var_interface()->Release(var_result);
}
}