|  | // Copyright (c) 2012 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/cpp/instance.h" | 
|  |  | 
|  | #include "ppapi/c/pp_errors.h" | 
|  | #include "ppapi/c/ppb_console.h" | 
|  | #include "ppapi/c/ppb_input_event.h" | 
|  | #include "ppapi/c/ppb_instance.h" | 
|  | #include "ppapi/c/ppb_messaging.h" | 
|  | #include "ppapi/c/ppp_message_handler.h" | 
|  | #include "ppapi/cpp/compositor.h" | 
|  | #include "ppapi/cpp/graphics_2d.h" | 
|  | #include "ppapi/cpp/graphics_3d.h" | 
|  | #include "ppapi/cpp/image_data.h" | 
|  | #include "ppapi/cpp/instance_handle.h" | 
|  | #include "ppapi/cpp/logging.h" | 
|  | #include "ppapi/cpp/message_handler.h" | 
|  | #include "ppapi/cpp/message_loop.h" | 
|  | #include "ppapi/cpp/module.h" | 
|  | #include "ppapi/cpp/module_impl.h" | 
|  | #include "ppapi/cpp/point.h" | 
|  | #include "ppapi/cpp/resource.h" | 
|  | #include "ppapi/cpp/var.h" | 
|  | #include "ppapi/cpp/view.h" | 
|  |  | 
|  | namespace pp { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | template <> const char* interface_name<PPB_Console_1_0>() { | 
|  | return PPB_CONSOLE_INTERFACE_1_0; | 
|  | } | 
|  |  | 
|  | template <> const char* interface_name<PPB_InputEvent_1_0>() { | 
|  | return PPB_INPUT_EVENT_INTERFACE_1_0; | 
|  | } | 
|  |  | 
|  | template <> const char* interface_name<PPB_Instance_1_0>() { | 
|  | return PPB_INSTANCE_INTERFACE_1_0; | 
|  | } | 
|  |  | 
|  | template <> const char* interface_name<PPB_Messaging_1_0>() { | 
|  | return PPB_MESSAGING_INTERFACE_1_0; | 
|  | } | 
|  |  | 
|  | template <> const char* interface_name<PPB_Messaging_1_2>() { | 
|  | return PPB_MESSAGING_INTERFACE_1_2; | 
|  | } | 
|  |  | 
|  | // PPP_MessageHandler implementation ------------------------------------------- | 
|  | void HandleMessage(PP_Instance pp_instance, | 
|  | void* user_data, | 
|  | const PP_Var* var) { | 
|  | MessageHandler* message_handler = static_cast<MessageHandler*>(user_data); | 
|  | message_handler->HandleMessage(InstanceHandle(pp_instance), Var(*var)); | 
|  | } | 
|  |  | 
|  | void HandleBlockingMessage(PP_Instance pp_instance, | 
|  | void* user_data, | 
|  | const PP_Var* var, | 
|  | PP_Var* result) { | 
|  | MessageHandler* message_handler = static_cast<MessageHandler*>(user_data); | 
|  | pp::Var result_var = | 
|  | message_handler->HandleBlockingMessage(InstanceHandle(pp_instance), | 
|  | Var(*var)); | 
|  | *result = result_var.Detach(); | 
|  | } | 
|  |  | 
|  | void Destroy(PP_Instance pp_instance, void* user_data) { | 
|  | MessageHandler* message_handler = static_cast<MessageHandler*>(user_data); | 
|  | message_handler->WasUnregistered(InstanceHandle(pp_instance)); | 
|  | } | 
|  |  | 
|  | static PPP_MessageHandler_0_2 message_handler_if = { | 
|  | &HandleMessage, &HandleBlockingMessage, &Destroy | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | Instance::Instance(PP_Instance instance) : pp_instance_(instance) { | 
|  | } | 
|  |  | 
|  | Instance::~Instance() { | 
|  | } | 
|  |  | 
|  | bool Instance::Init(uint32_t /*argc*/, const char* /*argn*/[], | 
|  | const char* /*argv*/[]) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void Instance::DidChangeView(const View& view) { | 
|  | // Call the deprecated version for source backwards-compat. | 
|  | DidChangeView(view.GetRect(), view.GetClipRect()); | 
|  | } | 
|  |  | 
|  | void Instance::DidChangeView(const pp::Rect& /*position*/, | 
|  | const pp::Rect& /*clip*/) { | 
|  | } | 
|  |  | 
|  | void Instance::DidChangeFocus(bool /*has_focus*/) { | 
|  | } | 
|  |  | 
|  |  | 
|  | bool Instance::HandleDocumentLoad(const URLLoader& /*url_loader*/) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool Instance::HandleInputEvent(const InputEvent& /*event*/) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | void Instance::HandleMessage(const Var& /*message*/) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | bool Instance::BindGraphics(const Graphics2D& graphics) { | 
|  | if (!has_interface<PPB_Instance_1_0>()) | 
|  | return false; | 
|  | return PP_ToBool(get_interface<PPB_Instance_1_0>()->BindGraphics( | 
|  | pp_instance(), graphics.pp_resource())); | 
|  | } | 
|  |  | 
|  | bool Instance::BindGraphics(const Graphics3D& graphics) { | 
|  | if (!has_interface<PPB_Instance_1_0>()) | 
|  | return false; | 
|  | return PP_ToBool(get_interface<PPB_Instance_1_0>()->BindGraphics( | 
|  | pp_instance(), graphics.pp_resource())); | 
|  | } | 
|  |  | 
|  | bool Instance::BindGraphics(const Compositor& compositor) { | 
|  | if (!has_interface<PPB_Instance_1_0>()) | 
|  | return false; | 
|  | return PP_ToBool(get_interface<PPB_Instance_1_0>()->BindGraphics( | 
|  | pp_instance(), compositor.pp_resource())); | 
|  | } | 
|  |  | 
|  | bool Instance::IsFullFrame() { | 
|  | if (!has_interface<PPB_Instance_1_0>()) | 
|  | return false; | 
|  | return PP_ToBool(get_interface<PPB_Instance_1_0>()->IsFullFrame( | 
|  | pp_instance())); | 
|  | } | 
|  |  | 
|  | int32_t Instance::RequestInputEvents(uint32_t event_classes) { | 
|  | if (!has_interface<PPB_InputEvent_1_0>()) | 
|  | return PP_ERROR_NOINTERFACE; | 
|  | return get_interface<PPB_InputEvent_1_0>()->RequestInputEvents(pp_instance(), | 
|  | event_classes); | 
|  | } | 
|  |  | 
|  | int32_t Instance::RequestFilteringInputEvents(uint32_t event_classes) { | 
|  | if (!has_interface<PPB_InputEvent_1_0>()) | 
|  | return PP_ERROR_NOINTERFACE; | 
|  | return get_interface<PPB_InputEvent_1_0>()->RequestFilteringInputEvents( | 
|  | pp_instance(), event_classes); | 
|  | } | 
|  |  | 
|  | void Instance::ClearInputEventRequest(uint32_t event_classes) { | 
|  | if (!has_interface<PPB_InputEvent_1_0>()) | 
|  | return; | 
|  | get_interface<PPB_InputEvent_1_0>()->ClearInputEventRequest(pp_instance(), | 
|  | event_classes); | 
|  | } | 
|  |  | 
|  | void Instance::PostMessage(const Var& message) { | 
|  | if (has_interface<PPB_Messaging_1_2>()) { | 
|  | get_interface<PPB_Messaging_1_2>()->PostMessage(pp_instance(), | 
|  | message.pp_var()); | 
|  | } else if (has_interface<PPB_Messaging_1_0>()) { | 
|  | get_interface<PPB_Messaging_1_0>()->PostMessage(pp_instance(), | 
|  | message.pp_var()); | 
|  | } | 
|  | } | 
|  |  | 
|  | int32_t Instance::RegisterMessageHandler(MessageHandler* message_handler, | 
|  | const MessageLoop& message_loop) { | 
|  | if (!has_interface<PPB_Messaging_1_2>()) | 
|  | return PP_ERROR_NOTSUPPORTED; | 
|  | return get_interface<PPB_Messaging_1_2>()->RegisterMessageHandler( | 
|  | pp_instance(), | 
|  | message_handler, | 
|  | &message_handler_if, | 
|  | message_loop.pp_resource()); | 
|  | } | 
|  |  | 
|  | void Instance::UnregisterMessageHandler() { | 
|  | if (!has_interface<PPB_Messaging_1_2>()) | 
|  | return; | 
|  | get_interface<PPB_Messaging_1_2>()->UnregisterMessageHandler(pp_instance()); | 
|  | } | 
|  |  | 
|  | void Instance::LogToConsole(PP_LogLevel level, const Var& value) { | 
|  | if (!has_interface<PPB_Console_1_0>()) | 
|  | return; | 
|  | get_interface<PPB_Console_1_0>()->Log( | 
|  | pp_instance(), level, value.pp_var()); | 
|  | } | 
|  |  | 
|  | void Instance::LogToConsoleWithSource(PP_LogLevel level, | 
|  | const Var& source, | 
|  | const Var& value) { | 
|  | if (!has_interface<PPB_Console_1_0>()) | 
|  | return; | 
|  | get_interface<PPB_Console_1_0>()->LogWithSource( | 
|  | pp_instance(), level, source.pp_var(), value.pp_var()); | 
|  | } | 
|  |  | 
|  | void Instance::AddPerInstanceObject(const std::string& interface_name, | 
|  | void* object) { | 
|  | // Ensure we're not trying to register more than one object per interface | 
|  | // type. Otherwise, we'll get confused in GetPerInstanceObject. | 
|  | PP_DCHECK(interface_name_to_objects_.find(interface_name) == | 
|  | interface_name_to_objects_.end()); | 
|  | interface_name_to_objects_[interface_name] = object; | 
|  | } | 
|  |  | 
|  | void Instance::RemovePerInstanceObject(const std::string& interface_name, | 
|  | void* object) { | 
|  | InterfaceNameToObjectMap::iterator found = interface_name_to_objects_.find( | 
|  | interface_name); | 
|  | if (found == interface_name_to_objects_.end()) { | 
|  | // Attempting to unregister an object that doesn't exist or was already | 
|  | // unregistered. | 
|  | PP_DCHECK(false); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Validate that we're removing the object we thing we are. | 
|  | PP_DCHECK(found->second == object); | 
|  | (void)object;  // Prevent warning in release mode. | 
|  |  | 
|  | interface_name_to_objects_.erase(found); | 
|  | } | 
|  |  | 
|  | // static | 
|  | void Instance::RemovePerInstanceObject(const InstanceHandle& instance, | 
|  | const std::string& interface_name, | 
|  | void* object) { | 
|  | // TODO(brettw) assert we're on the main thread. | 
|  | Instance* that = Module::Get()->InstanceForPPInstance(instance.pp_instance()); | 
|  | if (!that) | 
|  | return; | 
|  | that->RemovePerInstanceObject(interface_name, object); | 
|  | } | 
|  |  | 
|  | // static | 
|  | void* Instance::GetPerInstanceObject(PP_Instance instance, | 
|  | const std::string& interface_name) { | 
|  | Instance* that = Module::Get()->InstanceForPPInstance(instance); | 
|  | if (!that) | 
|  | return NULL; | 
|  | InterfaceNameToObjectMap::iterator found = | 
|  | that->interface_name_to_objects_.find(interface_name); | 
|  | if (found == that->interface_name_to_objects_.end()) | 
|  | return NULL; | 
|  | return found->second; | 
|  | } | 
|  |  | 
|  | }  // namespace pp |