Commit 0925622c authored by dmichael@chromium.org's avatar dmichael@chromium.org

Proxy PPB_Var, fix o-o-p string var id tracking.

Note this doesn't need to use IPC at all, so it's a little strange.

Made test for pp::Var/PPB_Var that does only strings (copied from test_var_deprecated.cc).  Fixed string var tracking so test can pass out-of-process (aside from invalid UTF8 checking, which is still not implemented o-o-p).

BUG=85236
TEST=test_var.cc, run tests manually out-of-process.

Review URL: http://codereview.chromium.org/6995083

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@88384 0039d316-1c4b-4281-b951-d872f2087c98
parent 67b85487
......@@ -166,6 +166,10 @@ TEST_F(PPAPITest, CharSet) {
RunTest("CharSet");
}
TEST_F(PPAPITest, Var) {
RunTest("Var");
}
TEST_F(PPAPITest, VarDeprecated) {
RunTest("VarDeprecated");
}
......
......@@ -122,6 +122,8 @@
'proxy/ppb_url_util_proxy.h',
'proxy/ppb_var_deprecated_proxy.cc',
'proxy/ppb_var_deprecated_proxy.h',
'proxy/ppb_var_proxy.cc',
'proxy/ppb_var_proxy.h',
'proxy/ppp_class_proxy.cc',
'proxy/ppp_class_proxy.h',
'proxy/ppp_graphics_3d_proxy.cc',
......
......@@ -236,6 +236,8 @@
'tests/test_url_util.h',
'tests/test_utils.cc',
'tests/test_utils.h',
'tests/test_var.cc',
'tests/test_var.h',
'tests/test_video_decoder.cc',
'tests/test_video_decoder.h',
......
......@@ -34,6 +34,7 @@
#include "ppapi/c/ppb_url_loader.h"
#include "ppapi/c/ppb_url_request_info.h"
#include "ppapi/c/ppb_url_response_info.h"
#include "ppapi/c/ppb_var.h"
#include "ppapi/c/ppp_instance.h"
#include "ppapi/c/private/ppb_flash.h"
#include "ppapi/c/private/ppb_flash_clipboard.h"
......@@ -77,6 +78,7 @@
#include "ppapi/proxy/ppb_url_response_info_proxy.h"
#include "ppapi/proxy/ppb_url_util_proxy.h"
#include "ppapi/proxy/ppb_var_deprecated_proxy.h"
#include "ppapi/proxy/ppb_var_proxy.h"
#include "ppapi/proxy/ppp_class_proxy.h"
#include "ppapi/proxy/ppp_graphics_3d_proxy.h"
#include "ppapi/proxy/ppp_instance_private_proxy.h"
......@@ -144,6 +146,7 @@ InterfaceList::InterfaceList() {
AddPPB(PPB_URLResponseInfo_Proxy::GetInfo());
AddPPB(PPB_URLUtil_Proxy::GetInfo());
AddPPB(PPB_Var_Deprecated_Proxy::GetInfo());
AddPPB(PPB_Var_Proxy::GetInfo());
#ifdef ENABLE_FLAPPER_HACKS
AddPPB(PPB_Flash_NetConnector_Proxy::GetInfo());
......
......@@ -24,10 +24,14 @@ PP_Var PluginVarSerializationRules::SendCallerOwned(const PP_Var& var,
if (var.type == PP_VARTYPE_OBJECT)
return var_tracker_->GetHostObject(var);
// Nothing to do since we manage the refcount, other than retrieve the string
// to use for IPC.
if (var.type == PP_VARTYPE_STRING)
*str_val = var_tracker_->GetString(var);
// Retrieve the string to use for IPC.
if (var.type == PP_VARTYPE_STRING) {
const std::string* var_string = var_tracker_->GetExistingString(var);
if (var_string)
*str_val = *var_string;
else
NOTREACHED() << "Trying to send unknown string over IPC.";
}
return var;
}
......@@ -119,8 +123,13 @@ PP_Var PluginVarSerializationRules::BeginSendPassRef(const PP_Var& var,
if (var.type == PP_VARTYPE_OBJECT)
return var_tracker_->GetHostObject(var);
if (var.type == PP_VARTYPE_STRING)
*str_val = var_tracker_->GetString(var);
if (var.type == PP_VARTYPE_STRING) {
const std::string* var_string = var_tracker_->GetExistingString(var);
if (var_string)
*str_val = *var_string;
else
NOTREACHED() << "Trying to send unknown string over IPC.";
}
return var;
}
......
......@@ -19,28 +19,6 @@ namespace {
// When non-NULL, this object overrides the VarTrackerSingleton.
PluginVarTracker* var_tracker_override = NULL;
class RefCountedString : public base::RefCounted<RefCountedString> {
public:
RefCountedString() {
}
RefCountedString(const std::string& str) : value_(str) {
}
RefCountedString(const char* data, size_t len)
: value_(data, len) {
}
const std::string& value() const { return value_; }
private:
std::string value_;
};
// When running in the plugin, this will convert the string ID to the object
// using casting. No validity checking is done.
RefCountedString* PluginStringFromID(PluginVarTracker::VarID id) {
return reinterpret_cast<RefCountedString*>(static_cast<intptr_t>(id));
}
} // namespace
PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, VarID i)
......@@ -62,7 +40,7 @@ PluginVarTracker::PluginVarInfo::PluginVarInfo(const HostVar& host_var)
track_with_no_reference_count(0) {
}
PluginVarTracker::PluginVarTracker() : last_plugin_object_id_(0) {
PluginVarTracker::PluginVarTracker() : last_plugin_var_id_(0) {
}
PluginVarTracker::~PluginVarTracker() {
......@@ -81,33 +59,45 @@ PluginVarTracker* PluginVarTracker::GetInstance() {
}
PluginVarTracker::VarID PluginVarTracker::MakeString(const std::string& str) {
RefCountedString* out = new RefCountedString(str);
out->AddRef();
return static_cast<VarID>(reinterpret_cast<intptr_t>(out));
return MakeString(str.c_str(), str.length());
}
PluginVarTracker::VarID PluginVarTracker::MakeString(const char* str,
uint32_t len) {
RefCountedString* out = new RefCountedString(str, len);
out->AddRef();
return static_cast<VarID>(reinterpret_cast<intptr_t>(out));
}
std::string PluginVarTracker::GetString(const PP_Var& var) const {
return PluginStringFromID(var.value.as_id)->value();
std::pair<VarIDStringMap::iterator, bool>
iter_success_pair(var_id_to_string_.end(), false);
VarID new_id(0);
RefCountedStringPtr str_ptr(new RefCountedString(str, len));
// Pick new IDs until one is successfully inserted. This loop is very unlikely
// to ever run a 2nd time, since we have ~2^63 possible IDs to exhaust.
while (!iter_success_pair.second) {
new_id = GetNewVarID();
iter_success_pair =
var_id_to_string_.insert(VarIDStringMap::value_type(new_id, str_ptr));
}
iter_success_pair.first->second->AddRef();
return new_id;
}
const std::string* PluginVarTracker::GetExistingString(
const PP_Var& var) const {
if (var.type != PP_VARTYPE_STRING)
return NULL;
RefCountedString* str = PluginStringFromID(var.value.as_id);
return &str->value();
VarIDStringMap::const_iterator found =
var_id_to_string_.find(var.value.as_id);
if (found != var_id_to_string_.end())
return &found->second->value();
return NULL;
}
void PluginVarTracker::AddRef(const PP_Var& var) {
if (var.type == PP_VARTYPE_STRING) {
PluginStringFromID(var.value.as_id)->AddRef();
VarIDStringMap::iterator found = var_id_to_string_.find(var.value.as_id);
if (found == var_id_to_string_.end()) {
NOTREACHED() << "Requesting to addref an unknown string.";
return;
}
found->second->AddRef();
} else if (var.type == PP_VARTYPE_OBJECT && var.value.as_id != 0) {
PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id);
if (found == plugin_var_info_.end()) {
......@@ -131,7 +121,16 @@ void PluginVarTracker::AddRef(const PP_Var& var) {
void PluginVarTracker::Release(const PP_Var& var) {
if (var.type == PP_VARTYPE_STRING) {
PluginStringFromID(var.value.as_id)->Release();
VarIDStringMap::iterator found = var_id_to_string_.find(var.value.as_id);
if (found == var_id_to_string_.end()) {
NOTREACHED() << "Requesting to release an unknown string.";
return;
}
found->second->Release();
// If there is only 1 reference left, it's the map's reference. Erase it
// from the map, which will delete the string.
if (found->second->HasOneRef())
var_id_to_string_.erase(found);
} else if (var.type == PP_VARTYPE_OBJECT) {
PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id);
if (found == plugin_var_info_.end()) {
......@@ -308,7 +307,7 @@ PluginVarTracker::FindOrMakePluginVarFromHostVar(const PP_Var& var,
}
// Make a new var, adding references to both maps.
VarID new_plugin_var_id = ++last_plugin_object_id_;
VarID new_plugin_var_id = GetNewVarID();
host_var_to_plugin_var_[host_var] = new_plugin_var_id;
return plugin_var_info_.insert(
std::make_pair(new_plugin_var_id, PluginVarInfo(host_var))).first;
......@@ -327,5 +326,11 @@ void PluginVarTracker::DeletePluginVarInfoIfNecessary(
plugin_var_info_.erase(iter);
}
PluginVarTracker::VarID PluginVarTracker::GetNewVarID() {
if (last_plugin_var_id_ == std::numeric_limits<VarID>::max())
last_plugin_var_id_ = 0;
return ++last_plugin_var_id_;
}
} // namesace proxy
} // namespace pp
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
......@@ -8,6 +8,7 @@
#include <map>
#include <string>
#include "base/memory/ref_counted.h"
#include "ppapi/c/pp_stdint.h"
#include "ppapi/c/pp_var.h"
......@@ -51,10 +52,6 @@ class PluginVarTracker {
VarID MakeString(const std::string& str);
VarID MakeString(const char* str, uint32_t len);
// Returns the string associated with the given string var. The var must be
// of type string and must be valid or this function will crash.
std::string GetString(const PP_Var& plugin_var) const;
// Returns a pointer to the given string if it exists, or NULL if the var
// isn't a string var.
const std::string* GetExistingString(const PP_Var& plugin_var) const;
......@@ -93,6 +90,27 @@ class PluginVarTracker {
friend struct DefaultSingletonTraits<PluginVarTracker>;
friend class PluginProxyTest;
class RefCountedString : public base::RefCounted<RefCountedString> {
public:
RefCountedString() {
}
RefCountedString(const std::string& str) : value_(str) {
}
RefCountedString(const char* data, size_t len)
: value_(data, len) {
}
const std::string& value() const { return value_; }
private:
std::string value_;
// Ensure only base::RefCounted can delete a RefCountedString.
friend void base::RefCounted<RefCountedString>::Release() const;
virtual ~RefCountedString() {}
};
typedef scoped_refptr<RefCountedString> RefCountedStringPtr;
// Represents a var as received from the host.
struct HostVar {
HostVar(PluginDispatcher* d, int64_t i);
......@@ -160,9 +178,16 @@ class PluginVarTracker {
typedef std::map<HostVar, VarID> HostVarToPluginVarMap;
HostVarToPluginVarMap host_var_to_plugin_var_;
// The last plugin object ID we've handed out. This must be unique for the
// Maps plugin var IDs to ref counted strings.
typedef std::map<VarID, RefCountedStringPtr> VarIDStringMap;
VarIDStringMap var_id_to_string_;
// The last plugin PP_Var ID we've handed out. This must be unique for the
// process.
VarID last_plugin_object_id_;
VarID last_plugin_var_id_;
// Get a new Var ID and increment last_plugin_var_id_.
VarID GetNewVarID();
};
} // namespace proxy
......
......@@ -58,10 +58,11 @@ TEST_F(PluginVarTrackerTest, Strings) {
EXPECT_NE(0, str_id2);
// Make sure the strings come out the other end.
std::string result = var_tracker().GetString(MakeString(str_id1));
EXPECT_EQ(str, result);
result = var_tracker().GetString(MakeString(str_id2));
EXPECT_EQ(str, result);
const std::string* result =
var_tracker().GetExistingString(MakeString(str_id1));
EXPECT_EQ(str, *result);
result = var_tracker().GetExistingString(MakeString(str_id2));
EXPECT_EQ(str, *result);
}
TEST_F(PluginVarTrackerTest, GetHostObject) {
......
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PPAPI_PPB_VAR_PROXY_H_
#define PPAPI_PPB_VAR_PROXY_H_
#ifndef PPAPI_PPB_VAR_DEPRECATED_PROXY_H_
#define PPAPI_PPB_VAR_DEPRECATED_PROXY_H_
#include <vector>
......@@ -33,7 +33,7 @@ class PPB_Var_Deprecated_Proxy : public InterfaceProxy {
static const Info* GetInfo();
const PPB_Var_Deprecated* ppb_var_target() const {
return reinterpret_cast<const PPB_Var_Deprecated*>(target_interface());
return static_cast<const PPB_Var_Deprecated*>(target_interface());
}
// InterfaceProxy implementation.
......@@ -101,4 +101,4 @@ class PPB_Var_Deprecated_Proxy : public InterfaceProxy {
} // namespace proxy
} // namespace pp
#endif // PPAPI_PPB_VAR_PROXY_H_
#endif // PPAPI_PPB_VAR_DEPRECATED_PROXY_H_
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ppapi/proxy/ppb_var_proxy.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppb_var.h"
#include "ppapi/proxy/plugin_var_tracker.h"
namespace pp {
namespace proxy {
namespace {
// PPP_Var plugin --------------------------------------------------------------
void AddRefVar(PP_Var var) {
PluginVarTracker::GetInstance()->AddRef(var);
}
void ReleaseVar(PP_Var var) {
PluginVarTracker::GetInstance()->Release(var);
}
PP_Var VarFromUtf8(PP_Module module, const char* data, uint32_t len) {
PP_Var ret = {};
ret.type = PP_VARTYPE_STRING;
ret.value.as_id = PluginVarTracker::GetInstance()->MakeString(data, len);
return ret;
}
const char* VarToUtf8(PP_Var var, uint32_t* len) {
const std::string* str =
PluginVarTracker::GetInstance()->GetExistingString(var);
if (str) {
*len = static_cast<uint32_t>(str->size());
return str->c_str();
}
*len = 0;
return NULL;
}
const PPB_Var var_interface = {
&AddRefVar,
&ReleaseVar,
&VarFromUtf8,
&VarToUtf8
};
InterfaceProxy* CreateVarProxy(Dispatcher* dispatcher,
const void* target_interface) {
return new PPB_Var_Proxy(dispatcher, target_interface);
}
} // namespace
PPB_Var_Proxy::PPB_Var_Proxy(Dispatcher* dispatcher,
const void* target_interface)
: InterfaceProxy(dispatcher, target_interface) {
}
PPB_Var_Proxy::~PPB_Var_Proxy() {
}
// static
const InterfaceProxy::Info* PPB_Var_Proxy::GetInfo() {
static const Info info = {
&var_interface,
PPB_VAR_INTERFACE,
INTERFACE_ID_PPB_VAR,
false,
&CreateVarProxy,
};
return &info;
}
bool PPB_Var_Proxy::OnMessageReceived(const IPC::Message& msg) {
// All PPB_Var calls are handled locally; there is no need to send or receive
// messages here.
return false;
}
} // namespace proxy
} // namespace pp
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PPAPI_PPB_VAR_PROXY_H_
#define PPAPI_PPB_VAR_PROXY_H_
#include "ppapi/proxy/interface_proxy.h"
struct PPB_Var;
namespace pp {
namespace proxy {
class PPB_Var_Proxy : public InterfaceProxy {
public:
PPB_Var_Proxy(Dispatcher* dispatcher,
const void* target_interface);
virtual ~PPB_Var_Proxy();
static const Info* GetInfo();
const PPB_Var* ppb_var_target() const {
return static_cast<const PPB_Var*>(target_interface());
}
// InterfaceProxy implementation. In this case, no messages are sent or
// received, so this always returns false.
virtual bool OnMessageReceived(const IPC::Message& msg);
};
} // namespace proxy
} // namespace pp
#endif // PPAPI_PPB_VAR_PROXY_H_
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ppapi/tests/test_var.h"
#include <string.h>
#include <limits>
#include "base/basictypes.h"
#include "ppapi/c/dev/ppb_testing_dev.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppb_var.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var.h"
#include "ppapi/tests/testing_instance.h"
namespace {
uint32_t kInvalidLength = static_cast<uint32_t>(-1);
} // namespace
REGISTER_TEST_CASE(Var);
bool TestVar::Init() {
var_interface_ = reinterpret_cast<const PPB_Var*>(
pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
return var_interface_ && InitTestingInterface();
}
void TestVar::RunTest() {
RUN_TEST(BasicString);
RUN_TEST(InvalidAndEmpty);
RUN_TEST(InvalidUtf8);
RUN_TEST(NullInputInUtf8Conversion);
RUN_TEST(ValidUtf8);
RUN_TEST(Utf8WithEmbeddedNulls);
RUN_TEST(VarToUtf8ForWrongType);
}
std::string TestVar::TestBasicString() {
uint32_t before_object = testing_interface_->GetLiveObjectsForInstance(
instance_->pp_instance());
{
const char kStr[] = "Hello";
const uint32_t kStrLen(arraysize(kStr) - 1);
PP_Var str = var_interface_->VarFromUtf8(pp::Module::Get()->pp_module(),
kStr, kStrLen);
ASSERT_EQ(PP_VARTYPE_STRING, str.type);
// Reading back the string should work.
uint32_t len = 0;
const char* result = var_interface_->VarToUtf8(str, &len);
ASSERT_EQ(kStrLen, len);
ASSERT_EQ(0, strncmp(kStr, result, kStrLen));
// Destroy the string, readback should now fail.
var_interface_->Release(str);
result = var_interface_->VarToUtf8(str, &len);
ASSERT_EQ(0, len);
ASSERT_EQ(NULL, result);
}
// Make sure nothing leaked.
ASSERT_TRUE(testing_interface_->GetLiveObjectsForInstance(
instance_->pp_instance()) == before_object);
PASS();
}
std::string TestVar::TestInvalidAndEmpty() {
PP_Var invalid_string;
invalid_string.type = PP_VARTYPE_STRING;
invalid_string.value.as_id = 31415926;
// Invalid strings should give NULL as the return value.
uint32_t len = std::numeric_limits<uint32_t>::max();
const char* result = var_interface_->VarToUtf8(invalid_string, &len);
ASSERT_EQ(0, len);
ASSERT_EQ(NULL, result);
// Same with vars that are not strings.
len = std::numeric_limits<uint32_t>::max();
pp::Var int_var(42);
result = var_interface_->VarToUtf8(int_var.pp_var(), &len);
ASSERT_EQ(0, len);
ASSERT_EQ(NULL, result);
// Empty strings should return non-NULL.
pp::Var empty_string("");
len = std::numeric_limits<uint32_t>::max();
result = var_interface_->VarToUtf8(empty_string.pp_var(), &len);
ASSERT_EQ(0, len);
ASSERT_NE(NULL, result);
PASS();
}
std::string TestVar::TestInvalidUtf8() {
// utf8じゃない (japanese for "is not utf8") in shift-jis encoding.
static const char kSjisString[] = "utf8\x82\xb6\x82\xe1\x82\xc8\x82\xa2";
pp::Var sjis(kSjisString);
if (!sjis.is_null())
return "Non-UTF8 string was permitted erroneously.";
PASS();
}
std::string TestVar::TestNullInputInUtf8Conversion() {
// This test talks directly to the C interface to access edge cases that
// cannot be exercised via the C++ interface.
PP_Var converted_string;
// 0-length string should not dereference input string, and should produce
// an empty string.
converted_string = var_interface_->VarFromUtf8(
pp::Module::Get()->pp_module(), NULL, 0);
if (converted_string.type != PP_VARTYPE_STRING) {
return "Expected 0 length to return empty string.";
}
// Now convert it back.
uint32_t length = kInvalidLength;
const char* result = NULL;
result = var_interface_->VarToUtf8(converted_string, &length);
if (length != 0) {
return "Expected 0 length string on conversion.";
}
if (result == NULL) {
return "Expected a non-null result for 0-lengthed string from VarToUtf8.";
}
// Should not crash, and make an empty string.
const char* null_string = NULL;
pp::Var null_var(null_string);
if (!null_var.is_string() || null_var.AsString() != "") {
return "Expected NULL input to make an empty string Var.";
}
PASS();
}
std::string TestVar::TestValidUtf8() {
// From UTF8 string -> PP_Var.
// Chinese for "I am utf8."
static const char kValidUtf8[] = "\xe6\x88\x91\xe6\x98\xafutf8.";
pp::Var converted_string(kValidUtf8);
if (converted_string.is_null())
return "Unable to convert valid utf8 to var.";
// Since we're already here, test PP_Var back to UTF8 string.
std::string returned_string = converted_string.AsString();
// We need to check against 1 less than sizeof because the resulting string
// is technically not NULL terminated by API design.
if (returned_string.size() != sizeof(kValidUtf8) - 1) {
return "Unable to convert utf8 string back from var.";
}
if (returned_string != kValidUtf8) {
return "String mismatches on conversion back from PP_Var.";
}
PASS();
}
std::string TestVar::TestUtf8WithEmbeddedNulls() {
// From UTF8 string with embedded nulls -> PP_Var.
// Chinese for "also utf8."
static const char kUtf8WithEmbededNull[] = "\xe6\xb9\x9f\xe6\x98\xaf\0utf8.";
std::string orig_string(kUtf8WithEmbededNull,
sizeof(kUtf8WithEmbededNull) -1);
pp::Var converted_string(orig_string);
if (converted_string.is_null())
return "Unable to convert utf8 with embedded nulls to var.";
// Since we're already here, test PP_Var back to UTF8 string.
std::string returned_string = converted_string.AsString();
if (returned_string.size() != orig_string.size()) {
return "Unable to convert utf8 with embedded nulls back from var.";
}
if (returned_string != orig_string) {
return "String mismatches on conversion back from PP_Var.";
}
PASS();
}
std::string TestVar::TestVarToUtf8ForWrongType() {
uint32_t length = kInvalidLength;
const char* result = NULL;
result = var_interface_->VarToUtf8(PP_MakeUndefined(), &length);
if (length != 0) {
return "Expected 0 on string conversion from Void var.";
}
if (result != NULL) {
return "Expected NULL on string conversion from Void var.";
}
length = kInvalidLength;
result = NULL;
result = var_interface_->VarToUtf8(PP_MakeNull(), &length);
if (length != 0) {
return "Expected 0 on string conversion from Null var.";
}
if (result != NULL) {
return "Expected NULL on string conversion from Null var.";
}
length = kInvalidLength;
result = NULL;
result = var_interface_->VarToUtf8(PP_MakeBool(PP_TRUE), &length);
if (length != 0) {
return "Expected 0 on string conversion from Bool var.";
}
if (result != NULL) {
return "Expected NULL on string conversion from Bool var.";
}
length = kInvalidLength;
result = NULL;
result = var_interface_->VarToUtf8(PP_MakeInt32(1), &length);
if (length != 0) {
return "Expected 0 on string conversion from Int32 var.";
}
if (result != NULL) {
return "Expected NULL on string conversion from Int32 var.";
}
length = kInvalidLength;
result = NULL;
result = var_interface_->VarToUtf8(PP_MakeDouble(1.0), &length);
if (length != 0) {
return "Expected 0 on string conversion from Double var.";
}
if (result != NULL) {
return "Expected NULL on string conversion from Double var.";
}
PASS();
}
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PPAPI_TEST_TEST_VAR_H_
#define PPAPI_TEST_TEST_VAR_H_
#include <string>
#include "ppapi/cpp/var.h"
#include "ppapi/tests/test_case.h"
struct PPB_Var;
class TestVar : public TestCase {
public:
explicit TestVar(TestingInstance* instance) : TestCase(instance) {}
private:
// TestCase implementation.
virtual bool Init();
virtual void RunTest();
std::string TestBasicString();
std::string TestInvalidAndEmpty();
std::string TestInvalidUtf8();
std::string TestNullInputInUtf8Conversion();
std::string TestValidUtf8();
std::string TestUtf8WithEmbeddedNulls();
std::string TestVarToUtf8ForWrongType();
std::string TestHasPropertyAndMethod();
// Used by the tests that access the C API directly.
const PPB_Var* var_interface_;
};
#endif // PPAPI_TEST_TEST_VAR_H_
......@@ -8,6 +8,7 @@
#include <limits>
#include "base/basictypes.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/dev/ppb_testing_dev.h"
#include "ppapi/c/dev/ppb_var_deprecated.h"
......@@ -67,7 +68,7 @@ pp::Var VarScriptableObject::Call(const pp::Var& method_name,
REGISTER_TEST_CASE(VarDeprecated);
bool TestVarDeprecated::Init() {
var_interface_ = reinterpret_cast<PPB_Var_Deprecated const*>(
var_interface_ = static_cast<const PPB_Var_Deprecated*>(
pp::Module::Get()->GetBrowserInterface(PPB_VAR_DEPRECATED_INTERFACE));
return var_interface_ && InitTestingInterface();
}
......@@ -92,10 +93,10 @@ std::string TestVarDeprecated::TestBasicString() {
uint32_t before_object = testing_interface_->GetLiveObjectsForInstance(
instance_->pp_instance());
{
const uint32_t kStrLen = 5;
const char kStr[kStrLen + 1] = "Hello";
const char kStr[] = "Hello";
const uint32_t kStrLen(arraysize(kStr) - 1);
PP_Var str = var_interface_->VarFromUtf8(pp::Module::Get()->pp_module(),
kStr, sizeof(kStr) - 1);
kStr, kStrLen);
ASSERT_EQ(PP_VARTYPE_STRING, str.type);
// Reading back the string should work.
......@@ -106,15 +107,9 @@ std::string TestVarDeprecated::TestBasicString() {
// Destroy the string, readback should now fail.
var_interface_->Release(str);
/*
Note: this will crash in the current out-of-process implementation since
we don't do actual tracking of strings (we just convert the ID to a
pointer).
TODO(brettw) This should be fixed and this checking code re-enabled.
result = var_interface_->VarToUtf8(str, &len);
ASSERT_EQ(0, len);
ASSERT_EQ(NULL, result);
*/
}
// Make sure nothing leaked.
......@@ -157,7 +152,7 @@ std::string TestVarDeprecated::TestInvalidUtf8() {
static const char kSjisString[] = "utf8\x82\xb6\x82\xe1\x82\xc8\x82\xa2";
pp::Var sjis(kSjisString);
if (!sjis.is_null())
return "Non-UTF8 string permitted.";
return "Non-UTF8 string was permitted erroneously.";
PASS();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment