summaryrefslogtreecommitdiffstats
path: root/content/shell
diff options
context:
space:
mode:
authorjochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-27 10:58:51 +0000
committerjochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-27 10:58:51 +0000
commit0799da03522c8fe06136710ea409c4e8d468f45c (patch)
treedbe61f3d30738e185f67a0cecbe43f90579c0c38 /content/shell
parentc91bb26fa85807df212657eb025c2c69be100b9f (diff)
downloadchromium_src-0799da03522c8fe06136710ea409c4e8d468f45c.zip
chromium_src-0799da03522c8fe06136710ea409c4e8d468f45c.tar.gz
chromium_src-0799da03522c8fe06136710ea409c4e8d468f45c.tar.bz2
Add basic support to dump pixel results
BUG=111316 TEST="webkit/tools/layout_tests/run_webkit_tests.py --chromium --debug --driver-name=content_shell --additional-drt-flag=--dump-render-tree css3/css3-modsel-33.html" should pass Review URL: https://chromiumcodereview.appspot.com/10656044 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@144436 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/shell')
-rw-r--r--content/shell/layout_test_controller.cc68
-rw-r--r--content/shell/layout_test_controller.h1
-rw-r--r--content/shell/layout_test_controller_host.cc59
-rw-r--r--content/shell/layout_test_controller_host.h7
-rw-r--r--content/shell/shell_browser_main.cc31
-rw-r--r--content/shell/shell_messages.h12
6 files changed, 163 insertions, 15 deletions
diff --git a/content/shell/layout_test_controller.cc b/content/shell/layout_test_controller.cc
index faef0cd..3a7439f 100644
--- a/content/shell/layout_test_controller.cc
+++ b/content/shell/layout_test_controller.cc
@@ -4,19 +4,26 @@
#include "content/shell/layout_test_controller.h"
+#include "base/md5.h"
#include "base/stringprintf.h"
#include "content/public/renderer/render_view.h"
#include "content/shell/shell_messages.h"
+#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
+#include "webkit/glue/webkit_glue.h"
using WebKit::WebFrame;
using WebKit::WebElement;
+using WebKit::WebRect;
using WebKit::WebSize;
+using WebKit::WebView;
namespace content {
@@ -84,6 +91,47 @@ std::string DumpFrameScrollPosition(WebFrame* frame, bool recursive) {
return result;
}
+bool PaintViewIntoCanvas(WebView* view, skia::PlatformCanvas& canvas) {
+ view->layout();
+ const WebSize& size = view->size();
+
+ if (!canvas.initialize(size.width, size.height, true))
+ return false;
+
+ view->paint(webkit_glue::ToWebCanvas(&canvas),
+ WebRect(0, 0, size.width, size.height));
+ return true;
+}
+
+#if !defined(OS_MACOSX)
+void MakeBitmapOpaque(SkBitmap* bitmap) {
+ SkAutoLockPixels lock(*bitmap);
+ DCHECK(bitmap->config() == SkBitmap::kARGB_8888_Config);
+ for (int y = 0; y < bitmap->height(); ++y) {
+ uint32_t* row = bitmap->getAddr32(0, y);
+ for (int x = 0; x < bitmap->width(); ++x)
+ row[x] |= 0xFF000000; // Set alpha bits to 1.
+ }
+}
+#endif
+
+void CaptureSnapshot(WebView* view, SkBitmap* snapshot) {
+ skia::PlatformCanvas canvas;
+ if (!PaintViewIntoCanvas(view, canvas))
+ return;
+
+ SkDevice* device = skia::GetTopDevice(canvas);
+
+ const SkBitmap& bitmap = device->accessBitmap(false);
+ bitmap.copyTo(snapshot, SkBitmap::kARGB_8888_Config);
+
+#if !defined(OS_MACOSX)
+ // Only the expected PNGs for Mac have a valid alpha channel.
+ MakeBitmapOpaque(snapshot);
+#endif
+
+}
+
} // namespace
LayoutTestController::LayoutTestController(RenderView* render_view)
@@ -102,6 +150,7 @@ bool LayoutTestController::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(LayoutTestController, message)
IPC_MESSAGE_HANDLER(ShellViewMsg_CaptureTextDump, OnCaptureTextDump)
+ IPC_MESSAGE_HANDLER(ShellViewMsg_CaptureImageDump, OnCaptureImageDump)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -126,4 +175,23 @@ void LayoutTestController::OnCaptureTextDump(bool as_text,
Send(new ShellViewHostMsg_TextDump(routing_id(), dump));
}
+void LayoutTestController::OnCaptureImageDump(
+ const std::string& expected_pixel_hash) {
+ SkBitmap snapshot;
+ CaptureSnapshot(render_view()->GetWebView(), &snapshot);
+
+ SkAutoLockPixels snapshot_lock(snapshot);
+ base::MD5Digest digest;
+ base::MD5Sum(snapshot.getPixels(), snapshot.getSize(), &digest);
+ std::string actual_pixel_hash = base::MD5DigestToBase16(digest);
+
+ if (actual_pixel_hash == expected_pixel_hash) {
+ SkBitmap empty_image;
+ Send(new ShellViewHostMsg_ImageDump(
+ routing_id(), actual_pixel_hash, empty_image));
+ }
+ Send(new ShellViewHostMsg_ImageDump(
+ routing_id(), actual_pixel_hash, snapshot));
+}
+
} // namespace content
diff --git a/content/shell/layout_test_controller.h b/content/shell/layout_test_controller.h
index b8e06b5..1b3faae 100644
--- a/content/shell/layout_test_controller.h
+++ b/content/shell/layout_test_controller.h
@@ -23,6 +23,7 @@ class LayoutTestController : public RenderViewObserver {
private:
// Message handlers.
void OnCaptureTextDump(bool as_text, bool printing, bool recursive);
+ void OnCaptureImageDump(const std::string& expected_pixel_hash);
DISALLOW_COPY_AND_ASSIGN(LayoutTestController);
};
diff --git a/content/shell/layout_test_controller_host.cc b/content/shell/layout_test_controller_host.cc
index ade2c98..5b52cbd 100644
--- a/content/shell/layout_test_controller_host.cc
+++ b/content/shell/layout_test_controller_host.cc
@@ -9,6 +9,7 @@
#include "base/message_loop.h"
#include "content/public/browser/render_view_host.h"
#include "content/shell/shell_messages.h"
+#include "webkit/support/webkit_support_gfx.h"
namespace content {
@@ -18,6 +19,7 @@ const int kTestTimeoutMilliseconds = 30 * 1000;
std::map<RenderViewHost*, LayoutTestControllerHost*>
LayoutTestControllerHost::controllers_;
+std::string LayoutTestControllerHost::expected_pixel_hash_;
// static
LayoutTestControllerHost* LayoutTestControllerHost::FromRenderViewHost(
@@ -29,6 +31,12 @@ LayoutTestControllerHost* LayoutTestControllerHost::FromRenderViewHost(
return it->second;
}
+// static
+void LayoutTestControllerHost::Init(const std::string& expected_pixel_hash) {
+ // TODO(jochen): We should only dump the results for the "main window".
+ expected_pixel_hash_ = expected_pixel_hash;
+}
+
LayoutTestControllerHost::LayoutTestControllerHost(
RenderViewHost* render_view_host)
: RenderViewHostObserver(render_view_host),
@@ -56,6 +64,11 @@ void LayoutTestControllerHost::CaptureDump() {
dump_as_text_,
is_printing_,
dump_child_frames_));
+ if (!dump_as_text_) {
+ render_view_host()->Send(
+ new ShellViewMsg_CaptureImageDump(render_view_host()->GetRoutingID(),
+ expected_pixel_hash_));
+ }
}
void LayoutTestControllerHost::TimeoutHandler() {
@@ -70,6 +83,7 @@ bool LayoutTestControllerHost::OnMessageReceived(
IPC_BEGIN_MESSAGE_MAP(LayoutTestControllerHost, message)
IPC_MESSAGE_HANDLER(ShellViewHostMsg_DidFinishLoad, OnDidFinishLoad)
IPC_MESSAGE_HANDLER(ShellViewHostMsg_TextDump, OnTextDump)
+ IPC_MESSAGE_HANDLER(ShellViewHostMsg_ImageDump, OnImageDump)
IPC_MESSAGE_HANDLER(ShellViewHostMsg_NotifyDone, OnNotifyDone)
IPC_MESSAGE_HANDLER(ShellViewHostMsg_DumpAsText, OnDumpAsText)
IPC_MESSAGE_HANDLER(ShellViewHostMsg_DumpChildFramesAsText,
@@ -97,7 +111,52 @@ void LayoutTestControllerHost::OnTextDump(const std::string& dump) {
std::cout << "#EOF\n";
std::cerr << "#EOF\n";
+ if (dump_as_text_)
+ MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+}
+
+void LayoutTestControllerHost::OnImageDump(
+ const std::string& actual_pixel_hash,
+ const SkBitmap& image) {
+#if !defined(OS_ANDROID)
+ // DumpRenderTree is not currently supported for Android. Also, on Android
+ // the required webkit_support methods are not defined, so this method just
+ // doesn't compile.
+
+ SkAutoLockPixels image_lock(image);
+
+ std::cout << "\nActualHash: " << actual_pixel_hash << "\n";
+ if (!expected_pixel_hash_.empty())
+ std::cout << "\nExpectedHash: " << expected_pixel_hash_ << "\n";
+
+ // Only encode and dump the png if the hashes don't match. Encoding the
+ // image is really expensive.
+ if (actual_pixel_hash != expected_pixel_hash_) {
+ std::vector<unsigned char> png;
+
+ // Only the expected PNGs for Mac have a valid alpha channel.
+#if defined(OS_MACOSX)
+ bool discard_transparency = false;
+#else
+ bool discard_transparency = true;
+#endif
+
+ webkit_support::EncodeBGRAPNGWithChecksum(
+ reinterpret_cast<const unsigned char*>(image.getPixels()),
+ image.width(),
+ image.height(),
+ static_cast<int>(image.rowBytes()),
+ discard_transparency,
+ actual_pixel_hash,
+ &png);
+
+ std::cout << "Content-Type: image/png\n";
+ std::cout << "Content-Length: " << png.size() << "\n";
+ std::cout.write(reinterpret_cast<const char*>(&png[0]), png.size());
+ }
+
MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+#endif
}
void LayoutTestControllerHost::OnNotifyDone() {
diff --git a/content/shell/layout_test_controller_host.h b/content/shell/layout_test_controller_host.h
index 7ff3d45..e31f610 100644
--- a/content/shell/layout_test_controller_host.h
+++ b/content/shell/layout_test_controller_host.h
@@ -12,6 +12,8 @@
#include "base/cancelable_callback.h"
#include "content/public/browser/render_view_host_observer.h"
+class SkBitmap;
+
namespace content {
class LayoutTestControllerHost : public RenderViewHostObserver {
@@ -19,6 +21,9 @@ class LayoutTestControllerHost : public RenderViewHostObserver {
static LayoutTestControllerHost* FromRenderViewHost(
RenderViewHost* render_view_host);
+ // Initialize the LayoutTestControllerHost for a given test.
+ static void Init(const std::string& expected_pixel_hash);
+
explicit LayoutTestControllerHost(RenderViewHost* render_view_host);
virtual ~LayoutTestControllerHost();
@@ -36,6 +41,7 @@ class LayoutTestControllerHost : public RenderViewHostObserver {
// Message handlers.
void OnDidFinishLoad();
void OnTextDump(const std::string& dump);
+ void OnImageDump(const std::string& actual_pixel_hash, const SkBitmap& image);
// layoutTestController handlers.
void OnNotifyDone();
@@ -46,6 +52,7 @@ class LayoutTestControllerHost : public RenderViewHostObserver {
void OnWaitUntilDone();
static std::map<RenderViewHost*, LayoutTestControllerHost*> controllers_;
+ static std::string expected_pixel_hash_;
bool captured_dump_;
diff --git a/content/shell/shell_browser_main.cc b/content/shell/shell_browser_main.cc
index f56af33..597f1a0 100644
--- a/content/shell/shell_browser_main.cc
+++ b/content/shell/shell_browser_main.cc
@@ -11,6 +11,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/browser/browser_main_runner.h"
+#include "content/shell/layout_test_controller_host.h"
#include "content/shell/shell.h"
#include "content/shell/shell_browser_context.h"
#include "content/shell/shell_content_browser_client.h"
@@ -19,7 +20,8 @@
namespace {
-GURL GetURLForLayoutTest(const char* test_name) {
+GURL GetURLForLayoutTest(const char* test_name,
+ std::string* expected_pixel_hash) {
#if defined(OS_ANDROID)
// DumpRenderTree is not currently supported for Android using the content
// shell.
@@ -28,18 +30,13 @@ GURL GetURLForLayoutTest(const char* test_name) {
#else
std::string path_or_url = test_name;
std::string pixel_hash;
- std::string timeout;
- std::string::size_type separator_position = path_or_url.find(' ');
+ std::string::size_type separator_position = path_or_url.find('\'');
if (separator_position != std::string::npos) {
- timeout = path_or_url.substr(separator_position + 1);
+ pixel_hash = path_or_url.substr(separator_position + 1);
path_or_url.erase(separator_position);
- separator_position = path_or_url.find(' ');
- if (separator_position != std::string::npos) {
- pixel_hash = timeout.substr(separator_position + 1);
- timeout.erase(separator_position);
- }
}
- // TODO(jochen): use pixel_hash and timeout.
+ if (expected_pixel_hash)
+ *expected_pixel_hash = pixel_hash;
GURL test_url = webkit_support::CreateURLForPathOrURL(path_or_url);
{
// We're outside of the message loop here, and this is a test.
@@ -86,11 +83,15 @@ int ShellBrowserMain(const content::MainFunctionParams& parameters) {
// Test header.
std::cout << "Content-Type: text/plain\n";
- content::Shell::CreateNewWindow(browser_context,
- GetURLForLayoutTest(test_string),
- NULL,
- MSG_ROUTING_NONE,
- NULL);
+ std::string pixel_hash;
+ content::Shell::CreateNewWindow(
+ browser_context,
+ GetURLForLayoutTest(test_string, &pixel_hash),
+ NULL,
+ MSG_ROUTING_NONE,
+ NULL);
+ content::LayoutTestControllerHost::Init(pixel_hash);
+
main_runner_->Run();
content::Shell::CloseAllWindows();
diff --git a/content/shell/shell_messages.h b/content/shell/shell_messages.h
index 50ce122..ddf2a4a 100644
--- a/content/shell/shell_messages.h
+++ b/content/shell/shell_messages.h
@@ -5,7 +5,9 @@
// Multiply-included file, no traditional include guard.
#include <string>
+#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#define IPC_MESSAGE_START ShellMsgStart
@@ -16,10 +18,20 @@ IPC_MESSAGE_ROUTED3(ShellViewMsg_CaptureTextDump,
bool /* printing */,
bool /* recursive */)
+// Tells the render view to capture an image of the page. The render view
+// responds with a ShelLViewHostMsg_ImageDump.
+IPC_MESSAGE_ROUTED1(ShellViewMsg_CaptureImageDump,
+ std::string /* expected pixel hash */)
+
// Send a text dump of the WebContents to the render host.
IPC_MESSAGE_ROUTED1(ShellViewHostMsg_TextDump,
std::string /* dump */)
+// Send an image dump of the WebContents to the render host.
+IPC_MESSAGE_ROUTED2(ShellViewHostMsg_ImageDump,
+ std::string /* actual pixel hash */,
+ SkBitmap /* image */)
+
// The main frame of the render view finished loading.
IPC_MESSAGE_ROUTED0(ShellViewHostMsg_DidFinishLoad)