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
6/** @file hello_world.c
7 * This example demonstrates loading, running and scripting a very simple
8 * NaCl module.
9 */
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14#include "ppapi/c/pp_errors.h"
15#include "ppapi/c/pp_module.h"
16#include "ppapi/c/pp_var.h"
17#include "ppapi/c/ppb.h"
18#include "ppapi/c/ppb_console.h"
19#include "ppapi/c/ppb_instance.h"
20#include "ppapi/c/ppb_messaging.h"
21#include "ppapi/c/ppb_var.h"
22#include "ppapi/c/ppp.h"
23#include "ppapi/c/ppp_instance.h"
24#include "ppapi/c/ppp_messaging.h"
25
26#if defined(__native_client__)
27#if defined(__pnacl__)
28#define TCNAME "pnacl"
29#elif defined(__GLIBC__)
30#define TCNAME "glibc"
31#else
32#define TCNAME "newlib"
33#endif
34#else
35#define TCNAME "host"
36#endif
37
38static PPB_Console* ppb_console_interface = NULL;
39static PPB_Messaging* ppb_messaging_interface = NULL;
40static PPB_Var* ppb_var_interface = NULL;
41
42/**
43 * Creates new string PP_Var from C string. The resulting object will be a
44 * refcounted string object. It will be AddRef()ed for the caller. When the
45 * caller is done with it, it should be Release()d.
46 * @param[in] str C string to be converted to PP_Var
47 * @return PP_Var containing string.
48 */
49static struct PP_Var CStrToVar(const char* str) {
50  if (ppb_var_interface != NULL) {
51    return ppb_var_interface->VarFromUtf8(str, strlen(str));
52  }
53  return PP_MakeUndefined();
54}
55
56/**
57 * Post a message back to our JavaScript
58 */
59static void SendMessage(PP_Instance instance, const char* str) {
60  if (ppb_messaging_interface) {
61    struct PP_Var var = CStrToVar(str);
62    ppb_messaging_interface->PostMessage(instance, var);
63    ppb_var_interface->Release(var);
64  }
65}
66
67/**
68 * Send a message to the JavaScript Console
69 */
70static void LogMessage(PP_Instance instance, const char* str) {
71  if (ppb_console_interface) {
72    struct PP_Var var = CStrToVar(str);
73    ppb_console_interface->Log(instance, PP_LOGLEVEL_ERROR, var);
74    ppb_var_interface->Release(var);
75  }
76}
77
78/**
79 * Called when the NaCl module is instantiated on the web page. The identifier
80 * of the new instance will be passed in as the first argument (this value is
81 * generated by the browser and is an opaque handle).  This is called for each
82 * instantiation of the NaCl module, which is each time the <embed> tag for
83 * this module is encountered.
84 *
85 * If this function reports a failure (by returning @a PP_FALSE), the NaCl
86 * module will be deleted and DidDestroy will be called.
87 * @param[in] instance The identifier of the new instance representing this
88 *     NaCl module.
89 * @param[in] argc The number of arguments contained in @a argn and @a argv.
90 * @param[in] argn An array of argument names.  These argument names are
91 *     supplied in the <embed> tag, for example:
92 *       <embed id="nacl_module" dimensions="2">
93 *     will produce two arguments, one named "id" and one named "dimensions".
94 * @param[in] argv An array of argument values.  These are the values of the
95 *     arguments listed in the <embed> tag.  In the above example, there will
96 *     be two elements in this array, "nacl_module" and "2".  The indices of
97 *     these values match the indices of the corresponding names in @a argn.
98 * @return @a PP_TRUE on success.
99 */
100static PP_Bool Instance_DidCreate(PP_Instance instance,
101                                  uint32_t argc,
102                                  const char* argn[],
103                                  const char* argv[]) {
104
105  const char* post_msg = "Hello World (" TCNAME ")!";
106  const char* console_msg = "Hello World (JavaScript Console)!";
107
108  SendMessage(instance, post_msg);
109  LogMessage(instance, console_msg);
110
111  return PP_TRUE;
112}
113
114/**
115 * Called when the NaCl module is destroyed. This will always be called,
116 * even if DidCreate returned failure. This routine should deallocate any data
117 * associated with the instance.
118 * @param[in] instance The identifier of the instance representing this NaCl
119 *     module.
120 */
121static void Instance_DidDestroy(PP_Instance instance) {}
122
123/**
124 * Called when the position, the size, or the clip rect of the element in the
125 * browser that corresponds to this NaCl module has changed.
126 * @param[in] instance The identifier of the instance representing this NaCl
127 *     module.
128 * @param[in] position The location on the page of this NaCl module. This is
129 *     relative to the top left corner of the viewport, which changes as the
130 *     page is scrolled.
131 * @param[in] clip The visible region of the NaCl module. This is relative to
132 *     the top left of the plugin's coordinate system (not the page).  If the
133 *     plugin is invisible, @a clip will be (0, 0, 0, 0).
134 */
135static void Instance_DidChangeView(PP_Instance instance,
136                                   PP_Resource view_resource) {}
137
138/**
139 * Notification that the given NaCl module has gained or lost focus.
140 * Having focus means that keyboard events will be sent to the NaCl module
141 * represented by @a instance. A NaCl module's default condition is that it
142 * will not have focus.
143 *
144 * Note: clicks on NaCl modules will give focus only if you handle the
145 * click event. You signal if you handled it by returning @a true from
146 * HandleInputEvent. Otherwise the browser will bubble the event and give
147 * focus to the element on the page that actually did end up consuming it.
148 * If you're not getting focus, check to make sure you're returning true from
149 * the mouse click in HandleInputEvent.
150 * @param[in] instance The identifier of the instance representing this NaCl
151 *     module.
152 * @param[in] has_focus Indicates whether this NaCl module gained or lost
153 *     event focus.
154 */
155static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
156
157/**
158 * Handler that gets called after a full-frame module is instantiated based on
159 * registered MIME types.  This function is not called on NaCl modules.  This
160 * function is essentially a place-holder for the required function pointer in
161 * the PPP_Instance structure.
162 * @param[in] instance The identifier of the instance representing this NaCl
163 *     module.
164 * @param[in] url_loader A PP_Resource an open PPB_URLLoader instance.
165 * @return PP_FALSE.
166 */
167static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
168                                           PP_Resource url_loader) {
169  /* NaCl modules do not need to handle the document load function. */
170  return PP_FALSE;
171}
172
173/**
174 * Entry points for the module.
175 * Initialize needed interfaces: PPB_Console, PPB_Messaging and PPB_Var.
176 * @param[in] a_module_id module ID
177 * @param[in] get_browser pointer to PPB_GetInterface
178 * @return PP_OK on success, any other value on failure.
179 */
180PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
181                                       PPB_GetInterface get_browser) {
182  ppb_console_interface = (PPB_Console*)(get_browser(PPB_CONSOLE_INTERFACE));
183  ppb_messaging_interface =
184      (PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
185  ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
186  return PP_OK;
187}
188
189/**
190 * Returns an interface pointer for the interface of the given name, or NULL
191 * if the interface is not supported.
192 * @param[in] interface_name name of the interface
193 * @return pointer to the interface
194 */
195PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
196  if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
197    static PPP_Instance instance_interface = {
198      &Instance_DidCreate,
199      &Instance_DidDestroy,
200      &Instance_DidChangeView,
201      &Instance_DidChangeFocus,
202      &Instance_HandleDocumentLoad,
203    };
204    return &instance_interface;
205  }
206  return NULL;
207}
208
209/**
210 * Called before the plugin module is unloaded.
211 */
212PP_EXPORT void PPP_ShutdownModule() {}
213