15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/test_var_deprecated.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_var.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/dev/ppb_testing_dev.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/dev/ppb_var_deprecated.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/dev/scriptable_object_deprecated.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/instance.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/private/var_private.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/var.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/testing_instance.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t kInvalidLength = static_cast<uint32_t>(-1);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kSetValueFunction[] = "SetValue";
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ScriptableObject used by the var tests.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VarScriptableObject : public pp::deprecated::ScriptableObject {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VarScriptableObject(TestVarDeprecated* v) : test_var_deprecated_(v) {}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pp::deprecated::ScriptableObject overrides.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasMethod(const pp::Var& name, pp::Var* exception);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var Call(const pp::Var& name,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               const std::vector<pp::Var>& args,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               pp::Var* exception);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestVarDeprecated* test_var_deprecated_;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VarScriptableObject::HasMethod(const pp::Var& name, pp::Var* exception) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!name.is_string())
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return name.AsString() == kSetValueFunction;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pp::Var VarScriptableObject::Call(const pp::Var& method_name,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const std::vector<pp::Var>& args,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  pp::Var* exception) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!method_name.is_string())
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name = method_name.AsString();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (name == kSetValueFunction) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (args.size() != 1)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *exception = pp::Var("Bad argument to SetValue(<value>)");
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      test_var_deprecated_->set_var_from_page(pp::VarPrivate(args[0]));
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pp::Var();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_TEST_CASE(VarDeprecated);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestVarDeprecated::Init() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_interface_ = static_cast<const PPB_Var_Deprecated*>(
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::Module::Get()->GetBrowserInterface(PPB_VAR_DEPRECATED_INTERFACE));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return var_interface_ && CheckTestingInterface();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestVarDeprecated::RunTests(const std::string& filter) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(BasicString, filter);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(InvalidAndEmpty, filter);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(InvalidUtf8, filter);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(NullInputInUtf8Conversion, filter);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(ValidUtf8, filter);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(Utf8WithEmbeddedNulls, filter);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(VarToUtf8ForWrongType, filter);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(HasPropertyAndMethod, filter);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(PassReference, filter);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pp::deprecated::ScriptableObject* TestVarDeprecated::CreateTestObject() {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new VarScriptableObject(this);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestVarDeprecated::TestBasicString() {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t before_object = testing_interface_->GetLiveObjectsForInstance(
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_->pp_instance());
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char kStr[] = "Hello";
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t kStrLen(sizeof(kStr) - 1);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Var str = var_interface_->VarFromUtf8(pp::Module::Get()->pp_module(),
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             kStr, kStrLen);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_VARTYPE_STRING, str.type);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reading back the string should work.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t len = 0;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* result = var_interface_->VarToUtf8(str, &len);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(kStrLen, len);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(0, strncmp(kStr, result, kStrLen));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Destroy the string, readback should now fail.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var_interface_->Release(str);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = var_interface_->VarToUtf8(str, &len);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(0, len);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(NULL, result);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure nothing leaked.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(testing_interface_->GetLiveObjectsForInstance(
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_->pp_instance()) == before_object);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestVarDeprecated::TestInvalidAndEmpty() {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var invalid_string;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  invalid_string.type = PP_VARTYPE_STRING;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  invalid_string.value.as_id = 31415926;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invalid strings should give NULL as the return value.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t len = std::numeric_limits<uint32_t>::max();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* result = var_interface_->VarToUtf8(invalid_string, &len);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, len);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(NULL, result);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Same with vars that are not strings.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  len = std::numeric_limits<uint32_t>::max();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var int_var(42);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = var_interface_->VarToUtf8(int_var.pp_var(), &len);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, len);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(NULL, result);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Empty strings should return non-NULL.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var empty_string("");
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  len = std::numeric_limits<uint32_t>::max();
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = var_interface_->VarToUtf8(empty_string.pp_var(), &len);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, len);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NE(NULL, result);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestVarDeprecated::TestInvalidUtf8() {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // utf8じゃない (japanese for "is not utf8") in shift-jis encoding.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kSjisString[] = "utf8\x82\xb6\x82\xe1\x82\xc8\x82\xa2";
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var sjis(kSjisString);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!sjis.is_null())
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Non-UTF8 string was permitted erroneously.";
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestVarDeprecated::TestNullInputInUtf8Conversion() {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This test talks directly to the C interface to access edge cases that
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cannot be exercised via the C++ interface.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var converted_string;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 0-length string should not dereference input string, and should produce
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // an empty string.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  converted_string = var_interface_->VarFromUtf8(
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::Module::Get()->pp_module(), NULL, 0);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (converted_string.type != PP_VARTYPE_STRING) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected 0 length to return empty string.";
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now convert it back.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t length = kInvalidLength;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* result = NULL;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = var_interface_->VarToUtf8(converted_string, &length);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (length != 0) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected 0 length string on conversion.";
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == NULL) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected a non-null result for 0-lengthed string from VarToUtf8.";
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_interface_->Release(converted_string);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should not crash, and make an empty string.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* null_string = NULL;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var null_var(null_string);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!null_var.is_string() || null_var.AsString() != "") {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected NULL input to make an empty string Var.";
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestVarDeprecated::TestValidUtf8() {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // From UTF8 string -> PP_Var.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chinese for "I am utf8."
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kValidUtf8[] = "\xe6\x88\x91\xe6\x98\xafutf8.";
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var converted_string(kValidUtf8);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (converted_string.is_null())
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Unable to convert valid utf8 to var.";
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since we're already here, test PP_Var back to UTF8 string.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string returned_string = converted_string.AsString();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to check against 1 less than sizeof because the resulting string
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is technically not NULL terminated by API design.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (returned_string.size() != sizeof(kValidUtf8) - 1) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Unable to convert utf8 string back from var.";
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (returned_string != kValidUtf8) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "String mismatches on conversion back from PP_Var.";
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestVarDeprecated::TestUtf8WithEmbeddedNulls() {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // From UTF8 string with embedded nulls -> PP_Var.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chinese for "also utf8."
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kUtf8WithEmbededNull[] = "\xe6\xb9\x9f\xe6\x98\xaf\0utf8.";
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string orig_string(kUtf8WithEmbededNull,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          sizeof(kUtf8WithEmbededNull) -1);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var converted_string(orig_string);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (converted_string.is_null())
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Unable to convert utf8 with embedded nulls to var.";
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since we're already here, test PP_Var back to UTF8 string.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string returned_string = converted_string.AsString();
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (returned_string.size() != orig_string.size()) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Unable to convert utf8 with embedded nulls back from var.";
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (returned_string != orig_string) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "String mismatches on conversion back from PP_Var.";
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestVarDeprecated::TestVarToUtf8ForWrongType() {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t length = kInvalidLength;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* result = NULL;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = var_interface_->VarToUtf8(PP_MakeUndefined(), &length);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (length != 0) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected 0 on string conversion from Void var.";
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != NULL) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected NULL on string conversion from Void var.";
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  length = kInvalidLength;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = NULL;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = var_interface_->VarToUtf8(PP_MakeNull(), &length);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (length != 0) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected 0 on string conversion from Null var.";
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != NULL) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected NULL on string conversion from Null var.";
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  length = kInvalidLength;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = NULL;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = var_interface_->VarToUtf8(PP_MakeBool(PP_TRUE), &length);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (length != 0) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected 0 on string conversion from Bool var.";
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != NULL) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected NULL on string conversion from Bool var.";
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  length = kInvalidLength;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = NULL;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = var_interface_->VarToUtf8(PP_MakeInt32(1), &length);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (length != 0) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected 0 on string conversion from Int32 var.";
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != NULL) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected NULL on string conversion from Int32 var.";
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  length = kInvalidLength;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = NULL;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = var_interface_->VarToUtf8(PP_MakeDouble(1.0), &length);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (length != 0) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected 0 on string conversion from Double var.";
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != NULL) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "Expected NULL on string conversion from Double var.";
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestVarDeprecated::TestHasPropertyAndMethod() {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::VarPrivate window = instance_->GetWindowObject();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(window.is_object());
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Regular property.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var exception;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(window.HasProperty("scrollX", &exception));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(exception.is_undefined());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(window.HasMethod("scrollX", &exception));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(exception.is_undefined());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Regular method (also counts as HasProperty).
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(window.HasProperty("find", &exception));
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(exception.is_undefined());
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(window.HasMethod("find", &exception));
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(exception.is_undefined());
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nonexistant ones should return false and not set the exception.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(window.HasProperty("superEvilBit", &exception));
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(exception.is_undefined());
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(window.HasMethod("superEvilBit", &exception));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(exception.is_undefined());
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check exception and return false on invalid property name.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(window.HasProperty(3.14159, &exception));
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(exception.is_undefined());
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exception = pp::Var();
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exception = pp::Var();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(window.HasMethod(3.14159, &exception));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(exception.is_undefined());
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to use something not an object.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exception = pp::Var();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::VarPrivate string_object("asdf");
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(string_object.HasProperty("find", &exception));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(exception.is_undefined());
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exception = pp::Var();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(string_object.HasMethod("find", &exception));
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(exception.is_undefined());
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to use an invalid object (need to use the C API).
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var invalid_object;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  invalid_object.type = PP_VARTYPE_OBJECT;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  invalid_object.value.as_id = static_cast<int64_t>(-1234567);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var exception2 = PP_MakeUndefined();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(var_interface_->HasProperty(invalid_object,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           pp::Var("find").pp_var(),
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           &exception2));
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NE(PP_VARTYPE_UNDEFINED, exception2.type);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_interface_->Release(exception2);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exception2 = PP_MakeUndefined();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(var_interface_->HasMethod(invalid_object,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         pp::Var("find").pp_var(),
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         &exception2));
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NE(PP_VARTYPE_UNDEFINED, exception2.type);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_interface_->Release(exception2);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Getting a valid property/method when the exception is set returns false.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exception = pp::Var("Bad something-or-other exception");
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(window.HasProperty("find", &exception));
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(exception.is_undefined());
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(window.HasMethod("find", &exception));
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(exception.is_undefined());
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that when the page sends an object to the plugin via a function call,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that the refcounting works properly (bug 79813).
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestVarDeprecated::TestPassReference() {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_from_page_ = pp::Var();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send a JS object from the page to the plugin.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var exception;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var ret = instance_->ExecuteScript(
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "document.getElementById('plugin').SetValue(function(arg) {"
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "return 'works' + arg;"
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "})",
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &exception);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(exception.is_undefined());
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have gotten an object set for our var_from_page.
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(var_from_page_.is_object());
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the reference counting works, the object should be valid. We can test
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this by executing it (it was a function we defined above) and it should
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // return "works" concatenated with the argument.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::VarPrivate function(var_from_page_);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var result = var_from_page_.Call(pp::Var(), "nice");
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(result.is_string());
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(result.AsString() == "worksnice");
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset var_from_page_ so it doesn't seem like a leak to the var leak
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // checking code.
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_from_page_ = pp::Var();
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
397