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

content / browser / media / web_app_system_media_controls_manager.h [blame]

// Copyright 2023 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_BROWSER_MEDIA_WEB_APP_SYSTEM_MEDIA_CONTROLS_MANAGER_H_
#define CONTENT_BROWSER_MEDIA_WEB_APP_SYSTEM_MEDIA_CONTROLS_MANAGER_H_

#include "base/functional/callback.h"
#include "base/unguessable_token.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"
#include "services/media_session/public/mojom/media_controller.mojom.h"

namespace system_media_controls {
class SystemMediaControls;
}

namespace content {

class WebAppSystemMediaControls;

// Used to fire telemetry about instanced PWA controls usage.
// This enum is used to back a histogram. Do not remove or reorder members.
enum class WebAppSystemMediaControlsEvent {
  kPwaPlayingMedia = 0,
  kPwaSmcNext = 1,
  kPwaSmcPrevious = 2,
  kPwaSmcPlay = 3,
  kPwaSmcPause = 4,
  kPwaSmcPlayPause = 5,
  kPwaSmcStop = 6,
  kPwaSmcSeek = 7,
  kPwaSmcSeekTo = 8,
  kMaxValue = kPwaSmcSeekTo,
};

// A simple observer interface for tests to be notified when events are
// received by the WebAppSystemmediaControlsManager.
class WebAppSystemMediaControlsManagerObserver {
 public:
  virtual void OnWebAppAdded(base::UnguessableToken request_id) {}
};

// WebAppSystemMediaControlsManager is a class that handles system media
// controls related metadata for use with instanced per dPWA system media
// controls. Primarily, it is used by other systems to find associated objects
// when only having one piece of information such as RequestId.
//
// WebAppSystemMediaControlsManager creates and owns WebAppSystemMediaControls
// objects. A single WebAppSystemMediaControls owns references to all the
// objects needed for a single dPWA to integrate with the OS' media playback
// system.
//
// NOTE: WebAppSystemMediaControls is not derived from SystemMediaControls.
// rather a WebAppSystemMediaControls owns and holds a SystemMediaControls.
// WebAppSystemMediaControls also contains other related classes. See
// web_app_system_media_controls.h.
//
// Usage: After this class is constructed, call Init(). The manager
// will connect itself to the AudioFocusManager to receive messages about
// focus changes.
class CONTENT_EXPORT WebAppSystemMediaControlsManager
    : public media_session::mojom::AudioFocusObserver {
 public:
  WebAppSystemMediaControlsManager();

  WebAppSystemMediaControlsManager(const WebAppSystemMediaControlsManager&) =
      delete;
  WebAppSystemMediaControlsManager& operator=(
      const WebAppSystemMediaControlsManager&) = delete;

  ~WebAppSystemMediaControlsManager() override;

  // Runs initialization steps such as connecting to AudioFocusManager
  void Init();

  // media_session::mojom::AudioFocusObserver implementation
  void OnFocusGained(
      media_session::mojom::AudioFocusRequestStatePtr state) override;
  void OnFocusLost(
      media_session::mojom::AudioFocusRequestStatePtr state) override;
  void OnRequestIdReleased(const base::UnguessableToken& request_id) override;

  // Helpers
  void OnMojoError();

  // Retrieve the WebAppSystemMediaControls for `request_id`, returns nullptr if
  // not found.
  WebAppSystemMediaControls* GetControlsForRequestId(
      base::UnguessableToken request_id);
  // Retrieve the WebAppSystemMediaControls that contains
  // `system_media_controls`, returns nullptr if not found.
  WebAppSystemMediaControls* GetWebAppSystemMediaControlsForSystemMediaControls(
      system_media_controls::SystemMediaControls* system_media_controls);

  bool IsActive() { return !controls_map_.empty(); }

  // Retrieves a vector of all the WebAppSystemMediaControls associated with
  // this manager.
  std::vector<WebAppSystemMediaControls*> GetAllControls();

  // This lets chrome/browser tests get notified when SMCBridge is created.
  void SetOnSystemMediaControlsBridgeCreatedCallbackForTesting(
      base::RepeatingCallback<void()> callback);

 private:
  void SkipMojoConnectionForTesting() {
    skip_mojo_connection_for_testing_ = true;
  }

  void TryConnectToAudioFocusManager();

  // This method allows friended tests to register themselves as observers
  // to be notified of events happening in this manager.
  void SetObserverForTesting(
      WebAppSystemMediaControlsManagerObserver* observer) {
    test_observer_ = observer;
  }

  std::map<base::UnguessableToken, std::unique_ptr<WebAppSystemMediaControls>>
      controls_map_;

  // Used to receive updates about all media sessions, not just the active one.
  mojo::Receiver<media_session::mojom::AudioFocusObserver>
      audio_focus_observer_receiver_{this};

  // Used to manage the AudioFocusObserver connection.
  mojo::Remote<media_session::mojom::AudioFocusManager> audio_focus_manager_;

  bool initialized_ = false;
  bool skip_mojo_connection_for_testing_ = false;
  bool always_assume_web_app_for_testing_ = false;

  raw_ptr<WebAppSystemMediaControlsManagerObserver> test_observer_;

  base::RepeatingCallback<void()>
      on_system_media_controls_bridge_created_callback_for_testing_;

  friend class WebAppSystemMediaControlsManagerTest;
  friend class WebAppSystemMediaControlsBrowserTest;
};

}  // namespace content

#endif  // CONTENT_BROWSER_MEDIA_WEB_APP_SYSTEM_MEDIA_CONTROLS_MANAGER_H_