// 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/messaging_bindings.h"

#include <map>
#include <string>

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/lazy_instance.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/values.h"
#include "components/guest_view/common/guest_view_constants.h"
#include "content/public/child/v8_value_converter.h"
#include "content/public/common/child_process_host.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
#include "extensions/common/api/messaging/message.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/manifest_handlers/externally_connectable.h"
#include "extensions/renderer/dispatcher.h"
#include "extensions/renderer/event_bindings.h"
#include "extensions/renderer/object_backed_native_handler.h"
#include "extensions/renderer/script_context.h"
#include "extensions/renderer/script_context_set.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
#include "third_party/WebKit/public/web/WebScopedWindowFocusAllowedIndicator.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "v8/include/v8.h"

// Message passing API example (in a content script):
// var extension =
//    new chrome.Extension('00123456789abcdef0123456789abcdef0123456');
// var port = runtime.connect();
// port.postMessage('Can you hear me now?');
// port.onmessage.addListener(function(msg, port) {
//   alert('response=' + msg);
//   port.postMessage('I got your reponse');
// });

using content::RenderThread;
using content::V8ValueConverter;

namespace extensions {

namespace {

// Binds |callback| to run when |object| is garbage collected. So as to not
// re-entrantly call into v8, we execute this function asynchronously, at
// which point |context| may have been invalidated. If so, |callback| is not
// run, and |fallback| will be called instead.
//
// Deletes itself when the object args[0] is garbage collected or when the
// context is invalidated.
class GCCallback : public base::SupportsWeakPtr<GCCallback> {
 public:
  GCCallback(ScriptContext* context,
             const v8::Local<v8::Object>& object,
             const v8::Local<v8::Function>& callback,
             const base::Closure& fallback)
      : context_(context),
        object_(context->isolate(), object),
        callback_(context->isolate(), callback),
        fallback_(fallback) {
    object_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter);
    context->AddInvalidationObserver(
        base::Bind(&GCCallback::OnContextInvalidated, AsWeakPtr()));
  }

 private:
  static void FirstWeakCallback(const v8::WeakCallbackInfo<GCCallback>& data) {
    // v8 says we need to explicitly reset weak handles from their callbacks.
    // It's not implicit as one might expect.
    data.GetParameter()->object_.Reset();
    data.SetSecondPassCallback(SecondWeakCallback);
  }

  static void SecondWeakCallback(const v8::WeakCallbackInfo<GCCallback>& data) {
    base::MessageLoop::current()->PostTask(
        FROM_HERE,
        base::Bind(&GCCallback::RunCallback, data.GetParameter()->AsWeakPtr()));
  }

  void RunCallback() {
    CHECK(context_);
    v8::Isolate* isolate = context_->isolate();
    v8::HandleScope handle_scope(isolate);
    context_->CallFunction(v8::Local<v8::Function>::New(isolate, callback_));
    delete this;
  }

  void OnContextInvalidated() {
    fallback_.Run();
    context_ = NULL;
    delete this;
  }

  // ScriptContext which owns this GCCallback.
  ScriptContext* context_;

  // Holds a global handle to the object this GCCallback is bound to.
  v8::Global<v8::Object> object_;

  // Function to run when |object_| bound to this GCCallback is GC'd.
  v8::Global<v8::Function> callback_;

  // Function to run if context is invalidated before we have a chance
  // to execute |callback_|.
  base::Closure fallback_;

  DISALLOW_COPY_AND_ASSIGN(GCCallback);
};

struct ExtensionData {
  struct PortData {
    int ref_count;  // how many contexts have a handle to this port
    PortData() : ref_count(0) {}
  };
  std::map<int, PortData> ports;  // port ID -> data
};

base::LazyInstance<ExtensionData> g_extension_data = LAZY_INSTANCE_INITIALIZER;

bool HasPortData(int port_id) {
  return g_extension_data.Get().ports.find(port_id) !=
         g_extension_data.Get().ports.end();
}

ExtensionData::PortData& GetPortData(int port_id) {
  return g_extension_data.Get().ports[port_id];
}

void ClearPortData(int port_id) {
  g_extension_data.Get().ports.erase(port_id);
}

const char kPortClosedError[] = "Attempting to use a disconnected port object";
const char kReceivingEndDoesntExistError[] =
    "Could not establish connection. Receiving end does not exist.";

class ExtensionImpl : public ObjectBackedNativeHandler {
 public:
  ExtensionImpl(Dispatcher* dispatcher, ScriptContext* context)
      : ObjectBackedNativeHandler(context),
        dispatcher_(dispatcher),
        weak_ptr_factory_(this) {
    RouteFunction(
        "CloseChannel",
        base::Bind(&ExtensionImpl::CloseChannel, base::Unretained(this)));
    RouteFunction(
        "PortAddRef",
        base::Bind(&ExtensionImpl::PortAddRef, base::Unretained(this)));
    RouteFunction(
        "PortRelease",
        base::Bind(&ExtensionImpl::PortRelease, base::Unretained(this)));
    RouteFunction(
        "PostMessage",
        base::Bind(&ExtensionImpl::PostMessage, base::Unretained(this)));
    // TODO(fsamuel, kalman): Move BindToGC out of messaging natives.
    RouteFunction("BindToGC",
                  base::Bind(&ExtensionImpl::BindToGC, base::Unretained(this)));
  }

