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