#include "content/renderer/media/inspector_media_event_handler.h"
#include <string>
#include <utility>
#include "base/json/json_writer.h"
namespace content {
namespace {
std::optional<blink::InspectorPlayerError> ErrorFromParams(
const base::Value::Dict& param) {
std::optional<int> code = param.FindInt(media::StatusConstants::kCodeKey);
const std::string* group =
param.FindString(media::StatusConstants::kGroupKey);
const std::string* message =
param.FindString(media::StatusConstants::kMsgKey);
CHECK(code.has_value() && group);
blink::InspectorPlayerErrors caused_by;
if (const auto* c = param.FindDict(media::StatusConstants::kCauseKey)) {
auto parsed_cause = ErrorFromParams(*c);
if (parsed_cause.has_value())
caused_by.push_back(*parsed_cause);
}
std::vector<blink::InspectorPlayerError::SourceLocation> stack_vec;
if (const auto* vec = param.FindList(media::StatusConstants::kStackKey)) {
for (const auto& loc : *vec) {
const auto& loc_dict = loc.GetDict();
const std::string* file =
loc_dict.FindString(media::StatusConstants::kFileKey);
std::optional<int> line =
loc_dict.FindInt(media::StatusConstants::kLineKey);
if (!file || !line.has_value())
continue;
blink::InspectorPlayerError::SourceLocation entry = {
blink::WebString::FromUTF8(*file), *line};
stack_vec.push_back(std::move(entry));
}
}
std::vector<blink::InspectorPlayerError::Data> data_vec;
if (auto* data = param.FindDict(media::StatusConstants::kDataKey)) {
for (const auto pair : *data) {
std::string json = base::WriteJson(pair.second).value_or("");
blink::InspectorPlayerError::Data entry = {
blink::WebString::FromUTF8(pair.first),
blink::WebString::FromUTF8(json)};
data_vec.push_back(std::move(entry));
}
}
blink::InspectorPlayerError result = {
blink::WebString::FromUTF8(*group),
*code,
blink::WebString::FromUTF8(message ? *message : ""),
std::move(stack_vec),
std::move(caused_by),
std::move(data_vec)};
return std::move(result);
}
blink::WebString ToString(const base::Value& value) {
if (value.is_string()) {
return blink::WebString::FromUTF8(value.GetString());
}
std::string output_str = base::WriteJson(value).value_or("");
return blink::WebString::FromUTF8(output_str);
}
blink::WebString ToString(const base::Value::Dict& value) {
std::string output_str = base::WriteJson(value).value_or("");
return blink::WebString::FromUTF8(output_str);
}
blink::InspectorPlayerMessage::Level LevelFromString(const std::string& level) {
if (level == "error")
return blink::InspectorPlayerMessage::Level::kError;
if (level == "warning")
return blink::InspectorPlayerMessage::Level::kWarning;
if (level == "info")
return blink::InspectorPlayerMessage::Level::kInfo;
CHECK_EQ(level, "debug");
return blink::InspectorPlayerMessage::Level::kDebug;
}
}
InspectorMediaEventHandler::InspectorMediaEventHandler(
blink::MediaInspectorContext* inspector_context,
int dom_node_id)
: inspector_context_(inspector_context),
player_id_(inspector_context_->CreatePlayer()) {
inspector_context->SetDomNodeIdForPlayer(player_id_, dom_node_id);
}
void InspectorMediaEventHandler::SendQueuedMediaEvents(
std::vector<media::MediaLogRecord> events_to_send) {
if (video_player_destroyed_)
return;
blink::InspectorPlayerProperties properties;
blink::InspectorPlayerMessages messages;
blink::InspectorPlayerEvents events;
blink::InspectorPlayerErrors errors;
for (media::MediaLogRecord event : events_to_send) {
switch (event.type) {
case media::MediaLogRecord::Type::kMessage: {
for (auto&& itr : event.params) {
blink::InspectorPlayerMessage msg = {
LevelFromString(itr.first),
blink::WebString::FromUTF8(itr.second.GetString())};
messages.emplace_back(std::move(msg));
}
break;
}
case media::MediaLogRecord::Type::kMediaPropertyChange: {
for (auto&& itr : event.params) {
blink::InspectorPlayerProperty prop = {
blink::WebString::FromUTF8(itr.first), ToString(itr.second)};
properties.emplace_back(std::move(prop));
}
break;
}
case media::MediaLogRecord::Type::kMediaEventTriggered: {
blink::InspectorPlayerEvent ev = {event.time, ToString(event.params)};
events.emplace_back(std::move(ev));
break;
}
case media::MediaLogRecord::Type::kMediaStatus: {
std::optional<blink::InspectorPlayerError> error =
ErrorFromParams(event.params);
if (error.has_value())
errors.emplace_back(std::move(*error));
}
}
}
if (!events.empty())
inspector_context_->NotifyPlayerEvents(player_id_, std::move(events));
if (!properties.empty())
inspector_context_->SetPlayerProperties(player_id_, std::move(properties));
if (!messages.empty())
inspector_context_->NotifyPlayerMessages(player_id_, std::move(messages));
if (!errors.empty())
inspector_context_->NotifyPlayerErrors(player_id_, std::move(errors));
}
void InspectorMediaEventHandler::OnWebMediaPlayerDestroyed() {
video_player_destroyed_ = true;
inspector_context_->DestroyPlayer(player_id_);
}
}