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