// 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/browser/renderer_host/render_widget_host_view_base.h"

#include "base/logging.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
#include "content/port/browser/smooth_scroll_gesture.h"
#include "third_party/WebKit/public/web/WebScreenInfo.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/size_f.h"

#if defined(OS_WIN)
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/win/wrapped_window_proc.h"
#include "content/browser/plugin_process_host.h"
#include "content/browser/plugin_service_impl.h"
#include "content/common/plugin_constants_win.h"
#include "content/common/webplugin_geometry.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/common/content_switches.h"
#include "ui/base/win/dpi.h"
#include "ui/base/win/hwnd_util.h"
#include "ui/gfx/gdi_util.h"
#endif

#if defined(TOOLKIT_GTK)
#include <gdk/gdkx.h>
#include <gtk/gtk.h>

#include "content/browser/renderer_host/gtk_window_utils.h"
#endif

namespace content {

// static
RenderWidgetHostViewPort* RenderWidgetHostViewPort::FromRWHV(
    RenderWidgetHostView* rwhv) {
  return static_cast<RenderWidgetHostViewPort*>(rwhv);
}

// static
RenderWidgetHostViewPort* RenderWidgetHostViewPort::CreateViewForWidget(
    RenderWidgetHost* widget) {
  return FromRWHV(RenderWidgetHostView::CreateViewForWidget(widget));
}

#if defined(OS_WIN)

namespace {

// |window| is the plugin HWND, created and destroyed in the plugin process.
// |parent| is the parent HWND, created and destroyed on the browser UI thread.
void NotifyPluginProcessHostHelper(HWND window, HWND parent, int tries) {
  // How long to wait between each try.
  static const int kTryDelayMs = 200;

  DWORD plugin_process_id;
  bool found_starting_plugin_process = false;
  GetWindowThreadProcessId(window, &plugin_process_id);
  for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
    if (!iter.GetData().handle) {
      found_starting_plugin_process = true;
      continue;
    }
    if (base::GetProcId(iter.GetData().handle) == plugin_process_id) {
      iter->AddWindow(parent);
      return;
    }
  }

  if (found_starting_plugin_process) {
    // A plugin process has started but we don't have its handle yet.  Since
    // it's most likely the one for this plugin, try a few more times after a
    // delay.
    if (tries > 0) {
      base::MessageLoop::current()->PostDelayedTask(
          FROM_HERE,
          base::Bind(&NotifyPluginProcessHostHelper, window, parent, tries - 1),
          base::TimeDelta::FromMilliseconds(kTryDelayMs));
      return;
    }
  }

