// Copyright 2017 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 "extensions/renderer/api_binding_js_util.h"

#include "base/bind.h"
#include "extensions/renderer/api_binding_test_util.h"
#include "extensions/renderer/api_bindings_system.h"
#include "extensions/renderer/api_bindings_system_unittest.h"
#include "gin/handle.h"

namespace extensions {

class APIBindingJSUtilUnittest : public APIBindingsSystemTest {
 protected:
  APIBindingJSUtilUnittest() {}
  ~APIBindingJSUtilUnittest() override {}

  gin::Handle<APIBindingJSUtil> CreateUtil() {
    return gin::CreateHandle(
        isolate(),
        new APIBindingJSUtil(bindings_system()->type_reference_map(),
                             bindings_system()->request_handler(),
                             bindings_system()->event_handler(),
                             base::Bind(&RunFunctionOnGlobalAndIgnoreResult)));
  }

  v8::Local<v8::Object> GetLastErrorParent(
      v8::Local<v8::Context> context) override {
    return context->Global();
  }

  std::string GetExposedError(v8::Local<v8::Context> context) {
    v8::Local<v8::Value> last_error =
        GetPropertyFromObject(context->Global(), context, "lastError");

    // Use ADD_FAILURE() to avoid messing up the return type with ASSERT.
    if (last_error.IsEmpty()) {
      ADD_FAILURE();
      return std::string();
    }
    if (!last_error->IsObject() && !last_error->IsUndefined()) {
      ADD_FAILURE();
      return std::string();
    }

    if (last_error->IsUndefined())
      return "[undefined]";
    return GetStringPropertyFromObject(last_error.As<v8::Object>(), context,
                                       "message");
  }

