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