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
|
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_MEDIA_ROUTER_COMMON_MEDIA_SOURCE_H_
#define COMPONENTS_MEDIA_ROUTER_COMMON_MEDIA_SOURCE_H_
#include <optional>
#include <ostream>
#include <string>
#include "base/hash/hash.h"
#include "url/gurl.h"
namespace media {
enum class AudioCodec;
enum class VideoCodec;
} // namespace media
namespace media_router {
// URL schemes used by Presentation URLs for Cast and DIAL.
constexpr char kCastPresentationUrlScheme[] = "cast";
constexpr char kCastDialPresentationUrlScheme[] = "cast-dial";
constexpr char kDialPresentationUrlScheme[] = "dial";
constexpr char kRemotePlaybackPresentationUrlScheme[] = "remote-playback";
// URL prefix used by legacy Cast presentations.
constexpr char kLegacyCastPresentationUrlPrefix[] =
"https://google.com/cast#__castAppId__=";
// Strings used in presentation IDs by the Cast SDK implementation.
// TODO(takumif): Move them out of this file, since they are not directly
// related to MediaSource.
//
// This value must be the same as |chrome.cast.AUTO_JOIN_PRESENTATION_ID| in the
// component extension.
constexpr char kAutoJoinPresentationId[] = "auto-join";
// This value must be the same as |chrome.cast.PRESENTATION_ID_PREFIX| in the
// component extension.
constexpr char kCastPresentationIdPrefix[] = "cast-session_";
// Returns true if |url| represents a legacy Cast presentation URL, i.e., it
// starts with |kLegacyCastPresentationUrlPrefix|.
bool IsLegacyCastPresentationUrl(const GURL& url);
// Returns true if |url| is a valid presentation URL.
bool IsValidPresentationUrl(const GURL& url);
// Returns true if |media_source| has a valid presentation URL.
bool IsValidStandardPresentationSource(const std::string& media_source);
// Returns true if |presentation_id| is an ID used by auto-join requests.
bool IsAutoJoinPresentationId(const std::string& presentation_id);
// A media source specifier, represented as an ID string and possibly a URL.
// If there is a URL, its string value with be the same as the ID string.
class MediaSource {
public:
using Id = std::string;
// Create from an arbitrary string, which may or may not be a presentation
// URL.
explicit MediaSource(const MediaSource::Id& id);
// Create from a URL which is assumed to be a presentation URL. If
// |presentation_url| is not a valid presentation URL, the resulting object's
// IsValid() method will return false.
explicit MediaSource(const GURL& presentation_url);
~MediaSource();
// Gets the ID of the media source.
const Id& id() const { return id_; }
// If the source ID is a presentation URL, returns the URL; otherwise returns
// an empty GURL.
const GURL& url() const { return url_; }
// Returns true if two MediaSource objects use the same media ID.
bool operator==(const MediaSource& other) const { return id_ == other.id(); }
bool operator<(const MediaSource& other) const { return id_ < other.id(); }
// Compare operator for std::optional<MediaSource>
struct Cmp {
bool operator()(const std::optional<MediaSource>& source1,
const std::optional<MediaSource>& source2) const {
Id id1 = (source1.has_value()) ? (source1->id()) : "";
Id id2 = (source2.has_value()) ? (source2->id()) : "";
return id1 < id2;
}
};
// Protocol-specific media source object creation.
// Returns MediaSource URI depending on the type of source.
static MediaSource ForAnyTab();
static MediaSource ForTab(int tab_id);
static MediaSource ForPresentationUrl(const GURL& presentation_url);
static MediaSource ForRemotePlayback(int tab_id,
media::VideoCodec video_codec,
media::AudioCodec audio_codec);
// Creates a media source for a specific desktop.
// `desktop_media_id` is the string representing content::DesktopMediaID.
static MediaSource ForDesktop(const std::string& desktop_media_id,
bool with_audio);
// Creates a media source representing a yet-to-be-chosen desktop, screen or
// window. This must never be passed to a mojom::MediaRouteProvider
// implementation's CreateRoute(). This is just a placeholder for the media
// router UI until the moment the user initiates capture and picks a specific
// desktop/screen/window.
static MediaSource ForUnchosenDesktop();
// Returns true if source outputs its content via tab mirroring.
bool IsTabMirroringSource() const;
// Returns true if source outputs its content via desktop mirroring.
bool IsDesktopMirroringSource() const;
// Returns true if this is represents a Cast Presentation URL.
bool IsCastPresentationUrl() const;
// Returns true if the source is a RemotePlayback source.
bool IsRemotePlaybackSource() const;
// Parses the ID and returns the SessionTabHelper tab ID referencing a source
// tab. Don't rely on this method returning something useful without first
// calling IsTabMirroringSource(); Returns std::nullopt for non-tab sources
// or the ForAnyTab() source.
std::optional<int> TabId() const;
// Parse the tab ID from the RemotePlayback source. Returns std::nullopt for
// non-RemotePlayback sources or invalid formats.
std::optional<int> TabIdFromRemotePlaybackSource() const;
// When this source was created by ForDesktop(), returns the string
// representing content::DesktopMediaID. Otherwise, returns std::nullopt.
std::optional<std::string> DesktopStreamId() const;
// Returns true if this source represents desktop capture that also provides
// audio loopback capture. Returns false otherwise.
bool IsDesktopSourceWithAudio() const;
// Returns true this source outputs its content via DIAL.
// TODO(crbug.com/41366226): Move this to in-browser DIAL/Cast MRP when we
// have one.
bool IsDialSource() const;
// Returns empty string if this source is not DIAL media source, or is not a
// valid DIAL media source.
std::string AppNameFromDialSource() const;
// Returns a shortened copy of the media source ID suitable for logging.
std::string TruncateForLogging(size_t max_length) const;
// Append the "&tab_id=xxx" string to the presentation url. The `tab_id` is
// used for MediaDialogView to associate the local media session notification
// with a Reote Playback MediaRoute so that users can control Remote Playback
// session from GMC.
// TODO(crbug.com/1491212): remove the `tab_id` field from the MediaSource
// and use the MVC model in GMC to handle Remote Playback UI presentation
// logic.
void AppendTabIdToRemotePlaybackUrlQuery(int tab_id);
private:
MediaSource::Id id_;
GURL url_;
};
// Only for debug logging. This operator is defined inline so it doesn't add
// any code in release builds. (Omitting the definition entirely when NDEBUG is
// defined causes linker errors on Android.)
inline std::ostream& operator<<(std::ostream& stream,
const MediaSource& source) {
return stream << "MediaSource[" << source.id() << "]";
}
} // namespace media_router
#endif // COMPONENTS_MEDIA_ROUTER_COMMON_MEDIA_SOURCE_H_
|