static void n2p_construct_ptac(void *param) { struct construct_param_s *p = param; NPP npp = tables_get_npobj_npp_mapping(p->object); NPVariant *np_args = malloc(p->argc * sizeof(NPVariant)); for (uint32_t k = 0; k < p->argc; k ++) np_args[k] = pp_var_to_np_variant(p->argv[k]); NPVariant np_result; bool res = npp ? npn.construct(npp, p->object, np_args, p->argc, &np_result) : FALSE; for (uint32_t k = 0; k < p->argc; k ++) npn.releasevariantvalue(&np_args[k]); free(np_args); if (res) { struct PP_Var var = np_variant_to_pp_var(np_result); if (np_result.type == NPVariantType_Object) tables_add_npobj_npp_mapping(np_result.value.objectValue, npp); else npn.releasevariantvalue(&np_result); p->result = var; } else { p->result = PP_MakeUndefined(); } ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void _execute_script_ptac(void *user_data) { struct execute_script_param_s *p = user_data; NPString np_script; NPVariant np_result; // no need to lock, this function is run only in browser thread if (!p->pp_i->npp) { trace_error("%s, plugin instance was destroyed\n", __func__); p->result = PP_MakeUndefined(); goto quit; } np_script.UTF8Characters = ppb_var_var_to_utf8(p->script, &np_script.UTF8Length); if (!npn.evaluate(p->pp_i->npp, p->pp_i->np_window_obj, &np_script, &np_result)) { trace_error("%s, NPN_Evaluate failed\n", __func__); p->result = PP_MakeUndefined(); goto quit; } // TODO: find out what exception is p->result = np_variant_to_pp_var(np_result); if (np_result.type == NPVariantType_Object) tables_add_npobj_npp_mapping(np_result.value.objectValue, p->pp_i->npp); else npn.releasevariantvalue(&np_result); quit: ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void call_plugin_shutdown_module_comt(void *user_data, int32_t result) { struct call_plugin_shutdown_module_param_s *p = user_data; p->ppp_shutdown_module(); // p->ppp_shutdown_module is always non-NULL ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void call_plugin_init_module_comt(void *user_data, int32_t result) { struct call_plugin_init_module_param_s *p = user_data; // TODO: make module ids distinct // p->ppp_initialize_module is always non-NULL p->result = p->ppp_initialize_module(42, ppb_get_interface); ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
void ppb_flash_message_loop_quit(PP_Resource flash_message_loop) { struct pp_flash_message_loop_s *fml = pp_resource_acquire(flash_message_loop, PP_RESOURCE_FLASH_MESSAGE_LOOP); if (!fml) { trace_error("%s, bad resource\n", __func__); return; } if (fml->running) ppb_message_loop_post_quit_depth(fml->message_loop, PP_FALSE, fml->depth); pp_resource_release(flash_message_loop); }
static void topmost_rect_ptac(void *param) { struct topmost_rect_param_s *p = param; struct pp_instance_s *pp_i = tables_get_pp_instance(p->instance); if (!pp_i) { trace_error("%s, no instance\n", __func__); goto err_1; } p->result = PP_FALSE; NPString topmost_func_src = NPString_literal( "(function(elem, x, y) {" "var r = elem.getBoundingClientRect();" "return document.elementFromPoint(x + r.left, y + r.top) == elem;" "})"); NPVariant topmost_func; if (!npn.evaluate(pp_i->npp, pp_i->np_window_obj, &topmost_func_src, &topmost_func)) goto err_1; if (!NPVARIANT_IS_OBJECT(topmost_func)) goto err_1; NPObject *topmost_func_obj = NPVARIANT_TO_OBJECT(topmost_func); NPVariant is_topmost; NPVariant args[3]; OBJECT_TO_NPVARIANT(pp_i->np_plugin_element_obj, args[0]); INT32_TO_NPVARIANT(p->rect.point.x + p->rect.size.width / 2, args[1]); INT32_TO_NPVARIANT(p->rect.point.y + p->rect.size.height / 2, args[2]); if (!npn.invokeDefault(pp_i->npp, topmost_func_obj, args, 3, &is_topmost)) goto err_2; if (!NPVARIANT_IS_BOOLEAN(is_topmost)) goto err_3; p->result = NPVARIANT_TO_BOOLEAN(is_topmost); err_3: npn.releasevariantvalue(&is_topmost); err_2: npn.releasevariantvalue(&topmost_func); err_1: ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void n2p_has_property_ptac(void *param) { struct has_property_param_s *p = param; const char *s_name = ppb_var_var_to_utf8(p->name, NULL); NPIdentifier identifier = npn.getstringidentifier(s_name); NPP npp = tables_get_npobj_npp_mapping(p->object); if (npp) p->result = npn.hasproperty(npp, p->object, identifier); else p->result = false; ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void p2n_enumerate_comt(void *user_data, int32_t result) { struct enumerate_param_s *p = user_data; struct np_proxy_object_s *obj = (void *)p->npobj; struct PP_Var exception; p->count = 0; p->values = NULL; p->result = true; ppb_var_get_all_property_names(obj->ppobj, &p->count, &p->values, &exception); ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void n2p_deallocate_ptac(void *param) { struct deallocate_param_s *p = param; NPObject *np_object = p->object; uint32_t ref_cnt = np_object->referenceCount; npn.releaseobject(p->object); if (ref_cnt <= 1) tables_remove_npobj_npp_mapping(p->object); ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void p2n_has_method_comt(void *user_data, int32_t result) { struct has_method_param_s *p = user_data; struct np_proxy_object_s *obj = (void *)p->npobj; struct PP_Var exception = PP_MakeUndefined(); struct PP_Var method_name = ppb_var_var_from_utf8_z(p->name); p->result = ppb_var_has_method(obj->ppobj, method_name, &exception); ppb_var_release(method_name); ppb_var_release(exception); ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void p2n_get_property_comt(void *user_data, int32_t result) { struct get_property_param_s *p = user_data; struct np_proxy_object_s *obj = (void *)p->npobj; struct PP_Var exception = PP_MakeUndefined(); struct PP_Var property_name = ppb_var_var_from_utf8_z(p->name); struct PP_Var res = ppb_var_get_property(obj->ppobj, property_name, &exception); p->result = true; *p->np_result = pp_var_to_np_variant(res); ppb_var_release(res); ppb_var_release(exception); ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void clipboard_is_format_available_ptac(void *user_data) { struct clipboard_is_format_available_param_s *p = user_data; p->result = PP_FALSE; GtkClipboard *clipboard = get_clipboard_of_type(p->clipboard_type); if (!clipboard) goto quit; GdkAtom target = get_clipboard_target_atom(p->format); if (target == GDK_NONE) goto quit; p->result = gw_gtk_clipboard_wait_is_target_available(clipboard, target); quit: ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void _get_document_url_ptac(void *user_data) { struct get_document_url_param_s *p = user_data; p->result = ppb_var_var_from_utf8("", 0); NPIdentifier location_id = npn.getstringidentifier("location"); NPIdentifier href_id = npn.getstringidentifier("href"); NPObject *np_location_obj; NPVariant location_var, href_var; if (!npn.getproperty(p->npp, p->np_window_obj, location_id, &location_var)) goto err_2; if (location_var.type != NPVariantType_Object) goto err_3; np_location_obj = location_var.value.objectValue; if (!npn.getproperty(p->npp, np_location_obj, href_id, &href_var)) goto err_3; struct PP_Var var = np_variant_to_pp_var(href_var); if (var.type != PP_VARTYPE_STRING) { ppb_var_release(var); goto err_4; } ppb_var_release(p->result); p->result = var; err_4: npn.releasevariantvalue(&href_var); err_3: npn.releasevariantvalue(&location_var); err_2: ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); return; }
static void flash_menu_create_ptac(void *param) { struct flash_menu_create_param_s *p = param; struct pp_flash_menu_s *fm = pp_resource_acquire(p->flash_menu, PP_RESOURCE_FLASH_MENU); if (!fm) { trace_error("%s, bad resource\n", __func__); goto quit; } // recursively construct menu fm->menu = convert_menu(p->menu_data); // we need notification on menu close g_signal_connect(fm->menu, "selection-done", G_CALLBACK(menu_selection_done), NULL); pp_resource_release(p->flash_menu); quit: ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void p2n_invoke_comt(void *user_data, int32_t result) { struct invoke_param_s *p = user_data; unsigned int k; p->result = true; struct np_proxy_object_s *obj = (void *)p->npobj; struct PP_Var exception = PP_MakeUndefined(); struct PP_Var method_name = ppb_var_var_from_utf8_z(p->name); struct PP_Var res; struct PP_Var *pp_args = malloc(p->argCount * sizeof(*pp_args)); for (k = 0; k < p->argCount; k ++) { pp_args[k] = np_variant_to_pp_var(p->args[k]); } res = ppb_var_call(obj->ppobj, method_name, p->argCount, pp_args, &exception); for (k = 0; k < p->argCount; k ++) ppb_var_release(pp_args[k]); free(pp_args); if (p->np_result) { *p->np_result = pp_var_to_np_variant(res); if (p->np_result->type == NPVariantType_Object) { NPP npp = tables_get_npobj_npp_mapping(p->npobj); tables_add_npobj_npp_mapping(p->np_result->value.objectValue, npp); } } ppb_var_release(res); ppb_var_release(method_name); ppb_var_release(exception); ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void clipboard_read_data_ptac(void *user_data) { struct clipboard_read_data_param_s *p = user_data; p->result = PP_MakeUndefined(); GtkClipboard *clipboard = get_clipboard_of_type(p->clipboard_type); if (!clipboard) goto quit; GdkAtom target = get_clipboard_target_atom(p->format); if (target == GDK_NONE) goto quit; GtkSelectionData *sd = gw_gtk_clipboard_wait_for_contents(clipboard, target); if (sd) { const guchar *sd_data = gw_gtk_selection_data_get_data(sd); const gint sd_length = gw_gtk_selection_data_get_length(sd); switch (p->format) { case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT: case PP_FLASH_CLIPBOARD_FORMAT_HTML: p->result = ppb_var_var_from_utf8((char *)sd_data, sd_length); break; default: p->result = ppb_var_array_buffer_create(sd_length); memcpy(ppb_var_array_buffer_map(p->result), sd_data, sd_length); ppb_var_array_buffer_unmap(p->result); break; } gw_gtk_selection_data_free(sd); } quit: ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void n2p_get_property_ptac(void *param) { struct get_property_param_s *p = param; const char *s_name = ppb_var_var_to_utf8(p->name, NULL); NPIdentifier identifier = npn.getstringidentifier(s_name); NPVariant np_value; NPP npp = tables_get_npobj_npp_mapping(p->object); if (npp && npn.getproperty(npp, p->object, identifier, &np_value)) { struct PP_Var var = np_variant_to_pp_var(np_value); if (np_value.type == NPVariantType_Object) tables_add_npobj_npp_mapping(np_value.value.objectValue, npp); else npn.releasevariantvalue(&np_value); p->result = var; } else { p->result = PP_MakeUndefined(); } ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
int32_t ppb_message_loop_run_int(PP_Resource message_loop, int nested, int increase_depth) { if (this_thread_message_loop != message_loop) { trace_error("%s, not attached to current thread\n", __func__); return PP_ERROR_WRONG_THREAD; } struct pp_message_loop_s *ml = pp_resource_acquire(message_loop, PP_RESOURCE_MESSAGE_LOOP); if (!ml) { trace_error("%s, bad resource\n", __func__); return PP_ERROR_BADRESOURCE; } // prevent nested loops if (!nested && ml->running) { trace_error("%s, trying to run nested loop without declaring as nested\n", __func__); pp_resource_release(message_loop); return PP_ERROR_INPROGRESS; } struct { int running; int teardown; } saved_state = { .running = ml->running, .teardown = ml->teardown, }; ml->running = 1; ml->teardown = 0; if (increase_depth) ml->depth++; int teardown = 0; int destroy_ml = 0; int depth = ml->depth; pp_resource_ref(message_loop); GAsyncQueue *async_q = ml->async_q; GQueue *int_q = ml->int_q; pp_resource_release(message_loop); while (1) { struct timespec now; struct message_loop_task_s *task = g_queue_peek_head(int_q); gint64 timeout = 1000 * 1000; if (task) { clock_gettime(CLOCK_REALTIME, &now); timeout = (task->when.tv_sec - now.tv_sec) * 1000 * 1000 + (task->when.tv_nsec - now.tv_nsec) / 1000; if (timeout <= 0) { // remove task from the queue g_queue_pop_head(int_q); // check if depth is correct if (task->depth > 0 && task->depth < depth) { // wrong, reschedule it a bit later task->when = add_ms(now, 10); g_queue_insert_sorted(int_q, task, time_compare_func, NULL); continue; } if (task->terminate) { if (depth > 1) { // exit at once, all remaining task will be processed by outer loop g_slice_free(struct message_loop_task_s, task); break; } // it's the outermost loop, we should wait for all tasks to be run ml = pp_resource_acquire(message_loop, PP_RESOURCE_MESSAGE_LOOP); if (ml) { ml->teardown = 1; teardown = 1; destroy_ml = task->should_destroy_ml; pp_resource_release(message_loop); } g_slice_free(struct message_loop_task_s, task); continue; } // run task const struct PP_CompletionCallback ccb = task->ccb; if (ccb.func) { ccb.func(ccb.user_data, task->result_to_pass); } // free task g_slice_free(struct message_loop_task_s, task); continue; // run cycle again } } else if (teardown) { // teardown, no tasks in queue left break; } task = g_async_queue_timeout_pop(async_q, timeout); if (task) g_queue_insert_sorted(int_q, task, time_compare_func, NULL); } // mark thread as non-running ml = pp_resource_acquire(message_loop, PP_RESOURCE_MESSAGE_LOOP); if (ml) { if (increase_depth) ml->depth--; ml->running = 0; if (nested) { ml->running = saved_state.running; ml->teardown = saved_state.teardown; } pp_resource_release(message_loop); } pp_resource_unref(message_loop); if (destroy_ml) pp_resource_unref(message_loop); return PP_OK; } int32_t ppb_message_loop_post_work_with_result(PP_Resource message_loop, struct PP_CompletionCallback callback, int64_t delay_ms, int32_t result_to_pass, int depth) { if (callback.func == NULL) { trace_error("%s, callback.func == NULL\n", __func__); return PP_ERROR_BADARGUMENT; } struct pp_message_loop_s *ml = pp_resource_acquire(message_loop, PP_RESOURCE_MESSAGE_LOOP); if (!ml) { trace_error("%s, bad resource\n", __func__); return PP_ERROR_BADRESOURCE; } if (ml->running && ml->teardown) { // message loop is in a teardown state pp_resource_release(message_loop); trace_error("%s, quit request received, no additional work could be posted\n", __func__); return PP_ERROR_FAILED; } struct message_loop_task_s *task = g_slice_alloc0(sizeof(*task)); task->result_to_pass = result_to_pass; task->ccb = callback; task->depth = depth; // calculate absolute time callback should be run at clock_gettime(CLOCK_REALTIME, &task->when); task->when.tv_sec += delay_ms / 1000; task->when.tv_nsec += (delay_ms % 1000) * 1000 * 1000; while (task->when.tv_nsec >= 1000 * 1000 * 1000) { task->when.tv_sec += 1; task->when.tv_nsec -= 1000 * 1000 * 1000; } g_async_queue_push(ml->async_q, task); pp_resource_release(message_loop); return PP_OK; } int32_t ppb_message_loop_post_work(PP_Resource message_loop, struct PP_CompletionCallback callback, int64_t delay_ms) { return ppb_message_loop_post_work_with_result(message_loop, callback, delay_ms, PP_OK, 0); } int32_t ppb_message_loop_post_quit_depth(PP_Resource message_loop, PP_Bool should_destroy, int depth) { struct pp_message_loop_s *ml = pp_resource_acquire(message_loop, PP_RESOURCE_MESSAGE_LOOP); if (!ml) { trace_error("%s, bad resource\n", __func__); return PP_ERROR_BADRESOURCE; } struct message_loop_task_s *task = g_slice_alloc0(sizeof(*task)); task->terminate = 1; task->depth = depth; task->should_destroy_ml = should_destroy; task->result_to_pass = PP_OK; clock_gettime(CLOCK_REALTIME, &task->when); // run as early as possible g_async_queue_push(ml->async_q, task); pp_resource_release(message_loop); return PP_OK; } int32_t ppb_message_loop_post_quit(PP_Resource message_loop, PP_Bool should_destroy) { int depth = ppb_message_loop_get_depth(message_loop); return ppb_message_loop_post_quit_depth(message_loop, should_destroy, depth); }
static void url_loader_open_ptac(void *user_data) { struct url_loader_open_param_s *p = user_data; struct pp_instance_s *pp_i = tables_get_pp_instance(p->instance_id); if (!pp_i) { p->retval = NPERR_INVALID_INSTANCE_ERROR; goto quit; } if (p->method == PP_METHOD_POST) { // POST request char *tmpfname; int fd; FILE *fp = NULL; int need_newline = 0; tmpfname = g_strdup_printf("/tmp/FreshPostBodyXXXXXX"); // TODO: make configurable fd = mkstemp(tmpfname); if (fd < 0) { p->retval = NPERR_GENERIC_ERROR; goto err; } fp = fdopen(fd, "wb+"); if (!fp) { close(fd); p->retval = NPERR_GENERIC_ERROR; goto err; } if (p->request_headers) { fprintf(fp, "%s\n", p->request_headers); need_newline = 1; } if (p->custom_referrer_url) { // the header name should be "referer", that's how it's spelled in HTTP spec fprintf(fp, "Referer: %s\n", p->custom_referrer_url); need_newline = 1; } if (p->custom_content_transfer_encoding) { fprintf(fp, "Content-Transfer-Encoding: %s\n", p->custom_content_transfer_encoding); need_newline = 1; } if (p->custom_user_agent) { fprintf(fp, "User-Agent: %s\n", p->custom_user_agent); need_newline = 1; } if (p->post_data) { size_t post_len = post_data_get_all_item_length(p->post_data); if (post_len == (size_t)-1) { // PP_ERROR_FILECHANGED? goto err; } if (post_len > 0) { fprintf(fp, "Content-Length: %"PRIu64"\n", (uint64_t)post_len); need_newline = 1; } } if (need_newline) fprintf(fp, "\n"); if (p->post_data) { for (guint k = 0; k < p->post_data->len; k ++) post_data_write_to_fp(p->post_data, k, fp); } fclose(fp); // flush all unwritten data and close the file fp = NULL; // avoid calling fclose() twice if (p->target) { p->retval = npn.posturl(pp_i->npp, p->url, p->target, strlen(tmpfname), tmpfname, true); } else { p->retval = npn.posturlnotify(pp_i->npp, p->url, NULL, strlen(tmpfname), tmpfname, true, (void*)(size_t)p->loader); } err: if (fp) fclose(fp); unlink(tmpfname); g_free(tmpfname); } else { // GET request if (p->target) { p->retval = npn.geturl(pp_i->npp, p->url, p->target); } else { p->retval = npn.geturlnotify(pp_i->npp, p->url, NULL, (void*)(size_t)p->loader); } } quit: ppb_core_release_resource(p->loader); ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
static void _url_loader_open_ptac(void *user_data) { struct url_loader_open_param_s *p = user_data; struct pp_instance_s *pp_i = tables_get_pp_instance(p->instance_id); if (!pp_i) { p->retval = NPERR_INVALID_INSTANCE_ERROR; goto quit; } if (p->method == PP_METHOD_POST) { // POST request char *tmpfname; int fd; FILE *fp; int need_newline = 0; tmpfname = g_strdup_printf("/tmp/FreshPostBodyXXXXXX"); // TODO: make configurable fd = mkstemp(tmpfname); if (fd < 0) { p->retval = NPERR_GENERIC_ERROR; goto err; } fp = fdopen(fd, "wb+"); if (!fp) { close(fd); p->retval = NPERR_GENERIC_ERROR; goto err; } if (p->request_headers) { fprintf(fp, "%s\n", p->request_headers); need_newline = 1; } if (p->custom_referrer_url) { fprintf(fp, "Referrer: %s\n", p->custom_referrer_url); need_newline = 1; } if (p->custom_content_transfer_encoding) { fprintf(fp, "Content-Transfer-Encoding: %s\n", p->custom_content_transfer_encoding); need_newline = 1; } if (p->custom_user_agent) { fprintf(fp, "User-Agent: %s\n", p->custom_user_agent); need_newline = 1; } if (p->post_len > 0) { fprintf(fp, "Content-Length: %"PRIu64"\n", (uint64_t)p->post_len); need_newline = 1; } if (need_newline) fprintf(fp, "\n"); fwrite(p->post_data, 1, p->post_len, fp); fclose(fp); if (p->target) { p->retval = npn.posturl(pp_i->npp, p->url, p->target, strlen(tmpfname), tmpfname, true); } else { p->retval = npn.posturlnotify(pp_i->npp, p->url, NULL, strlen(tmpfname), tmpfname, true, (void*)(size_t)p->loader); } err: unlink(tmpfname); g_free(tmpfname); } else { // GET request if (p->target) { p->retval = npn.geturl(pp_i->npp, p->url, p->target); } else { p->retval = npn.geturlnotify(pp_i->npp, p->url, NULL, (void*)(size_t)p->loader); } } quit: ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); }
PP_Bool ppb_flash_draw_glyphs(PP_Instance instance, PP_Resource pp_image_data, const struct PP_BrowserFont_Trusted_Description *font_desc, uint32_t color, const struct PP_Point *position, const struct PP_Rect *clip, const float transformation[3][3], PP_Bool allow_subpixel_aa, uint32_t glyph_count, const uint16_t glyph_indices[], const struct PP_Point glyph_advances[]) { struct pp_image_data_s *id = pp_resource_acquire(pp_image_data, PP_RESOURCE_IMAGE_DATA); if (!id) { trace_error("%s, bad resource\n", __func__); return PP_FALSE; } cairo_t *cr = cairo_create(id->cairo_surf); const char *font_family; if (font_desc->face.type == PP_VARTYPE_STRING) { font_family = ppb_var_var_to_utf8(font_desc->face, NULL); } else { switch (font_desc->family) { case PP_BROWSERFONT_TRUSTED_FAMILY_SERIF: font_family = "serif"; break; case PP_BROWSERFONT_TRUSTED_FAMILY_SANSSERIF: font_family = "sans-serif"; break; case PP_BROWSERFONT_TRUSTED_FAMILY_MONOSPACE: font_family = "monospace"; break; default: font_family = ""; break; } } cairo_select_font_face(cr, font_family, font_desc->italic ? CAIRO_FONT_SLANT_ITALIC : CAIRO_FONT_SLANT_NORMAL, font_desc->weight >= (int)PP_FONTWEIGHT_700 ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cr, font_desc->size); if (allow_subpixel_aa) { cairo_font_options_t *options = cairo_font_options_create(); cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL); cairo_set_font_options(cr, options); cairo_font_options_destroy(options); } if (clip) { cairo_rectangle(cr, clip->point.x, clip->point.y, clip->size.width, clip->size.height); cairo_clip(cr); } cairo_set_source_rgba(cr, ((color >> 16) & 0xffu) / 255.0, ((color >> 8) & 0xffu) / 255.0, ((color >> 0) & 0xffu) / 255.0, ((color >> 24) & 0xffu) / 255.0); cairo_matrix_t matrix; cairo_matrix_init(&matrix, transformation[0][0], transformation[0][1], transformation[1][0], transformation[1][1], transformation[0][2], transformation[1][2]); cairo_set_matrix(cr, &matrix); cairo_glyph_t *c_glyphs = malloc(glyph_count * sizeof(cairo_glyph_t)); struct PP_Point current = {.x = 0, .y = 0}; for (uint32_t k = 0; k < glyph_count; k ++) { c_glyphs[k].index = glyph_indices[k]; c_glyphs[k].x = current.x; c_glyphs[k].y = current.y; current.x += glyph_advances[k].x; current.y += glyph_advances[k].y; } cairo_show_glyphs(cr, c_glyphs, glyph_count); free(c_glyphs); cairo_surface_flush(id->cairo_surf); cairo_destroy(cr); pp_resource_release(pp_image_data); return PP_TRUE; } struct get_proxy_for_url_param_s { PP_Instance instance_id; const char *url; struct PP_Var result; PP_Resource m_loop; int depth; }; static void get_proxy_for_url_ptac(void *user_data) { struct get_proxy_for_url_param_s *p = user_data; struct pp_instance_s *pp_i = tables_get_pp_instance(p->instance_id); p->result = PP_MakeUndefined(); if (pp_i && pp_i->npp && npn.getvalueforurl) { char *value = NULL; uint32_t len = 0; NPError err; err = npn.getvalueforurl(pp_i->npp, NPNURLVProxy, p->url, &value, &len); if (err == NPERR_NO_ERROR) { p->result = ppb_var_var_from_utf8(value, len); } } ppb_message_loop_post_quit_depth(p->m_loop, PP_FALSE, p->depth); } static void get_proxy_for_url_comt(void *user_data, int32_t result) { ppb_core_call_on_browser_thread(0, get_proxy_for_url_ptac, user_data); }