Commit 479d9903 authored by John Williams's avatar John Williams Committed by Commit Bot

[Cast MRP] Fixed "source not supported" for local file casting.

This CL fixes an issue where all Cast devices show "source not
supported" after selecting a local file to cast.

Bug: 1078448, b/155777239
Change-Id: Ia71a0cca55c45ed9578e7d49ffccef7333b3319e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2210634Reviewed-by: default avatarTakumi Fujimoto <takumif@chromium.org>
Commit-Queue: John Williams <jrw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#775148}
parent 4def961e
...@@ -289,7 +289,7 @@ void MediaRouterMojoImpl::CreateRoute(const MediaSource::Id& source_id, ...@@ -289,7 +289,7 @@ void MediaRouterMojoImpl::CreateRoute(const MediaSource::Id& source_id,
} }
const MediaSource source(source_id); const MediaSource source(source_id);
if (source.IsTabMirroringSource()) { if (source.IsTabMirroringSource() || source.IsLocalFileSource()) {
// Ensure the CastRemotingConnector is created before mirroring starts. // Ensure the CastRemotingConnector is created before mirroring starts.
CastRemotingConnector* const connector = CastRemotingConnector* const connector =
CastRemotingConnector::Get(web_contents); CastRemotingConnector::Get(web_contents);
...@@ -659,6 +659,8 @@ bool MediaRouterMojoImpl::RegisterMediaSinksObserver( ...@@ -659,6 +659,8 @@ bool MediaRouterMojoImpl::RegisterMediaSinksObserver(
if (is_new_query) { if (is_new_query) {
for (const auto& provider : media_route_providers_) { for (const auto& provider : media_route_providers_) {
if (sink_availability_.IsAvailableForProvider(provider.first)) { if (sink_availability_.IsAvailableForProvider(provider.first)) {
// TODO(crbug.com/1090890): Don't allow MediaSource::ForAnyTab().id() to
// be passed here.
provider.second->StartObservingMediaSinks(source.id()); provider.second->StartObservingMediaSinks(source.id());
} }
} }
...@@ -687,6 +689,8 @@ void MediaRouterMojoImpl::UnregisterMediaSinksObserver( ...@@ -687,6 +689,8 @@ void MediaRouterMojoImpl::UnregisterMediaSinksObserver(
// Otherwise, the MRPs would have discarded the queries already. // Otherwise, the MRPs would have discarded the queries already.
for (const auto& provider : media_route_providers_) { for (const auto& provider : media_route_providers_) {
if (sink_availability_.IsAvailableForProvider(provider.first)) { if (sink_availability_.IsAvailableForProvider(provider.first)) {
// TODO(crbug.com/1090890): Don't allow MediaSource::ForAnyTab().id() to
// be passed here.
provider.second->StopObservingMediaSinks(source.id()); provider.second->StopObservingMediaSinks(source.id());
} }
} }
...@@ -839,8 +843,11 @@ void MediaRouterMojoImpl::OnSinkAvailabilityUpdated( ...@@ -839,8 +843,11 @@ void MediaRouterMojoImpl::OnSinkAvailabilityUpdated(
if (availability != SinkAvailability::UNAVAILABLE) { if (availability != SinkAvailability::UNAVAILABLE) {
// Sinks are now available. Tell the MRP to start all sink queries again. // Sinks are now available. Tell the MRP to start all sink queries again.
auto& provider = media_route_providers_[provider_id]; auto& provider = media_route_providers_[provider_id];
for (const auto& source_and_query : sinks_queries_) for (const auto& source_and_query : sinks_queries_) {
// TODO(crbug.com/1090890): Don't allow MediaSource::ForAnyTab().id() to
// be passed here.
provider->StartObservingMediaSinks(source_and_query.first); provider->StartObservingMediaSinks(source_and_query.first);
}
} else if (!sink_availability_.IsAvailable()) { } else if (!sink_availability_.IsAvailable()) {
// Sinks are no longer available. MRPs have already removed all sink // Sinks are no longer available. MRPs have already removed all sink
// queries. // queries.
...@@ -886,9 +893,12 @@ void MediaRouterMojoImpl::SyncStateToMediaRouteProvider( ...@@ -886,9 +893,12 @@ void MediaRouterMojoImpl::SyncStateToMediaRouteProvider(
const auto& provider = media_route_providers_[provider_id]; const auto& provider = media_route_providers_[provider_id];
// Sink queries. // Sink queries.
if (sink_availability_.IsAvailableForProvider(provider_id)) { if (sink_availability_.IsAvailableForProvider(provider_id)) {
for (const auto& it : sinks_queries_) for (const auto& it : sinks_queries_) {
// TODO(crbug.com/1090890): Don't allow MediaSource::ForAnyTab().id() to
// be passed here.
provider->StartObservingMediaSinks(it.first); provider->StartObservingMediaSinks(it.first);
} }
}
// Route queries. // Route queries.
for (const auto& it : routes_queries_) for (const auto& it : routes_queries_)
......
...@@ -87,7 +87,10 @@ void CastMediaRouteProvider::Init( ...@@ -87,7 +87,10 @@ void CastMediaRouteProvider::Init(
CastMediaRouteProvider::~CastMediaRouteProvider() { CastMediaRouteProvider::~CastMediaRouteProvider() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(sink_queries_.empty()); if (!sink_queries_.empty()) {
DCHECK_EQ(sink_queries_.size(), 1u);
DCHECK_EQ(sink_queries_.begin()->first, MediaSource::ForAnyTab().id());
}
} }
void CastMediaRouteProvider::CreateRoute(const std::string& source_id, void CastMediaRouteProvider::CreateRoute(const std::string& source_id,
......
...@@ -82,7 +82,7 @@ base::Optional<MirroringActivityRecord::MirroringType> GetMirroringType( ...@@ -82,7 +82,7 @@ base::Optional<MirroringActivityRecord::MirroringType> GetMirroringType(
return base::nullopt; return base::nullopt;
const auto source = route.media_source(); const auto source = route.media_source();
if (source.IsTabMirroringSource()) if (source.IsTabMirroringSource() || source.IsLocalFileSource())
return MirroringActivityRecord::MirroringType::kTab; return MirroringActivityRecord::MirroringType::kTab;
if (source.IsDesktopMirroringSource()) if (source.IsDesktopMirroringSource())
return MirroringActivityRecord::MirroringType::kDesktop; return MirroringActivityRecord::MirroringType::kDesktop;
......
...@@ -501,7 +501,7 @@ void MediaRouterViewsUI::InitCommon() { ...@@ -501,7 +501,7 @@ void MediaRouterViewsUI::InitCommon() {
// File mirroring is always available. // File mirroring is always available.
query_result_manager_->SetSourcesForCastMode( query_result_manager_->SetSourcesForCastMode(
MediaCastMode::LOCAL_FILE, {MediaSource::ForTab(0)}, origin); MediaCastMode::LOCAL_FILE, {MediaSource::ForLocalFile()}, origin);
SessionID::id_type tab_id = SessionID::id_type tab_id =
sessions::SessionTabHelper::IdForTab(initiator_).id(); sessions::SessionTabHelper::IdForTab(initiator_).id();
......
...@@ -68,6 +68,20 @@ MediaSource::MediaSource(const GURL& presentation_url) ...@@ -68,6 +68,20 @@ MediaSource::MediaSource(const GURL& presentation_url)
MediaSource::~MediaSource() = default; MediaSource::~MediaSource() = default;
// static
MediaSource MediaSource::ForLocalFile() {
// TODO(crbug.com/1090878): Use something more sane here. Fixing this
// requires tracking down other places where tab ID 0 is used to indicate
// local file casting.
//
// This probably isn't a source of bugs in practice, because tab IDs are
// generated by SessionIdGenerator, which appears to only produce positive
// values, but that fact isn't clearly documentated, and other parts of
// Chromium don't seem to rely on it, using -1 as the canonical invalid tab
// ID.
return MediaSource(base::StringPrintf(kTabMediaUrnFormat, 0));
}
// static // static
MediaSource MediaSource::ForAnyTab() { MediaSource MediaSource::ForAnyTab() {
return MediaSource(std::string(kAnyTabMediaUrn)); return MediaSource(std::string(kAnyTabMediaUrn));
...@@ -75,11 +89,17 @@ MediaSource MediaSource::ForAnyTab() { ...@@ -75,11 +89,17 @@ MediaSource MediaSource::ForAnyTab() {
// static // static
MediaSource MediaSource::ForTab(int tab_id) { MediaSource MediaSource::ForTab(int tab_id) {
// Ideally we shouldn't allow -1 as a tab ID, but in unit tests, a tab ID of
// -1 can show up when this function is called from
// CastHandler::StartObservingForSinks() because SessionTabHelper::IdForTab
// can return -1.
DCHECK_GE(tab_id, -1);
return MediaSource(base::StringPrintf(kTabMediaUrnFormat, tab_id)); return MediaSource(base::StringPrintf(kTabMediaUrnFormat, tab_id));
} }
// static // static
MediaSource MediaSource::ForDesktop(const std::string& desktop_media_id) { MediaSource MediaSource::ForDesktop(const std::string& desktop_media_id) {
DCHECK(!desktop_media_id.empty());
return MediaSource(kDesktopMediaUrnPrefix.as_string() + desktop_media_id); return MediaSource(kDesktopMediaUrnPrefix.as_string() + desktop_media_id);
} }
...@@ -94,10 +114,7 @@ MediaSource MediaSource::ForPresentationUrl(const GURL& presentation_url) { ...@@ -94,10 +114,7 @@ MediaSource MediaSource::ForPresentationUrl(const GURL& presentation_url) {
} }
bool MediaSource::IsTabMirroringSource() const { bool MediaSource::IsTabMirroringSource() const {
int tab_id; return id() == kAnyTabMediaUrn || TabId() > 0;
return id() == kAnyTabMediaUrn ||
(std::sscanf(id().c_str(), kTabMediaUrnFormat, &tab_id) == 1 &&
tab_id > 0);
} }
bool MediaSource::IsDesktopMirroringSource() const { bool MediaSource::IsDesktopMirroringSource() const {
...@@ -106,8 +123,9 @@ bool MediaSource::IsDesktopMirroringSource() const { ...@@ -106,8 +123,9 @@ bool MediaSource::IsDesktopMirroringSource() const {
base::CompareCase::SENSITIVE); base::CompareCase::SENSITIVE);
} }
bool MediaSource::IsMirroringSource() const { bool MediaSource::IsLocalFileSource() const {
return IsDesktopMirroringSource() || IsTabMirroringSource(); // TODO(crbug.com/1090878): Keep this method is sync with ForLocalFile().
return TabId() == 0;
} }
bool MediaSource::IsCastPresentationUrl() const { bool MediaSource::IsCastPresentationUrl() const {
...@@ -116,11 +134,9 @@ bool MediaSource::IsCastPresentationUrl() const { ...@@ -116,11 +134,9 @@ bool MediaSource::IsCastPresentationUrl() const {
} }
int MediaSource::TabId() const { int MediaSource::TabId() const {
int tab_id; int tab_id = -1;
if (sscanf(id_.c_str(), kTabMediaUrnFormat, &tab_id) == 1) sscanf(id_.c_str(), kTabMediaUrnFormat, &tab_id);
return tab_id; return tab_id;
else
return -1;
} }
base::Optional<std::string> MediaSource::DesktopStreamId() const { base::Optional<std::string> MediaSource::DesktopStreamId() const {
...@@ -131,11 +147,6 @@ base::Optional<std::string> MediaSource::DesktopStreamId() const { ...@@ -131,11 +147,6 @@ base::Optional<std::string> MediaSource::DesktopStreamId() const {
return base::nullopt; return base::nullopt;
} }
bool MediaSource::IsValid() const {
return IsTabMirroringSource() || IsDesktopMirroringSource() ||
IsValidPresentationUrl(GURL(id_));
}
bool MediaSource::IsDialSource() const { bool MediaSource::IsDialSource() const {
return url_.SchemeIs(kCastDialPresentationUrlScheme); return url_.SchemeIs(kCastDialPresentationUrlScheme);
} }
......
...@@ -90,6 +90,7 @@ class MediaSource { ...@@ -90,6 +90,7 @@ class MediaSource {
// Protocol-specific media source object creation. // Protocol-specific media source object creation.
// Returns MediaSource URI depending on the type of source. // Returns MediaSource URI depending on the type of source.
static MediaSource ForLocalFile();
static MediaSource ForAnyTab(); static MediaSource ForAnyTab();
static MediaSource ForTab(int tab_id); static MediaSource ForTab(int tab_id);
static MediaSource ForPresentationUrl(const GURL& presentation_url); static MediaSource ForPresentationUrl(const GURL& presentation_url);
...@@ -108,15 +109,23 @@ class MediaSource { ...@@ -108,15 +109,23 @@ class MediaSource {
// extension-based Cast MRP is removed. // extension-based Cast MRP is removed.
static MediaSource ForDesktop(); static MediaSource ForDesktop();
// Returns true if source outputs its content via tab mirroring and isn't a
// local file.
bool IsTabMirroringSource() const; bool IsTabMirroringSource() const;
// Returns true if source outputs its content via desktop mirroring.
bool IsDesktopMirroringSource() const; bool IsDesktopMirroringSource() const;
bool IsMirroringSource() const;
// Returns true if the source is a local file.
bool IsLocalFileSource() const;
// Returns true if this is represents a Cast Presentation URL. // Returns true if this is represents a Cast Presentation URL.
bool IsCastPresentationUrl() const; bool IsCastPresentationUrl() const;
// Parses the ID and returns the SessionTabHelper tab ID referencing a source // Parses the ID and returns the SessionTabHelper tab ID referencing a source
// tab. Returns a non-positive value on error. // tab. Don't rely on this method returning something useful without first
// calling IsTabMirroringSource(); it will return 0 for for ForLocalFile()
// source and -1 for non-tab sources or the ForAnyTab() source.
int TabId() const; int TabId() const;
// When this source was created by ForDesktop(string), returns a stream ID // When this source was created by ForDesktop(string), returns a stream ID
...@@ -125,10 +134,6 @@ class MediaSource { ...@@ -125,10 +134,6 @@ class MediaSource {
// returns base::nullopt. // returns base::nullopt.
base::Optional<std::string> DesktopStreamId() const; base::Optional<std::string> DesktopStreamId() const;
// Checks that this is a parseable URN and is of a known type.
// Does not deeper protocol-level syntax checks.
bool IsValid() const;
// Returns true this source outputs its content via DIAL. // Returns true this source outputs its content via DIAL.
// TODO(crbug.com/804419): Move this to in-browser DIAL/Cast MRP when we have // TODO(crbug.com/804419): Move this to in-browser DIAL/Cast MRP when we have
// one. // one.
......
...@@ -58,10 +58,9 @@ TEST(MediaSourceTest, ForAnyTab) { ...@@ -58,10 +58,9 @@ TEST(MediaSourceTest, ForAnyTab) {
auto source = MediaSource::ForAnyTab(); auto source = MediaSource::ForAnyTab();
EXPECT_EQ("urn:x-org.chromium.media:source:tab:*", source.id()); EXPECT_EQ("urn:x-org.chromium.media:source:tab:*", source.id());
EXPECT_EQ(-1, source.TabId()); EXPECT_EQ(-1, source.TabId());
EXPECT_TRUE(source.IsValid());
EXPECT_FALSE(source.IsDesktopMirroringSource()); EXPECT_FALSE(source.IsDesktopMirroringSource());
EXPECT_TRUE(source.IsTabMirroringSource()); EXPECT_TRUE(source.IsTabMirroringSource());
EXPECT_TRUE(source.IsMirroringSource()); EXPECT_FALSE(source.IsLocalFileSource());
EXPECT_FALSE(source.IsCastPresentationUrl()); EXPECT_FALSE(source.IsCastPresentationUrl());
EXPECT_FALSE(source.IsDialSource()); EXPECT_FALSE(source.IsDialSource());
} }
...@@ -70,10 +69,19 @@ TEST(MediaSourceTest, ForTab) { ...@@ -70,10 +69,19 @@ TEST(MediaSourceTest, ForTab) {
auto source = MediaSource::ForTab(123); auto source = MediaSource::ForTab(123);
EXPECT_EQ("urn:x-org.chromium.media:source:tab:123", source.id()); EXPECT_EQ("urn:x-org.chromium.media:source:tab:123", source.id());
EXPECT_EQ(123, source.TabId()); EXPECT_EQ(123, source.TabId());
EXPECT_TRUE(source.IsValid());
EXPECT_FALSE(source.IsDesktopMirroringSource()); EXPECT_FALSE(source.IsDesktopMirroringSource());
EXPECT_TRUE(source.IsTabMirroringSource()); EXPECT_TRUE(source.IsTabMirroringSource());
EXPECT_TRUE(source.IsMirroringSource()); EXPECT_FALSE(source.IsLocalFileSource());
EXPECT_FALSE(source.IsCastPresentationUrl());
EXPECT_FALSE(source.IsDialSource());
}
TEST(MediaSourceTest, ForLocalFile) {
auto source = MediaSource::ForLocalFile();
EXPECT_EQ("urn:x-org.chromium.media:source:tab:0", source.id());
EXPECT_FALSE(source.IsDesktopMirroringSource());
EXPECT_FALSE(source.IsTabMirroringSource());
EXPECT_TRUE(source.IsLocalFileSource());
EXPECT_FALSE(source.IsCastPresentationUrl()); EXPECT_FALSE(source.IsCastPresentationUrl());
EXPECT_FALSE(source.IsDialSource()); EXPECT_FALSE(source.IsDialSource());
} }
...@@ -82,10 +90,9 @@ TEST(MediaSourceTest, ForDesktop) { ...@@ -82,10 +90,9 @@ TEST(MediaSourceTest, ForDesktop) {
std::string media_id = "fakeMediaId"; std::string media_id = "fakeMediaId";
auto source = MediaSource::ForDesktop(media_id); auto source = MediaSource::ForDesktop(media_id);
EXPECT_EQ("urn:x-org.chromium.media:source:desktop:" + media_id, source.id()); EXPECT_EQ("urn:x-org.chromium.media:source:desktop:" + media_id, source.id());
EXPECT_TRUE(source.IsValid());
EXPECT_TRUE(source.IsDesktopMirroringSource()); EXPECT_TRUE(source.IsDesktopMirroringSource());
EXPECT_FALSE(source.IsTabMirroringSource()); EXPECT_FALSE(source.IsTabMirroringSource());
EXPECT_TRUE(source.IsMirroringSource()); EXPECT_FALSE(source.IsLocalFileSource());
EXPECT_FALSE(source.IsCastPresentationUrl()); EXPECT_FALSE(source.IsCastPresentationUrl());
EXPECT_FALSE(source.IsDialSource()); EXPECT_FALSE(source.IsDialSource());
} }
...@@ -95,23 +102,13 @@ TEST(MediaSourceTest, ForPresentationUrl) { ...@@ -95,23 +102,13 @@ TEST(MediaSourceTest, ForPresentationUrl) {
"https://www.example.com/presentation.html"; "https://www.example.com/presentation.html";
auto source = MediaSource::ForPresentationUrl(GURL(kPresentationUrl)); auto source = MediaSource::ForPresentationUrl(GURL(kPresentationUrl));
EXPECT_EQ(kPresentationUrl, source.id()); EXPECT_EQ(kPresentationUrl, source.id());
EXPECT_TRUE(source.IsValid());
EXPECT_FALSE(source.IsDesktopMirroringSource()); EXPECT_FALSE(source.IsDesktopMirroringSource());
EXPECT_FALSE(source.IsTabMirroringSource()); EXPECT_FALSE(source.IsTabMirroringSource());
EXPECT_FALSE(source.IsMirroringSource()); EXPECT_FALSE(source.IsLocalFileSource());
EXPECT_FALSE(source.IsCastPresentationUrl()); EXPECT_FALSE(source.IsCastPresentationUrl());
EXPECT_FALSE(source.IsDialSource()); EXPECT_FALSE(source.IsDialSource());
} }
TEST(MediaSourceTest, IsValid) {
// Disallowed scheme
EXPECT_FALSE(MediaSource::ForPresentationUrl(GURL("file:///some/local/path"))
.IsValid());
// Not a URL
EXPECT_FALSE(
MediaSource::ForPresentationUrl(GURL("totally not a url")).IsValid());
}
TEST(MediaSourceTest, IsCastPresentationUrl) { TEST(MediaSourceTest, IsCastPresentationUrl) {
EXPECT_TRUE(MediaSource(GURL("cast:233637DE")).IsCastPresentationUrl()); EXPECT_TRUE(MediaSource(GURL("cast:233637DE")).IsCastPresentationUrl());
EXPECT_TRUE( EXPECT_TRUE(
......
...@@ -353,7 +353,7 @@ CastAppInfo::CastAppInfo(const CastAppInfo& other) = default; ...@@ -353,7 +353,7 @@ CastAppInfo::CastAppInfo(const CastAppInfo& other) = default;
// static // static
std::unique_ptr<CastMediaSource> CastMediaSource::FromMediaSource( std::unique_ptr<CastMediaSource> CastMediaSource::FromMediaSource(
const MediaSource& source) { const MediaSource& source) {
if (source.IsTabMirroringSource()) if (source.IsTabMirroringSource() || source.IsLocalFileSource())
return CastMediaSourceForTabMirroring(source.id()); return CastMediaSourceForTabMirroring(source.id());
if (source.IsDesktopMirroringSource()) if (source.IsDesktopMirroringSource())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment