2
* Copyright (C) 2012 Google Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are
8
* * Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* * Redistributions in binary form must reproduce the above
11
* copyright notice, this list of conditions and the following disclaimer
12
* in the documentation and/or other materials provided with the
14
* * Neither the name of Google Inc. nor the names of its
15
* contributors may be used to endorse or promote products derived from
16
* this software without specific prior written permission.
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
#include "TestShell.h"
34
#include "DRTDevToolsAgent.h"
35
#include "DRTDevToolsClient.h"
36
#include "DRTTestRunner.h"
37
#include "MockWebPrerenderingSupport.h"
39
#include "WebDataSource.h"
40
#include "WebDocument.h"
41
#include "WebElement.h"
43
#include "WebHistoryItem.h"
44
#include "WebIDBFactory.h"
45
#include "WebTestingSupport.h"
46
#include "WebPermissions.h"
47
#include "WebRuntimeFeatures.h"
48
#include "WebScriptController.h"
49
#include "WebSettings.h"
50
#include "WebTestProxy.h"
52
#include "WebViewHost.h"
53
#include "platform/WebArrayBufferView.h"
54
#include "skia/ext/platform_canvas.h"
55
#include "webkit/support/webkit_support.h"
56
#include "webkit/support/webkit_support_gfx.h"
57
#include <public/Platform.h>
58
#include <public/WebCompositorSupport.h>
59
#include <public/WebPoint.h>
60
#include <public/WebSize.h>
61
#include <public/WebString.h>
62
#include <public/WebThread.h>
63
#include <public/WebURLRequest.h>
64
#include <public/WebURLResponse.h>
69
#include <wtf/OwnArrayPtr.h>
72
using namespace WebKit;
73
using namespace WebTestRunner;
76
// Content area size for newly created windows.
77
static const int testWindowWidth = 800;
78
static const int testWindowHeight = 600;
80
// The W3C SVG layout tests use a different size than the other layout tests.
81
static const int SVGTestWindowWidth = 480;
82
static const int SVGTestWindowHeight = 360;
84
static const char layoutTestsPattern[] = "/LayoutTests/";
85
static const string::size_type layoutTestsPatternSize = sizeof(layoutTestsPattern) - 1;
86
static const char fileUrlPattern[] = "file:/";
87
static const char fileTestPrefix[] = "(file test):";
88
static const char dataUrlPattern[] = "data:";
89
static const string::size_type dataUrlPatternSize = sizeof(dataUrlPattern) - 1;
91
// FIXME: Move this to a common place so that it can be shared with
92
// WebCore::TransparencyWin::makeLayerOpaque().
93
static void makeCanvasOpaque(SkCanvas* canvas)
95
const SkBitmap& bitmap = canvas->getTopDevice()->accessBitmap(true);
96
ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
98
SkAutoLockPixels lock(bitmap);
99
for (int y = 0; y < bitmap.height(); y++) {
100
uint32_t* row = bitmap.getAddr32(0, y);
101
for (int x = 0; x < bitmap.width(); x++)
102
row[x] |= 0xFF000000; // Set alpha bits to 1.
106
TestShell::TestShell()
107
: m_testIsPending(false)
108
, m_testIsPreparing(false)
111
, m_dumpPixelsForCurrentTest(false)
112
, m_allowExternalPages(false)
113
, m_acceleratedCompositingForVideoEnabled(false)
114
, m_acceleratedCompositingForFixedPositionEnabled(false)
115
, m_softwareCompositingEnabled(false)
116
, m_threadedCompositingEnabled(false)
117
, m_forceCompositingMode(false)
118
, m_accelerated2dCanvasEnabled(false)
119
, m_deferred2dCanvasEnabled(false)
120
, m_acceleratedPaintingEnabled(false)
121
, m_perTilePaintingEnabled(false)
122
, m_acceleratedAnimationEnabled(false)
123
, m_deferredImageDecodingEnabled(false)
125
, m_stressDeopt(false)
126
, m_dumpWhenFinished(true)
127
, m_isDisplayingModalDialog(false)
129
WebRuntimeFeatures::enableDataTransferItems(true);
130
WebRuntimeFeatures::enableDeviceMotion(false);
131
WebRuntimeFeatures::enableGeolocation(true);
132
WebRuntimeFeatures::enableIndexedDatabase(true);
133
WebRuntimeFeatures::enableInputTypeDateTime(true);
134
WebRuntimeFeatures::enableInputTypeDateTimeLocal(true);
135
WebRuntimeFeatures::enableInputTypeMonth(true);
136
WebRuntimeFeatures::enableInputTypeTime(true);
137
WebRuntimeFeatures::enableInputTypeWeek(true);
138
WebRuntimeFeatures::enableFileSystem(true);
139
WebRuntimeFeatures::enableJavaScriptI18NAPI(true);
140
WebRuntimeFeatures::enableMediaSource(true);
141
WebRuntimeFeatures::enableEncryptedMedia(true);
142
WebRuntimeFeatures::enableMediaStream(true);
143
WebRuntimeFeatures::enablePeerConnection(true);
144
WebRuntimeFeatures::enableWebAudio(true);
145
WebRuntimeFeatures::enableVideoTrack(true);
146
WebRuntimeFeatures::enableGamepad(true);
147
WebRuntimeFeatures::enableShadowDOM(true);
148
WebRuntimeFeatures::enableStyleScoped(true);
149
WebRuntimeFeatures::enableScriptedSpeech(true);
150
WebRuntimeFeatures::enableRequestAutocomplete(true);
152
// 30 second is the same as the value in Mac DRT.
153
// If we use a value smaller than the timeout value of
154
// (new-)run-webkit-tests, (new-)run-webkit-tests misunderstands that a
155
// timed-out DRT process was crashed.
156
m_timeout = 30 * 1000;
159
void TestShell::initialize()
161
m_webPermissions = adoptPtr(new WebPermissions(this));
162
m_testInterfaces = adoptPtr(new WebTestInterfaces());
163
m_testRunner = adoptPtr(new DRTTestRunner(this));
164
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
165
m_notificationPresenter = adoptPtr(new NotificationPresenter(this));
167
#if ENABLE(LINK_PRERENDER)
168
m_prerenderingSupport = adoptPtr(new MockWebPrerenderingSupport());
171
WTF::initializeThreading();
173
if (m_threadedCompositingEnabled)
174
m_webCompositorThread = adoptPtr(WebKit::Platform::current()->createThread("Compositor"));
175
WebKit::Platform::current()->compositorSupport()->initialize(m_webCompositorThread.get());
180
void TestShell::createMainWindow()
182
m_drtDevToolsAgent = adoptPtr(new DRTDevToolsAgent);
183
m_webViewHost = adoptPtr(createNewWindow(WebURL(), m_drtDevToolsAgent.get()));
184
m_webView = m_webViewHost->webView();
185
m_testInterfaces->setDelegate(m_webViewHost.get());
186
m_testInterfaces->setWebView(m_webView);
187
m_testRunner->setDelegate(m_webViewHost.get());
188
m_testRunner->setWebView(m_webView);
189
m_drtDevToolsAgent->setWebView(m_webView);
192
TestShell::~TestShell()
194
m_testInterfaces->setDelegate(0);
195
m_testInterfaces->setWebView(0);
196
m_testRunner->setDelegate(0);
197
m_testRunner->setWebView(0);
198
m_drtDevToolsAgent->setWebView(0);
201
void TestShell::createDRTDevToolsClient(DRTDevToolsAgent* agent)
203
m_drtDevToolsClient = adoptPtr(new DRTDevToolsClient(agent, m_devTools->webView()));
206
void TestShell::showDevTools()
209
WebURL url = webkit_support::GetDevToolsPathAsURL();
210
if (!url.isValid()) {
214
m_devTools = createNewWindow(url);
215
m_devTools->webView()->settings()->setMemoryInfoEnabled(true);
216
m_devTools->setLogConsoleOutput(false);
218
createDRTDevToolsClient(m_drtDevToolsAgent.get());
220
m_devTools->show(WebKit::WebNavigationPolicyNewWindow);
223
void TestShell::closeDevTools()
226
m_devTools->webView()->settings()->setMemoryInfoEnabled(false);
227
m_drtDevToolsAgent->reset();
228
m_drtDevToolsClient.clear();
229
closeWindow(m_devTools);
234
void TestShell::resetWebSettings(WebView& webView)
237
m_prefs.acceleratedCompositingEnabled = true;
238
m_prefs.acceleratedCompositingForVideoEnabled = m_acceleratedCompositingForVideoEnabled;
239
m_prefs.acceleratedCompositingForFixedPositionEnabled = m_acceleratedCompositingForFixedPositionEnabled;
240
m_prefs.forceCompositingMode = m_forceCompositingMode;
241
m_prefs.accelerated2dCanvasEnabled = m_accelerated2dCanvasEnabled;
242
m_prefs.deferred2dCanvasEnabled = m_deferred2dCanvasEnabled;
243
m_prefs.acceleratedPaintingEnabled = m_acceleratedPaintingEnabled;
244
m_prefs.perTilePaintingEnabled = m_perTilePaintingEnabled;
245
m_prefs.acceleratedAnimationEnabled = m_acceleratedAnimationEnabled;
246
m_prefs.deferredImageDecodingEnabled = m_deferredImageDecodingEnabled;
247
m_prefs.applyTo(&webView);
250
void TestShell::runFileTest(const TestParams& params, bool shouldDumpPixels)
252
ASSERT(params.testUrl.isValid());
253
m_dumpPixelsForCurrentTest = shouldDumpPixels;
254
m_testIsPreparing = true;
256
string testUrl = m_params.testUrl.spec();
258
m_testRunner->setShouldGeneratePixelResults(shouldDumpPixels);
260
if (testUrl.find("loading/") != string::npos
261
|| testUrl.find("loading\\") != string::npos)
262
m_testRunner->setShouldDumpFrameLoadCallbacks(true);
264
if (testUrl.find("compositing/") != string::npos || testUrl.find("compositing\\") != string::npos) {
265
if (!m_softwareCompositingEnabled)
266
m_prefs.accelerated2dCanvasEnabled = true;
267
m_prefs.acceleratedCompositingForVideoEnabled = true;
268
m_prefs.deferred2dCanvasEnabled = true;
269
m_prefs.mockScrollbarsEnabled = true;
270
m_prefs.applyTo(m_webView);
273
if (testUrl.find("/dumpAsText/") != string::npos
274
|| testUrl.find("\\dumpAsText\\") != string::npos) {
275
m_testRunner->setShouldDumpAsText(true);
276
m_testRunner->setShouldGeneratePixelResults(false);
279
if (testUrl.find("/inspector/") != string::npos
280
|| testUrl.find("\\inspector\\") != string::npos)
283
if (m_params.debugLayerTree)
284
m_testRunner->setShowDebugLayerTree(true);
286
if (m_dumpWhenFinished)
287
m_printer.handleTestHeader(testUrl.c_str());
288
loadURL(m_params.testUrl);
290
m_testIsPreparing = false;
294
static inline bool isSVGTestURL(const WebURL& url)
296
return url.isValid() && string(url.spec()).find("W3C-SVG-1.1") != string::npos;
299
void TestShell::resizeWindowForTest(WebViewHost* window, const WebURL& url)
302
if (isSVGTestURL(url)) {
303
width = SVGTestWindowWidth;
304
height = SVGTestWindowHeight;
306
width = testWindowWidth;
307
height = testWindowHeight;
309
window->setWindowRect(WebRect(0, 0, width + virtualWindowBorder * 2, height + virtualWindowBorder * 2));
312
void TestShell::resetTestController()
314
resetWebSettings(*webView());
315
m_webPermissions->reset();
316
m_testInterfaces->resetAll();
317
m_testRunner->reset();
318
m_webViewHost->reset();
319
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
320
m_notificationPresenter->reset();
323
webkit_support::ReleaseMediaResources();
325
m_drtDevToolsAgent->reset();
326
if (m_drtDevToolsClient)
327
m_drtDevToolsClient->reset();
328
webView()->setPageScaleFactor(1, WebPoint(0, 0));
329
webView()->enableFixedLayoutMode(false);
330
webView()->setFixedLayoutSize(WebSize(0, 0));
331
webView()->mainFrame()->clearOpener();
332
WebTestingSupport::resetInternalsObject(webView()->mainFrame());
336
void TestShell::loadURL(const WebURL& url)
338
m_webViewHost->loadURLForFrame(url, WebString());
341
void TestShell::reload()
343
m_webViewHost->navigationController()->reload();
346
void TestShell::goToOffset(int offset)
348
m_webViewHost->navigationController()->goToOffset(offset);
351
int TestShell::navigationEntryCount() const
353
return m_webViewHost->navigationController()->entryCount();
356
void TestShell::callJSGC()
358
m_webView->mainFrame()->collectGarbage();
361
void TestShell::setFocus(WebWidget* widget, bool enable)
363
// Simulate the effects of InteractiveSetFocus(), which includes calling
364
// both setFocus() and setIsActive().
366
if (m_focusedWidget != widget) {
368
m_focusedWidget->setFocus(false);
369
webView()->setIsActive(enable);
370
widget->setFocus(enable);
371
m_focusedWidget = widget;
374
if (m_focusedWidget == widget) {
375
widget->setFocus(enable);
376
webView()->setIsActive(enable);
382
void TestShell::testFinished()
384
if (!m_testIsPending)
386
m_testIsPending = false;
387
if (m_dumpWhenFinished)
389
webkit_support::QuitMessageLoop();
392
void TestShell::testTimedOut()
394
m_printer.handleTimedOut();
398
static string dumpDocumentText(WebFrame* frame)
400
// We use the document element's text instead of the body text here because
401
// not all documents have a body, such as XML documents.
402
WebElement documentElement = frame->document().documentElement();
403
if (documentElement.isNull())
405
return documentElement.innerText().utf8();
408
static string dumpFramesAsText(WebFrame* frame, bool recursive)
412
// Add header for all but the main frame. Skip empty frames.
413
if (frame->parent() && !frame->document().documentElement().isNull()) {
414
result.append("\n--------\nFrame: '");
415
result.append(frame->uniqueName().utf8().data());
416
result.append("'\n--------\n");
419
result.append(dumpDocumentText(frame));
423
for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling())
424
result.append(dumpFramesAsText(child, recursive));
430
static string dumpFramesAsPrintedText(WebFrame* frame, bool recursive)
434
// Cannot do printed format for anything other than HTML
435
if (!frame->document().isHTMLDocument())
438
// Add header for all but the main frame. Skip empty frames.
439
if (frame->parent() && !frame->document().documentElement().isNull()) {
440
result.append("\n--------\nFrame: '");
441
result.append(frame->uniqueName().utf8().data());
442
result.append("'\n--------\n");
445
result.append(frame->renderTreeAsText(WebFrame::RenderAsTextPrinting).utf8());
449
for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling())
450
result.append(dumpFramesAsPrintedText(child, recursive));
456
static void dumpFrameScrollPosition(WebFrame* frame, bool recursive)
458
WebSize offset = frame->scrollOffset();
459
if (offset.width > 0 || offset.height > 0) {
461
printf("frame '%s' ", frame->uniqueName().utf8().data());
462
printf("scrolled to %d,%d\n", offset.width, offset.height);
467
for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling())
468
dumpFrameScrollPosition(child, recursive);
472
char16 operator()(char16 c) { return tolower(c); }
475
// FIXME: Eliminate std::transform(), std::vector, and std::sort().
477
// Returns True if item1 < item2.
478
static bool HistoryItemCompareLess(const WebHistoryItem& item1, const WebHistoryItem& item2)
480
string16 target1 = item1.target();
481
string16 target2 = item2.target();
482
std::transform(target1.begin(), target1.end(), target1.begin(), ToLower());
483
std::transform(target2.begin(), target2.end(), target2.begin(), ToLower());
484
return target1 < target2;
487
static string normalizeLayoutTestURLInternal(const string& url)
491
if (!url.find(fileUrlPattern) && ((pos = url.find(layoutTestsPattern)) != string::npos)) {
492
// adjust file URLs to match upstream results.
493
result.replace(0, pos + layoutTestsPatternSize, fileTestPrefix);
494
} else if (!url.find(dataUrlPattern)) {
495
// URL-escape data URLs to match results upstream.
496
string path = url.substr(dataUrlPatternSize);
497
result.replace(dataUrlPatternSize, url.length(), path);
502
static string dumpHistoryItem(const WebHistoryItem& item, int indent, bool isCurrent)
507
result.append("curr->");
508
result.append(indent - 6, ' '); // 6 == "curr->".length()
510
result.append(indent, ' ');
512
string url = normalizeLayoutTestURLInternal(item.urlString().utf8());
514
if (!item.target().isEmpty()) {
515
result.append(" (in frame \"");
516
result.append(item.target().utf8());
517
result.append("\")");
519
if (item.isTargetItem())
520
result.append(" **nav target**");
523
const WebVector<WebHistoryItem>& children = item.children();
524
if (!children.isEmpty()) {
525
// Must sort to eliminate arbitrary result ordering which defeats
526
// reproducible testing.
527
// FIXME: WebVector should probably just be a std::vector!!
528
std::vector<WebHistoryItem> sortedChildren;
529
for (size_t i = 0; i < children.size(); ++i)
530
sortedChildren.push_back(children[i]);
531
std::sort(sortedChildren.begin(), sortedChildren.end(), HistoryItemCompareLess);
532
for (size_t i = 0; i < sortedChildren.size(); ++i)
533
result += dumpHistoryItem(sortedChildren[i], indent + 4, false);
539
static void dumpBackForwardList(const TestNavigationController& navigationController, string& result)
541
result.append("\n============== Back Forward List ==============\n");
542
for (int index = 0; index < navigationController.entryCount(); ++index) {
543
int currentIndex = navigationController.lastCommittedEntryIndex();
544
WebHistoryItem historyItem = navigationController.entryAtIndex(index)->contentState();
545
if (historyItem.isNull()) {
546
historyItem.initialize();
547
historyItem.setURLString(navigationController.entryAtIndex(index)->URL().spec().utf16());
549
result.append(dumpHistoryItem(historyItem, 8, index == currentIndex));
551
result.append("===============================================\n");
554
string TestShell::dumpAllBackForwardLists()
557
for (unsigned i = 0; i < m_windowList.size(); ++i)
558
dumpBackForwardList(*m_windowList[i]->navigationController(), result);
562
void TestShell::dump()
564
WebScriptController::flushConsoleMessages();
566
// Dump the requested representation.
567
WebFrame* frame = m_webView->mainFrame();
570
bool shouldDumpAsText = m_testRunner->shouldDumpAsText();
571
bool shouldDumpAsAudio = m_testRunner->shouldDumpAsAudio();
572
bool shouldGeneratePixelResults = m_testRunner->shouldGeneratePixelResults();
573
bool shouldDumpAsPrinted = m_testRunner->isPrinting();
574
bool dumpedAnything = false;
576
if (shouldDumpAsAudio) {
577
const WebKit::WebArrayBufferView& webArrayBufferView = m_testRunner->audioData();
578
m_printer.handleAudio(webArrayBufferView.baseAddress(), webArrayBufferView.byteLength());
579
m_printer.handleAudioFooter();
580
m_printer.handleTestFooter(true);
587
if (m_params.dumpTree) {
588
dumpedAnything = true;
589
m_printer.handleTextHeader();
590
// Text output: the test page can request different types of output
591
// which we handle here.
592
if (!shouldDumpAsText) {
593
// Plain text pages should be dumped as text
594
string mimeType = frame->dataSource()->response().mimeType().utf8();
595
if (mimeType == "text/plain") {
596
shouldDumpAsText = true;
597
shouldGeneratePixelResults = false;
600
if (shouldDumpAsText) {
601
bool recursive = m_testRunner->shouldDumpChildFramesAsText();
602
string dataUtf8 = shouldDumpAsPrinted ? dumpFramesAsPrintedText(frame, recursive) : dumpFramesAsText(frame, recursive);
603
if (fwrite(dataUtf8.c_str(), 1, dataUtf8.size(), stdout) != dataUtf8.size())
604
FATAL("Short write to stdout, disk full?\n");
606
WebFrame::RenderAsTextControls renderTextBehavior = WebFrame::RenderAsTextNormal;
607
if (shouldDumpAsPrinted)
608
renderTextBehavior |= WebFrame::RenderAsTextPrinting;
609
if (m_params.debugRenderTree)
610
renderTextBehavior |= WebFrame::RenderAsTextDebug;
611
printf("%s", frame->renderTreeAsText(renderTextBehavior).utf8().data());
612
bool recursive = m_testRunner->shouldDumpChildFrameScrollPositions();
613
dumpFrameScrollPosition(frame, recursive);
615
if (m_testRunner->shouldDumpBackForwardList())
616
printf("%s", dumpAllBackForwardLists().c_str());
618
if (dumpedAnything && m_params.printSeparators)
619
m_printer.handleTextFooter();
621
if (m_dumpPixelsForCurrentTest && shouldGeneratePixelResults) {
622
// Image output: we write the image data to the file given on the
623
// command line (for the dump pixels argument), and the MD5 sum to
625
dumpedAnything = true;
627
if (m_testRunner->testRepaint()) {
628
WebSize viewSize = m_webView->size();
629
int width = viewSize.width;
630
int height = viewSize.height;
631
if (m_testRunner->sweepHorizontally()) {
632
for (WebRect column(0, 0, 1, height); column.x < width; column.x++)
633
m_webViewHost->paintRect(column);
635
for (WebRect line(0, 0, width, 1); line.y < height; line.y++)
636
m_webViewHost->paintRect(line);
638
} else if (m_testRunner->isPrinting())
639
m_webViewHost->paintPagesWithBoundaries();
641
m_webViewHost->paintInvalidatedRegion();
643
// See if we need to draw the selection bounds rect. Selection bounds
644
// rect is the rect enclosing the (possibly transformed) selection.
645
// The rect should be drawn after everything is laid out and painted.
646
if (m_testRunner->shouldDumpSelectionRect()) {
647
// If there is a selection rect - draw a red 1px border enclosing rect
648
WebRect wr = frame->selectionBoundsRect();
650
// Render a red rectangle bounding selection rect
652
paint.setColor(0xFFFF0000); // Fully opaque red
653
paint.setStyle(SkPaint::kStroke_Style);
654
paint.setFlags(SkPaint::kAntiAlias_Flag);
655
paint.setStrokeWidth(1.0f);
656
SkIRect rect; // Bounding rect
657
rect.set(wr.x, wr.y, wr.x + wr.width, wr.y + wr.height);
658
m_webViewHost->canvas()->drawIRect(rect, paint);
662
dumpImage(m_webViewHost->canvas());
664
m_printer.handleTestFooter(dumpedAnything);
669
void TestShell::dumpImage(SkCanvas* canvas) const
671
// Fix the alpha. The expected PNGs on Mac have an alpha channel, so we want
672
// to keep it. On Windows, the alpha channel is wrong since text/form control
673
// drawing may have erased it in a few places. So on Windows we force it to
674
// opaque and also don't write the alpha channel for the reference. Linux
675
// doesn't have the wrong alpha like Windows, but we match Windows.
677
bool discardTransparency = false;
679
bool discardTransparency = true;
680
makeCanvasOpaque(canvas);
683
const SkBitmap& sourceBitmap = canvas->getTopDevice()->accessBitmap(false);
684
SkAutoLockPixels sourceBitmapLock(sourceBitmap);
688
Vector<uint8_t, 16> digestValue;
690
// On Android, pixel layout is RGBA (see third_party/skia/include/core/SkColorPriv.h);
691
// however, other Chrome platforms use BGRA (see skia/config/SkUserConfig.h).
692
// To match the checksum of other Chrome platforms, we need to reorder the layout of pixels.
693
// NOTE: The following code assumes we use SkBitmap::kARGB_8888_Config,
694
// which has been checked in device.makeOpaque() (see above).
695
const uint8_t* rawPixels = reinterpret_cast<const uint8_t*>(sourceBitmap.getPixels());
696
size_t bitmapSize = sourceBitmap.getSize();
697
OwnArrayPtr<uint8_t> reorderedPixels = adoptArrayPtr(new uint8_t[bitmapSize]);
698
for (size_t i = 0; i < bitmapSize; i += 4) {
699
reorderedPixels[i] = rawPixels[i + 2]; // R
700
reorderedPixels[i + 1] = rawPixels[i + 1]; // G
701
reorderedPixels[i + 2] = rawPixels[i]; // B
702
reorderedPixels[i + 3] = rawPixels[i + 3]; // A
704
digester.addBytes(reorderedPixels.get(), bitmapSize);
705
reorderedPixels.clear();
707
digester.addBytes(reinterpret_cast<const uint8_t*>(sourceBitmap.getPixels()), sourceBitmap.getSize());
709
digester.checksum(digestValue);
711
md5hash.reserve(16 * 2);
712
for (unsigned i = 0; i < 16; ++i) {
714
// Use "x", not "X". The string must be lowercased.
715
sprintf(hex, "%02x", digestValue[i]);
719
// Only encode and dump the png if the hashes don't match. Encoding the
720
// image is really expensive.
721
if (md5hash.compare(m_params.pixelHash)) {
722
std::vector<unsigned char> png;
724
webkit_support::EncodeRGBAPNGWithChecksum(reinterpret_cast<const unsigned char*>(sourceBitmap.getPixels()), sourceBitmap.width(),
725
sourceBitmap.height(), static_cast<int>(sourceBitmap.rowBytes()), discardTransparency, md5hash, &png);
727
webkit_support::EncodeBGRAPNGWithChecksum(reinterpret_cast<const unsigned char*>(sourceBitmap.getPixels()), sourceBitmap.width(),
728
sourceBitmap.height(), static_cast<int>(sourceBitmap.rowBytes()), discardTransparency, md5hash, &png);
731
m_printer.handleImage(md5hash.c_str(), m_params.pixelHash.c_str(), &png[0], png.size());
733
m_printer.handleImage(md5hash.c_str(), m_params.pixelHash.c_str(), 0, 0);
736
void TestShell::bindJSObjectsToWindow(WebFrame* frame)
738
WebTestingSupport::injectInternalsObject(frame);
739
m_testInterfaces->bindTo(frame);
740
m_testRunner->bindToJavascript(frame, WebString::fromUTF8("testRunner"));
741
m_testRunner->bindToJavascript(frame, WebString::fromUTF8("layoutTestController"));
744
WebViewHost* TestShell::createNewWindow(const WebKit::WebURL& url)
746
return createNewWindow(url, 0);
749
WebViewHost* TestShell::createNewWindow(const WebKit::WebURL& url, DRTDevToolsAgent* devToolsAgent)
751
WebTestRunner::WebTestProxy<WebViewHost, TestShell*>* host = new WebTestRunner::WebTestProxy<WebViewHost, TestShell*>(this);
752
host->setInterfaces(m_testInterfaces.get());
754
host->setDelegate(m_webViewHost.get());
756
host->setDelegate(host);
757
host->setProxy(host);
758
WebView* view = WebView::create(host);
759
view->setPermissionClient(webPermissions());
760
view->setDevToolsAgentClient(devToolsAgent);
761
host->setWebWidget(view);
762
m_prefs.applyTo(view);
763
view->initializeMainFrame(host);
764
m_windowList.append(host);
765
host->loadURLForFrame(url, WebString());
769
void TestShell::closeWindow(WebViewHost* window)
771
size_t i = m_windowList.find(window);
773
ASSERT_NOT_REACHED();
776
m_windowList.remove(i);
777
WebWidget* focusedWidget = m_focusedWidget;
778
if (window->webWidget() == m_focusedWidget)
782
// We set the focused widget after deleting the web view host because it
783
// can change the focus.
784
m_focusedWidget = focusedWidget;
785
if (m_focusedWidget) {
786
webView()->setIsActive(true);
787
m_focusedWidget->setFocus(true);
791
void TestShell::closeRemainingWindows()
793
// Just close devTools window manually because we have custom deinitialization code for it.
796
// Iterate through the window list and close everything except the main
797
// window. We don't want to delete elements as we're iterating, so we copy
798
// to a temp vector first.
799
Vector<WebViewHost*> windowsToDelete;
800
for (unsigned i = 0; i < m_windowList.size(); ++i) {
801
if (m_windowList[i] != webViewHost())
802
windowsToDelete.append(m_windowList[i]);
804
ASSERT(windowsToDelete.size() + 1 == m_windowList.size());
805
for (unsigned i = 0; i < windowsToDelete.size(); ++i)
806
closeWindow(windowsToDelete[i]);
807
ASSERT(m_windowList.size() == 1);
810
int TestShell::windowCount()
812
return m_windowList.size();
815
string TestShell::normalizeLayoutTestURL(const string& url)
817
return normalizeLayoutTestURLInternal(url);