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)(); 85 HostMethodTask(WebTestProxyBase* object, CallbackMethodType callback) 86 : WebMethodTask<WebTestProxyBase>(object) 87 , m_callback(callback) 88 { } 89 90 virtual void runIfValid() { (m_object->*m_callback)(); } 91 92 private: 93 CallbackMethodType m_callback; 94 }; 95 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 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"). 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 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 150 string URLDescription(const GURL& url) 151 { 152 if (url.SchemeIs("file")) 153 return url.ExtractFileName(); 154 return url.possibly_invalid_spec(); 155 } 156 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 176 void blockRequest(WebURLRequest& request) 177 { 178 request.setURL(GURL("255.255.255.255")); 179 } 180 181 bool isLocalhost(const string& host) 182 { 183 return host == "127.0.0.1" || host == "localhost"; 184 } 185 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"). 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. 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 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 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 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 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 { 321 char16 operator()(char16 c) { return tolower(c); } 322 }; 323 324 // Returns True if item1 < 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 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 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 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 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 403 WebTestProxyBase::~WebTestProxyBase() 404 { 405 m_testInterfaces->windowClosed(this); 406 } 407 408 void WebTestProxyBase::setInterfaces(WebTestInterfaces* interfaces) 409 { 410 m_testInterfaces = interfaces->testInterfaces(); 411 m_testInterfaces->windowOpened(this); 412 } 413 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 427 void WebTestProxyBase::setWidget(WebWidget* widget) 428 { 429 m_webWidget = widget; 430 } 431 432 WebWidget* WebTestProxyBase::webWidget() 433 { 434 return m_webWidget; 435 } 436 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 444 void WebTestProxyBase::didForceResize() 445 { 446 invalidateAll(); 447 discardBackingStore(); 448 } 449 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 468 WebSpellCheckClient* WebTestProxyBase::spellCheckClient() const 469 { 470 return m_spellcheck.get(); 471 } 472 473 WebValidationMessageClient* WebTestProxyBase::validationMessageClient() 474 { 475 return m_validationMessageClient.get(); 476 } 477 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 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 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 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 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 570 void WebTestProxyBase::setLogConsoleOutput(bool enabled) 571 { 572 m_logConsoleOutput = enabled; 573 } 574 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 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 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 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. 662 void WebTestProxyBase::displayRepaintMask() 663 { 664 canvas()->drawARGB(167, 0, 0, 0); 665 } 666 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 676 void WebTestProxyBase::displayInvalidatedRegion() 677 { 678 paintInvalidatedRegion(); 679 displayRepaintMask(); 680 } 681 682 void WebTestProxyBase::discardBackingStore() 683 { 684 m_canvas.reset(); 685 } 686 687 WebGeolocationClientMock* WebTestProxyBase::geolocationClientMock() 688 { 689 if (!m_geolocationClient.get()) 690 m_geolocationClient.reset(WebGeolocationClientMock::create()); 691 return m_geolocationClient.get(); 692 } 693 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 702 MockWebSpeechInputController* WebTestProxyBase::speechInputControllerMock() 703 { 704 BLINK_ASSERT(m_speechInputController.get()); 705 return m_speechInputController.get(); 706 } 707 #endif 708 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 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 734 void WebTestProxyBase::didScrollRect(int, int, const WebRect& clipRect) 735 { 736 didInvalidateRect(clipRect); 737 } 738 739 void WebTestProxyBase::invalidateAll() 740 { 741 m_paintRect = WebRect(0, 0, INT_MAX, INT_MAX); 742 } 743 744 void WebTestProxyBase::scheduleComposite() 745 { 746 invalidateAll(); 747 } 748 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 760 void WebTestProxyBase::animateNow() 761 { 762 if (m_animateScheduled) { 763 m_animateScheduled = false; 764 webWidget()->animate(0.0); 765 } 766 } 767 768 void WebTestProxyBase::show(WebNavigationPolicy) 769 { 770 invalidateAll(); 771 } 772 773 void WebTestProxyBase::setWindowRect(const WebRect& rect) 774 { 775 invalidateAll(); 776 discardBackingStore(); 777 } 778 779 void WebTestProxyBase::didAutoResize(const WebSize&) 780 { 781 invalidateAll(); 782 } 783 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 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 903 void WebTestProxyBase::didChangeSelection(bool isEmptySelection) 904 { 905 if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) 906 m_delegate->printMessage("EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification\n"); 907 } 908 909 void WebTestProxyBase::didChangeContents() 910 { 911 if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) 912 m_delegate->printMessage("EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification\n"); 913 } 914 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 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 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 938 void WebTestProxyBase::didStopLoading() 939 { 940 if (m_testInterfaces->testRunner()->shouldDumpProgressFinishedCallback()) 941 m_delegate->printMessage("postProgressFinishedNotification\n"); 942 } 943 944 void WebTestProxyBase::showContextMenu(WebFrame*, const WebContextMenuData& contextMenuData) 945 { 946 m_testInterfaces->eventSender()->setContextMenuData(contextMenuData); 947 } 948 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. 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 967 WebNotificationPresenter* WebTestProxyBase::notificationPresenter() 968 { 969 return m_testInterfaces->testRunner()->notificationPresenter(); 970 } 971 972 WebGeolocationClient* WebTestProxyBase::geolocationClient() 973 { 974 return geolocationClientMock(); 975 } 976 977 WebMIDIClient* WebTestProxyBase::webMIDIClient() 978 { 979 return midiClientMock(); 980 } 981 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 996 WebSpeechRecognizer* WebTestProxyBase::speechRecognizer() 997 { 998 return speechRecognizerMock(); 999 } 1000 1001 bool WebTestProxyBase::requestPointerLock() 1002 { 1003 return m_testInterfaces->testRunner()->requestPointerLock(); 1004 } 1005 1006 void WebTestProxyBase::requestPointerUnlock() 1007 { 1008 m_testInterfaces->testRunner()->requestPointerUnlock(); 1009 } 1010 1011 bool WebTestProxyBase::isPointerLocked() 1012 { 1013 return m_testInterfaces->testRunner()->isPointerLocked(); 1014 } 1015 1016 void WebTestProxyBase::didFocus() 1017 { 1018 m_delegate->setFocus(this, true); 1019 } 1020 1021 void WebTestProxyBase::didBlur() 1022 { 1023 m_delegate->setFocus(this, false); 1024 } 1025 1026 void WebTestProxyBase::setToolTipText(const WebString& text, WebTextDirection) 1027 { 1028 m_testInterfaces->testRunner()->setToolTipText(text); 1029 } 1030 1031 void WebTestProxyBase::didOpenChooser() 1032 { 1033 m_chooserCount++; 1034 } 1035 1036 void WebTestProxyBase::didCloseChooser() 1037 { 1038 m_chooserCount--; 1039 } 1040 1041 bool WebTestProxyBase::isChooserShown() 1042 { 1043 return 0 < m_chooserCount; 1044 } 1045 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 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 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 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 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 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 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 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 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 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 1149 void WebTestProxyBase::didDetectXSS(WebFrame*, const WebURL&, bool) 1150 { 1151 if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) 1152 m_delegate->printMessage("didDetectXSS\n"); 1153 } 1154 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 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 1170 void WebTestProxyBase::didCreateDataSource(WebFrame*, WebDataSource* ds) 1171 { 1172 if (!m_testInterfaces->testRunner()->deferMainResourceDataLoad()) 1173 ds->setDeferMainResourceDataLoad(false); 1174 } 1175 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 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 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 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 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 1322 void WebTestProxyBase::runModalAlertDialog(WebFrame*, const WebString& message) 1323 { 1324 m_delegate->printMessage(string("ALERT: ") + message.utf8().data() + "\n"); 1325 } 1326 1327 bool WebTestProxyBase::runModalConfirmDialog(WebFrame*, const WebString& message) 1328 { 1329 m_delegate->printMessage(string("CONFIRM: ") + message.utf8().data() + "\n"); 1330 return true; 1331 } 1332 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 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 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 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 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 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 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