blob: 4c8f6b249c305f41905c7b0e67deadf1e9637eba [file] [log] [blame]
// 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 <stddef.h>
#include <string>
#include <vector>
#include "base/atomicops.h"
#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/trace_event/trace_event_impl.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "content/browser/devtools/devtools_traceable_screenshot.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_conversions.h"
namespace content {
namespace {
static size_t kFrameAreaLimit = 256000;
void FrameCaptured(base::TimeTicks timestamp, const SkBitmap& bitmap) {
if (bitmap.drawsNothing())
return;
if (DevToolsTraceableScreenshot::GetNumberOfInstances() >=
DevToolsFrameTraceRecorder::kMaximumNumberOfScreenshots) {
return;
}
TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID_AND_TIMESTAMP(
TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), "Screenshot", 1,
timestamp,
std::unique_ptr<base::trace_event::ConvertableToTraceFormat>(
new DevToolsTraceableScreenshot(bitmap)));
}
void CaptureFrame(RenderFrameHostImpl* host,
const viz::CompositorFrameMetadata& metadata) {
RenderWidgetHostViewBase* view =
static_cast<RenderWidgetHostViewBase*>(host->GetView());
if (!view)
return;
if (DevToolsTraceableScreenshot::GetNumberOfInstances() >=
DevToolsFrameTraceRecorder::kMaximumNumberOfScreenshots) {
return;
}
gfx::Size predicted_bitmap_size = gfx::ToCeiledSize(gfx::ScaleSize(
metadata.scrollable_viewport_size, metadata.page_scale_factor));
gfx::Size snapshot_size;
float area = predicted_bitmap_size.GetArea();
if (area <= kFrameAreaLimit) {
snapshot_size = predicted_bitmap_size;
} else {
double scale = sqrt(kFrameAreaLimit / area);
snapshot_size = gfx::ScaleToCeiledSize(predicted_bitmap_size, scale);
}
view->CopyFromSurface(gfx::Rect(), snapshot_size,
base::BindOnce(FrameCaptured, base::TimeTicks::Now()));
}
bool ScreenshotCategoryEnabled() {
bool enabled;
TRACE_EVENT_CATEGORY_GROUP_ENABLED(
TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), &enabled);
return enabled;
}
} // namespace
DevToolsFrameTraceRecorder::DevToolsFrameTraceRecorder() { }
DevToolsFrameTraceRecorder::~DevToolsFrameTraceRecorder() { }
void DevToolsFrameTraceRecorder::OnSynchronousSwapCompositorFrame(
RenderFrameHostImpl* host,
const viz::CompositorFrameMetadata& frame_metadata) {
if (!host || !ScreenshotCategoryEnabled()) {
last_metadata_.reset();
return;
}
bool is_new_trace;
TRACE_EVENT_IS_NEW_TRACE(&is_new_trace);
if (!is_new_trace && last_metadata_)
CaptureFrame(host, *last_metadata_);
last_metadata_.reset(new viz::CompositorFrameMetadata);
*last_metadata_ = frame_metadata.Clone();
}
} // namespace content