// Copyright 2014 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/set_icon_natives.h"

#include <stddef.h>
#include <stdint.h>

#include <limits>
#include <memory>

#include "base/bind.h"
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "content/public/common/common_param_traits.h"
#include "extensions/renderer/request_sender.h"
#include "extensions/renderer/script_context.h"
#include "ipc/ipc_message_utils.h"
#include "third_party/blink/public/web/web_array_buffer_converter.h"
#include "third_party/skia/include/core/SkBitmap.h"

namespace {

const char kInvalidDimensions[] = "ImageData has invalid dimensions.";
const char kInvalidData[] = "ImageData data length does not match dimensions.";
const char kNoMemory[] = "Chrome was unable to initialize icon.";

void ThrowException(v8::Isolate* isolate, const char* error_message) {
  isolate->ThrowException(v8::Exception::Error(
      v8::String::NewFromUtf8(isolate, error_message,
                              v8::NewStringType::kInternalized)
          .ToLocalChecked()));
}

int GetIntPropertyFromV8Object(v8::Local<v8::Object> v8_object,
                               v8::Local<v8::Context> v8_context,
                               const char* property_name) {
  v8::Local<v8::Value> v8_property_value;
  if (!v8_object
           ->Get(v8_context, v8::String::NewFromUtf8(
                                 v8_context->GetIsolate(), property_name,
                                 v8::NewStringType::kInternalized)
                                 .ToLocalChecked())
           .ToLocal(&v8_property_value)) {
    return 0;
  }
  return v8_property_value->Int32Value(v8_context).FromMaybe(0);
}

int GetIntPropertyFromV8Object(v8::Local<v8::Object> v8_object,
                               v8::Local<v8::Context> v8_context,
                               int index) {
  v8::Local<v8::Value> v8_property_value;
  if (!v8_object
           ->Get(v8_context, v8::Integer::New(v8_context->GetIsolate(), index))
           .ToLocal(&v8_property_value)) {
    return 0;
  }
  return v8_property_value->Int32Value(v8_context).FromMaybe(0);
}

}  // namespace

