chromium/chromecast/browser/cast_session_id_map.h

// Copyright 2018 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_CAST_SESSION_ID_MAP_H_
#define CHROMECAST_BROWSER_CAST_SESSION_ID_MAP_H_

#include <memory>
#include <string>
#include <utility>

#include "base/containers/flat_map.h"
#include "base/no_destructor.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "base/unguessable_token.h"
#include "chromecast/media/audio/cast_audio_manager_helper.h"

namespace base {
class SequencedTaskRunner;
}  // namespace base

namespace content {
class WebContents;
}  // namespace content

namespace chromecast {
namespace shell {

class CastSessionIdMap : public media::CastAudioManagerHelper::Delegate {
 public:
  // Retrieve the map instance. The first time this is called, a task runner can
  // be specified for the instance to run on. Any subsequent calls to this
  // function will return the same map instance, but will not change the task
  // runner.
  // This must be called for the first time on the browser main thread.
  static CastSessionIdMap* GetInstance(
      base::SequencedTaskRunner* task_runner = nullptr);

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

  // Map a session id to a particular group id in the provided WebContents.
  // Record whether the session is an audio only session.
  // Can be called on any thread.
  void SetAppProperties(std::string session_id,
                        bool is_audio_app,
                        content::WebContents* web_contents);
  // Record whether the session is launched in a group.
  // Can be called on any thread.
  void SetGroupInfo(std::string session_id, bool is_group);

  // CastAudioManagerHelper::Delegate implementation:
  // Fetch the session id that is mapped to the provided group_id. Defaults to
  // empty string if the mapping is not found.
  // Must be called on the sequence for |task_runner_|.
  std::string GetSessionId(const std::string& group_id) override;
  // Fetch whether the session is an audio only session based on the provided
  // session id. Defaults to false if the mapping is not found.
  // Must be called on the sequence for |task_runner_|.
  bool IsAudioOnlySession(const std::string& session_id) override;
  // Fetch whether the session is launched in a group based on the provided
  // session id. Defaults to false if the mapping is not found.
  // Must be called on the sequence for |task_runner_|.
  bool IsGroup(const std::string& session_id) override;

  // Async version of IsAudioOnlySession. It can be called from any thread.
  using IsAudioOnlySessionAsyncCallback = base::OnceCallback<void(bool)>;
  void IsAudioOnlySessionAsync(const std::string& session_id,
                               IsAudioOnlySessionAsyncCallback callback);

 private:
  class GroupObserver;
  friend class base::NoDestructor<CastSessionIdMap>;

  explicit CastSessionIdMap(base::SequencedTaskRunner* task_runner);
  ~CastSessionIdMap() override;

  // Callback for the group being destroyed.
  void OnGroupDestroyed(base::UnguessableToken group_id);
  // Removes the mapping between group_id and session_id and release the
  // GroupObserver. This must not be called in the group destructor callback,
  // because it releases the GroupObserver who owns the destuctor callback.
  void RemoveGroupId(base::UnguessableToken group_id);
  // Maps the session id for the provided group id.
  // Record whether the session is an audio only session.
  // This call be called on any thread.
  void SetAppPropertiesInternal(std::string session_id,
                                bool is_audio_app,
                                base::UnguessableToken group_id,
                                std::unique_ptr<GroupObserver> group_observer);

  base::flat_map<
      std::string,
      std::pair<std::string /* group_id */, std::unique_ptr<GroupObserver>>>
      mapping_;

  base::flat_map<std::string /* session_id */, bool /* is_audio_app */>
      application_capability_mapping_;
  base::flat_map<std::string /* session_id */, bool /* is_group */>
      group_info_mapping_;
  base::SequencedTaskRunner* const task_runner_;
  SEQUENCE_CHECKER(sequence_checker_);
};

}  // namespace shell
}  // namespace chromecast

#endif  // CHROMECAST_BROWSER_CAST_SESSION_ID_MAP_H_