  ~ExtensionImpl() override {}

 private:
  void ClearPortDataAndNotifyDispatcher(int port_id) {
    ClearPortData(port_id);
    dispatcher_->ClearPortData(port_id);
  }

  // Sends a message along the given channel.
  void PostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
    content::RenderFrame* renderframe = context()->GetRenderFrame();
    if (!renderframe)
      return;

    // Arguments are (int32 port_id, string message).
    CHECK(args.Length() == 2 && args[0]->IsInt32() && args[1]->IsString());

    int port_id = args[0]->Int32Value();
    if (!HasPortData(port_id)) {
      args.GetIsolate()->ThrowException(v8::Exception::Error(
          v8::String::NewFromUtf8(args.GetIsolate(), kPortClosedError)));
      return;
    }

    renderframe->Send(new ExtensionHostMsg_PostMessage(
        renderframe->GetRoutingID(), port_id,
        Message(*v8::String::Utf8Value(args[1]),
                blink::WebUserGestureIndicator::isProcessingUserGesture())));
  }

  // Forcefully disconnects a port.
  void CloseChannel(const v8::FunctionCallbackInfo<v8::Value>& args) {
    // Arguments are (int32 port_id, boolean notify_browser).
    CHECK_EQ(2, args.Length());
    CHECK(args[0]->IsInt32());
    CHECK(args[1]->IsBoolean());

    int port_id = args[0]->Int32Value();
    if (!HasPortData(port_id))
      return;

    // Send via the RenderThread because the RenderFrame might be closing.
    bool notify_browser = args[1]->BooleanValue();
    if (notify_browser) {
      content::RenderThread::Get()->Send(
          new ExtensionHostMsg_CloseChannel(port_id, std::string()));
    }

    ClearPortDataAndNotifyDispatcher(port_id);
  }

  // A new port has been created for a context.  This occurs both when script
  // opens a connection, and when a connection is opened to this script.
  void PortAddRef(const v8::FunctionCallbackInfo<v8::Value>& args) {
    // Arguments are (int32 port_id).
    CHECK_EQ(1, args.Length());
    CHECK(args[0]->IsInt32());

    int port_id = args[0]->Int32Value();
    ++GetPortData(port_id).ref_count;
  }

  // The frame a port lived in has been destroyed.  When there are no more
  // frames with a reference to a given port, we will disconnect it and notify
  // the other end of the channel.
  void PortRelease(const v8::FunctionCallbackInfo<v8::Value>& args) {
    // Arguments are (int32 port_id).
    CHECK(args.Length() == 1 && args[0]->IsInt32());
    ReleasePort(args[0]->Int32Value());
  }

  // Implementation of both the PortRelease native handler call, and callback
  // when contexts are invalidated to release their ports.
  void ReleasePort(int port_id) {
    if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) {
      // Send via the RenderThread because the RenderFrame might be closing.
      content::RenderThread::Get()->Send(
          new ExtensionHostMsg_CloseChannel(port_id, std::string()));
      ClearPortDataAndNotifyDispatcher(port_id);
    }
  }

  // void BindToGC(object, callback, port_id)
  //
  // Binds |callback| to be invoked *sometime after* |object| is garbage
  // collected. We don't call the method re-entrantly so as to avoid executing
  // JS in some bizarro undefined mid-GC state, nor do we then call into the
  // script context if it's been invalidated.
  //
  // If the script context *is* invalidated in the meantime, as a slight hack,
  // release the port with ID |port_id| if it's >= 0.
  void BindToGC(const v8::FunctionCallbackInfo<v8::Value>& args) {
    CHECK(args.Length() == 3 && args[0]->IsObject() && args[1]->IsFunction() &&
          args[2]->IsInt32());
    int port_id = args[2]->Int32Value();
    base::Closure fallback = base::Bind(&base::DoNothing);
    if (port_id >= 0) {
      fallback = base::Bind(&ExtensionImpl::ReleasePort,
                            weak_ptr_factory_.GetWeakPtr(), port_id);
    }
    // Destroys itself when the object is GC'd or context is invalidated.
    new GCCallback(context(), args[0].As<v8::Object>(),
                   args[1].As<v8::Function>(), fallback);
  }

  // Dispatcher handle. Not owned.
  Dispatcher* dispatcher_;

  base::WeakPtrFactory<ExtensionImpl> weak_ptr_factory_;
};

