Skip to content

Commit

Permalink
Add InspectorMediaLog
Browse files Browse the repository at this point in the history
Splits event batching and event handling that was present in
RenderMediaLog so that a new InspectorMediaLog can share the behavior.
InspectorMediaLog converts the events from media::MediaLogEvent into
both blink::InspectorPlayerEvent and blink::InspectorPlayerProperty.

media::MediaLogEvent will eventually be refactored to look more like
the blink side of things, but not until the old media-internals page
is deprecated.

Adds a flag MediaInspectorLogging which when enabled replaces the
RenderMediaLog with InspectorMediaLog, which sends events to the chrome
devtools inspector instead of chrome://media-internals.

Bug: 794255
Change-Id: I51408ae16954e014a16e495d3b901ef2815daf75
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1679230
Commit-Queue: Ted Meyer <tmathmeyer@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Reviewed-by: Dan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#686545}
  • Loading branch information
tm-chromium authored and Commit Bot committed Aug 13, 2019
1 parent 895c676 commit cda47a0
Show file tree
Hide file tree
Showing 21 changed files with 499 additions and 85 deletions.
8 changes: 6 additions & 2 deletions content/renderer/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -180,16 +180,20 @@ target(link_target_type, "renderer") {
"media/audio/mojo_audio_output_ipc.h",
"media/audio_decoder.cc",
"media/audio_decoder.h",
"media/batching_media_log.cc",
"media/batching_media_log.h",
"media/gpu/gpu_video_accelerator_factories_impl.cc",
"media/gpu/gpu_video_accelerator_factories_impl.h",
"media/inspector_media_event_handler.cc",
"media/inspector_media_event_handler.h",
"media/media_factory.cc",
"media/media_factory.h",
"media/media_permission_dispatcher.cc",
"media/media_permission_dispatcher.h",
"media/render_media_client.cc",
"media/render_media_client.h",
"media/render_media_log.cc",
"media/render_media_log.h",
"media/render_media_event_handler.cc",
"media/render_media_event_handler.h",
"media/renderer_webaudiodevice_impl.cc",
"media/renderer_webaudiodevice_impl.h",
"media/renderer_webmediaplayer_delegate.cc",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/media/render_media_log.h"
#include "content/renderer/media/batching_media_log.h"

#include <sstream>

Expand All @@ -12,7 +12,6 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_client.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/render_thread.h"
Expand All @@ -36,22 +35,25 @@ void Log(media::MediaLogEvent* event) {

namespace content {

RenderMediaLog::RenderMediaLog(
BatchingMediaLog::BatchingMediaLog(
const GURL& security_origin,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
std::unique_ptr<EventHandler> event_handler)
: security_origin_(security_origin),
task_runner_(std::move(task_runner)),
event_handler_(std::move(event_handler)),
tick_clock_(base::DefaultTickClock::GetInstance()),
last_ipc_send_time_(tick_clock_->NowTicks()),
ipc_send_pending_(false) {
ipc_send_pending_(false),
weak_factory_(this) {
DCHECK(RenderThread::Get())
<< "RenderMediaLog must be constructed on the render thread";
<< "BatchingMediaLog must be constructed on the render thread";
// Pre-bind the WeakPtr on the right thread since we'll receive calls from
// other threads and don't want races.
weak_this_ = weak_factory_.GetWeakPtr();
}

RenderMediaLog::~RenderMediaLog() {
BatchingMediaLog::~BatchingMediaLog() {
DCHECK(task_runner_->BelongsToCurrentThread());
// AddEvent() could be in-flight on some other thread. Wait for it, and make
// sure that nobody else calls it.
Expand All @@ -64,7 +66,7 @@ RenderMediaLog::~RenderMediaLog() {
SendQueuedMediaEvents();
}

void RenderMediaLog::AddEventLocked(
void BatchingMediaLog::AddEventLocked(
std::unique_ptr<media::MediaLogEvent> event) {
Log(event.get());

Expand Down Expand Up @@ -109,7 +111,7 @@ void RenderMediaLog::AddEventLocked(
if (delay_for_next_ipc_send > base::TimeDelta()) {
task_runner_->PostDelayedTask(
FROM_HERE,
base::BindOnce(&RenderMediaLog::SendQueuedMediaEvents, weak_this_),
base::BindOnce(&BatchingMediaLog::SendQueuedMediaEvents, weak_this_),
delay_for_next_ipc_send);
return;
}
Expand All @@ -121,10 +123,10 @@ void RenderMediaLog::AddEventLocked(
}
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&RenderMediaLog::SendQueuedMediaEvents, weak_this_));
base::BindOnce(&BatchingMediaLog::SendQueuedMediaEvents, weak_this_));
}

std::string RenderMediaLog::GetErrorMessageLocked() {
std::string BatchingMediaLog::GetErrorMessageLocked() {
// Keep message structure in sync with
// HTMLMediaElement::BuildElementErrorMessage().
std::stringstream result;
Expand All @@ -143,21 +145,21 @@ std::string RenderMediaLog::GetErrorMessageLocked() {
return result.str();
}

void RenderMediaLog::RecordRapporWithSecurityOriginLocked(
void BatchingMediaLog::RecordRapporWithSecurityOriginLocked(
const std::string& metric) {
if (!task_runner_->BelongsToCurrentThread()) {
// Note that we don't post back to *Locked.
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&RenderMediaLog::RecordRapporWithSecurityOrigin,
base::BindOnce(&BatchingMediaLog::RecordRapporWithSecurityOrigin,
weak_this_, metric));
return;
}

GetContentClient()->renderer()->RecordRapporURL(metric, security_origin_);
}

void RenderMediaLog::SendQueuedMediaEvents() {
void BatchingMediaLog::SendQueuedMediaEvents() {
DCHECK(task_runner_->BelongsToCurrentThread());

std::vector<media::MediaLogEvent> events_to_send;
Expand All @@ -178,18 +180,14 @@ void RenderMediaLog::SendQueuedMediaEvents() {
if (events_to_send.empty())
return;

RenderThread::Get()->Send(new ViewHostMsg_MediaLogEvents(events_to_send));
event_handler_->SendQueuedMediaEvents(std::move(events_to_send));
}

void RenderMediaLog::SetTickClockForTesting(const base::TickClock* tick_clock) {
void BatchingMediaLog::SetTickClockForTesting(
const base::TickClock* tick_clock) {
base::AutoLock auto_lock(lock_);
tick_clock_ = tick_clock;
last_ipc_send_time_ = tick_clock_->NowTicks();
}

void RenderMediaLog::SetTaskRunnerForTesting(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
task_runner_ = task_runner;
}

} // namespace content
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_RENDERER_MEDIA_RENDER_MEDIA_LOG_H_
#define CONTENT_RENDERER_MEDIA_RENDER_MEDIA_LOG_H_
#ifndef CONTENT_RENDERER_MEDIA_BATCHING_MEDIA_LOG_H_
#define CONTENT_RENDERER_MEDIA_BATCHING_MEDIA_LOG_H_

#include <string>
#include <utility>
#include <vector>

#include "base/macros.h"
Expand All @@ -22,26 +23,27 @@ class TickClock;

namespace content {

// RenderMediaLog is an implementation of MediaLog that forwards events to the
// browser process, throttling as necessary.
//
// It also caches the last error events to support renderer-side reporting to
// entities like HTMLMediaElement and devtools console.
//
// To minimize the number of events sent over the wire, only the latest event
// added is sent for high frequency events (e.g., BUFFERED_EXTENTS_CHANGED).
// BatchingMediaLog is an implementation of MediaLog that sends messages
// grouped together in order to reduce IPC pressure.
// In order to subclass it, a subclass of the BatchingMediaLog::EventHandler
// should implement behavior when recieving a group of messages.
//
// It must be constructed on the render thread.
class CONTENT_EXPORT RenderMediaLog : public media::MediaLog {
class CONTENT_EXPORT BatchingMediaLog : public media::MediaLog {
public:
RenderMediaLog(const GURL& security_origin,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~RenderMediaLog() override;
class EventHandler {
public:
virtual ~EventHandler() = default;
virtual void SendQueuedMediaEvents(std::vector<media::MediaLogEvent>) = 0;
};

BatchingMediaLog(const GURL& security_origin,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
std::unique_ptr<EventHandler> impl);
~BatchingMediaLog() override;

// Will reset |last_ipc_send_time_| with the value of NowTicks().
void SetTickClockForTesting(const base::TickClock* tick_clock);
void SetTaskRunnerForTesting(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);

protected:
// MediaLog implementation.
Expand All @@ -59,6 +61,9 @@ class CONTENT_EXPORT RenderMediaLog : public media::MediaLog {

scoped_refptr<base::SingleThreadTaskRunner> task_runner_;

// impl for sending queued events.
std::unique_ptr<EventHandler> event_handler_;

// |lock_| protects access to all of the following member variables. It
// allows any render process thread to AddEvent(), while preserving their
// sequence for throttled send on |task_runner_| and coherent retrieval by
Expand Down Expand Up @@ -86,12 +91,12 @@ class CONTENT_EXPORT RenderMediaLog : public media::MediaLog {
// Holds a copy of the most recent PIPELINE_ERROR, if any.
std::unique_ptr<media::MediaLogEvent> last_pipeline_error_;

base::WeakPtr<RenderMediaLog> weak_this_;
base::WeakPtrFactory<RenderMediaLog> weak_factory_{this};
base::WeakPtr<BatchingMediaLog> weak_this_;
base::WeakPtrFactory<BatchingMediaLog> weak_factory_;

DISALLOW_COPY_AND_ASSIGN(RenderMediaLog);
DISALLOW_COPY_AND_ASSIGN(BatchingMediaLog);
};

} // namespace content

#endif // CONTENT_RENDERER_MEDIA_RENDER_MEDIA_LOG_H_
#endif // CONTENT_RENDERER_MEDIA_BATCHING_MEDIA_LOG_H_
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,41 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <tuple>

#include "content/renderer/media/batching_media_log.h"
#include "base/macros.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/test/test_mock_time_task_runner.h"
#include "content/common/view_messages.h"
#include "content/public/test/mock_render_thread.h"
#include "content/renderer/media/render_media_log.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"

namespace content {

class RenderMediaLogTest : public testing::Test {
class BatchingMediaLogTest;

class TestEventHandler : public BatchingMediaLog::EventHandler {
public:
RenderMediaLogTest()
: log_(GURL("http://foo.com"),
blink::scheduler::GetSingleThreadTaskRunnerForTesting()),
task_runner_(new base::TestMockTimeTaskRunner()) {
explicit TestEventHandler(BatchingMediaLogTest* test_cls)
: test_cls_(test_cls) {}
void SendQueuedMediaEvents(std::vector<media::MediaLogEvent> events) override;

private:
BatchingMediaLogTest* test_cls_;
};

class BatchingMediaLogTest : public testing::Test {
public:
BatchingMediaLogTest()
: task_runner_(new base::TestMockTimeTaskRunner()),
log_(GURL("http://foo.com"),
task_runner_,
std::make_unique<TestEventHandler>(this)) {
log_.SetTickClockForTesting(&tick_clock_);
log_.SetTaskRunnerForTesting(task_runner_);
}

~RenderMediaLogTest() override {
task_runner_->ClearPendingTasks();
}
~BatchingMediaLogTest() override { task_runner_->ClearPendingTasks(); }

void AddEvent(media::MediaLogEvent::Type type) {
log_.AddEvent(log_.CreateEvent(type));
Expand All @@ -41,32 +49,36 @@ class RenderMediaLogTest : public testing::Test {
task_runner_->FastForwardBy(delta);
}

int message_count() { return render_thread_.sink().message_count(); }
int message_count() { return add_events_count_; }

std::vector<media::MediaLogEvent> GetMediaLogEvents() {
const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching(
ViewHostMsg_MediaLogEvents::ID);
if (!msg) {
ADD_FAILURE() << "Did not find ViewHostMsg_MediaLogEvents IPC message";
return std::vector<media::MediaLogEvent>();
}

std::tuple<std::vector<media::MediaLogEvent>> events;
ViewHostMsg_MediaLogEvents::Read(msg, &events);
return std::get<0>(events);
std::vector<media::MediaLogEvent> return_events = std::move(events_);
return return_events;
}

private:
friend class TestEventHandler;
void AddEventsForTesting(std::vector<media::MediaLogEvent> events) {
events_.insert(events_.end(), events.begin(), events.end());
add_events_count_++;
}
int add_events_count_ = 0;
std::vector<media::MediaLogEvent> events_;
base::test::ScopedTaskEnvironment task_environment_;
MockRenderThread render_thread_;
base::SimpleTestTickClock tick_clock_;
RenderMediaLog log_;
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
BatchingMediaLog log_;

DISALLOW_COPY_AND_ASSIGN(RenderMediaLogTest);
DISALLOW_COPY_AND_ASSIGN(BatchingMediaLogTest);
};

TEST_F(RenderMediaLogTest, ThrottleSendingEvents) {
void TestEventHandler::SendQueuedMediaEvents(
std::vector<media::MediaLogEvent> events) {
test_cls_->AddEventsForTesting(events);
}

TEST_F(BatchingMediaLogTest, ThrottleSendingEvents) {
AddEvent(media::MediaLogEvent::LOAD);
EXPECT_EQ(0, message_count());

Expand All @@ -90,7 +102,7 @@ TEST_F(RenderMediaLogTest, ThrottleSendingEvents) {
EXPECT_EQ(1, message_count());
}

TEST_F(RenderMediaLogTest, EventSentWithoutDelayAfterIpcInterval) {
TEST_F(BatchingMediaLogTest, EventSentWithoutDelayAfterIpcInterval) {
AddEvent(media::MediaLogEvent::LOAD);
Advance(base::TimeDelta::FromMilliseconds(1000));
EXPECT_EQ(1, message_count());
Expand All @@ -102,7 +114,7 @@ TEST_F(RenderMediaLogTest, EventSentWithoutDelayAfterIpcInterval) {
EXPECT_EQ(2, message_count());
}

TEST_F(RenderMediaLogTest, DurationChanged) {
TEST_F(BatchingMediaLogTest, DurationChanged) {
AddEvent(media::MediaLogEvent::LOAD);
AddEvent(media::MediaLogEvent::SEEK);

Expand Down

0 comments on commit cda47a0

Please sign in to comment.