Commit 514383cf authored by Takumi Fujimoto's avatar Takumi Fujimoto Committed by Commit Bot

Make ChromeDriver/DevTools APIs return sink structs

Make the get_sinks API return sink structs instead of sink name strings.

Bug: 963963
Change-Id: Idb6b555544f29aaa308b8d289335073348c653f5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1615982Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Reviewed-by: default avatarJohn Chen <johnchen@chromium.org>
Commit-Queue: Takumi Fujimoto <takumif@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664485}
parent 86b88ce2
...@@ -17,7 +17,9 @@ ...@@ -17,7 +17,9 @@
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
using media_router::MediaRoute;
using protocol::Response; using protocol::Response;
using protocol::Cast::Sink;
namespace { namespace {
...@@ -31,42 +33,44 @@ media_router::MediaRouter* GetMediaRouter(content::WebContents* web_contents) { ...@@ -31,42 +33,44 @@ media_router::MediaRouter* GetMediaRouter(content::WebContents* web_contents) {
class CastHandler::MediaRoutesObserver class CastHandler::MediaRoutesObserver
: public media_router::MediaRoutesObserver { : public media_router::MediaRoutesObserver {
public: public:
explicit MediaRoutesObserver(media_router::MediaRouter* router) MediaRoutesObserver(media_router::MediaRouter* router,
: media_router::MediaRoutesObserver(router) {} base::RepeatingClosure update_callback)
: media_router::MediaRoutesObserver(router),
update_callback_(std::move(update_callback)) {}
~MediaRoutesObserver() override = default; ~MediaRoutesObserver() override = default;
void OnRoutesUpdated(const std::vector<media_router::MediaRoute>& routes, const std::vector<MediaRoute>& routes() const { return routes_; }
const std::vector<media_router::MediaRoute::Id>&
joinable_route_ids) override {
routes_ = routes;
}
const std::vector<media_router::MediaRoute>& routes() const { private:
return routes_; void OnRoutesUpdated(
const std::vector<MediaRoute>& routes,
const std::vector<MediaRoute::Id>& joinable_route_ids) override {
routes_ = routes;
update_callback_.Run();
} }
private: std::vector<MediaRoute> routes_;
std::vector<media_router::MediaRoute> routes_; base::RepeatingClosure update_callback_;
}; };
class CastHandler::IssuesObserver : public media_router::IssuesObserver { class CastHandler::IssuesObserver : public media_router::IssuesObserver {
public: public:
explicit IssuesObserver( IssuesObserver(
media_router::MediaRouter* router, media_router::MediaRouter* router,
base::RepeatingCallback<void(const std::string& issue)> callback) base::RepeatingCallback<void(const std::string& issue)> update_callback)
: media_router::IssuesObserver(router->GetIssueManager()), : media_router::IssuesObserver(router->GetIssueManager()),
callback_(std::move(callback)) { update_callback_(std::move(update_callback)) {
Init(); Init();
} }
~IssuesObserver() override = default; ~IssuesObserver() override = default;
void OnIssue(const media_router::Issue& issue) override { void OnIssue(const media_router::Issue& issue) override {
callback_.Run(issue.info().title); update_callback_.Run(issue.info().title);
} }
void OnIssuesCleared() override { callback_.Run(std::string()); } void OnIssuesCleared() override { update_callback_.Run(std::string()); }
private: private:
base::RepeatingCallback<void(const std::string& issue)> callback_; base::RepeatingCallback<void(const std::string& issue)> update_callback_;
}; };
CastHandler::CastHandler(content::WebContents* web_contents, CastHandler::CastHandler(content::WebContents* web_contents,
...@@ -116,7 +120,7 @@ Response CastHandler::StopCasting(const std::string& in_sink_name) { ...@@ -116,7 +120,7 @@ Response CastHandler::StopCasting(const std::string& in_sink_name) {
const media_router::MediaSink::Id& sink_id = GetSinkIdByName(in_sink_name); const media_router::MediaSink::Id& sink_id = GetSinkIdByName(in_sink_name);
if (sink_id.empty()) if (sink_id.empty())
return Response::Error("Sink not found"); return Response::Error("Sink not found");
const media_router::MediaRoute::Id& route_id = GetRouteIdForSink(sink_id); const MediaRoute::Id& route_id = GetRouteIdForSink(sink_id);
if (route_id.empty()) if (route_id.empty())
return Response::Error("Route not found"); return Response::Error("Route not found");
router_->TerminateRoute(route_id); router_->TerminateRoute(route_id);
...@@ -127,7 +131,6 @@ Response CastHandler::StopCasting(const std::string& in_sink_name) { ...@@ -127,7 +131,6 @@ Response CastHandler::StopCasting(const std::string& in_sink_name) {
Response CastHandler::Enable(protocol::Maybe<std::string> in_presentation_url) { Response CastHandler::Enable(protocol::Maybe<std::string> in_presentation_url) {
EnsureInitialized(); EnsureInitialized();
StartObservingForSinks(std::move(in_presentation_url)); StartObservingForSinks(std::move(in_presentation_url));
StartObservingForIssues();
return Response::OK(); return Response::OK();
} }
...@@ -135,21 +138,15 @@ Response CastHandler::Disable() { ...@@ -135,21 +138,15 @@ Response CastHandler::Disable() {
query_result_manager_.reset(); query_result_manager_.reset();
routes_observer_.reset(); routes_observer_.reset();
issues_observer_.reset(); issues_observer_.reset();
for (const media_router::MediaRoute::Id& route_id : initiated_routes_) for (const MediaRoute::Id& route_id : initiated_routes_)
router_->TerminateRoute(route_id); router_->TerminateRoute(route_id);
return Response::OK(); return Response::OK();
} }
void CastHandler::OnResultsUpdated( void CastHandler::OnResultsUpdated(
const std::vector<media_router::MediaSinkWithCastModes>& sinks) { const std::vector<media_router::MediaSinkWithCastModes>& sinks) {
std::unique_ptr<protocol::Array<std::string>> sink_names =
protocol::Array<std::string>::create();
for (const media_router::MediaSinkWithCastModes& sink_with_modes : sinks)
sink_names->addItem(sink_with_modes.sink.name());
if (frontend_)
frontend_->SinksUpdated(std::move(sink_names));
sinks_ = sinks; sinks_ = sinks;
SendSinkUpdate();
} }
CastHandler::CastHandler(content::WebContents* web_contents) CastHandler::CastHandler(content::WebContents* web_contents)
...@@ -158,14 +155,18 @@ CastHandler::CastHandler(content::WebContents* web_contents) ...@@ -158,14 +155,18 @@ CastHandler::CastHandler(content::WebContents* web_contents)
weak_factory_(this) {} weak_factory_(this) {}
void CastHandler::EnsureInitialized() { void CastHandler::EnsureInitialized() {
if (initialized_) if (query_result_manager_)
return; return;
query_result_manager_ = query_result_manager_ =
std::make_unique<media_router::QueryResultManager>(router_); std::make_unique<media_router::QueryResultManager>(router_);
query_result_manager_->AddObserver(this); query_result_manager_->AddObserver(this);
routes_observer_ = std::make_unique<MediaRoutesObserver>(router_); routes_observer_ = std::make_unique<MediaRoutesObserver>(
initialized_ = true; router_, base::BindRepeating(&CastHandler::SendSinkUpdate,
base::Unretained(this)));
issues_observer_ = std::make_unique<IssuesObserver>(
router_,
base::BindRepeating(&CastHandler::OnIssue, base::Unretained(this)));
} }
void CastHandler::StartPresentation( void CastHandler::StartPresentation(
...@@ -202,18 +203,17 @@ media_router::MediaSink::Id CastHandler::GetSinkIdByName( ...@@ -202,18 +203,17 @@ media_router::MediaSink::Id CastHandler::GetSinkIdByName(
[&sink_name](const media_router::MediaSinkWithCastModes& sink) { [&sink_name](const media_router::MediaSinkWithCastModes& sink) {
return sink.sink.name() == sink_name; return sink.sink.name() == sink_name;
}); });
return it == sinks_.end() ? media_router::MediaSink::Id() : (*it).sink.id(); return it == sinks_.end() ? media_router::MediaSink::Id() : it->sink.id();
} }
media_router::MediaRoute::Id CastHandler::GetRouteIdForSink( MediaRoute::Id CastHandler::GetRouteIdForSink(
const media_router::MediaSink::Id& sink_id) const { const media_router::MediaSink::Id& sink_id) const {
const auto& routes = routes_observer_->routes(); const auto& routes = routes_observer_->routes();
auto it = std::find_if(routes.begin(), routes.end(), auto it = std::find_if(routes.begin(), routes.end(),
[&sink_id](const media_router::MediaRoute& route) { [&sink_id](const MediaRoute& route) {
return route.media_sink_id() == sink_id; return route.media_sink_id() == sink_id;
}); });
return it == routes.end() ? media_router::MediaRoute::Id() return it == routes.end() ? MediaRoute::Id() : it->media_route_id();
: (*it).media_route_id();
} }
void CastHandler::StartObservingForSinks( void CastHandler::StartObservingForSinks(
...@@ -234,10 +234,31 @@ void CastHandler::StartObservingForSinks( ...@@ -234,10 +234,31 @@ void CastHandler::StartObservingForSinks(
} }
} }
void CastHandler::StartObservingForIssues() { void CastHandler::SendSinkUpdate() {
issues_observer_ = std::make_unique<IssuesObserver>( if (!frontend_)
router_, return;
base::BindRepeating(&CastHandler::OnIssue, base::Unretained(this)));
std::unique_ptr<protocol::Array<Sink>> protocol_sinks =
protocol::Array<Sink>::create();
for (const media_router::MediaSinkWithCastModes& sink_with_modes : sinks_) {
auto route_it = std::find_if(
routes_observer_->routes().begin(), routes_observer_->routes().end(),
[&sink_with_modes](const MediaRoute& route) {
return route.media_sink_id() == sink_with_modes.sink.id();
});
std::string session = route_it == routes_observer_->routes().end()
? ""
: route_it->description();
std::unique_ptr<Sink> sink = Sink::Create()
.SetName(sink_with_modes.sink.name())
.SetId(sink_with_modes.sink.id())
.Build();
if (!session.empty())
sink->SetSession(session);
protocol_sinks->addItem(std::move(sink));
}
frontend_->SinksUpdated(std::move(protocol_sinks));
} }
void CastHandler::OnTabMirroringStarted( void CastHandler::OnTabMirroringStarted(
......
...@@ -69,7 +69,10 @@ class CastHandler : public protocol::Cast::Backend, ...@@ -69,7 +69,10 @@ class CastHandler : public protocol::Cast::Backend,
const media_router::MediaSink::Id& sink_id) const; const media_router::MediaSink::Id& sink_id) const;
void StartObservingForSinks(protocol::Maybe<std::string> presentation_url); void StartObservingForSinks(protocol::Maybe<std::string> presentation_url);
void StartObservingForIssues();
// Sends a notification that sinks (or their associated routes) have been
// updated.
void SendSinkUpdate();
void OnTabMirroringStarted( void OnTabMirroringStarted(
std::unique_ptr<StartTabMirroringCallback> callback, std::unique_ptr<StartTabMirroringCallback> callback,
...@@ -96,8 +99,6 @@ class CastHandler : public protocol::Cast::Backend, ...@@ -96,8 +99,6 @@ class CastHandler : public protocol::Cast::Backend,
std::unique_ptr<protocol::Cast::Frontend> frontend_; std::unique_ptr<protocol::Cast::Frontend> frontend_;
bool initialized_ = false;
base::WeakPtrFactory<CastHandler> weak_factory_; base::WeakPtrFactory<CastHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CastHandler); DISALLOW_COPY_AND_ASSIGN(CastHandler);
......
...@@ -21,7 +21,7 @@ Status CastTracker::OnEvent(DevToolsClient* client, ...@@ -21,7 +21,7 @@ Status CastTracker::OnEvent(DevToolsClient* client,
const std::string& method, const std::string& method,
const base::DictionaryValue& params) { const base::DictionaryValue& params) {
if (method == "Cast.sinksUpdated") { if (method == "Cast.sinksUpdated") {
const base::Value* sinks = params.FindKey("sinkNames"); const base::Value* sinks = params.FindKey("sinks");
if (sinks) if (sinks)
sinks_ = sinks->Clone(); sinks_ = sinks->Clone();
} else if (method == "Cast.issueUpdated") { } else if (method == "Cast.issueUpdated") {
......
...@@ -15,6 +15,14 @@ using testing::Return; ...@@ -15,6 +15,14 @@ using testing::Return;
namespace { namespace {
base::Value CreateSink(const std::string& name, const std::string& id) {
base::Value sink(base::Value::Type::DICTIONARY);
sink.SetKey("name", base::Value(name));
sink.SetKey("id", base::Value(id));
sink.SetKey("session", base::Value("Example session"));
return sink;
}
class MockDevToolsClient : public StubDevToolsClient { class MockDevToolsClient : public StubDevToolsClient {
public: public:
MOCK_METHOD2(SendCommand, MOCK_METHOD2(SendCommand,
...@@ -46,13 +54,13 @@ TEST_F(CastTrackerTest, OnSinksUpdated) { ...@@ -46,13 +54,13 @@ TEST_F(CastTrackerTest, OnSinksUpdated) {
EXPECT_EQ(0u, cast_tracker_->sinks().GetList().size()); EXPECT_EQ(0u, cast_tracker_->sinks().GetList().size());
base::Value sinks(base::Value::Type::LIST); base::Value sinks(base::Value::Type::LIST);
sinks.GetList().emplace_back(base::Value("sink1")); sinks.GetList().emplace_back(CreateSink("sink1", "1"));
sinks.GetList().emplace_back(base::Value("sink2")); sinks.GetList().emplace_back(CreateSink("sink2", "2"));
params.SetKey("sinkNames", std::move(sinks)); params.SetKey("sinks", std::move(sinks));
cast_tracker_->OnEvent(&devtools_client_, "Cast.sinksUpdated", params); cast_tracker_->OnEvent(&devtools_client_, "Cast.sinksUpdated", params);
EXPECT_EQ(2u, cast_tracker_->sinks().GetList().size()); EXPECT_EQ(2u, cast_tracker_->sinks().GetList().size());
params.SetKey("sinkNames", base::Value(base::Value::Type::LIST)); params.SetKey("sinks", base::Value(base::Value::Type::LIST));
cast_tracker_->OnEvent(&devtools_client_, "Cast.sinksUpdated", params); cast_tracker_->OnEvent(&devtools_client_, "Cast.sinksUpdated", params);
EXPECT_EQ(0u, cast_tracker_->sinks().GetList().size()); EXPECT_EQ(0u, cast_tracker_->sinks().GetList().size());
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
namespace base { namespace base {
class DictionaryValue; class DictionaryValue;
class Value; class Value;
} } // namespace base
struct Session; struct Session;
class Status; class Status;
...@@ -26,7 +26,8 @@ typedef base::Callback<Status(Session* session, ...@@ -26,7 +26,8 @@ typedef base::Callback<Status(Session* session,
WebView* web_view, WebView* web_view,
const base::DictionaryValue&, const base::DictionaryValue&,
std::unique_ptr<base::Value>*, std::unique_ptr<base::Value>*,
Timeout*)> WindowCommand; Timeout*)>
WindowCommand;
// Execute a Window Command on the target window. // Execute a Window Command on the target window.
Status ExecuteWindowCommand(const WindowCommand& command, Status ExecuteWindowCommand(const WindowCommand& command,
...@@ -426,7 +427,7 @@ Status ExecuteStopCasting(Session* session, ...@@ -426,7 +427,7 @@ Status ExecuteStopCasting(Session* session,
std::unique_ptr<base::Value>* value, std::unique_ptr<base::Value>* value,
Timeout* timeout); Timeout* timeout);
// Returns a list of names of Cast sinks that are available. // Returns a list of Cast sinks that are available.
Status ExecuteGetSinks(Session* session, Status ExecuteGetSinks(Session* session,
WebView* web_view, WebView* web_view,
const base::DictionaryValue& params, const base::DictionaryValue& params,
......
...@@ -1343,6 +1343,14 @@ experimental domain CacheStorage ...@@ -1343,6 +1343,14 @@ experimental domain CacheStorage
# functionalities. # functionalities.
experimental domain Cast experimental domain Cast
type Sink extends object
properties
string name
string id
# Text describing the current session. Present only if there is an active
# session on the sink.
optional string session
# Starts observing for sinks that can be used for tab mirroring, and if set, # Starts observing for sinks that can be used for tab mirroring, and if set,
# sinks compatible with |presentationUrl| as well. When sinks are found, a # sinks compatible with |presentationUrl| as well. When sinks are found, a
# |sinksUpdated| event is fired. # |sinksUpdated| event is fired.
...@@ -1375,7 +1383,7 @@ experimental domain Cast ...@@ -1375,7 +1383,7 @@ experimental domain Cast
# device or a software surface that you can cast to. # device or a software surface that you can cast to.
event sinksUpdated event sinksUpdated
parameters parameters
array of string sinkNames array of Sink sinks
# This is fired whenever the outstanding issue/error message changes. # This is fired whenever the outstanding issue/error message changes.
# |issueMessage| is empty if there is no issue. # |issueMessage| is empty if there is no issue.
......
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