chromium/ppapi/shared_impl/var.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/shared_impl/var.h"

#include <stddef.h>

#include <limits>
#include <string_view>

#include "base/check.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/resource_var.h"
#include "ppapi/shared_impl/var_tracker.h"

namespace ppapi {

// Var -------------------------------------------------------------------------

// static
std::string Var::PPVarToLogString(PP_Var var) {
  switch (var.type) {
    case PP_VARTYPE_UNDEFINED:
      return "[Undefined]";
    case PP_VARTYPE_NULL:
      return "[Null]";
    case PP_VARTYPE_BOOL:
      return var.value.as_bool ? "[True]" : "[False]";
    case PP_VARTYPE_INT32:
      return base::NumberToString(var.value.as_int);
    case PP_VARTYPE_DOUBLE:
      return base::NumberToString(var.value.as_double);
    case PP_VARTYPE_STRING: {
      StringVar* string(StringVar::FromPPVar(var));
      if (!string)
        return "[Invalid string]";

      // Since this is for logging, escape NULLs, truncate length.
      std::string result;
      const size_t kTruncateAboveLength = 128;
      if (string->value().size() > kTruncateAboveLength)
        result = string->value().substr(0, kTruncateAboveLength) + "...";
      else
        result = string->value();

      base::ReplaceSubstringsAfterOffset(&result, 0, std::string_view("\0", 1),
                                         "\\0");
      return result;
    }
    case PP_VARTYPE_OBJECT:
      return "[Object]";
    case PP_VARTYPE_ARRAY:
      return "[Array]";
    case PP_VARTYPE_DICTIONARY:
      return "[Dictionary]";
    case PP_VARTYPE_ARRAY_BUFFER:
      return "[Array buffer]";
    case PP_VARTYPE_RESOURCE: {
      ResourceVar* resource(ResourceVar::FromPPVar(var));
      if (!resource)
        return "[Invalid resource]";

      if (resource->IsPending()) {
        return base::StringPrintf("[Pending resource]");
      } else if (resource->GetPPResource()) {
        return base::StringPrintf("[Resource %d]", resource->GetPPResource());
      } else {
        return "[Null resource]";
      }
    }
    default:
      return "[Invalid var]";
  }
}

StringVar* Var::AsStringVar() { return NULL; }

ArrayBufferVar* Var::AsArrayBufferVar() { return NULL; }

V8ObjectVar* Var::AsV8ObjectVar() { return NULL; }

ProxyObjectVar* Var::AsProxyObjectVar() { return NULL; }

ArrayVar* Var::AsArrayVar() { return NULL; }

DictionaryVar* Var::AsDictionaryVar() { return NULL; }

ResourceVar* Var::AsResourceVar() { return NULL; }

PP_Var Var::GetPPVar() {
  int32_t id = GetOrCreateVarID();
  if (!id)
    return PP_MakeNull();

  PP_Var result;
  result.type = GetType();
  result.padding = 0;
  result.value.as_id = id;
  return result;
}

int32_t Var::GetExistingVarID() const {
  return var_id_;
}

Var::Var() : var_id_(0) {}

Var::~Var() {}

int32_t Var::GetOrCreateVarID() {
  VarTracker* tracker = PpapiGlobals::Get()->GetVarTracker();
  if (var_id_) {
    if (!tracker->AddRefVar(var_id_))
      return 0;
  } else {
    var_id_ = tracker->AddVar(this);
    if (!var_id_)
      return 0;
  }
  return var_id_;
}

void Var::AssignVarID(int32_t id) {
  DCHECK(!var_id_);  // Must not have already been generated.
  var_id_ = id;
}

// StringVar -------------------------------------------------------------------

StringVar::StringVar() {}

StringVar::StringVar(const std::string& str) : value_(str) {}

StringVar::StringVar(const char* str, uint32_t len) : value_(str, len) {}

StringVar::~StringVar() {}

StringVar* StringVar::AsStringVar() { return this; }

PP_VarType StringVar::GetType() const { return PP_VARTYPE_STRING; }

// static
PP_Var StringVar::StringToPPVar(const std::string& var) {
  return StringToPPVar(var.c_str(), static_cast<uint32_t>(var.size()));
}

// static
PP_Var StringVar::StringToPPVar(const char* data, uint32_t len) {
  scoped_refptr<StringVar> str(new StringVar(data, len));
  if (!str.get() || !base::IsStringUTF8(str->value()))
    return PP_MakeNull();
  return str->GetPPVar();
}

// static
StringVar* StringVar::FromPPVar(PP_Var var) {
  if (var.type != PP_VARTYPE_STRING)
    return NULL;
  scoped_refptr<Var> var_object(
      PpapiGlobals::Get()->GetVarTracker()->GetVar(var));
  if (!var_object.get())
    return NULL;
  return var_object->AsStringVar();
}

// static
PP_Var StringVar::SwapValidatedUTF8StringIntoPPVar(std::string* src) {
  scoped_refptr<StringVar> str(new StringVar);
  str->value_.swap(*src);
  return str->GetPPVar();
}

// ArrayBufferVar --------------------------------------------------------------

ArrayBufferVar::ArrayBufferVar() {}

ArrayBufferVar::~ArrayBufferVar() {}

ArrayBufferVar* ArrayBufferVar::AsArrayBufferVar() { return this; }

PP_VarType ArrayBufferVar::GetType() const { return PP_VARTYPE_ARRAY_BUFFER; }

// static
ArrayBufferVar* ArrayBufferVar::FromPPVar(PP_Var var) {
  if (var.type != PP_VARTYPE_ARRAY_BUFFER)
    return NULL;
  scoped_refptr<Var> var_object(
      PpapiGlobals::Get()->GetVarTracker()->GetVar(var));
  if (!var_object.get())
    return NULL;
  return var_object->AsArrayBufferVar();
}

}  // namespace ppapi