From f897f3221b58aebe1e2019c1521d891a93e4feb4 Mon Sep 17 00:00:00 2001 From: eustas Date: Tue, 10 Feb 2015 06:49:30 -0800 Subject: [PATCH] DevTools: add screenshot events to tracing. BUG= Review URL: https://codereview.chromium.org/895403002 Cr-Commit-Position: refs/heads/master@{#315560} --- .../devtools/devtools_frame_trace_recorder.cc | 141 +++++++++++++++++++++ .../devtools/devtools_frame_trace_recorder.h | 36 ++++++ .../devtools/render_frame_devtools_agent_host.cc | 6 + .../devtools/render_frame_devtools_agent_host.h | 2 + content/content_browser.gypi | 2 + 5 files changed, 187 insertions(+) create mode 100644 content/browser/devtools/devtools_frame_trace_recorder.cc create mode 100644 content/browser/devtools/devtools_frame_trace_recorder.h diff --git a/content/browser/devtools/devtools_frame_trace_recorder.cc b/content/browser/devtools/devtools_frame_trace_recorder.cc new file mode 100644 index 000000000000..0626bfa8fdbc --- /dev/null +++ b/content/browser/devtools/devtools_frame_trace_recorder.cc @@ -0,0 +1,141 @@ +// Copyright (c) 2015 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. + +#include "content/browser/devtools/devtools_frame_trace_recorder.h" + +#include +#include + +#include "base/atomicops.h" +#include "base/base64.h" +#include "base/bind.h" +#include "base/memory/ref_counted.h" +#include "base/trace_event/trace_event_impl.h" +#include "cc/output/compositor_frame_metadata.h" +#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/browser/renderer_host/render_widget_host_view_base.h" +#include "content/public/browser/readback_types.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/codec/png_codec.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/geometry/size_conversions.h" + +namespace content { + +namespace { + +static base::subtle::Atomic32 frame_data_count = 0; +static int kMaximumFrameDataCount = 150; +static size_t kFrameAreaLimit = 256000; + +} // namespace + +class DevToolsFrameTraceRecorderData + : public base::trace_event::ConvertableToTraceFormat { + public: + DevToolsFrameTraceRecorderData(const cc::CompositorFrameMetadata& metadata) + : metadata_(metadata), + weak_factory_(this) { + } + + base::WeakPtr GetWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + + void FrameCaptured(const SkBitmap& bitmap, ReadbackResponse response) { + if (response != READBACK_SUCCESS) + return; + int current_frame_count = base::subtle::NoBarrier_Load(&frame_data_count); + if (current_frame_count >= kMaximumFrameDataCount) + return; + frame_ = bitmap; + if (!frame_.drawsNothing()) + base::subtle::NoBarrier_AtomicIncrement(&frame_data_count, 1); + } + + void CaptureFrame(RenderFrameHostImpl* host) { + RenderWidgetHostViewBase* view = + static_cast(host->GetView()); + if (!view) + return; + int current_frame_count = base::subtle::NoBarrier_Load(&frame_data_count); + if (current_frame_count >= kMaximumFrameDataCount) + return; + float scale = metadata_.page_scale_factor; + float area = metadata_.scrollable_viewport_size.GetArea(); + if (area * scale * scale > kFrameAreaLimit) + scale = sqrt(kFrameAreaLimit / area); + gfx::Size snapshot_size(gfx::ToRoundedSize(gfx::ScaleSize( + metadata_.scrollable_viewport_size, scale))); + view->CopyFromCompositingSurface(gfx::Rect(), snapshot_size, + base::Bind( + &DevToolsFrameTraceRecorderData::FrameCaptured, + GetWeakPtr()), + kN32_SkColorType); + } + + void AppendAsTraceFormat(std::string* out) const override { + out->append("\""); + std::vector data; + SkAutoLockPixels lock_image(frame_); + bool encoded = gfx::PNGCodec::Encode( + reinterpret_cast(frame_.getAddr32(0, 0)), + gfx::PNGCodec::FORMAT_SkBitmap, + gfx::Size(frame_.width(), frame_.height()), + frame_.width() * frame_.bytesPerPixel(), + false, std::vector(), &data); + if (encoded) { + std::string encoded_data; + base::Base64Encode( + base::StringPiece(reinterpret_cast(&data[0]), data.size()), + &encoded_data); + out->append(encoded_data); + } + out->append("\""); + } + + private: + ~DevToolsFrameTraceRecorderData() override { + if (!frame_.drawsNothing()) + base::subtle::NoBarrier_AtomicIncrement(&frame_data_count, -1); + } + + cc::CompositorFrameMetadata metadata_; + SkBitmap frame_; + base::WeakPtrFactory weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsFrameTraceRecorderData); +}; + +DevToolsFrameTraceRecorder::DevToolsFrameTraceRecorder() { } + +DevToolsFrameTraceRecorder::~DevToolsFrameTraceRecorder() { } + +void DevToolsFrameTraceRecorder::OnSwapCompositorFrame( + RenderFrameHostImpl* host, + const cc::CompositorFrameMetadata& frame_metadata) { + if (!host) + return; + + bool enabled; + TRACE_EVENT_CATEGORY_GROUP_ENABLED( + TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), &enabled); + if (!enabled) + return; + + if (last_event_data_.get()) + last_event_data_->CaptureFrame(host); + + scoped_refptr data( + new DevToolsFrameTraceRecorderData(frame_metadata)); + last_event_data_ = data->GetWeakPtr(); + TRACE_EVENT_INSTANT1( + TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), + "CaptureFrame", + TRACE_EVENT_SCOPE_THREAD, + "data", + scoped_refptr(data)); +} + +} // namespace content diff --git a/content/browser/devtools/devtools_frame_trace_recorder.h b/content/browser/devtools/devtools_frame_trace_recorder.h new file mode 100644 index 000000000000..88c4311b8525 --- /dev/null +++ b/content/browser/devtools/devtools_frame_trace_recorder.h @@ -0,0 +1,36 @@ +// Copyright (c) 2015 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. + +#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRAME_TRACE_RECORDER_H_ +#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRAME_TRACE_RECORDER_H_ + +#include "base/compiler_specific.h" +#include "base/memory/weak_ptr.h" + +namespace cc { +class CompositorFrameMetadata; +} + +namespace content { + +class DevToolsFrameTraceRecorderData; +class RenderFrameHostImpl; + +class DevToolsFrameTraceRecorder { + public: + DevToolsFrameTraceRecorder(); + ~DevToolsFrameTraceRecorder(); + + void OnSwapCompositorFrame( + RenderFrameHostImpl* host, + const cc::CompositorFrameMetadata& frame_metadata); + + private: + base::WeakPtr last_event_data_; + DISALLOW_COPY_AND_ASSIGN(DevToolsFrameTraceRecorder); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRAME_TRACE_RECORDER_H_ diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 924e23e2dfa7..da04255766e6 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc @@ -9,6 +9,7 @@ #include "base/lazy_instance.h" #include "base/strings/utf_string_conversions.h" #include "content/browser/child_process_security_policy_impl.h" +#include "content/browser/devtools/devtools_frame_trace_recorder.h" #include "content/browser/devtools/devtools_manager.h" #include "content/browser/devtools/protocol/devtools_protocol_handler.h" #include "content/browser/devtools/protocol/dom_handler.h" @@ -135,6 +136,7 @@ RenderFrameDevToolsAgentHost::RenderFrameDevToolsAgentHost(RenderFrameHost* rfh) protocol_handler_(new DevToolsProtocolHandler( base::Bind(&RenderFrameDevToolsAgentHost::DispatchOnInspectorFrontend, base::Unretained(this)))), + frame_trace_recorder_(new DevToolsFrameTraceRecorder()), reattaching_(false) { DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher(); dispatcher->SetDOMHandler(dom_handler_.get()); @@ -496,6 +498,8 @@ void RenderFrameDevToolsAgentHost::OnSwapCompositorFrame( if (!ViewHostMsg_SwapCompositorFrame::Read(&message, ¶m)) return; page_handler_->OnSwapCompositorFrame(get<1>(param).metadata); + frame_trace_recorder_->OnSwapCompositorFrame( + render_frame_host_, get<1>(param).metadata); } void RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame( @@ -503,6 +507,8 @@ void RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame( if (!render_frame_host_) return; page_handler_->OnSwapCompositorFrame(frame_metadata); + frame_trace_recorder_->OnSwapCompositorFrame( + render_frame_host_, frame_metadata); } bool RenderFrameDevToolsAgentHost::HasRenderFrameHost( diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h index fba63685402f..df0f47fc9f33 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.h +++ b/content/browser/devtools/render_frame_devtools_agent_host.h @@ -23,6 +23,7 @@ class CompositorFrameMetadata; namespace content { class BrowserContext; +class DevToolsFrameTraceRecorder; class DevToolsProtocolHandler; class RenderFrameHost; class RenderFrameHostImpl; @@ -125,6 +126,7 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost scoped_ptr power_handler_; scoped_ptr tracing_handler_; scoped_ptr protocol_handler_; + scoped_ptr frame_trace_recorder_; #if defined(OS_ANDROID) scoped_ptr power_save_blocker_; #endif diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 977907cf60ae..e4a179575d93 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -452,6 +452,8 @@ 'browser/cocoa/system_hotkey_map.mm', 'browser/devtools/devtools_agent_host_impl.cc', 'browser/devtools/devtools_agent_host_impl.h', + 'browser/devtools/devtools_frame_trace_recorder.cc', + 'browser/devtools/devtools_frame_trace_recorder.h', 'browser/devtools/devtools_frontend_host_impl.cc', 'browser/devtools/devtools_frontend_host_impl.h', 'browser/devtools/devtools_http_handler_impl.cc', -- 2.11.4.GIT