Home | History | Annotate | Download | only in android
      1 // Copyright 2014 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 #include "content/common/android/gin_java_bridge_value.h"
      6 
      7 namespace content {
      8 
      9 namespace {
     10 
     11 // The magic value is only used to prevent accidental attempts of reading
     12 // GinJavaBridgeValue from a random BinaryValue.  GinJavaBridgeValue is not
     13 // intended for scenarios where with BinaryValues are being used for anything
     14 // else than holding GinJavaBridgeValues.  If a need for such scenario ever
     15 // emerges, the best solution would be to extend GinJavaBridgeValue to be able
     16 // to wrap raw BinaryValues.
     17 const uint32 kHeaderMagic = 0xBEEFCAFE;
     18 
     19 #pragma pack(push, 4)
     20 struct Header : public Pickle::Header {
     21   uint32 magic;
     22   int32 type;
     23 };
     24 #pragma pack(pop)
     25 
     26 }
     27 
     28 // static
     29 scoped_ptr<base::BinaryValue> GinJavaBridgeValue::CreateUndefinedValue() {
     30   GinJavaBridgeValue gin_value(TYPE_UNDEFINED);
     31   return make_scoped_ptr(gin_value.SerializeToBinaryValue());
     32 }
     33 
     34 // static
     35 scoped_ptr<base::BinaryValue> GinJavaBridgeValue::CreateNonFiniteValue(
     36     float in_value) {
     37   GinJavaBridgeValue gin_value(TYPE_NONFINITE);
     38   gin_value.pickle_.WriteFloat(in_value);
     39   return make_scoped_ptr(gin_value.SerializeToBinaryValue());
     40 }
     41 
     42 // static
     43 scoped_ptr<base::BinaryValue> GinJavaBridgeValue::CreateNonFiniteValue(
     44     double in_value) {
     45   return CreateNonFiniteValue(static_cast<float>(in_value)).Pass();
     46 }
     47 
     48 // static
     49 scoped_ptr<base::BinaryValue> GinJavaBridgeValue::CreateObjectIDValue(
     50     int32 in_value) {
     51   GinJavaBridgeValue gin_value(TYPE_OBJECT_ID);
     52   gin_value.pickle_.WriteInt(in_value);
     53   return make_scoped_ptr(gin_value.SerializeToBinaryValue());
     54 }
     55 
     56 // static
     57 bool GinJavaBridgeValue::ContainsGinJavaBridgeValue(const base::Value* value) {
     58   if (!value->IsType(base::Value::TYPE_BINARY))
     59     return false;
     60   const base::BinaryValue* binary_value =
     61       reinterpret_cast<const base::BinaryValue*>(value);
     62   if (binary_value->GetSize() < sizeof(Header))
     63     return false;
     64   Pickle pickle(binary_value->GetBuffer(), binary_value->GetSize());
     65   // Broken binary value: payload or header size is wrong
     66   if (!pickle.data() || pickle.size() - pickle.payload_size() != sizeof(Header))
     67     return false;
     68   Header* header = pickle.headerT<Header>();
     69   return (header->magic == kHeaderMagic &&
     70           header->type >= TYPE_FIRST_VALUE && header->type < TYPE_LAST_VALUE);
     71 }
     72 
     73 // static
     74 scoped_ptr<const GinJavaBridgeValue> GinJavaBridgeValue::FromValue(
     75     const base::Value* value) {
     76   return scoped_ptr<const GinJavaBridgeValue>(
     77       value->IsType(base::Value::TYPE_BINARY)
     78           ? new GinJavaBridgeValue(
     79                 reinterpret_cast<const base::BinaryValue*>(value))
     80           : NULL);
     81 }
     82 
     83 GinJavaBridgeValue::Type GinJavaBridgeValue::GetType() const {
     84   const Header* header = pickle_.headerT<Header>();
     85   DCHECK(header->type >= TYPE_FIRST_VALUE && header->type < TYPE_LAST_VALUE);
     86   return static_cast<Type>(header->type);
     87 }
     88 
     89 bool GinJavaBridgeValue::IsType(Type type) const {
     90   return GetType() == type;
     91 }
     92 
     93 bool GinJavaBridgeValue::GetAsNonFinite(float* out_value) const {
     94   if (GetType() == TYPE_NONFINITE) {
     95     PickleIterator iter(pickle_);
     96     return iter.ReadFloat(out_value);
     97   } else {
     98     return false;
     99   }
    100 }
    101 
    102 bool GinJavaBridgeValue::GetAsObjectID(int32* out_object_id) const {
    103   if (GetType() == TYPE_OBJECT_ID) {
    104     PickleIterator iter(pickle_);
    105     return iter.ReadInt(out_object_id);
    106   } else {
    107     return false;
    108   }
    109 }
    110 
    111 GinJavaBridgeValue::GinJavaBridgeValue(Type type) :
    112     pickle_(sizeof(Header)) {
    113   Header* header = pickle_.headerT<Header>();
    114   header->magic = kHeaderMagic;
    115   header->type = type;
    116 }
    117 
    118 GinJavaBridgeValue::GinJavaBridgeValue(const base::BinaryValue* value)
    119     : pickle_(value->GetBuffer(), value->GetSize()) {
    120   DCHECK(ContainsGinJavaBridgeValue(value));
    121 }
    122 
    123 base::BinaryValue* GinJavaBridgeValue::SerializeToBinaryValue() {
    124   return base::BinaryValue::CreateWithCopiedBuffer(
    125       reinterpret_cast<const char*>(pickle_.data()), pickle_.size());
    126 }
    127 
    128 }  // namespace content
    129