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