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, ¤tEntryIndex);
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