1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/capture_web_contents_function.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/base64.h" 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/strings/stringprintf.h" 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/render_view_host.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/render_widget_host_view.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/web_contents.h" 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "extensions/browser/extension_function.h" 13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/constants.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/gfx/codec/jpeg_codec.h" 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h" 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using content::RenderViewHost; 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using content::RenderWidgetHost; 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using content::RenderWidgetHostView; 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using content::WebContents; 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace extensions { 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool CaptureWebContentsFunction::HasPermission() { 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool CaptureWebContentsFunction::RunAsync() { 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(args_); 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context_id_ = extension_misc::kCurrentWindowId; 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) args_->GetInteger(0, &context_id_); 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<ImageDetails> image_details; 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (args_->GetSize() > 1) { 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Value* spec = NULL; 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(args_->Get(1, &spec) && spec); 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) image_details = ImageDetails::FromValue(*spec); 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!IsScreenshotEnabled()) 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebContents* contents = GetWebContentsForID(context_id_); 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!contents) 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // The default format and quality setting used when encoding jpegs. 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const ImageDetails::Format kDefaultFormat = ImageDetails::FORMAT_JPEG; 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const int kDefaultQuality = 90; 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) image_format_ = kDefaultFormat; 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) image_quality_ = kDefaultQuality; 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (image_details) { 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (image_details->format != ImageDetails::FORMAT_NONE) 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) image_format_ = image_details->format; 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (image_details->quality.get()) 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) image_quality_ = *image_details->quality; 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RenderViewHost* render_view_host = contents->GetRenderViewHost(); 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RenderWidgetHostView* view = render_view_host->GetView(); 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!view) { 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) OnCaptureFailure(FAILURE_REASON_VIEW_INVISIBLE); 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) render_view_host->CopyFromBackingStore( 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) gfx::Rect(), 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) view->GetViewBounds().size(), 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&CaptureWebContentsFunction::CopyFromBackingStoreComplete, 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this), 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch kN32_SkColorType); 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void CaptureWebContentsFunction::CopyFromBackingStoreComplete( 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool succeeded, 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const SkBitmap& bitmap) { 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (succeeded) { 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) OnCaptureSuccess(bitmap); 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu OnCaptureFailure(FAILURE_REASON_UNKNOWN); 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void CaptureWebContentsFunction::OnCaptureSuccess(const SkBitmap& bitmap) { 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<unsigned char> data; 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SkAutoLockPixels screen_capture_lock(bitmap); 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool encoded = false; 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string mime_type; 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) switch (image_format_) { 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case ImageDetails::FORMAT_JPEG: 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) encoded = gfx::JPEGCodec::Encode( 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)), 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) gfx::JPEGCodec::FORMAT_SkBitmap, 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bitmap.width(), 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bitmap.height(), 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static_cast<int>(bitmap.rowBytes()), 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) image_quality_, 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &data); 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mime_type = kMimeTypeJpeg; 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case ImageDetails::FORMAT_PNG: 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci encoded = 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci true, // Discard transparency. 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &data); 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mime_type = kMimeTypePng; 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) default: 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NOTREACHED() << "Invalid image format."; 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!encoded) { 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) OnCaptureFailure(FAILURE_REASON_ENCODING_FAILED); 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string base64_result; 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::StringPiece stream_as_string( 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reinterpret_cast<const char*>(vector_as_array(&data)), data.size()); 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Base64Encode(stream_as_string, &base64_result); 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base64_result.insert( 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0, base::StringPrintf("data:%s;base64,", mime_type.c_str())); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetResult(new base::StringValue(base64_result)); 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SendResponse(true); 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace extensions 132