diff options
author | kkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-27 22:50:35 +0000 |
---|---|---|
committer | kkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-27 22:50:35 +0000 |
commit | 44fbf837bff527c9f2cb9757a96034cf093706af (patch) | |
tree | 708b50c56bf2f1ae0f5f7e707789efa98c5a9ded | |
parent | 3ba226c5d3494fbe754c860366f7126cd51df9d2 (diff) | |
download | chromium_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
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)) |