  // The plugin process might have died in the time to execute the task, don't
  // leak the HWND.
  PostMessage(parent, WM_CLOSE, 0, 0);
}

// The plugin wrapper window which lives in the browser process has this proc
// as its window procedure. We only handle the WM_PARENTNOTIFY message sent by
// windowed plugins for mouse input. This is forwarded off to the wrappers
// parent which is typically the RVH window which turns on user gesture.
LRESULT CALLBACK PluginWrapperWindowProc(HWND window, unsigned int message,
                                         WPARAM wparam, LPARAM lparam) {
  if (message == WM_PARENTNOTIFY) {
    switch (LOWORD(wparam)) {
      case WM_LBUTTONDOWN:
      case WM_RBUTTONDOWN:
      case WM_MBUTTONDOWN:
        ::SendMessage(GetParent(window), message, wparam, lparam);
        return 0;
      default:
        break;
    }
  }
  return ::DefWindowProc(window, message, wparam, lparam);
}

bool IsPluginWrapperWindow(HWND window) {
  return ui::GetClassNameW(window) ==
      string16(kWrapperNativeWindowClassName);
}

// Create an intermediate window between the given HWND and its parent.
HWND ReparentWindow(HWND window, HWND parent) {
  static ATOM atom = 0;
  static HMODULE instance = NULL;
  if (!atom) {
    WNDCLASSEX window_class;
    base::win::InitializeWindowClass(
        kWrapperNativeWindowClassName,
        &base::win::WrappedWindowProc<PluginWrapperWindowProc>,
        CS_DBLCLKS,
        0,
        0,
        NULL,
        // xxx reinterpret_cast<HBRUSH>(COLOR_WINDOW+1),
        reinterpret_cast<HBRUSH>(COLOR_GRAYTEXT+1),
        NULL,
        NULL,
        NULL,
        &window_class);
    instance = window_class.hInstance;
    atom = RegisterClassEx(&window_class);
  }
  DCHECK(atom);

  HWND new_parent = CreateWindowEx(
      WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
      MAKEINTATOM(atom), 0,
      WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
      0, 0, 0, 0, parent, 0, instance, 0);
  ui::CheckWindowCreated(new_parent);
  ::SetParent(window, new_parent);
  // How many times we try to find a PluginProcessHost whose process matches
  // the HWND.
  static const int kMaxTries = 5;
  BrowserThread::PostTask(
      BrowserThread::IO,
      FROM_HERE,
      base::Bind(&NotifyPluginProcessHostHelper, window, new_parent,
                 kMaxTries));
  return new_parent;
}

BOOL CALLBACK PaintEnumChildProc(HWND hwnd, LPARAM lparam) {
  if (!PluginServiceImpl::GetInstance()->IsPluginWindow(hwnd))
    return TRUE;

  gfx::Rect* rect = reinterpret_cast<gfx::Rect*>(lparam);
  gfx::Rect rect_in_pixels = ui::win::DIPToScreenRect(*rect);
  static UINT msg = RegisterWindowMessage(kPaintMessageName);
  WPARAM wparam = MAKEWPARAM(rect_in_pixels.x(), rect_in_pixels.y());
  lparam = MAKELPARAM(rect_in_pixels.width(), rect_in_pixels.height());

  // SendMessage gets the message across much quicker than PostMessage, since it
  // doesn't get queued.  When the plugin thread calls PeekMessage or other
  // Win32 APIs, sent messages are dispatched automatically.
  SendNotifyMessage(hwnd, msg, wparam, lparam);

  return TRUE;
}

// Windows callback for OnDestroy to detach the plugin windows.
BOOL CALLBACK DetachPluginWindowsCallbackInternal(HWND window, LPARAM param) {
  RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
  return TRUE;
}

}  // namespace

// static
void RenderWidgetHostViewBase::DetachPluginWindowsCallback(HWND window) {
  if (PluginServiceImpl::GetInstance()->IsPluginWindow(window) &&
      !IsHungAppWindow(window)) {
    ::ShowWindow(window, SW_HIDE);
    SetParent(window, NULL);
  }
}

// static
void RenderWidgetHostViewBase::MovePluginWindowsHelper(
    HWND parent,
    const std::vector<WebPluginGeometry>& moves) {
  if (moves.empty())
    return;

  bool oop_plugins =
    !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) &&
    !CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessPlugins);

  HDWP defer_window_pos_info =
      ::BeginDeferWindowPos(static_cast<int>(moves.size()));

  if (!defer_window_pos_info) {
    NOTREACHED();
    return;
  }

#if defined(USE_AURA)
  std::vector<RECT> invalidate_rects;
