/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "web/WebPagePopupImpl.h"

#include "core/dom/ContextFeatures.h"
#include "core/events/MessageEvent.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/VisualViewport.h"
#include "core/input/EventHandler.h"
#include "core/layout/api/LayoutAPIShim.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/loader/EmptyClients.h"
#include "core/loader/FrameLoadRequest.h"
#include "core/page/FocusController.h"
#include "core/page/Page.h"
#include "core/page/PagePopupClient.h"
#include "core/page/PagePopupSupplement.h"
#include "modules/accessibility/AXObject.h"
#include "modules/accessibility/AXObjectCacheImpl.h"
#include "platform/EventDispatchForbiddenScope.h"
#include "platform/LayoutTestSupport.h"
#include "platform/ScriptForbiddenScope.h"
#include "platform/heap/Handle.h"
#include "platform/tracing/TraceEvent.h"
#include "public/platform/WebCompositeAndReadbackAsyncCallback.h"
#include "public/platform/WebCursorInfo.h"
#include "public/web/WebAXObject.h"
#include "public/web/WebFrameClient.h"
#include "public/web/WebViewClient.h"
#include "public/web/WebWidgetClient.h"
#include "web/WebInputEventConversion.h"
#include "web/WebLocalFrameImpl.h"
#include "web/WebSettingsImpl.h"
#include "web/WebViewImpl.h"
#include "wtf/PtrUtil.h"

namespace blink {

class PagePopupChromeClient final : public EmptyChromeClient {
 public:
  static PagePopupChromeClient* create(WebPagePopupImpl* popup) {
    return new PagePopupChromeClient(popup);
  }

  void setWindowRect(const IntRect& rect, LocalFrame&) override {
    m_popup->setWindowRect(rect);
  }

 private:
  explicit PagePopupChromeClient(WebPagePopupImpl* popup) : m_popup(popup) {
    DCHECK(m_popup->widgetClient());
  }

  void closeWindowSoon() override { m_popup->closePopup(); }

  IntRect rootWindowRect() override { return m_popup->windowRectInScreen(); }

  IntRect viewportToScreen(const IntRect& rect,
                           const Widget* widget) const override {
    WebRect rectInScreen(rect);
    WebRect windowRect = m_popup->windowRectInScreen();
    m_popup->widgetClient()->convertViewportToWindow(&rectInScreen);
    rectInScreen.x += windowRect.x;
    rectInScreen.y += windowRect.y;
    return rectInScreen;
  }

  void addMessageToConsole(LocalFrame*,
                           MessageSource,
                           MessageLevel,
                           const String& message,
                           unsigned lineNumber,
                           const String&,
                           const String&) override {
#ifndef NDEBUG
    fprintf(stderr, "CONSOLE MESSSAGE:%u: %s\n", lineNumber,
            message.utf8().data());
#endif
  }

  void invalidateRect(const IntRect& paintRect) override {
    if (!paintRect.isEmpty())
      m_popup->widgetClient()->didInvalidateRect(paintRect);
  }

  void scheduleAnimation(Widget*) override {
    // Calling scheduleAnimation on m_webView so WebViewTestProxy will call
    // beginFrame.
    if (LayoutTestSupport::isRunningLayoutTest())
      m_popup->m_webView->mainFrameImpl()->frameWidget()->scheduleAnimation();

    if (m_popup->isAcceleratedCompositingActive()) {
      DCHECK(m_popup->m_layerTreeView);
      m_popup->m_layerTreeView->setNeedsBeginFrame();
      return;
    }
    m_popup->m_widgetClient->scheduleAnimation();
  }

  void attachCompositorAnimationTimeline(CompositorAnimationTimeline* timeline,
                                         LocalFrame*) override {
    if (m_popup->m_layerTreeView)
      m_popup->m_layerTreeView->attachCompositorAnimationTimeline(
          timeline->animationTimeline());
  }

  void detachCompositorAnimationTimeline(CompositorAnimationTimeline* timeline,
                                         LocalFrame*) override {
    if (m_popup->m_layerTreeView)
      m_popup->m_layerTreeView->detachCompositorAnimationTimeline(
          timeline->animationTimeline());
  }

