• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
CreateUndefinedValue()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
CreateNonFiniteValue(float in_value)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
CreateNonFiniteValue(double in_value)43 scoped_ptr<base::BinaryValue> GinJavaBridgeValue::CreateNonFiniteValue(
44     double in_value) {
45   return CreateNonFiniteValue(static_cast<float>(in_value)).Pass();
46 }
47 
48 // static
CreateObjectIDValue(int32 in_value)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
ContainsGinJavaBridgeValue(const base::Value * value)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
FromValue(const base::Value * value)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 
GetType() const83 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 
IsType(Type type) const89 bool GinJavaBridgeValue::IsType(Type type) const {
90   return GetType() == type;
91 }
92 
GetAsNonFinite(float * out_value) const93 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 
GetAsObjectID(int32 * out_object_id) const102 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 
GinJavaBridgeValue(Type type)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 
GinJavaBridgeValue(const base::BinaryValue * value)118 GinJavaBridgeValue::GinJavaBridgeValue(const base::BinaryValue* value)
119     : pickle_(value->GetBuffer(), value->GetSize()) {
120   DCHECK(ContainsGinJavaBridgeValue(value));
121 }
122 
SerializeToBinaryValue()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