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