void DispatchOnConnectToScriptContext(
    int target_port_id,
    const std::string& channel_name,
    const ExtensionMsg_TabConnectionInfo* source,
    const ExtensionMsg_ExternalConnectionInfo& info,
    const std::string& tls_channel_id,
    bool* port_created,
    ScriptContext* script_context) {
  // Only dispatch the events if this is the requested target frame (0 = main
  // frame; positive = child frame).
  content::RenderFrame* renderframe = script_context->GetRenderFrame();
  if (info.target_frame_id == 0 && renderframe->GetWebFrame()->parent() != NULL)
    return;
  if (info.target_frame_id > 0 &&
      renderframe->GetRoutingID() != info.target_frame_id)
    return;
  v8::Isolate* isolate = script_context->isolate();
  v8::HandleScope handle_scope(isolate);

  scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());

  const std::string& source_url_spec = info.source_url.spec();
  std::string target_extension_id = script_context->GetExtensionID();
  const Extension* extension = script_context->extension();

  v8::Local<v8::Value> tab = v8::Null(isolate);
  v8::Local<v8::Value> tls_channel_id_value = v8::Undefined(isolate);
  v8::Local<v8::Value> guest_process_id = v8::Undefined(isolate);

  if (extension) {
    if (!source->tab.empty() && !extension->is_platform_app())
      tab = converter->ToV8Value(&source->tab, script_context->v8_context());

    ExternallyConnectableInfo* externally_connectable =
        ExternallyConnectableInfo::Get(extension);
    if (externally_connectable &&
        externally_connectable->accepts_tls_channel_id) {
      tls_channel_id_value = v8::String::NewFromUtf8(isolate,
                                                     tls_channel_id.c_str(),
                                                     v8::String::kNormalString,
                                                     tls_channel_id.size());
    }

    if (info.guest_process_id != content::ChildProcessHost::kInvalidUniqueID)
      guest_process_id = v8::Integer::New(isolate, info.guest_process_id);
  }

  v8::Local<v8::Value> arguments[] = {
      // portId
      v8::Integer::New(isolate, target_port_id),
      // channelName
      v8::String::NewFromUtf8(isolate, channel_name.c_str(),
                              v8::String::kNormalString, channel_name.size()),
      // sourceTab
      tab,
      // source_frame_id
      v8::Integer::New(isolate, source->frame_id),
      // guestProcessId
      guest_process_id,
      // sourceExtensionId
      v8::String::NewFromUtf8(isolate, info.source_id.c_str(),
                              v8::String::kNormalString, info.source_id.size()),
      // targetExtensionId
      v8::String::NewFromUtf8(isolate, target_extension_id.c_str(),
                              v8::String::kNormalString,
                              target_extension_id.size()),
      // sourceUrl
      v8::String::NewFromUtf8(isolate, source_url_spec.c_str(),
                              v8::String::kNormalString,
                              source_url_spec.size()),
      // tlsChannelId
      tls_channel_id_value,
  };

  v8::Local<v8::Value> retval =
      script_context->module_system()->CallModuleMethod(
          "messaging", "dispatchOnConnect", arraysize(arguments), arguments);

  if (!retval.IsEmpty()) {
    CHECK(retval->IsBoolean());
    *port_created |= retval->BooleanValue();
  } else {
    LOG(ERROR) << "Empty return value from dispatchOnConnect.";
  }
}

