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 "extensions/browser/api/capture_web_contents_function.h"
7 #include "base/base64.h"
8 #include "base/strings/stringprintf.h"
9 #include "content/public/browser/render_view_host.h"
10 #include "content/public/browser/render_widget_host_view.h"
11 #include "content/public/browser/web_contents.h"
12 #include "extensions/browser/extension_function.h"
13 #include "extensions/common/constants.h"
14 #include "ui/gfx/codec/jpeg_codec.h"
15 #include "ui/gfx/codec/png_codec.h"
17 using content::RenderViewHost;
18 using content::RenderWidgetHost;
19 using content::RenderWidgetHostView;
20 using content::WebContents;
22 namespace extensions {
24 bool CaptureWebContentsFunction::HasPermission() {
28 bool CaptureWebContentsFunction::RunAsync() {
29 EXTENSION_FUNCTION_VALIDATE(args_);
31 context_id_ = extension_misc::kCurrentWindowId;
32 args_->GetInteger(0, &context_id_);
34 scoped_ptr<ImageDetails> image_details;
35 if (args_->GetSize() > 1) {
36 base::Value* spec = NULL;
37 EXTENSION_FUNCTION_VALIDATE(args_->Get(1, &spec) && spec);
38 image_details = ImageDetails::FromValue(*spec);
41 if (!IsScreenshotEnabled())
44 WebContents* contents = GetWebContentsForID(context_id_);
48 // The default format and quality setting used when encoding jpegs.
49 const ImageDetails::Format kDefaultFormat = ImageDetails::FORMAT_JPEG;
50 const int kDefaultQuality = 90;
52 image_format_ = kDefaultFormat;
53 image_quality_ = kDefaultQuality;
56 if (image_details->format != ImageDetails::FORMAT_NONE)
57 image_format_ = image_details->format;
58 if (image_details->quality.get())
59 image_quality_ = *image_details->quality;
62 RenderViewHost* render_view_host = contents->GetRenderViewHost();
63 RenderWidgetHostView* view = render_view_host->GetView();
65 OnCaptureFailure(FAILURE_REASON_VIEW_INVISIBLE);
68 render_view_host->CopyFromBackingStore(
70 view->GetViewBounds().size(),
71 base::Bind(&CaptureWebContentsFunction::CopyFromBackingStoreComplete,
77 void CaptureWebContentsFunction::CopyFromBackingStoreComplete(
79 const SkBitmap& bitmap) {
81 OnCaptureSuccess(bitmap);
84 OnCaptureFailure(FAILURE_REASON_UNKNOWN);
87 void CaptureWebContentsFunction::OnCaptureSuccess(const SkBitmap& bitmap) {
88 std::vector<unsigned char> data;
89 SkAutoLockPixels screen_capture_lock(bitmap);
91 std::string mime_type;
92 switch (image_format_) {
93 case ImageDetails::FORMAT_JPEG:
94 encoded = gfx::JPEGCodec::Encode(
95 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
96 gfx::JPEGCodec::FORMAT_SkBitmap,
99 static_cast<int>(bitmap.rowBytes()),
102 mime_type = kMimeTypeJpeg;
104 case ImageDetails::FORMAT_PNG:
106 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap,
107 true, // Discard transparency.
109 mime_type = kMimeTypePng;
112 NOTREACHED() << "Invalid image format.";
116 OnCaptureFailure(FAILURE_REASON_ENCODING_FAILED);
120 std::string base64_result;
121 base::StringPiece stream_as_string(
122 reinterpret_cast<const char*>(vector_as_array(&data)), data.size());
124 base::Base64Encode(stream_as_string, &base64_result);
125 base64_result.insert(
126 0, base::StringPrintf("data:%s;base64,", mime_type.c_str()));
127 SetResult(new base::StringValue(base64_result));
131 } // namespace extensions