00001
00002
00003
00004
00005
00006 #include <stdlib.h>
00007 #include <stdio.h>
00008 #include <string.h>
00009 #include <pthread.h>
00010 #include <sys/stat.h>
00011 #include <fcntl.h>
00012 #include <pthread.h>
00013 #include "ppapi/c/pp_errors.h"
00014 #include "ppapi/c/pp_module.h"
00015 #include "ppapi/c/pp_var.h"
00016 #include "ppapi/c/ppb.h"
00017 #include "ppapi/c/ppb_core.h"
00018 #include "ppapi/c/ppb_file_ref.h"
00019 #include "ppapi/c/ppb_instance.h"
00020 #include "ppapi/c/ppb_messaging.h"
00021 #include "ppapi/c/ppb_url_loader.h"
00022 #include "ppapi/c/ppb_url_request_info.h"
00023 #include "ppapi/c/ppb_url_response_info.h"
00024 #include "ppapi/c/ppb_var.h"
00025 #include "ppapi/c/ppp.h"
00026 #include "ppapi/c/ppp_instance.h"
00027 #include "ppapi/c/ppp_messaging.h"
00028
00029 #include "verconf.h"
00030 #include "ruby/ruby.h"
00031 #include "version.h"
00032 #include "gc.h"
00033
00034 #ifdef HAVE_STRUCT_PPB_CORE
00035 typedef struct PPB_Core PPB_Core;
00036 #endif
00037 #ifdef HAVE_STRUCT_PPB_MESSAGING
00038 typedef struct PPB_Messaging PPB_Messaging;
00039 #endif
00040 #ifdef HAVE_STRUCT_PPB_VAR
00041 typedef struct PPB_Var PPB_Var;
00042 #endif
00043 #ifdef HAVE_STRUCT_PPB_URLLOADER
00044 typedef struct PPB_URLLoader PPB_URLLoader;
00045 #endif
00046 #ifdef HAVE_STRUCT_PPB_URLREQUESTINFO
00047 typedef struct PPB_URLRequestInfo PPB_URLRequestInfo;
00048 #endif
00049 #ifdef HAVE_STRUCT_PPB_URLRESPONSEINFO
00050 typedef struct PPB_URLResponseInfo PPB_URLResponseInfo;
00051 #endif
00052 #ifdef HAVE_STRUCT_PPP_INSTANCE
00053 typedef struct PPP_Instance PPP_Instance;
00054 #endif
00055
00056 static PP_Module module_id = 0;
00057 static PPB_Core* core_interface = NULL;
00058 static PPB_Messaging* messaging_interface = NULL;
00059 static PPB_Var* var_interface = NULL;
00060 static PPB_URLLoader* loader_interface = NULL;
00061 static PPB_URLRequestInfo* request_interface = NULL;
00062 static PPB_URLResponseInfo* response_interface = NULL;
00063 static PPB_FileRef* fileref_interface = NULL;
00064 static struct st_table* instance_data = NULL;
00065
00066 static VALUE instance_table = Qundef;
00067
00068 static PP_Instance current_instance = 0;
00069
00070
00071
00072
00073
00074 static void inst_mark(void *const ptr);
00075 static void inst_free(void *const ptr);
00076 static size_t inst_memsize(void *const ptr);
00077 static const rb_data_type_t pepper_instance_data_type = {
00078 "PepperInstance",
00079 { inst_mark, inst_free, inst_memsize }
00080 };
00081
00082 struct PepperInstance {
00083 PP_Instance instance;
00084 PP_Resource url_loader;
00085 VALUE self;
00086 void* async_call_args;
00087 union {
00088 int32_t as_int;
00089 const char* as_str;
00090 VALUE as_value;
00091 } async_call_result;
00092 char buf[1000];
00093
00094 pthread_t th;
00095 pthread_mutex_t mutex;
00096 pthread_cond_t cond;
00097 };
00098
00099 struct PepperInstance*
00100 pruby_get_instance(PP_Instance instance)
00101 {
00102 VALUE self = rb_hash_aref(instance_table, INT2FIX(instance));
00103 if (RTEST(self)) {
00104 struct PepperInstance *inst;
00105 TypedData_Get_Struct(self, struct PepperInstance, &pepper_instance_data_type, inst);
00106 return inst;
00107 }
00108 else {
00109 return NULL;
00110 }
00111 }
00112
00113 #define GET_PEPPER_INSTANCE() (pruby_get_instance(current_instance))
00114
00115 struct PepperInstance*
00116 pruby_register_instance(PP_Instance instance)
00117 {
00118 VALUE obj;
00119 struct PepperInstance *data;
00120 obj = TypedData_Make_Struct(rb_cData, struct PepperInstance, &pepper_instance_data_type, data);
00121 data->self = obj;
00122 data->instance = instance;
00123 data->url_loader = 0;
00124
00125 pthread_mutex_init(&data->mutex, NULL);
00126 pthread_cond_init(&data->cond, NULL);
00127
00128 rb_hash_aset(instance_table, INT2FIX(instance), obj);
00129 return data;
00130 }
00131
00132 int
00133 pruby_unregister_instance(PP_Instance instance)
00134 {
00135 VALUE inst = rb_hash_delete(instance_table, INT2FIX(instance));
00136 return RTEST(inst);
00137 }
00138
00139 static void
00140 inst_mark(void *const ptr)
00141 {
00142 RUBY_MARK_ENTER("PepperInstance"0);
00143 if (ptr) {
00144 const struct PepperInstance* inst = (struct PepperInstance*)ptr;
00145 RUBY_MARK_UNLESS_NULL(inst->async_call_result.as_value);
00146 }
00147 RUBY_MARK_LEAVE("PepperInstance"0);
00148 }
00149
00150 static void
00151 inst_free(void *const ptr)
00152 {
00153 ruby_xfree(ptr);
00154 }
00155
00156 static size_t
00157 inst_memsize(void *const ptr)
00158 {
00159 if (ptr) {
00160 const struct PepperInstance* inst = (struct PepperInstance*)ptr;
00161 return sizeof(*inst);
00162 } else {
00163 return 0;
00164 }
00165 }
00166
00167 void
00168 pruby_async_return_int(void* data, int32_t result)
00169 {
00170
00171 struct PepperInstance* const instance = (struct PepperInstance*)data;
00172 instance->async_call_result.as_int = result;
00173 if (pthread_cond_signal(&instance->cond)) {
00174 perror("pepper-ruby:pthread_cond_signal");
00175 }
00176 }
00177
00178 void
00179 pruby_async_return_str(void* data, const char *result)
00180 {
00181
00182 struct PepperInstance* const instance = (struct PepperInstance*)data;
00183 instance->async_call_result.as_str = result;
00184 if (pthread_cond_signal(&instance->cond)) {
00185 perror("pepper-ruby:pthread_cond_signal");
00186 }
00187 }
00188
00189 void
00190 pruby_async_return_value(void* data, VALUE value)
00191 {
00192
00193 struct PepperInstance* const instance = (struct PepperInstance*)data;
00194 instance->async_call_result.as_value = value;
00195 if (pthread_cond_signal(&instance->cond)) {
00196 perror("pepper-ruby:pthread_cond_signal");
00197 }
00198 }
00199
00200
00201
00202
00210 static struct PP_Var
00211 pruby_cstr_to_var(const char* str)
00212 {
00213 #ifdef PPB_VAR_INTERFACE_1_0
00214 if (var_interface != NULL)
00215 return var_interface->VarFromUtf8(module_id, str, strlen(str));
00216 return PP_MakeUndefined();
00217 #else
00218 return var_interface->VarFromUtf8(str, strlen(str));
00219 #endif
00220 }
00221
00232 static char*
00233 pruby_var_to_cstr(struct PP_Var var)
00234 {
00235 uint32_t len = 0;
00236 if (var_interface != NULL) {
00237 const char* var_c_str = var_interface->VarToUtf8(var, &len);
00238 if (len > 0) {
00239 char* c_str = (char*)malloc(len + 1);
00240 memcpy(c_str, var_c_str, len);
00241 c_str[len] = '\0';
00242 return c_str;
00243 }
00244 }
00245 return NULL;
00246 }
00247
00248 static struct PP_Var
00249 pruby_str_to_var(volatile VALUE str)
00250 {
00251 if (!RB_TYPE_P(str, T_STRING)) {
00252 fprintf(stderr, "[BUG] Unexpected object type: %x\n", TYPE(str));
00253 exit(EXIT_FAILURE);
00254 }
00255 #ifdef PPB_VAR_INTERFACE_1_0
00256 if (var_interface != NULL) {
00257 return var_interface->VarFromUtf8(module_id, RSTRING_PTR(str), RSTRING_LEN(str));
00258 }
00259 #else
00260 return var_interface->VarFromUtf8(RSTRING_PTR(str), RSTRING_LEN(str));
00261 #endif
00262 return PP_MakeUndefined();
00263 }
00264
00265 static struct PP_Var
00266 pruby_obj_to_var(volatile VALUE obj)
00267 {
00268 static const char* const error =
00269 "throw 'Failed to convert the result to a JavaScript object';";
00270 int state;
00271 obj = rb_protect(&rb_obj_as_string, obj, &state);
00272 if (!state) {
00273 return pruby_str_to_var(obj);
00274 }
00275 else {
00276 return pruby_cstr_to_var(error);
00277 }
00278 }
00279
00280 int
00281 pruby_var_equal_to_cstr_p(struct PP_Var lhs, const char* rhs)
00282 {
00283 uint32_t len = 0;
00284 if (var_interface == NULL) {
00285 return 0;
00286 }
00287 else {
00288 const char* const cstr = var_interface->VarToUtf8(lhs, &len);
00289 return strncmp(cstr, rhs, len) == 0;
00290 }
00291 }
00292
00293 int
00294 pruby_var_prefixed_p(struct PP_Var var, const char* prefix)
00295 {
00296 uint32_t len = 0;
00297 if (var_interface == NULL) {
00298 return 0;
00299 }
00300 else {
00301 const char* const cstr = var_interface->VarToUtf8(var, &len);
00302 const size_t prefix_len = strlen(prefix);
00303 return len >= prefix_len && memcmp(cstr, prefix, len) == 0;
00304 }
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314 void
00315 pruby_post_cstr(void* data)
00316 {
00317
00318 struct PepperInstance* const instance = (struct PepperInstance*)data;
00319 const char* const msg = (const char*)instance->async_call_args;
00320 messaging_interface->PostMessage(instance->instance,
00321 pruby_cstr_to_var(msg));
00322 }
00323
00324
00325
00326 void
00327 pruby_post_value(void* data)
00328 {
00329
00330 struct PepperInstance* const instance = (struct PepperInstance*)data;
00331 volatile VALUE value = (VALUE)instance->async_call_args;
00332 messaging_interface->PostMessage(instance->instance, pruby_obj_to_var(value));
00333 }
00334
00335
00336
00337
00338
00339
00340
00341 static void
00342 init_loadpath(void)
00343 {
00344 ruby_incpush("lib/ruby/"RUBY_LIB_VERSION);
00345 ruby_incpush("lib/ruby/"RUBY_LIB_VERSION"/"RUBY_PLATFORM);
00346 ruby_incpush(".");
00347 }
00348
00349 static VALUE
00350 init_libraries_internal(VALUE unused)
00351 {
00352 extern void Init_enc();
00353 extern void Init_ext();
00354
00355 init_loadpath();
00356 Init_enc();
00357 Init_ext();
00358 return Qnil;
00359 }
00360
00361 static void*
00362 init_libraries(void* data)
00363 {
00364 int state;
00365 struct PepperInstance* const instance = (struct PepperInstance*)data;
00366 current_instance = instance->instance;
00367
00368 if (pthread_mutex_lock(&instance->mutex)) {
00369 perror("pepper-ruby:pthread_mutex_lock");
00370 return 0;
00371 }
00372 rb_protect(&init_libraries_internal, Qnil, &state);
00373 pthread_mutex_unlock(&instance->mutex);
00374
00375 if (state) {
00376 volatile VALUE err = rb_errinfo();
00377 err = rb_obj_as_string(err);
00378 } else {
00379 instance->async_call_args = (void*)"rubyReady";
00380 core_interface->CallOnMainThread(
00381 0, PP_MakeCompletionCallback(pruby_post_cstr, instance), 0);
00382 }
00383 return NULL;
00384 }
00385
00386 static int
00387 init_libraries_if_necessary(void)
00388 {
00389 static int initialized = 0;
00390 if (!initialized) {
00391 struct PepperInstance* const instance = GET_PEPPER_INSTANCE();
00392 int err;
00393 initialized = 1;
00394 err = pthread_create(&instance->th, NULL, &init_libraries, instance);
00395 if (err) {
00396 fprintf(stderr, "pepper_ruby:pthread_create: %s\n", strerror(err));
00397 exit(EXIT_FAILURE);
00398 }
00399 pthread_detach(instance->th);
00400 }
00401 return 0;
00402 }
00403
00404 static int
00405 pruby_init(void)
00406 {
00407 RUBY_INIT_STACK;
00408 ruby_init();
00409
00410 instance_table = rb_hash_new();
00411 rb_gc_register_mark_object(instance_table);
00412
00413 return 0;
00414 }
00415
00416
00417
00418
00419
00420
00421 static void*
00422 pruby_eval(void* data)
00423 {
00424 extern VALUE ruby_eval_string_from_file_protect(const char* src, const char* path, int* state);
00425 struct PepperInstance* const instance = (struct PepperInstance*)data;
00426 volatile VALUE src = (VALUE)instance->async_call_args;
00427 volatile VALUE result = Qnil;
00428 volatile int state;
00429
00430 RUBY_INIT_STACK;
00431
00432 if (pthread_mutex_lock(&instance->mutex)) {
00433 perror("pepper-ruby:pthread_mutex_lock");
00434 return 0;
00435 }
00436 result = ruby_eval_string_from_file_protect(
00437 RSTRING_PTR(src), "(pepper-ruby)", &state);
00438 pthread_mutex_unlock(&instance->mutex);
00439
00440 if (!state) {
00441 instance->async_call_args =
00442 rb_str_concat(rb_usascii_str_new_cstr("return:"),
00443 rb_obj_as_string(result));
00444 core_interface->CallOnMainThread(
00445 0, PP_MakeCompletionCallback(pruby_post_value, instance), 0);
00446 return NULL;
00447 }
00448 else {
00449 rb_set_errinfo(Qnil);
00450 instance->async_call_args =
00451 rb_str_concat(rb_usascii_str_new_cstr("error:"),
00452 rb_obj_as_string(result));
00453 core_interface->CallOnMainThread(
00454 0, PP_MakeCompletionCallback(pruby_post_value, instance), 0);
00455 return NULL;
00456 }
00457 }
00458
00459
00460
00461
00462
00463
00486 static PP_Bool
00487 Instance_DidCreate(PP_Instance instance,
00488 uint32_t argc, const char* argn[], const char* argv[])
00489 {
00490 struct PepperInstance* data = pruby_register_instance(instance);
00491 current_instance = instance;
00492 return init_libraries_if_necessary() ? PP_FALSE : PP_TRUE;
00493 }
00494
00502 static void Instance_DidDestroy(PP_Instance instance) {
00503 struct PepperInstance* data = pruby_get_instance(instance);
00504 core_interface->ReleaseResource(data->url_loader);
00505 pruby_unregister_instance(instance);
00506 }
00507
00520 #ifdef PPP_INSTANCE_INTERFACE_1_0
00521 static void
00522 Instance_DidChangeView(PP_Instance instance,
00523 const struct PP_Rect* position,
00524 const struct PP_Rect* clip)
00525 {
00526 }
00527 #else
00528 static void
00529 Instance_DidChangeView(PP_Instance instance, PP_Resource view_resource)
00530 {
00531 }
00532 #endif
00533
00551 static void
00552 Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus)
00553 {
00554 }
00555
00566 static PP_Bool
00567 Instance_HandleDocumentLoad(PP_Instance instance, PP_Resource url_loader)
00568 {
00569
00570 return PP_FALSE;
00571 }
00572
00573
00589 void
00590 Messaging_HandleMessage(PP_Instance instance, struct PP_Var var_message)
00591 {
00592 char* const message = pruby_var_to_cstr(var_message);
00593 size_t message_len = strlen(message);
00594 current_instance = instance;
00595
00596 if (strstr(message, "eval:") != NULL) {
00597 volatile VALUE src;
00598 struct PepperInstance* const instance_data = GET_PEPPER_INSTANCE();
00599 int err;
00600 #define EVAL_PREFIX_LEN 5
00601 src = rb_str_new(message + EVAL_PREFIX_LEN, message_len - EVAL_PREFIX_LEN);
00602 instance_data->async_call_args = (void*)src;
00603 err = pthread_create(&instance_data->th, NULL, &pruby_eval, instance_data);
00604 if (err) {
00605 fprintf(stderr, "pepper_ruby:pthread_create: %s\n", strerror(err));
00606 exit(EXIT_FAILURE);
00607 }
00608 pthread_detach(instance_data->th);
00609 }
00610 free(message);
00611 }
00612
00620 PP_EXPORT int32_t
00621 PPP_InitializeModule(PP_Module a_module_id, PPB_GetInterface get_browser_interface)
00622 {
00623 module_id = a_module_id;
00624 core_interface = (PPB_Core*)(get_browser_interface(PPB_CORE_INTERFACE));
00625 if (core_interface == NULL) return PP_ERROR_NOINTERFACE;
00626
00627 var_interface = (PPB_Var*)(get_browser_interface(PPB_VAR_INTERFACE));
00628 if (var_interface == NULL) return PP_ERROR_NOINTERFACE;
00629
00630 messaging_interface = (PPB_Messaging*)(get_browser_interface(PPB_MESSAGING_INTERFACE));
00631 if (messaging_interface == NULL) return PP_ERROR_NOINTERFACE;
00632
00633 loader_interface = (PPB_URLLoader*)(get_browser_interface(PPB_URLLOADER_INTERFACE));
00634 if (loader_interface == NULL) return PP_ERROR_NOINTERFACE;
00635
00636 request_interface = (PPB_URLRequestInfo*)(get_browser_interface(PPB_URLREQUESTINFO_INTERFACE));
00637 if (request_interface == NULL) return PP_ERROR_NOINTERFACE;
00638
00639 response_interface = (PPB_URLResponseInfo*)(get_browser_interface(PPB_URLRESPONSEINFO_INTERFACE));
00640 if (response_interface == NULL) return PP_ERROR_NOINTERFACE;
00641
00642 fileref_interface = (PPB_FileRef*)(get_browser_interface(PPB_FILEREF_INTERFACE));
00643 if (fileref_interface == NULL) return PP_ERROR_NOINTERFACE;
00644
00645 return pruby_init() ? PP_ERROR_FAILED : PP_OK;
00646 }
00647
00654 PP_EXPORT const void*
00655 PPP_GetInterface(const char* interface_name)
00656 {
00657 if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
00658 static PPP_Instance instance_interface = {
00659 &Instance_DidCreate,
00660 &Instance_DidDestroy,
00661 &Instance_DidChangeView,
00662 &Instance_DidChangeFocus,
00663 &Instance_HandleDocumentLoad
00664 };
00665 return &instance_interface;
00666 } else if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) {
00667 static PPP_Messaging messaging_interface = {
00668 &Messaging_HandleMessage
00669 };
00670 return &messaging_interface;
00671 }
00672 return NULL;
00673 }
00674
00678 PP_EXPORT void
00679 PPP_ShutdownModule()
00680 {
00681 ruby_cleanup(0);
00682 }
00683
00684
00685
00686
00687
00688 static void
00689 load_ok_internal(void* data, int32_t unused)
00690 {
00691
00692 struct PepperInstance* const instance = (struct PepperInstance*)data;
00693 const char *const path = (const char*)instance->async_call_args;
00694 PP_Resource req;
00695 int result;
00696
00697 instance->url_loader = loader_interface->Create(instance->instance);
00698 req = request_interface->Create(instance->instance);
00699 request_interface->SetProperty(
00700 req, PP_URLREQUESTPROPERTY_METHOD, pruby_cstr_to_var("HEAD"));
00701 request_interface->SetProperty(
00702 req, PP_URLREQUESTPROPERTY_URL, pruby_cstr_to_var(path));
00703
00704 result = loader_interface->Open(
00705 instance->url_loader, req,
00706 PP_MakeCompletionCallback(pruby_async_return_int, instance));
00707 if (result != PP_OK_COMPLETIONPENDING) {
00708 pruby_async_return_int(instance, result);
00709 }
00710 }
00711
00712 static void
00713 pruby_file_fetch_check_response(void* data, int32_t unused)
00714 {
00715
00716 PP_Resource res;
00717 struct PepperInstance* const instance = (struct PepperInstance*)data;
00718
00719 res = loader_interface->GetResponseInfo(instance->url_loader);
00720 if (res) {
00721 struct PP_Var status =
00722 response_interface->GetProperty(res, PP_URLRESPONSEPROPERTY_STATUSCODE);
00723 if (status.type == PP_VARTYPE_INT32) {
00724 pruby_async_return_int(instance, status.value.as_int / 100 == 2 ? PP_OK : PP_ERROR_FAILED);
00725 return;
00726 }
00727 else {
00728 messaging_interface->PostMessage(
00729 instance->instance, pruby_cstr_to_var("Unexpected type: ResponseInfoInterface::GetProperty"));
00730 }
00731 }
00732 else {
00733 messaging_interface->PostMessage(
00734 instance->instance, pruby_cstr_to_var("Failed to open URL: URLLoaderInterface::GetResponseInfo"));
00735 }
00736 pruby_async_return_int(instance, PP_ERROR_FAILED);
00737 }
00738
00739
00740 int
00741 rb_file_load_ok(const char *path)
00742 {
00743 struct PepperInstance* const instance = GET_PEPPER_INSTANCE();
00744 if (path[0] == '.' && path[1] == '/') path += 2;
00745
00746 instance->async_call_args = (void*)path;
00747 core_interface->CallOnMainThread(
00748 0, PP_MakeCompletionCallback(load_ok_internal, instance), 0);
00749 if (pthread_cond_wait(&instance->cond, &instance->mutex)) {
00750 perror("pepper-ruby:pthread_cond_wait");
00751 return 0;
00752 }
00753 if (instance->async_call_result.as_int != PP_OK) {
00754 fprintf(stderr, "Failed to open URL: %d: %s\n",
00755 instance->async_call_result.as_int, path);
00756 return 0;
00757 }
00758
00759 core_interface->CallOnMainThread(
00760 0, PP_MakeCompletionCallback(pruby_file_fetch_check_response, instance), 0);
00761 if (pthread_cond_wait(&instance->cond, &instance->mutex)) {
00762 perror("pepper-ruby:pthread_cond_wait");
00763 return 0;
00764 }
00765 return instance->async_call_result.as_int == PP_OK;
00766 }
00767
00768
00769
00770
00771
00772 static void
00773 load_file_internal(void* data, int32_t unused)
00774 {
00775
00776 struct PepperInstance* const instance = (struct PepperInstance*)data;
00777 const char *const path = (const char*)instance->async_call_args;
00778 PP_Resource req;
00779 int result;
00780
00781 instance->url_loader = loader_interface->Create(instance->instance);
00782 req = request_interface->Create(instance->instance);
00783 request_interface->SetProperty(
00784 req, PP_URLREQUESTPROPERTY_METHOD, pruby_cstr_to_var("GET"));
00785 request_interface->SetProperty(
00786 req, PP_URLREQUESTPROPERTY_URL, pruby_cstr_to_var(path));
00787
00788 result = loader_interface->Open(
00789 instance->url_loader, req,
00790 PP_MakeCompletionCallback(pruby_async_return_int, instance));
00791 if (result != PP_OK_COMPLETIONPENDING) {
00792 pruby_async_return_int(instance, result);
00793 }
00794 }
00795
00796 static void
00797 load_file_read_contents_callback(void *data, int result)
00798 {
00799 struct PepperInstance* const instance = (struct PepperInstance*)data;
00800 if (result > 0) {
00801 rb_str_buf_cat(instance->async_call_result.as_value,
00802 instance->buf, result);
00803 loader_interface->ReadResponseBody(
00804 instance->url_loader, instance->buf, 1000, PP_MakeCompletionCallback(load_file_read_contents_callback, instance));
00805 }
00806 else if (result == 0) {
00807 pruby_async_return_value(data, instance->async_call_result.as_value);
00808 }
00809 else {
00810 pruby_async_return_value(data, INT2FIX(result));
00811 }
00812 }
00813
00814 static void
00815 load_file_read_contents(void *data, int result)
00816 {
00817 struct PepperInstance* const instance = (struct PepperInstance*)data;
00818 instance->async_call_result.as_value = rb_str_new(0, 0);
00819 loader_interface->ReadResponseBody(
00820 instance->url_loader, instance->buf, 1000, PP_MakeCompletionCallback(load_file_read_contents_callback, instance));
00821 }
00822
00823 void*
00824 rb_load_file(const char *path)
00825 {
00826 const char *real_path;
00827 struct PepperInstance* instance;
00828 if (path[0] != '.' || path[1] != '/') path += 2;
00829
00830 instance = GET_PEPPER_INSTANCE();
00831
00832 instance->async_call_args = (void*)path;
00833 core_interface->CallOnMainThread(
00834 0, PP_MakeCompletionCallback(load_file_internal, instance), 0);
00835 if (pthread_cond_wait(&instance->cond, &instance->mutex)) {
00836 perror("pepper-ruby:pthread_cond_wait");
00837 return 0;
00838 }
00839 if (instance->async_call_result.as_int != PP_OK) {
00840 fprintf(stderr, "Failed to open URL: %d: %s\n",
00841 instance->async_call_result.as_int, path);
00842 return 0;
00843 }
00844
00845 core_interface->CallOnMainThread(
00846 0, PP_MakeCompletionCallback(pruby_file_fetch_check_response, instance), 0);
00847 if (pthread_cond_wait(&instance->cond, &instance->mutex)) {
00848 perror("pepper-ruby:pthread_cond_wait");
00849 return 0;
00850 }
00851 if (instance->async_call_result.as_int != PP_OK) return 0;
00852
00853 core_interface->CallOnMainThread(
00854 0, PP_MakeCompletionCallback(load_file_read_contents, instance), 0);
00855 if (pthread_cond_wait(&instance->cond, &instance->mutex)) {
00856 perror("pepper-ruby:pthread_cond_wait");
00857 return 0;
00858 }
00859 if (FIXNUM_P(instance->async_call_result.as_value)) {
00860 return 0;
00861 }
00862 else if (RB_TYPE_P(instance->async_call_result.as_value, T_STRING)) {
00863 VALUE str = instance->async_call_result.as_value;
00864 extern void* rb_compile_cstr(const char *f, const char *s, int len, int line);
00865 return rb_compile_cstr(path, RSTRING_PTR(str), RSTRING_LEN(str), 0);
00866 }
00867 else {
00868 return 0;
00869 }
00870 }
00871