1 /* 2 * Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 * Use of this source code is governed by a BSD-style license that can be 4 * found in the LICENSE file. 5 */ 6 7 #include "native_client/tests/inbrowser_test_runner/test_runner.h" 8 9 #include <stdio.h> 10 #include <string.h> 11 12 #include "ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h" 13 14 #include "ppapi/c/pp_bool.h" 15 #include "ppapi/c/pp_errors.h" 16 #include "ppapi/c/pp_var.h" 17 #include "ppapi/c/ppb_messaging.h" 18 #include "ppapi/c/ppb_var.h" 19 #include "ppapi/c/ppp.h" 20 #include "ppapi/c/ppp_instance.h" 21 #include "ppapi/c/ppp_messaging.h" 22 23 24 /* 25 * Remembers the callback that actually performs the tests once the browser 26 * has posted a message to run the test. 27 */ 28 static int (*g_test_func)(void); 29 30 /* 31 * Browser interfaces invoked by the plugin. 32 */ 33 static PPB_GetInterface g_get_browser_interface; 34 const static PPB_Messaging *g_browser_messaging; 35 const static PPB_Var *g_browser_var; 36 37 38 /*************************************************************************** 39 * The entry point invoked by tests using this library. 40 **************************************************************************/ 41 int RunTests(int (*test_func)(void)) { 42 /* Turn off stdout buffering to aid debugging in case of a crash. */ 43 setvbuf(stdout, NULL, _IONBF, 0); 44 if (getenv("OUTSIDE_BROWSER") != NULL) { 45 return test_func(); 46 } else { 47 g_test_func = test_func; 48 return PpapiPluginMain(); 49 } 50 } 51 52 int TestRunningInBrowser(void) { 53 return 1; 54 } 55 56 /*************************************************************************** 57 * PPP_Instance allows the browser to create an instance of the plugin. 58 **************************************************************************/ 59 static PP_Bool PppInstanceDidCreate(PP_Instance instance, 60 uint32_t argc, 61 const char *argn[], 62 const char *argv[]) { 63 g_browser_messaging = (*g_get_browser_interface)(PPB_MESSAGING_INTERFACE); 64 g_browser_var = (*g_get_browser_interface)(PPB_VAR_INTERFACE); 65 return PP_TRUE; 66 } 67 68 static void PppInstanceDidDestroy(PP_Instance instance) { 69 /* Do nothing. */ 70 } 71 72 static void PppInstanceDidChangeView(PP_Instance instance, PP_Resource view) { 73 /* Do nothing. */ 74 } 75 76 void PppInstanceDidChangeFocus(PP_Instance instance, PP_Bool has_focus) { 77 /* Do nothing. */ 78 } 79 80 PP_Bool PppInstanceHandleDocumentLoad(PP_Instance instance, 81 PP_Resource url_loader) { 82 /* Signal document loading failed. */ 83 return PP_FALSE; 84 } 85 86 static const PPP_Instance kPppInstance = { 87 PppInstanceDidCreate, 88 PppInstanceDidDestroy, 89 PppInstanceDidChangeView, 90 PppInstanceDidChangeFocus, 91 PppInstanceHandleDocumentLoad 92 }; 93 94 /*************************************************************************** 95 * PPP_Messaging allows the browser to do postMessage to the plugin. 96 **************************************************************************/ 97 static void PppMessagingHandleMessage(PP_Instance instance, 98 struct PP_Var message) { 99 const char *data; 100 uint32_t len; 101 static const char kStartMessage[] = "run_tests"; 102 int num_fails; 103 struct PP_Var result; 104 105 /* Ensure the start message is valid. */ 106 data = g_browser_var->VarToUtf8(message, &len); 107 if (len == 0) { 108 return; 109 } 110 if (strcmp(data, kStartMessage) != 0) { 111 return; 112 } 113 /* Run the tests. */ 114 num_fails = (*g_test_func)(); 115 /* Report the results. */ 116 if (num_fails == 0) { 117 static const char kPassed[] = "passed"; 118 result = g_browser_var->VarFromUtf8(kPassed, strlen(kPassed)); 119 } else { 120 static const char kFailed[] = "failed"; 121 result = g_browser_var->VarFromUtf8(kFailed, strlen(kFailed)); 122 } 123 124 /* 125 * This is a workaround for the problem that the messages sent by 126 * the "dev://postmessage" are unsynchronized. The Javascript code 127 * looks for this message before finishing the test. 128 */ 129 fprintf(stderr, "\nEND_OF_LOG\n"); 130 131 g_browser_messaging->PostMessage(instance, result); 132 } 133 134 static const PPP_Messaging kPppMessaging = { 135 PppMessagingHandleMessage 136 }; 137 138 /*************************************************************************** 139 * The three entry points every PPAPI plugin must export. 140 **************************************************************************/ 141 int32_t PPP_InitializeModule(PP_Module module, 142 PPB_GetInterface get_browser_interface) { 143 g_get_browser_interface = get_browser_interface; 144 return PP_OK; 145 } 146 147 void PPP_ShutdownModule(void) { 148 } 149 150 const void *PPP_GetInterface(const char *interface_name) { 151 /* Export PPP_Instance and PPP_Messaging. */ 152 if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) { 153 return (const void*) &kPppInstance; 154 } 155 if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) { 156 return (const void*) &kPppMessaging; 157 } 158 return NULL; 159 } 160