• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/extensions/api/capture_web_contents_function.h"
6 
7 #include "base/base64.h"
8 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
10 #include "content/public/browser/render_view_host.h"
11 #include "content/public/browser/render_widget_host_view.h"
12 #include "content/public/browser/web_contents.h"
13 #include "extensions/browser/extension_function.h"
14 #include "extensions/common/constants.h"
15 #include "ui/gfx/codec/jpeg_codec.h"
16 #include "ui/gfx/codec/png_codec.h"
17 
18 using content::RenderViewHost;
19 using content::RenderWidgetHost;
20 using content::RenderWidgetHostView;
21 using content::WebContents;
22 
23 namespace extensions {
24 
CaptureWebContentsFunction()25 CaptureWebContentsFunction::CaptureWebContentsFunction() {
26 }
27 
~CaptureWebContentsFunction()28 CaptureWebContentsFunction::~CaptureWebContentsFunction() {
29 }
30 
HasPermission()31 bool CaptureWebContentsFunction::HasPermission() {
32   return true;
33 }
34 
RunAsync()35 bool CaptureWebContentsFunction::RunAsync() {
36   EXTENSION_FUNCTION_VALIDATE(args_);
37 
38   context_id_ = extension_misc::kCurrentWindowId;
39   args_->GetInteger(0, &context_id_);
40 
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);
46   }
47 
48   if (!IsScreenshotEnabled())
49     return false;
50 
51   WebContents* contents = GetWebContentsForID(context_id_);
52   if (!contents)
53     return false;
54 
55   // The default format and quality setting used when encoding jpegs.
56   const ImageDetails::Format kDefaultFormat = ImageDetails::FORMAT_JPEG;
57   const int kDefaultQuality = 90;
58 
59   image_format_ = kDefaultFormat;
60   image_quality_ = kDefaultQuality;
61 
62   if (image_details) {
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;
67   }
68 
69   RenderViewHost* render_view_host = contents->GetRenderViewHost();
70   RenderWidgetHostView* view = render_view_host->GetView();
71   if (!view) {
72     OnCaptureFailure(FAILURE_REASON_VIEW_INVISIBLE);
73     return false;
74   }
75   render_view_host->CopyFromBackingStore(
76       gfx::Rect(),
77       view->GetViewBounds().size(),
78       base::Bind(&CaptureWebContentsFunction::CopyFromBackingStoreComplete,
79                  this),
80       SkBitmap::kARGB_8888_Config);
81   return true;
82 }
83 
CopyFromBackingStoreComplete(bool succeeded,const SkBitmap & bitmap)84 void CaptureWebContentsFunction::CopyFromBackingStoreComplete(
85     bool succeeded,
86     const SkBitmap& bitmap) {
87   if (succeeded) {
88     OnCaptureSuccess(bitmap);
89     return;
90   }
91   OnCaptureFailure(FAILURE_REASON_UNKNOWN);
92 }
93 
OnCaptureSuccess(const SkBitmap & bitmap)94 void CaptureWebContentsFunction::OnCaptureSuccess(const SkBitmap& bitmap) {
95   std::vector<unsigned char> data;
96   SkAutoLockPixels screen_capture_lock(bitmap);
97   bool encoded = false;
98   std::string mime_type;
99   switch (image_format_) {
100     case ImageDetails::FORMAT_JPEG:
101       encoded = gfx::JPEGCodec::Encode(
102           reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
103           gfx::JPEGCodec::FORMAT_SkBitmap,
104           bitmap.width(),
105           bitmap.height(),
106           static_cast<int>(bitmap.rowBytes()),
107           image_quality_,
108           &data);
109       mime_type = tabs_constants::kMimeTypeJpeg;
110       break;
111     case ImageDetails::FORMAT_PNG:
112       encoded = gfx::PNGCodec::EncodeBGRASkBitmap(
113           bitmap,
114           true,  // Discard transparency.
115           &data);
116       mime_type = tabs_constants::kMimeTypePng;
117       break;
118     default:
119       NOTREACHED() << "Invalid image format.";
120   }
121 
122   if (!encoded) {
123     OnCaptureFailure(FAILURE_REASON_ENCODING_FAILED);
124     return;
125   }
126 
127   std::string base64_result;
128   base::StringPiece stream_as_string(
129       reinterpret_cast<const char*>(vector_as_array(&data)), data.size());
130 
131   base::Base64Encode(stream_as_string, &base64_result);
132   base64_result.insert(0, base::StringPrintf("data:%s;base64,",
133                                              mime_type.c_str()));
134   SetResult(new base::StringValue(base64_result));
135   SendResponse(true);
136 }
137 
138 }  // namespace extensions
139