/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"

#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_path.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_value.h"
#include "third_party/blink/public/platform/web_blob_info.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_any.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key_path.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_value.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"

namespace blink {

namespace {

std::unique_ptr<IDBKey> CheckKeyFromValueAndKeyPathInternal(
    v8::Isolate* isolate,
    const ScriptValue& value,
    const String& key_path) {
  IDBKeyPath idb_key_path(key_path);
  EXPECT_TRUE(idb_key_path.IsValid());

  NonThrowableExceptionState exception_state;
  return ScriptValue::To<std::unique_ptr<IDBKey>>(
      isolate, value, exception_state, idb_key_path);
}

void CheckKeyPathNullValue(v8::Isolate* isolate,
                           const ScriptValue& value,
                           const String& key_path) {
  ASSERT_FALSE(CheckKeyFromValueAndKeyPathInternal(isolate, value, key_path));
}

bool InjectKey(ScriptState* script_state,
               IDBKey* key,
               ScriptValue& value,
               const String& key_path) {
  IDBKeyPath idb_key_path(key_path);
  EXPECT_TRUE(idb_key_path.IsValid());
  ScriptValue key_value = ScriptValue::From(script_state, key);
  return InjectV8KeyIntoV8Value(script_state->GetIsolate(), key_value.V8Value(),
                                value.V8Value(), idb_key_path);
}

void CheckInjection(ScriptState* script_state,
                    IDBKey* key,
                    ScriptValue& value,
                    const String& key_path) {
  bool result = InjectKey(script_state, key, value, key_path);
  ASSERT_TRUE(result);
  std::unique_ptr<IDBKey> extracted_key = CheckKeyFromValueAndKeyPathInternal(
      script_state->GetIsolate(), value, key_path);
  EXPECT_TRUE(key->IsEqual(extracted_key.get()));
}

void CheckInjectionIgnored(ScriptState* script_state,
                           IDBKey* key,
                           ScriptValue& value,
                           const String& key_path) {
  bool result = InjectKey(script_state, key, value, key_path);
  ASSERT_TRUE(result);
  std::unique_ptr<IDBKey> extracted_key = CheckKeyFromValueAndKeyPathInternal(
      script_state->GetIsolate(), value, key_path);
  EXPECT_FALSE(key->IsEqual(extracted_key.get()));
}

void CheckInjectionDisallowed(ScriptState* script_state,
                              ScriptValue& value,
                              const String& key_path) {
  const IDBKeyPath idb_key_path(key_path);
  ASSERT_TRUE(idb_key_path.IsValid());
  EXPECT_FALSE(CanInjectIDBKeyIntoScriptValue(script_state->GetIsolate(), value,
                                              idb_key_path));
}

void CheckKeyPathStringValue(v8::Isolate* isolate,
                             const ScriptValue& value,
                             const String& key_path,
                             const String& expected) {
  std::unique_ptr<IDBKey> idb_key =
      CheckKeyFromValueAndKeyPathInternal(isolate, value, key_path);
  ASSERT_TRUE(idb_key);
  ASSERT_EQ(mojom::IDBKeyType::String, idb_key->GetType());
  ASSERT_TRUE(expected == idb_key->GetString());
}

void CheckKeyPathNumberValue(v8::Isolate* isolate,
                             const ScriptValue& value,
                             const String& key_path,
                             int expected) {
  std::unique_ptr<IDBKey> idb_key =
      CheckKeyFromValueAndKeyPathInternal(isolate, value, key_path);
  ASSERT_TRUE(idb_key);
  ASSERT_EQ(mojom::IDBKeyType::Number, idb_key->GetType());
  ASSERT_TRUE(expected == idb_key->Number());
}

// SerializedScriptValue header format offsets are inferred from the Blink and
// V8 serialization code. The code below DCHECKs that
constexpr static size_t kSSVHeaderBlinkVersionTagOffset = 0;
constexpr static size_t kSSVHeaderBlinkVersionOffset = 1;
constexpr static size_t kSSVHeaderV8VersionTagOffset = 2;
// constexpr static size_t kSSVHeaderV8VersionOffset = 3;

// Follows the same steps as the IndexedDB value serialization code.
void SerializeV8Value(v8::Local<v8::Value> value,
                      v8::Isolate* isolate,
                      Vector<char>* wire_bytes) {
  NonThrowableExceptionState non_throwable_exception_state;

  SerializedScriptValue::SerializeOptions options;
  scoped_refptr<SerializedScriptValue> serialized_value =
      SerializedScriptValue::Serialize(isolate, value, options,
                                       non_throwable_exception_state);
  base::span<const uint8_t> ssv_wire_data = serialized_value->GetWireData();
  DCHECK(wire_bytes->IsEmpty());
  wire_bytes->Append(ssv_wire_data.data(),
                     static_cast<wtf_size_t>(ssv_wire_data.size()));

  // Sanity check that the serialization header has not changed, as the tests
  // that use this method rely on the header format.
  //
  // The cast from char* to unsigned char* is necessary to avoid VS2015 warning
  // C4309 (truncation of constant value). This happens because VersionTag is
  // 0xFF.
  const unsigned char* wire_data =
      reinterpret_cast<unsigned char*>(wire_bytes->data());
  ASSERT_EQ(static_cast<unsigned char>(kVersionTag),
            wire_data[kSSVHeaderBlinkVersionTagOffset]);
  ASSERT_EQ(
      static_cast<unsigned char>(SerializedScriptValue::kWireFormatVersion),
      wire_data[kSSVHeaderBlinkVersionOffset]);

  ASSERT_EQ(static_cast<unsigned char>(kVersionTag),
            wire_data[kSSVHeaderV8VersionTagOffset]);
  // TODO(jbroman): Use the compile-time constant for V8 data format version.
  // ASSERT_EQ(v8::ValueSerializer::GetCurrentDataFormatVersion(),
  //           wire_data[kSSVHeaderV8VersionOffset]);
}

std::unique_ptr<IDBValue> CreateIDBValue(v8::Isolate* isolate,
                                         Vector<char>& wire_bytes,
                                         double primary_key,
                                         const WebString& key_path) {
  WebData web_data(SharedBuffer::AdoptVector(wire_bytes));
  WebIDBValue web_idb_value(web_data, Vector<WebBlobInfo>());
  web_idb_value.SetInjectedPrimaryKey(WebIDBKey::CreateNumber(primary_key),
                                      WebIDBKeyPath(key_path));

  std::unique_ptr<IDBValue> idb_value = web_idb_value.ReleaseIdbValue();
  idb_value->SetIsolate(isolate);
  return idb_value;
}

TEST(IDBKeyFromValueAndKeyPathTest, TopLevelPropertyStringValue) {
  V8TestingScope scope;
  v8::Isolate* isolate = scope.GetIsolate();

  // object = { foo: "zoo" }
  ScriptValue script_value = V8ObjectBuilder(scope.GetScriptState())
                                 .Add("foo", "zoo")
                                 .GetScriptValue();
  CheckKeyPathStringValue(isolate, script_value, "foo", "zoo");
  CheckKeyPathNullValue(isolate, script_value, "bar");
}

}  // namespace

TEST(IDBKeyFromValueAndKeyPathTest, TopLevelPropertyNumberValue) {
  V8TestingScope scope;
  v8::Isolate* isolate = scope.GetIsolate();

  // object = { foo: 456 }
  ScriptValue script_value = V8ObjectBuilder(scope.GetScriptState())
                                 .AddNumber("foo", 456)
                                 .GetScriptValue();
  CheckKeyPathNumberValue(isolate, script_value, "foo", 456);
  CheckKeyPathNullValue(isolate, script_value, "bar");
}

TEST(IDBKeyFromValueAndKeyPathTest, SubProperty) {
  V8TestingScope scope;
  ScriptState* script_state = scope.GetScriptState();
  v8::Isolate* isolate = scope.GetIsolate();

  // object = { foo: { bar: "zee" } }
  ScriptValue script_value =
      V8ObjectBuilder(script_state)
          .Add("foo", V8ObjectBuilder(script_state).Add("bar", "zee"))
          .GetScriptValue();
  CheckKeyPathStringValue(isolate, script_value, "foo.bar", "zee");
  CheckKeyPathNullValue(isolate, script_value, "bar");
}

TEST(InjectIDBKeyTest, ImplicitValues) {
  V8TestingScope scope;
  v8::Isolate* isolate = scope.GetIsolate();
  {
    v8::Local<v8::String> string = V8String(isolate, "string");
    ScriptValue value = ScriptValue(scope.GetScriptState(), string);
    std::unique_ptr<IDBKey> idb_key = IDBKey::CreateNumber(123);
    CheckInjectionIgnored(scope.GetScriptState(), idb_key.get(), value,
                          "length");
  }
  {
    v8::Local<v8::Array> array = v8::Array::New(isolate);
    ScriptValue value = ScriptValue(scope.GetScriptState(), array);
    std::unique_ptr<IDBKey> idb_key = IDBKey::CreateNumber(456);
    CheckInjectionIgnored(scope.GetScriptState(), idb_key.get(), value,
                          "length");
  }
}

TEST(InjectIDBKeyTest, TopLevelPropertyStringValue) {
  V8TestingScope scope;

  // object = { foo: "zoo" }
  ScriptValue script_object = V8ObjectBuilder(scope.GetScriptState())
                                  .Add("foo", "zoo")
                                  .GetScriptValue();
  std::unique_ptr<IDBKey> idb_string_key = IDBKey::CreateString("myNewKey");
  CheckInjection(scope.GetScriptState(), idb_string_key.get(), script_object,
                 "bar");
  std::unique_ptr<IDBKey> idb_number_key = IDBKey::CreateNumber(1234);
  CheckInjection(scope.GetScriptState(), idb_number_key.get(), script_object,
                 "bar");

  CheckInjectionDisallowed(scope.GetScriptState(), script_object, "foo.bar");
}

TEST(InjectIDBKeyTest, SubProperty) {
  V8TestingScope scope;
  ScriptState* script_state = scope.GetScriptState();

  // object = { foo: { bar: "zee" } }
  ScriptValue script_object =
      V8ObjectBuilder(script_state)
          .Add("foo", V8ObjectBuilder(script_state).Add("bar", "zee"))
          .GetScriptValue();

  std::unique_ptr<IDBKey> idb_string_key = IDBKey::CreateString("myNewKey");
  CheckInjection(scope.GetScriptState(), idb_string_key.get(), script_object,
                 "foo.baz");
  std::unique_ptr<IDBKey> idb_number_key = IDBKey::CreateNumber(789);
  CheckInjection(scope.GetScriptState(), idb_number_key.get(), script_object,
                 "foo.baz");
  std::unique_ptr<IDBKey> idb_date_key = IDBKey::CreateDate(4567);
  CheckInjection(scope.GetScriptState(), idb_date_key.get(), script_object,
                 "foo.baz");
  CheckInjection(scope.GetScriptState(), idb_date_key.get(), script_object,
                 "bar");
  std::unique_ptr<IDBKey> idb_array_key =
      IDBKey::CreateArray(IDBKey::KeyArray());
  CheckInjection(scope.GetScriptState(), idb_array_key.get(), script_object,
                 "foo.baz");
  CheckInjection(scope.GetScriptState(), idb_array_key.get(), script_object,
                 "bar");

  CheckInjectionDisallowed(scope.GetScriptState(), script_object,
                           "foo.bar.baz");
  std::unique_ptr<IDBKey> idb_zoo_key = IDBKey::CreateString("zoo");
  CheckInjection(scope.GetScriptState(), idb_zoo_key.get(), script_object,
                 "foo.xyz.foo");
}

TEST(DeserializeIDBValueTest, CurrentVersions) {
  V8TestingScope scope;
  v8::Isolate* isolate = scope.GetIsolate();

  Vector<char> object_bytes;
  v8::Local<v8::Object> empty_object = v8::Object::New(isolate);
  SerializeV8Value(empty_object, isolate, &object_bytes);
  std::unique_ptr<IDBValue> idb_value =
      CreateIDBValue(isolate, object_bytes, 42.0, "foo");

  v8::Local<v8::Value> v8_value = DeserializeIDBValue(
      isolate, scope.GetContext()->Global(), idb_value.get());
  EXPECT_TRUE(!scope.GetExceptionState().HadException());

  ASSERT_TRUE(v8_value->IsObject());
  v8::Local<v8::Object> v8_value_object = v8_value.As<v8::Object>();
  v8::Local<v8::Value> v8_number_value =
      v8_value_object->Get(scope.GetContext(), V8AtomicString(isolate, "foo"))
          .ToLocalChecked();
  ASSERT_TRUE(v8_number_value->IsNumber());
  v8::Local<v8::Number> v8_number = v8_number_value.As<v8::Number>();
  EXPECT_EQ(v8_number->Value(), 42.0);
}

TEST(DeserializeIDBValueTest, FutureV8Version) {
  V8TestingScope scope;
  v8::Isolate* isolate = scope.GetIsolate();

  // Pretend that the object was serialized by a future version of V8.
  Vector<char> object_bytes;
  v8::Local<v8::Object> empty_object = v8::Object::New(isolate);
  SerializeV8Value(empty_object, isolate, &object_bytes);
  object_bytes[kSSVHeaderV8VersionTagOffset] += 1;

  // The call sequence below mimics IndexedDB's usage pattern when attempting to
  // read a value in an object store with a key generator and a key path, but
  // the serialized value uses a newer format version.
  //
  // http://crbug.com/703704 has a reproduction for this test's circumstances.
  std::unique_ptr<IDBValue> idb_value =
      CreateIDBValue(isolate, object_bytes, 42.0, "foo");

  v8::Local<v8::Value> v8_value = DeserializeIDBValue(
      isolate, scope.GetContext()->Global(), idb_value.get());
  EXPECT_TRUE(!scope.GetExceptionState().HadException());
  EXPECT_TRUE(v8_value->IsNull());
}

TEST(DeserializeIDBValueTest, InjectionIntoNonObject) {
  V8TestingScope scope;
  v8::Isolate* isolate = scope.GetIsolate();

  // Simulate a storage corruption where an object is read back as a number.
  // This test uses a one-segment key path.
  Vector<char> object_bytes;
  v8::Local<v8::Number> number = v8::Number::New(isolate, 42.0);
  SerializeV8Value(number, isolate, &object_bytes);
  std::unique_ptr<IDBValue> idb_value =
      CreateIDBValue(isolate, object_bytes, 42.0, "foo");

  v8::Local<v8::Value> v8_value = DeserializeIDBValue(
      isolate, scope.GetContext()->Global(), idb_value.get());
  EXPECT_TRUE(!scope.GetExceptionState().HadException());
  ASSERT_TRUE(v8_value->IsNumber());
  v8::Local<v8::Number> v8_number = v8_value.As<v8::Number>();
  EXPECT_EQ(v8_number->Value(), 42.0);
}

TEST(DeserializeIDBValueTest, NestedInjectionIntoNonObject) {
  V8TestingScope scope;
  v8::Isolate* isolate = scope.GetIsolate();

  // Simulate a storage corruption where an object is read back as a number.
  // This test uses a multiple-segment key path.
  Vector<char> object_bytes;
  v8::Local<v8::Number> number = v8::Number::New(isolate, 42.0);
  SerializeV8Value(number, isolate, &object_bytes);
  std::unique_ptr<IDBValue> idb_value =
      CreateIDBValue(isolate, object_bytes, 42.0, "foo.bar");

  v8::Local<v8::Value> v8_value = DeserializeIDBValue(
      isolate, scope.GetContext()->Global(), idb_value.get());
  EXPECT_TRUE(!scope.GetExceptionState().HadException());
  ASSERT_TRUE(v8_value->IsNumber());
  v8::Local<v8::Number> v8_number = v8_value.As<v8::Number>();
  EXPECT_EQ(v8_number->Value(), 42.0);
}

}  // namespace blink