#endif

  for (size_t i = 0; i < moves.size(); ++i) {
    unsigned long flags = 0;
    const WebPluginGeometry& move = moves[i];
    HWND window = move.window;

    // As the plugin parent window which lives on the browser UI thread is
    // destroyed asynchronously, it is possible that we have a stale window
    // sent in by the renderer for moving around.
    // Note: get the parent before checking if the window is valid, to avoid a
    // race condition where the window is destroyed after the check but before
    // the GetParent call.
    HWND cur_parent = ::GetParent(window);
    if (!::IsWindow(window))
      continue;

    if (!PluginServiceImpl::GetInstance()->IsPluginWindow(window)) {
      // The renderer should only be trying to move plugin windows. However,
      // this may happen as a result of a race condition (i.e. even after the
      // check right above), so we ignore it.
      continue;
    }

    if (oop_plugins) {
      if (cur_parent == GetDesktopWindow()) {
        // The plugin window hasn't been parented yet, add an intermediate
        // window that lives on this thread to speed up scrolling. Note this
        // only works with out of process plugins since we depend on
        // PluginProcessHost to destroy the intermediate HWNDs.
        cur_parent = ReparentWindow(window, parent);
        ::ShowWindow(window, SW_SHOW);  // Window was created hidden.
      } else if (!IsPluginWrapperWindow(cur_parent)) {
        continue;  // Race if plugin process is shutting down.
      }

      // We move the intermediate parent window which doesn't result in cross-
      // process synchronous Windows messages.
      window = cur_parent;
    } else {
      if (cur_parent == GetDesktopWindow())
        SetParent(window, parent);
    }

    if (move.visible)
      flags |= SWP_SHOWWINDOW;
    else
      flags |= SWP_HIDEWINDOW;

#if defined(USE_AURA)
    if (GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
      // Without this flag, Windows repaints the parent area uncovered by this
      // move. However when software compositing is used the clipping region is
      // ignored. Since in Aura the browser chrome could be under the plugin, if
      // if Windows tries to paint it synchronously inside EndDeferWindowsPos
      // then it won't have the data and it will flash white. So instead we
      // manually redraw the plugin.
      // Why not do this for native Windows? Not sure if there are any
      // performance issues with this.
      flags |= SWP_NOREDRAW;
    }
#endif

    if (move.rects_valid) {
      gfx::Rect clip_rect_in_pixel = ui::win::DIPToScreenRect(move.clip_rect);
      HRGN hrgn = ::CreateRectRgn(clip_rect_in_pixel.x(),
                                  clip_rect_in_pixel.y(),
                                  clip_rect_in_pixel.right(),
                                  clip_rect_in_pixel.bottom());
      gfx::SubtractRectanglesFromRegion(hrgn, move.cutout_rects);

      // Note: System will own the hrgn after we call SetWindowRgn,
      // so we don't need to call DeleteObject(hrgn)
      ::SetWindowRgn(window, hrgn, !move.clip_rect.IsEmpty());

#if defined(USE_AURA)
      // When using the software compositor, if the clipping rectangle is empty
      // then DeferWindowPos won't redraw the newly uncovered area under the
      // plugin.
      if (clip_rect_in_pixel.IsEmpty() &&
          !GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
        RECT r;
        GetClientRect(window, &r);
        MapWindowPoints(window, parent, reinterpret_cast<POINT*>(&r), 2);
        invalidate_rects.push_back(r);
      }
#endif
    } else {
      flags |= SWP_NOMOVE;
      flags |= SWP_NOSIZE;
    }

    gfx::Rect window_rect_in_pixel =
        ui::win::DIPToScreenRect(move.window_rect);
    defer_window_pos_info = ::DeferWindowPos(defer_window_pos_info,
                                             window, NULL,
                                             window_rect_in_pixel.x(),
                                             window_rect_in_pixel.y(),
                                             window_rect_in_pixel.width(),
                                             window_rect_in_pixel.height(),
                                             flags);

    if (!defer_window_pos_info) {
      DCHECK(false) << "DeferWindowPos failed, so all plugin moves ignored.";
      return;
    }
  }

  ::EndDeferWindowPos(defer_window_pos_info);

#if defined(USE_AURA)
  if (GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
    for (size_t i = 0; i < moves.size(); ++i) {
      const WebPluginGeometry& move = moves[i];
      RECT r;
      GetWindowRect(move.window, &r);
      gfx::Rect gr(r);
      PaintEnumChildProc(move.window, reinterpret_cast<LPARAM>(&gr));
    }
  } else {
      for (size_t i = 0; i < invalidate_rects.size(); ++i) {
      ::RedrawWindow(
          parent, &invalidate_rects[i], NULL,
          // These flags are from WebPluginDelegateImpl::NativeWndProc.
          RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_FRAME | RDW_UPDATENOW);
    }
  }
