Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

pepper_main.c
Go to the documentation of this file.
1 /******************************************************************************
2 Copyright 2012 Google Inc. All Rights Reserved.
3 Author: yugui@google.com (Yugui Sonoda)
4 ******************************************************************************/
5
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <pthread.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <pthread.h>
13 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/c/pp_module.h"
15 #include "ppapi/c/pp_var.h"
16 #include "ppapi/c/ppb.h"
17 #include "ppapi/c/ppb_core.h"
18 #include "ppapi/c/ppb_file_ref.h"
19 #include "ppapi/c/ppb_instance.h"
20 #include "ppapi/c/ppb_messaging.h"
21 #include "ppapi/c/ppb_url_loader.h"
22 #include "ppapi/c/ppb_url_request_info.h"
23 #include "ppapi/c/ppb_url_response_info.h"
24 #include "ppapi/c/ppb_var.h"
25 #include "ppapi/c/ppp.h"
26 #include "ppapi/c/ppp_instance.h"
27 #include "ppapi/c/ppp_messaging.h"
28
29 #include "verconf.h"
30 #include "ruby/ruby.h"
31 #include "version.h"
32 #include "gc.h"
33
34 #ifdef HAVE_STRUCT_PPB_CORE
35 typedef struct PPB_Core PPB_Core;
36 #endif
37 #ifdef HAVE_STRUCT_PPB_MESSAGING
38 typedef struct PPB_Messaging PPB_Messaging;
39 #endif
40 #ifdef HAVE_STRUCT_PPB_VAR
41 typedef struct PPB_Var PPB_Var;
42 #endif
43 #ifdef HAVE_STRUCT_PPB_URLLOADER
44 typedef struct PPB_URLLoader PPB_URLLoader;
45 #endif
46 #ifdef HAVE_STRUCT_PPB_URLREQUESTINFO
47 typedef struct PPB_URLRequestInfo PPB_URLRequestInfo;
48 #endif
49 #ifdef HAVE_STRUCT_PPB_URLRESPONSEINFO
50 typedef struct PPB_URLResponseInfo PPB_URLResponseInfo;
51 #endif
52 #ifdef HAVE_STRUCT_PPP_INSTANCE
53 typedef struct PPP_Instance PPP_Instance;
54 #endif
55
56 static PP_Module module_id = 0;
57 static PPB_Core* core_interface = NULL;
58 static PPB_Messaging* messaging_interface = NULL;
59 static PPB_Var* var_interface = NULL;
60 static PPB_URLLoader* loader_interface = NULL;
61 static PPB_URLRequestInfo* request_interface = NULL;
62 static PPB_URLResponseInfo* response_interface = NULL;
63 static PPB_FileRef* fileref_interface = NULL;
64 static struct st_table* instance_data = NULL;
65
66 static VALUE instance_table = Qundef;
67
68 static PP_Instance current_instance = 0;
69
70 /******************************************************************************
71 * State of instance
72 ******************************************************************************/
73
74 static void inst_mark(void *const ptr);
75 static void inst_free(void *const ptr);
76 static size_t inst_memsize(void *const ptr);
77 static const rb_data_type_t pepper_instance_data_type = {
78 "PepperInstance",
79 { inst_mark, inst_free, inst_memsize }
80 };
81
82 struct PepperInstance {
83 PP_Instance instance;
84 PP_Resource url_loader;
85 VALUE self;
86 void* async_call_args;
87 union {
88 int32_t as_int;
89 const char* as_str;
90 VALUE as_value;
91 } async_call_result;
92 char buf[1000];
93
94 pthread_t th;
95 pthread_mutex_t mutex;
96 pthread_cond_t cond;
97 };
98
99 struct PepperInstance*
100 pruby_get_instance(PP_Instance instance)
101 {
102 VALUE self = rb_hash_aref(instance_table, INT2FIX(instance));
103 if (RTEST(self)) {
104 struct PepperInstance *inst;
105 TypedData_Get_Struct(self, struct PepperInstance, &pepper_instance_data_type, inst);
106 return inst;
107 }
108 else {
109 return NULL;
110 }
111 }
112
113 #define GET_PEPPER_INSTANCE() (pruby_get_instance(current_instance))
114
115 struct PepperInstance*
116 pruby_register_instance(PP_Instance instance)
117 {
118 VALUE obj;
119 struct PepperInstance *data;
120 obj = TypedData_Make_Struct(rb_cData, struct PepperInstance, &pepper_instance_data_type, data);
121 data->self = obj;
122 data->instance = instance;
123 data->url_loader = 0;
124
125 pthread_mutex_init(&data->mutex, NULL);
126 pthread_cond_init(&data->cond, NULL);
127
128 rb_hash_aset(instance_table, INT2FIX(instance), obj);
129 return data;
130 }
131
132 int
133 pruby_unregister_instance(PP_Instance instance)
134 {
135 VALUE inst = rb_hash_delete(instance_table, INT2FIX(instance));
136 return RTEST(inst);
137 }
138
139 static void
140 inst_mark(void *const ptr)
141 {
142 RUBY_MARK_ENTER("PepperInstance"0);
143 if (ptr) {
144 const struct PepperInstance* inst = (struct PepperInstance*)ptr;
145 RUBY_MARK_UNLESS_NULL(inst->async_call_result.as_value);
146 }
147 RUBY_MARK_LEAVE("PepperInstance"0);
148 }
149
150 static void
151 inst_free(void *const ptr)
152 {
153 ruby_xfree(ptr);
154 }
155
156 static size_t
157 inst_memsize(void *const ptr)
158 {
159 if (ptr) {
160 const struct PepperInstance* inst = (struct PepperInstance*)ptr;
161 return sizeof(*inst);
162 } else {
163 return 0;
164 }
165 }
166
167 void
168 pruby_async_return_int(void* data, int32_t result)
169 {
170 /* PPAPI main thread */
171 struct PepperInstance* const instance = (struct PepperInstance*)data;
172 instance->async_call_result.as_int = result;
173 if (pthread_cond_signal(&instance->cond)) {
174 perror("pepper-ruby:pthread_cond_signal");
175 }
176 }
177
178 void
179 pruby_async_return_str(void* data, const char *result)
180 {
181 /* PPAPI main thread */
182 struct PepperInstance* const instance = (struct PepperInstance*)data;
183 instance->async_call_result.as_str = result;
184 if (pthread_cond_signal(&instance->cond)) {
185 perror("pepper-ruby:pthread_cond_signal");
186 }
187 }
188
189 void
190 pruby_async_return_value(void* data, VALUE value)
191 {
192 /* PPAPI main thread */
193 struct PepperInstance* const instance = (struct PepperInstance*)data;
194 instance->async_call_result.as_value = value;
195 if (pthread_cond_signal(&instance->cond)) {
196 perror("pepper-ruby:pthread_cond_signal");
197 }
198 }
199 /******************************************************************************
200 * Conversion between Ruby's VALUE, Pepper's Var and C string
201 ******************************************************************************/
202
210 static struct PP_Var
211 pruby_cstr_to_var(const char* str)
212 {
213 #ifdef PPB_VAR_INTERFACE_1_0
214 if (var_interface != NULL)
215 return var_interface->VarFromUtf8(module_id, str, strlen(str));
216 return PP_MakeUndefined();
217 #else
218 return var_interface->VarFromUtf8(str, strlen(str));
219 #endif
220 }
221
232 static char*
233 pruby_var_to_cstr(struct PP_Var var)
234 {
235 uint32_t len = 0;
236 if (var_interface != NULL) {
237 const char* var_c_str = var_interface->VarToUtf8(var, &len);
238 if (len > 0) {
239 char* c_str = (char*)malloc(len + 1);
240 memcpy(c_str, var_c_str, len);
241 c_str[len] = '\0';
242 return c_str;
243 }
244 }
245 return NULL;
246 }
247
248 static struct PP_Var
249 pruby_str_to_var(volatile VALUE str)
250 {
251 if (!RB_TYPE_P(str, T_STRING)) {
252 fprintf(stderr, "[BUG] Unexpected object type: %x\n", TYPE(str));
253 exit(EXIT_FAILURE);
254 }
255 #ifdef PPB_VAR_INTERFACE_1_0
256 if (var_interface != NULL) {
257 return var_interface->VarFromUtf8(module_id, RSTRING_PTR(str), RSTRING_LEN(str));
258 }
259 #else
260 return var_interface->VarFromUtf8(RSTRING_PTR(str), RSTRING_LEN(str));
261 #endif
262 return PP_MakeUndefined();
263 }
264
265 static struct PP_Var
266 pruby_obj_to_var(volatile VALUE obj)
267 {
268 static const char* const error =
269 "throw 'Failed to convert the result to a JavaScript object';";
270 int state;
271 obj = rb_protect(&rb_obj_as_string, obj, &state);
272 if (!state) {
273 return pruby_str_to_var(obj);
274 }
275 else {
276 return pruby_cstr_to_var(error);
277 }
278 }
279
280 int
281 pruby_var_equal_to_cstr_p(struct PP_Var lhs, const char* rhs)
282 {
283 uint32_t len = 0;
284 if (var_interface == NULL) {
285 return 0;
286 }
287 else {
288 const char* const cstr = var_interface->VarToUtf8(lhs, &len);
289 return strncmp(cstr, rhs, len) == 0;
290 }
291 }
292
293 int
294 pruby_var_prefixed_p(struct PP_Var var, const char* prefix)
295 {
296 uint32_t len = 0;
297 if (var_interface == NULL) {
298 return 0;
299 }
300 else {
301 const char* const cstr = var_interface->VarToUtf8(var, &len);
302 const size_t prefix_len = strlen(prefix);
303 return len >= prefix_len && memcmp(cstr, prefix, len) == 0;
304 }
305 }
306
307
308 /******************************************************************************
309 * Messaging
310 ******************************************************************************/
311
312 /* Posts the given C string as a message.
313 * @param data pointer to a NULL-terminated string */
314 void
315 pruby_post_cstr(void* data)
316 {
317 /* PPAPI main thread */
318 struct PepperInstance* const instance = (struct PepperInstance*)data;
319 const char* const msg = (const char*)instance->async_call_args;
320 messaging_interface->PostMessage(instance->instance,
321 pruby_cstr_to_var(msg));
322 }
323
324 /* Posts the given Ruby VALUE as a message.
325 * @param data a VALUE casted to void* */
326 void
327 pruby_post_value(void* data)
328 {
329 /* PPAPI main thread */
330 struct PepperInstance* const instance = (struct PepperInstance*)data;
331 volatile VALUE value = (VALUE)instance->async_call_args;
332 messaging_interface->PostMessage(instance->instance, pruby_obj_to_var(value));
333 }
334
335
336
337 /******************************************************************************
338 * Ruby initialization
339 ******************************************************************************/
340
341 static void
342 init_loadpath(void)
343 {
344 ruby_incpush("lib/ruby/"RUBY_LIB_VERSION);
345 ruby_incpush("lib/ruby/"RUBY_LIB_VERSION"/"RUBY_PLATFORM);
346 ruby_incpush(".");
347 }
348
349 static VALUE
350 init_libraries_internal(VALUE unused)
351 {
352 extern void Init_enc();
353 extern void Init_ext();
354
355 init_loadpath();
356 Init_enc();
357 Init_ext();
358 return Qnil;
359 }
360
361 static void*
362 init_libraries(void* data)
363 {
364 int state;
365 struct PepperInstance* const instance = (struct PepperInstance*)data;
366 current_instance = instance->instance;
367
368 if (pthread_mutex_lock(&instance->mutex)) {
369 perror("pepper-ruby:pthread_mutex_lock");
370 return 0;
371 }
372 rb_protect(&init_libraries_internal, Qnil, &state);
373 pthread_mutex_unlock(&instance->mutex);
374
375 if (state) {
376 volatile VALUE err = rb_errinfo();
377 err = rb_obj_as_string(err);
378 } else {
379 instance->async_call_args = (void*)"rubyReady";
380 core_interface->CallOnMainThread(
381 0, PP_MakeCompletionCallback(pruby_post_cstr, instance), 0);
382 }
383 return NULL;
384 }
385
386 static int
387 init_libraries_if_necessary(void)
388 {
389 static int initialized = 0;
390 if (!initialized) {
391 struct PepperInstance* const instance = GET_PEPPER_INSTANCE();
392 int err;
393 initialized = 1;
394 err = pthread_create(&instance->th, NULL, &init_libraries, instance);
395 if (err) {
396 fprintf(stderr, "pepper_ruby:pthread_create: %s\n", strerror(err));
397 exit(EXIT_FAILURE);
398 }
399 pthread_detach(instance->th);
400 }
401 return 0;
402 }
403
404 static int
405 pruby_init(void)
406 {
407 RUBY_INIT_STACK;
408 ruby_init();
409
410 instance_table = rb_hash_new();
411 rb_gc_register_mark_object(instance_table);
412
413 return 0;
414 }
415
416
417 /******************************************************************************
418 * Ruby evaluation
419 ******************************************************************************/
420
421 static void*
422 pruby_eval(void* data)
423 {
424 extern VALUE ruby_eval_string_from_file_protect(const char* src, const char* path, int* state);
425 struct PepperInstance* const instance = (struct PepperInstance*)data;
426 volatile VALUE src = (VALUE)instance->async_call_args;
427 volatile VALUE result = Qnil;
428 volatile int state;
429
430 RUBY_INIT_STACK;
431
432 if (pthread_mutex_lock(&instance->mutex)) {
433 perror("pepper-ruby:pthread_mutex_lock");
434 return 0;
435 }
436 result = ruby_eval_string_from_file_protect(
437 RSTRING_PTR(src), "(pepper-ruby)", &state);
438 pthread_mutex_unlock(&instance->mutex);
439
440 if (!state) {
441 instance->async_call_args =
442 rb_str_concat(rb_usascii_str_new_cstr("return:"),
443 rb_obj_as_string(result));
444 core_interface->CallOnMainThread(
445 0, PP_MakeCompletionCallback(pruby_post_value, instance), 0);
446 return NULL;
447 }
448 else {
449 rb_set_errinfo(Qnil);
450 instance->async_call_args =
451 rb_str_concat(rb_usascii_str_new_cstr("error:"),
452 rb_obj_as_string(result));
453 core_interface->CallOnMainThread(
454 0, PP_MakeCompletionCallback(pruby_post_value, instance), 0);
455 return NULL;
456 }
457 }
458
459
460 /******************************************************************************
461 * Pepper Module callbacks
462 ******************************************************************************/
463
486 static PP_Bool
487 Instance_DidCreate(PP_Instance instance,
488 uint32_t argc, const char* argn[], const char* argv[])
489 {
490 struct PepperInstance* data = pruby_register_instance(instance);
491 current_instance = instance;
492 return init_libraries_if_necessary() ? PP_FALSE : PP_TRUE;
493 }
494
502 static void Instance_DidDestroy(PP_Instance instance) {
503 struct PepperInstance* data = pruby_get_instance(instance);
504 core_interface->ReleaseResource(data->url_loader);
505 pruby_unregister_instance(instance);
506 }
507
520 #ifdef PPP_INSTANCE_INTERFACE_1_0
521 static void
522 Instance_DidChangeView(PP_Instance instance,
523 const struct PP_Rect* position,
524 const struct PP_Rect* clip)
525 {
526 }
527 #else
528 static void
529 Instance_DidChangeView(PP_Instance instance, PP_Resource view_resource)
530 {
531 }
532 #endif
533
551 static void
552 Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus)
553 {
554 }
555
566 static PP_Bool
567 Instance_HandleDocumentLoad(PP_Instance instance, PP_Resource url_loader)
568 {
569 /* NaCl modules do not need to handle the document load function. */
570 return PP_FALSE;
571 }
572
573
589 void
590 Messaging_HandleMessage(PP_Instance instance, struct PP_Var var_message)
591 {
592 char* const message = pruby_var_to_cstr(var_message);
593 size_t message_len = strlen(message);
594 current_instance = instance;
595
596 if (strstr(message, "eval:") != NULL) {
597 volatile VALUE src;
598 struct PepperInstance* const instance_data = GET_PEPPER_INSTANCE();
599 int err;
600 #define EVAL_PREFIX_LEN 5
601 src = rb_str_new(message + EVAL_PREFIX_LEN, message_len - EVAL_PREFIX_LEN);
602 instance_data->async_call_args = (void*)src;
603 err = pthread_create(&instance_data->th, NULL, &pruby_eval, instance_data);
604 if (err) {
605 fprintf(stderr, "pepper_ruby:pthread_create: %s\n", strerror(err));
606 exit(EXIT_FAILURE);
607 }
608 pthread_detach(instance_data->th);
609 }
610 free(message);
611 }
612
620 PP_EXPORT int32_t
621 PPP_InitializeModule(PP_Module a_module_id, PPB_GetInterface get_browser_interface)
622 {
623 module_id = a_module_id;
624 core_interface = (PPB_Core*)(get_browser_interface(PPB_CORE_INTERFACE));
625 if (core_interface == NULL) return PP_ERROR_NOINTERFACE;
626
627 var_interface = (PPB_Var*)(get_browser_interface(PPB_VAR_INTERFACE));
628 if (var_interface == NULL) return PP_ERROR_NOINTERFACE;
629
630 messaging_interface = (PPB_Messaging*)(get_browser_interface(PPB_MESSAGING_INTERFACE));
631 if (messaging_interface == NULL) return PP_ERROR_NOINTERFACE;
632
633 loader_interface = (PPB_URLLoader*)(get_browser_interface(PPB_URLLOADER_INTERFACE));
634 if (loader_interface == NULL) return PP_ERROR_NOINTERFACE;
635
636 request_interface = (PPB_URLRequestInfo*)(get_browser_interface(PPB_URLREQUESTINFO_INTERFACE));
637 if (request_interface == NULL) return PP_ERROR_NOINTERFACE;
638
639 response_interface = (PPB_URLResponseInfo*)(get_browser_interface(PPB_URLRESPONSEINFO_INTERFACE));
640 if (response_interface == NULL) return PP_ERROR_NOINTERFACE;
641
642 fileref_interface = (PPB_FileRef*)(get_browser_interface(PPB_FILEREF_INTERFACE));
643 if (fileref_interface == NULL) return PP_ERROR_NOINTERFACE;
644
645 return pruby_init() ? PP_ERROR_FAILED : PP_OK;
646 }
647
654 PP_EXPORT const void*
655 PPP_GetInterface(const char* interface_name)
656 {
657 if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
658 static PPP_Instance instance_interface = {
659 &Instance_DidCreate,
660 &Instance_DidDestroy,
661 &Instance_DidChangeView,
662 &Instance_DidChangeFocus,
663 &Instance_HandleDocumentLoad
664 };
665 return &instance_interface;
666 } else if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) {
667 static PPP_Messaging messaging_interface = {
668 &Messaging_HandleMessage
669 };
670 return &messaging_interface;
671 }
672 return NULL;
673 }
674
678 PP_EXPORT void
679 PPP_ShutdownModule()
680 {
681 ruby_cleanup(0);
682 }
683
684 /******************************************************************************
685 * Overwrites rb_file_load_ok
686 ******************************************************************************/
687
688 static void
689 load_ok_internal(void* data, int32_t unused)
690 {
691 /* PPAPI main thread */
692 struct PepperInstance* const instance = (struct PepperInstance*)data;
693 const char *const path = (const char*)instance->async_call_args;
694 PP_Resource req;
695 int result;
696
697 instance->url_loader = loader_interface->Create(instance->instance);
698 req = request_interface->Create(instance->instance);
699 request_interface->SetProperty(
700 req, PP_URLREQUESTPROPERTY_METHOD, pruby_cstr_to_var("HEAD"));
701 request_interface->SetProperty(
702 req, PP_URLREQUESTPROPERTY_URL, pruby_cstr_to_var(path));
703
704 result = loader_interface->Open(
705 instance->url_loader, req,
706 PP_MakeCompletionCallback(pruby_async_return_int, instance));
707 if (result != PP_OK_COMPLETIONPENDING) {
708 pruby_async_return_int(instance, result);
709 }
710 }
711
712 static void
713 pruby_file_fetch_check_response(void* data, int32_t unused)
714 {
715 /* PPAPI main thread */
716 PP_Resource res;
717 struct PepperInstance* const instance = (struct PepperInstance*)data;
718
719 res = loader_interface->GetResponseInfo(instance->url_loader);
720 if (res) {
721 struct PP_Var status =
722 response_interface->GetProperty(res, PP_URLRESPONSEPROPERTY_STATUSCODE);
723 if (status.type == PP_VARTYPE_INT32) {
724 pruby_async_return_int(instance, status.value.as_int / 100 == 2 ? PP_OK : PP_ERROR_FAILED);
725 return;
726 }
727 else {
728 messaging_interface->PostMessage(
729 instance->instance, pruby_cstr_to_var("Unexpected type: ResponseInfoInterface::GetProperty"));
730 }
731 }
732 else {
733 messaging_interface->PostMessage(
734 instance->instance, pruby_cstr_to_var("Failed to open URL: URLLoaderInterface::GetResponseInfo"));
735 }
736 pruby_async_return_int(instance, PP_ERROR_FAILED);
737 }
738
739
740 int
741 rb_file_load_ok(const char *path)
742 {
743 struct PepperInstance* const instance = GET_PEPPER_INSTANCE();
744 if (path[0] == '.' && path[1] == '/') path += 2;
745
746 instance->async_call_args = (void*)path;
747 core_interface->CallOnMainThread(
748 0, PP_MakeCompletionCallback(load_ok_internal, instance), 0);
749 if (pthread_cond_wait(&instance->cond, &instance->mutex)) {
750 perror("pepper-ruby:pthread_cond_wait");
751 return 0;
752 }
753 if (instance->async_call_result.as_int != PP_OK) {
754 fprintf(stderr, "Failed to open URL: %d: %s\n",
755 instance->async_call_result.as_int, path);
756 return 0;
757 }
758
759 core_interface->CallOnMainThread(
760 0, PP_MakeCompletionCallback(pruby_file_fetch_check_response, instance), 0);
761 if (pthread_cond_wait(&instance->cond, &instance->mutex)) {
762 perror("pepper-ruby:pthread_cond_wait");
763 return 0;
764 }
765 return instance->async_call_result.as_int == PP_OK;
766 }
767
768 /******************************************************************************
769 * Overwrites rb_load_file
770 ******************************************************************************/
771
772 static void
773 load_file_internal(void* data, int32_t unused)
774 {
775 /* PPAPI main thread */
776 struct PepperInstance* const instance = (struct PepperInstance*)data;
777 const char *const path = (const char*)instance->async_call_args;
778 PP_Resource req;
779 int result;
780
781 instance->url_loader = loader_interface->Create(instance->instance);
782 req = request_interface->Create(instance->instance);
783 request_interface->SetProperty(
784 req, PP_URLREQUESTPROPERTY_METHOD, pruby_cstr_to_var("GET"));
785 request_interface->SetProperty(
786 req, PP_URLREQUESTPROPERTY_URL, pruby_cstr_to_var(path));
787
788 result = loader_interface->Open(
789 instance->url_loader, req,
790 PP_MakeCompletionCallback(pruby_async_return_int, instance));
791 if (result != PP_OK_COMPLETIONPENDING) {
792 pruby_async_return_int(instance, result);
793 }
794 }
795
796 static void
797 load_file_read_contents_callback(void *data, int result)
798 {
799 struct PepperInstance* const instance = (struct PepperInstance*)data;
800 if (result > 0) {
801 rb_str_buf_cat(instance->async_call_result.as_value,
802 instance->buf, result);
803 loader_interface->ReadResponseBody(
804 instance->url_loader, instance->buf, 1000, PP_MakeCompletionCallback(load_file_read_contents_callback, instance));
805 }
806 else if (result == 0) {
807 pruby_async_return_value(data, instance->async_call_result.as_value);
808 }
809 else {
810 pruby_async_return_value(data, INT2FIX(result));
811 }
812 }
813
814 static void
815 load_file_read_contents(void *data, int result)
816 {
817 struct PepperInstance* const instance = (struct PepperInstance*)data;
818 instance->async_call_result.as_value = rb_str_new(0, 0);
819 loader_interface->ReadResponseBody(
820 instance->url_loader, instance->buf, 1000, PP_MakeCompletionCallback(load_file_read_contents_callback, instance));
821 }
822
823 void*
824 rb_load_file(const char *path)
825 {
826 const char *real_path;
827 struct PepperInstance* instance;
828 if (path[0] != '.' || path[1] != '/') path += 2;
829
830 instance = GET_PEPPER_INSTANCE();
831
832 instance->async_call_args = (void*)path;
833 core_interface->CallOnMainThread(
834 0, PP_MakeCompletionCallback(load_file_internal, instance), 0);
835 if (pthread_cond_wait(&instance->cond, &instance->mutex)) {
836 perror("pepper-ruby:pthread_cond_wait");
837 return 0;
838 }
839 if (instance->async_call_result.as_int != PP_OK) {
840 fprintf(stderr, "Failed to open URL: %d: %s\n",
841 instance->async_call_result.as_int, path);
842 return 0;
843 }
844
845 core_interface->CallOnMainThread(
846 0, PP_MakeCompletionCallback(pruby_file_fetch_check_response, instance), 0);
847 if (pthread_cond_wait(&instance->cond, &instance->mutex)) {
848 perror("pepper-ruby:pthread_cond_wait");
849 return 0;
850 }
851 if (instance->async_call_result.as_int != PP_OK) return 0;
852
853 core_interface->CallOnMainThread(
854 0, PP_MakeCompletionCallback(load_file_read_contents, instance), 0);
855 if (pthread_cond_wait(&instance->cond, &instance->mutex)) {
856 perror("pepper-ruby:pthread_cond_wait");
857 return 0;
858 }
859 if (FIXNUM_P(instance->async_call_result.as_value)) {
860 return 0;
861 }
862 else if (RB_TYPE_P(instance->async_call_result.as_value, T_STRING)) {
863 VALUE str = instance->async_call_result.as_value;
864 extern void* rb_compile_cstr(const char *f, const char *s, int len, int line);
865 return rb_compile_cstr(path, RSTRING_PTR(str), RSTRING_LEN(str), 0);
866 }
867 else {
868 return 0;
869 }
870 }
data
VALUE data
Definition: tcltklib.c:3368
RB_TYPE_P
#define RB_TYPE_P(obj, type)
PepperInstance::as_value
VALUE as_value
Definition: pepper_main.c:90
load_file_read_contents_callback
static void load_file_read_contents_callback(void *data, int result)
Definition: pepper_main.c:797
pruby_init
static int pruby_init(void)
Definition: pepper_main.c:405
ruby_cleanup
int ruby_cleanup(volatile int ex)
Destructs the VM.
Definition: eval.c:155
pepper_instance_data_type
static const rb_data_type_t pepper_instance_data_type
Definition: pepper_main.c:77
malloc
void * malloc()
PepperInstance::as_int
int32_t as_int
Definition: pepper_main.c:88
Instance_DidChangeFocus
static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus)
Notification that the given NaCl module has gained or lost focus.
Definition: pepper_main.c:552
strlen
size_t strlen(const char *)
st_table
Definition: ripper.y:77
pruby_unregister_instance
int pruby_unregister_instance(PP_Instance instance)
Definition: pepper_main.c:133
ruby.h
rb_file_load_ok
int rb_file_load_ok(const char *)
Definition: file.c:5260
PepperInstance::instance
PP_Instance instance
Definition: pepper_main.c:83
response_interface
static PPB_URLResponseInfo * response_interface
Definition: pepper_main.c:62
pruby_register_instance
struct PepperInstance * pruby_register_instance(PP_Instance instance)
Definition: pepper_main.c:116
path
gz path
Definition: zlib.c:2279
TYPE
#define TYPE(x)
RSTRING_PTR
#define RSTRING_PTR(str)
var
VALUE var
Definition: tcltklib.c:5517
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:771
RUBY_MARK_LEAVE
#define RUBY_MARK_LEAVE(msg)
Definition: gc.h:54
verconf.h
gc.h
PepperInstance::cond
pthread_cond_t cond
Definition: pepper_main.c:96
Init_ext
void Init_ext(void)
Definition: dmyext.c:2
init_loadpath
static void init_loadpath(void)
Definition: pepper_main.c:342
pruby_eval
static void * pruby_eval(void *data)
Definition: pepper_main.c:422
current_instance
static PP_Instance current_instance
Definition: pepper_main.c:68
pruby_obj_to_var
static struct PP_Var pruby_obj_to_var(volatile VALUE obj)
Definition: pepper_main.c:266
state
int state
Definition: tcltklib.c:1462
PPP_GetInterface
PP_EXPORT const void * PPP_GetInterface(const char *interface_name)
Returns an interface pointer for the interface of the given name, or NULL if the interface is not sup...
Definition: pepper_main.c:655
rb_load_file
void * rb_load_file(const char *)
Definition: pepper_main.c:824
Instance_DidChangeView
static void Instance_DidChangeView(PP_Instance instance, PP_Resource view_resource)
Called when the position, the size, or the clip rect of the element in the browser that corresponds t...
Definition: pepper_main.c:529
pruby_async_return_str
void pruby_async_return_str(void *data, const char *result)
Definition: pepper_main.c:179
rb_str_concat
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:2162
rb_hash_delete
VALUE rb_hash_delete(VALUE, VALUE)
Definition: hash.c:859
Instance_HandleDocumentLoad
static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance, PP_Resource url_loader)
Handler that gets called after a full-frame module is instantiated based on registered MIME types...
Definition: pepper_main.c:567
ruby_incpush
void ruby_incpush(const char *)
Definition: ruby.c:336
lhs
command_asgn lhs
Definition: ripper.y:1269
PepperInstance::self
VALUE self
Definition: pepper_main.c:85
PepperInstance::mutex
pthread_mutex_t mutex
Definition: pepper_main.c:95
pruby_var_equal_to_cstr_p
int pruby_var_equal_to_cstr_p(struct PP_Var lhs, const char *rhs)
Definition: pepper_main.c:281
init_libraries_internal
static VALUE init_libraries_internal(VALUE unused)
Definition: pepper_main.c:350
messaging_interface
static PPB_Messaging * messaging_interface
Definition: pepper_main.c:58
FIXNUM_P
#define FIXNUM_P(f)
TypedData_Get_Struct
#define TypedData_Get_Struct(obj, type, data_type, sval)
Qnil
#define Qnil
Definition: tcltklib.c:1896
ruby_init
void ruby_init(void)
Definition: eval.c:71
str
static VALUE char * str
Definition: tcltklib.c:3547
PPP_ShutdownModule
PP_EXPORT void PPP_ShutdownModule()
Called before the plugin module is unloaded.
Definition: pepper_main.c:679
EVAL_PREFIX_LEN
#define EVAL_PREFIX_LEN
obj
static VALUE VALUE obj
Definition: tcltklib.c:3158
RSTRING_LEN
#define RSTRING_LEN(str)
INT2FIX
#define INT2FIX(i)
PepperInstance::as_str
const char * as_str
Definition: pepper_main.c:89
pruby_str_to_var
static struct PP_Var pruby_str_to_var(volatile VALUE str)
Definition: pepper_main.c:249
inst_mark
static void inst_mark(void *const ptr)
Definition: pepper_main.c:140
T_STRING
#define T_STRING
RUBY_MARK_ENTER
#define RUBY_MARK_ENTER(msg)
Definition: gc.h:53
err
int err
Definition: win32.c:87
pruby_get_instance
struct PepperInstance * pruby_get_instance(PP_Instance instance)
Definition: pepper_main.c:100
EXIT_FAILURE
#define EXIT_FAILURE
Definition: eval_intern.h:24
prefix_len
size_t prefix_len
Definition: tkutil.c:206
rb_compile_cstr
NODE * rb_compile_cstr(const char *f, const char *s, int len, int line)
Definition: ripper.c:12043
RUBY_INIT_STACK
#define RUBY_INIT_STACK
pruby_var_to_cstr
static char * pruby_var_to_cstr(struct PP_Var var)
Returns a mutable C string contained in the var or NULL if var is not string.
Definition: pepper_main.c:233
instance_table
static VALUE instance_table
Definition: pepper_main.c:66
rb_str_buf_cat
VALUE rb_str_buf_cat(VALUE, const char *, long)
Definition: string.c:1947
PepperInstance
Definition: pepper_main.c:82
rb_obj_as_string
VALUE rb_obj_as_string(VALUE)
Definition: string.c:895
argv
VALUE * argv
Definition: tcltklib.c:1971
rb_hash_aset
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
memcpy
memcpy(buf+1, str, len)
RTEST
#define RTEST(v)
result
q result
Definition: tcltklib.c:7070
module_id
static PP_Module module_id
Definition: pepper_main.c:56
value
volatile VALUE value
Definition: tcltklib.c:9442
const
#define const
Definition: strftime.c:102
s
register char * s
Definition: os2.c:56
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE)
Definition: gc.c:2980
ruby_xfree
void ruby_xfree(void *x)
Definition: gc.c:3651
instance_data
static struct st_table * instance_data
Definition: pepper_main.c:64
inst_memsize
static size_t inst_memsize(void *const ptr)
Definition: pepper_main.c:157
core_interface
static PPB_Core * core_interface
Definition: pepper_main.c:57
fileref_interface
static PPB_FileRef * fileref_interface
Definition: pepper_main.c:63
argc
int argc
Definition: tcltklib.c:1970
init_libraries_if_necessary
static int init_libraries_if_necessary(void)
Definition: pepper_main.c:387
pruby_post_value
void pruby_post_value(void *data)
Definition: pepper_main.c:327
memcmp
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
version.h
free
#define free(x)
Definition: dln.c:50
ptr
return ptr
Definition: tcltklib.c:784
msg
volatile VALUE msg
Definition: tcltklib.c:3100
uint32_t
unsigned int uint32_t
Definition: sha2.h:101
strerror
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
PepperInstance::url_loader
PP_Resource url_loader
Definition: pepper_main.c:84
RUBY_PLATFORM
#define RUBY_PLATFORM
Definition: defines.h:237
src
VALUE src
Definition: tcltklib.c:7953
PPP_InitializeModule
PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id, PPB_GetInterface get_browser_interface)
Entry points for the module.
Definition: pepper_main.c:621
GET_PEPPER_INSTANCE
#define GET_PEPPER_INSTANCE()
Definition: pepper_main.c:113
f
#define f
Qundef
#define Qundef
if
if(RB_TYPE_P(r, T_FLOAT))
Definition: bigdecimal.c:1186
PepperInstance::async_call_result
union PepperInstance::@114 async_call_result
rb_set_errinfo
void rb_set_errinfo(VALUE err)
Definition: eval.c:1436
pruby_cstr_to_var
static struct PP_Var pruby_cstr_to_var(const char *str)
Creates a new string PP_Var from C string.
Definition: pepper_main.c:211
rb_data_type_struct
Definition: ripper.y:960
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Instance_DidDestroy
static void Instance_DidDestroy(PP_Instance instance)
Called when the NaCl module is destroyed.
Definition: pepper_main.c:502
ruby_eval_string_from_file_protect
VALUE ruby_eval_string_from_file_protect(const char *str, const char *filename, int *state)
Definition: vm_eval.c:1366
pruby_post_cstr
void pruby_post_cstr(void *data)
Definition: pepper_main.c:315
pruby_var_prefixed_p
int pruby_var_prefixed_p(struct PP_Var var, const char *prefix)
Definition: pepper_main.c:294
request_interface
static PPB_URLRequestInfo * request_interface
Definition: pepper_main.c:61
pruby_file_fetch_check_response
static void pruby_file_fetch_check_response(void *data, int32_t unused)
Definition: pepper_main.c:713
RUBY_MARK_UNLESS_NULL
#define RUBY_MARK_UNLESS_NULL(ptr)
Definition: gc.h:60
strstr
RUBY_EXTERN char * strstr(const char *, const char *)
Definition: strstr.c:8
init_libraries
static void * init_libraries(void *data)
Definition: pepper_main.c:362
rb_str_new
VALUE rb_str_new(const char *, long)
Definition: string.c:425
res
Real * res
Definition: bigdecimal.c:1233
Init_enc
void Init_enc(void)
Definition: dmyext.c:7
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:234
rb_errinfo
#define rb_errinfo()
Definition: tcltklib.c:89
PepperInstance::async_call_args
void * async_call_args
Definition: pepper_main.c:86
rb_hash_aref
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:560
load_ok_internal
static void load_ok_internal(void *data, int32_t unused)
Definition: pepper_main.c:689
VALUE
unsigned long VALUE
Definition: ripper.y:104
Messaging_HandleMessage
void Messaging_HandleMessage(PP_Instance instance, struct PP_Var var_message)
Handler for messages coming in from the browser via postMessage.
Definition: pepper_main.c:590
inst_free
static void inst_free(void *const ptr)
Definition: pepper_main.c:151
var_interface
static PPB_Var * var_interface
Definition: pepper_main.c:59
position
Tcl_QueuePosition position
Definition: tcltklib.c:7616
PepperInstance::buf
char buf[1000]
Definition: pepper_main.c:92
rb_cData
RUBY_EXTERN VALUE rb_cData
Definition: ripper.y:1433
pruby_async_return_value
void pruby_async_return_value(void *data, VALUE value)
Definition: pepper_main.c:190
NULL
#define NULL
Definition: _sdbm.c:103
Instance_DidCreate
static PP_Bool Instance_DidCreate(PP_Instance instance, uint32_t argc, const char *argn[], const char *argv[])
Called when the NaCl module is instantiated on the web page.
Definition: pepper_main.c:487
PepperInstance::th
pthread_t th
Definition: pepper_main.c:94
rb_usascii_str_new_cstr
VALUE rb_usascii_str_new_cstr(const char *)
load_file_internal
static void load_file_internal(void *data, int32_t unused)
Definition: pepper_main.c:773
load_file_read_contents
static void load_file_read_contents(void *data, int result)
Definition: pepper_main.c:815
pruby_async_return_int
void pruby_async_return_int(void *data, int32_t result)
Definition: pepper_main.c:168
loader_interface
static PPB_URLLoader * loader_interface
Definition: pepper_main.c:60
len
size_t len
Definition: tcltklib.c:3568