namespace extensions {

SetIconNatives::SetIconNatives(ScriptContext* context)
    : ObjectBackedNativeHandler(context) {}

void SetIconNatives::AddRoutes() {
  RouteHandlerFunction("SetIconCommon",
                       base::BindRepeating(&SetIconNatives::SetIconCommon,
                                           base::Unretained(this)));
}

bool SetIconNatives::ConvertImageDataToBitmapValue(
    const v8::Local<v8::Object> image_data,
    v8::Local<v8::Value>* image_data_bitmap) {
  v8::Local<v8::Context> v8_context = context()->v8_context();
  v8::Isolate* isolate = v8_context->GetIsolate();
  v8::Local<v8::Value> value;
  if (!image_data
           ->Get(v8_context,
                 v8::String::NewFromUtf8(isolate, "data",
                                         v8::NewStringType::kInternalized)
                     .ToLocalChecked())
           .ToLocal(&value)) {
    ThrowException(isolate, kInvalidData);
    return false;
  }

  v8::Local<v8::Object> data;
  if (!value->ToObject(v8_context).ToLocal(&data)) {
    ThrowException(isolate, kInvalidData);
    return false;
  }

  int width = GetIntPropertyFromV8Object(image_data, v8_context, "width");
  int height = GetIntPropertyFromV8Object(image_data, v8_context, "height");
  if (width <= 0 || height <= 0) {
    ThrowException(isolate, kInvalidDimensions);
    return false;
  }

  // We need to be able to safely check |data_length| == 4 * width * height
  // without overflowing below.
  int max_width = (std::numeric_limits<int>::max() / 4) / height;
  if (width > max_width) {
    ThrowException(isolate, kInvalidDimensions);
    return false;
  }

  int data_length = GetIntPropertyFromV8Object(data, v8_context, "length");
  if (data_length != 4 * width * height) {
    ThrowException(isolate, kInvalidData);
    return false;
  }

  SkBitmap bitmap;
  if (!bitmap.tryAllocN32Pixels(width, height)) {
    ThrowException(isolate, kNoMemory);
    return false;
  }
  bitmap.eraseARGB(0, 0, 0, 0);

  uint32_t* pixels = bitmap.getAddr32(0, 0);
  for (int t = 0; t < width * height; t++) {
    // |data| is RGBA, pixels is ARGB.
    pixels[t] = SkPreMultiplyColor(
        ((GetIntPropertyFromV8Object(data, v8_context, 4 * t + 3) & 0xFF)
         << 24) |
        ((GetIntPropertyFromV8Object(data, v8_context, 4 * t + 0) & 0xFF)
         << 16) |
        ((GetIntPropertyFromV8Object(data, v8_context, 4 * t + 1) & 0xFF)
         << 8) |
        ((GetIntPropertyFromV8Object(data, v8_context, 4 * t + 2) & 0xFF)
         << 0));
  }

  // Construct the Value object.
  IPC::Message bitmap_pickle;
  IPC::WriteParam(&bitmap_pickle, bitmap);
  blink::WebArrayBuffer buffer =
      blink::WebArrayBuffer::Create(bitmap_pickle.size(), 1);
  memcpy(buffer.Data(), bitmap_pickle.data(), bitmap_pickle.size());
  *image_data_bitmap = blink::WebArrayBufferConverter::ToV8Value(
      &buffer, context()->v8_context()->Global(), isolate);

  return true;
}

bool SetIconNatives::ConvertImageDataSetToBitmapValueSet(
    v8::Local<v8::Object>& details,
    v8::Local<v8::Object>* bitmap_set_value) {
  v8::Local<v8::Context> v8_context = context()->v8_context();
  v8::Isolate* isolate = v8_context->GetIsolate();
  v8::Local<v8::Value> v8_value;
  if (!details
           ->Get(v8_context,
                 v8::String::NewFromUtf8(isolate, "imageData",
                                         v8::NewStringType::kInternalized)
                     .ToLocalChecked())
           .ToLocal(&v8_value)) {
    return false;
  }
  v8::Local<v8::Object> image_data_set;
  if (!v8_value->ToObject(v8_context).ToLocal(&image_data_set)) {
    return false;
  }

  DCHECK(bitmap_set_value);

  v8::Local<v8::Array> property_names(
      image_data_set->GetOwnPropertyNames(v8_context)
          .FromMaybe(v8::Local<v8::Array>()));
  for (size_t i = 0; i < property_names->Length(); ++i) {
    v8::Local<v8::Value> key =
        property_names->Get(v8_context, i).ToLocalChecked();
    v8::String::Utf8Value utf8_key(isolate, key);
    int size;
    if (!base::StringToInt(std::string(*utf8_key), &size))
      continue;
    v8::Local<v8::Value> v8_image_value;
    if (!image_data_set->Get(v8_context, key).ToLocal(&v8_image_value)) {
      return false;
    }
    v8::Local<v8::Object> image_data;
    if (!v8_image_value->ToObject(v8_context).ToLocal(&image_data)) {
      return false;
    }
    v8::Local<v8::Value> image_data_bitmap;
    if (!ConvertImageDataToBitmapValue(image_data, &image_data_bitmap))
      return false;
    (*bitmap_set_value)
        ->Set(v8_context, key, image_data_bitmap)
        .FromMaybe(false);
  }
  return true;
}

void SetIconNatives::SetIconCommon(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  CHECK_EQ(1, args.Length());
  CHECK(args[0]->IsObject());
  v8::Local<v8::Context> v8_context = context()->v8_context();
  v8::Local<v8::Object> details = args[0].As<v8::Object>();
  v8::Local<v8::Object> bitmap_set_value(v8::Object::New(args.GetIsolate()));
  if (!ConvertImageDataSetToBitmapValueSet(details, &bitmap_set_value))
    return;

  v8::Local<v8::Object> dict(v8::Object::New(args.GetIsolate()));
  dict->Set(v8_context,
            v8::String::NewFromUtf8(args.GetIsolate(), "imageData",
                                    v8::NewStringType::kInternalized)
                .ToLocalChecked(),
            bitmap_set_value)
      .FromMaybe(false);
  v8::Local<v8::String> tabId =
      v8::String::NewFromUtf8(args.GetIsolate(), "tabId",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked();
  bool has_tabid = false;
  if (details->Has(v8_context, tabId).To(&has_tabid) && has_tabid) {
    dict->Set(v8_context, tabId,
              details->Get(v8_context, tabId).ToLocalChecked())
        .FromMaybe(false);
  }
  args.GetReturnValue().Set(dict);
}

}  // namespace extensions
