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/renderer/chrome_render_frame_observer.h" 6 7 #include "base/strings/utf_string_conversions.h" 8 #include "chrome/common/prerender_messages.h" 9 #include "chrome/common/print_messages.h" 10 #include "chrome/common/render_messages.h" 11 #include "chrome/renderer/prerender/prerender_helper.h" 12 #include "chrome/renderer/printing/print_web_view_helper.h" 13 #include "content/public/renderer/render_frame.h" 14 #include "skia/ext/image_operations.h" 15 #include "skia/ext/platform_canvas.h" 16 #include "third_party/WebKit/public/platform/WebImage.h" 17 #include "third_party/WebKit/public/web/WebElement.h" 18 #include "third_party/WebKit/public/web/WebFrame.h" 19 #include "third_party/WebKit/public/web/WebNode.h" 20 21 using blink::WebElement; 22 using blink::WebNode; 23 24 namespace { 25 26 // If the source image is null or occupies less area than 27 // |thumbnail_min_area_pixels|, we return the image unmodified. Otherwise, we 28 // scale down the image so that the width and height do not exceed 29 // |thumbnail_max_size_pixels|, preserving the original aspect ratio. 30 SkBitmap Downscale(blink::WebImage image, 31 int thumbnail_min_area_pixels, 32 gfx::Size thumbnail_max_size_pixels) { 33 if (image.isNull()) 34 return SkBitmap(); 35 36 gfx::Size image_size = image.size(); 37 38 if (image_size.GetArea() < thumbnail_min_area_pixels) 39 return image.getSkBitmap(); 40 41 if (image_size.width() <= thumbnail_max_size_pixels.width() && 42 image_size.height() <= thumbnail_max_size_pixels.height()) 43 return image.getSkBitmap(); 44 45 gfx::SizeF scaled_size = image_size; 46 47 if (scaled_size.width() > thumbnail_max_size_pixels.width()) { 48 scaled_size.Scale(thumbnail_max_size_pixels.width() / scaled_size.width()); 49 } 50 51 if (scaled_size.height() > thumbnail_max_size_pixels.height()) { 52 scaled_size.Scale( 53 thumbnail_max_size_pixels.height() / scaled_size.height()); 54 } 55 56 return skia::ImageOperations::Resize(image.getSkBitmap(), 57 skia::ImageOperations::RESIZE_GOOD, 58 static_cast<int>(scaled_size.width()), 59 static_cast<int>(scaled_size.height())); 60 } 61 62 } // namespace 63 64 ChromeRenderFrameObserver::ChromeRenderFrameObserver( 65 content::RenderFrame* render_frame) 66 : content::RenderFrameObserver(render_frame) { 67 } 68 69 ChromeRenderFrameObserver::~ChromeRenderFrameObserver() { 70 } 71 72 bool ChromeRenderFrameObserver::OnMessageReceived(const IPC::Message& message) { 73 // Filter only. 74 bool handled = true; 75 IPC_BEGIN_MESSAGE_MAP(ChromeRenderFrameObserver, message) 76 IPC_MESSAGE_HANDLER(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering) 77 IPC_MESSAGE_UNHANDLED(handled = false) 78 IPC_END_MESSAGE_MAP() 79 if (handled) 80 return false; 81 82 IPC_BEGIN_MESSAGE_MAP(ChromeRenderFrameObserver, message) 83 IPC_MESSAGE_HANDLER(ChromeViewMsg_RequestThumbnailForContextNode, 84 OnRequestThumbnailForContextNode) 85 IPC_MESSAGE_HANDLER(PrintMsg_PrintNodeUnderContextMenu, 86 OnPrintNodeUnderContextMenu) 87 IPC_MESSAGE_UNHANDLED(handled = false) 88 IPC_END_MESSAGE_MAP() 89 90 return handled; 91 } 92 93 void ChromeRenderFrameObserver::DidChangeName( 94 const base::string16& name) { 95 Send(new ChromeViewHostMsg_UpdateFrameName( 96 routing_id(), 97 !render_frame()->GetWebFrame()->parent(), 98 base::UTF16ToUTF8(name))); 99 } 100 101 void ChromeRenderFrameObserver::OnSetIsPrerendering(bool is_prerendering) { 102 if (is_prerendering) { 103 // If the PrerenderHelper for this frame already exists, don't create it. It 104 // can already be created for subframes during handling of 105 // RenderFrameCreated, if the parent frame was prerendering at time of 106 // subframe creation. 107 if (prerender::PrerenderHelper::Get(render_frame())) 108 return; 109 110 // The PrerenderHelper will destroy itself either after recording histograms 111 // or on destruction of the RenderView. 112 new prerender::PrerenderHelper(render_frame()); 113 } 114 } 115 116 void ChromeRenderFrameObserver::OnRequestThumbnailForContextNode( 117 int thumbnail_min_area_pixels, 118 const gfx::Size& thumbnail_max_size_pixels) { 119 WebNode context_node = render_frame()->GetContextMenuNode(); 120 SkBitmap thumbnail; 121 gfx::Size original_size; 122 if (!context_node.isNull() && context_node.isElementNode()) { 123 blink::WebImage image = context_node.to<WebElement>().imageContents(); 124 original_size = image.size(); 125 thumbnail = Downscale(image, 126 thumbnail_min_area_pixels, 127 thumbnail_max_size_pixels); 128 } 129 Send(new ChromeViewHostMsg_RequestThumbnailForContextNode_ACK( 130 routing_id(), thumbnail, original_size)); 131 } 132 133 void ChromeRenderFrameObserver::OnPrintNodeUnderContextMenu() { 134 printing::PrintWebViewHelper* helper = 135 printing::PrintWebViewHelper::Get(render_frame()->GetRenderView()); 136 if (helper) 137 helper->PrintNode(render_frame()->GetContextMenuNode()); 138 } 139