| OLD | NEW |
| (Empty) |
| 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, is a modified version of hello world. It will start a second | |
| 8 * thread and cause that thread to crash via a NULL dereference. | |
| 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_core.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 #include <pthread.h> | |
| 27 | |
| 28 #include "error_handling/error_handling.h" | |
| 29 | |
| 30 PPB_Messaging* ppb_messaging_interface = NULL; | |
| 31 PPB_Var* ppb_var_interface = NULL; | |
| 32 PPB_Core* ppb_core_interface = NULL; | |
| 33 | |
| 34 pthread_t g_NexeThread; | |
| 35 pthread_t g_PPAPIThread; | |
| 36 PP_Instance g_Instance; | |
| 37 | |
| 38 volatile int g_CrashTime = 0; | |
| 39 | |
| 40 void PostMessage(const char* str); | |
| 41 | |
| 42 void layer5(int x, int y) { | |
| 43 if (g_CrashTime) { | |
| 44 *(volatile int*)x = y; | |
| 45 } | |
| 46 } | |
| 47 | |
| 48 void layer4(int x) { layer5(x, 1); } | |
| 49 | |
| 50 void layer3(int a, int b, int c) { layer4(a + b + c); } | |
| 51 | |
| 52 void layer2(int i, int j) { layer3(i, j, 7); } | |
| 53 | |
| 54 void layer1(int s, int t) { | |
| 55 int* junk = (int*)alloca(sizeof(int) * 1234); | |
| 56 junk[0] = s + 5; | |
| 57 layer2(junk[0], t + 1); | |
| 58 } | |
| 59 | |
| 60 void* NexeMain(void* data) { | |
| 61 PostMessage("Running Boom thread."); | |
| 62 while (1) { | |
| 63 layer1(2, 9); | |
| 64 } | |
| 65 return NULL; | |
| 66 } | |
| 67 | |
| 68 /** | |
| 69 * Creates new string PP_Var from C string. The resulting object will be a | |
| 70 * refcounted string object. It will be AddRef()ed for the caller. When the | |
| 71 * caller is done with it, it should be Release()d. | |
| 72 * @param[in] str C string to be converted to PP_Var | |
| 73 * @return PP_Var containing string. | |
| 74 */ | |
| 75 static struct PP_Var CStrToVar(const char* str) { | |
| 76 if (ppb_var_interface != NULL) { | |
| 77 return ppb_var_interface->VarFromUtf8(str, strlen(str)); | |
| 78 } | |
| 79 return PP_MakeUndefined(); | |
| 80 } | |
| 81 | |
| 82 static void PostCompletionCallback(void* user_data, int32_t result) { | |
| 83 const char* str = (const char*)user_data; | |
| 84 ppb_messaging_interface->PostMessage(g_Instance, CStrToVar(str)); | |
| 85 free(user_data); | |
| 86 } | |
| 87 | |
| 88 void PostMessage(const char* str) { | |
| 89 struct PP_CompletionCallback cb; | |
| 90 | |
| 91 if (NULL == str) | |
| 92 return; | |
| 93 if (NULL == ppb_messaging_interface) | |
| 94 return; | |
| 95 if (0 == g_Instance) | |
| 96 return; | |
| 97 | |
| 98 if (strncmp(str, "ERR:", 4)) { | |
| 99 fprintf(stderr, "%s\n", str); | |
| 100 fflush(stderr); | |
| 101 } else { | |
| 102 fprintf(stdout, "%s\n", str); | |
| 103 fflush(stdout); | |
| 104 } | |
| 105 | |
| 106 /* If on Main Pepper thread, then call interface directly. */ | |
| 107 if (pthread_self() == g_PPAPIThread) { | |
| 108 ppb_messaging_interface->PostMessage(g_Instance, CStrToVar(str)); | |
| 109 return; | |
| 110 } | |
| 111 | |
| 112 /* Otherwise use call on main thread. */ | |
| 113 cb = PP_MakeCompletionCallback(PostCompletionCallback, strdup(str)); | |
| 114 ppb_core_interface->CallOnMainThread(0, cb, 0); | |
| 115 } | |
| 116 | |
| 117 void DumpJson(const char* json) { | |
| 118 char* out = (char*)malloc(strlen(json) + 5); | |
| 119 strcpy(out, "TRC: "); | |
| 120 strcat(out, json); | |
| 121 | |
| 122 PostMessage(out); | |
| 123 free(out); | |
| 124 } | |
| 125 /** | |
| 126 * Called when the NaCl module is instantiated on the web page. The identifier | |
| 127 * of the new instance will be passed in as the first argument (this value is | |
| 128 * generated by the browser and is an opaque handle). This is called for each | |
| 129 * instantiation of the NaCl module, which is each time the <embed> tag for | |
| 130 * this module is encountered. | |
| 131 * | |
| 132 * If this function reports a failure (by returning @a PP_FALSE), the NaCl | |
| 133 * module will be deleted and DidDestroy will be called. | |
| 134 * @param[in] instance The identifier of the new instance representing this | |
| 135 * NaCl module. | |
| 136 * @param[in] argc The number of arguments contained in @a argn and @a argv. | |
| 137 * @param[in] argn An array of argument names. These argument names are | |
| 138 * supplied in the <embed> tag, for example: | |
| 139 * <embed id="nacl_module" dimensions="2"> | |
| 140 * will produce two arguments, one named "id" and one named "dimensions". | |
| 141 * @param[in] argv An array of argument values. These are the values of the | |
| 142 * arguments listed in the <embed> tag. In the above example, there will | |
| 143 * be two elements in this array, "nacl_module" and "2". The indices of | |
| 144 * these values match the indices of the corresponding names in @a argn. | |
| 145 * @return @a PP_TRUE on success. | |
| 146 */ | |
| 147 static PP_Bool Instance_DidCreate(PP_Instance instance, | |
| 148 uint32_t argc, | |
| 149 const char* argn[], | |
| 150 const char* argv[]) { | |
| 151 g_Instance = instance; | |
| 152 g_PPAPIThread = pthread_self(); | |
| 153 | |
| 154 PostMessage("LOG: DidCreate"); | |
| 155 | |
| 156 /* Request exception callbacks with JSON. */ | |
| 157 EHRequestExceptionsJson(DumpJson); | |
| 158 | |
| 159 /* Report back if the request was honored. */ | |
| 160 if (!EHHanderInstalled()) { | |
| 161 PostMessage("LOG: Stack traces not available, so don't expect them.\n"); | |
| 162 } else { | |
| 163 PostMessage("LOG: Stack traces are on."); | |
| 164 } | |
| 165 pthread_create(&g_NexeThread, NULL, NexeMain, NULL); | |
| 166 return PP_TRUE; | |
| 167 } | |
| 168 | |
| 169 /** | |
| 170 * Called when the NaCl module is destroyed. This will always be called, | |
| 171 * even if DidCreate returned failure. This routine should deallocate any data | |
| 172 * associated with the instance. | |
| 173 * @param[in] instance The identifier of the instance representing this NaCl | |
| 174 * module. | |
| 175 */ | |
| 176 static void Instance_DidDestroy(PP_Instance instance) {} | |
| 177 | |
| 178 /** | |
| 179 * Called when the position, the size, or the clip rect of the element in the | |
| 180 * browser that corresponds to this NaCl module has changed. | |
| 181 * @param[in] instance The identifier of the instance representing this NaCl | |
| 182 * module. | |
| 183 * @param[in] position The location on the page of this NaCl module. This is | |
| 184 * relative to the top left corner of the viewport, which changes as the | |
| 185 * page is scrolled. | |
| 186 * @param[in] clip The visible region of the NaCl module. This is relative to | |
| 187 * the top left of the plugin's coordinate system (not the page). If the | |
| 188 * plugin is invisible, @a clip will be (0, 0, 0, 0). | |
| 189 */ | |
| 190 static void Instance_DidChangeView(PP_Instance instance, | |
| 191 PP_Resource view_resource) {} | |
| 192 | |
| 193 /** | |
| 194 * Notification that the given NaCl module has gained or lost focus. | |
| 195 * Having focus means that keyboard events will be sent to the NaCl module | |
| 196 * represented by @a instance. A NaCl module's default condition is that it | |
| 197 * will not have focus. | |
| 198 * | |
| 199 * Note: clicks on NaCl modules will give focus only if you handle the | |
| 200 * click event. You signal if you handled it by returning @a true from | |
| 201 * HandleInputEvent. Otherwise the browser will bubble the event and give | |
| 202 * focus to the element on the page that actually did end up consuming it. | |
| 203 * If you're not getting focus, check to make sure you're returning true from | |
| 204 * the mouse click in HandleInputEvent. | |
| 205 * @param[in] instance The identifier of the instance representing this NaCl | |
| 206 * module. | |
| 207 * @param[in] has_focus Indicates whether this NaCl module gained or lost | |
| 208 * event focus. | |
| 209 */ | |
| 210 static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {} | |
| 211 | |
| 212 /** | |
| 213 * Handler that gets called after a full-frame module is instantiated based on | |
| 214 * registered MIME types. This function is not called on NaCl modules. This | |
| 215 * function is essentially a place-holder for the required function pointer in | |
| 216 * the PPP_Instance structure. | |
| 217 * @param[in] instance The identifier of the instance representing this NaCl | |
| 218 * module. | |
| 219 * @param[in] url_loader A PP_Resource an open PPB_URLLoader instance. | |
| 220 * @return PP_FALSE. | |
| 221 */ | |
| 222 static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance, | |
| 223 PP_Resource url_loader) { | |
| 224 /* NaCl modules do not need to handle the document load function. */ | |
| 225 return PP_FALSE; | |
| 226 } | |
| 227 | |
| 228 /** | |
| 229 * Handles message from JavaScript. | |
| 230 * | |
| 231 * Any message from JS is a request to cause the main thread to crash. | |
| 232 */ | |
| 233 static void Messaging_HandleMessage(PP_Instance instance, | |
| 234 struct PP_Var message) { | |
| 235 PostMessage("LOG: Got BOOM"); | |
| 236 g_CrashTime = 1; | |
| 237 } | |
| 238 | |
| 239 /** | |
| 240 * Entry points for the module. | |
| 241 * Initialize needed interfaces: PPB_Core, PPB_Messaging and PPB_Var. | |
| 242 * @param[in] a_module_id module ID | |
| 243 * @param[in] get_browser pointer to PPB_GetInterface | |
| 244 * @return PP_OK on success, any other value on failure. | |
| 245 */ | |
| 246 PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id, | |
| 247 PPB_GetInterface get_browser) { | |
| 248 ppb_messaging_interface = | |
| 249 (PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE)); | |
| 250 ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE)); | |
| 251 ppb_core_interface = (PPB_Core*)(get_browser(PPB_CORE_INTERFACE)); | |
| 252 return PP_OK; | |
| 253 } | |
| 254 | |
| 255 /** | |
| 256 * Returns an interface pointer for the interface of the given name, or NULL | |
| 257 * if the interface is not supported. | |
| 258 * @param[in] interface_name name of the interface | |
| 259 * @return pointer to the interface | |
| 260 */ | |
| 261 PP_EXPORT const void* PPP_GetInterface(const char* interface_name) { | |
| 262 if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) { | |
| 263 static PPP_Instance instance_interface = { | |
| 264 &Instance_DidCreate, | |
| 265 &Instance_DidDestroy, | |
| 266 &Instance_DidChangeView, | |
| 267 &Instance_DidChangeFocus, | |
| 268 &Instance_HandleDocumentLoad, | |
| 269 }; | |
| 270 return &instance_interface; | |
| 271 } | |
| 272 if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) { | |
| 273 static PPP_Messaging messaging_interface = { | |
| 274 &Messaging_HandleMessage, | |
| 275 }; | |
| 276 return &messaging_interface; | |
| 277 } | |
| 278 return NULL; | |
| 279 } | |
| 280 | |
| 281 /** | |
| 282 * Called before the plugin module is unloaded. | |
| 283 */ | |
| 284 PP_EXPORT void PPP_ShutdownModule() {} | |
| OLD | NEW |