summaryrefslogtreecommitdiff
path: root/chromium/chrome/common/media_router/providers
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/common/media_router/providers')
-rw-r--r--chromium/chrome/common/media_router/providers/cast/cast_media_source.cc53
-rw-r--r--chromium/chrome/common/media_router/providers/cast/cast_media_source.h43
-rw-r--r--chromium/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc13
3 files changed, 97 insertions, 12 deletions
diff --git a/chromium/chrome/common/media_router/providers/cast/cast_media_source.cc b/chromium/chrome/common/media_router/providers/cast/cast_media_source.cc
index 97002d0fd2a..c7fe6bf2e93 100644
--- a/chromium/chrome/common/media_router/providers/cast/cast_media_source.cc
+++ b/chromium/chrome/common/media_router/providers/cast/cast_media_source.cc
@@ -61,6 +61,7 @@ const EnumTable<CastDeviceCapability> EnumTable<CastDeviceCapability>::instance(
template <>
const EnumTable<ReceiverAppType> EnumTable<ReceiverAppType>::instance(
{
+ {ReceiverAppType::kOther, "OTHER"},
{ReceiverAppType::kWeb, "WEB"},
{ReceiverAppType::kAndroidTv, "ANDROID_TV"},
},
@@ -70,6 +71,9 @@ const EnumTable<ReceiverAppType> EnumTable<ReceiverAppType>::instance(
namespace media_router {
+// The maximum length of presentation URL is 64KB.
+constexpr int kMaxCastPresentationUrlLength = 64 * 1024;
+
namespace {
// A nonmember version of base::Optional::value_or that works on pointers as
@@ -188,8 +192,8 @@ std::unique_ptr<CastMediaSource> CastMediaSourceForTabMirroring(
const MediaSource::Id& source_id) {
return std::make_unique<CastMediaSource>(
source_id,
- std::vector<CastAppInfo>({CastAppInfo(kCastStreamingAppId),
- CastAppInfo(kCastStreamingAudioAppId)}));
+ std::vector<CastAppInfo>({CastAppInfo::ForCastStreaming(),
+ CastAppInfo::ForCastStreamingAudio()}));
}
std::unique_ptr<CastMediaSource> CastMediaSourceForDesktopMirroring(
@@ -197,7 +201,7 @@ std::unique_ptr<CastMediaSource> CastMediaSourceForDesktopMirroring(
// TODO(https://crbug.com/849335): Add back audio-only devices for desktop
// mirroring when proper support is implemented.
return std::make_unique<CastMediaSource>(
- source_id, std::vector<CastAppInfo>({CastAppInfo(kCastStreamingAppId)}));
+ source_id, std::vector<CastAppInfo>({CastAppInfo::ForCastStreaming()}));
}
// The logic shared by ParseCastUrl() and ParseLegacyCastUrl().
@@ -210,6 +214,8 @@ std::unique_ptr<CastMediaSource> CreateFromURLParams(
const std::string& broadcast_namespace,
const std::string& encoded_broadcast_message,
const std::string& launch_timeout_str,
+ const std::string& target_playout_delay_millis_str,
+ const std::string& audio_capture_str,
const std::vector<ReceiverAppType>& supported_app_types,
const std::string& app_params) {
if (app_infos.empty())
@@ -227,13 +233,24 @@ std::unique_ptr<CastMediaSource> CreateFromURLParams(
broadcast_namespace, DecodeURLComponent(encoded_broadcast_message)));
}
- int launch_timeout_millis;
+ int launch_timeout_millis = 0;
if (base::StringToInt(launch_timeout_str, &launch_timeout_millis) &&
launch_timeout_millis > 0) {
cast_source->set_launch_timeout(
base::TimeDelta::FromMilliseconds(launch_timeout_millis));
}
+ int target_playout_delay_millis = 0;
+ if (base::StringToInt(target_playout_delay_millis_str,
+ &target_playout_delay_millis) &&
+ target_playout_delay_millis > 0) {
+ cast_source->set_target_playout_delay(
+ base::TimeDelta::FromMilliseconds(target_playout_delay_millis));
+ }
+
+ if (audio_capture_str == "0")
+ cast_source->set_allow_audio_capture(false);
+
if (!supported_app_types.empty())
cast_source->set_supported_app_types(supported_app_types);
cast_source->set_app_params(app_params);
@@ -259,6 +276,8 @@ std::unique_ptr<CastMediaSource> ParseCastUrl(const MediaSource::Id& source_id,
FindValueOr(params, "broadcastNamespace", ""),
FindValueOr(params, "broadcastMessage", ""),
FindValueOr(params, "launchTimeout", ""),
+ FindValueOr(params, "streamingTargetPlayoutDelayMillis", ""),
+ FindValueOr(params, "streamingCaptureAudio", ""),
SupportedAppTypesFromString(FindValueOr(params, "supportedAppTypes", "")),
FindValueOr(params, "appParams", ""));
}
@@ -318,6 +337,8 @@ std::unique_ptr<CastMediaSource> ParseLegacyCastUrl(
FindValueOr(params, "__castBroadcastNamespace__", ""),
FindValueOr(params, "__castBroadcastMessage__", ""),
FindValueOr(params, "__castLaunchTimeout__", ""),
+ /* target_playout_delay_millis_str */ "",
+ /* audio_capture */ "",
/* supported_app_types */ {},
/* appParams */ "");
}
@@ -339,27 +360,45 @@ bool IsAutoJoinAllowed(AutoJoinPolicy policy,
}
}
+bool IsSiteInitiatedMirroringSource(const MediaSource::Id& source_id) {
+ return base::StartsWith(source_id, kMirroringAppUri,
+ base::CompareCase::SENSITIVE);
+}
+
CastAppInfo::CastAppInfo(
const std::string& app_id,
BitwiseOr<cast_channel::CastDeviceCapability> required_capabilities)
: app_id(app_id), required_capabilities(required_capabilities) {}
+
CastAppInfo::~CastAppInfo() = default;
CastAppInfo::CastAppInfo(const CastAppInfo& other) = default;
// static
+CastAppInfo CastAppInfo::ForCastStreaming() {
+ return CastAppInfo(kCastStreamingAppId, {CastDeviceCapability::VIDEO_OUT,
+ CastDeviceCapability::AUDIO_OUT});
+}
+
+// static
+CastAppInfo CastAppInfo::ForCastStreamingAudio() {
+ return CastAppInfo(kCastStreamingAudioAppId,
+ {CastDeviceCapability::AUDIO_OUT});
+}
+
+// static
std::unique_ptr<CastMediaSource> CastMediaSource::FromMediaSource(
const MediaSource& source) {
- if (source.IsTabMirroringSource())
+ if (source.IsTabMirroringSource() || source.IsLocalFileSource())
return CastMediaSourceForTabMirroring(source.id());
if (source.IsDesktopMirroringSource())
return CastMediaSourceForDesktopMirroring(source.id());
const GURL& url = source.url();
- if (!url.is_valid())
- return nullptr;
+ if (!url.is_valid() || url.spec().length() > kMaxCastPresentationUrlLength)
+ return nullptr;
if (url.SchemeIs(kCastPresentationUrlScheme)) {
return ParseCastUrl(source.id(), url);
} else if (IsLegacyCastPresentationUrl(url)) {
diff --git a/chromium/chrome/common/media_router/providers/cast/cast_media_source.h b/chromium/chrome/common/media_router/providers/cast/cast_media_source.h
index 09c04496b2f..ce8f7b9ef98 100644
--- a/chromium/chrome/common/media_router/providers/cast/cast_media_source.h
+++ b/chromium/chrome/common/media_router/providers/cast/cast_media_source.h
@@ -11,7 +11,7 @@
#include <type_traits>
#include <vector>
-#include "base/logging.h"
+#include "base/check.h"
#include "base/optional.h"
#include "chrome/common/media_router/media_source.h"
#include "components/cast_channel/cast_message_util.h"
@@ -28,6 +28,13 @@ static constexpr char kCastStreamingAudioAppId[] = "85CDB22F";
// message.
static constexpr char kMultizoneLeaderAppId[] = "MultizoneLeader";
+static const constexpr char* const kMultizoneMemberAppIds[] = {
+ kMultizoneLeaderAppId,
+ "531A4F84", // MultizoneLeader
+ "MultizoneFollower",
+ "705D30C6" // MultizoneFollower
+};
+
static constexpr base::TimeDelta kDefaultLaunchTimeout =
base::TimeDelta::FromSeconds(60);
@@ -44,12 +51,20 @@ class BitwiseOr {
for (E e : values)
Add(e);
}
+ static constexpr BitwiseOr FromBits(T bits) { return BitwiseOr(bits); }
bool empty() const { return bits_ == 0; }
+ T bits() const { return bits_; }
void Add(E value) { bits_ |= Mask(value); }
+ bool Has(E value) const { return (bits_ & Mask(value)) != 0; }
+ bool HasAll(const BitwiseOr& other) const {
+ return (bits_ & other.bits_) == other.bits_;
+ }
bool operator==(const BitwiseOr& other) const { return bits_ == other.bits_; }
bool operator!=(const BitwiseOr& other) const { return *this != other; }
private:
+ explicit constexpr BitwiseOr(T bits) : bits_(bits) {}
+
static T Mask(E value) {
const T result = static_cast<T>(value);
DCHECK(static_cast<E>(result) == value);
@@ -60,12 +75,16 @@ class BitwiseOr {
// Represents a Cast app and its capabilitity requirements.
struct CastAppInfo {
- explicit CastAppInfo(const std::string& app_id,
- BitwiseOr<cast_channel::CastDeviceCapability> = {});
+ explicit CastAppInfo(
+ const std::string& app_id,
+ BitwiseOr<cast_channel::CastDeviceCapability> required_capabilities);
~CastAppInfo();
CastAppInfo(const CastAppInfo& other);
+ static CastAppInfo ForCastStreaming();
+ static CastAppInfo ForCastStreamingAudio();
+
std::string app_id;
// A bitset of capabilities required by the app.
@@ -114,6 +133,9 @@ bool IsAutoJoinAllowed(AutoJoinPolicy policy,
const url::Origin& origin2,
int tab_id2);
+// Returns true if |source_id| is a valid origin for site-initiated mirroring.
+bool IsSiteInitiatedMirroringSource(const MediaSource::Id& source_id);
+
// Represents a MediaSource parsed into structured, Cast specific data. The
// following MediaSources can be parsed into CastMediaSource:
// - Cast Presentation URLs
@@ -165,6 +187,17 @@ class CastMediaSource {
DefaultActionPolicy default_action_policy() const {
return default_action_policy_;
}
+ base::Optional<base::TimeDelta> target_playout_delay() const {
+ return target_playout_delay_;
+ }
+ void set_target_playout_delay(
+ const base::Optional<base::TimeDelta>& target_playout_delay) {
+ target_playout_delay_ = target_playout_delay;
+ }
+ bool allow_audio_capture() const { return allow_audio_capture_; }
+ void set_allow_audio_capture(bool allow_audio_capture) {
+ allow_audio_capture_ = allow_audio_capture;
+ }
const std::string& app_params() const { return app_params_; }
void set_app_params(const std::string& app_params) {
app_params_ = app_params;
@@ -180,9 +213,11 @@ class CastMediaSource {
AutoJoinPolicy auto_join_policy_;
DefaultActionPolicy default_action_policy_;
base::TimeDelta launch_timeout_ = kDefaultLaunchTimeout;
- // Empty if not set.
+ // Optional parameters.
std::string client_id_;
base::Optional<cast_channel::BroadcastRequest> broadcast_request_;
+ base::Optional<base::TimeDelta> target_playout_delay_;
+ bool allow_audio_capture_ = true;
std::vector<ReceiverAppType> supported_app_types_ = {ReceiverAppType::kWeb};
std::string app_params_;
};
diff --git a/chromium/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc b/chromium/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
index 42c5c660f7a..03ebc375c99 100644
--- a/chromium/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
+++ b/chromium/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
@@ -30,6 +30,8 @@ TEST(CastMediaSourceTest, FromCastURLWithDefaults) {
EXPECT_EQ(DefaultActionPolicy::kCreateSession,
source->default_action_policy());
EXPECT_EQ(ReceiverAppType::kWeb, source->supported_app_types()[0]);
+ EXPECT_EQ(base::nullopt, source->target_playout_delay());
+ EXPECT_EQ(true, source->allow_audio_capture());
}
TEST(CastMediaSourceTest, FromCastURL) {
@@ -42,7 +44,9 @@ TEST(CastMediaSourceTest, FromCastURL) {
"&autoJoinPolicy=tab_and_origin_scoped"
"&defaultActionPolicy=cast_this_tab"
"&appParams=appParams"
- "&supportedAppTypes=ANDROID_TV,WEB");
+ "&supportedAppTypes=ANDROID_TV,WEB"
+ "&streamingTargetPlayoutDelayMillis=42"
+ "&streamingCaptureAudio=0");
std::unique_ptr<CastMediaSource> source =
CastMediaSource::FromMediaSourceId(source_id);
ASSERT_TRUE(source);
@@ -64,6 +68,9 @@ TEST(CastMediaSourceTest, FromCastURL) {
EXPECT_EQ(ReceiverAppType::kAndroidTv, source->supported_app_types()[0]);
EXPECT_EQ(ReceiverAppType::kWeb, source->supported_app_types()[1]);
EXPECT_EQ("appParams", source->app_params());
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(42),
+ source->target_playout_delay());
+ EXPECT_EQ(false, source->allow_audio_capture());
}
TEST(CastMediaSourceTest, FromLegacyCastURL) {
@@ -159,6 +166,10 @@ TEST(CastMediaSourceTest, FromInvalidSource) {
EXPECT_FALSE(CastMediaSource::FromMediaSourceId("cast:?param=foo"));
EXPECT_FALSE(CastMediaSource::FromMediaSourceId(
"https://google.com/cast#__castAppId__=/param=foo"));
+ // URL spec exceeds maximum size limit 64KB.
+ int length = 64 * 1024 + 1;
+ std::string invalidURL(length, 'a');
+ EXPECT_FALSE(CastMediaSource::FromMediaSourceId("cast:appid?" + invalidURL));
}
} // namespace media_router