1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191

content / test / fuzzer / controller_presentation_service_delegate_for_fuzzing.h [blame]

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

#ifndef CONTENT_TEST_FUZZER_CONTROLLER_PRESENTATION_SERVICE_DELEGATE_FOR_FUZZING_H_
#define CONTENT_TEST_FUZZER_CONTROLLER_PRESENTATION_SERVICE_DELEGATE_FOR_FUZZING_H_

#include <map>
#include <memory>
#include <string>

#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/presentation_screen_availability_listener.h"
#include "content/public/browser/presentation_service_delegate.h"
#include "content/test/fuzzer/controller_presentation_service_delegate_for_fuzzing.pb.h"
#include "media/base/flinging_controller.h"
#include "third_party/blink/public/mojom/presentation/presentation.mojom.h"

// Fake for the `ControllerPresentationServiceDelegate` interface
//
// This fake is limited to do callback, observer and listener behaviours,
// according to a set of actions specified by a protobuf.
// So it is not suitable for tests. It is designed for a fuzzer.
//
// Usage: call the component as expected as the delegate interface.
// To run the callables provided, use `NextAction`,
// provide a protobuf of the `Action` message - there lists the possible calls.
// This will instruct the fake to run the callbacks accordingly.
//
// The callables are run on the UI thread, as the delegate interface is expected
// to be called on the UI thread.
// In the case of MojoLPM fuzzers, `NextAction` should be called on the fuzzer
// thread.
class ControllerPresentationServiceDelegateForFuzzing
    : public content::ControllerPresentationServiceDelegate {
 public:
  ControllerPresentationServiceDelegateForFuzzing();
  ~ControllerPresentationServiceDelegateForFuzzing() override;

  // Used to run one callable.
  // These are set by using this as implementation of the delegate interface.
  // The callable is specified by the `action`, as defined in assocciated proto.
  //
  // All calls must be run on the same sequence
  // (for MojoLPM fuzzers, it should be the fuzzer thread)
  void NextAction(
      const content::fuzzing::
          controller_presentation_service_delegate_for_fuzzing::proto::Action&
              action);

  // ControllerPresentationServiceDelegate implementation
  void AddObserver(int render_process_id,
                   int render_frame_id,
                   Observer* observer) override;

  void RemoveObserver(int render_process_id, int render_frame_id) override;

  void Reset(int render_process_id, int render_frame_id) override;

  bool AddScreenAvailabilityListener(
      int render_process_id,
      int render_frame_id,
      content::PresentationScreenAvailabilityListener* listener) override;

  void RemoveScreenAvailabilityListener(
      int render_process_id,
      int render_frame_id,
      content::PresentationScreenAvailabilityListener* listener) override;

  void SetDefaultPresentationUrls(
      const content::PresentationRequest& request,
      content::DefaultPresentationConnectionCallback callback) override;

  void StartPresentation(
      const content::PresentationRequest& request,
      content::PresentationConnectionCallback success_cb,
      content::PresentationConnectionErrorCallback error_cb) override;

  void ReconnectPresentation(
      const content::PresentationRequest& request,
      const std::string& presentation_id,
      content::PresentationConnectionCallback success_cb,
      content::PresentationConnectionErrorCallback error_cb) override;

  void CloseConnection(int render_process_id,
                       int render_frame_id,
                       const std::string& presentation_id) override;

  void Terminate(int render_process_id,
                 int render_frame_id,
                 const std::string& presentation_id) override;

  std::unique_ptr<media::FlingingController> GetFlingingController(
      int render_process_id,
      int render_frame_id,
      const std::string& presentation_id) override;

  void ListenForConnectionStateChange(
      int render_process_id,
      int render_frame_id,
      const blink::mojom::PresentationInfo& connection,
      const content::PresentationConnectionStateChangedCallback&
          state_changed_cb) override;

 private:
  using Action = content::fuzzing::
      controller_presentation_service_delegate_for_fuzzing::proto::Action;

  // Use to invoke the callbacks & registered callables
  // For each, we have two member functions, where the first calls the second.
  // The first is prefixed by `Handle`, which takes the raw protobuf datatype,
  // and is run on the same thread as `NextAction` (for MojoLPM: fuzzer thread).
  // The second is prefixed by `Call` which invokes the call with the converted
  // datatype, and is run on the UI thread.
  void HandleListenersGetAvailabilityUrl(
      const mojolpm::url::mojom::Url& proto_url);
  void CallListenersGetAvailabilityUrl(GURL url);

  void HandleListenersOnScreenAvailabilityChanged(
      const mojolpm::url::mojom::Url& proto_url,
      const mojolpm::blink::mojom::ScreenAvailability&
          proto_screen_availability);
  void CallListenersOnScreenAvailabilityChanged(
      GURL url,
      blink::mojom::ScreenAvailability screen_availability);

  void HandleSetDefaultPresentationUrls(
      const mojolpm::blink::mojom::PresentationConnectionResult& proto_result);
  void CallSetDefaultPresentationUrls(
      blink::mojom::PresentationConnectionResultPtr result_ptr);

  void HandleStartPresentationSuccess(
      const mojolpm::blink::mojom::PresentationConnectionResult& proto_result);
  void CallStartPresentationSuccess(
      blink::mojom::PresentationConnectionResultPtr result_ptr);

  void HandleStartPresentationError(
      const mojolpm::blink::mojom::PresentationError& proto_error);
  void CallStartPresentationError(blink::mojom::PresentationErrorPtr error_ptr);

  void HandleReconnectPresentationSuccess(
      const mojolpm::blink::mojom::PresentationConnectionResult& proto_result);
  void CallReconnectPresentationSuccess(
      blink::mojom::PresentationConnectionResultPtr result_ptr);

  void HandleReconnectPresentationError(
      const mojolpm::blink::mojom::PresentationError& proto_error);
  void CallReconnectPresentationError(
      blink::mojom::PresentationErrorPtr error_ptr);

  void HandleListenForConnectionStateChangeStateChanged(
      const mojolpm::blink::mojom::PresentationConnectionState&
          proto_connection_state);
  void CallListenForConnectionStateChangeStateChanged(
      blink::mojom::PresentationConnectionState connection_state);

  base::WeakPtr<ControllerPresentationServiceDelegateForFuzzing> GetWeakPtr() {
    return weak_factory_.GetWeakPtr();
  }

  // We store all callbacks as single callables; not queued nor out of order,
  // as this mimics the real delegate as closely as possible
  std::map<content::GlobalRenderFrameHostId,
           content::PresentationServiceDelegate::Observer*>
      observers_;

  std::map<GURL, content::PresentationScreenAvailabilityListener*> listeners_;

  content::DefaultPresentationConnectionCallback
      set_default_presentation_urls_callback_;

  content::PresentationConnectionCallback start_presentation_success_cb_;

  content::PresentationConnectionErrorCallback start_presentation_error_cb_;

  content::PresentationConnectionCallback reconnect_presentation_success_cb_;

  content::PresentationConnectionErrorCallback reconnect_presentation_error_cb_;

  content::PresentationConnectionStateChangedCallback
      listen_for_connection_state_change_state_changed_cb_;

  SEQUENCE_CHECKER(sequence_checker_);

  // `PostTask`ing the calls onto the UI thread is not guaranteed to outlive
  // `this`. So a weak pointer is necessary for those calls.
  base::WeakPtrFactory<ControllerPresentationServiceDelegateForFuzzing>
      weak_factory_{this};
};

#endif  // CONTENT_TEST_FUZZER_CONTROLLER_PRESENTATION_SERVICE_DELEGATE_FOR_FUZZING_H_