1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ppapi/cpp/instance.h"
6
7#include "ppapi/c/pp_errors.h"
8#include "ppapi/c/ppb_console.h"
9#include "ppapi/c/ppb_input_event.h"
10#include "ppapi/c/ppb_instance.h"
11#include "ppapi/c/ppb_messaging.h"
12#include "ppapi/c/ppp_message_handler.h"
13#include "ppapi/cpp/compositor.h"
14#include "ppapi/cpp/graphics_2d.h"
15#include "ppapi/cpp/graphics_3d.h"
16#include "ppapi/cpp/image_data.h"
17#include "ppapi/cpp/instance_handle.h"
18#include "ppapi/cpp/logging.h"
19#include "ppapi/cpp/message_handler.h"
20#include "ppapi/cpp/message_loop.h"
21#include "ppapi/cpp/module.h"
22#include "ppapi/cpp/module_impl.h"
23#include "ppapi/cpp/point.h"
24#include "ppapi/cpp/resource.h"
25#include "ppapi/cpp/var.h"
26#include "ppapi/cpp/view.h"
27
28namespace pp {
29
30namespace {
31
32template <> const char* interface_name<PPB_Console_1_0>() {
33  return PPB_CONSOLE_INTERFACE_1_0;
34}
35
36template <> const char* interface_name<PPB_InputEvent_1_0>() {
37  return PPB_INPUT_EVENT_INTERFACE_1_0;
38}
39
40template <> const char* interface_name<PPB_Instance_1_0>() {
41  return PPB_INSTANCE_INTERFACE_1_0;
42}
43
44template <> const char* interface_name<PPB_Messaging_1_0>() {
45  return PPB_MESSAGING_INTERFACE_1_0;
46}
47
48template <> const char* interface_name<PPB_Messaging_1_2>() {
49  return PPB_MESSAGING_INTERFACE_1_2;
50}
51
52// PPP_MessageHandler implementation -------------------------------------------
53void HandleMessage(PP_Instance pp_instance,
54                   void* user_data,
55                   const PP_Var* var) {
56  MessageHandler* message_handler = static_cast<MessageHandler*>(user_data);
57  message_handler->HandleMessage(InstanceHandle(pp_instance), Var(*var));
58}
59
60void HandleBlockingMessage(PP_Instance pp_instance,
61                           void* user_data,
62                           const PP_Var* var,
63                           PP_Var* result) {
64  MessageHandler* message_handler = static_cast<MessageHandler*>(user_data);
65  pp::Var result_var =
66      message_handler->HandleBlockingMessage(InstanceHandle(pp_instance),
67                                             Var(*var));
68  *result = result_var.Detach();
69}
70
71void Destroy(PP_Instance pp_instance, void* user_data) {
72  MessageHandler* message_handler = static_cast<MessageHandler*>(user_data);
73  message_handler->WasUnregistered(InstanceHandle(pp_instance));
74}
75
76static PPP_MessageHandler_0_2 message_handler_if = {
77  &HandleMessage, &HandleBlockingMessage, &Destroy
78};
79
80}  // namespace
81
82Instance::Instance(PP_Instance instance) : pp_instance_(instance) {
83}
84
85Instance::~Instance() {
86}
87
88bool Instance::Init(uint32_t /*argc*/, const char* /*argn*/[],
89                    const char* /*argv*/[]) {
90  return true;
91}
92
93void Instance::DidChangeView(const View& view) {
94  // Call the deprecated version for source backwards-compat.
95  DidChangeView(view.GetRect(), view.GetClipRect());
96}
97
98void Instance::DidChangeView(const pp::Rect& /*position*/,
99                             const pp::Rect& /*clip*/) {
100}
101
102void Instance::DidChangeFocus(bool /*has_focus*/) {
103}
104
105
106bool Instance::HandleDocumentLoad(const URLLoader& /*url_loader*/) {
107  return false;
108}
109
110bool Instance::HandleInputEvent(const InputEvent& /*event*/) {
111  return false;
112}
113
114void Instance::HandleMessage(const Var& /*message*/) {
115  return;
116}
117
118bool Instance::BindGraphics(const Graphics2D& graphics) {
119  if (!has_interface<PPB_Instance_1_0>())
120    return false;
121  return PP_ToBool(get_interface<PPB_Instance_1_0>()->BindGraphics(
122      pp_instance(), graphics.pp_resource()));
123}
124
125bool Instance::BindGraphics(const Graphics3D& graphics) {
126  if (!has_interface<PPB_Instance_1_0>())
127    return false;
128  return PP_ToBool(get_interface<PPB_Instance_1_0>()->BindGraphics(
129      pp_instance(), graphics.pp_resource()));
130}
131
132bool Instance::BindGraphics(const Compositor& compositor) {
133  if (!has_interface<PPB_Instance_1_0>())
134    return false;
135  return PP_ToBool(get_interface<PPB_Instance_1_0>()->BindGraphics(
136      pp_instance(), compositor.pp_resource()));
137}
138
139bool Instance::IsFullFrame() {
140  if (!has_interface<PPB_Instance_1_0>())
141    return false;
142  return PP_ToBool(get_interface<PPB_Instance_1_0>()->IsFullFrame(
143      pp_instance()));
144}
145
146int32_t Instance::RequestInputEvents(uint32_t event_classes) {
147  if (!has_interface<PPB_InputEvent_1_0>())
148    return PP_ERROR_NOINTERFACE;
149  return get_interface<PPB_InputEvent_1_0>()->RequestInputEvents(pp_instance(),
150                                                                 event_classes);
151}
152
153int32_t Instance::RequestFilteringInputEvents(uint32_t event_classes) {
154  if (!has_interface<PPB_InputEvent_1_0>())
155    return PP_ERROR_NOINTERFACE;
156  return get_interface<PPB_InputEvent_1_0>()->RequestFilteringInputEvents(
157      pp_instance(), event_classes);
158}
159
160void Instance::ClearInputEventRequest(uint32_t event_classes) {
161  if (!has_interface<PPB_InputEvent_1_0>())
162    return;
163  get_interface<PPB_InputEvent_1_0>()->ClearInputEventRequest(pp_instance(),
164                                                          event_classes);
165}
166
167void Instance::PostMessage(const Var& message) {
168  if (has_interface<PPB_Messaging_1_2>()) {
169    get_interface<PPB_Messaging_1_2>()->PostMessage(pp_instance(),
170                                                    message.pp_var());
171  } else if (has_interface<PPB_Messaging_1_0>()) {
172    get_interface<PPB_Messaging_1_0>()->PostMessage(pp_instance(),
173                                                    message.pp_var());
174  }
175}
176
177int32_t Instance::RegisterMessageHandler(MessageHandler* message_handler,
178                                         const MessageLoop& message_loop) {
179  if (!has_interface<PPB_Messaging_1_2>())
180    return PP_ERROR_NOTSUPPORTED;
181  return get_interface<PPB_Messaging_1_2>()->RegisterMessageHandler(
182      pp_instance(),
183      message_handler,
184      &message_handler_if,
185      message_loop.pp_resource());
186}
187
188void Instance::UnregisterMessageHandler() {
189  if (!has_interface<PPB_Messaging_1_2>())
190    return;
191  get_interface<PPB_Messaging_1_2>()->UnregisterMessageHandler(pp_instance());
192}
193
194void Instance::LogToConsole(PP_LogLevel level, const Var& value) {
195  if (!has_interface<PPB_Console_1_0>())
196    return;
197  get_interface<PPB_Console_1_0>()->Log(
198      pp_instance(), level, value.pp_var());
199}
200
201void Instance::LogToConsoleWithSource(PP_LogLevel level,
202                                      const Var& source,
203                                      const Var& value) {
204  if (!has_interface<PPB_Console_1_0>())
205    return;
206  get_interface<PPB_Console_1_0>()->LogWithSource(
207      pp_instance(), level, source.pp_var(), value.pp_var());
208}
209
210void Instance::AddPerInstanceObject(const std::string& interface_name,
211                                    void* object) {
212  // Ensure we're not trying to register more than one object per interface
213  // type. Otherwise, we'll get confused in GetPerInstanceObject.
214  PP_DCHECK(interface_name_to_objects_.find(interface_name) ==
215            interface_name_to_objects_.end());
216  interface_name_to_objects_[interface_name] = object;
217}
218
219void Instance::RemovePerInstanceObject(const std::string& interface_name,
220                                       void* object) {
221  InterfaceNameToObjectMap::iterator found = interface_name_to_objects_.find(
222      interface_name);
223  if (found == interface_name_to_objects_.end()) {
224    // Attempting to unregister an object that doesn't exist or was already
225    // unregistered.
226    PP_DCHECK(false);
227    return;
228  }
229
230  // Validate that we're removing the object we thing we are.
231  PP_DCHECK(found->second == object);
232  (void)object;  // Prevent warning in release mode.
233
234  interface_name_to_objects_.erase(found);
235}
236
237// static
238void Instance::RemovePerInstanceObject(const InstanceHandle& instance,
239                                       const std::string& interface_name,
240                                       void* object) {
241  // TODO(brettw) assert we're on the main thread.
242  Instance* that = Module::Get()->InstanceForPPInstance(instance.pp_instance());
243  if (!that)
244    return;
245  that->RemovePerInstanceObject(interface_name, object);
246}
247
248// static
249void* Instance::GetPerInstanceObject(PP_Instance instance,
250                                     const std::string& interface_name) {
251  Instance* that = Module::Get()->InstanceForPPInstance(instance);
252  if (!that)
253    return NULL;
254  InterfaceNameToObjectMap::iterator found =
255      that->interface_name_to_objects_.find(interface_name);
256  if (found == that->interface_name_to_objects_.end())
257    return NULL;
258  return found->second;
259}
260
261}  // namespace pp
262