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 */
28static int (*g_test_func)(void);
29
30/*
31 * Browser interfaces invoked by the plugin.
32 */
33static PPB_GetInterface g_get_browser_interface;
34const static PPB_Messaging *g_browser_messaging;
35const static PPB_Var *g_browser_var;
36
37
38/***************************************************************************
39 * The entry point invoked by tests using this library.
40 **************************************************************************/
41int 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
52int TestRunningInBrowser(void) {
53  return 1;
54}
55
56/***************************************************************************
57 * PPP_Instance allows the browser to create an instance of the plugin.
58 **************************************************************************/
59static 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
68static void PppInstanceDidDestroy(PP_Instance instance) {
69  /* Do nothing. */
70}
71
72static void PppInstanceDidChangeView(PP_Instance instance, PP_Resource view) {
73  /* Do nothing. */
74}
75
76void PppInstanceDidChangeFocus(PP_Instance instance, PP_Bool has_focus) {
77  /* Do nothing. */
78}
79
80PP_Bool PppInstanceHandleDocumentLoad(PP_Instance instance,
81                                      PP_Resource url_loader) {
82  /* Signal document loading failed. */
83  return PP_FALSE;
84}
85
86static 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 **************************************************************************/
97static 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  g_browser_messaging->PostMessage(instance, result);
125}
126
127static const PPP_Messaging kPppMessaging = {
128  PppMessagingHandleMessage
129};
130
131/***************************************************************************
132 * The three entry points every PPAPI plugin must export.
133 **************************************************************************/
134int32_t PPP_InitializeModule(PP_Module module,
135                             PPB_GetInterface get_browser_interface) {
136  g_get_browser_interface = get_browser_interface;
137  return PP_OK;
138}
139
140void PPP_ShutdownModule(void) {
141}
142
143const void *PPP_GetInterface(const char *interface_name) {
144  /* Export PPP_Instance and PPP_Messaging. */
145  if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
146    return (const void*) &kPppInstance;
147  }
148  if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) {
149    return (const void*) &kPppMessaging;
150  }
151  return NULL;
152}
153