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#include "ppapi/shared_impl/var.h"
6
7#include <limits>
8
9#include "base/logging.h"
10#include "base/strings/string_number_conversions.h"
11#include "base/strings/string_util.h"
12#include "ppapi/c/pp_var.h"
13#include "ppapi/shared_impl/ppapi_globals.h"
14#include "ppapi/shared_impl/var_tracker.h"
15
16namespace ppapi {
17
18// Var -------------------------------------------------------------------------
19
20Var::Var() : var_id_(0) {
21}
22
23Var::~Var() {
24}
25
26// static
27std::string Var::PPVarToLogString(PP_Var var) {
28  switch (var.type) {
29    case PP_VARTYPE_UNDEFINED:
30      return "[Undefined]";
31    case PP_VARTYPE_NULL:
32      return "[Null]";
33    case PP_VARTYPE_BOOL:
34      return var.value.as_bool ? "[True]" : "[False]";
35    case PP_VARTYPE_INT32:
36      return base::IntToString(var.value.as_int);
37    case PP_VARTYPE_DOUBLE:
38      return base::DoubleToString(var.value.as_double);
39    case PP_VARTYPE_STRING: {
40      StringVar* string(StringVar::FromPPVar(var));
41      if (!string)
42        return "[Invalid string]";
43
44      // Since this is for logging, escape NULLs, truncate length.
45      std::string result;
46      const size_t kTruncateAboveLength = 128;
47      if (string->value().size() > kTruncateAboveLength)
48        result = string->value().substr(0, kTruncateAboveLength) + "...";
49      else
50        result = string->value();
51
52      std::string null;
53      null.push_back(0);
54      ReplaceSubstringsAfterOffset(&result, 0, null, "\\0");
55      return result;
56    }
57    case PP_VARTYPE_OBJECT:
58      return "[Object]";
59    case PP_VARTYPE_ARRAY:
60      return "[Array]";
61    case PP_VARTYPE_DICTIONARY:
62      return "[Dictionary]";
63    case PP_VARTYPE_ARRAY_BUFFER:
64      return "[Array buffer]";
65    default:
66      return "[Invalid var]";
67  }
68}
69
70StringVar* Var::AsStringVar() {
71  return NULL;
72}
73
74ArrayBufferVar* Var::AsArrayBufferVar() {
75  return NULL;
76}
77
78NPObjectVar* Var::AsNPObjectVar() {
79  return NULL;
80}
81
82ProxyObjectVar* Var::AsProxyObjectVar() {
83  return NULL;
84}
85
86ArrayVar* Var::AsArrayVar() {
87  return NULL;
88}
89
90DictionaryVar* Var::AsDictionaryVar() {
91  return NULL;
92}
93
94PP_Var Var::GetPPVar() {
95  int32 id = GetOrCreateVarID();
96  if (!id)
97    return PP_MakeNull();
98
99  PP_Var result;
100  result.type = GetType();
101  result.padding = 0;
102  result.value.as_id = id;
103  return result;
104}
105
106int32 Var::GetExistingVarID() const {
107  return var_id_;
108}
109
110int32 Var::GetOrCreateVarID() {
111  VarTracker* tracker = PpapiGlobals::Get()->GetVarTracker();
112  if (var_id_) {
113    if (!tracker->AddRefVar(var_id_))
114      return 0;
115  } else {
116    var_id_ = tracker->AddVar(this);
117    if (!var_id_)
118      return 0;
119  }
120  return var_id_;
121}
122
123void Var::AssignVarID(int32 id) {
124  DCHECK(!var_id_);  // Must not have already been generated.
125  var_id_ = id;
126}
127
128// StringVar -------------------------------------------------------------------
129
130StringVar::StringVar() {
131}
132
133StringVar::StringVar(const std::string& str)
134    : value_(str) {
135}
136
137StringVar::StringVar(const char* str, uint32 len)
138    : value_(str, len) {
139}
140
141StringVar::~StringVar() {
142}
143
144StringVar* StringVar::AsStringVar() {
145  return this;
146}
147
148PP_VarType StringVar::GetType() const {
149  return PP_VARTYPE_STRING;
150}
151
152// static
153PP_Var StringVar::StringToPPVar(const std::string& var) {
154  return StringToPPVar(var.c_str(), static_cast<uint32>(var.size()));
155}
156
157// static
158PP_Var StringVar::StringToPPVar(const char* data, uint32 len) {
159  scoped_refptr<StringVar> str(new StringVar(data, len));
160  if (!str.get() || !IsStringUTF8(str->value()))
161    return PP_MakeNull();
162  return str->GetPPVar();
163}
164
165// static
166StringVar* StringVar::FromPPVar(PP_Var var) {
167  if (var.type != PP_VARTYPE_STRING)
168    return NULL;
169  scoped_refptr<Var> var_object(
170      PpapiGlobals::Get()->GetVarTracker()->GetVar(var));
171  if (!var_object.get())
172    return NULL;
173  return var_object->AsStringVar();
174}
175
176// static
177PP_Var StringVar::SwapValidatedUTF8StringIntoPPVar(std::string* src) {
178  scoped_refptr<StringVar> str(new StringVar);
179  str->value_.swap(*src);
180  return str->GetPPVar();
181}
182
183// ArrayBufferVar --------------------------------------------------------------
184
185ArrayBufferVar::ArrayBufferVar() {
186}
187
188ArrayBufferVar::~ArrayBufferVar() {
189}
190
191ArrayBufferVar* ArrayBufferVar::AsArrayBufferVar() {
192  return this;
193}
194
195PP_VarType ArrayBufferVar::GetType() const {
196  return PP_VARTYPE_ARRAY_BUFFER;
197}
198
199// static
200ArrayBufferVar* ArrayBufferVar::FromPPVar(PP_Var var) {
201  if (var.type != PP_VARTYPE_ARRAY_BUFFER)
202    return NULL;
203  scoped_refptr<Var> var_object(
204      PpapiGlobals::Get()->GetVarTracker()->GetVar(var));
205  if (!var_object.get())
206    return NULL;
207  return var_object->AsArrayBufferVar();
208}
209
210}  // namespace ppapi
211
212