chromium/chromecast/browser/gesture_router.h

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMECAST_BROWSER_GESTURE_ROUTER_H_
#define CHROMECAST_BROWSER_GESTURE_ROUTER_H_

#include "base/functional/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "chromecast/browser/visibility_types.h"
#include "chromecast/common/mojom/gesture.mojom.h"
#include "chromecast/ui/back_gesture_router.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"

namespace chromecast {

// This class exposes Cast UI gesture hooks to JavaScript. The page notifies
// its ability to handle specific gestures, which allows this class to perform
// necessary routing.
class GestureRouter : private mojom::GestureSource, public BackGestureRouter {
 public:
  GestureRouter();
  GestureRouter(const GestureRouter&) = delete;
  GestureRouter& operator=(const GestureRouter&) = delete;
  ~GestureRouter() override;

  using GestureHandledCallback = base::OnceCallback<void(bool)>;

  using ConsumerCallback =
      base::RepeatingCallback<void(GestureType, GestureHandledCallback)>;

  // Check to see if the gesture can be handled by JS. This is called prior to
  // ConsumeGesture().
  bool CanHandleGesture(GestureType gesture_type);

  // Called while a system UI gesture is in progress.
  void GestureProgress(GestureType gesture_type,
                       const gfx::Point& touch_location);

  // Called when an in-progress system UI gesture is cancelled (for example
  // when the finger is lifted before the completion of the gesture.)
  void CancelGesture(GestureType gesture_type);

  // Consume and handle a completed UI gesture. Invokes the callback with a
  // boolean indicating whether the gesture was handled or not.
  void ConsumeGesture(GestureType gesture_type,
                      GestureHandledCallback handled_callback);

  // Registers an in-process gesture consumer. If set, this supersedes the
  // mojo handler path. This can be called multiple times, overriding a
  // previously registered callback.
  void SetConsumeGestureCallback(ConsumerCallback callback);

  // mojom::GestureSource implementation:
  void Subscribe(mojo::PendingRemote<mojom::GestureHandler>
                     pending_handler_remote) override;
  void SetCanGoBack(bool can_go_back) override;
  void SetCanTopDrag(bool can_top_drag) override;
  void SetCanRightDrag(bool can_right_drag) override;

  bool CanGoBack() const;
  void SendBackGesture(base::OnceCallback<void(bool)> was_handled_callback);
  void SendBackGestureProgress(const gfx::Point& touch_location);
  void SendBackGestureCancel();
  bool CanTopDrag() const;
  void SendTopDragGestureProgress(const gfx::Point& touch_location);
  void SendTopDragGestureDone();
  bool CanRightDrag() const;
  void SendRightDragGestureProgress(const gfx::Point& touch_location);
  void SendRightDragGestureDone();
  void SendTapGesture();
  void SendTapDownGesture();

  // BackGestureRouter overrides:
  void SetBackGestureDelegate(Delegate* delegate) override;

  base::RepeatingCallback<void(mojo::PendingReceiver<mojom::GestureSource>)>
  GetBinder();

 private:
  friend class CastContentGestureHandlerTest;
  friend class CastContentWindowEmbeddedTest;

  // Helper method for unit tests. Instead of having to register an async
  // subscriber, tests can use SetHandler() to register a mock instead. This
  // can be called multiple times.
  void SetHandler(mojom::GestureHandler* handler);

  void BindGestureSource(mojo::PendingReceiver<mojom::GestureSource> request);

  mojo::Receiver<mojom::GestureSource> gesture_source_receiver_;
  mojo::Remote<mojom::GestureHandler> handler_remote_;
  mojom::GestureHandler* handler_;

  bool can_go_back_;
  bool can_top_drag_;
  bool can_right_drag_;
  bool managed_mode_;  // If in managed mode, disable top drag.
  Delegate* delegate_ = nullptr;

  ConsumerCallback consumer_callback_;

  base::WeakPtrFactory<GestureRouter> weak_factory_;
};

}  // namespace chromecast

#endif  // CHROMECAST_BROWSER_GESTURE_ROUTER_H_