Home | History | Annotate | Download | only in pepper
      1 // Copyright (c) 2011 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 CONTENT_RENDERER_PEPPER_NPAPI_GLUE_H_
      6 #define CONTENT_RENDERER_PEPPER_NPAPI_GLUE_H_
      7 
      8 #include "base/basictypes.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "content/common/content_export.h"
     11 #include "ppapi/c/pp_module.h"
     12 #include "ppapi/c/pp_var.h"
     13 
     14 struct NPObject;
     15 typedef struct _NPVariant NPVariant;
     16 typedef void* NPIdentifier;
     17 
     18 namespace content {
     19 
     20 class PepperPluginInstanceImpl;
     21 class PluginObject;
     22 
     23 // Utilities -------------------------------------------------------------------
     24 
     25 // Converts the given PP_Var to an NPVariant, returning true on success.
     26 // False means that the given variant is invalid. In this case, the result
     27 // NPVariant will be set to a void one.
     28 //
     29 // The contents of the PP_Var will be copied unless the PP_Var corresponds to
     30 // an object.
     31 bool PPVarToNPVariant(PP_Var var, NPVariant* result);
     32 
     33 // Returns a PP_Var that corresponds to the given NPVariant. The contents of
     34 // the NPVariant will be copied unless the NPVariant corresponds to an
     35 // object. This will handle all Variant types including POD, strings, and
     36 // objects.
     37 //
     38 // The returned PP_Var will have a refcount of 1, this passing ownership of
     39 // the reference to the caller. This is suitable for returning to a plugin.
     40 PP_Var NPVariantToPPVar(PepperPluginInstanceImpl* instance,
     41                         const NPVariant* variant);
     42 
     43 // Returns a NPIdentifier that corresponds to the given PP_Var. The contents
     44 // of the PP_Var will be copied. Returns 0 if the given PP_Var is not a a
     45 // string or integer type.
     46 NPIdentifier PPVarToNPIdentifier(PP_Var var);
     47 
     48 // Returns a PP_Var corresponding to the given identifier. In the case of
     49 // a string identifier, the returned string will have a reference count of 1.
     50 PP_Var NPIdentifierToPPVar(NPIdentifier id);
     51 
     52 // Helper function to create a PP_Var of type object that contains the given
     53 // NPObject for use byt he given module. Calling this function multiple times
     54 // given the same module + NPObject results in the same PP_Var, assuming that
     55 // there is still a PP_Var with a reference open to it from the previous
     56 // call.
     57 //
     58 // The instance is necessary because we can have different instances pointing to
     59 // the same NPObject, and we want to keep their refs separate.
     60 //
     61 // If no ObjectVar currently exists corresponding to the NPObject, one is
     62 // created associated with the given module.
     63 //
     64 // Note: this could easily be changed to take a PP_Instance instead if that
     65 // makes certain calls in the future easier. Currently all callers have a
     66 // PluginInstance so that's what we use here.
     67 CONTENT_EXPORT PP_Var NPObjectToPPVar(PepperPluginInstanceImpl* instance,
     68                                       NPObject* object);
     69 
     70 // This version creates a default v8::Context rather than using the one from
     71 // the container of |instance|. It is only for use in unit tests, where we don't
     72 // have a real container for |instance|.
     73 CONTENT_EXPORT PP_Var NPObjectToPPVarForTest(PepperPluginInstanceImpl* instance,
     74                                              NPObject* object);
     75 
     76 // PPResultAndExceptionToNPResult ----------------------------------------------
     77 
     78 // Convenience object for converting a PPAPI call that can throw an exception
     79 // and optionally return a value, back to the NPAPI layer which expects a
     80 // NPVariant as a result.
     81 //
     82 // Normal usage is that you will pass the result of exception() to the
     83 // PPAPI function as the exception output parameter. Then you will either
     84 // call SetResult with the result of the PPAPI call, or
     85 // CheckExceptionForNoResult if the PPAPI call doesn't return a PP_Var.
     86 //
     87 // Both SetResult and CheckExceptionForNoResult will throw an exception to
     88 // the JavaScript library if the plugin reported an exception. SetResult
     89 // will additionally convert the result to an NPVariant and write it to the
     90 // output parameter given in the constructor.
     91 class PPResultAndExceptionToNPResult {
     92  public:
     93   // The object_var parameter is the object to associate any exception with.
     94   // It may not be NULL.
     95   //
     96   // The np_result parameter is the NPAPI result output parameter. This may be
     97   // NULL if there is no NPVariant result (like for HasProperty). If this is
     98   // specified, you must call SetResult() to set it. If it is not, you must
     99   // call CheckExceptionForNoResult to do the exception checking with no result
    100   // conversion.
    101   PPResultAndExceptionToNPResult(NPObject* object_var, NPVariant* np_result);
    102 
    103   ~PPResultAndExceptionToNPResult();
    104 
    105   // Returns true if an exception has been set.
    106   bool has_exception() const { return exception_.type != PP_VARTYPE_UNDEFINED; }
    107 
    108   // Returns a pointer to the exception. You would pass this to the PPAPI
    109   // function as the exception parameter. If it is set to non-void, this object
    110   // will take ownership of destroying it.
    111   PP_Var* exception() { return &exception_; }
    112 
    113   // Returns true if everything succeeded with no exception. This is valid only
    114   // after calling SetResult/CheckExceptionForNoResult.
    115   bool success() const {
    116     return success_;
    117   }
    118 
    119   // Call this with the return value of the PPAPI function. It will convert
    120   // the result to the NPVariant output parameter and pass any exception on to
    121   // the JS engine. It will update the success flag and return it.
    122   bool SetResult(PP_Var result);
    123 
    124   // Call this after calling a PPAPI function that could have set the
    125   // exception. It will pass the exception on to the JS engine and update
    126   // the success flag.
    127   //
    128   // The success flag will be returned.
    129   bool CheckExceptionForNoResult();
    130 
    131   // Call this to ignore any exception. This prevents the DCHECK from failing
    132   // in the destructor.
    133   void IgnoreException();
    134 
    135  private:
    136   // Throws the current exception to JS. The exception must be set.
    137   void ThrowException();
    138 
    139   NPObject* object_var_;  // Non-owning ref (see constructor).
    140   NPVariant* np_result_;  // Output value, possibly NULL (see constructor).
    141   PP_Var exception_;  // Exception set by the PPAPI call. We own a ref to it.
    142   bool success_;  // See the success() function above.
    143   bool checked_exception_;  // SetResult/CheckExceptionForNoResult was called.
    144 
    145   DISALLOW_COPY_AND_ASSIGN(PPResultAndExceptionToNPResult);
    146 };
    147 
    148 // PPVarArrayFromNPVariantArray ------------------------------------------------
    149 
    150 // Converts an array of NPVariants to an array of PP_Var, and scopes the
    151 // ownership of the PP_Var. This is used when converting argument lists from
    152 // WebKit to the plugin.
    153 class PPVarArrayFromNPVariantArray {
    154  public:
    155   PPVarArrayFromNPVariantArray(PepperPluginInstanceImpl* instance,
    156                                size_t size,
    157                                const NPVariant* variants);
    158   ~PPVarArrayFromNPVariantArray();
    159 
    160   PP_Var* array() { return array_.get(); }
    161 
    162  private:
    163   size_t size_;
    164   scoped_ptr<PP_Var[]> array_;
    165 
    166   DISALLOW_COPY_AND_ASSIGN(PPVarArrayFromNPVariantArray);
    167 };
    168 
    169 // PPVarFromNPObject -----------------------------------------------------------
    170 
    171 // Converts an NPObject tp PP_Var, and scopes the ownership of the PP_Var. This
    172 // is used when converting 'this' pointer from WebKit to the plugin.
    173 class PPVarFromNPObject {
    174  public:
    175   PPVarFromNPObject(PepperPluginInstanceImpl* instance, NPObject* object);
    176   ~PPVarFromNPObject();
    177 
    178   PP_Var var() const { return var_; }
    179 
    180  private:
    181   const PP_Var var_;
    182 
    183   DISALLOW_COPY_AND_ASSIGN(PPVarFromNPObject);
    184 };
    185 
    186 // NPObjectAccessorWithIdentifier ----------------------------------------------
    187 
    188 // Helper class for our NPObject wrapper. This converts a call from WebKit
    189 // where it gives us an NPObject and an NPIdentifier to an easily-accessible
    190 // ObjectVar (corresponding to the NPObject) and PP_Var (corresponding to the
    191 // NPIdentifier).
    192 //
    193 // If the NPObject or identifier is invalid, we'll set is_valid() to false.
    194 // The caller should check is_valid() before doing anything with the class.
    195 //
    196 // JS can't have integer functions, so when dealing with these, we don't want
    197 // to allow integer identifiers. The calling code can decode if it wants to
    198 // allow integer identifiers (like for property access) or prohibit them
    199 // (like for method calling) by setting |allow_integer_identifier|. If this
    200 // is false and the identifier is an integer, we'll set is_valid() to false.
    201 //
    202 // Getting an integer identifier in this case should be impossible. V8
    203 // shouldn't be allowing this, and the Pepper Var calls from the plugin are
    204 // supposed to error out before calling into V8 (which will then call us back).
    205 // Aside from an egregious error, the only time this could happen is an NPAPI
    206 // plugin calling us.
    207 class NPObjectAccessorWithIdentifier {
    208  public:
    209   NPObjectAccessorWithIdentifier(NPObject* object,
    210                                  NPIdentifier identifier,
    211                                  bool allow_integer_identifier);
    212   ~NPObjectAccessorWithIdentifier();
    213 
    214   // Returns true if both the object and identifier are valid.
    215   bool is_valid() const {
    216     return object_ && identifier_.type != PP_VARTYPE_UNDEFINED;
    217   }
    218 
    219   PluginObject* object() { return object_; }
    220   PP_Var identifier() const { return identifier_; }
    221 
    222  private:
    223   PluginObject* object_;
    224   PP_Var identifier_;
    225 
    226   DISALLOW_COPY_AND_ASSIGN(NPObjectAccessorWithIdentifier);
    227 };
    228 
    229 // TryCatch --------------------------------------------------------------------
    230 
    231 // Instantiate this object on the stack to catch V8 exceptions and pass them
    232 // to an optional out parameter supplied by the plugin.
    233 class TryCatch {
    234  public:
    235   // The given exception may be NULL if the consumer isn't interested in
    236   // catching exceptions. If non-NULL, the given var will be updated if any
    237   // exception is thrown (so it must outlive the TryCatch object).
    238   TryCatch(PP_Var* exception);
    239   ~TryCatch();
    240 
    241   // Returns true is an exception has been thrown. This can be true immediately
    242   // after construction if the var passed to the constructor is non-void.
    243   bool has_exception() const { return has_exception_; }
    244 
    245   // Sets the given exception. If an exception has been previously set, this
    246   // function will do nothing (normally you want only the first exception).
    247   void SetException(const char* message);
    248 
    249  private:
    250   static void Catch(void* self, const char* message);
    251 
    252   // True if an exception has been thrown. Since the exception itself may be
    253   // NULL if the plugin isn't interested in getting the exception, this will
    254   // always indicate if SetException has been called, regardless of whether
    255   // the exception itself has been stored.
    256   bool has_exception_;
    257 
    258   // May be null if the consumer isn't interesting in catching exceptions.
    259   PP_Var* exception_;
    260 };
    261 
    262 }  // namespace content
    263 
    264 #endif  // CONTENT_RENDERER_PEPPER_NPAPI_GLUE_H_
    265