text: // 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.
  
  #ifndef PPAPI_PROXY_SERIALIZED_VAR_H_
  #define PPAPI_PROXY_SERIALIZED_VAR_H_
  
  #include <stddef.h>
  #include <stdint.h>
  
  #include <memory>
  #include <string>
  #include <vector>
  
  #include "base/macros.h"
  #include "base/memory/ref_counted.h"
  #include "ppapi/c/pp_instance.h"
  #include "ppapi/c/pp_var.h"
  #include "ppapi/proxy/ppapi_proxy_export.h"
  #include "ppapi/proxy/raw_var_data.h"
  #include "ppapi/proxy/serialized_handle.h"
  #include "ppapi/proxy/serialized_structs.h"
  #include "ppapi/proxy/var_serialization_rules.h"
  
  namespace base {
  class PickleIterator;
  }
  
  namespace IPC {
  class Message;
  }
  
  namespace ppapi {
  namespace proxy {
  
  class Dispatcher;
  class VarSerializationRules;
  
  // This class encapsulates a var so that we can serialize and deserialize it.
  // The problem is that for strings, serialization and deserialization requires
  // knowledge from outside about how to get at or create a string. So this
  // object groups the var with a dispatcher so that string values can be set or
  // gotten.
  //
  // Declare IPC messages as using this type, but don't use it directly (it has
  // no useful public methods). Instead, instantiate one of the helper classes
  // below which are conveniently named for each use case to prevent screwups.
  //
  // Design background
  // -----------------
  // This is sadly super complicated. The IPC system needs a consistent type to
  // use for sending and receiving vars (this is a SerializedVar). But there are
  // different combinations of reference counting for sending and receiving
  // objects and for dealing with strings
  //
  // This makes SerializedVar complicated and easy to mess up. To make it
  // reasonable to use, all functions are protected and there are use-specific
  // classes that each encapsulate exactly one type of use in a way that typically
  // won't compile if you do the wrong thing.
  //
  // The IPC system is designed to pass things around and will make copies in
  // some cases, so our system must be designed so that this stuff will work.
  // This is challenging when the SerializedVar must do some cleanup after the
  // message is sent. To work around this, we create an inner class using a
  // linked_ptr so all copies of a SerializedVar can share and we can guarantee
  // that the actual data will get cleaned up on shutdown.
  //
  // Constness
  // ---------
  // SerializedVar basically doesn't support const. Everything is mutable and
  // most functions are declared const. This unfortunateness is because of the
  // way the IPC system works. When deserializing, it will have a const
  // SerializedVar in a Tuple and this will be given to the function. We kind of
  // want to modify that to convert strings and do refcounting.
  //
  // The helper classes used for accessing the SerializedVar have more reasonable
  // behavior and will enforce that you don't do stupid things.
  class PPAPI_PROXY_EXPORT SerializedVar {
   public:
    SerializedVar();
    ~SerializedVar();
  
    // Backend implementation for IPC::ParamTraits<SerializedVar>.
    void WriteToMessage(base::Pickle* m) const { inner_->WriteToMessage(m); }
    // If ReadFromMessage has been called, WriteDataToMessage will write the var
    // that has been read from ReadFromMessage back to a message. This is used
    // when converting handles for use in NaCl.
    void WriteDataToMessage(base::Pickle* m,
                            const HandleWriter& handle_writer) const {
      inner_->WriteDataToMessage(m, handle_writer);
    }
    bool ReadFromMessage(const base::Pickle* m, base::PickleIterator* iter) {
      return inner_->ReadFromMessage(m, iter);
    }
  
    bool is_valid_var() const {
      return inner_->is_valid_var();
    }
  
    // Returns the shared memory handles associated with this SerializedVar.
    std::vector<SerializedHandle*> GetHandles() const {
      return inner_->GetHandles();
    }
  
   protected:
    friend class SerializedVarReceiveInput;
    friend class SerializedVarReturnValue;
    friend class SerializedVarOutParam;
    friend class SerializedVarSendInput;
    friend class SerializedVarSendInputShmem;
    friend class SerializedVarTestConstructor;
    friend class SerializedVarVectorReceiveInput;
  
    class PPAPI_PROXY_EXPORT Inner : public base::RefCounted<Inner> {
     public:
      Inner();
      Inner(VarSerializationRules* serialization_rules);
      ~Inner();
  
      VarSerializationRules* serialization_rules() {
        return serialization_rules_.get();
      }
      void set_serialization_rules(VarSerializationRules* serialization_rules) {
        serialization_rules_ = serialization_rules;
      }
  
      bool is_valid_var() const {
        return is_valid_var_;
      }
  
      std::vector<SerializedHandle*> GetHandles() {
        return (raw_var_data_ ? raw_var_data_->GetHandles() :
            std::vector<SerializedHandle*>());
      }
  
      // See outer class's declarations above.
      PP_Var GetVar();
      void SetVar(PP_Var var);
      void SetInstance(PP_Instance instance);
  
      // For the SerializedVarTestConstructor, this writes the Var value as if
      // it was just received off the wire, without any serialization rules.
      void ForceSetVarValueForTest(PP_Var value);
  
      void WriteToMessage(base::Pickle* m) const;
      void WriteDataToMessage(base::Pickle* m,
                              const HandleWriter& handle_writer) const;
      bool ReadFromMessage(const base::Pickle* m, base::PickleIterator* iter);
  
      // Sets the cleanup mode. See the CleanupMode enum below.
      void SetCleanupModeToEndSendPassRef();
      void SetCleanupModeToEndReceiveCallerOwned();
  
     private:
      enum CleanupMode {
        // The serialized var won't do anything special in the destructor
        // (default).
        CLEANUP_NONE,
  
        // The serialized var will call EndSendPassRef in the destructor.
        END_SEND_PASS_REF,
  
        // The serialized var will call EndReceiveCallerOwned in the destructor.
        END_RECEIVE_CALLER_OWNED
      };
  
      // Rules for serializing and deserializing vars for this process type.
      // This may be NULL, but must be set before trying to serialize to IPC when
      // sending, or before converting back to a PP_Var when receiving.
      scoped_refptr<VarSerializationRules> serialization_rules_;
  
      // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the
      // string_from_ipc_ holds the string. This means that the caller hasn't
      // called Deserialize with a valid Dispatcher yet, which is how we can
      // convert the serialized string value to a PP_Var string ID.
      //
      // This var may not be complete until the serialization rules are set when
      // reading from IPC since we'll need that to convert the string_value to
      // a string ID. Before this, the as_id will be 0 for VARTYPE_STRING.
      PP_Var var_;
  
      PP_Instance instance_;
  
      CleanupMode cleanup_mode_;
  
      // If the var is not properly serialized, this will be false.
      bool is_valid_var_;
  
  #ifndef NDEBUG
      // When being sent or received over IPC, we should only be serialized or
      // deserialized once. These flags help us assert this is true.
      mutable bool has_been_serialized_;
      mutable bool has_been_deserialized_;
  #endif
  
      // ReadFromMessage() may be called on the I/O thread, e.g., when reading the
      // reply to a sync message. We cannot use the var tracker on the I/O thread,
      // which means we cannot create some types of PP_Var
      // (e.g. PP_VARTYPE_STRING). The data is stored in |raw_var_data_| and the
      // PP_Var is constructed when |GetVar()| is called.
      std::unique_ptr<RawVarDataGraph> raw_var_data_;
  
      DISALLOW_COPY_AND_ASSIGN(Inner);
    };
  
    SerializedVar(VarSerializationRules* serialization_rules);
  
    mutable scoped_refptr<Inner> inner_;
  };
  
  // Helpers for message sending side --------------------------------------------
  
  // For sending a value to the remote side.
  //
  // Example for API:
  //   void MyFunction(PP_Var)
  // IPC message:
  //   IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar);
  // Sender would be:
  //   void MyFunctionProxy(PP_Var param) {
  //     Send(new MyFunctionMsg(SerializedVarSendInput(dispatcher, param));
  //   }
  class PPAPI_PROXY_EXPORT SerializedVarSendInput : public SerializedVar {
   public:
    SerializedVarSendInput(Dispatcher* dispatcher, const PP_Var& var);
  
    // Helper function for serializing a vector of input vars for serialization.
    static void ConvertVector(Dispatcher* dispatcher,
                              const PP_Var* input,
                              size_t input_count,
                              std::vector<SerializedVar>* output);
  
   private:
    // Disallow the empty constructor, but keep the default copy constructor
    // which is required to send the object to the IPC system.
    SerializedVarSendInput();
  };
  
  // Specialization for optionally sending over shared memory.
  class PPAPI_PROXY_EXPORT SerializedVarSendInputShmem : public SerializedVar {
   public:
    SerializedVarSendInputShmem(Dispatcher* dispatcher, const PP_Var& var,
                                const PP_Instance& instance);
  
   private:
    // Disallow the empty constructor, but keep the default copy constructor
    // which is required to send the object to the IPC system.
    SerializedVarSendInputShmem();
  };
  
  
  // For the calling side of a function returning a var. The sending side uses
  // SerializedVarReturnValue.
  //
  // Example for API:
  //   PP_Var MyFunction()
  // IPC message:
  //   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
  // Message handler would be:
  //   PP_Var MyFunctionProxy() {
  //     ReceiveSerializedVarReturnValue result;
  //     Send(new MyFunctionMsg(&result));
  //     return result.Return(dispatcher());
  //   }
  //
  // TODO(yzshen): Move the dispatcher parameter to the constructor and store a
  // VarSerializationRules reference instead, in case the dispatcher is destroyed
  // while waiting for reply to the sync message.
  class PPAPI_PROXY_EXPORT ReceiveSerializedVarReturnValue
      : public SerializedVar {
   public:
    // Note that we can't set the dispatcher in the constructor because the
    // data will be overridden when the return value is set. This constructor is
    // normally used in the pattern above (operator= will be implicitly invoked
    // when the sync message writes the output values).
    ReceiveSerializedVarReturnValue();
  
    // This constructor can be used when deserializing manually. This is useful
    // when you're getting strings "returned" via a struct and need to manually
    // get the PP_Vars out. In this case just do:
    //   ReceiveSerializedVarReturnValue(serialized).Return(dispatcher);
    explicit ReceiveSerializedVarReturnValue(const SerializedVar& serialized);
  
    PP_Var Return(Dispatcher* dispatcher);
  
   private:
    DISALLOW_COPY_AND_ASSIGN(ReceiveSerializedVarReturnValue);
  };
  
  // Example for API:
  //   "void MyFunction(PP_Var* exception);"
  // IPC message:
  //   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
  // Message handler would be:
  //   void OnMsgMyFunction(PP_Var* exception) {
  //     ReceiveSerializedException se(dispatcher(), exception)
  //     Send(new PpapiHostMsg_Foo(&se));
  //   }
  class PPAPI_PROXY_EXPORT ReceiveSerializedException : public SerializedVar {
   public:
    ReceiveSerializedException(Dispatcher* dispatcher, PP_Var* exception);
    ~ReceiveSerializedException();
  
    // Returns true if the exception passed in the constructor is set. Check
    // this before actually issuing the IPC.
    bool IsThrown() const;
  
   private:
    // The input/output exception we're wrapping. May be NULL.
    PP_Var* exception_;
  
    DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedException);
  };
  
  // Helper class for when we're returning a vector of Vars. When it goes out
  // of scope it will automatically convert the vector filled by the IPC layer
  // into the array specified by the constructor params.
  //
  // Example for API:
  //   "void MyFunction(uint32_t* count, PP_Var** vars);"
  // IPC message:
  //   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, std::vector<SerializedVar>);
  // Proxy function:
  //   void MyFunction(uint32_t* count, PP_Var** vars) {
  //     ReceiveSerializedVarVectorOutParam vect(dispatcher, count, vars);
  //     Send(new MyMsg(vect.OutParam()));
  //   }
  class PPAPI_PROXY_EXPORT ReceiveSerializedVarVectorOutParam {
   public:
    ReceiveSerializedVarVectorOutParam(Dispatcher* dispatcher,
                                       uint32_t* output_count,
                                       PP_Var** output);
    ~ReceiveSerializedVarVectorOutParam();
  
    std::vector<SerializedVar>* OutParam();
  
   private:
    Dispatcher* dispatcher_;
    uint32_t* output_count_;
    PP_Var** output_;
  
    std::vector<SerializedVar> vector_;
  
    DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedVarVectorOutParam);
  };
  
  // Helpers for message receiving side ------------------------------------------
  
  // For receiving a value from the remote side.
  //
  // Example for API:
  //   void MyFunction(PP_Var)
  // IPC message:
  //   IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar);
  // Message handler would be:
  //   void OnMsgMyFunction(SerializedVarReceiveInput param) {
  //     MyFunction(param.Get());
  //   }
  class PPAPI_PROXY_EXPORT SerializedVarReceiveInput {
   public:
    // We rely on the implicit constructor here since the IPC layer will call
    // us with a SerializedVar. Pass this object by value, the copy constructor
    // will pass along the pointer (as cheap as passing a pointer arg).
    SerializedVarReceiveInput(const SerializedVar& serialized);
    ~SerializedVarReceiveInput();
  
    PP_Var Get(Dispatcher* dispatcher);
    PP_Var GetForInstance(Dispatcher* dispatcher, PP_Instance instance);
    bool is_valid_var() { return serialized_.is_valid_var(); }
  
   private:
    const SerializedVar& serialized_;
  };
  
  // For receiving an input vector of vars from the remote side.
  //
  // Example:
  //   OnMsgMyFunction(SerializedVarVectorReceiveInput vector) {
  //     uint32_t size;
  //     PP_Var* array = vector.Get(dispatcher, &size);
  //     MyFunction(size, array);
  //   }
  class PPAPI_PROXY_EXPORT SerializedVarVectorReceiveInput {
   public:
    SerializedVarVectorReceiveInput(const std::vector<SerializedVar>& serialized);
    ~SerializedVarVectorReceiveInput();
  
    // Only call Get() once. It will return a pointer to the converted array and
    // place the array size in the out param. Will return NULL when the array is
    // empty.
    PP_Var* Get(Dispatcher* dispatcher, uint32_t* array_size);
  
   private:
    const std::vector<SerializedVar>& serialized_;
  
    // Filled by Get().
    std::vector<PP_Var> deserialized_;
  };
  
  // For the receiving side of a function returning a var. The calling side uses
  // ReceiveSerializedVarReturnValue.
  //
  // Example for API:
  //   PP_Var MyFunction()
  // IPC message:
  //   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
  // Message handler would be:
  //   void OnMsgMyFunction(SerializedVarReturnValue result) {
  //     result.Return(dispatcher(), MyFunction());
  //   }
  class PPAPI_PROXY_EXPORT SerializedVarReturnValue {
   public:
    // We rely on the implicit constructor here since the IPC layer will call
    // us with a SerializedVar*. Pass this object by value, the copy constructor
    // will pass along the pointer (as cheap as passing a pointer arg).
    SerializedVarReturnValue(SerializedVar* serialized);
  
    void Return(Dispatcher* dispatcher, const PP_Var& var);
  
    // Helper function for code that doesn't use the pattern above, but gets
    // a return value from the remote side via a struct. You can pass in the
    // SerializedVar and a PP_Var will be created with return value semantics.
    static SerializedVar Convert(Dispatcher* dispatcher, const PP_Var& var);
  
   private:
    SerializedVar* serialized_;
  };
  
  // For writing an out param to the remote side.
  //
  // Example for API:
  //   "void MyFunction(PP_Var* out);"
  // IPC message:
  //   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
  // Message handler would be:
  //   void OnMsgMyFunction(SerializedVarOutParam out_param) {
  //     MyFunction(out_param.OutParam(dispatcher()));
  //   }
  class PPAPI_PROXY_EXPORT SerializedVarOutParam {
   public:
    // We rely on the implicit constructor here since the IPC layer will call
    // us with a SerializedVar*. Pass this object by value, the copy constructor
    // will pass along the pointer (as cheap as passing a pointer arg).
    SerializedVarOutParam(SerializedVar* serialized);
    ~SerializedVarOutParam();
  
    // Call this function only once. The caller should write its result to the
    // returned var pointer before this class goes out of scope. The var's
    // initial value will be VARTYPE_UNDEFINED.
    PP_Var* OutParam(Dispatcher* dispatcher);
  
   private:
    SerializedVar* serialized_;
  
    // This is the value actually written by the code and returned by OutParam.
    // We'll write this into serialized_ in our destructor.
    PP_Var writable_var_;
  
    Dispatcher* dispatcher_;
  };
  
  // For returning an array of PP_Vars to the other side and transferring
  // ownership.
  //
  class PPAPI_PROXY_EXPORT SerializedVarVectorOutParam {
   public:
    SerializedVarVectorOutParam(std::vector<SerializedVar>* serialized);
    ~SerializedVarVectorOutParam();
  
    uint32_t* CountOutParam() { return &count_; }
    PP_Var** ArrayOutParam(Dispatcher* dispatcher);
  
   private:
    Dispatcher* dispatcher_;
    std::vector<SerializedVar>* serialized_;
  
    uint32_t count_;
    PP_Var* array_;
  };
  
  // For tests that just want to construct a SerializedVar for giving it to one
  // of the other classes. This emulates a SerializedVar just received over the
  // wire from another process.
  class PPAPI_PROXY_EXPORT SerializedVarTestConstructor : public SerializedVar {
   public:
    // For POD-types and objects.
    explicit SerializedVarTestConstructor(const PP_Var& pod_var);
  
    // For strings.
    explicit SerializedVarTestConstructor(const std::string& str);
  };
  
  // For tests that want to read what's in a SerializedVar.
  class PPAPI_PROXY_EXPORT SerializedVarTestReader : public SerializedVar {
   public:
    explicit SerializedVarTestReader(const SerializedVar& var);
  
    PP_Var GetVar() const { return inner_->GetVar(); }
  };
  
  }  // namespace proxy
  }  // namespace ppapi
  
  #endif  // PPAPI_PROXY_SERIALIZED_VAR_H_
  