#endif
}

// static
void RenderWidgetHostViewBase::PaintPluginWindowsHelper(
    HWND parent, const gfx::Rect& damaged_screen_rect) {
  LPARAM lparam = reinterpret_cast<LPARAM>(&damaged_screen_rect);
  EnumChildWindows(parent, PaintEnumChildProc, lparam);
}

// static
void RenderWidgetHostViewBase::DetachPluginsHelper(HWND parent) {
  // When a tab is closed all its child plugin windows are destroyed
  // automatically. This happens before plugins get any notification that its
  // instances are tearing down.
  //
  // Plugins like Quicktime assume that their windows will remain valid as long
  // as they have plugin instances active. Quicktime crashes in this case
  // because its windowing code cleans up an internal data structure that the
  // handler for NPP_DestroyStream relies on.
  //
  // The fix is to detach plugin windows from web contents when it is going
  // away. This will prevent the plugin windows from getting destroyed
  // automatically. The detached plugin windows will get cleaned up in proper
  // sequence as part of the usual cleanup when the plugin instance goes away.
  EnumChildWindows(parent, DetachPluginWindowsCallbackInternal, NULL);
}

#endif  // OS_WIN

RenderWidgetHostViewBase::RenderWidgetHostViewBase()
    : popup_type_(WebKit::WebPopupTypeNone),
      mouse_locked_(false),
      showing_context_menu_(false),
      selection_text_offset_(0),
      selection_range_(ui::Range::InvalidRange()),
      current_device_scale_factor_(0),
      renderer_frame_number_(0) {
}

RenderWidgetHostViewBase::~RenderWidgetHostViewBase() {
  DCHECK(!mouse_locked_);
}

bool RenderWidgetHostViewBase::OnMessageReceived(const IPC::Message& msg){
  return false;
}

void RenderWidgetHostViewBase::SetBackground(const SkBitmap& background) {
  background_ = background;
}

const SkBitmap& RenderWidgetHostViewBase::GetBackground() {
  return background_;
}

gfx::Size RenderWidgetHostViewBase::GetPhysicalBackingSize() const {
  gfx::NativeView view = GetNativeView();
  gfx::Display display =
      gfx::Screen::GetScreenFor(view)->GetDisplayNearestWindow(view);
  return gfx::ToCeiledSize(gfx::ScaleSize(GetViewBounds().size(),
                                          display.device_scale_factor()));
}

float RenderWidgetHostViewBase::GetOverdrawBottomHeight() const {
  return 0.f;
}

void RenderWidgetHostViewBase::SelectionChanged(const string16& text,
                                                size_t offset,
                                                const ui::Range& range) {
  selection_text_ = text;
  selection_text_offset_ = offset;
  selection_range_.set_start(range.start());
  selection_range_.set_end(range.end());
}

bool RenderWidgetHostViewBase::IsShowingContextMenu() const {
  return showing_context_menu_;
}

void RenderWidgetHostViewBase::SetShowingContextMenu(bool showing) {
  DCHECK_NE(showing_context_menu_, showing);
  showing_context_menu_ = showing;
}

string16 RenderWidgetHostViewBase::GetSelectedText() const {
  if (!selection_range_.IsValid())
    return string16();
  return selection_text_.substr(
      selection_range_.GetMin() - selection_text_offset_,
      selection_range_.length());
}

bool RenderWidgetHostViewBase::IsMouseLocked() {
  return mouse_locked_;
}

void RenderWidgetHostViewBase::UnhandledWheelEvent(
    const WebKit::WebMouseWheelEvent& event) {
  // Most implementations don't need to do anything here.
}

InputEventAckState RenderWidgetHostViewBase::FilterInputEvent(
    const WebKit::WebInputEvent& input_event) {
  // By default, input events are simply forwarded to the renderer.
  return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}

