summaryrefslogtreecommitdiff
path: root/chromium/chrome/common/media_router
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/common/media_router')
-rw-r--r--chromium/chrome/common/media_router/discovery/media_sink_internal.cc1
-rw-r--r--chromium/chrome/common/media_router/discovery/media_sink_service_base.cc1
-rw-r--r--chromium/chrome/common/media_router/issue.h1
-rw-r--r--chromium/chrome/common/media_router/media_route.cc6
-rw-r--r--chromium/chrome/common/media_router/media_route.h11
-rw-r--r--chromium/chrome/common/media_router/media_route_unittest.cc4
-rw-r--r--chromium/chrome/common/media_router/media_source.cc73
-rw-r--r--chromium/chrome/common/media_router/media_source.h25
-rw-r--r--chromium/chrome/common/media_router/media_source_unittest.cc38
-rw-r--r--chromium/chrome/common/media_router/mojom/BUILD.gn6
-rw-r--r--chromium/chrome/common/media_router/mojom/logger.mojom53
-rw-r--r--chromium/chrome/common/media_router/mojom/media_router.mojom33
-rw-r--r--chromium/chrome/common/media_router/mojom/media_router_mojom_traits.cc2
-rw-r--r--chromium/chrome/common/media_router/mojom/media_router_mojom_traits.h13
-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
-rw-r--r--chromium/chrome/common/media_router/route_request_result.h2
18 files changed, 280 insertions, 98 deletions
diff --git a/chromium/chrome/common/media_router/discovery/media_sink_internal.cc b/chromium/chrome/common/media_router/discovery/media_sink_internal.cc
index e39d0ebddbb..2c5c8ed5bc5 100644
--- a/chromium/chrome/common/media_router/discovery/media_sink_internal.cc
+++ b/chromium/chrome/common/media_router/discovery/media_sink_internal.cc
@@ -7,6 +7,7 @@
#include <new>
#include "base/logging.h"
+#include "base/notreached.h"
#include "base/strings/string_util.h"
namespace media_router {
diff --git a/chromium/chrome/common/media_router/discovery/media_sink_service_base.cc b/chromium/chrome/common/media_router/discovery/media_sink_service_base.cc
index a5a34a53330..e7eba6f2bb5 100644
--- a/chromium/chrome/common/media_router/discovery/media_sink_service_base.cc
+++ b/chromium/chrome/common/media_router/discovery/media_sink_service_base.cc
@@ -4,6 +4,7 @@
#include "chrome/common/media_router/discovery/media_sink_service_base.h"
#include "base/bind.h"
+#include "base/logging.h"
#include "chrome/common/media_router/media_route.h"
#include <vector>
diff --git a/chromium/chrome/common/media_router/issue.h b/chromium/chrome/common/media_router/issue.h
index 8b790b6cf72..840c3747645 100644
--- a/chromium/chrome/common/media_router/issue.h
+++ b/chromium/chrome/common/media_router/issue.h
@@ -8,7 +8,6 @@
#include <string>
#include <vector>
-#include "base/logging.h"
#include "chrome/common/media_router/media_route.h"
#include "chrome/common/media_router/media_sink.h"
diff --git a/chromium/chrome/common/media_router/media_route.cc b/chromium/chrome/common/media_router/media_route.cc
index eac0e63063e..82ba6ac02c2 100644
--- a/chromium/chrome/common/media_router/media_route.cc
+++ b/chromium/chrome/common/media_router/media_route.cc
@@ -33,9 +33,7 @@ MediaRoute::MediaRoute(const MediaRoute::Id& media_route_id,
media_sink_id_(media_sink_id),
description_(description),
is_local_(is_local),
- for_display_(for_display),
- is_incognito_(false),
- is_local_presentation_(false) {}
+ for_display_(for_display) {}
MediaRoute::MediaRoute(const MediaRoute& other) = default;
@@ -51,7 +49,7 @@ bool MediaRoute::operator==(const MediaRoute& other) const {
description_ == other.description_ && is_local_ == other.is_local_ &&
controller_type_ == other.controller_type_ &&
for_display_ == other.for_display_ &&
- is_incognito_ == other.is_incognito_ &&
+ is_off_the_record_ == other.is_off_the_record_ &&
is_local_presentation_ == other.is_local_presentation_;
}
diff --git a/chromium/chrome/common/media_router/media_route.h b/chromium/chrome/common/media_router/media_route.h
index 1d8f946885f..16e19e7485c 100644
--- a/chromium/chrome/common/media_router/media_route.h
+++ b/chromium/chrome/common/media_router/media_route.h
@@ -8,7 +8,6 @@
#include <iosfwd>
#include <string>
-#include "base/logging.h"
#include "base/values.h"
#include "chrome/common/media_router/media_sink.h"
#include "chrome/common/media_router/media_source.h"
@@ -96,8 +95,10 @@ class MediaRoute {
void set_for_display(bool for_display) { for_display_ = for_display; }
bool for_display() const { return for_display_; }
- void set_incognito(bool is_incognito) { is_incognito_ = is_incognito; }
- bool is_incognito() const { return is_incognito_; }
+ void set_off_the_record(bool is_off_the_record) {
+ is_off_the_record_ = is_off_the_record;
+ }
+ bool is_off_the_record() const { return is_off_the_record_; }
void set_local_presentation(bool is_local_presentation) {
is_local_presentation_ = is_local_presentation;
@@ -139,8 +140,8 @@ class MediaRoute {
// |true| if the route can be displayed in the UI.
bool for_display_ = false;
- // |true| if the route was created by an incognito profile.
- bool is_incognito_ = false;
+ // |true| if the route was created by an OffTheRecord profile.
+ bool is_off_the_record_ = false;
// |true| if the presentation associated with this route is a local
// presentation.
diff --git a/chromium/chrome/common/media_router/media_route_unittest.cc b/chromium/chrome/common/media_router/media_route_unittest.cc
index 01a94be6b1e..86a3ca8c758 100644
--- a/chromium/chrome/common/media_router/media_route_unittest.cc
+++ b/chromium/chrome/common/media_router/media_route_unittest.cc
@@ -47,10 +47,10 @@ TEST(MediaRouteTest, TestEquals) {
false);
EXPECT_FALSE(route1 == route5);
- // Same as route1 with different incognito.
+ // Same as route1 with different off_the_record.
MediaRoute route6(kRouteId1, media_source, "sinkId", "Description", true,
false);
- route6.set_incognito(true);
+ route6.set_off_the_record(true);
EXPECT_FALSE(route1 == route6);
}
diff --git a/chromium/chrome/common/media_router/media_source.cc b/chromium/chrome/common/media_router/media_source.cc
index 05a71cabcbd..1f7dd3f4d2c 100644
--- a/chromium/chrome/common/media_router/media_source.cc
+++ b/chromium/chrome/common/media_router/media_source.cc
@@ -21,13 +21,12 @@ namespace {
// Prefixes used to format and detect various protocols' media source URNs.
// See: https://www.ietf.org/rfc/rfc3406.txt
+constexpr char kAnyTabMediaUrn[] = "urn:x-org.chromium.media:source:tab:*";
constexpr char kTabMediaUrnFormat[] = "urn:x-org.chromium.media:source:tab:%d";
constexpr base::StringPiece kDesktopMediaUrnPrefix =
"urn:x-org.chromium.media:source:desktop:";
constexpr base::StringPiece kUnknownDesktopMediaUrn =
"urn:x-org.chromium.media:source:desktop";
-constexpr char kTabRemotingUrnFormat[] =
- "urn:x-org.chromium.media:source:tab_content_remoting:%d";
// List of non-http(s) schemes that are allowed in a Presentation URL.
constexpr std::array<const char* const, 5> kAllowedSchemes{
@@ -70,17 +69,37 @@ MediaSource::MediaSource(const GURL& presentation_url)
MediaSource::~MediaSource() = default;
// static
-MediaSource MediaSource::ForTab(int tab_id) {
- return MediaSource(base::StringPrintf(kTabMediaUrnFormat, tab_id));
+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
-MediaSource MediaSource::ForTabContentRemoting(int tab_id) {
- return MediaSource(base::StringPrintf(kTabRemotingUrnFormat, tab_id));
+MediaSource MediaSource::ForAnyTab() {
+ return MediaSource(std::string(kAnyTabMediaUrn));
+}
+
+// static
+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));
}
// static
MediaSource MediaSource::ForDesktop(const std::string& desktop_media_id) {
+ DCHECK(!desktop_media_id.empty());
return MediaSource(kDesktopMediaUrnPrefix.as_string() + desktop_media_id);
}
@@ -94,20 +113,19 @@ MediaSource MediaSource::ForPresentationUrl(const GURL& presentation_url) {
return MediaSource(presentation_url);
}
+bool MediaSource::IsTabMirroringSource() const {
+ return id() == kAnyTabMediaUrn || TabId() > 0;
+}
+
bool MediaSource::IsDesktopMirroringSource() const {
return id() == kUnknownDesktopMediaUrn ||
base::StartsWith(id(), kDesktopMediaUrnPrefix,
base::CompareCase::SENSITIVE);
}
-bool MediaSource::IsTabMirroringSource() const {
- int tab_id;
- return std::sscanf(id_.c_str(), kTabMediaUrnFormat, &tab_id) == 1 &&
- tab_id > 0;
-}
-
-bool MediaSource::IsMirroringSource() const {
- return IsDesktopMirroringSource() || IsTabMirroringSource();
+bool MediaSource::IsLocalFileSource() const {
+ // TODO(crbug.com/1090878): Keep this method is sync with ForLocalFile().
+ return TabId() == 0;
}
bool MediaSource::IsCastPresentationUrl() const {
@@ -116,13 +134,9 @@ bool MediaSource::IsCastPresentationUrl() const {
}
int MediaSource::TabId() const {
- int tab_id;
- if (sscanf(id_.c_str(), kTabMediaUrnFormat, &tab_id) == 1)
- return tab_id;
- else if (sscanf(id_.c_str(), kTabRemotingUrnFormat, &tab_id) == 1)
- return tab_id;
- else
- return -1;
+ int tab_id = -1;
+ sscanf(id_.c_str(), kTabMediaUrnFormat, &tab_id);
+ return tab_id;
}
base::Optional<std::string> MediaSource::DesktopStreamId() const {
@@ -133,11 +147,6 @@ base::Optional<std::string> MediaSource::DesktopStreamId() const {
return base::nullopt;
}
-bool MediaSource::IsValid() const {
- return TabId() > 0 || IsDesktopMirroringSource() ||
- IsValidPresentationUrl(GURL(id_));
-}
-
bool MediaSource::IsDialSource() const {
return url_.SchemeIs(kCastDialPresentationUrlScheme);
}
@@ -146,4 +155,16 @@ std::string MediaSource::AppNameFromDialSource() const {
return IsDialSource() ? url_.path() : "";
}
+std::string MediaSource::TruncateForLogging(size_t max_length) const {
+ const std::string origin = url_.GetOrigin().spec();
+ if (!origin.empty())
+ return origin.substr(0, max_length);
+ // TODO(takumif): Keep the query string by redacting PII. The query string may
+ // contain info useful for debugging such as the required capabilities.
+ const size_t query_start_index = id_.find("?");
+ const size_t length =
+ query_start_index == std::string::npos ? max_length : query_start_index;
+ return id_.substr(0, length);
+}
+
} // namespace media_router
diff --git a/chromium/chrome/common/media_router/media_source.h b/chromium/chrome/common/media_router/media_source.h
index edf2111d694..6fdbea9350d 100644
--- a/chromium/chrome/common/media_router/media_source.h
+++ b/chromium/chrome/common/media_router/media_source.h
@@ -90,8 +90,9 @@ class MediaSource {
// Protocol-specific media source object creation.
// Returns MediaSource URI depending on the type of source.
+ static MediaSource ForLocalFile();
+ static MediaSource ForAnyTab();
static MediaSource ForTab(int tab_id);
- static MediaSource ForTabContentRemoting(int tab_id);
static MediaSource ForPresentationUrl(const GURL& presentation_url);
// Creates a media source for a specific desktop.
@@ -108,16 +109,23 @@ class MediaSource {
// extension-based Cast MRP is removed.
static MediaSource ForDesktop();
- // Returns true if source outputs its content via mirroring.
- bool IsDesktopMirroringSource() const;
+ // Returns true if source outputs its content via tab mirroring and isn't a
+ // local file.
bool IsTabMirroringSource() const;
- bool IsMirroringSource() const;
+
+ // Returns true if source outputs its content via desktop mirroring.
+ bool IsDesktopMirroringSource() const;
+
+ // Returns true if the source is a local file.
+ bool IsLocalFileSource() const;
// Returns true if this is represents a Cast Presentation URL.
bool IsCastPresentationUrl() const;
// 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;
// When this source was created by ForDesktop(string), returns a stream ID
@@ -126,10 +134,6 @@ class MediaSource {
// returns base::nullopt.
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.
// TODO(crbug.com/804419): Move this to in-browser DIAL/Cast MRP when we have
// one.
@@ -139,6 +143,9 @@ class MediaSource {
// 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;
+
private:
MediaSource::Id id_;
GURL url_;
diff --git a/chromium/chrome/common/media_router/media_source_unittest.cc b/chromium/chrome/common/media_router/media_source_unittest.cc
index 11825581c17..c4609881dab 100644
--- a/chromium/chrome/common/media_router/media_source_unittest.cc
+++ b/chromium/chrome/common/media_router/media_source_unittest.cc
@@ -54,25 +54,34 @@ TEST(MediaSourceTest, ConstructorWithURLString) {
EXPECT_EQ(test_url, source1.url());
}
+TEST(MediaSourceTest, ForAnyTab) {
+ auto source = MediaSource::ForAnyTab();
+ EXPECT_EQ("urn:x-org.chromium.media:source:tab:*", source.id());
+ EXPECT_EQ(-1, source.TabId());
+ EXPECT_FALSE(source.IsDesktopMirroringSource());
+ EXPECT_TRUE(source.IsTabMirroringSource());
+ EXPECT_FALSE(source.IsLocalFileSource());
+ EXPECT_FALSE(source.IsCastPresentationUrl());
+ EXPECT_FALSE(source.IsDialSource());
+}
+
TEST(MediaSourceTest, ForTab) {
auto source = MediaSource::ForTab(123);
EXPECT_EQ("urn:x-org.chromium.media:source:tab:123", source.id());
EXPECT_EQ(123, source.TabId());
- EXPECT_TRUE(source.IsValid());
EXPECT_FALSE(source.IsDesktopMirroringSource());
EXPECT_TRUE(source.IsTabMirroringSource());
- EXPECT_TRUE(source.IsMirroringSource());
+ EXPECT_FALSE(source.IsLocalFileSource());
EXPECT_FALSE(source.IsCastPresentationUrl());
EXPECT_FALSE(source.IsDialSource());
}
-TEST(MediaSourceTest, ForTabContentRemoting) {
- auto source = MediaSource::ForTabContentRemoting(123);
- EXPECT_EQ(123, source.TabId());
- EXPECT_TRUE(source.IsValid());
+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_FALSE(source.IsMirroringSource());
+ EXPECT_TRUE(source.IsLocalFileSource());
EXPECT_FALSE(source.IsCastPresentationUrl());
EXPECT_FALSE(source.IsDialSource());
}
@@ -81,10 +90,9 @@ TEST(MediaSourceTest, ForDesktop) {
std::string media_id = "fakeMediaId";
auto source = MediaSource::ForDesktop(media_id);
EXPECT_EQ("urn:x-org.chromium.media:source:desktop:" + media_id, source.id());
- EXPECT_TRUE(source.IsValid());
EXPECT_TRUE(source.IsDesktopMirroringSource());
EXPECT_FALSE(source.IsTabMirroringSource());
- EXPECT_TRUE(source.IsMirroringSource());
+ EXPECT_FALSE(source.IsLocalFileSource());
EXPECT_FALSE(source.IsCastPresentationUrl());
EXPECT_FALSE(source.IsDialSource());
}
@@ -94,23 +102,13 @@ TEST(MediaSourceTest, ForPresentationUrl) {
"https://www.example.com/presentation.html";
auto source = MediaSource::ForPresentationUrl(GURL(kPresentationUrl));
EXPECT_EQ(kPresentationUrl, source.id());
- EXPECT_TRUE(source.IsValid());
EXPECT_FALSE(source.IsDesktopMirroringSource());
EXPECT_FALSE(source.IsTabMirroringSource());
- EXPECT_FALSE(source.IsMirroringSource());
+ EXPECT_FALSE(source.IsLocalFileSource());
EXPECT_FALSE(source.IsCastPresentationUrl());
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) {
EXPECT_TRUE(MediaSource(GURL("cast:233637DE")).IsCastPresentationUrl());
EXPECT_TRUE(
diff --git a/chromium/chrome/common/media_router/mojom/BUILD.gn b/chromium/chrome/common/media_router/mojom/BUILD.gn
index 7463f0776a5..b6cb091ba85 100644
--- a/chromium/chrome/common/media_router/mojom/BUILD.gn
+++ b/chromium/chrome/common/media_router/mojom/BUILD.gn
@@ -4,6 +4,11 @@
import("//mojo/public/tools/bindings/mojom.gni")
+mojom("logger") {
+ sources = [ "logger.mojom" ]
+ public_deps = [ "//mojo/public/mojom/base" ]
+}
+
mojom("media_controller") {
sources = [
"media_controller.mojom",
@@ -21,6 +26,7 @@ mojom("media_router") {
sources = [ "media_router.mojom" ]
public_deps = [
+ ":logger",
":media_controller",
"//components/mirroring/mojom:host",
"//media/mojo/mojom:mirror_service_remoting",
diff --git a/chromium/chrome/common/media_router/mojom/logger.mojom b/chromium/chrome/common/media_router/mojom/logger.mojom
new file mode 100644
index 00000000000..340062e46ca
--- /dev/null
+++ b/chromium/chrome/common/media_router/mojom/logger.mojom
@@ -0,0 +1,53 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module media_router.mojom;
+
+import "mojo/public/mojom/base/time.mojom";
+
+enum LogCategory {
+ kDiscovery,
+ kRoute,
+ kMirroring,
+ kUi,
+};
+
+// Collects logs from Media Router components such as Media Route Providers.
+// The implementation lives in the browser process.
+interface Logger {
+ // Records a log entry of "info" severity. The severities are "info",
+ // "warning", and "error" in increasing order.
+ // |component|: This is usually the name of the class that is emitting the
+ // log, such as "CastSessionTracker".
+ // |message|: The log message.
+ // |sink_id|: ID of the media sink associated with this log. May be empty if
+ // the log is not associated with a sink.
+ // |media_source|: ID of the media source, which may be of the format
+ // "cast:ABCDEFGH?arg1=val1" (app ID and query params) for Cast sessions,
+ // or the receiver page URL in the case of presentations. May be empty.
+ // |session_id|: ID of the Cast or presentation session associated with this
+ // log. May be empty.
+ LogInfo(LogCategory category,
+ string component,
+ string message,
+ string sink_id,
+ string media_source,
+ string session_id);
+
+ // Records a log entry of "warning" severity.
+ LogWarning(LogCategory category,
+ string component,
+ string message,
+ string sink_id,
+ string media_source,
+ string session_id);
+
+ // Records a log entry of "error" severity.
+ LogError(LogCategory category,
+ string component,
+ string message,
+ string sink_id,
+ string media_source,
+ string session_id);
+};
diff --git a/chromium/chrome/common/media_router/mojom/media_router.mojom b/chromium/chrome/common/media_router/mojom/media_router.mojom
index 95e445dfa20..0219ea1b462 100644
--- a/chromium/chrome/common/media_router/mojom/media_router.mojom
+++ b/chromium/chrome/common/media_router/mojom/media_router.mojom
@@ -4,6 +4,7 @@
module media_router.mojom;
+import "chrome/common/media_router/mojom/logger.mojom";
import "chrome/common/media_router/mojom/media_controller.mojom";
import "chrome/common/media_router/mojom/media_status.mojom";
import "components/mirroring/mojom/mirroring_service_host.mojom";
@@ -122,8 +123,8 @@ struct MediaRoute {
RouteControllerType controller_type;
// Set to true if this route should be displayed for |media_sink_id| in UI.
bool for_display;
- // Set to true if this route was created by an incognito profile.
- bool is_incognito;
+ // Set to true if this route was created by an OffTheRecord profile.
+ bool is_off_the_record;
// Set to true if this route corresponds to a local presentation.
bool is_local_presentation;
};
@@ -208,7 +209,7 @@ enum RouteRequestResultCode {
ROUTE_NOT_FOUND,
SINK_NOT_FOUND,
INVALID_ORIGIN,
- INCOGNITO_MISMATCH,
+ OFF_THE_RECORD_MISMATCH,
NO_SUPPORTED_PROVIDER,
CANCELLED,
ROUTE_ALREADY_EXISTS,
@@ -307,7 +308,8 @@ interface MediaRouteProvider {
// If |timeout| is positive, it will be used in place of the default timeout
// defined by Media Route Provider Manager.
//
- // If |incognito| is true, the request was made by an incognito profile.
+ // If |off_the_record| is true, the request was made by an OffTheRecord
+ // profile.
//
// If the operation was successful, |route| will be defined and |error_text|
// will be null. If the operation failed, |route| will be null and
@@ -323,7 +325,7 @@ interface MediaRouteProvider {
url.mojom.Origin origin,
int32 tab_id,
mojo_base.mojom.TimeDelta timeout,
- bool incognito) =>
+ bool off_the_record) =>
(MediaRoute? route,
RoutePresentationConnection? connection,
string? error_text,
@@ -338,8 +340,8 @@ interface MediaRouteProvider {
// If |timeout| is positive, it will be used in place of the default timeout
// defined by Media Route Provider Manager.
//
- // If the route request was created by an incognito profile,
- // |incognito| must be true.
+ // If the route request was created by an OffTheRecord profile,
+ // |off_the_record| must be true.
//
// If the operation was successful, |route| will be defined and |error_text|
// will be null. If the operation failed, |route| will be null and
@@ -353,7 +355,7 @@ interface MediaRouteProvider {
url.mojom.Origin origin,
int32 tab_id,
mojo_base.mojom.TimeDelta timeout,
- bool incognito) =>
+ bool off_the_record) =>
(MediaRoute? route,
RoutePresentationConnection? connection,
string? error_text,
@@ -373,8 +375,8 @@ interface MediaRouteProvider {
// defined by Media Route Provider Manager; see CreateRoute for additional
// documentation.
//
- // If the route request was created by an incognito profile,
- // |incognito| must be true.
+ // If the route request was created by an OffTheRecord profile,
+ // |off_the_record| must be true.
//
// If the operation was successful, |route| will be defined and
// |error_text| will be null. If the operation failed, |route| will be null
@@ -391,7 +393,7 @@ interface MediaRouteProvider {
url.mojom.Origin origin,
int32 tab_id,
mojo_base.mojom.TimeDelta timeout,
- bool incognito) =>
+ bool off_the_record) =>
(MediaRoute? route,
RoutePresentationConnection? connection,
string? error_text,
@@ -597,6 +599,15 @@ interface MediaRouter {
// Returns current status of media sink service in JSON format.
GetMediaSinkServiceStatus() => (string status);
+ // The logger can be used to add entries to logs returned by GetLogs().
+ GetLogger(pending_receiver<Logger> receiver);
+
+ // Returns a JSON array of logs collected by Media Router components.
+ // Serializing the logs requires allocating extra memory, so it should only be
+ // called under limited circumstances, such as when the user is submitting a
+ // feedback report.
+ GetLogsAsString() => (string logs);
+
// Called to get a mirroring.mojom.MirroringServiceHost. These APIs are used
// by Media Router extension to start mirroring through the mirroring service.
// TODO(http://crbug.com/809249): Remove these APIs when native Cast MRP with
diff --git a/chromium/chrome/common/media_router/mojom/media_router_mojom_traits.cc b/chromium/chrome/common/media_router/mojom/media_router_mojom_traits.cc
index ecb173bd65c..a48bece3a32 100644
--- a/chromium/chrome/common/media_router/mojom/media_router_mojom_traits.cc
+++ b/chromium/chrome/common/media_router/mojom/media_router_mojom_traits.cc
@@ -216,7 +216,7 @@ bool StructTraits<media_router::mojom::MediaRouteDataView,
out->set_local(data.is_local());
out->set_for_display(data.for_display());
- out->set_incognito(data.is_incognito());
+ out->set_off_the_record(data.is_off_the_record());
out->set_local_presentation(data.is_local_presentation());
return true;
diff --git a/chromium/chrome/common/media_router/mojom/media_router_mojom_traits.h b/chromium/chrome/common/media_router/mojom/media_router_mojom_traits.h
index cc7c383a797..76ab7593602 100644
--- a/chromium/chrome/common/media_router/mojom/media_router_mojom_traits.h
+++ b/chromium/chrome/common/media_router/mojom/media_router_mojom_traits.h
@@ -397,8 +397,8 @@ struct StructTraits<media_router::mojom::MediaRouteDataView,
return route.for_display();
}
- static bool is_incognito(const media_router::MediaRoute& route) {
- return route.is_incognito();
+ static bool is_off_the_record(const media_router::MediaRoute& route) {
+ return route.is_off_the_record();
}
static bool is_local_presentation(const media_router::MediaRoute& route) {
@@ -426,8 +426,9 @@ struct EnumTraits<media_router::mojom::RouteRequestResultCode,
return media_router::mojom::RouteRequestResultCode::SINK_NOT_FOUND;
case media_router::RouteRequestResult::INVALID_ORIGIN:
return media_router::mojom::RouteRequestResultCode::INVALID_ORIGIN;
- case media_router::RouteRequestResult::INCOGNITO_MISMATCH:
- return media_router::mojom::RouteRequestResultCode::INCOGNITO_MISMATCH;
+ case media_router::RouteRequestResult::OFF_THE_RECORD_MISMATCH:
+ return media_router::mojom::RouteRequestResultCode::
+ OFF_THE_RECORD_MISMATCH;
case media_router::RouteRequestResult::NO_SUPPORTED_PROVIDER:
return media_router::mojom::RouteRequestResultCode::
NO_SUPPORTED_PROVIDER;
@@ -467,8 +468,8 @@ struct EnumTraits<media_router::mojom::RouteRequestResultCode,
case media_router::mojom::RouteRequestResultCode::INVALID_ORIGIN:
*output = media_router::RouteRequestResult::INVALID_ORIGIN;
return true;
- case media_router::mojom::RouteRequestResultCode::INCOGNITO_MISMATCH:
- *output = media_router::RouteRequestResult::INCOGNITO_MISMATCH;
+ case media_router::mojom::RouteRequestResultCode::OFF_THE_RECORD_MISMATCH:
+ *output = media_router::RouteRequestResult::OFF_THE_RECORD_MISMATCH;
return true;
case media_router::mojom::RouteRequestResultCode::NO_SUPPORTED_PROVIDER:
*output = media_router::RouteRequestResult::NO_SUPPORTED_PROVIDER;
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
diff --git a/chromium/chrome/common/media_router/route_request_result.h b/chromium/chrome/common/media_router/route_request_result.h
index 855dfa8e1f0..65761d726a2 100644
--- a/chromium/chrome/common/media_router/route_request_result.h
+++ b/chromium/chrome/common/media_router/route_request_result.h
@@ -42,7 +42,7 @@ class RouteRequestResult {
ROUTE_NOT_FOUND = 3,
SINK_NOT_FOUND = 4,
INVALID_ORIGIN = 5,
- INCOGNITO_MISMATCH = 6,
+ OFF_THE_RECORD_MISMATCH = 6,
NO_SUPPORTED_PROVIDER = 7,
CANCELLED = 8,
ROUTE_ALREADY_EXISTS = 9,