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

// A BrowserPluginEmbedder handles messages coming from a BrowserPlugin's
// embedder that are not directed at any particular existing guest process.
// In the beginning, when a BrowserPlugin instance in the embedder renderer
// process requests an initial navigation, the WebContents for that renderer
// renderer creates a BrowserPluginEmbedder for itself. The
// BrowserPluginEmbedder, in turn, forwards the requests to a
// BrowserPluginGuestManager, which creates and manages the lifetime of the new
// guest.

#ifndef CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_EMBEDDER_H_
#define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_EMBEDDER_H_

#include "base/memory/weak_ptr.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"

struct BrowserPluginHostMsg_Attach_Params;

namespace content {

class BrowserPluginGuest;
class BrowserPluginGuestManager;
class RenderWidgetHostImpl;
struct NativeWebKeyboardEvent;

class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
 public:
  ~BrowserPluginEmbedder() override;

  static BrowserPluginEmbedder* Create(WebContentsImpl* web_contents);

  // Called when embedder's |rwh| has sent screen rects to renderer.
  void DidSendScreenRects();

  // WebContentsObserver implementation.
  bool OnMessageReceived(const IPC::Message& message) override;
  bool OnMessageReceived(const IPC::Message& message,
                         RenderFrameHost* render_frame_host) override;

  // Sends a 'dragend' message to the guest that started the drag.
  void DragSourceEndedAt(int client_x, int client_y, int screen_x,
      int screen_y, blink::WebDragOperation operation);

  // Indicates that a drag operation has entered into the bounds of a given
  // |guest|. Returns whether the |guest| also started the operation.
  bool DragEnteredGuest(BrowserPluginGuest* guest);

  // Indicates that a drag operation has left the bounds of a given |guest|.
  void DragLeftGuest(BrowserPluginGuest* guest);

  // Called when the screen info has changed.
  void ScreenInfoChanged();

  // Closes modal dialogs in all of the guests.
  void CancelGuestDialogs();

  // Called by WebContentsViewGuest when a drag operation is started within
  // |guest|. This |guest| will be signaled at the end of the drag operation.
  void StartDrag(BrowserPluginGuest* guest);

  // Sends EndSystemDrag message to the guest that initiated the last drag/drop
  // operation, if there's any.
  void SystemDragEnded();

  // Used to handle special keyboard events.
  bool HandleKeyboardEvent(const NativeWebKeyboardEvent& event);

  // Returns the "full page" guest if there is one. That is, if there is a
  // single BrowserPlugin in the embedder which takes up the full page, then it
  // is returned.
  BrowserPluginGuest* GetFullPageGuest();

 private:
  explicit BrowserPluginEmbedder(WebContentsImpl* web_contents);

  BrowserPluginGuestManager* GetBrowserPluginGuestManager() const;

  void ClearGuestDragStateIfApplicable();

  static bool DidSendScreenRectsCallback(WebContents* guest_web_contents);

  // Notifies a guest that the embedder's screen info has changed.
  static bool NotifyScreenInfoChanged(WebContents* guest_web_contents);

  // Closes modal dialogs in |guest_web_contents|.
  static bool CancelDialogs(WebContents* guest_web_contents);

  static bool UnlockMouseIfNecessaryCallback(bool* mouse_unlocked,
                                             WebContents* guest);

  // Message handlers.

  void OnAttach(RenderFrameHost* render_frame_host,
                int instance_id,
                const BrowserPluginHostMsg_Attach_Params& params);
  void OnUpdateDragCursor(bool* handled);

  // Used to correctly update the cursor when dragging over a guest, and to
  // handle a race condition when dropping onto the guest that started the drag
  // (the race is that the dragend message arrives before the drop message so
  // the drop never takes place).
  // crbug.com/233571
  base::WeakPtr<BrowserPluginGuest> guest_dragging_over_;

  // Pointer to the guest that started the drag, used to forward necessary drag
  // status messages to the correct guest.
  base::WeakPtr<BrowserPluginGuest> guest_started_drag_;

  // Keeps track of "dragend" state.
  bool guest_drag_ending_;

  base::WeakPtrFactory<BrowserPluginEmbedder> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(BrowserPluginEmbedder);
};

}  // namespace content

#endif  // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_EMBEDDER_H_