void RenderWidgetHostViewBase::GestureEventAck(int gesture_event_type,
                                               InputEventAckState ack_result) {}

void RenderWidgetHostViewBase::SetPopupType(WebKit::WebPopupType popup_type) {
  popup_type_ = popup_type;
}

WebKit::WebPopupType RenderWidgetHostViewBase::GetPopupType() {
  return popup_type_;
}

BrowserAccessibilityManager*
    RenderWidgetHostViewBase::GetBrowserAccessibilityManager() const {
  return browser_accessibility_manager_.get();
}

void RenderWidgetHostViewBase::SetBrowserAccessibilityManager(
    BrowserAccessibilityManager* manager) {
  browser_accessibility_manager_.reset(manager);
}

void RenderWidgetHostViewBase::UpdateScreenInfo(gfx::NativeView view) {
  RenderWidgetHostImpl* impl = NULL;
  if (GetRenderWidgetHost())
    impl = RenderWidgetHostImpl::From(GetRenderWidgetHost());

  if (impl)
    impl->SendScreenRects();

  if (HasDisplayPropertyChanged(view) && impl)
    impl->NotifyScreenInfoChanged();
}

bool RenderWidgetHostViewBase::HasDisplayPropertyChanged(gfx::NativeView view) {
  gfx::Display display =
      gfx::Screen::GetScreenFor(view)->GetDisplayNearestWindow(view);
  if (current_display_area_ == display.work_area() &&
      current_device_scale_factor_ == display.device_scale_factor()) {
    return false;
  }
  current_display_area_ = display.work_area();
  current_device_scale_factor_ = display.device_scale_factor();
  return true;
}

SmoothScrollGesture* RenderWidgetHostViewBase::CreateSmoothScrollGesture(
    bool scroll_down, int pixels_to_scroll, int mouse_event_x,
    int mouse_event_y) {
  return new BasicMouseWheelSmoothScrollGesture(scroll_down, pixels_to_scroll,
                                                mouse_event_x, mouse_event_y);
}

void RenderWidgetHostViewBase::ProcessAckedTouchEvent(
    const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
}

// Platform implementation should override this method to allow frame
// subscription. Frame subscriber is set to RenderProcessHost, which is
// platform independent. It should be set to the specific presenter on each
// platform.
bool RenderWidgetHostViewBase::CanSubscribeFrame() const {
  NOTIMPLEMENTED();
  return false;
}

// Base implementation for this method sets the subscriber to RenderProcessHost,
// which is platform independent. Note: Implementation only support subscribing
// to accelerated composited frames.
void RenderWidgetHostViewBase::BeginFrameSubscription(
    scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
  RenderWidgetHostImpl* impl = NULL;
  if (GetRenderWidgetHost())
    impl = RenderWidgetHostImpl::From(GetRenderWidgetHost());
  if (!impl)
    return;
  RenderProcessHostImpl* render_process_host =
      static_cast<RenderProcessHostImpl*>(impl->GetProcess());
  render_process_host->BeginFrameSubscription(impl->GetRoutingID(),
                                              subscriber.Pass());
}

void RenderWidgetHostViewBase::EndFrameSubscription() {
  RenderWidgetHostImpl* impl = NULL;
  if (GetRenderWidgetHost())
    impl = RenderWidgetHostImpl::From(GetRenderWidgetHost());
  if (!impl)
    return;
  RenderProcessHostImpl* render_process_host =
      static_cast<RenderProcessHostImpl*>(impl->GetProcess());
  render_process_host->EndFrameSubscription(impl->GetRoutingID());
}

void RenderWidgetHostViewBase::OnOverscrolled(
    gfx::Vector2dF accumulated_overscroll,
    gfx::Vector2dF current_fling_velocity) {
}

uint32 RenderWidgetHostViewBase::RendererFrameNumber() {
  return renderer_frame_number_;
}

void RenderWidgetHostViewBase::DidReceiveRendererFrame() {
  ++renderer_frame_number_;
}

}  // namespace content