  WebScreenInfo screenInfo() const override {
    return m_popup->m_webView->client()
               ? m_popup->m_webView->client()->screenInfo()
               : WebScreenInfo();
  }

  void* webView() const override { return m_popup->m_webView; }

  IntSize minimumWindowSize() const override { return IntSize(0, 0); }

  void setCursor(const Cursor& cursor, LocalFrame* localFrame) override {
    m_popup->m_widgetClient->didChangeCursor(WebCursorInfo(cursor));
  }

  void setEventListenerProperties(
      WebEventListenerClass eventClass,
      WebEventListenerProperties properties) override {
    if (m_popup->m_layerTreeView) {
      m_popup->m_layerTreeView->setEventListenerProperties(eventClass,
                                                           properties);
      if (eventClass == WebEventListenerClass::TouchStartOrMove) {
        m_popup->widgetClient()->hasTouchEventHandlers(
            properties != WebEventListenerProperties::Nothing ||
            eventListenerProperties(WebEventListenerClass::TouchEndOrCancel) !=
                WebEventListenerProperties::Nothing);
      } else if (eventClass == WebEventListenerClass::TouchEndOrCancel) {
        m_popup->widgetClient()->hasTouchEventHandlers(
            properties != WebEventListenerProperties::Nothing ||
            eventListenerProperties(WebEventListenerClass::TouchStartOrMove) !=
                WebEventListenerProperties::Nothing);
      }
    } else {
      m_popup->widgetClient()->hasTouchEventHandlers(true);
    }
  }
  WebEventListenerProperties eventListenerProperties(
      WebEventListenerClass eventClass) const override {
    if (m_popup->m_layerTreeView)
      return m_popup->m_layerTreeView->eventListenerProperties(eventClass);
    return WebEventListenerProperties::Nothing;
  }

  void setHasScrollEventHandlers(bool hasEventHandlers) override {
    if (m_popup->m_layerTreeView)
      m_popup->m_layerTreeView->setHaveScrollEventHandlers(hasEventHandlers);
  }

  bool hasScrollEventHandlers() const override {
    if (m_popup->m_layerTreeView)
      return m_popup->m_layerTreeView->haveScrollEventHandlers();
    return false;
  }

  void setTouchAction(TouchAction touchAction) override {
    if (WebViewClient* client = m_popup->m_webView->client())
      client->setTouchAction(static_cast<WebTouchAction>(touchAction));
  }

  void attachRootGraphicsLayer(GraphicsLayer* graphicsLayer,
                               LocalFrame* localRoot) override {
    m_popup->setRootGraphicsLayer(graphicsLayer);
  }

  void postAccessibilityNotification(
      AXObject* obj,
      AXObjectCache::AXNotification notification) override {
    WebLocalFrameImpl* frame = WebLocalFrameImpl::fromFrame(
        m_popup->m_popupClient->ownerElement().document().frame());
    if (obj && frame && frame->client())
      frame->client()->postAccessibilityEvent(
          WebAXObject(obj), static_cast<WebAXEvent>(notification));
  }

  void setToolTip(LocalFrame&,
                  const String& tooltipText,
                  TextDirection dir) override {
    if (m_popup->widgetClient())
      m_popup->widgetClient()->setToolTipText(tooltipText,
                                              toWebTextDirection(dir));
  }