  APILastError* last_error() {
    return bindings_system()->request_handler()->last_error();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(APIBindingJSUtilUnittest);
};

TEST_F(APIBindingJSUtilUnittest, TestSetLastError) {
  v8::HandleScope handle_scope(isolate());
  v8::Local<v8::Context> context = MainContext();

  gin::Handle<APIBindingJSUtil> util = CreateUtil();
  v8::Local<v8::Object> v8_util = util.ToV8().As<v8::Object>();

  EXPECT_FALSE(last_error()->HasError(context));
  EXPECT_EQ("[undefined]", GetExposedError(context));
  const char kSetLastError[] = "obj.setLastError('a last error');";
  CallFunctionOnObject(context, v8_util, kSetLastError);
  EXPECT_TRUE(last_error()->HasError(context));
  EXPECT_EQ("\"a last error\"", GetExposedError(context));

  CallFunctionOnObject(context, v8_util,
                       "obj.setLastError('a new last error')");
  EXPECT_TRUE(last_error()->HasError(context));
  EXPECT_EQ("\"a new last error\"", GetExposedError(context));
}

TEST_F(APIBindingJSUtilUnittest, TestHasLastError) {
  v8::HandleScope handle_scope(isolate());
  v8::Local<v8::Context> context = MainContext();

  gin::Handle<APIBindingJSUtil> util = CreateUtil();
  v8::Local<v8::Object> v8_util = util.ToV8().As<v8::Object>();

  EXPECT_FALSE(last_error()->HasError(context));
  EXPECT_EQ("[undefined]", GetExposedError(context));
  const char kHasLastError[] = "return obj.hasLastError();";
  v8::Local<v8::Value> has_error =
      CallFunctionOnObject(context, v8_util, kHasLastError);
  EXPECT_EQ("false", V8ToString(has_error, context));

  last_error()->SetError(context, "an error");
  EXPECT_TRUE(last_error()->HasError(context));
  EXPECT_EQ("\"an error\"", GetExposedError(context));
  has_error = CallFunctionOnObject(context, v8_util, kHasLastError);
  EXPECT_EQ("true", V8ToString(has_error, context));

  last_error()->ClearError(context, false);
  EXPECT_FALSE(last_error()->HasError(context));
  EXPECT_EQ("[undefined]", GetExposedError(context));
  has_error = CallFunctionOnObject(context, v8_util, kHasLastError);
  EXPECT_EQ("false", V8ToString(has_error, context));
}

TEST_F(APIBindingJSUtilUnittest, TestRunWithLastError) {
  v8::HandleScope handle_scope(isolate());
  v8::Local<v8::Context> context = MainContext();

  gin::Handle<APIBindingJSUtil> util = CreateUtil();
  v8::Local<v8::Object> v8_util = util.ToV8().As<v8::Object>();

  EXPECT_FALSE(last_error()->HasError(context));
  EXPECT_EQ("[undefined]", GetExposedError(context));

  const char kRunWithLastError[] =
      "obj.runCallbackWithLastError('last error', function() {\n"
      "  this.exposedLastError =\n"
      "      this.lastError ? this.lastError.message : 'undefined';\n"
      "}, [1, 'foo']);";
  CallFunctionOnObject(context, v8_util, kRunWithLastError);

  EXPECT_FALSE(last_error()->HasError(context));
  EXPECT_EQ("[undefined]", GetExposedError(context));
  EXPECT_EQ("\"last error\"",
            GetStringPropertyFromObject(context->Global(), context,
                                        "exposedLastError"));
}

TEST_F(APIBindingJSUtilUnittest, TestSendRequestWithOptions) {
  v8::HandleScope handle_scope(isolate());
  v8::Local<v8::Context> context = MainContext();

  gin::Handle<APIBindingJSUtil> util = CreateUtil();
  v8::Local<v8::Object> v8_util = util.ToV8().As<v8::Object>();

  const char kSendRequestWithNoOptions[] =
      "obj.sendRequest('alpha.functionWithCallback',\n"
      "                ['someString', function() {}], undefined, undefined);";
  CallFunctionOnObject(context, v8_util, kSendRequestWithNoOptions);
  ASSERT_TRUE(last_request());
  EXPECT_EQ("alpha.functionWithCallback", last_request()->method_name);
  EXPECT_EQ("[\"someString\"]", ValueToString(*last_request()->arguments));
  EXPECT_EQ(binding::RequestThread::UI, last_request()->thread);
  reset_last_request();

  const char kSendRequestForIOThread[] =
      "obj.sendRequest('alpha.functionWithCallback',\n"
      "                ['someOtherString', function() {}], undefined,\n"
      "                {__proto__: null, forIOThread: true});";
  CallFunctionOnObject(context, v8_util, kSendRequestForIOThread);
  ASSERT_TRUE(last_request());
  EXPECT_EQ("alpha.functionWithCallback", last_request()->method_name);
  EXPECT_EQ("[\"someOtherString\"]", ValueToString(*last_request()->arguments));
  EXPECT_EQ(binding::RequestThread::IO, last_request()->thread);
  reset_last_request();

  const char kSendRequestForUIThread[] =
      "obj.sendRequest('alpha.functionWithCallback',\n"
      "                ['someOtherString', function() {}], undefined,\n"
      "                {__proto__: null, forIOThread: false});";
  CallFunctionOnObject(context, v8_util, kSendRequestForUIThread);
  ASSERT_TRUE(last_request());
  EXPECT_EQ("alpha.functionWithCallback", last_request()->method_name);
  EXPECT_EQ("[\"someOtherString\"]", ValueToString(*last_request()->arguments));
  EXPECT_EQ(binding::RequestThread::UI, last_request()->thread);
  reset_last_request();

  const char kSendRequestWithCustomCallback[] =
      R"(obj.sendRequest(
             'alpha.functionWithCallback',
             ['stringy', function() {}], undefined,
             {
               __proto__: null,
               customCallback: function() {
                 this.callbackCalled = true;
               },
             });)";
  CallFunctionOnObject(context, v8_util, kSendRequestWithCustomCallback);
  ASSERT_TRUE(last_request());
  EXPECT_EQ("alpha.functionWithCallback", last_request()->method_name);
  EXPECT_EQ("[\"stringy\"]", ValueToString(*last_request()->arguments));
  EXPECT_EQ(binding::RequestThread::UI, last_request()->thread);
  bindings_system()->CompleteRequest(last_request()->request_id,
                                     base::ListValue(), std::string());
  EXPECT_EQ("true", GetStringPropertyFromObject(context->Global(), context,
                                                "callbackCalled"));
}

}  // namespace extensions
