| OLD | NEW |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/devtools/devtools_frame_trace_recorder.h" | 5 #include "content/browser/devtools/devtools_frame_trace_recorder.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/atomicops.h" | 10 #include "base/atomicops.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "ui/gfx/geometry/size_conversions.h" | 22 #include "ui/gfx/geometry/size_conversions.h" |
| 23 | 23 |
| 24 namespace content { | 24 namespace content { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 static base::subtle::Atomic32 frame_data_count = 0; | 28 static base::subtle::Atomic32 frame_data_count = 0; |
| 29 static int kMaximumFrameDataCount = 150; | 29 static int kMaximumFrameDataCount = 150; |
| 30 static size_t kFrameAreaLimit = 256000; | 30 static size_t kFrameAreaLimit = 256000; |
| 31 | 31 |
| 32 class TraceableDevToolsScreenshot |
| 33 : public base::trace_event::ConvertableToTraceFormat { |
| 34 public: |
| 35 TraceableDevToolsScreenshot(const SkBitmap& bitmap) : frame_(bitmap) {} |
| 36 |
| 37 void AppendAsTraceFormat(std::string* out) const override { |
| 38 out->append("\""); |
| 39 if (!frame_.drawsNothing()) { |
| 40 std::vector<unsigned char> data; |
| 41 SkAutoLockPixels lock_image(frame_); |
| 42 bool encoded = gfx::PNGCodec::Encode( |
| 43 reinterpret_cast<unsigned char*>(frame_.getAddr32(0, 0)), |
| 44 gfx::PNGCodec::FORMAT_SkBitmap, |
| 45 gfx::Size(frame_.width(), frame_.height()), |
| 46 frame_.width() * frame_.bytesPerPixel(), false, |
| 47 std::vector<gfx::PNGCodec::Comment>(), &data); |
| 48 if (encoded) { |
| 49 std::string encoded_data; |
| 50 base::Base64Encode( |
| 51 base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()), |
| 52 &encoded_data); |
| 53 out->append(encoded_data); |
| 54 } |
| 55 } |
| 56 out->append("\""); |
| 57 } |
| 58 |
| 59 private: |
| 60 ~TraceableDevToolsScreenshot() override { |
| 61 base::subtle::NoBarrier_AtomicIncrement(&frame_data_count, -1); |
| 62 } |
| 63 |
| 64 SkBitmap frame_; |
| 65 }; |
| 66 |
| 32 } // namespace | 67 } // namespace |
| 33 | 68 |
| 34 class DevToolsFrameTraceRecorderData | 69 class DevToolsFrameTraceRecorderData |
| 35 : public base::trace_event::ConvertableToTraceFormat { | 70 : public base::RefCounted<DevToolsFrameTraceRecorderData> { |
| 36 public: | 71 public: |
| 37 DevToolsFrameTraceRecorderData(const cc::CompositorFrameMetadata& metadata) | 72 DevToolsFrameTraceRecorderData(const cc::CompositorFrameMetadata& metadata) |
| 38 : metadata_(metadata), | 73 : metadata_(metadata), timestamp_(base::TraceTicks::Now()) {} |
| 39 weak_factory_(this) { | |
| 40 } | |
| 41 | |
| 42 base::WeakPtr<DevToolsFrameTraceRecorderData> GetWeakPtr() { | |
| 43 return weak_factory_.GetWeakPtr(); | |
| 44 } | |
| 45 | 74 |
| 46 void FrameCaptured(const SkBitmap& bitmap, ReadbackResponse response) { | 75 void FrameCaptured(const SkBitmap& bitmap, ReadbackResponse response) { |
| 47 if (response != READBACK_SUCCESS) | 76 if (response != READBACK_SUCCESS) |
| 48 return; | 77 return; |
| 49 int current_frame_count = base::subtle::NoBarrier_Load(&frame_data_count); | 78 int current_frame_count = base::subtle::NoBarrier_Load(&frame_data_count); |
| 50 if (current_frame_count >= kMaximumFrameDataCount) | 79 if (current_frame_count >= kMaximumFrameDataCount) |
| 51 return; | 80 return; |
| 52 frame_ = bitmap; | 81 if (bitmap.drawsNothing()) |
| 53 if (!frame_.drawsNothing()) | 82 return; |
| 54 base::subtle::NoBarrier_AtomicIncrement(&frame_data_count, 1); | 83 base::subtle::NoBarrier_AtomicIncrement(&frame_data_count, 1); |
| 84 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID_AND_TIMESTAMP( |
| 85 TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), "Screenshot", 1, |
| 86 timestamp_.ToInternalValue(), |
| 87 scoped_refptr<base::trace_event::ConvertableToTraceFormat>( |
| 88 new TraceableDevToolsScreenshot(bitmap))); |
| 55 } | 89 } |
| 56 | 90 |
| 57 void CaptureFrame(RenderFrameHostImpl* host) { | 91 void CaptureFrame(RenderFrameHostImpl* host) { |
| 58 RenderWidgetHostViewBase* view = | 92 RenderWidgetHostViewBase* view = |
| 59 static_cast<RenderWidgetHostViewBase*>(host->GetView()); | 93 static_cast<RenderWidgetHostViewBase*>(host->GetView()); |
| 60 if (!view) | 94 if (!view) |
| 61 return; | 95 return; |
| 62 int current_frame_count = base::subtle::NoBarrier_Load(&frame_data_count); | 96 int current_frame_count = base::subtle::NoBarrier_Load(&frame_data_count); |
| 63 if (current_frame_count >= kMaximumFrameDataCount) | 97 if (current_frame_count >= kMaximumFrameDataCount) |
| 64 return; | 98 return; |
| 65 float scale = metadata_.page_scale_factor; | 99 float scale = metadata_.page_scale_factor; |
| 66 float area = metadata_.scrollable_viewport_size.GetArea(); | 100 float area = metadata_.scrollable_viewport_size.GetArea(); |
| 67 if (area * scale * scale > kFrameAreaLimit) | 101 if (area * scale * scale > kFrameAreaLimit) |
| 68 scale = sqrt(kFrameAreaLimit / area); | 102 scale = sqrt(kFrameAreaLimit / area); |
| 69 gfx::Size snapshot_size(gfx::ToRoundedSize(gfx::ScaleSize( | 103 gfx::Size snapshot_size(gfx::ToRoundedSize(gfx::ScaleSize( |
| 70 metadata_.scrollable_viewport_size, scale))); | 104 metadata_.scrollable_viewport_size, scale))); |
| 71 view->CopyFromCompositingSurface(gfx::Rect(), snapshot_size, | 105 view->CopyFromCompositingSurface( |
| 72 base::Bind( | 106 gfx::Rect(), snapshot_size, |
| 73 &DevToolsFrameTraceRecorderData::FrameCaptured, | 107 base::Bind(&DevToolsFrameTraceRecorderData::FrameCaptured, this), |
| 74 GetWeakPtr()), | |
| 75 kN32_SkColorType); | 108 kN32_SkColorType); |
| 76 } | 109 } |
| 77 | 110 |
| 78 void AppendAsTraceFormat(std::string* out) const override { | |
| 79 out->append("\""); | |
| 80 if (!frame_.drawsNothing()) { | |
| 81 std::vector<unsigned char> data; | |
| 82 SkAutoLockPixels lock_image(frame_); | |
| 83 bool encoded = gfx::PNGCodec::Encode( | |
| 84 reinterpret_cast<unsigned char*>(frame_.getAddr32(0, 0)), | |
| 85 gfx::PNGCodec::FORMAT_SkBitmap, | |
| 86 gfx::Size(frame_.width(), frame_.height()), | |
| 87 frame_.width() * frame_.bytesPerPixel(), | |
| 88 false, std::vector<gfx::PNGCodec::Comment>(), &data); | |
| 89 if (encoded) { | |
| 90 std::string encoded_data; | |
| 91 base::Base64Encode( | |
| 92 base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()), | |
| 93 &encoded_data); | |
| 94 out->append(encoded_data); | |
| 95 } | |
| 96 } | |
| 97 out->append("\""); | |
| 98 } | |
| 99 | |
| 100 private: | 111 private: |
| 101 ~DevToolsFrameTraceRecorderData() override { | 112 friend class base::RefCounted<DevToolsFrameTraceRecorderData>; |
| 102 if (!frame_.drawsNothing()) | 113 ~DevToolsFrameTraceRecorderData() {} |
| 103 base::subtle::NoBarrier_AtomicIncrement(&frame_data_count, -1); | |
| 104 } | |
| 105 | 114 |
| 106 cc::CompositorFrameMetadata metadata_; | 115 cc::CompositorFrameMetadata metadata_; |
| 107 SkBitmap frame_; | 116 base::TraceTicks timestamp_; |
| 108 base::WeakPtrFactory<DevToolsFrameTraceRecorderData> weak_factory_; | |
| 109 | 117 |
| 110 DISALLOW_COPY_AND_ASSIGN(DevToolsFrameTraceRecorderData); | 118 DISALLOW_COPY_AND_ASSIGN(DevToolsFrameTraceRecorderData); |
| 111 }; | 119 }; |
| 112 | 120 |
| 113 DevToolsFrameTraceRecorder::DevToolsFrameTraceRecorder() { } | 121 DevToolsFrameTraceRecorder::DevToolsFrameTraceRecorder() { } |
| 114 | 122 |
| 115 DevToolsFrameTraceRecorder::~DevToolsFrameTraceRecorder() { } | 123 DevToolsFrameTraceRecorder::~DevToolsFrameTraceRecorder() { } |
| 116 | 124 |
| 117 void DevToolsFrameTraceRecorder::OnSwapCompositorFrame( | 125 void DevToolsFrameTraceRecorder::OnSwapCompositorFrame( |
| 118 RenderFrameHostImpl* host, | 126 RenderFrameHostImpl* host, |
| 119 const cc::CompositorFrameMetadata& frame_metadata) { | 127 const cc::CompositorFrameMetadata& frame_metadata) { |
| 120 if (!host) | 128 if (!host) |
| 121 return; | 129 return; |
| 122 | 130 |
| 123 bool enabled; | 131 bool enabled; |
| 124 TRACE_EVENT_CATEGORY_GROUP_ENABLED( | 132 TRACE_EVENT_CATEGORY_GROUP_ENABLED( |
| 125 TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), &enabled); | 133 TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), &enabled); |
| 126 if (!enabled) | 134 if (!enabled) { |
| 135 pending_frame_data_ = nullptr; |
| 127 return; | 136 return; |
| 128 | 137 } |
| 129 if (last_event_data_.get()) | 138 if (pending_frame_data_.get()) |
| 130 last_event_data_->CaptureFrame(host); | 139 pending_frame_data_->CaptureFrame(host); |
| 131 | 140 pending_frame_data_ = new DevToolsFrameTraceRecorderData(frame_metadata); |
| 132 scoped_refptr<DevToolsFrameTraceRecorderData> data( | |
| 133 new DevToolsFrameTraceRecorderData(frame_metadata)); | |
| 134 last_event_data_ = data->GetWeakPtr(); | |
| 135 TRACE_EVENT_INSTANT1( | |
| 136 TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), | |
| 137 "CaptureFrame", | |
| 138 TRACE_EVENT_SCOPE_THREAD, | |
| 139 "data", | |
| 140 scoped_refptr<base::trace_event::ConvertableToTraceFormat>(data)); | |
| 141 } | 141 } |
| 142 | 142 |
| 143 } // namespace content | 143 } // namespace content |
| OLD | NEW |