  WebPagePopupImpl* m_popup;
};

class PagePopupFeaturesClient : public ContextFeaturesClient {
  bool isEnabled(Document*, ContextFeatures::FeatureType, bool) override;
};

bool PagePopupFeaturesClient::isEnabled(Document*,
                                        ContextFeatures::FeatureType type,
                                        bool defaultValue) {
  if (type == ContextFeatures::PagePopup)
    return true;
  return defaultValue;
}

// WebPagePopupImpl ----------------------------------------------------------

WebPagePopupImpl::WebPagePopupImpl(WebWidgetClient* client)
    : m_widgetClient(client),
      m_closing(false),
      m_layerTreeView(0),
      m_rootLayer(0),
      m_rootGraphicsLayer(0),
      m_isAcceleratedCompositingActive(false) {
  DCHECK(client);
}

WebPagePopupImpl::~WebPagePopupImpl() {
  DCHECK(!m_page);
}

bool WebPagePopupImpl::initialize(WebViewImpl* webView,
                                  PagePopupClient* popupClient) {
  DCHECK(webView);
  DCHECK(popupClient);
  m_webView = webView;
  m_popupClient = popupClient;

  if (!m_widgetClient || !initializePage())
    return false;
  m_widgetClient->show(WebNavigationPolicy());
  setFocus(true);

  return true;
}

bool WebPagePopupImpl::initializePage() {
  Page::PageClients pageClients;
  fillWithEmptyClients(pageClients);
  m_chromeClient = PagePopupChromeClient::create(this);
  pageClients.chromeClient = m_chromeClient.get();

  Settings& mainSettings = m_webView->page()->settings();
  m_page = Page::create(pageClients);
  m_page->settings().setScriptEnabled(true);
  m_page->settings().setAllowScriptsToCloseWindows(true);
  m_page->settings().setDeviceSupportsTouch(mainSettings.deviceSupportsTouch());
  m_page->settings().setMinimumFontSize(mainSettings.minimumFontSize());
  m_page->settings().setMinimumLogicalFontSize(
      mainSettings.minimumLogicalFontSize());
  // FIXME: Should we support enabling a11y while a popup is shown?
  m_page->settings().setAccessibilityEnabled(
      mainSettings.accessibilityEnabled());
  m_page->settings().setScrollAnimatorEnabled(
      mainSettings.scrollAnimatorEnabled());

  provideContextFeaturesTo(*m_page, wrapUnique(new PagePopupFeaturesClient()));
  DEFINE_STATIC_LOCAL(FrameLoaderClient, emptyFrameLoaderClient,
                      (EmptyFrameLoaderClient::create()));
  LocalFrame* frame =
      LocalFrame::create(&emptyFrameLoaderClient, &m_page->frameHost(), 0);
  frame->setPagePopupOwner(m_popupClient->ownerElement());
  frame->setView(FrameView::create(frame));
  frame->init();
  frame->view()->setParentVisible(true);
  frame->view()->setSelfVisible(true);
  frame->view()->setTransparent(false);
  if (AXObjectCache* cache =
          m_popupClient->ownerElement().document().existingAXObjectCache())
    cache->childrenChanged(&m_popupClient->ownerElement());

  DCHECK(frame->localDOMWindow());
  PagePopupSupplement::install(*frame, *this, m_popupClient);
  DCHECK_EQ(m_popupClient->ownerElement().document().existingAXObjectCache(),
            frame->document()->existingAXObjectCache());

  RefPtr<SharedBuffer> data = SharedBuffer::create();
  m_popupClient->writeDocument(data.get());
  frame->loader().load(FrameLoadRequest(
      0, blankURL(), SubstituteData(data, "text/html", "UTF-8", KURL(),
                                    ForceSynchronousLoad)));
  frame->setPageZoomFactor(m_popupClient->zoomFactor());
  return true;
}

void WebPagePopupImpl::postMessage(const String& message) {
  if (!m_page)
    return;
  ScriptForbiddenScope::AllowUserAgentScript allowScript;
  if (LocalDOMWindow* window =
          toLocalFrame(m_page->mainFrame())->localDOMWindow())
    window->dispatchEvent(MessageEvent::create(message));
}

void WebPagePopupImpl::destroyPage() {
  if (!m_page)
    return;

  m_page->willBeDestroyed();
  m_page.clear();
}

AXObject* WebPagePopupImpl::rootAXObject() {
  if (!m_page || !m_page->mainFrame())
    return 0;
  Document* document = toLocalFrame(m_page->mainFrame())->document();
  if (!document)
    return 0;
  AXObjectCache* cache = document->axObjectCache();
  DCHECK(cache);
  return toAXObjectCacheImpl(cache)->getOrCreate(toLayoutView(
      LayoutAPIShim::layoutObjectFrom(document->layoutViewItem())));
}

void WebPagePopupImpl::setWindowRect(const IntRect& rectInScreen) {
  widgetClient()->setWindowRect(rectInScreen);
}

void WebPagePopupImpl::setRootGraphicsLayer(GraphicsLayer* layer) {
  m_rootGraphicsLayer = layer;
  m_rootLayer = layer ? layer->platformLayer() : 0;

  setIsAcceleratedCompositingActive(layer);
  if (m_layerTreeView) {
    if (m_rootLayer) {
      m_layerTreeView->setRootLayer(*m_rootLayer);
    } else {
      m_layerTreeView->clearRootLayer();
    }
  }
}

void WebPagePopupImpl::setIsAcceleratedCompositingActive(bool enter) {
  if (m_isAcceleratedCompositingActive == enter)
    return;

  if (!enter) {
    m_isAcceleratedCompositingActive = false;
  } else if (m_layerTreeView) {
    m_isAcceleratedCompositingActive = true;
  } else {
    TRACE_EVENT0("blink",
                 "WebPagePopupImpl::setIsAcceleratedCompositingActive(true)");

    m_widgetClient->initializeLayerTreeView();
    m_layerTreeView = m_widgetClient->layerTreeView();
    if (m_layerTreeView) {
      m_layerTreeView->setVisible(true);
      m_isAcceleratedCompositingActive = true;
      m_page->layerTreeViewInitialized(*m_layerTreeView);
    } else {
      m_isAcceleratedCompositingActive = false;
    }
  }
}

void WebPagePopupImpl::beginFrame(double lastFrameTimeMonotonic) {
  if (!m_page)
    return;
  // FIXME: This should use lastFrameTimeMonotonic but doing so
  // breaks tests.
  PageWidgetDelegate::animate(*m_page, monotonicallyIncreasingTime());
}

void WebPagePopupImpl::willCloseLayerTreeView() {
  if (m_page && m_layerTreeView)
    m_page->willCloseLayerTreeView(*m_layerTreeView);

  setIsAcceleratedCompositingActive(false);
  m_layerTreeView = 0;
}

void WebPagePopupImpl::updateAllLifecyclePhases() {
  if (!m_page)
    return;
  PageWidgetDelegate::updateAllLifecyclePhases(
      *m_page, *m_page->deprecatedLocalMainFrame());
}

void WebPagePopupImpl::paint(WebCanvas* canvas, const WebRect& rect) {
  if (!m_closing)
    PageWidgetDelegate::paint(*m_page, canvas, rect,
                              *m_page->deprecatedLocalMainFrame());
}

void WebPagePopupImpl::resize(const WebSize& newSizeInViewport) {
  WebRect newSize(0, 0, newSizeInViewport.width, newSizeInViewport.height);
  widgetClient()->convertViewportToWindow(&newSize);

  WebRect windowRect = windowRectInScreen();

  // TODO(bokan): We should only call into this if the bounds actually changed
  // but this reveals a bug in Aura. crbug.com/633140.
  windowRect.width = newSize.width;
  windowRect.height = newSize.height;
  setWindowRect(windowRect);

  if (m_page) {
    toLocalFrame(m_page->mainFrame())->view()->resize(newSizeInViewport);
    m_page->frameHost().visualViewport().setSize(newSizeInViewport);
  }

  m_widgetClient->didInvalidateRect(
      WebRect(0, 0, newSize.width, newSize.height));
}

WebInputEventResult WebPagePopupImpl::handleKeyEvent(
    const WebKeyboardEvent& event) {
  if (m_closing || !m_page->mainFrame() ||
      !toLocalFrame(m_page->mainFrame())->view())
    return WebInputEventResult::NotHandled;
  return toLocalFrame(m_page->mainFrame())->eventHandler().keyEvent(event);
}

WebInputEventResult WebPagePopupImpl::handleCharEvent(
    const WebKeyboardEvent& event) {
  return handleKeyEvent(event);
}

WebInputEventResult WebPagePopupImpl::handleGestureEvent(
    const WebGestureEvent& event) {
  if (m_closing || !m_page || !m_page->mainFrame() ||
      !toLocalFrame(m_page->mainFrame())->view())
    return WebInputEventResult::NotHandled;
  if (event.type == WebInputEvent::GestureTap &&
      !isViewportPointInWindow(event.x, event.y)) {
    cancel();
    return WebInputEventResult::NotHandled;
  }
  LocalFrame& frame = *toLocalFrame(m_page->mainFrame());
  return frame.eventHandler().handleGestureEvent(
      PlatformGestureEventBuilder(frame.view(), event));
}

void WebPagePopupImpl::handleMouseDown(LocalFrame& mainFrame,
                                       const WebMouseEvent& event) {
  if (isViewportPointInWindow(event.x, event.y))
    PageWidgetEventHandler::handleMouseDown(mainFrame, event);
  else
    cancel();
}

WebInputEventResult WebPagePopupImpl::handleMouseWheel(
    LocalFrame& mainFrame,
    const WebMouseWheelEvent& event) {
  if (isViewportPointInWindow(event.x, event.y))
    return PageWidgetEventHandler::handleMouseWheel(mainFrame, event);
  cancel();
  return WebInputEventResult::NotHandled;
}

bool WebPagePopupImpl::isViewportPointInWindow(int x, int y) {
  WebRect pointInWindow(x, y, 0, 0);
  widgetClient()->convertViewportToWindow(&pointInWindow);
  WebRect windowRect = windowRectInScreen();
  return IntRect(0, 0, windowRect.width, windowRect.height)
      .contains(IntPoint(pointInWindow.x, pointInWindow.y));
}

WebInputEventResult WebPagePopupImpl::handleInputEvent(
    const WebInputEvent& event) {
  if (m_closing)
    return WebInputEventResult::NotHandled;
  return PageWidgetDelegate::handleInputEvent(
      *this, event, m_page->deprecatedLocalMainFrame());
}

void WebPagePopupImpl::setFocus(bool enable) {
  if (!m_page)
    return;
  m_page->focusController().setFocused(enable);
  if (enable)
    m_page->focusController().setActive(true);
}

void WebPagePopupImpl::close() {
  m_closing = true;
  // In case closePopup() was not called.
  if (m_page)
    cancel();
  m_widgetClient = nullptr;
  deref();
}

void WebPagePopupImpl::closePopup() {
  {
    // This function can be called in EventDispatchForbiddenScope for the main
    // document, and the following operations dispatch some events.  It's safe
    // because web authors can't listen the events.
    EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents;

    if (m_page) {
      toLocalFrame(m_page->mainFrame())->loader().stopAllLoaders();
      PagePopupSupplement::uninstall(*toLocalFrame(m_page->mainFrame()));
    }
    bool closeAlreadyCalled = m_closing;
    m_closing = true;

    destroyPage();

    // m_widgetClient might be 0 because this widget might be already closed.
    if (m_widgetClient && !closeAlreadyCalled) {
      // closeWidgetSoon() will call this->close() later.
      m_widgetClient->closeWidgetSoon();
    }
  }
  m_popupClient->didClosePopup();
  m_webView->cleanupPagePopup();
}

LocalDOMWindow* WebPagePopupImpl::window() {
  return m_page->deprecatedLocalMainFrame()->localDOMWindow();
}

void WebPagePopupImpl::layoutAndPaintAsync(
    WebLayoutAndPaintAsyncCallback* callback) {
  m_layerTreeView->layoutAndPaintAsync(callback);
}

void WebPagePopupImpl::compositeAndReadbackAsync(
    WebCompositeAndReadbackAsyncCallback* callback) {
  DCHECK(isAcceleratedCompositingActive());
  m_layerTreeView->compositeAndReadbackAsync(callback);
}

WebPoint WebPagePopupImpl::positionRelativeToOwner() {
  WebRect rootWindowRect = m_webView->client()->rootWindowRect();
  WebRect windowRect = windowRectInScreen();
  return WebPoint(windowRect.x - rootWindowRect.x,
                  windowRect.y - rootWindowRect.y);
}

void WebPagePopupImpl::cancel() {
  if (m_popupClient)
    m_popupClient->closePopup();
}

WebRect WebPagePopupImpl::windowRectInScreen() const {
  return widgetClient()->windowRect();
}

// WebPagePopup ----------------------------------------------------------------

WebPagePopup* WebPagePopup::create(WebWidgetClient* client) {
  if (!client)
    CRASH();
  // A WebPagePopupImpl instance usually has two references.
  //  - One owned by the instance itself. It represents the visible widget.
  //  - One owned by a WebViewImpl. It's released when the WebViewImpl ask the
  //    WebPagePopupImpl to close.
  // We need them because the closing operation is asynchronous and the widget
  // can be closed while the WebViewImpl is unaware of it.
  return adoptRef(new WebPagePopupImpl(client)).leakRef();
}

}  // namespace blink
