Home | History | Annotate | Download | only in proxy
      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 #ifndef PPAPI_PROXY_PROXY_ARRAY_OUTPUT_H_
      6 #define PPAPI_PROXY_PROXY_ARRAY_OUTPUT_H_
      7 
      8 #include <vector>
      9 
     10 #include "base/logging.h"
     11 #include "base/memory/ref_counted.h"
     12 #include "ppapi/c/pp_array_output.h"
     13 
     14 // Like ppapi/cpp/array_output.h file in the C++ wrappers but for use in the
     15 // proxy where we can't link to the C++ wrappers. This also adds a refcounted
     16 // version.
     17 //
     18 // Use ArrayOutputAdapter when calling a function that synchronously returns
     19 // an array of data. Use RefCountedArrayOutputAdapterWithStorage for
     20 // asynchronous returns:
     21 //
     22 // void OnCallbackComplete(
     23 //     int32_t result,
     24 //     scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> > output) {
     25 //   // Vector is in output->output().
     26 // }
     27 //
     28 // void ScheduleCallback() {
     29 //   base::scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> > output;
     30 //
     31 //   callback = factory.NewOptionalCallback(&OnCallbackComplete, output);
     32 //   DoSomethingAsynchronously(output->pp_array_output(),
     33 //                             callback.pp_completion_callback());
     34 //   ...
     35 namespace ppapi {
     36 namespace proxy {
     37 
     38 // Non-templatized base class for the array output conversion. It provides the
     39 // C implementation of a PP_ArrayOutput whose callback function is implemented
     40 // as a virtual call on a derived class. Do not use directly, use one of the
     41 // derived classes below.
     42 class ArrayOutputAdapterBase {
     43  public:
     44   ArrayOutputAdapterBase() {
     45     pp_array_output_.GetDataBuffer =
     46         &ArrayOutputAdapterBase::GetDataBufferThunk;
     47     pp_array_output_.user_data = this;
     48   }
     49   virtual ~ArrayOutputAdapterBase() {}
     50 
     51   const PP_ArrayOutput& pp_array_output() { return pp_array_output_; }
     52 
     53  protected:
     54   virtual void* GetDataBuffer(uint32_t element_count,
     55                               uint32_t element_size) = 0;
     56 
     57  private:
     58   static void* GetDataBufferThunk(void* user_data,
     59                                   uint32_t element_count,
     60                                   uint32_t element_size);
     61 
     62   PP_ArrayOutput pp_array_output_;
     63 
     64   // Disallow copying and assignment. This will do the wrong thing for most
     65   // subclasses.
     66   ArrayOutputAdapterBase(const ArrayOutputAdapterBase&);
     67   ArrayOutputAdapterBase& operator=(const ArrayOutputAdapterBase&);
     68 };
     69 
     70 // This adapter provides functionality for implementing a PP_ArrayOutput
     71 // structure as writing to a given vector object.
     72 //
     73 // This is generally used internally in the C++ wrapper objects to
     74 // write into an output parameter supplied by the plugin. If the element size
     75 // that the browser is writing does not match the size of the type we're using
     76 // this will assert and return NULL (which will cause the browser to fail the
     77 // call).
     78 //
     79 // Example that allows the browser to write into a given vector:
     80 //   void DoFoo(std::vector<int>* results) {
     81 //     ArrayOutputAdapter<int> adapter(results);
     82 //     ppb_foo->DoFoo(adapter.pp_array_output());
     83 //   }
     84 template<typename T>
     85 class ArrayOutputAdapter : public ArrayOutputAdapterBase {
     86  public:
     87   ArrayOutputAdapter(std::vector<T>* output) : output_(output) {}
     88 
     89  protected:
     90   // Two-step init for the "with storage" version below.
     91   ArrayOutputAdapter() : output_(NULL) {}
     92   void set_output(std::vector<T>* output) { output_ = output; }
     93 
     94   // ArrayOutputAdapterBase implementation.
     95   virtual void* GetDataBuffer(uint32_t element_count, uint32_t element_size) {
     96     DCHECK(element_size == sizeof(T));
     97     if (element_count == 0 || element_size != sizeof(T))
     98       return NULL;
     99     output_->resize(element_count);
    100     return &(*output_)[0];
    101   }
    102 
    103  private:
    104   std::vector<T>* output_;
    105 };
    106 
    107 template<typename T>
    108 class ArrayOutputAdapterWithStorage : public ArrayOutputAdapter<T> {
    109  public:
    110   ArrayOutputAdapterWithStorage() {
    111     // Note: "this->" is required due to two-phase name lookup where it isn't
    112     // allowed to look in the base class during parsing.
    113     this->set_output(&output_storage_);
    114   }
    115 
    116   std::vector<T>& output() { return output_storage_; }
    117 
    118  private:
    119   std::vector<T> output_storage_;
    120 };
    121 
    122 // A reference counted version of ArrayOutputAdapterWithStorage. Since it
    123 // doesn't make much sense to heap-allocate one without storage, we don't
    124 // call it "with storage" to keep the name length under control.
    125 template<typename T>
    126 class RefCountedArrayOutputAdapter
    127     : public ArrayOutputAdapterWithStorage<T>,
    128       public base::RefCounted<RefCountedArrayOutputAdapter<T> > {
    129  public:
    130   RefCountedArrayOutputAdapter()
    131       : ArrayOutputAdapterWithStorage<T>() {
    132   }
    133 };
    134 
    135 }  // namespace proxy
    136 }  // namespace ppapi
    137 
    138 #endif  // PPAPI_PROXY_PROXY_ARRAY_OUTPUT_H_
    139