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