1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/capture_web_contents_function.h"
7 #include "base/base64.h"
8 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
10 #include "chrome/common/extensions/extension_constants.h"
11 #include "content/public/browser/render_view_host.h"
12 #include "content/public/browser/render_widget_host_view.h"
13 #include "content/public/browser/web_contents.h"
14 #include "extensions/browser/extension_function.h"
15 #include "ui/gfx/codec/jpeg_codec.h"
16 #include "ui/gfx/codec/png_codec.h"
18 using content::RenderViewHost
;
19 using content::RenderWidgetHost
;
20 using content::RenderWidgetHostView
;
21 using content::WebContents
;
23 namespace extensions
{
25 CaptureWebContentsFunction::CaptureWebContentsFunction() {
28 CaptureWebContentsFunction::~CaptureWebContentsFunction() {
31 bool CaptureWebContentsFunction::HasPermission() {
35 bool CaptureWebContentsFunction::RunImpl() {
36 EXTENSION_FUNCTION_VALIDATE(args_
);
38 context_id_
= extension_misc::kCurrentWindowId
;
39 args_
->GetInteger(0, &context_id_
);
41 scoped_ptr
<ImageDetails
> image_details
;
42 if (args_
->GetSize() > 1) {
43 base::Value
* spec
= NULL
;
44 EXTENSION_FUNCTION_VALIDATE(args_
->Get(1, &spec
) && spec
);
45 image_details
= ImageDetails::FromValue(*spec
);
48 if (!IsScreenshotEnabled())
51 WebContents
* contents
= GetWebContentsForID(context_id_
);
55 // The default format and quality setting used when encoding jpegs.
56 const ImageDetails::Format kDefaultFormat
= ImageDetails::FORMAT_JPEG
;
57 const int kDefaultQuality
= 90;
59 image_format_
= kDefaultFormat
;
60 image_quality_
= kDefaultQuality
;
63 if (image_details
->format
!= ImageDetails::FORMAT_NONE
)
64 image_format_
= image_details
->format
;
65 if (image_details
->quality
.get())
66 image_quality_
= *image_details
->quality
;
69 RenderViewHost
* render_view_host
= contents
->GetRenderViewHost();
70 RenderWidgetHostView
* view
= render_view_host
->GetView();
72 OnCaptureFailure(FAILURE_REASON_VIEW_INVISIBLE
);
75 render_view_host
->CopyFromBackingStore(
77 view
->GetViewBounds().size(),
78 base::Bind(&CaptureWebContentsFunction::CopyFromBackingStoreComplete
,
83 void CaptureWebContentsFunction::CopyFromBackingStoreComplete(
85 const SkBitmap
& bitmap
) {
87 OnCaptureSuccess(bitmap
);
91 WebContents
* contents
= GetWebContentsForID(context_id_
);
93 OnCaptureFailure(FAILURE_REASON_CONTENT_NOT_FOUND
);
97 // Ask the renderer for a snapshot of the page.
98 RenderWidgetHost
* render_widget_host
= contents
->GetRenderViewHost();
99 render_widget_host
->GetSnapshotFromRenderer(
101 base::Bind(&CaptureWebContentsFunction::GetSnapshotFromRendererComplete
,
105 void CaptureWebContentsFunction::GetSnapshotFromRendererComplete(
107 const SkBitmap
& bitmap
) {
109 OnCaptureSuccess(bitmap
);
111 OnCaptureFailure(FAILURE_REASON_UNKNOWN
);
114 void CaptureWebContentsFunction::OnCaptureSuccess(const SkBitmap
& bitmap
) {
115 std::vector
<unsigned char> data
;
116 SkAutoLockPixels
screen_capture_lock(bitmap
);
117 bool encoded
= false;
118 std::string mime_type
;
119 switch (image_format_
) {
120 case ImageDetails::FORMAT_JPEG
:
121 encoded
= gfx::JPEGCodec::Encode(
122 reinterpret_cast<unsigned char*>(bitmap
.getAddr32(0, 0)),
123 gfx::JPEGCodec::FORMAT_SkBitmap
,
126 static_cast<int>(bitmap
.rowBytes()),
129 mime_type
= tabs_constants::kMimeTypeJpeg
;
131 case ImageDetails::FORMAT_PNG
:
132 encoded
= gfx::PNGCodec::EncodeBGRASkBitmap(
134 true, // Discard transparency.
136 mime_type
= tabs_constants::kMimeTypePng
;
139 NOTREACHED() << "Invalid image format.";
143 OnCaptureFailure(FAILURE_REASON_ENCODING_FAILED
);
147 std::string base64_result
;
148 base::StringPiece
stream_as_string(
149 reinterpret_cast<const char*>(vector_as_array(&data
)), data
.size());
151 base::Base64Encode(stream_as_string
, &base64_result
);
152 base64_result
.insert(0, base::StringPrintf("data:%s;base64,",
154 SetResult(new base::StringValue(base64_result
));
158 } // namespace extensions