[chromium] move most of the remaining mocks to TestRunner library
[WebKit-https.git] / Tools / DumpRenderTree / chromium / TestRunner / src / WebTestProxy.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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
13  * distribution.
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.
17  *
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.
29  */
30
31 #include "config.h"
32 #include "WebTestProxy.h"
33
34 #include "AccessibilityControllerChromium.h"
35 #include "EventSender.h"
36 #include "MockWebSpeechInputController.h"
37 #include "MockWebSpeechRecognizer.h"
38 #include "SpellCheckClient.h"
39 #include "TestCommon.h"
40 #include "TestInterfaces.h"
41 #include "TestPlugin.h"
42 #include "TestRunner.h"
43 #include "WebAccessibilityNotification.h"
44 #include "WebAccessibilityObject.h"
45 #include "WebCachedURLRequest.h"
46 #include "WebConsoleMessage.h"
47 #include "WebDataSource.h"
48 #include "WebDeviceOrientationClientMock.h"
49 #include "WebDocument.h"
50 #include "WebElement.h"
51 #include "WebFrame.h"
52 #include "WebGeolocationClientMock.h"
53 #include "WebHistoryItem.h"
54 #include "WebNode.h"
55 #include "WebPluginParams.h"
56 #include "WebPrintParams.h"
57 #include "WebRange.h"
58 #include "WebScriptController.h"
59 #include "WebTestDelegate.h"
60 #include "WebTestInterfaces.h"
61 #include "WebTestRunner.h"
62 #include "WebUserMediaClientMock.h"
63 #include "WebView.h"
64 // FIXME: Including platform_canvas.h here is a layering violation.
65 #include "skia/ext/platform_canvas.h"
66 #include <cctype>
67 #include <public/WebCString.h>
68 #include <public/WebURLError.h>
69 #include <public/WebURLRequest.h>
70 #include <public/WebURLResponse.h>
71
72 using namespace WebKit;
73 using namespace std;
74
75 namespace WebTestRunner {
76
77 namespace {
78
79 void printNodeDescription(WebTestDelegate* delegate, const WebNode& node, int exception)
80 {
81     if (exception) {
82         delegate->printMessage("ERROR");
83         return;
84     }
85     if (node.isNull()) {
86         delegate->printMessage("(null)");
87         return;
88     }
89     delegate->printMessage(node.nodeName().utf8().data());
90     const WebNode& parent = node.parentNode();
91     if (!parent.isNull()) {
92         delegate->printMessage(" > ");
93         printNodeDescription(delegate, parent, 0);
94     }
95 }
96
97 void printRangeDescription(WebTestDelegate* delegate, const WebRange& range)
98 {
99     if (range.isNull()) {
100         delegate->printMessage("(null)");
101         return;
102     }
103     char buffer[100];
104     snprintf(buffer, sizeof(buffer), "range from %d of ", range.startOffset());
105     delegate->printMessage(buffer);
106     int exception = 0;
107     WebNode startNode = range.startContainer(exception);
108     printNodeDescription(delegate, startNode, exception);
109     snprintf(buffer, sizeof(buffer), " to %d of ", range.endOffset());
110     delegate->printMessage(buffer);
111     WebNode endNode = range.endContainer(exception);
112     printNodeDescription(delegate, endNode, exception);
113 }
114
115 string editingActionDescription(WebEditingAction action)
116 {
117     switch (action) {
118     case WebKit::WebEditingActionTyped:
119         return "WebViewInsertActionTyped";
120     case WebKit::WebEditingActionPasted:
121         return "WebViewInsertActionPasted";
122     case WebKit::WebEditingActionDropped:
123         return "WebViewInsertActionDropped";
124     }
125     return "(UNKNOWN ACTION)";
126 }
127
128 string textAffinityDescription(WebTextAffinity affinity)
129 {
130     switch (affinity) {
131     case WebKit::WebTextAffinityUpstream:
132         return "NSSelectionAffinityUpstream";
133     case WebKit::WebTextAffinityDownstream:
134         return "NSSelectionAffinityDownstream";
135     }
136     return "(UNKNOWN AFFINITY)";
137 }
138
139 void printFrameDescription(WebTestDelegate* delegate, WebFrame* frame)
140 {
141     string name8 = frame->uniqueName().utf8();
142     if (frame == frame->view()->mainFrame()) {
143         if (!name8.length()) {
144             delegate->printMessage("main frame");
145             return;
146         }
147         delegate->printMessage(string("main frame \"") + name8 + "\"");
148         return;
149     }
150     if (!name8.length()) {
151         delegate->printMessage("frame (anonymous)");
152         return;
153     }
154     delegate->printMessage(string("frame \"") + name8 + "\"");
155 }
156
157 void printFrameUserGestureStatus(WebTestDelegate* delegate, WebFrame* frame, const char* msg)
158 {
159     bool isUserGesture = frame->isProcessingUserGesture();
160     delegate->printMessage(string("Frame with user gesture \"") + (isUserGesture ? "true" : "false") + "\"" + msg);
161 }
162
163 // Used to write a platform neutral file:/// URL by taking the
164 // filename and its directory. (e.g., converts
165 // "file:///tmp/foo/bar.txt" to just "bar.txt").
166 string descriptionSuitableForTestResult(const string& url)
167 {
168     if (url.empty() || string::npos == url.find("file://"))
169         return url;
170
171     size_t pos = url.rfind('/');
172     if (pos == string::npos || !pos)
173         return "ERROR:" + url;
174     pos = url.rfind('/', pos - 1);
175     if (pos == string::npos)
176         return "ERROR:" + url;
177
178     return url.substr(pos + 1);
179 }
180
181 void printResponseDescription(WebTestDelegate* delegate, const WebURLResponse& response)
182 {
183     if (response.isNull()) {
184         delegate->printMessage("(null)");
185         return;
186     }
187     string url = response.url().spec();
188     char data[100];
189     snprintf(data, sizeof(data), "%d", response. httpStatusCode());
190     delegate->printMessage(string("<NSURLResponse ") + descriptionSuitableForTestResult(url) + ", http status code " + data + ">");
191 }
192
193 string URLDescription(const GURL& url)
194 {
195     if (url.SchemeIs("file"))
196         return url.ExtractFileName();
197     return url.possibly_invalid_spec();
198 }
199
200 void blockRequest(WebURLRequest& request)
201 {
202     request.setURL(WebURL());
203 }
204
205 bool isLocalhost(const string& host)
206 {
207     return host == "127.0.0.1" || host == "localhost";
208 }
209
210 bool hostIsUsedBySomeTestsToGenerateError(const string& host)
211 {
212     return host == "255.255.255.255";
213 }
214
215 // Used to write a platform neutral file:/// URL by only taking the filename
216 // (e.g., converts "file:///tmp/foo.txt" to just "foo.txt").
217 string urlSuitableForTestResult(const string& url)
218 {
219     if (url.empty() || string::npos == url.find("file://"))
220         return url;
221
222     size_t pos = url.rfind('/');
223     if (pos == string::npos) {
224 #ifdef WIN32
225         pos = url.rfind('\\');
226         if (pos == string::npos)
227             pos = 0;
228 #else
229         pos = 0;
230 #endif
231     }
232     string filename = url.substr(pos + 1);
233     if (filename.empty())
234         return "file:"; // A WebKit test has this in its expected output.
235     return filename;
236 }
237
238 // WebNavigationType debugging strings taken from PolicyDelegate.mm.
239 const char* linkClickedString = "link clicked";
240 const char* formSubmittedString = "form submitted";
241 const char* backForwardString = "back/forward";
242 const char* reloadString = "reload";
243 const char* formResubmittedString = "form resubmitted";
244 const char* otherString = "other";
245 const char* illegalString = "illegal value";
246
247 // Get a debugging string from a WebNavigationType.
248 const char* webNavigationTypeToString(WebNavigationType type)
249 {
250     switch (type) {
251     case WebKit::WebNavigationTypeLinkClicked:
252         return linkClickedString;
253     case WebKit::WebNavigationTypeFormSubmitted:
254         return formSubmittedString;
255     case WebKit::WebNavigationTypeBackForward:
256         return backForwardString;
257     case WebKit::WebNavigationTypeReload:
258         return reloadString;
259     case WebKit::WebNavigationTypeFormResubmitted:
260         return formResubmittedString;
261     case WebKit::WebNavigationTypeOther:
262         return otherString;
263     }
264     return illegalString;
265 }
266
267 string dumpDocumentText(WebFrame* frame)
268 {
269     // We use the document element's text instead of the body text here because
270     // not all documents have a body, such as XML documents.
271     WebElement documentElement = frame->document().documentElement();
272     if (documentElement.isNull())
273         return string();
274     return documentElement.innerText().utf8();
275 }
276
277 string dumpFramesAsText(WebFrame* frame, bool recursive)
278 {
279     string result;
280
281     // Add header for all but the main frame. Skip empty frames.
282     if (frame->parent() && !frame->document().documentElement().isNull()) {
283         result.append("\n--------\nFrame: '");
284         result.append(frame->uniqueName().utf8().data());
285         result.append("'\n--------\n");
286     }
287
288     result.append(dumpDocumentText(frame));
289     result.append("\n");
290
291     if (recursive) {
292         for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling())
293             result.append(dumpFramesAsText(child, recursive));
294     }
295
296     return result;
297 }
298
299 string dumpFramesAsPrintedText(WebFrame* frame, bool recursive)
300 {
301     string result;
302
303     // Cannot do printed format for anything other than HTML
304     if (!frame->document().isHTMLDocument())
305         return string();
306
307     // Add header for all but the main frame. Skip empty frames.
308     if (frame->parent() && !frame->document().documentElement().isNull()) {
309         result.append("\n--------\nFrame: '");
310         result.append(frame->uniqueName().utf8().data());
311         result.append("'\n--------\n");
312     }
313
314     result.append(frame->renderTreeAsText(WebFrame::RenderAsTextPrinting).utf8());
315     result.append("\n");
316
317     if (recursive) {
318         for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling())
319             result.append(dumpFramesAsPrintedText(child, recursive));
320     }
321
322     return result;
323 }
324
325 string dumpFrameScrollPosition(WebFrame* frame, bool recursive)
326 {
327     string result;
328     WebSize offset = frame->scrollOffset();
329     if (offset.width > 0 || offset.height > 0) {
330         if (frame->parent())
331             result = string("frame '") + frame->uniqueName().utf8().data() + "' ";
332         char data[100];
333         snprintf(data, sizeof(data), "scrolled to %d,%d\n", offset.width, offset.height);
334         result += data;
335     }
336
337     if (!recursive)
338         return result;
339     for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling())
340         result += dumpFrameScrollPosition(child, recursive);
341     return result;
342 }
343
344 struct ToLower {
345     char16 operator()(char16 c) { return tolower(c); }
346 };
347
348 // Returns True if item1 < item2.
349 bool HistoryItemCompareLess(const WebHistoryItem& item1, const WebHistoryItem& item2)
350 {
351     string16 target1 = item1.target();
352     string16 target2 = item2.target();
353     std::transform(target1.begin(), target1.end(), target1.begin(), ToLower());
354     std::transform(target2.begin(), target2.end(), target2.begin(), ToLower());
355     return target1 < target2;
356 }
357
358 string dumpHistoryItem(const WebHistoryItem& item, int indent, bool isCurrent)
359 {
360     string result;
361
362     if (isCurrent) {
363         result.append("curr->");
364         result.append(indent - 6, ' '); // 6 == "curr->".length()
365     } else
366         result.append(indent, ' ');
367
368     string url = normalizeLayoutTestURL(item.urlString().utf8());
369     result.append(url);
370     if (!item.target().isEmpty()) {
371         result.append(" (in frame \"");
372         result.append(item.target().utf8());
373         result.append("\")");
374     }
375     if (item.isTargetItem())
376         result.append("  **nav target**");
377     result.append("\n");
378
379     const WebVector<WebHistoryItem>& children = item.children();
380     if (!children.isEmpty()) {
381         // Must sort to eliminate arbitrary result ordering which defeats
382         // reproducible testing.
383         // FIXME: WebVector should probably just be a std::vector!!
384         std::vector<WebHistoryItem> sortedChildren;
385         for (size_t i = 0; i < children.size(); ++i)
386             sortedChildren.push_back(children[i]);
387         std::sort(sortedChildren.begin(), sortedChildren.end(), HistoryItemCompareLess);
388         for (size_t i = 0; i < sortedChildren.size(); ++i)
389             result += dumpHistoryItem(sortedChildren[i], indent + 4, false);
390     }
391
392     return result;
393 }
394
395 void dumpBackForwardList(const WebVector<WebHistoryItem>& history, size_t currentEntryIndex, string& result)
396 {
397     result.append("\n============== Back Forward List ==============\n");
398     for (size_t index = 0; index < history.size(); ++index)
399         result.append(dumpHistoryItem(history[index], 8, index == currentEntryIndex));
400     result.append("===============================================\n");
401 }
402
403 string dumpAllBackForwardLists(WebTestDelegate* delegate, unsigned windowCount)
404 {
405     string result;
406     for (unsigned i = 0; i < windowCount; ++i) {
407         size_t currentEntryIndex = 0;
408         WebVector<WebHistoryItem> history;
409         delegate->captureHistoryForWindow(i, &history, &currentEntryIndex);
410         dumpBackForwardList(history, currentEntryIndex, result);
411     }
412     return result;
413 }
414
415 }
416
417 WebTestProxyBase::WebTestProxyBase()
418     : m_testInterfaces(0)
419     , m_delegate(0)
420     , m_spellcheck(new SpellCheckClient)
421 {
422     reset();
423 }
424
425 WebTestProxyBase::~WebTestProxyBase()
426 {
427     m_testInterfaces->windowClosed(this);
428 }
429
430 void WebTestProxyBase::setInterfaces(WebTestInterfaces* interfaces)
431 {
432     m_testInterfaces = interfaces->testInterfaces();
433     m_testInterfaces->windowOpened(this);
434 }
435
436 void WebTestProxyBase::setDelegate(WebTestDelegate* delegate)
437 {
438     m_delegate = delegate;
439     m_spellcheck->setDelegate(delegate);
440 #if ENABLE_INPUT_SPEECH
441     if (m_speechInputController.get())
442         m_speechInputController->setDelegate(delegate);
443 #endif
444     if (m_speechRecognizer.get())
445         m_speechRecognizer->setDelegate(delegate);
446 }
447
448 void WebTestProxyBase::reset()
449 {
450     m_paintRect = WebRect();
451     m_canvas.reset();
452     m_isPainting = false;
453     m_resourceIdentifierMap.clear();
454     m_logConsoleOutput = true;
455     if (m_geolocationClient.get())
456         m_geolocationClient->resetMock();
457 #if ENABLE_INPUT_SPEECH
458     if (m_speechInputController.get())
459         m_speechInputController->clearResults();
460 #endif
461 }
462
463 WebSpellCheckClient* WebTestProxyBase::spellCheckClient() const
464 {
465     return m_spellcheck.get();
466 }
467
468 string WebTestProxyBase::captureTree(bool debugRenderTree)
469 {
470     WebScriptController::flushConsoleMessages();
471
472     bool shouldDumpAsText = m_testInterfaces->testRunner()->shouldDumpAsText();
473     bool shouldDumpAsPrinted = m_testInterfaces->testRunner()->isPrinting();
474     WebFrame* frame = m_testInterfaces->webView()->mainFrame();
475     string dataUtf8;
476     if (shouldDumpAsText) {
477         bool recursive = m_testInterfaces->testRunner()->shouldDumpChildFramesAsText();
478         dataUtf8 = shouldDumpAsPrinted ? dumpFramesAsPrintedText(frame, recursive) : dumpFramesAsText(frame, recursive);
479     } else {
480         bool recursive = m_testInterfaces->testRunner()->shouldDumpChildFrameScrollPositions();
481         WebFrame::RenderAsTextControls renderTextBehavior = WebFrame::RenderAsTextNormal;
482         if (shouldDumpAsPrinted)
483             renderTextBehavior |= WebFrame::RenderAsTextPrinting;
484         if (debugRenderTree)
485             renderTextBehavior |= WebFrame::RenderAsTextDebug;
486         dataUtf8 = frame->renderTreeAsText(renderTextBehavior).utf8();
487         dataUtf8 += dumpFrameScrollPosition(frame, recursive);
488     }
489
490     if (m_testInterfaces->testRunner()->shouldDumpBackForwardList())
491         dataUtf8 += dumpAllBackForwardLists(m_delegate, m_testInterfaces->windowList().size());
492
493     return dataUtf8;
494 }
495
496 SkCanvas* WebTestProxyBase::capturePixels()
497 {
498     m_testInterfaces->webView()->layout();
499     if (m_testInterfaces->testRunner()->testRepaint()) {
500         WebSize viewSize = m_testInterfaces->webView()->size();
501         int width = viewSize.width;
502         int height = viewSize.height;
503         if (m_testInterfaces->testRunner()->sweepHorizontally()) {
504             for (WebRect column(0, 0, 1, height); column.x < width; column.x++)
505                 paintRect(column);
506         } else {
507             for (WebRect line(0, 0, width, 1); line.y < height; line.y++)
508                 paintRect(line);
509         }
510     } else if (m_testInterfaces->testRunner()->isPrinting())
511         paintPagesWithBoundaries();
512     else
513         paintInvalidatedRegion();
514
515     // See if we need to draw the selection bounds rect. Selection bounds
516     // rect is the rect enclosing the (possibly transformed) selection.
517     // The rect should be drawn after everything is laid out and painted.
518     if (m_testInterfaces->testRunner()->shouldDumpSelectionRect()) {
519         // If there is a selection rect - draw a red 1px border enclosing rect
520         WebRect wr = m_testInterfaces->webView()->mainFrame()->selectionBoundsRect();
521         if (!wr.isEmpty()) {
522             // Render a red rectangle bounding selection rect
523             SkPaint paint;
524             paint.setColor(0xFFFF0000); // Fully opaque red
525             paint.setStyle(SkPaint::kStroke_Style);
526             paint.setFlags(SkPaint::kAntiAlias_Flag);
527             paint.setStrokeWidth(1.0f);
528             SkIRect rect; // Bounding rect
529             rect.set(wr.x, wr.y, wr.x + wr.width, wr.y + wr.height);
530             canvas()->drawIRect(rect, paint);
531         }
532     }
533
534     return canvas();
535 }
536
537 void WebTestProxyBase::setLogConsoleOutput(bool enabled)
538 {
539     m_logConsoleOutput = enabled;
540 }
541
542 void WebTestProxyBase::paintRect(const WebRect& rect)
543 {
544     WEBKIT_ASSERT(!m_isPainting);
545     WEBKIT_ASSERT(canvas());
546     m_isPainting = true;
547     float deviceScaleFactor = m_testInterfaces->webView()->deviceScaleFactor();
548     int scaledX = static_cast<int>(static_cast<float>(rect.x) * deviceScaleFactor);
549     int scaledY = static_cast<int>(static_cast<float>(rect.y) * deviceScaleFactor);
550     int scaledWidth = static_cast<int>(ceil(static_cast<float>(rect.width) * deviceScaleFactor));
551     int scaledHeight = static_cast<int>(ceil(static_cast<float>(rect.height) * deviceScaleFactor));
552     WebRect deviceRect(scaledX, scaledY, scaledWidth, scaledHeight);
553     m_testInterfaces->webView()->paint(canvas(), deviceRect);
554     m_isPainting = false;
555 }
556
557 void WebTestProxyBase::paintInvalidatedRegion()
558 {
559     m_testInterfaces->webView()->animate(0.0);
560     m_testInterfaces->webView()->layout();
561     WebSize widgetSize = m_testInterfaces->webView()->size();
562     WebRect clientRect(0, 0, widgetSize.width, widgetSize.height);
563
564     // Paint the canvas if necessary. Allow painting to generate extra rects
565     // for the first two calls. This is necessary because some WebCore rendering
566     // objects update their layout only when painted.
567     // Store the total area painted in total_paint. Then tell the gdk window
568     // to update that area after we're done painting it.
569     for (int i = 0; i < 3; ++i) {
570         // rect = intersect(m_paintRect , clientRect)
571         WebRect damageRect = m_paintRect;
572         int left = max(damageRect.x, clientRect.x);
573         int top = max(damageRect.y, clientRect.y);
574         int right = min(damageRect.x + damageRect.width, clientRect.x + clientRect.width);
575         int bottom = min(damageRect.y + damageRect.height, clientRect.y + clientRect.height);
576         WebRect rect;
577         if (left < right && top < bottom)
578             rect = WebRect(left, top, right - left, bottom - top);
579
580         m_paintRect = WebRect();
581         if (rect.isEmpty())
582             continue;
583         paintRect(rect);
584     }
585     WEBKIT_ASSERT(m_paintRect.isEmpty());
586 }
587
588 void WebTestProxyBase::paintPagesWithBoundaries()
589 {
590     WEBKIT_ASSERT(!m_isPainting);
591     WEBKIT_ASSERT(canvas());
592     m_isPainting = true;
593
594     WebSize pageSizeInPixels = m_testInterfaces->webView()->size();
595     WebFrame* webFrame = m_testInterfaces->webView()->mainFrame();
596
597     int pageCount = webFrame->printBegin(pageSizeInPixels);
598     int totalHeight = pageCount * (pageSizeInPixels.height + 1) - 1;
599
600     SkCanvas* testCanvas = skia::TryCreateBitmapCanvas(pageSizeInPixels.width, totalHeight, true);
601     if (testCanvas) {
602         discardBackingStore();
603         m_canvas.reset(testCanvas);
604     } else {
605         webFrame->printEnd();
606         return;
607     }
608
609     webFrame->printPagesWithBoundaries(canvas(), pageSizeInPixels);
610     webFrame->printEnd();
611
612     m_isPainting = false;
613 }
614
615 SkCanvas* WebTestProxyBase::canvas()
616 {
617     if (m_canvas.get())
618         return m_canvas.get();
619     WebSize widgetSize = m_testInterfaces->webView()->size();
620     float deviceScaleFactor = m_testInterfaces->webView()->deviceScaleFactor();
621     int scaledWidth = static_cast<int>(ceil(static_cast<float>(widgetSize.width) * deviceScaleFactor));
622     int scaledHeight = static_cast<int>(ceil(static_cast<float>(widgetSize.height) * deviceScaleFactor));
623     m_canvas.reset(skia::CreateBitmapCanvas(scaledWidth, scaledHeight, true));
624     return m_canvas.get();
625 }
626
627 // Paints the entire canvas a semi-transparent black (grayish). This is used
628 // by the layout tests in fast/repaint. The alpha value matches upstream.
629 void WebTestProxyBase::displayRepaintMask()
630 {
631     canvas()->drawARGB(167, 0, 0, 0);
632 }
633
634 void WebTestProxyBase::display()
635 {
636     const WebKit::WebSize& size = m_testInterfaces->webView()->size();
637     WebRect rect(0, 0, size.width, size.height);
638     m_paintRect = rect;
639     paintInvalidatedRegion();
640     displayRepaintMask();
641 }
642
643 void WebTestProxyBase::displayInvalidatedRegion()
644 {
645     paintInvalidatedRegion();
646     displayRepaintMask();
647 }
648
649 void WebTestProxyBase::discardBackingStore()
650 {
651     m_canvas.reset();
652 }
653
654 WebGeolocationClientMock* WebTestProxyBase::geolocationClientMock()
655 {
656     if (!m_geolocationClient.get())
657         m_geolocationClient.reset(WebGeolocationClientMock::create());
658     return m_geolocationClient.get();
659 }
660
661 WebDeviceOrientationClientMock* WebTestProxyBase::deviceOrientationClientMock()
662 {
663     if (!m_deviceOrientationClient.get())
664         m_deviceOrientationClient.reset(WebDeviceOrientationClientMock::create());
665     return m_deviceOrientationClient.get();
666 }
667
668 #if ENABLE_INPUT_SPEECH
669 MockWebSpeechInputController* WebTestProxyBase::speechInputControllerMock()
670 {
671     WEBKIT_ASSERT(m_speechInputController.get());
672     return m_speechInputController.get();
673 }
674 #endif
675
676 MockWebSpeechRecognizer* WebTestProxyBase::speechRecognizerMock()
677 {
678     if (!m_speechRecognizer.get()) {
679         m_speechRecognizer.reset(new MockWebSpeechRecognizer());
680         m_speechRecognizer->setDelegate(m_delegate);
681     }
682     return m_speechRecognizer.get();
683 }
684
685 void WebTestProxyBase::didInvalidateRect(const WebRect& rect)
686 {
687     // m_paintRect = m_paintRect U rect
688     if (rect.isEmpty())
689         return;
690     if (m_paintRect.isEmpty()) {
691         m_paintRect = rect;
692         return;
693     }
694     int left = min(m_paintRect.x, rect.x);
695     int top = min(m_paintRect.y, rect.y);
696     int right = max(m_paintRect.x + m_paintRect.width, rect.x + rect.width);
697     int bottom = max(m_paintRect.y + m_paintRect.height, rect.y + rect.height);
698     m_paintRect = WebRect(left, top, right - left, bottom - top);
699 }
700
701 void WebTestProxyBase::didScrollRect(int, int, const WebRect& clipRect)
702 {
703     didInvalidateRect(clipRect);
704 }
705
706 void WebTestProxyBase::scheduleComposite()
707 {
708     m_paintRect = WebRect(0, 0, INT_MAX, INT_MAX);
709 }
710
711 void WebTestProxyBase::scheduleAnimation()
712 {
713     scheduleComposite();
714 }
715
716 void WebTestProxyBase::show(WebNavigationPolicy)
717 {
718     scheduleComposite();
719 }
720
721 void WebTestProxyBase::setWindowRect(const WebRect& rect)
722 {
723     scheduleComposite();
724     discardBackingStore();
725 }
726
727 void WebTestProxyBase::didAutoResize(const WebSize&)
728 {
729     scheduleComposite();
730 }
731
732 void WebTestProxyBase::postAccessibilityNotification(const WebKit::WebAccessibilityObject& obj, WebKit::WebAccessibilityNotification notification)
733 {
734     if (notification == WebKit::WebAccessibilityNotificationFocusedUIElementChanged)
735         m_testInterfaces->accessibilityController()->setFocusedElement(obj);
736
737     const char* notificationName;
738     switch (notification) {
739     case WebKit::WebAccessibilityNotificationActiveDescendantChanged:
740         notificationName = "ActiveDescendantChanged";
741         break;
742     case WebKit::WebAccessibilityNotificationAutocorrectionOccured:
743         notificationName = "AutocorrectionOccured";
744         break;
745     case WebKit::WebAccessibilityNotificationCheckedStateChanged:
746         notificationName = "CheckedStateChanged";
747         break;
748     case WebKit::WebAccessibilityNotificationChildrenChanged:
749         notificationName = "ChildrenChanged";
750         break;
751     case WebKit::WebAccessibilityNotificationFocusedUIElementChanged:
752         notificationName = "FocusedUIElementChanged";
753         break;
754     case WebKit::WebAccessibilityNotificationLayoutComplete:
755         notificationName = "LayoutComplete";
756         break;
757     case WebKit::WebAccessibilityNotificationLoadComplete:
758         notificationName = "LoadComplete";
759         break;
760     case WebKit::WebAccessibilityNotificationSelectedChildrenChanged:
761         notificationName = "SelectedChildrenChanged";
762         break;
763     case WebKit::WebAccessibilityNotificationSelectedTextChanged:
764         notificationName = "SelectedTextChanged";
765         break;
766     case WebKit::WebAccessibilityNotificationValueChanged:
767         notificationName = "ValueChanged";
768         break;
769     case WebKit::WebAccessibilityNotificationScrolledToAnchor:
770         notificationName = "ScrolledToAnchor";
771         break;
772     case WebKit::WebAccessibilityNotificationLiveRegionChanged:
773         notificationName = "LiveRegionChanged";
774         break;
775     case WebKit::WebAccessibilityNotificationMenuListItemSelected:
776         notificationName = "MenuListItemSelected";
777         break;
778     case WebKit::WebAccessibilityNotificationMenuListValueChanged:
779         notificationName = "MenuListValueChanged";
780         break;
781     case WebKit::WebAccessibilityNotificationRowCountChanged:
782         notificationName = "RowCountChanged";
783         break;
784     case WebKit::WebAccessibilityNotificationRowCollapsed:
785         notificationName = "RowCollapsed";
786         break;
787     case WebKit::WebAccessibilityNotificationRowExpanded:
788         notificationName = "RowExpanded";
789         break;
790     case WebKit::WebAccessibilityNotificationInvalidStatusChanged:
791         notificationName = "InvalidStatusChanged";
792         break;
793     case WebKit::WebAccessibilityNotificationTextChanged:
794         notificationName = "TextChanged";
795         break;
796     case WebKit::WebAccessibilityNotificationAriaAttributeChanged:
797         notificationName = "AriaAttributeChanged";
798         break;
799     default:
800         notificationName = "UnknownNotification";
801         break;
802     }
803
804     m_testInterfaces->accessibilityController()->notificationReceived(obj, notificationName);
805
806     if (m_testInterfaces->accessibilityController()->shouldLogAccessibilityEvents()) {
807         string message("AccessibilityNotification - ");
808         message += notificationName;
809
810         WebKit::WebNode node = obj.node();
811         if (!node.isNull() && node.isElementNode()) {
812             WebKit::WebElement element = node.to<WebKit::WebElement>();
813             if (element.hasAttribute("id")) {
814                 message += " - id:";
815                 message += element.getAttribute("id").utf8().data();
816             }
817         }
818
819         m_delegate->printMessage(message + "\n");
820     }
821 }
822
823 void WebTestProxyBase::startDragging(WebFrame*, const WebDragData& data, WebDragOperationsMask mask, const WebImage&, const WebPoint&)
824 {
825     // When running a test, we need to fake a drag drop operation otherwise
826     // Windows waits for real mouse events to know when the drag is over.
827     m_testInterfaces->eventSender()->doDragDrop(data, mask);
828 }
829
830 // The output from these methods in layout test mode should match that
831 // expected by the layout tests. See EditingDelegate.m in DumpRenderTree.
832
833 bool WebTestProxyBase::shouldBeginEditing(const WebRange& range)
834 {
835     if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
836         m_delegate->printMessage("EDITING DELEGATE: shouldBeginEditingInDOMRange:");
837         printRangeDescription(m_delegate, range);
838         m_delegate->printMessage("\n");
839     }
840     return true;
841 }
842
843 bool WebTestProxyBase::shouldEndEditing(const WebRange& range)
844 {
845     if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
846         m_delegate->printMessage("EDITING DELEGATE: shouldEndEditingInDOMRange:");
847         printRangeDescription(m_delegate, range);
848         m_delegate->printMessage("\n");
849     }
850     return true;
851 }
852
853 bool WebTestProxyBase::shouldInsertNode(const WebNode& node, const WebRange& range, WebEditingAction action)
854 {
855     if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
856         m_delegate->printMessage("EDITING DELEGATE: shouldInsertNode:");
857         printNodeDescription(m_delegate, node, 0);
858         m_delegate->printMessage(" replacingDOMRange:");
859         printRangeDescription(m_delegate, range);
860         m_delegate->printMessage(string(" givenAction:") + editingActionDescription(action) + "\n");
861     }
862     return true;
863 }
864
865 bool WebTestProxyBase::shouldInsertText(const WebString& text, const WebRange& range, WebEditingAction action)
866 {
867     if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
868         m_delegate->printMessage(string("EDITING DELEGATE: shouldInsertText:") + text.utf8().data() + " replacingDOMRange:");
869         printRangeDescription(m_delegate, range);
870         m_delegate->printMessage(string(" givenAction:") + editingActionDescription(action) + "\n");
871     }
872     return true;
873 }
874
875 bool WebTestProxyBase::shouldChangeSelectedRange(
876     const WebRange& fromRange, const WebRange& toRange, WebTextAffinity affinity, bool stillSelecting)
877 {
878     if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
879         m_delegate->printMessage("EDITING DELEGATE: shouldChangeSelectedDOMRange:");
880         printRangeDescription(m_delegate, fromRange);
881         m_delegate->printMessage(" toDOMRange:");
882         printRangeDescription(m_delegate, toRange);
883         m_delegate->printMessage(string(" affinity:") + textAffinityDescription(affinity) + " stillSelecting:" + (stillSelecting ? "TRUE" : "FALSE") + "\n");
884     }
885     return true;
886 }
887
888 bool WebTestProxyBase::shouldDeleteRange(const WebRange& range)
889 {
890     if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
891         m_delegate->printMessage("EDITING DELEGATE: shouldDeleteDOMRange:");
892         printRangeDescription(m_delegate, range);
893         m_delegate->printMessage("\n");
894     }
895     return true;
896 }
897
898 bool WebTestProxyBase::shouldApplyStyle(const WebString& style, const WebRange& range)
899 {
900     if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
901         m_delegate->printMessage(string("EDITING DELEGATE: shouldApplyStyle:") + style.utf8().data() + " toElementsInDOMRange:");
902         printRangeDescription(m_delegate, range);
903         m_delegate->printMessage("\n");
904     }
905     return true;
906 }
907
908 void WebTestProxyBase::didBeginEditing()
909 {
910     if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks())
911         m_delegate->printMessage("EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification\n");
912 }
913
914 void WebTestProxyBase::didChangeSelection(bool isEmptySelection)
915 {
916     if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks())
917         m_delegate->printMessage("EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification\n");
918 }
919
920 void WebTestProxyBase::didChangeContents()
921 {
922     if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks())
923         m_delegate->printMessage("EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification\n");
924 }
925
926 void WebTestProxyBase::didEndEditing()
927 {
928     if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks())
929         m_delegate->printMessage("EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification\n");
930 }
931
932 bool WebTestProxyBase::createView(WebFrame*, const WebURLRequest& request, const WebWindowFeatures&, const WebString&, WebNavigationPolicy)
933 {
934     if (!m_testInterfaces->testRunner()->canOpenWindows())
935         return false;
936     if (m_testInterfaces->testRunner()->shouldDumpCreateView())
937         m_delegate->printMessage(string("createView(") + URLDescription(request.url()) + ")\n");
938     return true;
939 }
940
941 WebPlugin* WebTestProxyBase::createPlugin(WebFrame* frame, const WebPluginParams& params)
942 {
943     if (params.mimeType == TestPlugin::mimeType())
944         return TestPlugin::create(frame, params, m_delegate);
945     return 0;
946 }
947
948 void WebTestProxyBase::setStatusText(const WebString& text)
949 {
950     if (!m_testInterfaces->testRunner()->shouldDumpStatusCallbacks())
951         return;
952     m_delegate->printMessage(string("UI DELEGATE STATUS CALLBACK: setStatusText:") + text.utf8().data() + "\n");
953 }
954
955 void WebTestProxyBase::didStopLoading()
956 {
957     if (m_testInterfaces->testRunner()->shouldDumpProgressFinishedCallback())
958         m_delegate->printMessage("postProgressFinishedNotification\n");
959 }
960
961 bool WebTestProxyBase::isSmartInsertDeleteEnabled()
962 {
963     return m_testInterfaces->testRunner()->isSmartInsertDeleteEnabled();
964 }
965
966 bool WebTestProxyBase::isSelectTrailingWhitespaceEnabled()
967 {
968     return m_testInterfaces->testRunner()->isSelectTrailingWhitespaceEnabled();
969 }
970
971 void WebTestProxyBase::showContextMenu(WebFrame*, const WebContextMenuData& contextMenuData)
972 {
973     m_testInterfaces->eventSender()->setContextMenuData(contextMenuData);
974 }
975
976 WebUserMediaClient* WebTestProxyBase::userMediaClient()
977 {
978 #if ENABLE_WEBRTC
979     if (!m_userMediaClient.get())
980         m_userMediaClient.reset(new WebUserMediaClientMock(m_delegate));
981     return m_userMediaClient.get();
982 #else
983     return 0;
984 #endif // ENABLE_WEBRTC
985 }
986
987 // Simulate a print by going into print mode and then exit straight away.
988 void WebTestProxyBase::printPage(WebFrame* frame)
989 {
990     WebSize pageSizeInPixels = m_testInterfaces->webView()->size();
991     WebPrintParams printParams(pageSizeInPixels);
992     frame->printBegin(printParams);
993     frame->printEnd();
994 }
995
996 WebNotificationPresenter* WebTestProxyBase::notificationPresenter()
997 {
998 #if ENABLE_NOTIFICATIONS
999     return m_testInterfaces->testRunner()->notificationPresenter();
1000 #else
1001     return 0;
1002 #endif
1003 }
1004
1005 WebGeolocationClient* WebTestProxyBase::geolocationClient()
1006 {
1007     return geolocationClientMock();
1008 }
1009
1010 WebSpeechInputController* WebTestProxyBase::speechInputController(WebSpeechInputListener* listener)
1011 {
1012 #if ENABLE_INPUT_SPEECH
1013     if (!m_speechInputController.get()) {
1014         m_speechInputController.reset(new MockWebSpeechInputController(listener));
1015         m_speechInputController->setDelegate(m_delegate);
1016     }
1017     return m_speechInputController.get();
1018 #else
1019     WEBKIT_ASSERT(listener);
1020     return 0;
1021 #endif
1022 }
1023
1024 WebSpeechRecognizer* WebTestProxyBase::speechRecognizer()
1025 {
1026     return speechRecognizerMock();
1027 }
1028
1029 WebDeviceOrientationClient* WebTestProxyBase::deviceOrientationClient()
1030 {
1031     return deviceOrientationClientMock();
1032 }
1033
1034 bool WebTestProxyBase::requestPointerLock()
1035 {
1036     return m_testInterfaces->testRunner()->requestPointerLock();
1037 }
1038
1039 void WebTestProxyBase::requestPointerUnlock()
1040 {
1041     m_testInterfaces->testRunner()->requestPointerUnlock();
1042 }
1043
1044 bool WebTestProxyBase::isPointerLocked()
1045 {
1046     return m_testInterfaces->testRunner()->isPointerLocked();
1047 }
1048
1049 void WebTestProxyBase::willPerformClientRedirect(WebFrame* frame, const WebURL&, const WebURL& to, double, double)
1050 {
1051     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
1052         printFrameDescription(m_delegate, frame);
1053         m_delegate->printMessage(string(" - willPerformClientRedirectToURL: ") + to.spec().data() + " \n");
1054     }
1055
1056     if (m_testInterfaces->testRunner()->shouldDumpUserGestureInFrameLoadCallbacks())
1057         printFrameUserGestureStatus(m_delegate, frame, " - in willPerformClientRedirect\n");
1058 }
1059
1060 void WebTestProxyBase::didCancelClientRedirect(WebFrame* frame)
1061 {
1062     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
1063         printFrameDescription(m_delegate, frame);
1064         m_delegate->printMessage(" - didCancelClientRedirectForFrame\n");
1065     }
1066 }
1067
1068 void WebTestProxyBase::didStartProvisionalLoad(WebFrame* frame)
1069 {
1070     if (!m_testInterfaces->testRunner()->topLoadingFrame())
1071         m_testInterfaces->testRunner()->setTopLoadingFrame(frame, false);
1072
1073     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
1074         printFrameDescription(m_delegate, frame);
1075         m_delegate->printMessage(" - didStartProvisionalLoadForFrame\n");
1076     }
1077
1078     if (m_testInterfaces->testRunner()->shouldDumpUserGestureInFrameLoadCallbacks())
1079         printFrameUserGestureStatus(m_delegate, frame, " - in didStartProvisionalLoadForFrame\n");
1080
1081     if (m_testInterfaces->testRunner()->stopProvisionalFrameLoads()) {
1082         printFrameDescription(m_delegate, frame);
1083         m_delegate->printMessage(" - stopping load in didStartProvisionalLoadForFrame callback\n");
1084         frame->stopLoading();
1085     }
1086 }
1087
1088 void WebTestProxyBase::didReceiveServerRedirectForProvisionalLoad(WebFrame* frame)
1089 {
1090     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
1091         printFrameDescription(m_delegate, frame);
1092         m_delegate->printMessage(" - didReceiveServerRedirectForProvisionalLoadForFrame\n");
1093     }
1094 }
1095
1096 void WebTestProxyBase::didFailProvisionalLoad(WebFrame* frame, const WebURLError&)
1097 {
1098     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
1099         printFrameDescription(m_delegate, frame);
1100         m_delegate->printMessage(" - didFailProvisionalLoadWithError\n");
1101     }
1102     locationChangeDone(frame);
1103 }
1104
1105 void WebTestProxyBase::didCommitProvisionalLoad(WebFrame* frame, bool)
1106 {
1107     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
1108         printFrameDescription(m_delegate, frame);
1109         m_delegate->printMessage(" - didCommitLoadForFrame\n");
1110     }
1111 }
1112
1113 void WebTestProxyBase::didReceiveTitle(WebFrame* frame, const WebString& title, WebTextDirection direction)
1114 {
1115     WebCString title8 = title.utf8();
1116
1117     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
1118         printFrameDescription(m_delegate, frame);
1119         m_delegate->printMessage(string(" - didReceiveTitle: ") + title8.data() + "\n");
1120     }
1121
1122     if (m_testInterfaces->testRunner()->shouldDumpTitleChanges())
1123         m_delegate->printMessage(string("TITLE CHANGED: '") + title8.data() + "'\n");
1124
1125     m_testInterfaces->testRunner()->setTitleTextDirection(direction);
1126 }
1127
1128 void WebTestProxyBase::didFinishDocumentLoad(WebFrame* frame)
1129 {
1130     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
1131         printFrameDescription(m_delegate, frame);
1132         m_delegate->printMessage(" - didFinishDocumentLoadForFrame\n");
1133     } else {
1134         unsigned pendingUnloadEvents = frame->unloadListenerCount();
1135         if (pendingUnloadEvents) {
1136             printFrameDescription(m_delegate, frame);
1137             char buffer[100];
1138             snprintf(buffer, sizeof(buffer), " - has %u onunload handler(s)\n", pendingUnloadEvents);
1139             m_delegate->printMessage(buffer);
1140         }
1141     }
1142 }
1143
1144 void WebTestProxyBase::didHandleOnloadEvents(WebFrame* frame)
1145 {
1146     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
1147         printFrameDescription(m_delegate, frame);
1148         m_delegate->printMessage(" - didHandleOnloadEventsForFrame\n");
1149     }
1150 }
1151
1152 void WebTestProxyBase::didFailLoad(WebFrame* frame, const WebURLError&)
1153 {
1154     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
1155         printFrameDescription(m_delegate, frame);
1156         m_delegate->printMessage(" - didFailLoadWithError\n");
1157     }
1158     locationChangeDone(frame);
1159 }
1160
1161 void WebTestProxyBase::didFinishLoad(WebFrame* frame)
1162 {
1163     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
1164         printFrameDescription(m_delegate, frame);
1165         m_delegate->printMessage(" - didFinishLoadForFrame\n");
1166     }
1167     locationChangeDone(frame);
1168 }
1169
1170 void WebTestProxyBase::didChangeLocationWithinPage(WebFrame* frame)
1171 {
1172     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
1173         printFrameDescription(m_delegate, frame);
1174         m_delegate->printMessage(" - didChangeLocationWithinPageForFrame\n");
1175     }
1176 }
1177
1178 void WebTestProxyBase::didDisplayInsecureContent(WebFrame*)
1179 {
1180     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks())
1181         m_delegate->printMessage("didDisplayInsecureContent\n");
1182 }
1183
1184 void WebTestProxyBase::didRunInsecureContent(WebFrame*, const WebSecurityOrigin&, const WebURL&)
1185 {
1186     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks())
1187         m_delegate->printMessage("didRunInsecureContent\n");
1188 }
1189
1190 void WebTestProxyBase::didDetectXSS(WebFrame*, const WebURL&, bool)
1191 {
1192     if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks())
1193         m_delegate->printMessage("didDetectXSS\n");
1194 }
1195
1196 void WebTestProxyBase::assignIdentifierToRequest(WebFrame*, unsigned identifier, const WebKit::WebURLRequest& request)
1197 {
1198     if (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks()) {
1199         WEBKIT_ASSERT(m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end());
1200         m_resourceIdentifierMap[identifier] = descriptionSuitableForTestResult(request.url().spec());
1201     }
1202 }
1203
1204 void WebTestProxyBase::willRequestResource(WebFrame* frame, const WebKit::WebCachedURLRequest& request)
1205 {
1206     if (m_testInterfaces->testRunner()->shouldDumpResourceRequestCallbacks()) {
1207         printFrameDescription(m_delegate, frame);
1208         WebElement element = request.initiatorElement();
1209         if (!element.isNull()) {
1210             m_delegate->printMessage(" - element with ");
1211             if (element.hasAttribute("id"))
1212                 m_delegate->printMessage(string("id '") + element.getAttribute("id").utf8().data() + "'");
1213             else
1214                 m_delegate->printMessage("no id");
1215         } else
1216             m_delegate->printMessage(string(" - ") + request.initiatorName().utf8().data());
1217         m_delegate->printMessage(string(" requested '") + URLDescription(request.urlRequest().url()).c_str() + "'\n");
1218     }
1219 }
1220
1221 bool WebTestProxyBase::canHandleRequest(WebFrame*, const WebURLRequest& request)
1222 {
1223     GURL url = request.url();
1224     // Just reject the scheme used in
1225     // LayoutTests/http/tests/misc/redirect-to-external-url.html
1226     return !url.SchemeIs("spaceballs");
1227 }
1228
1229 WebURLError WebTestProxyBase::cannotHandleRequestError(WebFrame*, const WebURLRequest& request)
1230 {
1231     WebURLError error;
1232     // A WebKit layout test expects the following values.
1233     // unableToImplementPolicyWithError() below prints them.
1234     error.domain = WebString::fromUTF8("WebKitErrorDomain");
1235     error.reason = 101;
1236     error.unreachableURL = request.url();
1237     return error;
1238 }
1239
1240 void WebTestProxyBase::didCreateDataSource(WebFrame*, WebDataSource* ds)
1241 {
1242     if (!m_testInterfaces->testRunner()->deferMainResourceDataLoad())
1243         ds->setDeferMainResourceDataLoad(false);
1244 }
1245
1246 void WebTestProxyBase::willSendRequest(WebFrame*, unsigned identifier, WebKit::WebURLRequest& request, const WebKit::WebURLResponse& redirectResponse)
1247 {
1248     // Need to use GURL for host() and SchemeIs()
1249     GURL url = request.url();
1250     string requestURL = url.possibly_invalid_spec();
1251
1252     GURL mainDocumentURL = request.firstPartyForCookies();
1253
1254     if (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks()) {
1255         if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end())
1256             m_delegate->printMessage("<unknown>");
1257         else
1258             m_delegate->printMessage(m_resourceIdentifierMap[identifier]);
1259         m_delegate->printMessage(" - willSendRequest <NSURLRequest URL ");
1260         m_delegate->printMessage(descriptionSuitableForTestResult(requestURL).c_str());
1261         m_delegate->printMessage(", main document URL ");
1262         m_delegate->printMessage(URLDescription(mainDocumentURL).c_str());
1263         m_delegate->printMessage(", http method ");
1264         m_delegate->printMessage(request.httpMethod().utf8().data());
1265         m_delegate->printMessage("> redirectResponse ");
1266         printResponseDescription(m_delegate, redirectResponse);
1267         m_delegate->printMessage("\n");
1268     }
1269
1270     if (!redirectResponse.isNull() && m_testInterfaces->testRunner()->shouldBlockRedirects()) {
1271         m_delegate->printMessage("Returning null for this redirect\n");
1272         blockRequest(request);
1273         return;
1274     }
1275
1276     if (m_testInterfaces->testRunner()->willSendRequestShouldReturnNull()) {
1277         blockRequest(request);
1278         return;
1279     }
1280
1281     if (m_testInterfaces->testRunner()->httpHeadersToClear()) {
1282         const set<string> *clearHeaders = m_testInterfaces->testRunner()->httpHeadersToClear();
1283         for (set<string>::const_iterator header = clearHeaders->begin(); header != clearHeaders->end(); ++header)
1284             request.clearHTTPHeaderField(WebString::fromUTF8(*header));
1285     }
1286
1287     string host = url.host();
1288     if (!host.empty() && (url.SchemeIs("http") || url.SchemeIs("https"))) {
1289         if (!isLocalhost(host) && !hostIsUsedBySomeTestsToGenerateError(host)
1290             && ((!mainDocumentURL.SchemeIs("http") && !mainDocumentURL.SchemeIs("https")) || isLocalhost(mainDocumentURL.host()))
1291             && !m_delegate->allowExternalPages()) {
1292             m_delegate->printMessage(string("Blocked access to external URL ") + requestURL + "\n");
1293             blockRequest(request);
1294             return;
1295         }
1296     }
1297
1298     // Set the new substituted URL.
1299     request.setURL(m_delegate->rewriteLayoutTestsURL(request.url().spec()));
1300 }
1301
1302 void WebTestProxyBase::didReceiveResponse(WebFrame*, unsigned identifier, const WebKit::WebURLResponse& response)
1303 {
1304     if (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks()) {
1305         if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end())
1306             m_delegate->printMessage("<unknown>");
1307         else
1308             m_delegate->printMessage(m_resourceIdentifierMap[identifier]);
1309         m_delegate->printMessage(" - didReceiveResponse ");
1310         printResponseDescription(m_delegate, response);
1311         m_delegate->printMessage("\n");
1312     }
1313     if (m_testInterfaces->testRunner()->shouldDumpResourceResponseMIMETypes()) {
1314         GURL url = response.url();
1315         WebString mimeType = response.mimeType();
1316         m_delegate->printMessage(url.ExtractFileName());
1317         m_delegate->printMessage(" has MIME type ");
1318         // Simulate NSURLResponse's mapping of empty/unknown MIME types to application/octet-stream
1319         m_delegate->printMessage(mimeType.isEmpty() ? "application/octet-stream" : mimeType.utf8().data());
1320         m_delegate->printMessage("\n");
1321     }
1322 }
1323
1324 void WebTestProxyBase::didFinishResourceLoad(WebFrame*, unsigned identifier)
1325 {
1326     if (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks()) {
1327         if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end())
1328             m_delegate->printMessage("<unknown>");
1329         else
1330             m_delegate->printMessage(m_resourceIdentifierMap[identifier]);
1331         m_delegate->printMessage(" - didFinishLoading\n");
1332     }
1333     m_resourceIdentifierMap.erase(identifier);
1334 }
1335
1336 void WebTestProxyBase::didFailResourceLoad(WebFrame*, unsigned identifier, const WebKit::WebURLError& error)
1337 {
1338     if (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks()) {
1339         if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end())
1340             m_delegate->printMessage("<unknown>");
1341         else
1342             m_delegate->printMessage(m_resourceIdentifierMap[identifier]);
1343         m_delegate->printMessage(" - didFailLoadingWithError: ");
1344         m_delegate->printMessage(m_delegate->makeURLErrorDescription(error));
1345         m_delegate->printMessage("\n");
1346     }
1347     m_resourceIdentifierMap.erase(identifier);
1348 }
1349
1350 void WebTestProxyBase::unableToImplementPolicyWithError(WebKit::WebFrame* frame, const WebKit::WebURLError& error)
1351 {
1352     char errorBuffer[40];
1353     snprintf(errorBuffer, sizeof(errorBuffer), "%d", error.reason);
1354     m_delegate->printMessage(string("Policy delegate: unable to implement policy with error domain '") + error.domain.utf8().data() +
1355         "', error code " +  errorBuffer +
1356         ", in frame '" + frame->uniqueName().utf8().data() + "'\n");
1357 }
1358
1359 void WebTestProxyBase::didAddMessageToConsole(const WebConsoleMessage& message, const WebString& sourceName, unsigned sourceLine)
1360 {
1361     // This matches win DumpRenderTree's UIDelegate.cpp.
1362     if (!m_logConsoleOutput)
1363         return;
1364     m_delegate->printMessage(string("CONSOLE MESSAGE: "));
1365     if (sourceLine) {
1366         char buffer[40];
1367         snprintf(buffer, sizeof(buffer), "line %d: ", sourceLine);
1368         m_delegate->printMessage(buffer);
1369     }
1370     if (!message.text.isEmpty()) {
1371         string newMessage;
1372         newMessage = message.text.utf8();
1373         size_t fileProtocol = newMessage.find("file://");
1374         if (fileProtocol != string::npos) {
1375             newMessage = newMessage.substr(0, fileProtocol)
1376                 + urlSuitableForTestResult(newMessage.substr(fileProtocol));
1377         }
1378         m_delegate->printMessage(newMessage);
1379     }
1380     m_delegate->printMessage(string("\n"));
1381 }
1382
1383 void WebTestProxyBase::runModalAlertDialog(WebFrame*, const WebString& message)
1384 {
1385     m_delegate->printMessage(string("ALERT: ") + message.utf8().data() + "\n");
1386 }
1387
1388 bool WebTestProxyBase::runModalConfirmDialog(WebFrame*, const WebString& message)
1389 {
1390     m_delegate->printMessage(string("CONFIRM: ") + message.utf8().data() + "\n");
1391     return true;
1392 }
1393
1394 bool WebTestProxyBase::runModalPromptDialog(WebFrame* frame, const WebString& message, const WebString& defaultValue, WebString*)
1395 {
1396     m_delegate->printMessage(string("PROMPT: ") + message.utf8().data() + ", default text: " + defaultValue.utf8().data() + "\n");
1397     return true;
1398 }
1399
1400 bool WebTestProxyBase::runModalBeforeUnloadDialog(WebFrame*, const WebString& message)
1401 {
1402     m_delegate->printMessage(string("CONFIRM NAVIGATION: ") + message.utf8().data() + "\n");
1403     return !m_testInterfaces->testRunner()->shouldStayOnPageAfterHandlingBeforeUnload();
1404 }
1405
1406 void WebTestProxyBase::locationChangeDone(WebFrame* frame)
1407 {
1408     if (frame != m_testInterfaces->testRunner()->topLoadingFrame())
1409         return;
1410     m_testInterfaces->testRunner()->setTopLoadingFrame(frame, true);
1411 }
1412
1413 WebNavigationPolicy WebTestProxyBase::decidePolicyForNavigation(WebFrame*, const WebURLRequest& request, WebNavigationType type, const WebNode& originatingNode, WebNavigationPolicy defaultPolicy, bool isRedirect)
1414 {
1415     WebNavigationPolicy result;
1416     if (!m_testInterfaces->testRunner()->policyDelegateEnabled())
1417         return defaultPolicy;
1418
1419     m_delegate->printMessage(string("Policy delegate: attempt to load ") + URLDescription(request.url()) + " with navigation type '" + webNavigationTypeToString(type) + "'");
1420     if (!originatingNode.isNull()) {
1421         m_delegate->printMessage(" originating from ");
1422         printNodeDescription(m_delegate, originatingNode, 0);
1423     }
1424     m_delegate->printMessage("\n");
1425     if (m_testInterfaces->testRunner()->policyDelegateIsPermissive())
1426         result = WebKit::WebNavigationPolicyCurrentTab;
1427     else
1428         result = WebKit::WebNavigationPolicyIgnore;
1429
1430     if (m_testInterfaces->testRunner()->policyDelegateShouldNotifyDone())
1431         m_testInterfaces->testRunner()->policyDelegateDone();
1432     return result;
1433 }
1434
1435 bool WebTestProxyBase::willCheckAndDispatchMessageEvent(WebFrame*, WebFrame*, WebSecurityOrigin, WebDOMMessageEvent)
1436 {
1437     if (m_testInterfaces->testRunner()->shouldInterceptPostMessage()) {
1438         m_delegate->printMessage("intercepted postMessage\n");
1439         return true;
1440     }
1441
1442     return false;
1443 }
1444
1445 }