chromium/ppapi/native_client/src/untrusted/pnacl_irt_shim/shim_ppapi.c

/*
 * Copyright 2012 The Chromium Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "ppapi/native_client/src/untrusted/pnacl_irt_shim/shim_ppapi.h"

#include "native_client/src/untrusted/irt/irt.h"
#include "ppapi/nacl_irt/public/irt_ppapi.h"
#include "ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h"
#include "ppapi/native_client/src/untrusted/pnacl_irt_shim/irt_shim_ppapi.h"
#include "ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.h"

#define ARRAY_SIZEOF(a) (sizeof(a) / sizeof(a[0]))

/* Returns 1 if the strings s1 and s2 are equal, comparing only the first n
   bytes of s1 and s2; 0 otherwise. */
static int streq(const char *s1, const char *s2, size_t n) {
  for(; n && *s1 && *s2 && *s1 == *s2; ++s1, ++s2, --n);
  return n == 0 || *s1 == *s2;
}


TYPE_nacl_irt_query __pnacl_real_irt_query_func = NULL;

size_t __pnacl_wrap_irt_query_func(const char *interface_ident,
                                   void *table, size_t tablesize) {
  /*
   * Note there is a benign race in initializing the wrapper.
   * We build the "hook" structure by copying from the IRT's hook and then
   * writing our wrapper for the ppapi method.  Two threads may end up
   * attempting to do this simultaneously, which should not be a problem,
   * as they are writing the same values.
   */
  if (!streq(interface_ident, NACL_IRT_PPAPIHOOK_v0_1,
             ARRAY_SIZEOF(NACL_IRT_PPAPIHOOK_v0_1))) {
    /*
     * The interface is not wrapped, so use the real interface.
     */
    return (*__pnacl_real_irt_query_func)(interface_ident, table, tablesize);
  }
#ifndef PNACL_SHIM_AOT
  /*
   * For PNaCl in-the-browser, redirect to using
   * NACL_IRT_PPAPIHOOK_PNACL_PRIVATE_v0_1 instead of NACL_IRT_PPAPIHOOK_v0_1.
   */
  return (*__pnacl_real_irt_query_func)(NACL_IRT_PPAPIHOOK_PNACL_PRIVATE_v0_1,
                                        table, tablesize);
#else
  /*
   * For offline generated nexes, avoid depending on the private
   * NACL_IRT_PPAPIHOOK_PNACL_PRIVATE_v0_1 interface, and just do the
   * overriding here manually.
   */
  struct nacl_irt_ppapihook real_irt_ppapi_hook;
  if ((*__pnacl_real_irt_query_func)(NACL_IRT_PPAPIHOOK_v0_1,
                                     &real_irt_ppapi_hook,
                                     sizeof real_irt_ppapi_hook) !=
      sizeof real_irt_ppapi_hook) {
    return 0;
  }
  real_irt_ppapi_start = real_irt_ppapi_hook.ppapi_start;
  /*
   * Copy the interface structure into the client.
   */
  struct nacl_irt_ppapihook *dest = table;
  if (sizeof *dest <= tablesize) {
    dest->ppapi_start = irt_shim_ppapi_start;
    dest->ppapi_register_thread_creator =
        real_irt_ppapi_hook.ppapi_register_thread_creator;
    return sizeof *dest;
  }
  return 0;
#endif
}