| Index: ppapi/native_client/tests/nacl_browser/manifest_file/pm_manifest_file_test.cc
|
| diff --git a/ppapi/native_client/tests/nacl_browser/manifest_file/pm_manifest_file_test.cc b/ppapi/native_client/tests/nacl_browser/manifest_file/pm_manifest_file_test.cc
|
| deleted file mode 100644
|
| index bfa26dd9597d2b51f7b65f5240a0035180045232..0000000000000000000000000000000000000000
|
| --- a/ppapi/native_client/tests/nacl_browser/manifest_file/pm_manifest_file_test.cc
|
| +++ /dev/null
|
| @@ -1,669 +0,0 @@
|
| -/*
|
| - * Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| - * Use of this source code is governed by a BSD-style license that can be
|
| - * found in the LICENSE file.
|
| - */
|
| -
|
| -//
|
| -// Post-message based test for simple rpc based access to name services.
|
| -//
|
| -
|
| -#include <string>
|
| -
|
| -#include <assert.h>
|
| -#include <stdio.h>
|
| -#include <stdlib.h>
|
| -#include <inttypes.h>
|
| -#include <sys/fcntl.h>
|
| -#include <string.h>
|
| -#include <unistd.h>
|
| -#include <pthread.h>
|
| -
|
| -#include "native_client/src/include/nacl_base.h"
|
| -#include "native_client/src/public/imc_syscalls.h"
|
| -#include "native_client/src/public/name_service.h"
|
| -#include "native_client/src/shared/platform/nacl_sync.h"
|
| -#include "native_client/src/shared/platform/nacl_sync_checked.h"
|
| -#include "native_client/src/shared/platform/nacl_sync_raii.h"
|
| -#include "native_client/src/shared/srpc/nacl_srpc.h"
|
| -
|
| -// TODO(bsy): move weak_ref module to the shared directory
|
| -#include "native_client/src/trusted/weak_ref/weak_ref.h"
|
| -
|
| -#include "ppapi/cpp/instance.h"
|
| -#include "ppapi/cpp/module.h"
|
| -#include "ppapi/cpp/var.h"
|
| -
|
| -#include "ppapi/native_client/src/trusted/weak_ref/call_on_main_thread.h"
|
| -#include "ppapi/native_client/src/untrusted/nacl_ppapi_util/nacl_ppapi_util.h"
|
| -#include "ppapi/native_client/src/untrusted/nacl_ppapi_util/string_buffer.h"
|
| -
|
| -class PostStringMessageWrapper
|
| - : public nacl_ppapi::EventThreadWorkStateWrapper<nacl_ppapi::VoidResult> {
|
| - public:
|
| - PostStringMessageWrapper(nacl_ppapi::EventThreadWorkState<
|
| - nacl_ppapi::VoidResult>
|
| - *state,
|
| - const std::string &msg)
|
| - : nacl_ppapi::EventThreadWorkStateWrapper<nacl_ppapi::VoidResult>(
|
| - state),
|
| - msg_(msg) {}
|
| - ~PostStringMessageWrapper();
|
| - const std::string &msg() const { return msg_; }
|
| - private:
|
| - std::string msg_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(PostStringMessageWrapper);
|
| -};
|
| -
|
| -// ---------------------------------------------------------------------------
|
| -
|
| -class MyInstance;
|
| -
|
| -struct WorkRequest {
|
| - explicit WorkRequest(const std::string &message)
|
| - : msg(message),
|
| - next(reinterpret_cast<WorkRequest *>(NULL)) {}
|
| - std::string msg; // copied from HandleMessage
|
| - WorkRequest *next;
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(WorkRequest);
|
| -};
|
| -
|
| -// A Worker object is associated with a single worker thread and a
|
| -// plugin instance (which may be associated with multiple Worker
|
| -// objects/threads). It is created by a plugin instance (on the event
|
| -// handler thread) with a refcount of 2, with the expectation that one
|
| -// reference will be immediately handed off to its associated worker
|
| -// thread. When the plugin instance is about to be destroyed in the
|
| -// event handler thread, the event handler should invoke the
|
| -// ShouldExit member function, which automatically decrements the
|
| -// reference associated with the event handler thread (i.e., the event
|
| -// handler thread should no longer use the Worker*).
|
| -class Worker {
|
| - public:
|
| - explicit Worker(MyInstance *instance);
|
| -
|
| - // RunToCompletion should be invoked in the worker thread. It
|
| - // returns when the plugin instance went away, and will
|
| - // automatically unref the Worker object, so the worker thread
|
| - // should no longer use the Worker object pointer after invoking
|
| - // RunToCompletion().
|
| - void RunToCompletion();
|
| -
|
| - WorkRequest *Dequeue();
|
| - void Enqueue(WorkRequest *req);
|
| -
|
| - void Initialize(nacl::StringBuffer *sb);
|
| - void NameServiceDump(nacl::StringBuffer *sb);
|
| - void ManifestListTest(nacl::StringBuffer *sb);
|
| - void ManifestOpenTest(nacl::StringBuffer *sb);
|
| -
|
| - // Called on the event thread as part of the instance shutdown.
|
| - // Automatically unreferences the Worker object, so the event thread
|
| - // should stop using the Worker pointer after invoking ShouldExit.
|
| - void ShouldExit();
|
| -
|
| - void Unref(); // used only for error cleanup, e.g., when the worker
|
| - // thread did not launch.
|
| -
|
| - bool InitializeChannel(nacl::StringBuffer *sb);
|
| -
|
| - protected:
|
| - // Event thread operation(s):
|
| - //
|
| - // In order for a test method to send reply messages, it should use
|
| - // this PostStringMessage method, since (currently) the PostMessage
|
| - // interface is event thread-only and not thread-safe. Returns true
|
| - // if successful and the thread should continue to do work, false
|
| - // otherwise (anchor has been abandoned).
|
| - bool PostStringMessage(const std::string &msg);
|
| - // ... more Event thread operations here.
|
| -
|
| - private:
|
| - MyInstance *instance_; // cannot use directly from test worker thread!
|
| - nacl::WeakRefAnchor *anchor_;
|
| - // must copy out and Ref in ctor, since instance_ might go bad at any time.
|
| -
|
| - NaClMutex mu_;
|
| - NaClCondVar cv_; // queue not empty or should_exit_
|
| -
|
| - int ref_count_;
|
| - WorkRequest *queue_head_;
|
| - WorkRequest **queue_insert_;
|
| -
|
| - bool should_exit_;
|
| -
|
| - ~Worker();
|
| -
|
| - WorkRequest *Dequeue_mu();
|
| - void Enqueue_mu(WorkRequest *req);
|
| -
|
| - struct DispatchTable {
|
| - char const *op_name;
|
| - void (Worker::*mfunc)(nacl::StringBuffer *sb);
|
| - };
|
| -
|
| - bool ns_channel_initialized_;
|
| - NaClSrpcChannel ns_channel_;
|
| -
|
| - static DispatchTable const kDispatch[]; // null terminated
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(Worker);
|
| -};
|
| -
|
| -// This object represents one time the page says <embed>.
|
| -class MyInstance : public nacl_ppapi::NaClPpapiPluginInstance {
|
| - public:
|
| - explicit MyInstance(PP_Instance instance);
|
| - virtual ~MyInstance();
|
| - virtual void HandleMessage(const pp::Var& message_data);
|
| -
|
| - Worker *worker() { return worker_; }
|
| -
|
| - // used with plugin::WeakRefCompletionCallback
|
| - void PostStringMessage_EventThread(PostStringMessageWrapper *msg_wrapper,
|
| - int32_t err);
|
| - private:
|
| - Worker *worker_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MyInstance);
|
| -};
|
| -
|
| -// ---------------------------------------------------------------------------
|
| -
|
| -// success/fail
|
| -bool EnumerateNames(NaClSrpcChannel *nschan, nacl::StringBuffer *sb) {
|
| - char *buffer;
|
| - uint32_t nbytes = 4;
|
| - uint32_t in_out_nbytes;
|
| - char *new_buffer;
|
| -
|
| - buffer = reinterpret_cast<char *>(malloc(nbytes));
|
| - if (NULL == buffer) {
|
| - sb->Printf("EnumerateNames: initial malloc failed\n");
|
| - return false;
|
| - }
|
| -
|
| - for (;;) {
|
| - in_out_nbytes = nbytes;
|
| - if (NACL_SRPC_RESULT_OK != NaClSrpcInvokeBySignature(nschan,
|
| - NACL_NAME_SERVICE_LIST,
|
| - &in_out_nbytes,
|
| - buffer)) {
|
| - sb->Printf("NaClSrpcInvokeBySignature failed\n");
|
| - return false;
|
| - }
|
| - sb->Printf("EnumerateNames: in_out_nbytes %d\n", in_out_nbytes);
|
| - if (in_out_nbytes < nbytes) {
|
| - break;
|
| - }
|
| - nbytes *= 2;
|
| - new_buffer = reinterpret_cast<char *>(realloc(buffer, nbytes));
|
| - if (NULL == new_buffer) {
|
| - sb->Printf("EnumerateNames: out of memory during realloc\n");
|
| - free(buffer);
|
| - return false;
|
| - }
|
| - buffer = new_buffer;
|
| - new_buffer = NULL;
|
| - }
|
| - nbytes = in_out_nbytes;
|
| - sb->Printf("nbytes = %u\n", (size_t) nbytes);
|
| - if (nbytes == sizeof buffer) {
|
| - sb->Printf("Insufficent space for namespace enumeration\n");
|
| - return false;
|
| - }
|
| - size_t name_len;
|
| - for (char *p = buffer;
|
| - static_cast<size_t>(p - buffer) < nbytes;
|
| - p += name_len) {
|
| - name_len = strlen(p) + 1;
|
| - sb->Printf("%s\n", p);
|
| - }
|
| - free(buffer);
|
| - return true;
|
| -}
|
| -
|
| -// ---------------------------------------------------------------------------
|
| -
|
| -PostStringMessageWrapper::~PostStringMessageWrapper() {}
|
| -
|
| -// ---------------------------------------------------------------------------
|
| -
|
| -MyInstance::MyInstance(PP_Instance instance)
|
| - : nacl_ppapi::NaClPpapiPluginInstance(instance),
|
| - worker_(new Worker(this)) {
|
| -}
|
| -
|
| -MyInstance::~MyInstance() {
|
| - worker_->ShouldExit();
|
| -}
|
| -
|
| -void MyInstance::PostStringMessage_EventThread(
|
| - PostStringMessageWrapper *msg_wrapper,
|
| - int32_t err) {
|
| - PostMessage(msg_wrapper->msg());
|
| - msg_wrapper->SetResult(nacl_ppapi::g_void_result);
|
| -}
|
| -
|
| -// ---------------------------------------------------------------------------
|
| -
|
| -Worker::Worker(MyInstance *instance)
|
| - : instance_(instance),
|
| - anchor_(instance->anchor()->Ref()),
|
| - ref_count_(2), // one for the master and one for the dame...
|
| - queue_head_(NULL),
|
| - queue_insert_(&queue_head_),
|
| - should_exit_(false),
|
| - ns_channel_initialized_(false) {
|
| - NaClXMutexCtor(&mu_);
|
| - NaClXCondVarCtor(&cv_);
|
| -}
|
| -
|
| -void Worker::Unref() {
|
| - bool do_delete;
|
| - do {
|
| - nacl::MutexLocker take(&mu_);
|
| - do_delete = (--ref_count_ == 0);
|
| - } while (0);
|
| - // dropped lock before invoking dtor
|
| - if (do_delete) {
|
| - delete this;
|
| - }
|
| -}
|
| -
|
| -Worker::~Worker() {
|
| - anchor_->Unref();
|
| -
|
| - WorkRequest *req;
|
| - while ((req = Dequeue_mu()) != NULL) {
|
| - delete req;
|
| - }
|
| -
|
| - NaClMutexDtor(&mu_);
|
| - NaClCondVarDtor(&cv_);
|
| -}
|
| -
|
| -void Worker::ShouldExit() {
|
| - do {
|
| - nacl::MutexLocker take(&mu_);
|
| - should_exit_ = true;
|
| - NaClXCondVarBroadcast(&cv_);
|
| - } while (0);
|
| - Unref();
|
| -}
|
| -
|
| -WorkRequest *Worker::Dequeue_mu() {
|
| - WorkRequest *head = queue_head_;
|
| -
|
| - if (head != NULL) {
|
| - queue_head_ = head->next;
|
| - if (queue_head_ == NULL) {
|
| - queue_insert_ = &queue_head_;
|
| - }
|
| - }
|
| - return head;
|
| -}
|
| -
|
| -void Worker::Enqueue_mu(WorkRequest *req) {
|
| - req->next = NULL;
|
| - *queue_insert_ = req;
|
| - queue_insert_ = &req->next;
|
| -}
|
| -
|
| -WorkRequest *Worker::Dequeue() {
|
| - nacl::MutexLocker take(&mu_);
|
| - return Dequeue_mu();
|
| -}
|
| -
|
| -void Worker::Enqueue(WorkRequest *req) {
|
| - nacl::MutexLocker take(&mu_);
|
| - Enqueue_mu(req);
|
| - NaClXCondVarBroadcast(&cv_);
|
| -}
|
| -
|
| -Worker::DispatchTable const Worker::kDispatch[] = {
|
| - { "init", &Worker::Initialize },
|
| - { "name_dump", &Worker::NameServiceDump },
|
| - { "manifest_list", &Worker::ManifestListTest },
|
| - { "manifest_open", &Worker::ManifestOpenTest },
|
| - { reinterpret_cast<char const *>(NULL), NULL }
|
| -};
|
| -
|
| -bool Worker::PostStringMessage(const std::string &msg) {
|
| - nacl_ppapi::EventThreadWorkState<nacl_ppapi::VoidResult> state;
|
| - plugin::WeakRefCallOnMainThread(anchor_,
|
| - 0 /* mS */,
|
| - instance_,
|
| - &MyInstance::PostStringMessage_EventThread,
|
| - new PostStringMessageWrapper(&state, msg));
|
| - if (NULL == state.WaitForCompletion()) {
|
| - // anchor_ has been abandoned, so the plugin instance went away.
|
| - // we should drop our ref to the anchor, then shut down the worker
|
| - // thread.
|
| - nacl::MutexLocker take(&mu_);
|
| - should_exit_ = true;
|
| - // There's no need to condvar broadcast, since it is the worker
|
| - // thread that will look at the work queue and the should_exit_ to
|
| - // act on this. Unfortunately every worker thread must test the
|
| - // return value of PostStringMessage to determine if it should do
|
| - // early exit (if the worker needs to do multiple event-thread
|
| - // operations).
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void Worker::RunToCompletion() {
|
| - for (;;) {
|
| - WorkRequest *req;
|
| - do {
|
| - nacl::MutexLocker take(&mu_);
|
| - for (;;) {
|
| - if (should_exit_) {
|
| - // drop the lock and drop the reference count to this
|
| - goto break_x3;
|
| - }
|
| - fprintf(stderr, "RunToCompletion: Dequeuing...\n");
|
| - if ((req = Dequeue_mu()) != NULL) {
|
| - fprintf(stderr, "RunToCompletion: found work %p\n",
|
| - reinterpret_cast<void *>(req));
|
| - break;
|
| - }
|
| - fprintf(stderr, "RunToCompletion: waiting\n");
|
| - NaClXCondVarWait(&cv_, &mu_);
|
| - fprintf(stderr, "RunToCompletion: woke up\n");
|
| - }
|
| - } while (0);
|
| -
|
| - // Do the work, without holding the lock. The work function
|
| - // should reacquire mu_ as needed.
|
| -
|
| - nacl::StringBuffer sb;
|
| -
|
| - // scan dispatch table for op_name
|
| - fprintf(stderr, "RunToCompletion: scanning for %s\n", req->msg.c_str());
|
| - for (size_t ix = 0; kDispatch[ix].op_name != NULL; ++ix) {
|
| - fprintf(stderr,
|
| - "RunToCompletion: comparing against %s\n", kDispatch[ix].op_name);
|
| - if (req->msg == kDispatch[ix].op_name) {
|
| - if (InitializeChannel(&sb)) {
|
| - fprintf(stderr, "RunToCompletion: invoking table entry %u\n", ix);
|
| - (this->*(kDispatch[ix].mfunc))(&sb);
|
| - }
|
| - break;
|
| - }
|
| - }
|
| - // always post a reply, even if it is the empty string
|
| - fprintf(stderr,
|
| - "RunToCompletion: posting reply %s\n", sb.ToString().c_str());
|
| - if (!PostStringMessage(sb.ToString())) {
|
| - break;
|
| - }
|
| - }
|
| - break_x3:
|
| - fprintf(stderr, "RunToCompletion: exiting\n");
|
| - Unref();
|
| -}
|
| -
|
| -bool Worker::InitializeChannel(nacl::StringBuffer *sb) {
|
| - if (ns_channel_initialized_) {
|
| - return true;
|
| - }
|
| - int ns = -1;
|
| - nacl_nameservice(&ns);
|
| - printf("ns = %d\n", ns);
|
| - assert(-1 != ns);
|
| - int connected_socket = imc_connect(ns);
|
| - assert(-1 != connected_socket);
|
| - if (!NaClSrpcClientCtor(&ns_channel_, connected_socket)) {
|
| - sb->Printf("Srpc client channel ctor failed\n");
|
| - close(ns);
|
| - return false;
|
| - }
|
| - sb->Printf("NaClSrpcClientCtor succeeded\n");
|
| - close(ns);
|
| - ns_channel_initialized_ = true;
|
| - return true;
|
| -}
|
| -
|
| -void Worker::Initialize(nacl::StringBuffer *sb) {
|
| - // we just want the log output from the InitializeChannel
|
| - return;
|
| -}
|
| -
|
| -// return name service output in sb
|
| -void Worker::NameServiceDump(nacl::StringBuffer *sb) {
|
| - (void) EnumerateNames(&ns_channel_, sb);
|
| -}
|
| -
|
| -void Worker::ManifestListTest(nacl::StringBuffer *sb) {
|
| - int status;
|
| - int manifest;
|
| - // name service lookup for the manifest service descriptor
|
| - if (NACL_SRPC_RESULT_OK !=
|
| - NaClSrpcInvokeBySignature(&ns_channel_, NACL_NAME_SERVICE_LOOKUP,
|
| - "ManifestNameService", O_RDWR,
|
| - &status, &manifest) ||
|
| - NACL_NAME_SERVICE_SUCCESS != status) {
|
| - sb->Printf("nameservice lookup failed, status %d\n", status);
|
| - }
|
| - sb->Printf("Got manifest descriptor %d\n", manifest);
|
| - if (-1 == manifest) {
|
| - return;
|
| - }
|
| -
|
| - // connect to manifest name server
|
| - int manifest_conn = imc_connect(manifest);
|
| - close(manifest);
|
| - sb->Printf("got manifest connection %d\n", manifest_conn);
|
| - if (-1 == manifest_conn) {
|
| - sb->Printf("could not connect\n");
|
| - return;
|
| - }
|
| -
|
| - // build the SRPC connection (do service discovery)
|
| - struct NaClSrpcChannel manifest_channel;
|
| - if (!NaClSrpcClientCtor(&manifest_channel, manifest_conn)) {
|
| - sb->Printf("could not build srpc client\n");
|
| - return;
|
| - }
|
| - sb->Printf("ManifestListTest: basic connectivity ok\n");
|
| -
|
| - // list manifest service contents
|
| - char buffer[1024];
|
| - uint32_t nbytes = sizeof buffer;
|
| -
|
| - if (NACL_SRPC_RESULT_OK !=
|
| - NaClSrpcInvokeBySignature(&manifest_channel, NACL_NAME_SERVICE_LIST,
|
| - &nbytes, buffer)) {
|
| - sb->Printf("manifest list RPC failed\n");
|
| - NaClSrpcDtor(&manifest_channel);
|
| - return;
|
| - }
|
| -
|
| - sb->DiscardOutput();
|
| - sb->Printf("Manifest Contents:\n");
|
| - size_t name_len;
|
| - // Should we explicitly sort the names? This would ensure that the
|
| - // test output is easy to compare with expected results. Currently,
|
| - // the manifest uses a set to hold the names, so the results will be
|
| - // sorted anyway, but this is not a guarantee of the API.
|
| - for (char *p = buffer;
|
| - static_cast<size_t>(p - buffer) < nbytes;
|
| - p += name_len + 1) {
|
| - name_len = strlen(p);
|
| - sb->Printf("%.*s\n", (int) name_len, p);
|
| - }
|
| - NaClSrpcDtor(&manifest_channel);
|
| - return;
|
| -}
|
| -
|
| -void Worker::ManifestOpenTest(nacl::StringBuffer *sb) {
|
| - int status = -1;
|
| - int manifest;
|
| - struct NaClSrpcChannel manifest_channel;
|
| -
|
| - // name service lookup for the manifest service descriptor
|
| - if (NACL_SRPC_RESULT_OK !=
|
| - NaClSrpcInvokeBySignature(&ns_channel_, NACL_NAME_SERVICE_LOOKUP,
|
| - "ManifestNameService", O_RDWR,
|
| - &status, &manifest) ||
|
| - NACL_NAME_SERVICE_SUCCESS != status) {
|
| - sb->Printf("nameservice lookup failed, status %d\n", status);
|
| - return;
|
| - }
|
| - sb->Printf("Got manifest descriptor %d\n", manifest);
|
| - if (-1 == manifest) {
|
| - return;
|
| - }
|
| -
|
| - // connect to manifest name server
|
| - int manifest_conn = imc_connect(manifest);
|
| - close(manifest);
|
| - sb->Printf("got manifest connection %d\n", manifest_conn);
|
| - if (-1 == manifest_conn) {
|
| - sb->Printf("could not connect\n");
|
| - return;
|
| - }
|
| -
|
| - // build the SRPC connection (do service discovery)
|
| - if (!NaClSrpcClientCtor(&manifest_channel, manifest_conn)) {
|
| - sb->Printf("could not build srpc client\n");
|
| - return;
|
| - }
|
| -
|
| - int desc;
|
| -
|
| - sb->Printf("Invoking name service lookup\n");
|
| - if (NACL_SRPC_RESULT_OK !=
|
| - NaClSrpcInvokeBySignature(&manifest_channel,
|
| - NACL_NAME_SERVICE_LOOKUP,
|
| - "files/test_file", O_RDONLY,
|
| - &status, &desc)) {
|
| - sb->Printf("manifest lookup RPC failed\n");
|
| - NaClSrpcDtor(&manifest_channel);
|
| - return;
|
| - }
|
| -
|
| - sb->DiscardOutput();
|
| - sb->Printf("File Contents:\n");
|
| -
|
| - FILE *iob = fdopen(desc, "r");
|
| - char buffer[4096];
|
| - while (fgets(buffer, sizeof buffer, iob) != NULL) {
|
| - // NB: fgets does not discard the newline nor any carriage return
|
| - // character before that.
|
| - //
|
| - // Note that CR LF is the default end-of-line style for Windows.
|
| - // Furthermore, when the test_file (input data, which happens to
|
| - // be the nmf file) is initially created in a change list, the
|
| - // patch is sent to our try bots as text. This means that when
|
| - // the file arrives, it has CR LF endings instead of the original
|
| - // LF line endings. Since the expected or golden data is
|
| - // (manually) encoded in the HTML file's JavaScript, there will be
|
| - // a mismatch. After submission, the svn property svn:eol-style
|
| - // will be set to LF, so a clean check out should have LF and not
|
| - // CR LF endings, and the tests will pass without CR removal.
|
| - // However -- and there's always a however in long discourses --
|
| - // if the nmf file is edited, say, because the test is being
|
| - // modified, and the modification is being done on a Windows
|
| - // machine, then it is likely that the editor used by the
|
| - // programmer will convert the file to CR LF endings. Which,
|
| - // unfortunatly, implies that the test will mysteriously fail
|
| - // again.
|
| - //
|
| - // To defend against such nonsense, we weaken the test slighty,
|
| - // and just strip the CR if it is present.
|
| - int len = strlen(buffer);
|
| - if (len >= 2 && buffer[len-1] == '\n' && buffer[len-2] == '\r') {
|
| - buffer[len-2] = '\n';
|
| - buffer[len-1] = '\0';
|
| - }
|
| - sb->Printf("%s", buffer);
|
| - }
|
| - fclose(iob); // closed desc
|
| - NaClSrpcDtor(&manifest_channel);
|
| - return;
|
| -}
|
| -
|
| -// HandleMessage gets invoked when postMessage is called on the DOM
|
| -// element associated with this plugin instance. In this case, if we
|
| -// are given a string, we'll post a message back to JavaScript with a
|
| -// reply -- essentially treating this as a string-based RPC.
|
| -void MyInstance::HandleMessage(const pp::Var& message) {
|
| - if (message.is_string()) {
|
| - fprintf(stderr,
|
| - "HandleMessage: enqueuing %s\n", message.AsString().c_str());
|
| - fflush(NULL);
|
| - worker_->Enqueue(new WorkRequest(message.AsString()));
|
| - } else {
|
| - fprintf(stderr, "HandleMessage: message is not a string\n");
|
| - fflush(NULL);
|
| - }
|
| -}
|
| -
|
| -void *worker_thread_start(void *arg) {
|
| - Worker *worker = reinterpret_cast<Worker *>(arg);
|
| -
|
| - fprintf(stderr, "Sleeping...\n"); fflush(stderr);
|
| - sleep(1);
|
| - fprintf(stderr, "worker_thread_start: worker %p\n",
|
| - reinterpret_cast<void *>(worker));
|
| - fflush(NULL);
|
| - worker->RunToCompletion();
|
| - worker = NULL; // RunToCompletion automatically Unrefs
|
| - return reinterpret_cast<void *>(NULL);
|
| -}
|
| -
|
| -// This object is the global object representing this plugin library as long
|
| -// as it is loaded.
|
| -class MyModule : public pp::Module {
|
| - public:
|
| - MyModule() : pp::Module() {}
|
| - virtual ~MyModule() {}
|
| -
|
| - // Override CreateInstance to create your customized Instance object.
|
| - virtual pp::Instance *CreateInstance(PP_Instance instance);
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MyModule);
|
| -};
|
| -
|
| -pp::Instance *MyModule::CreateInstance(PP_Instance pp_instance) {
|
| - MyInstance *instance = new MyInstance(pp_instance);
|
| - // spawn worker thread associated with this instance
|
| - pthread_t thread;
|
| -
|
| - fprintf(stderr, "CreateInstance invoked\n"); fflush(NULL);
|
| - if (0 != pthread_create(&thread,
|
| - reinterpret_cast<pthread_attr_t *>(NULL),
|
| - worker_thread_start,
|
| - reinterpret_cast<void *>(instance->worker()))) {
|
| - // Remove the reference the ownership of which should have been
|
| - // passed to the worker thread.
|
| - instance->worker()->Unref();
|
| - delete instance;
|
| - instance = NULL;
|
| - fprintf(stderr, "pthread_create failed\n"); fflush(NULL);
|
| - } else {
|
| - fprintf(stderr, "CreateInstance: Worker thread started\n");
|
| - fprintf(stderr, "CreateInstance: worker thread object %p\n",
|
| - reinterpret_cast<void *>(instance->worker()));
|
| - (void) pthread_detach(thread);
|
| - }
|
| - fprintf(stderr, "CreateInstance: returning instance %p\n",
|
| - reinterpret_cast<void *>(instance));
|
| -
|
| - return instance;
|
| -}
|
| -
|
| -namespace pp {
|
| -
|
| -// Factory function for your specialization of the Module object.
|
| -Module* CreateModule() {
|
| - fprintf(stderr, "CreateModule invoked\n"); fflush(NULL);
|
| - return new MyModule();
|
| -}
|
| -
|
| -} // namespace pp
|
|
|