// Copyright (c) 2012 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 "chrome/renderer/external_host_bindings.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/values.h"
#include "chrome/common/render_messages.h"
#include "third_party/WebKit/public/web/WebBindings.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"

using blink::WebBindings;
using webkit_glue::CppArgumentList;
using webkit_glue::CppVariant;

ExternalHostBindings::ExternalHostBindings(IPC::Sender* sender, int routing_id)
    : frame_(NULL), sender_(sender), routing_id_(routing_id) {
  BindCallback("postMessage", base::Bind(&ExternalHostBindings::PostMessage,
                                         base::Unretained(this)));
  BindProperty("onmessage", &on_message_handler_);
}

ExternalHostBindings::~ExternalHostBindings() {
}

void ExternalHostBindings::PostMessage(
    const CppArgumentList& args, CppVariant* result) {
  DCHECK(result);

  // We need at least one argument (message) and at most 2 arguments.
  // Also, the first argument must be a string
  if (args.size() < 1 || args.size() > 2 || !args[0].isString()) {
    result->Set(false);
    return;
  }

  const std::string& message = args[0].ToString();
  std::string target;
  if (args.size() >= 2 && args[1].isString()) {
    target = args[1].ToString();
    if (target.compare("*") != 0) {
      GURL resolved(target);
      if (!resolved.is_valid()) {
        DLOG(WARNING) << "Unable to parse the specified target URL. " << target;
        result->Set(false);
        return;
      }
      target = resolved.spec();
    }
  } else {
    target = "*";
  }

  std::string origin = frame_->document().securityOrigin().toString().utf8();

  result->Set(sender_->Send(
      new ChromeViewHostMsg_ForwardMessageToExternalHost(
          routing_id_, message, origin, target)));
}

bool ExternalHostBindings::ForwardMessageFromExternalHost(
    const std::string& message, const std::string& origin,
    const std::string& target) {
  if (!on_message_handler_.isObject())
    return false;

  bool status = false;

  if (target.compare("*") != 0) {
    // TODO(abarth): This code should use WebSecurityOrigin::toString to
    // make origin strings. GURL::GetOrigin() doesn't understand all the
    // cases that WebSecurityOrigin::toString understands.
    GURL document_url(frame_->document().url());
    GURL document_origin(document_url.GetOrigin());
    GURL target_origin(GURL(target).GetOrigin());

    // We want to compare the origins of the two URLs but first
    // we need to make sure that we don't compare an invalid one
    // to a valid one.
    bool drop = (document_origin.is_valid() != target_origin.is_valid());

    if (!drop) {
      if (!document_origin.is_valid()) {
        // Both origins are invalid, so compare the URLs as opaque strings.
        drop = (document_url.spec().compare(target) != 0);
      } else {
        drop = (document_origin != target_origin);
      }
    }

    if (drop) {
      DLOG(WARNING) << "Dropping posted message.  Origins don't match";
      return false;
    }
  }

  // Construct an event object, assign the origin to the origin member and
  // assign message parameter to the 'data' member of the event.
  NPObject* event_obj = NULL;
  CreateMessageEvent(&event_obj);
  if (!event_obj) {
    NOTREACHED() << "CreateMessageEvent failed";
  } else {
    NPIdentifier init_message_event =
        WebBindings::getStringIdentifier("initMessageEvent");
    NPVariant init_args[8];
    STRINGN_TO_NPVARIANT("message", sizeof("message") - 1,
                         init_args[0]);  // type
    BOOLEAN_TO_NPVARIANT(false, init_args[1]);  // canBubble
    BOOLEAN_TO_NPVARIANT(true, init_args[2]);  // cancelable
    STRINGN_TO_NPVARIANT(message.c_str(), message.length(), \
                         init_args[3]);  // data
    STRINGN_TO_NPVARIANT(origin.c_str(), origin.length(), \
                         init_args[4]);  // origin
    STRINGN_TO_NPVARIANT("", 0, init_args[5]);  // lastEventId
    NULL_TO_NPVARIANT(init_args[6]);  // source
    NULL_TO_NPVARIANT(init_args[7]);  // messagePort

    NPVariant result;
    NULL_TO_NPVARIANT(result);
    status = WebBindings::invoke(NULL, event_obj, init_message_event, init_args,
                                 arraysize(init_args), &result);
    DCHECK(status) << "Failed to initialize MessageEvent";
    WebBindings::releaseVariantValue(&result);

    if (status) {
      NPVariant event_arg;
      OBJECT_TO_NPVARIANT(event_obj, event_arg);
      status = WebBindings::invokeDefault(NULL,
                                          on_message_handler_.value.objectValue,
                                          &event_arg, 1, &result);
      // Don't DCHECK here in case the reason for the failure is a script error.
      DLOG_IF(ERROR, !status) << "NPN_InvokeDefault failed";
      WebBindings::releaseVariantValue(&result);
    }

    WebBindings::releaseObject(event_obj);
  }

  return status;
}

void ExternalHostBindings::BindToJavascript(blink::WebFrame* frame,
                                            const std::string& classname) {
  frame_ = frame;
  CppBoundClass::BindToJavascript(frame, classname);
}

bool ExternalHostBindings::CreateMessageEvent(NPObject** message_event) {
  DCHECK(message_event != NULL);
  DCHECK(frame_ != NULL);

  NPObject* window = frame_->windowObject();
  if (!window) {
    NOTREACHED() << "frame_->windowObject";
    return false;
  }

  const char* identifier_names[] = {
    "document",
    "createEvent",
  };

  NPIdentifier identifiers[arraysize(identifier_names)] = {0};
  WebBindings::getStringIdentifiers(identifier_names,
                                    arraysize(identifier_names), identifiers);

  CppVariant document;
  bool ok = WebBindings::getProperty(NULL, window, identifiers[0], &document);
  DCHECK(document.isObject());

  bool success = false;
  if (ok && document.isObject()) {
    NPVariant result, event_type;
    STRINGN_TO_NPVARIANT("MessageEvent", sizeof("MessageEvent") - 1, \
                         event_type);
    success = WebBindings::invoke(NULL, document.value.objectValue,
                                  identifiers[1], &event_type, 1, &result);
    DCHECK(!success || result.type == NPVariantType_Object);
    if (result.type != NPVariantType_Object) {
      DCHECK(success == false);
    } else {
      DCHECK(success != false);
      // Pass the ownership to the caller (don't call ReleaseVariantValue).
      *message_event = result.value.objectValue;
    }
  }

  return success;
}
