// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ppapi/proxy/resource_creation_proxy.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/pp_size.h" #include "ppapi/proxy/interface_id.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/c/trusted/ppb_image_data_trusted.h" #include "ppapi/proxy/plugin_resource_tracker.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/ppb_audio_proxy.h" #include "ppapi/proxy/ppb_buffer_proxy.h" #include "ppapi/proxy/ppb_broker_proxy.h" #include "ppapi/proxy/ppb_context_3d_proxy.h" #include "ppapi/proxy/ppb_file_chooser_proxy.h" #include "ppapi/proxy/ppb_file_ref_proxy.h" #include "ppapi/proxy/ppb_file_system_proxy.h" #include "ppapi/proxy/ppb_flash_menu_proxy.h" #include "ppapi/proxy/ppb_flash_net_connector_proxy.h" #include "ppapi/proxy/ppb_flash_tcp_socket_proxy.h" #include "ppapi/proxy/ppb_font_proxy.h" #include "ppapi/proxy/ppb_graphics_2d_proxy.h" #include "ppapi/proxy/ppb_graphics_3d_proxy.h" #include "ppapi/proxy/ppb_image_data_proxy.h" #include "ppapi/proxy/ppb_surface_3d_proxy.h" #include "ppapi/proxy/ppb_url_loader_proxy.h" #include "ppapi/proxy/ppb_video_capture_proxy.h" #include "ppapi/proxy/ppb_video_decoder_proxy.h" #include "ppapi/shared_impl/audio_config_impl.h" #include "ppapi/shared_impl/font_impl.h" #include "ppapi/shared_impl/function_group_base.h" #include "ppapi/shared_impl/host_resource.h" #include "ppapi/shared_impl/input_event_impl.h" #include "ppapi/shared_impl/url_request_info_impl.h" #include "ppapi/shared_impl/var.h" #include "ppapi/thunk/enter.h" #include "ppapi/thunk/ppb_image_data_api.h" using ppapi::thunk::ResourceCreationAPI; namespace ppapi { namespace proxy { ResourceCreationProxy::ResourceCreationProxy(Dispatcher* dispatcher) : InterfaceProxy(dispatcher) { } ResourceCreationProxy::~ResourceCreationProxy() { } // static InterfaceProxy* ResourceCreationProxy::Create(Dispatcher* dispatcher) { return new ResourceCreationProxy(dispatcher); } ResourceCreationAPI* ResourceCreationProxy::AsResourceCreationAPI() { return this; } PP_Resource ResourceCreationProxy::CreateAudio( PP_Instance instance, PP_Resource config_id, PPB_Audio_Callback audio_callback, void* user_data) { return PPB_Audio_Proxy::CreateProxyResource(instance, config_id, audio_callback, user_data); } PP_Resource ResourceCreationProxy::CreateAudioConfig( PP_Instance instance, PP_AudioSampleRate sample_rate, uint32_t sample_frame_count) { return AudioConfigImpl::CreateAsProxy( instance, sample_rate, sample_frame_count); } PP_Resource ResourceCreationProxy::CreateAudioTrusted(PP_Instance instance) { // Proxied plugins can't created trusted audio devices. return 0; } PP_Resource ResourceCreationProxy::CreateBroker(PP_Instance instance) { return PPB_Broker_Proxy::CreateProxyResource(instance); } PP_Resource ResourceCreationProxy::CreateBuffer(PP_Instance instance, uint32_t size) { return PPB_Buffer_Proxy::CreateProxyResource(instance, size); } PP_Resource ResourceCreationProxy::CreateContext3D( PP_Instance instance, PP_Config3D_Dev config, PP_Resource share_context, const int32_t* attrib_list) { return PPB_Context3D_Proxy::Create(instance, config, share_context, attrib_list); } PP_Resource ResourceCreationProxy::CreateContext3DRaw( PP_Instance instance, PP_Config3D_Dev config, PP_Resource share_context, const int32_t* attrib_list) { // Not proxied. The raw creation function is used only in the implementation // of the proxy on the host side. return 0; } PP_Resource ResourceCreationProxy::CreateDirectoryReader( PP_Resource directory_ref) { NOTIMPLEMENTED(); // Not proxied yet. return 0; } PP_Resource ResourceCreationProxy::CreateFileChooser( PP_Instance instance, PP_FileChooserMode_Dev mode, const PP_Var& accept_mime_types) { return PPB_FileChooser_Proxy::CreateProxyResource(instance, mode, accept_mime_types); } PP_Resource ResourceCreationProxy::CreateFileIO(PP_Instance instance) { NOTIMPLEMENTED(); // Not proxied yet. return 0; } PP_Resource ResourceCreationProxy::CreateFileRef(PP_Resource file_system, const char* path) { return PPB_FileRef_Proxy::CreateProxyResource(file_system, path); } PP_Resource ResourceCreationProxy::CreateFileSystem( PP_Instance instance, PP_FileSystemType type) { return PPB_FileSystem_Proxy::CreateProxyResource(instance, type); } PP_Resource ResourceCreationProxy::CreateFlashMenu( PP_Instance instance, const PP_Flash_Menu* menu_data) { return PPB_Flash_Menu_Proxy::CreateProxyResource(instance, menu_data); } PP_Resource ResourceCreationProxy::CreateFlashNetConnector( PP_Instance instance) { return PPB_Flash_NetConnector_Proxy::CreateProxyResource(instance); } PP_Resource ResourceCreationProxy::CreateFlashTCPSocket( PP_Instance instance) { return PPB_Flash_TCPSocket_Proxy::CreateProxyResource(instance); } PP_Resource ResourceCreationProxy::CreateFontObject( PP_Instance instance, const PP_FontDescription_Dev* description) { if (!ppapi::FontImpl::IsPPFontDescriptionValid(*description)) return 0; return (new Font(HostResource::MakeInstanceOnly(instance), *description))-> GetReference(); } PP_Resource ResourceCreationProxy::CreateGraphics2D(PP_Instance instance, const PP_Size& size, PP_Bool is_always_opaque) { return PPB_Graphics2D_Proxy::CreateProxyResource(instance, size, is_always_opaque); } PP_Resource ResourceCreationProxy::CreateImageData(PP_Instance instance, PP_ImageDataFormat format, const PP_Size& size, PP_Bool init_to_zero) { PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); if (!dispatcher) return 0; HostResource result; std::string image_data_desc; ImageHandle image_handle = ImageData::NullHandle; dispatcher->Send(new PpapiHostMsg_ResourceCreation_ImageData( INTERFACE_ID_RESOURCE_CREATION, instance, format, size, init_to_zero, &result, &image_data_desc, &image_handle)); if (result.is_null() || image_data_desc.size() != sizeof(PP_ImageDataDesc)) return 0; // We serialize the PP_ImageDataDesc just by copying to a string. PP_ImageDataDesc desc; memcpy(&desc, image_data_desc.data(), sizeof(PP_ImageDataDesc)); return (new ImageData(result, desc, image_handle))->GetReference(); } PP_Resource ResourceCreationProxy::CreateKeyboardInputEvent( PP_Instance instance, PP_InputEvent_Type type, PP_TimeTicks time_stamp, uint32_t modifiers, uint32_t key_code, struct PP_Var character_text) { if (type != PP_INPUTEVENT_TYPE_RAWKEYDOWN && type != PP_INPUTEVENT_TYPE_KEYDOWN && type != PP_INPUTEVENT_TYPE_KEYUP && type != PP_INPUTEVENT_TYPE_CHAR) return 0; ppapi::InputEventData data; data.event_type = type; data.event_time_stamp = time_stamp; data.event_modifiers = modifiers; data.key_code = key_code; if (character_text.type == PP_VARTYPE_STRING) { StringVar* text_str = StringVar::FromPPVar(character_text); if (!text_str) return 0; data.character_text = text_str->value(); } return (new InputEventImpl(InputEventImpl::InitAsProxy(), instance, data))->GetReference(); } PP_Resource ResourceCreationProxy::CreateMouseInputEvent( PP_Instance instance, PP_InputEvent_Type type, PP_TimeTicks time_stamp, uint32_t modifiers, PP_InputEvent_MouseButton mouse_button, const PP_Point* mouse_position, int32_t click_count, const PP_Point* mouse_movement) { if (type != PP_INPUTEVENT_TYPE_MOUSEDOWN && type != PP_INPUTEVENT_TYPE_MOUSEUP && type != PP_INPUTEVENT_TYPE_MOUSEMOVE && type != PP_INPUTEVENT_TYPE_MOUSEENTER && type != PP_INPUTEVENT_TYPE_MOUSELEAVE) return 0; ppapi::InputEventData data; data.event_type = type; data.event_time_stamp = time_stamp; data.event_modifiers = modifiers; data.mouse_button = mouse_button; data.mouse_position = *mouse_position; data.mouse_click_count = click_count; data.mouse_movement = *mouse_movement; return (new InputEventImpl(InputEventImpl::InitAsProxy(), instance, data))->GetReference(); } PP_Resource ResourceCreationProxy::CreateGraphics3D( PP_Instance instance, PP_Resource share_context, const int32_t* attrib_list) { return PPB_Graphics3D_Proxy::CreateProxyResource( instance, share_context, attrib_list); } PP_Resource ResourceCreationProxy::CreateGraphics3DRaw( PP_Instance instance, PP_Resource share_context, const int32_t* attrib_list) { // Not proxied. The raw creation function is used only in the implementation // of the proxy on the host side. return 0; } PP_Resource ResourceCreationProxy::CreateScrollbar(PP_Instance instance, PP_Bool vertical) { NOTIMPLEMENTED(); // Not proxied yet. return 0; } PP_Resource ResourceCreationProxy::CreateSurface3D( PP_Instance instance, PP_Config3D_Dev config, const int32_t* attrib_list) { return PPB_Surface3D_Proxy::CreateProxyResource(instance, config, attrib_list); } PP_Resource ResourceCreationProxy::CreateTransport(PP_Instance instance, const char* name, PP_TransportType type) { NOTIMPLEMENTED(); // Not proxied yet. return 0; } PP_Resource ResourceCreationProxy::CreateURLLoader(PP_Instance instance) { return PPB_URLLoader_Proxy::CreateProxyResource(instance); } PP_Resource ResourceCreationProxy::CreateURLRequestInfo( PP_Instance instance, const PPB_URLRequestInfo_Data& data) { return (new URLRequestInfoImpl( HostResource::MakeInstanceOnly(instance), data))->GetReference(); } PP_Resource ResourceCreationProxy::CreateVideoCapture(PP_Instance instance) { return PPB_VideoCapture_Proxy::CreateProxyResource(instance); } PP_Resource ResourceCreationProxy::CreateVideoDecoder( PP_Instance instance, PP_Resource context3d_id, PP_VideoDecoder_Profile profile) { return PPB_VideoDecoder_Proxy::CreateProxyResource( instance, context3d_id, profile); } PP_Resource ResourceCreationProxy::CreateVideoLayer( PP_Instance instance, PP_VideoLayerMode_Dev mode) { NOTIMPLEMENTED(); return 0; } PP_Resource ResourceCreationProxy::CreateWheelInputEvent( PP_Instance instance, PP_TimeTicks time_stamp, uint32_t modifiers, const PP_FloatPoint* wheel_delta, const PP_FloatPoint* wheel_ticks, PP_Bool scroll_by_page) { ppapi::InputEventData data; data.event_type = PP_INPUTEVENT_TYPE_WHEEL; data.event_time_stamp = time_stamp; data.event_modifiers = modifiers; data.wheel_delta = *wheel_delta; data.wheel_ticks = *wheel_ticks; data.wheel_scroll_by_page = PP_ToBool(scroll_by_page); return (new InputEventImpl(InputEventImpl::InitAsProxy(), instance, data))->GetReference(); } bool ResourceCreationProxy::Send(IPC::Message* msg) { return dispatcher()->Send(msg); } bool ResourceCreationProxy::OnMessageReceived(const IPC::Message& msg) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(ResourceCreationProxy, msg) IPC_MESSAGE_HANDLER(PpapiHostMsg_ResourceCreation_Graphics2D, OnMsgCreateGraphics2D) IPC_MESSAGE_HANDLER(PpapiHostMsg_ResourceCreation_ImageData, OnMsgCreateImageData) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } void ResourceCreationProxy::OnMsgCreateGraphics2D(PP_Instance instance, const PP_Size& size, PP_Bool is_always_opaque, HostResource* result) { ppapi::thunk::EnterFunction enter(instance, false); if (enter.succeeded()) { result->SetHostResource(instance, enter.functions()->CreateGraphics2D( instance, size, is_always_opaque)); } } void ResourceCreationProxy::OnMsgCreateImageData( PP_Instance instance, int32_t format, const PP_Size& size, PP_Bool init_to_zero, HostResource* result, std::string* image_data_desc, ImageHandle* result_image_handle) { *result_image_handle = ImageData::NullHandle; ppapi::thunk::EnterFunction enter(instance, false); if (enter.failed()) return; PP_Resource resource = enter.functions()->CreateImageData( instance, static_cast(format), size, init_to_zero); if (!resource) return; result->SetHostResource(instance, resource); // Get the description, it's just serialized as a string. ppapi::thunk::EnterResourceNoLock enter_resource(resource, false); PP_ImageDataDesc desc; if (enter_resource.object()->Describe(&desc) == PP_TRUE) { image_data_desc->resize(sizeof(PP_ImageDataDesc)); memcpy(&(*image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc)); } // Get the shared memory handle. const PPB_ImageDataTrusted* trusted = reinterpret_cast( dispatcher()->local_get_interface()(PPB_IMAGEDATA_TRUSTED_INTERFACE)); uint32_t byte_count = 0; if (trusted) { int32_t handle; if (trusted->GetSharedMemory(resource, &handle, &byte_count) == PP_OK) { #if defined(OS_WIN) ImageHandle ih = ImageData::HandleFromInt(handle); *result_image_handle = dispatcher()->ShareHandleWithRemote(ih, false); #else *result_image_handle = ImageData::HandleFromInt(handle); #endif } } } } // namespace proxy } // namespace ppapi