/*
 * 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.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_PAGE_POPUP_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_PAGE_POPUP_IMPL_H_

#include "base/macros.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "third_party/blink/public/mojom/input/pointer_lock_context.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/input/pointer_lock_result.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/page/widget.mojom-blink.h"
#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
#include "third_party/blink/public/web/web_page_popup.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/frame/web_feature_forward.h"
#include "third_party/blink/renderer/core/page/page_popup.h"
#include "third_party/blink/renderer/core/page/page_widget_delegate.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/widget/widget_base_client.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"

namespace cc {
class Layer;
}

namespace blink {
class Element;
class Node;
class Page;
class PagePopupChromeClient;
class PagePopupClient;
class WebViewImpl;
class LocalDOMWindow;
class WidgetBase;
class DOMRect;

class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
                                           public PageWidgetEventHandler,
                                           public PagePopup,
                                           public RefCounted<WebPagePopupImpl>,
                                           public WidgetBaseClient {
  USING_FAST_MALLOC(WebPagePopupImpl);

 public:
  ~WebPagePopupImpl() override;

  void Initialize(WebViewImpl*, PagePopupClient*);

  // Cancel informs the PopupClient that it should initiate shutdown of this
  // popup via ClosePopup(). It is called to indicate the popup was closed due
  // to a user gesture outside the popup or other such reasons, where a default
  // cancelled response can be made.
  //
  // When the user chooses a value in the popup and thus it is closed, or if the
  // origin in the DOM disppears, then the Cancel() step would be skipped and go
  // directly to ClosePopup().
  void Cancel();
  // Once ClosePopup() has been called, the WebPagePopupImpl should be disowned
  // by any clients, and will be reaped when then browser closes its
  // RenderWidget which closes this object. This will call back to the
  // PopupClient to say DidClosePopup(), and to the WebViewImpl to cleanup
  // its reference to the popup.
  //
  // Only HasSamePopupClient() may still be called after ClosePopup() runs.
  void ClosePopup();

  // Returns whether another WebPagePopupImpl has the same PopupClient as this
  // instance. May be called after ClosePopup() has run still, in order to
  // determine if a popup sharing the same client was created immediately after
  // closing one.
  bool HasSamePopupClient(WebPagePopupImpl* other) {
    return other && popup_client_ == other->popup_client_;
  }

  LocalDOMWindow* Window();

  // WebPagePopup implementation.
  WebDocument GetDocument() override;
  void InitializeForTesting(WebView* view) override;

  // PagePopup implementation.
  void PostMessageToPopup(const String& message) override;
  void Update() override;

  // PageWidgetEventHandler implementation.
  WebInputEventResult HandleKeyEvent(const WebKeyboardEvent&) override;

  // Return the LayerTreeHost backing this popup widget.
  cc::LayerTreeHost* LayerTreeHostForTesting();

 private:
  // WidgetBaseClient overrides:
  void BeginMainFrame(base::TimeTicks last_frame_time) override;
  void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final;
  WebInputEventResult DispatchBufferedTouchEvents() override;
  bool WillHandleGestureEvent(const WebGestureEvent& event) override;
  void WillHandleMouseEvent(const WebMouseEvent& event) override;
  void ObserveGestureEventAndResult(
      const WebGestureEvent& gesture_event,
      const gfx::Vector2dF& unused_delta,
      const cc::OverscrollBehavior& overscroll_behavior,
      bool event_processed) override;
  bool SupportsBufferedTouchEvents() override { return true; }
  void FocusChanged(bool enabled) override;
  void ScheduleAnimation() override;
  void UpdateVisualProperties(
      const VisualProperties& visual_properties) override;
  const ScreenInfo& GetOriginalScreenInfo() override;
  gfx::Rect ViewportVisibleRect() override;
  void ScreenRectToEmulated(gfx::Rect& screen_rect) override;
  void EmulatedToScreenRect(gfx::Rect& screen_rect) override;
  KURL GetURLForDebugTrace() override;
  std::unique_ptr<cc::LayerTreeFrameSink> AllocateNewLayerTreeFrameSink()
      override;

  // WebWidget implementation.
  // NOTE: The WebWidget may still be used after requesting the popup to be
  // closed and destroyed. But the Page and the MainFrame are destroyed
  // immediately. So all methods (outside of initialization) that are part
  // of the WebWidget need to check if close has already been initiated (they
  // can do so by checking |page_|) and not crash! https://crbug.com/906340
  void SetCompositorVisible(bool visible) override;
  void UpdateLifecycle(WebLifecycleUpdate requested_update,
                       DocumentUpdateReason reason) override;
  void Resize(const gfx::Size&) override;
  void Close() override;
  WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override;
  void SetFocus(bool) override;
  bool HasFocus() override;
  WebHitTestResult HitTestResultAt(const gfx::PointF&) override { return {}; }
  void InitializeCompositing(
      scheduler::WebAgentGroupScheduler& agent_group_scheduler,
      cc::TaskGraphRunner* task_graph_runner,
      const ScreenInfo& screen_info,
      std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory,
      const cc::LayerTreeSettings* settings) override;
  scheduler::WebRenderWidgetSchedulingState* RendererWidgetSchedulingState()
      override;
  void SetCursor(const ui::Cursor& cursor) override;
  bool HandlingInputEvent() override;
  void SetHandlingInputEvent(bool handling) override;
  void ProcessInputEventSynchronouslyForTesting(const WebCoalescedInputEvent&,
                                                HandledEventCallback) override;
  void UpdateTextInputState() override;
  void UpdateSelectionBounds() override;
  void ShowVirtualKeyboard() override;
  void FlushInputProcessedCallback() override;
  void CancelCompositionForPepper() override;

  // PageWidgetEventHandler functions
  WebInputEventResult HandleCharEvent(const WebKeyboardEvent&) override;
  WebInputEventResult HandleGestureEvent(const WebGestureEvent&) override;
  void HandleMouseDown(LocalFrame& main_frame, const WebMouseEvent&) override;
  WebInputEventResult HandleMouseWheel(LocalFrame& main_frame,
                                       const WebMouseWheelEvent&) override;
  void ApplyVisualProperties(
      const VisualProperties& visual_properties) override;
  const ScreenInfo& GetScreenInfo() override;
  gfx::Rect WindowRect() override;
  gfx::Rect ViewRect() override;
  void SetScreenRects(const gfx::Rect& widget_screen_rect,
                      const gfx::Rect& window_screen_rect) override;
  gfx::Size VisibleViewportSizeInDIPs() override;
  bool IsHidden() const override;

  // This may only be called if page_ is non-null.
  LocalFrame& MainFrame() const;

  Element* FocusedElement() const;

  bool IsViewportPointInWindow(int x, int y);
  void CheckScreenPointInOwnerWindowAndCount(const gfx::PointF& point_in_screen,
                                             WebFeature feature) const;
  IntRect OwnerWindowRectInScreen() const;

  // PagePopup function
  AXObject* RootAXObject() override;
  void SetWindowRect(const IntRect&) override;

  WebPagePopupImpl(
      CrossVariantMojoAssociatedRemote<
          mojom::blink::PopupWidgetHostInterfaceBase> popup_widget_host,
      CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
          widget_host,
      CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
          widget,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
  void DestroyPage();
  void SetRootLayer(scoped_refptr<cc::Layer>);
  void SetWebView(WebViewImpl* web_view);

  gfx::Rect WindowRectInScreen() const;

  void InjectGestureScrollEvent(WebGestureDevice device,
                                const gfx::Vector2dF& delta,
                                ui::ScrollGranularity granularity,
                                cc::ElementId scrollable_area_element_id,
                                WebInputEvent::Type injected_type);

  void WidgetHostDisconnected();
  void DidShowPopup();
  void DidSetBounds();

  // This is the WebView that opened the popup.
  WebViewImpl* opener_web_view_ = nullptr;
  // WebPagePopupImpl wraps its own Page that renders the content in the popup.
  // This member is non-null between the call to Initialize() and the call to
  // ClosePopup(). If page_ is non-null, it is guaranteed to have an attached
  // main LocalFrame with a corresponding non-null LocalFrameView and non-null
  // Document.
  Persistent<Page> page_;
  Persistent<PagePopupChromeClient> chrome_client_;
  PagePopupClient* popup_client_;
  bool closing_ = false;

  scoped_refptr<cc::Layer> root_layer_;
  base::TimeTicks raf_aligned_input_start_time_;

  bool suppress_next_keypress_event_ = false;
  Persistent<DOMRect> popup_owner_client_rect_;

  // When emulation is enabled, and a popup widget is opened, the popup widget
  // needs these values to move between the popup's (non-emulated) coordinates
  // and the opener widget's (emulated) coordinates. They are only valid when
  // the |opener_emulator_scale_| is non-zero.
  gfx::Point opener_widget_screen_origin_;
  gfx::Point opener_original_widget_screen_origin_;
  float opener_emulator_scale_ = 0;

  // The channel associated with the browser. When this is closed the popup will
  // be destroyed.
  mojo::AssociatedRemote<mojom::blink::PopupWidgetHost> popup_widget_host_;

  // The rect before the widget is shown.
  gfx::Rect initial_rect_;

  // Defer setting the window rect until the widget is shown.
  bool should_defer_setting_window_rect_ = true;

  // Base functionality all widgets have. This is a member as to avoid
  // complicated inheritance structures.
  std::unique_ptr<WidgetBase> widget_base_;

  // Only used for Scroll Unification.
  // Will be set in GestureScrollBegin
  WeakPersistent<Node> scrollable_node_;

  friend class WebPagePopup;
  friend class PagePopupChromeClient;

  DISALLOW_COPY_AND_ASSIGN(WebPagePopupImpl);
};

// WebPagePopupImpl is the only implementation of WebPagePopup and PagePopup, so
// no further checking required.
template <>
struct DowncastTraits<WebPagePopupImpl> {
  static bool AllowFrom(const WebPagePopup& widget) { return true; }
  static bool AllowFrom(const PagePopup& popup) { return true; }
};

}  // namespace blink
#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_PAGE_POPUP_IMPL_H_
