summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-27 22:50:35 +0000
committerkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-27 22:50:35 +0000
commit44fbf837bff527c9f2cb9757a96034cf093706af (patch)
tree708b50c56bf2f1ae0f5f7e707789efa98c5a9ded
parent3ba226c5d3494fbe754c860366f7126cd51df9d2 (diff)
downloadchromium_src-44fbf837bff527c9f2cb9757a96034cf093706af.zip
chromium_src-44fbf837bff527c9f2cb9757a96034cf093706af.tar.gz
chromium_src-44fbf837bff527c9f2cb9757a96034cf093706af.tar.bz2
Fix test snapshotting on linux by creating a separate automation path for
snapshots outside of the thumbnail generator. BUG=69370,66371,63022 TEST=none Review URL: http://codereview.chromium.org/8294030 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107645 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/automation/automation_provider_observers.cc95
-rw-r--r--chrome/browser/automation/automation_provider_observers.h32
-rw-r--r--chrome/browser/automation/automation_tab_helper.cc16
-rw-r--r--chrome/browser/automation/automation_tab_helper.h14
-rw-r--r--chrome/browser/automation/testing_automation_provider.cc9
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/automation_messages_internal.h10
-rw-r--r--chrome/renderer/automation/automation_renderer_helper.cc101
-rw-r--r--chrome/renderer/automation/automation_renderer_helper.h17
-rw-r--r--chrome/renderer/automation/automation_renderer_helper_browsertest.cc78
-rw-r--r--chrome/test/automation/automation_proxy_uitest.cc119
-rw-r--r--chrome/test/data/automation_proxy_snapshot/just_image.html14
-rw-r--r--chrome/test/webdriver/test/chromedriver_tests.py5
13 files changed, 293 insertions, 218 deletions
diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc
index f93c2f8..ca64410 100644
--- a/chrome/browser/automation/automation_provider_observers.cc
+++ b/chrome/browser/automation/automation_provider_observers.cc
@@ -1892,87 +1892,46 @@ void SavePackageNotificationObserver::Observe(
PageSnapshotTaker::PageSnapshotTaker(AutomationProvider* automation,
IPC::Message* reply_message,
- RenderViewHost* render_view,
+ TabContentsWrapper* tab_contents,
const FilePath& path)
: automation_(automation->AsWeakPtr()),
reply_message_(reply_message),
- render_view_(render_view),
- image_path_(path),
- received_width_(false) {}
+ tab_contents_(tab_contents),
+ image_path_(path) {
+ registrar_.Add(this, chrome::NOTIFICATION_APP_MODAL_DIALOG_SHOWN,
+ content::NotificationService::AllSources());
+}
PageSnapshotTaker::~PageSnapshotTaker() {}
void PageSnapshotTaker::Start() {
- ExecuteScript(L"window.domAutomationController.send(document.width);");
-}
-
-void PageSnapshotTaker::OnDomOperationCompleted(const std::string& json) {
- int dimension;
- if (!base::StringToInt(json, &dimension)) {
- SendMessage(false, "could not parse received dimensions: " + json);
- } else if (!received_width_) {
- received_width_ = true;
- entire_page_size_.set_width(dimension);
-
- ExecuteScript(L"window.domAutomationController.send(document.height);");
- } else {
- entire_page_size_.set_height(dimension);
-
- ThumbnailGenerator* generator =
- g_browser_process->GetThumbnailGenerator();
- ThumbnailGenerator::ThumbnailReadyCallback callback =
- base::Bind(&PageSnapshotTaker::OnSnapshotTaken, base::Unretained(this));
- // Don't actually start the thumbnail generator, this leads to crashes on
- // Mac, crbug.com/62986. Instead, just hook the generator to the
- // RenderViewHost manually.
-
- generator->MonitorRenderer(render_view_, true);
- generator->AskForSnapshot(render_view_, false, callback,
- entire_page_size_, entire_page_size_);
+ StartObserving(tab_contents_->automation_tab_helper());
+ tab_contents_->automation_tab_helper()->SnapshotEntirePage();
+}
+
+void PageSnapshotTaker::OnSnapshotEntirePageACK(
+ bool success,
+ const std::vector<unsigned char>& png_data,
+ const std::string& error_msg) {
+ bool overall_success = success;
+ std::string overall_error_msg = error_msg;
+ if (success) {
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+ int bytes_written = file_util::WriteFile(image_path_,
+ reinterpret_cast<const char*>(&png_data[0]), png_data.size());
+ overall_success = (bytes_written == static_cast<int>(png_data.size()));
+ if (!overall_success)
+ overall_error_msg = "could not write snapshot to disk";
}
+ SendMessage(overall_success, overall_error_msg);
}
-void PageSnapshotTaker::OnModalDialogShown() {
+void PageSnapshotTaker::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
SendMessage(false, "a modal dialog is active");
}
-void PageSnapshotTaker::OnSnapshotTaken(const SkBitmap& bitmap) {
- base::ThreadRestrictions::ScopedAllowIO allow_io;
- std::vector<unsigned char> png_data;
- SkAutoLockPixels lock_input(bitmap);
- bool success = gfx::PNGCodec::Encode(
- reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
- gfx::PNGCodec::FORMAT_BGRA,
- gfx::Size(bitmap.width(), bitmap.height()),
- bitmap.rowBytes(),
- true, // discard_transparency
- std::vector<gfx::PNGCodec::Comment>(),
- &png_data);
- std::string error_msg;
- if (!success) {
- error_msg = "could not encode bitmap as PNG";
- } else {
- int bytes_written = file_util::WriteFile(image_path_,
- reinterpret_cast<char*>(&png_data[0]), png_data.size());
- success = bytes_written == static_cast<int>(png_data.size());
- if (!success)
- error_msg = "could not write snapshot to disk";
- }
- SendMessage(success, error_msg);
-}
-
-void PageSnapshotTaker::ExecuteScript(const std::wstring& javascript) {
- std::wstring set_automation_id;
- base::SStringPrintf(
- &set_automation_id,
- L"window.domAutomationController.setAutomationId(%d);",
- reply_message_->routing_id());
-
- render_view_->ExecuteJavascriptInWebFrame(string16(),
- WideToUTF16Hack(set_automation_id));
- render_view_->ExecuteJavascriptInWebFrame(string16(),
- WideToUTF16Hack(javascript));
-}
void PageSnapshotTaker::SendMessage(bool success,
const std::string& error_msg) {
diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h
index d92b73a..ad51f80 100644
--- a/chrome/browser/automation/automation_provider_observers.h
+++ b/chrome/browser/automation/automation_provider_observers.h
@@ -1343,13 +1343,13 @@ class SavePackageNotificationObserver : public content::NotificationObserver {
DISALLOW_COPY_AND_ASSIGN(SavePackageNotificationObserver);
};
-// This class manages taking a snapshot of a page. This requires waiting on
-// asynchronous callbacks and notifications.
-class PageSnapshotTaker : public DomOperationObserver {
+// This class manages taking a snapshot of a page.
+class PageSnapshotTaker : public TabEventObserver,
+ public content::NotificationObserver {
public:
PageSnapshotTaker(AutomationProvider* automation,
IPC::Message* reply_message,
- RenderViewHost* render_view,
+ TabContentsWrapper* tab_contents,
const FilePath& path);
virtual ~PageSnapshotTaker();
@@ -1357,26 +1357,24 @@ class PageSnapshotTaker : public DomOperationObserver {
void Start();
private:
- // Overriden from DomOperationObserver.
- virtual void OnDomOperationCompleted(const std::string& json) OVERRIDE;
- virtual void OnModalDialogShown() OVERRIDE;
-
- // Called by the ThumbnailGenerator when the requested snapshot has been
- // generated.
- void OnSnapshotTaken(const SkBitmap& bitmap);
-
- // Helper method to send arbitrary javascript to the renderer for evaluation.
- void ExecuteScript(const std::wstring& javascript);
+ // TabEventObserver overrides.
+ virtual void OnSnapshotEntirePageACK(
+ bool success,
+ const std::vector<unsigned char>& png_data,
+ const std::string& error_msg) OVERRIDE;
+ // NotificationObserver overrides.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details);
// Helper method to send a response back to the client. Deletes this.
void SendMessage(bool success, const std::string& error_msg);
base::WeakPtr<AutomationProvider> automation_;
scoped_ptr<IPC::Message> reply_message_;
- RenderViewHost* render_view_;
+ TabContentsWrapper* tab_contents_;
FilePath image_path_;
- bool received_width_;
- gfx::Size entire_page_size_;
+ content::NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(PageSnapshotTaker);
};
diff --git a/chrome/browser/automation/automation_tab_helper.cc b/chrome/browser/automation/automation_tab_helper.cc
index c9658a4..3e4945a 100644
--- a/chrome/browser/automation/automation_tab_helper.cc
+++ b/chrome/browser/automation/automation_tab_helper.cc
@@ -12,6 +12,8 @@
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
+#include "ui/gfx/size.h"
+
TabEventObserver::TabEventObserver() { }
TabEventObserver::~TabEventObserver() {
@@ -49,6 +51,10 @@ void AutomationTabHelper::RemoveObserver(TabEventObserver* observer) {
observers_.RemoveObserver(observer);
}
+void AutomationTabHelper::SnapshotEntirePage() {
+ Send(new AutomationMsg_SnapshotEntirePage(routing_id()));
+}
+
bool AutomationTabHelper::has_pending_loads() const {
return is_loading_ || !pending_client_redirects_.empty();
}
@@ -99,10 +105,20 @@ void AutomationTabHelper::OnTabOrRenderViewDestroyed(
}
}
+void AutomationTabHelper::OnSnapshotEntirePageACK(
+ bool success,
+ const std::vector<unsigned char>& png_data,
+ const std::string& error_msg) {
+ FOR_EACH_OBSERVER(TabEventObserver, observers_,
+ OnSnapshotEntirePageACK(success, png_data, error_msg));
+}
+
bool AutomationTabHelper::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
bool msg_is_good = true;
IPC_BEGIN_MESSAGE_MAP_EX(AutomationTabHelper, message, msg_is_good)
+ IPC_MESSAGE_HANDLER(AutomationMsg_SnapshotEntirePageACK,
+ OnSnapshotEntirePageACK)
IPC_MESSAGE_HANDLER(AutomationMsg_WillPerformClientRedirect,
OnWillPerformClientRedirect)
IPC_MESSAGE_HANDLER(AutomationMsg_DidCompleteOrCancelClientRedirect,
diff --git a/chrome/browser/automation/automation_tab_helper.h b/chrome/browser/automation/automation_tab_helper.h
index d3016d8..a8ddef7 100644
--- a/chrome/browser/automation/automation_tab_helper.h
+++ b/chrome/browser/automation/automation_tab_helper.h
@@ -48,6 +48,12 @@ class TabEventObserver {
// This method will always be called if |OnFirstPendingLoad| was called.
virtual void OnNoMorePendingLoads(TabContents* tab_contents) { }
+ // Called as a result of a tab being snapshotted.
+ virtual void OnSnapshotEntirePageACK(
+ bool success,
+ const std::vector<unsigned char>& png_data,
+ const std::string& error_msg) { }
+
protected:
TabEventObserver();
virtual ~TabEventObserver();
@@ -84,6 +90,9 @@ class AutomationTabHelper
void AddObserver(TabEventObserver* observer);
void RemoveObserver(TabEventObserver* observer);
+ // Snapshots the entire page without resizing.
+ void SnapshotEntirePage();
+
// Returns true if the tab is loading or the tab is scheduled to load
// immediately. Note that scheduled loads may be canceled.
bool has_pending_loads() const;
@@ -91,6 +100,11 @@ class AutomationTabHelper
private:
friend class AutomationTabHelperTest;
+ void OnSnapshotEntirePageACK(
+ bool success,
+ const std::vector<unsigned char>& png_data,
+ const std::string& error_msg);
+
// TabContentsObserver implementation.
virtual void DidStartLoading();
virtual void DidStopLoading();
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index 4bc985c..9b61c83 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -6191,12 +6191,6 @@ void TestingAutomationProvider::GetTabTitleJSON(
void TestingAutomationProvider::CaptureEntirePageJSON(
DictionaryValue* args,
IPC::Message* reply_message) {
-#if defined(OS_LINUX)
- // See crbug.com/89777.
- AutomationJSONReply(this, reply_message).SendError(
- "Taking a page snapshot is not supported on this platform");
- return;
-#endif
if (SendErrorIfModalDialogActive(this, reply_message))
return;
@@ -6220,7 +6214,8 @@ void TestingAutomationProvider::CaptureEntirePageJSON(
FilePath path(path_str);
// This will delete itself when finished.
PageSnapshotTaker* snapshot_taker = new PageSnapshotTaker(
- this, reply_message, render_view, path);
+ this, reply_message,
+ TabContentsWrapper::GetCurrentWrapperForContents(tab_contents), path);
snapshot_taker->Start();
} else {
AutomationJSONReply(this, reply_message)
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index cc30bd3..1ebde8f 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -2544,6 +2544,7 @@
'renderer/autofill/form_autocomplete_browsertest.cc',
'renderer/autofill/form_autofill_browsertest.cc',
'renderer/autofill/password_autofill_manager_browsertest.cc',
+ 'renderer/automation/automation_renderer_helper_browsertest.cc',
'renderer/content_settings_observer_browsertest.cc',
'renderer/page_click_tracker_browsertest.cc',
'renderer/print_web_view_helper_browsertest.cc',
diff --git a/chrome/common/automation_messages_internal.h b/chrome/common/automation_messages_internal.h
index 29aa8a8..aa59612 100644
--- a/chrome/common/automation_messages_internal.h
+++ b/chrome/common/automation_messages_internal.h
@@ -1494,9 +1494,19 @@ IPC_SYNC_MESSAGE_CONTROL0_1(AutomationMsg_EndTracing,
IPC_SYNC_MESSAGE_CONTROL0_2(AutomationMsg_GetTracingOutput,
std::string /* trace_chunk */,
int /* remaining_chunks */)
+// Browser -> renderer messages.
+
+// Requests a snapshot.
+IPC_MESSAGE_ROUTED0(AutomationMsg_SnapshotEntirePage)
// Renderer -> browser messages.
+// Sent as a response to |AutomationMsg_Snapshot|.
+IPC_MESSAGE_ROUTED3(AutomationMsg_SnapshotEntirePageACK,
+ bool /* success */,
+ std::vector<unsigned char> /* png bytes */,
+ std::string /* error message */)
+
// Sent when the renderer has scheduled a client redirect to occur.
IPC_MESSAGE_ROUTED2(AutomationMsg_WillPerformClientRedirect,
int64 /* frame_id */,
diff --git a/chrome/renderer/automation/automation_renderer_helper.cc b/chrome/renderer/automation/automation_renderer_helper.cc
index 28a8b18..a65b9f28 100644
--- a/chrome/renderer/automation/automation_renderer_helper.cc
+++ b/chrome/renderer/automation/automation_renderer_helper.cc
@@ -4,21 +4,120 @@
#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)
- : content::RenderViewObserver(render_view) {
+ : content::RenderViewObserver(render_view),
+ content::RenderViewObserverTracker<AutomationRendererHelper>(
+ render_view) {
}
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..fc17c4d 100644
--- a/chrome/renderer/automation/automation_renderer_helper.h
+++ b/chrome/renderer/automation/automation_renderer_helper.h
@@ -6,22 +6,37 @@
#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
// automation/testing messages to the browser.
-class AutomationRendererHelper : public content::RenderViewObserver {
+class AutomationRendererHelper
+ : public content::RenderViewObserver,
+ public content::RenderViewObserverTracker<AutomationRendererHelper> {
public:
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..9bc38f0
--- /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::Get(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::Get(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::Get(view_)->SnapshotEntirePage(
+ view_->GetWebView(), &png_data, &error_msg)) << error_msg;
+ CompareSnapshot(png_data, kThreeBoxesMD5);
+}
diff --git a/chrome/test/automation/automation_proxy_uitest.cc b/chrome/test/automation/automation_proxy_uitest.cc
index 22ed307..9b2d4df 100644
--- a/chrome/test/automation/automation_proxy_uitest.cc
+++ b/chrome/test/automation/automation_proxy_uitest.cc
@@ -10,6 +10,7 @@
#include "base/file_util.h"
#include "base/i18n/rtl.h"
#include "base/json/json_value_serializer.h"
+#include "base/md5.h"
#include "base/memory/scoped_ptr.h"
#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
@@ -1529,8 +1530,7 @@ class AutomationProxySnapshotTest : public UITest {
// Asserts that the given png file can be read and decoded into the given
// bitmap.
- void AssertReadPNG(const FilePath& filename, SkBitmap* bitmap) {
- DCHECK(bitmap);
+ void AssertReadPNG(const FilePath& filename, std::string* data) {
ASSERT_TRUE(file_util::PathExists(filename));
int64 size64;
@@ -1540,13 +1540,9 @@ class AutomationProxySnapshotTest : public UITest {
// Read and decode image.
int size = static_cast<int>(size64);
- scoped_array<char> data(new char[size]);
- int bytes_read = file_util::ReadFile(filename, &data[0], size);
+ data->resize(size);
+ int bytes_read = file_util::ReadFile(filename, &(*data)[0], size);
ASSERT_EQ(size, bytes_read);
- ASSERT_TRUE(gfx::PNGCodec::Decode(
- reinterpret_cast<unsigned char*>(&data[0]),
- bytes_read,
- bitmap));
}
// Returns the file path for the directory for these tests appended with
@@ -1566,113 +1562,26 @@ class AutomationProxySnapshotTest : public UITest {
ScopedTempDir snapshot_dir_;
};
-// See http://crbug.com/63022.
-#if defined(OS_LINUX)
-#define MAYBE_ContentLargerThanView FAILS_ContentLargerThanView
-#else
-#define MAYBE_ContentLargerThanView ContentLargerThanView
-#endif
// Tests that taking a snapshot when the content is larger than the view
// produces a snapshot equal to the content size.
-TEST_F(AutomationProxySnapshotTest, MAYBE_ContentLargerThanView) {
- scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
- ASSERT_TRUE(browser.get());
-
- // Resize the window to guarantee that the content is larger than the view.
- scoped_refptr<WindowProxy> window(browser->GetWindow());
- ASSERT_TRUE(window.get());
- ASSERT_TRUE(window->SetBounds(gfx::Rect(300, 400)));
-
- scoped_refptr<TabProxy> tab(browser->GetTab(0));
- ASSERT_TRUE(tab.get());
-
- ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS,
- tab->NavigateToURL(GetTestUrl("set_size.html", "600,800")));
-
- ASSERT_TRUE(tab->CaptureEntirePageAsPNG(snapshot_path_));
-
- SkBitmap bitmap;
- ASSERT_NO_FATAL_FAILURE(AssertReadPNG(snapshot_path_, &bitmap));
- ASSERT_EQ(600, bitmap.width());
- ASSERT_EQ(800, bitmap.height());
-}
-
-// Tests taking a large snapshot works.
-#if defined(OS_LINUX)
-// See http://code.google.com/p/chromium/issues/detail?id=89777
-#define MAYBE_LargeSnapshot DISABLED_LargeSnapshot
-#else
-#define MAYBE_LargeSnapshot LargeSnapshot
-#endif
-TEST_F(AutomationProxySnapshotTest, MAYBE_LargeSnapshot) {
- scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
- ASSERT_TRUE(browser.get());
-
- scoped_refptr<TabProxy> tab(browser->GetTab(0));
- ASSERT_TRUE(tab.get());
-
- // 2000x2000 creates an approximately 15 MB bitmap.
- // Don't increase this too much. At least my linux box has SHMMAX set at
- // 32 MB.
- ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS,
- tab->NavigateToURL(GetTestUrl("set_size.html", "2000,2000")));
-
- ASSERT_TRUE(tab->CaptureEntirePageAsPNG(snapshot_path_));
-
- SkBitmap bitmap;
- ASSERT_NO_FATAL_FAILURE(AssertReadPNG(snapshot_path_, &bitmap));
- ASSERT_EQ(2000, bitmap.width());
- ASSERT_EQ(2000, bitmap.height());
-}
-
-#if defined(OS_MACOSX)
-// Most pixels on mac are slightly off.
-#define MAYBE_ContentsCorrect DISABLED_ContentsCorrect
-#elif defined(OS_LINUX)
-// See http://crbug.com/63022.
-#define MAYBE_ContentsCorrect FAILS_ContentsCorrect
-#else
-#define MAYBE_ContentsCorrect ContentsCorrect
-#endif
-
-// Tests that the snapshot contents are correct.
-TEST_F(AutomationProxySnapshotTest, MAYBE_ContentsCorrect) {
+TEST_F(AutomationProxySnapshotTest, ContentLargerThanView) {
+ const char kReferenceMd5[] = "3d594850fd25cb116338cb3610afe18e";
scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
ASSERT_TRUE(browser.get());
-
- const gfx::Size img_size(400, 300);
- scoped_refptr<WindowProxy> window(browser->GetWindow());
- ASSERT_TRUE(window.get());
- ASSERT_TRUE(window->SetBounds(gfx::Rect(img_size)));
-
scoped_refptr<TabProxy> tab(browser->GetTab(0));
ASSERT_TRUE(tab.get());
ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS,
- tab->NavigateToURL(GetTestUrl("just_image.html", "")));
+ tab->NavigateToURL(GetTestUrl("set_size.html", "2000,2500")));
ASSERT_TRUE(tab->CaptureEntirePageAsPNG(snapshot_path_));
- SkBitmap snapshot_bmp;
- ASSERT_NO_FATAL_FAILURE(AssertReadPNG(snapshot_path_, &snapshot_bmp));
- ASSERT_EQ(img_size.width(), snapshot_bmp.width());
- ASSERT_EQ(img_size.height(), snapshot_bmp.height());
-
- SkBitmap reference_bmp;
- ASSERT_NO_FATAL_FAILURE(AssertReadPNG(GetTestFilePath("image.png"),
- &reference_bmp));
- ASSERT_EQ(img_size.width(), reference_bmp.width());
- ASSERT_EQ(img_size.height(), reference_bmp.height());
-
- SkAutoLockPixels lock_snapshot(snapshot_bmp);
- SkAutoLockPixels lock_reference(reference_bmp);
- int diff_pixels_count = 0;
- for (int x = 0; x < img_size.width(); ++x) {
- for (int y = 0; y < img_size.height(); ++y) {
- if (*snapshot_bmp.getAddr32(x, y) != *reference_bmp.getAddr32(x, y)) {
- ++diff_pixels_count;
- }
- }
+ std::string data;
+ ASSERT_NO_FATAL_FAILURE(AssertReadPNG(snapshot_path_, &data));
+ EXPECT_STREQ(kReferenceMd5, base::MD5String(data).c_str());
+ if (CommandLine::ForCurrentProcess()->HasSwitch("dump-test-image")) {
+ FilePath path(FILE_PATH_LITERAL("snapshot.png"));
+ EXPECT_EQ(file_util::WriteFile(path, &data[0], data.length()),
+ static_cast<int>(data.length()));
}
- ASSERT_EQ(diff_pixels_count, 0);
}
diff --git a/chrome/test/data/automation_proxy_snapshot/just_image.html b/chrome/test/data/automation_proxy_snapshot/just_image.html
deleted file mode 100644
index a2d8c84..0000000
--- a/chrome/test/data/automation_proxy_snapshot/just_image.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<html>
- <head>
- <style>
- * {
- margin: 0px;
- padding: 0px;
- background-color: red;
- }
- </style>
- </head>
- <body>
- <img src="image.png">
- </body>
-</html> \ No newline at end of file
diff --git a/chrome/test/webdriver/test/chromedriver_tests.py b/chrome/test/webdriver/test/chromedriver_tests.py
index a545970..2d23a0c 100644
--- a/chrome/test/webdriver/test/chromedriver_tests.py
+++ b/chrome/test/webdriver/test/chromedriver_tests.py
@@ -389,11 +389,6 @@ class ScreenshotTest(ChromeDriverTest):
REDBOX = "automation_proxy_snapshot/set_size.html"
def testScreenCaptureAgainstReference(self):
- # This has regressed on linux because of tighter sandbox restrictions.
- # See crbug.com/89777.
- if IsLinux():
- return
-
# Create a red square of 2000x2000 pixels.
url = GetFileURLForPath(os.path.join(test_paths.DataDir(),
self.REDBOX))