diff options
author | kkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-28 21:09:06 +0000 |
---|---|---|
committer | kkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-28 21:09:06 +0000 |
commit | fad8296611231b3efca90eeb6708fd3036c04cbd (patch) | |
tree | 4f0f8fb6644bc53fb030613672b11e22b24abb8e /chrome/renderer/automation | |
parent | f575629cd2580342b586ff0574465ed42e3231c3 (diff) | |
download | chromium_src-fad8296611231b3efca90eeb6708fd3036c04cbd.zip chromium_src-fad8296611231b3efca90eeb6708fd3036c04cbd.tar.gz chromium_src-fad8296611231b3efca90eeb6708fd3036c04cbd.tar.bz2 |
Re-land 107645 with static initializer removed.
Don't inherit from content::RenderViewObserver, instead just
create it on the fly when needed in tests.
BUG=69370, 66371, 63022
TEST=none
Review URL: http://codereview.chromium.org/8416024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107792 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/automation')
3 files changed, 188 insertions, 0 deletions
diff --git a/chrome/renderer/automation/automation_renderer_helper.cc b/chrome/renderer/automation/automation_renderer_helper.cc index 28a8b18..7d09dc1 100644 --- a/chrome/renderer/automation/automation_renderer_helper.cc +++ b/chrome/renderer/automation/automation_renderer_helper.cc @@ -4,13 +4,24 @@ #include "chrome/renderer/automation/automation_renderer_helper.h" +#include <algorithm> + #include "base/basictypes.h" #include "chrome/common/automation_messages.h" +#include "content/public/renderer/render_view.h" +#include "skia/ext/platform_canvas.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" +#include "ui/gfx/codec/png_codec.h" +#include "ui/gfx/rect.h" +#include "webkit/glue/webkit_glue.h" using WebKit::WebFrame; +using WebKit::WebSize; using WebKit::WebURL; +using WebKit::WebView; AutomationRendererHelper::AutomationRendererHelper( content::RenderView* render_view) @@ -19,6 +30,92 @@ AutomationRendererHelper::AutomationRendererHelper( AutomationRendererHelper::~AutomationRendererHelper() { } +bool AutomationRendererHelper::SnapshotEntirePage( + WebView* view, + std::vector<unsigned char>* png_data, + std::string* error_msg) { + WebFrame* frame = view->mainFrame(); + WebSize old_size = view->size(); + WebSize new_size = frame->contentsSize(); + // For RTL, the minimum scroll offset may be negative. + WebSize min_scroll = frame->minimumScrollOffset(); + WebSize old_scroll = frame->scrollOffset(); + bool fixed_layout_enabled = view->isFixedLayoutModeEnabled(); + WebSize fixed_size = view->fixedLayoutSize(); + + frame->setCanHaveScrollbars(false); + view->setFixedLayoutSize(old_size); + view->enableFixedLayoutMode(true); + view->resize(new_size); + view->layout(); + frame->setScrollOffset(WebSize(0, 0)); + + skia::PlatformCanvas canvas( + new_size.width, new_size.height, true /* is_opaque */); + view->paint(webkit_glue::ToWebCanvas(&canvas), + gfx::Rect(0, 0, new_size.width, new_size.height)); + + frame->setCanHaveScrollbars(true); + view->setFixedLayoutSize(fixed_size); + view->enableFixedLayoutMode(fixed_layout_enabled); + view->resize(old_size); + view->layout(); + frame->setScrollOffset(WebSize(old_scroll.width - min_scroll.width, + old_scroll.height - min_scroll.height)); + + const SkBitmap& bmp = skia::GetTopDevice(canvas)->accessBitmap(false); + SkAutoLockPixels lock_pixels(bmp); + // EncodeBGRA uses FORMAT_SkBitmap, which doesn't work on windows for some + // cases dealing with transparency. See crbug.com/96317. Use FORMAT_BGRA. + bool encode_success = gfx::PNGCodec::Encode( + reinterpret_cast<unsigned char*>(bmp.getPixels()), + gfx::PNGCodec::FORMAT_BGRA, + gfx::Size(bmp.width(), bmp.height()), + bmp.rowBytes(), + true, // discard_transparency + std::vector<gfx::PNGCodec::Comment>(), + png_data); + if (!encode_success) + *error_msg = "failed to encode image as png"; + return encode_success; +} + +void AutomationRendererHelper::OnSnapshotEntirePage() { + std::vector<unsigned char> png_data; + std::string error_msg; + bool success = false; + if (render_view()->GetWebView()) { + success = SnapshotEntirePage( + render_view()->GetWebView(), &png_data, &error_msg); + } else { + error_msg = "cannot snapshot page because webview is null"; + } + + // Check that the image is not too large, allowing a 1kb buffer for other + // message data. + if (success && png_data.size() > IPC::Channel::kMaximumMessageSize - 1024) { + png_data.clear(); + success = false; + error_msg = "image is too large to be transferred over ipc"; + } + Send(new AutomationMsg_SnapshotEntirePageACK( + routing_id(), success, png_data, error_msg)); +} + +bool AutomationRendererHelper::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + bool deserialize_success = true; + IPC_BEGIN_MESSAGE_MAP_EX(AutomationRendererHelper, message, + deserialize_success) + IPC_MESSAGE_HANDLER(AutomationMsg_SnapshotEntirePage, OnSnapshotEntirePage) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP_EX() + if (!deserialize_success) { + LOG(ERROR) << "Failed to deserialize an IPC message"; + } + return handled; +} + void AutomationRendererHelper::WillPerformClientRedirect( WebFrame* frame, const WebURL& from, const WebURL& to, double interval, double fire_time) { diff --git a/chrome/renderer/automation/automation_renderer_helper.h b/chrome/renderer/automation/automation_renderer_helper.h index f83cf4d..8369ca2 100644 --- a/chrome/renderer/automation/automation_renderer_helper.h +++ b/chrome/renderer/automation/automation_renderer_helper.h @@ -6,11 +6,16 @@ #define CHROME_RENDERER_AUTOMATION_AUTOMATION_RENDERER_HELPER_H_ #pragma once +#include <string> +#include <vector> + #include "content/public/renderer/render_view_observer.h" +#include "content/public/renderer/render_view_observer_tracker.h" namespace WebKit { class WebFrame; class WebURL; +class WebView; } // Filters automation/testing messages sent to a |RenderView| and sends @@ -20,8 +25,16 @@ class AutomationRendererHelper : public content::RenderViewObserver { explicit AutomationRendererHelper(content::RenderView* render_view); virtual ~AutomationRendererHelper(); + // Takes a snapshot of the entire page without changing layout size. + bool SnapshotEntirePage(WebKit::WebView* view, + std::vector<unsigned char>* png_data, + std::string* error_msg); + private: + void OnSnapshotEntirePage(); + // RenderViewObserver implementation. + virtual bool OnMessageReceived(const IPC::Message& message); virtual void WillPerformClientRedirect( WebKit::WebFrame* frame, const WebKit::WebURL& from, const WebKit::WebURL& to, double interval, double fire_time); diff --git a/chrome/renderer/automation/automation_renderer_helper_browsertest.cc b/chrome/renderer/automation/automation_renderer_helper_browsertest.cc new file mode 100644 index 0000000..4d11134 --- /dev/null +++ b/chrome/renderer/automation/automation_renderer_helper_browsertest.cc @@ -0,0 +1,78 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/md5.h" +#include "chrome/test/base/chrome_render_view_test.h" +#include "chrome/renderer/automation/automation_renderer_helper.h" +#include "content/public/renderer/render_view.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h" + +namespace { + +const char kThreeBoxesHTML[] = + "<style> * { margin:0px; padding:0px } </style>" + "<body>" + " <div style='background:red;width:100;height:100'></div>" + " <div style='background:green;width:100;height:100'></div>" + " <div style='background:blue;width:100;height:100'></div>" + "</body>"; + +const char kThreeBoxesMD5[] = "3adefecb4472e6ba1812f9af1fdea3e4"; + +void CompareSnapshot(const std::vector<unsigned char>& png_data, + const std::string& reference_md5) { + std::string png_data_str(reinterpret_cast<const char*>(&png_data[0]), + png_data.size()); + if (CommandLine::ForCurrentProcess()->HasSwitch("dump-test-image")) { + FilePath path = FilePath().AppendASCII("snapshot" + reference_md5 + ".png"); + EXPECT_EQ(file_util::WriteFile(path, png_data_str.c_str(), png_data.size()), + static_cast<int>(png_data.size())); + } + EXPECT_STREQ(reference_md5.c_str(), base::MD5String(png_data_str).c_str()); +} + +} // namespace + +typedef ChromeRenderViewTest AutomationRendererHelperTest; + +TEST_F(AutomationRendererHelperTest, BasicSnapshot) { + GetWebWidget()->resize(WebKit::WebSize(100, 300)); + LoadHTML(kThreeBoxesHTML); + std::vector<unsigned char> png_data; + std::string error_msg; + ASSERT_TRUE(AutomationRendererHelper(view_).SnapshotEntirePage( + view_->GetWebView(), &png_data, &error_msg)) << error_msg; + CompareSnapshot(png_data, kThreeBoxesMD5); +} + +TEST_F(AutomationRendererHelperTest, ScrollingSnapshot) { + GetWebWidget()->resize(WebKit::WebSize(40, 90)); + LoadHTML(kThreeBoxesHTML); + std::vector<unsigned char> png_data; + std::string error_msg; + ASSERT_TRUE(AutomationRendererHelper(view_).SnapshotEntirePage( + view_->GetWebView(), &png_data, &error_msg)) << error_msg; + CompareSnapshot(png_data, kThreeBoxesMD5); +} + +TEST_F(AutomationRendererHelperTest, RTLSnapshot) { + GetWebWidget()->resize(WebKit::WebSize(40, 90)); + const char kThreeBoxesRTLHTML[] = + "<style> * { margin:0px; padding:0px } </style>" + "<body dir='rtl'>" + " <div style='background:red;width:100;height:100'></div>" + " <div style='background:green;width:100;height:100'></div>" + " <div style='background:blue;width:100;height:100'></div>" + "</body>"; + LoadHTML(kThreeBoxesRTLHTML); + std::vector<unsigned char> png_data; + std::string error_msg; + ASSERT_TRUE(AutomationRendererHelper(view_).SnapshotEntirePage( + view_->GetWebView(), &png_data, &error_msg)) << error_msg; + CompareSnapshot(png_data, kThreeBoxesMD5); +} |