// 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 "content/renderer/text_input_client_observer.h"

#include <stddef.h>

#include <memory>

#include "build/build_config.h"
#include "content/common/text_input_client_messages.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/render_widget.h"
#include "ipc/ipc_message.h"
#include "ppapi/features/features.h"
#include "third_party/WebKit/public/platform/WebPoint.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "ui/gfx/geometry/rect.h"

#if defined(OS_MACOSX)
#include "third_party/WebKit/public/web/mac/WebSubstringUtil.h"
#endif

namespace content {

namespace {
uint32_t GetCurrentCursorPositionInFrame(blink::WebLocalFrame* localFrame) {
  blink::WebRange range = localFrame->SelectionRange();
  return range.IsNull() ? 0U : static_cast<uint32_t>(range.StartOffset());
}
}

TextInputClientObserver::TextInputClientObserver(RenderWidget* render_widget)
    : render_widget_(render_widget) {}

TextInputClientObserver::~TextInputClientObserver() {
}

bool TextInputClientObserver::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(TextInputClientObserver, message)
    IPC_MESSAGE_HANDLER(TextInputClientMsg_StringAtPoint,
                        OnStringAtPoint)
    IPC_MESSAGE_HANDLER(TextInputClientMsg_CharacterIndexForPoint,
                        OnCharacterIndexForPoint)
    IPC_MESSAGE_HANDLER(TextInputClientMsg_FirstRectForCharacterRange,
                        OnFirstRectForCharacterRange)
    IPC_MESSAGE_HANDLER(TextInputClientMsg_StringForRange, OnStringForRange)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

bool TextInputClientObserver::Send(IPC::Message* message) {
  return render_widget_->Send(message);
}

blink::WebFrameWidget* TextInputClientObserver::GetWebFrameWidget() const {
  blink::WebWidget* widget = render_widget_->GetWebWidget();
  if (!widget->IsWebFrameWidget()) {
    // When a page navigation occurs, for a brief period
    // RenderViewImpl::GetWebWidget() will return a WebViewImpl instead of a
    // WebViewFrameWidget. Therefore, casting to WebFrameWidget is invalid and
    // could cause crashes. Also, WebView::mainFrame() could be a remote frame
    // which will yield a nullptr for localRoot() (https://crbug.com/664890).
    return nullptr;
  }
  return static_cast<blink::WebFrameWidget*>(widget);
}

blink::WebLocalFrame* TextInputClientObserver::GetFocusedFrame() const {
  if (auto* frame_widget = GetWebFrameWidget()) {
    blink::WebLocalFrame* localRoot = frame_widget->LocalRoot();
    RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(localRoot);
    if (!render_frame) {
      // TODO(ekaramad): Can this ever be nullptr? (https://crbug.com/664890).
      return nullptr;
    }
    blink::WebLocalFrame* focused =
        render_frame->render_view()->webview()->FocusedFrame();
    return focused->LocalRoot() == localRoot ? focused : nullptr;
  }
  return nullptr;
}

#if BUILDFLAG(ENABLE_PLUGINS)
PepperPluginInstanceImpl* TextInputClientObserver::GetFocusedPepperPlugin()
    const {
  blink::WebLocalFrame* focusedFrame = GetFocusedFrame();
  return focusedFrame
             ? RenderFrameImpl::FromWebFrame(focusedFrame)
                   ->focused_pepper_plugin()
             : nullptr;
}
#endif

void TextInputClientObserver::OnStringAtPoint(gfx::Point point) {
#if defined(OS_MACOSX)
  blink::WebPoint baselinePoint;
  NSAttributedString* string = nil;

  if (auto* frame_widget = GetWebFrameWidget()) {
    string = blink::WebSubstringUtil::AttributedWordAtPoint(frame_widget, point,
                                                            baselinePoint);
  }

  std::unique_ptr<const mac::AttributedStringCoder::EncodedString> encoded(
      mac::AttributedStringCoder::Encode(string));
  Send(new TextInputClientReplyMsg_GotStringAtPoint(
      render_widget_->routing_id(), *encoded.get(), baselinePoint));
#else
  NOTIMPLEMENTED();
#endif
}

void TextInputClientObserver::OnCharacterIndexForPoint(gfx::Point point) {
  blink::WebPoint web_point(point);
  uint32_t index = 0U;
  if (auto* frame = GetFocusedFrame())
    index = static_cast<uint32_t>(frame->CharacterIndexForPoint(web_point));

  Send(new TextInputClientReplyMsg_GotCharacterIndexForPoint(
      render_widget_->routing_id(), index));
}

void TextInputClientObserver::OnFirstRectForCharacterRange(gfx::Range range) {
  gfx::Rect rect;
#if BUILDFLAG(ENABLE_PLUGINS)
  PepperPluginInstanceImpl* focused_plugin = GetFocusedPepperPlugin();
  if (focused_plugin) {
    rect = focused_plugin->GetCaretBounds();
  } else
#endif
  {
    blink::WebLocalFrame* frame = GetFocusedFrame();
    // TODO(yabinh): Null check should not be necessary.
    // See crbug.com/304341
    if (frame) {
      blink::WebRect web_rect;
      // When request range is invalid we will try to obtain it from current
      // frame selection. The fallback value will be 0.
      uint32_t start = range.IsValid() ? range.start()
                                       : GetCurrentCursorPositionInFrame(frame);
      frame->FirstRectForCharacterRange(start, range.length(), web_rect);
      rect = web_rect;
    }
  }
  Send(new TextInputClientReplyMsg_GotFirstRectForRange(
      render_widget_->routing_id(), rect));
}

void TextInputClientObserver::OnStringForRange(gfx::Range range) {
#if defined(OS_MACOSX)
  blink::WebPoint baselinePoint;
  NSAttributedString* string = nil;
  blink::WebLocalFrame* frame = GetFocusedFrame();
  // TODO(yabinh): Null check should not be necessary.
  // See crbug.com/304341
  if (frame) {
    string = blink::WebSubstringUtil::AttributedSubstringInRange(
        frame, range.start(), range.length(), &baselinePoint);
  }
  std::unique_ptr<const mac::AttributedStringCoder::EncodedString> encoded(
      mac::AttributedStringCoder::Encode(string));
  Send(new TextInputClientReplyMsg_GotStringForRange(
      render_widget_->routing_id(), *encoded.get(), baselinePoint));
#else
  NOTIMPLEMENTED();
#endif
}

}  // namespace content
