| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ppapi/proxy/ppb_testing_proxy.h" |
| |
| #include <stddef.h> |
| |
| #include "base/run_loop.h" |
| #include "ppapi/c/private/ppb_testing_private.h" |
| #include "ppapi/proxy/enter_proxy.h" |
| #include "ppapi/proxy/plugin_dispatcher.h" |
| #include "ppapi/proxy/ppapi_messages.h" |
| #include "ppapi/shared_impl/ppapi_globals.h" |
| #include "ppapi/shared_impl/proxy_lock.h" |
| #include "ppapi/shared_impl/resource.h" |
| #include "ppapi/shared_impl/resource_tracker.h" |
| #include "ppapi/thunk/enter.h" |
| #include "ppapi/thunk/ppb_graphics_2d_api.h" |
| #include "ppapi/thunk/ppb_input_event_api.h" |
| |
| using ppapi::thunk::EnterInstance; |
| using ppapi::thunk::EnterResource; |
| using ppapi::thunk::EnterResourceNoLock; |
| using ppapi::thunk::PPB_Graphics2D_API; |
| using ppapi::thunk::PPB_InputEvent_API; |
| |
| namespace ppapi { |
| namespace proxy { |
| |
| namespace { |
| |
| PP_Bool ReadImageData(PP_Resource graphics_2d, |
| PP_Resource image, |
| const PP_Point* top_left) { |
| ProxyAutoLock lock; |
| Resource* image_object = |
| PpapiGlobals::Get()->GetResourceTracker()->GetResource(image); |
| if (!image_object) |
| return PP_FALSE; |
| Resource* graphics_2d_object = |
| PpapiGlobals::Get()->GetResourceTracker()->GetResource(graphics_2d); |
| if (!graphics_2d_object || |
| image_object->pp_instance() != graphics_2d_object->pp_instance()) |
| return PP_FALSE; |
| |
| EnterResourceNoLock<PPB_Graphics2D_API> enter(graphics_2d, true); |
| if (enter.failed()) |
| return PP_FALSE; |
| const HostResource& host_image = image_object->host_resource(); |
| return enter.object()->ReadImageData(host_image.host_resource(), top_left) ? |
| PP_TRUE : PP_FALSE; |
| } |
| |
| void RunMessageLoop(PP_Instance instance) { |
| CHECK(PpapiGlobals::Get()->GetMainThreadMessageLoop()-> |
| BelongsToCurrentThread()); |
| base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).Run(); |
| } |
| |
| void QuitMessageLoop(PP_Instance instance) { |
| CHECK(PpapiGlobals::Get()->GetMainThreadMessageLoop()-> |
| BelongsToCurrentThread()); |
| base::RunLoop::QuitCurrentDeprecated(); |
| } |
| |
| uint32_t GetLiveObjectsForInstance(PP_Instance instance_id) { |
| ProxyAutoLock lock; |
| PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id); |
| if (!dispatcher) |
| return static_cast<uint32_t>(-1); |
| |
| uint32_t result = 0; |
| dispatcher->Send(new PpapiHostMsg_PPBTesting_GetLiveObjectsForInstance( |
| API_ID_PPB_TESTING, instance_id, &result)); |
| return result; |
| } |
| |
| PP_Bool IsOutOfProcess() { |
| return PP_TRUE; |
| } |
| |
| void SimulateInputEvent(PP_Instance instance_id, PP_Resource input_event) { |
| ProxyAutoLock lock; |
| PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id); |
| if (!dispatcher) |
| return; |
| EnterResourceNoLock<PPB_InputEvent_API> enter(input_event, false); |
| if (enter.failed()) |
| return; |
| |
| const InputEventData& input_event_data = enter.object()->GetInputEventData(); |
| dispatcher->Send(new PpapiHostMsg_PPBTesting_SimulateInputEvent( |
| API_ID_PPB_TESTING, instance_id, input_event_data)); |
| } |
| |
| PP_Var GetDocumentURL(PP_Instance instance, PP_URLComponents_Dev* components) { |
| EnterInstance enter(instance); |
| if (enter.failed()) |
| return PP_MakeUndefined(); |
| return enter.functions()->GetDocumentURL(instance, components); |
| } |
| |
| // TODO(dmichael): Ideally we could get a way to check the number of vars in the |
| // host-side tracker when running out-of-process, to make sure the proxy does |
| // not leak host-side vars. |
| uint32_t GetLiveVars(PP_Var live_vars[], uint32_t array_size) { |
| ProxyAutoLock lock; |
| std::vector<PP_Var> vars = |
| PpapiGlobals::Get()->GetVarTracker()->GetLiveVars(); |
| for (size_t i = 0u; |
| i < std::min(static_cast<size_t>(array_size), vars.size()); |
| ++i) |
| live_vars[i] = vars[i]; |
| return static_cast<uint32_t>(vars.size()); |
| } |
| |
| void SetMinimumArrayBufferSizeForShmem(PP_Instance instance, |
| uint32_t threshold) { |
| ProxyAutoLock lock; |
| RawVarDataGraph::SetMinimumArrayBufferSizeForShmemForTest(threshold); |
| PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); |
| if (!dispatcher) |
| return; |
| dispatcher->Send( |
| new PpapiHostMsg_PPBTesting_SetMinimumArrayBufferSizeForShmem( |
| API_ID_PPB_TESTING, threshold)); |
| } |
| |
| void RunV8GC(PP_Instance instance) { |
| // TODO(raymes): Implement this if we need it. |
| NOTIMPLEMENTED(); |
| } |
| |
| const PPB_Testing_Private testing_interface = { |
| &ReadImageData, |
| &RunMessageLoop, |
| &QuitMessageLoop, |
| &GetLiveObjectsForInstance, |
| &IsOutOfProcess, |
| &SimulateInputEvent, |
| &GetDocumentURL, |
| &GetLiveVars, |
| &SetMinimumArrayBufferSizeForShmem, |
| &RunV8GC}; |
| |
| } // namespace |
| |
| PPB_Testing_Proxy::PPB_Testing_Proxy(Dispatcher* dispatcher) |
| : InterfaceProxy(dispatcher), |
| ppb_testing_impl_(NULL) { |
| if (!dispatcher->IsPlugin()) { |
| ppb_testing_impl_ = static_cast<const PPB_Testing_Private*>( |
| dispatcher->local_get_interface()(PPB_TESTING_PRIVATE_INTERFACE)); |
| } |
| } |
| |
| PPB_Testing_Proxy::~PPB_Testing_Proxy() { |
| } |
| |
| // static |
| const PPB_Testing_Private* PPB_Testing_Proxy::GetProxyInterface() { |
| return &testing_interface; |
| } |
| |
| bool PPB_Testing_Proxy::OnMessageReceived(const IPC::Message& msg) { |
| if (!dispatcher()->permissions().HasPermission(PERMISSION_TESTING)) |
| return false; |
| |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(PPB_Testing_Proxy, msg) |
| IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_ReadImageData, |
| OnMsgReadImageData) |
| IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_GetLiveObjectsForInstance, |
| OnMsgGetLiveObjectsForInstance) |
| IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_SimulateInputEvent, |
| OnMsgSimulateInputEvent) |
| IPC_MESSAGE_HANDLER( |
| PpapiHostMsg_PPBTesting_SetMinimumArrayBufferSizeForShmem, |
| OnMsgSetMinimumArrayBufferSizeForShmem) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| return handled; |
| } |
| |
| void PPB_Testing_Proxy::OnMsgReadImageData( |
| const HostResource& device_context_2d, |
| const HostResource& image, |
| const PP_Point& top_left, |
| PP_Bool* result) { |
| *result = ppb_testing_impl_->ReadImageData( |
| device_context_2d.host_resource(), image.host_resource(), &top_left); |
| } |
| |
| void PPB_Testing_Proxy::OnMsgRunMessageLoop(PP_Instance instance) { |
| ppb_testing_impl_->RunMessageLoop(instance); |
| } |
| |
| void PPB_Testing_Proxy::OnMsgQuitMessageLoop(PP_Instance instance) { |
| ppb_testing_impl_->QuitMessageLoop(instance); |
| } |
| |
| void PPB_Testing_Proxy::OnMsgGetLiveObjectsForInstance(PP_Instance instance, |
| uint32_t* result) { |
| *result = ppb_testing_impl_->GetLiveObjectsForInstance(instance); |
| } |
| |
| void PPB_Testing_Proxy::OnMsgSimulateInputEvent( |
| PP_Instance instance, |
| const InputEventData& input_event) { |
| scoped_refptr<PPB_InputEvent_Shared> input_event_impl( |
| new PPB_InputEvent_Shared(OBJECT_IS_PROXY, instance, input_event)); |
| ppb_testing_impl_->SimulateInputEvent(instance, |
| input_event_impl->pp_resource()); |
| } |
| |
| void PPB_Testing_Proxy::OnMsgSetMinimumArrayBufferSizeForShmem( |
| uint32_t threshold) { |
| RawVarDataGraph::SetMinimumArrayBufferSizeForShmemForTest(threshold); |
| } |
| |
| } // namespace proxy |
| } // namespace ppapi |