void DeliverMessageToScriptContext(const Message& message,
                                   int target_port_id,
                                   ScriptContext* script_context) {
  v8::Isolate* isolate = script_context->isolate();
  v8::HandleScope handle_scope(isolate);

  // Check to see whether the context has this port before bothering to create
  // the message.
  v8::Local<v8::Value> port_id_handle =
      v8::Integer::New(isolate, target_port_id);
  v8::Local<v8::Value> has_port =
      script_context->module_system()->CallModuleMethod("messaging", "hasPort",
                                                        1, &port_id_handle);

  CHECK(!has_port.IsEmpty());
  if (!has_port->BooleanValue())
    return;

  std::vector<v8::Local<v8::Value>> arguments;
  arguments.push_back(v8::String::NewFromUtf8(isolate,
                                              message.data.c_str(),
                                              v8::String::kNormalString,
                                              message.data.size()));
  arguments.push_back(port_id_handle);

  scoped_ptr<blink::WebScopedUserGesture> web_user_gesture;
  scoped_ptr<blink::WebScopedWindowFocusAllowedIndicator> allow_window_focus;
  if (message.user_gesture) {
    web_user_gesture.reset(new blink::WebScopedUserGesture);

    if (script_context->web_frame()) {
      blink::WebDocument document = script_context->web_frame()->document();
      allow_window_focus.reset(new blink::WebScopedWindowFocusAllowedIndicator(
          &document));
    }
  }

  script_context->module_system()->CallModuleMethod(
      "messaging", "dispatchOnMessage", &arguments);
}

void DispatchOnDisconnectToScriptContext(int port_id,
                                         const std::string& error_message,
                                         ScriptContext* script_context) {
  v8::Isolate* isolate = script_context->isolate();
  v8::HandleScope handle_scope(isolate);

  std::vector<v8::Local<v8::Value>> arguments;
  arguments.push_back(v8::Integer::New(isolate, port_id));
  if (!error_message.empty()) {
    arguments.push_back(
        v8::String::NewFromUtf8(isolate, error_message.c_str()));
  } else {
    arguments.push_back(v8::Null(isolate));
  }

  script_context->module_system()->CallModuleMethod(
      "messaging", "dispatchOnDisconnect", &arguments);
}

}  // namespace

ObjectBackedNativeHandler* MessagingBindings::Get(Dispatcher* dispatcher,
                                                  ScriptContext* context) {
  return new ExtensionImpl(dispatcher, context);
}

// static
void MessagingBindings::DispatchOnConnect(
    const ScriptContextSet& context_set,
    int target_port_id,
    const std::string& channel_name,
    const ExtensionMsg_TabConnectionInfo& source,
    const ExtensionMsg_ExternalConnectionInfo& info,
    const std::string& tls_channel_id,
    content::RenderFrame* restrict_to_render_frame) {
  // TODO(robwu): ScriptContextSet.ForEach should accept RenderFrame*.
  content::RenderView* restrict_to_render_view =
      restrict_to_render_frame ? restrict_to_render_frame->GetRenderView()
                               : NULL;
  bool port_created = false;
  context_set.ForEach(
      info.target_id, restrict_to_render_view,
      base::Bind(&DispatchOnConnectToScriptContext, target_port_id,
                 channel_name, &source, info, tls_channel_id, &port_created));

  // If we didn't create a port, notify the other end of the channel (treat it
  // as a disconnect).
  if (!port_created) {
    content::RenderThread::Get()->Send(new ExtensionHostMsg_CloseChannel(
        target_port_id, kReceivingEndDoesntExistError));
  }
}

// static
void MessagingBindings::DeliverMessage(
    const ScriptContextSet& context_set,
    int target_port_id,
    const Message& message,
    content::RenderFrame* restrict_to_render_frame) {
  // TODO(robwu): ScriptContextSet.ForEach should accept RenderFrame*.
  content::RenderView* restrict_to_render_view =
      restrict_to_render_frame ? restrict_to_render_frame->GetRenderView()
                               : NULL;
  context_set.ForEach(
      restrict_to_render_view,
      base::Bind(&DeliverMessageToScriptContext, message, target_port_id));
}

// static
void MessagingBindings::DispatchOnDisconnect(
    const ScriptContextSet& context_set,
    int port_id,
    const std::string& error_message,
    content::RenderFrame* restrict_to_render_frame) {
  // TODO(robwu): ScriptContextSet.ForEach should accept RenderFrame*.
  content::RenderView* restrict_to_render_view =
      restrict_to_render_frame ? restrict_to_render_frame->GetRenderView()
                               : NULL;
  context_set.ForEach(
      restrict_to_render_view,
      base::Bind(&DispatchOnDisconnectToScriptContext, port_id, error_message));
}

}  // namespace extensions
