1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/shell/renderer/test_runner/web_test_proxy.h" 6 7 #include <cctype> 8 9 #include "base/callback_helpers.h" 10 #include "base/command_line.h" 11 #include "base/debug/trace_event.h" 12 #include "base/logging.h" 13 #include "base/strings/string_util.h" 14 #include "base/strings/stringprintf.h" 15 #include "base/strings/utf_string_conversions.h" 16 #include "content/public/common/content_switches.h" 17 #include "content/shell/renderer/test_runner/accessibility_controller.h" 18 #include "content/shell/renderer/test_runner/event_sender.h" 19 #include "content/shell/renderer/test_runner/mock_color_chooser.h" 20 #include "content/shell/renderer/test_runner/mock_credential_manager_client.h" 21 #include "content/shell/renderer/test_runner/mock_screen_orientation_client.h" 22 #include "content/shell/renderer/test_runner/mock_web_push_client.h" 23 #include "content/shell/renderer/test_runner/mock_web_speech_recognizer.h" 24 #include "content/shell/renderer/test_runner/mock_web_user_media_client.h" 25 #include "content/shell/renderer/test_runner/spell_check_client.h" 26 #include "content/shell/renderer/test_runner/test_interfaces.h" 27 #include "content/shell/renderer/test_runner/test_plugin.h" 28 #include "content/shell/renderer/test_runner/test_runner.h" 29 #include "content/shell/renderer/test_runner/web_test_delegate.h" 30 #include "content/shell/renderer/test_runner/web_test_interfaces.h" 31 #include "content/shell/renderer/test_runner/web_test_runner.h" 32 // FIXME: Including platform_canvas.h here is a layering violation. 33 #include "skia/ext/platform_canvas.h" 34 #include "third_party/WebKit/public/platform/Platform.h" 35 #include "third_party/WebKit/public/platform/WebCString.h" 36 #include "third_party/WebKit/public/platform/WebClipboard.h" 37 #include "third_party/WebKit/public/platform/WebCompositeAndReadbackAsyncCallback.h" 38 #include "third_party/WebKit/public/platform/WebURLError.h" 39 #include "third_party/WebKit/public/platform/WebURLRequest.h" 40 #include "third_party/WebKit/public/platform/WebURLResponse.h" 41 #include "third_party/WebKit/public/web/WebAXEnums.h" 42 #include "third_party/WebKit/public/web/WebAXObject.h" 43 #include "third_party/WebKit/public/web/WebCachedURLRequest.h" 44 #include "third_party/WebKit/public/web/WebConsoleMessage.h" 45 #include "third_party/WebKit/public/web/WebDataSource.h" 46 #include "third_party/WebKit/public/web/WebDocument.h" 47 #include "third_party/WebKit/public/web/WebElement.h" 48 #include "third_party/WebKit/public/web/WebHistoryItem.h" 49 #include "third_party/WebKit/public/web/WebLocalFrame.h" 50 #include "third_party/WebKit/public/web/WebMIDIClientMock.h" 51 #include "third_party/WebKit/public/web/WebNode.h" 52 #include "third_party/WebKit/public/web/WebPagePopup.h" 53 #include "third_party/WebKit/public/web/WebPluginParams.h" 54 #include "third_party/WebKit/public/web/WebPrintParams.h" 55 #include "third_party/WebKit/public/web/WebRange.h" 56 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 57 #include "third_party/WebKit/public/web/WebView.h" 58 #include "third_party/WebKit/public/web/WebWidgetClient.h" 59 60 namespace content { 61 62 namespace { 63 64 class CaptureCallback : public blink::WebCompositeAndReadbackAsyncCallback { 65 public: 66 CaptureCallback(const base::Callback<void(const SkBitmap&)>& callback); 67 virtual ~CaptureCallback(); 68 69 void set_wait_for_popup(bool wait) { wait_for_popup_ = wait; } 70 void set_popup_position(const gfx::Point& position) { 71 popup_position_ = position; 72 } 73 74 // WebCompositeAndReadbackAsyncCallback implementation. 75 virtual void didCompositeAndReadback(const SkBitmap& bitmap); 76 77 private: 78 base::Callback<void(const SkBitmap&)> callback_; 79 SkBitmap main_bitmap_; 80 bool wait_for_popup_; 81 gfx::Point popup_position_; 82 }; 83 84 class HostMethodTask : public WebMethodTask<WebTestProxyBase> { 85 public: 86 typedef void (WebTestProxyBase::*CallbackMethodType)(); 87 HostMethodTask(WebTestProxyBase* object, CallbackMethodType callback) 88 : WebMethodTask<WebTestProxyBase>(object), callback_(callback) {} 89 90 virtual void RunIfValid() OVERRIDE { (object_->*callback_)(); } 91 92 private: 93 CallbackMethodType callback_; 94 }; 95 96 void PrintFrameDescription(WebTestDelegate* delegate, blink::WebFrame* frame) { 97 std::string name8 = frame->uniqueName().utf8(); 98 if (frame == frame->view()->mainFrame()) { 99 if (!name8.length()) { 100 delegate->PrintMessage("main frame"); 101 return; 102 } 103 delegate->PrintMessage(std::string("main frame \"") + name8 + "\""); 104 return; 105 } 106 if (!name8.length()) { 107 delegate->PrintMessage("frame (anonymous)"); 108 return; 109 } 110 delegate->PrintMessage(std::string("frame \"") + name8 + "\""); 111 } 112 113 void PrintFrameuserGestureStatus(WebTestDelegate* delegate, 114 blink::WebFrame* frame, 115 const char* msg) { 116 bool is_user_gesture = 117 blink::WebUserGestureIndicator::isProcessingUserGesture(); 118 delegate->PrintMessage(std::string("Frame with user gesture \"") + 119 (is_user_gesture ? "true" : "false") + "\"" + msg); 120 } 121 122 // Used to write a platform neutral file:/// URL by taking the 123 // filename and its directory. (e.g., converts 124 // "file:///tmp/foo/bar.txt" to just "bar.txt"). 125 std::string DescriptionSuitableForTestResult(const std::string& url) { 126 if (url.empty() || std::string::npos == url.find("file://")) 127 return url; 128 129 size_t pos = url.rfind('/'); 130 if (pos == std::string::npos || !pos) 131 return "ERROR:" + url; 132 pos = url.rfind('/', pos - 1); 133 if (pos == std::string::npos) 134 return "ERROR:" + url; 135 136 return url.substr(pos + 1); 137 } 138 139 void PrintResponseDescription(WebTestDelegate* delegate, 140 const blink::WebURLResponse& response) { 141 if (response.isNull()) { 142 delegate->PrintMessage("(null)"); 143 return; 144 } 145 delegate->PrintMessage(base::StringPrintf( 146 "<NSURLResponse %s, http status code %d>", 147 DescriptionSuitableForTestResult(response.url().spec()).c_str(), 148 response.httpStatusCode())); 149 } 150 151 std::string URLDescription(const GURL& url) { 152 if (url.SchemeIs(url::kFileScheme)) 153 return url.ExtractFileName(); 154 return url.possibly_invalid_spec(); 155 } 156 157 std::string PriorityDescription( 158 const blink::WebURLRequest::Priority& priority) { 159 switch (priority) { 160 case blink::WebURLRequest::PriorityVeryLow: 161 return "VeryLow"; 162 case blink::WebURLRequest::PriorityLow: 163 return "Low"; 164 case blink::WebURLRequest::PriorityMedium: 165 return "Medium"; 166 case blink::WebURLRequest::PriorityHigh: 167 return "High"; 168 case blink::WebURLRequest::PriorityVeryHigh: 169 return "VeryHigh"; 170 case blink::WebURLRequest::PriorityUnresolved: 171 default: 172 return "Unresolved"; 173 } 174 } 175 176 void BlockRequest(blink::WebURLRequest& request) { 177 request.setURL(GURL("255.255.255.255")); 178 } 179 180 bool IsLocalHost(const std::string& host) { 181 return host == "127.0.0.1" || host == "localhost"; 182 } 183 184 bool IsTestHost(const std::string& host) { 185 return EndsWith(host, ".test", false); 186 } 187 188 bool HostIsUsedBySomeTestsToGenerateError(const std::string& host) { 189 return host == "255.255.255.255"; 190 } 191 192 // Used to write a platform neutral file:/// URL by only taking the filename 193 // (e.g., converts "file:///tmp/foo.txt" to just "foo.txt"). 194 std::string URLSuitableForTestResult(const std::string& url) { 195 if (url.empty() || std::string::npos == url.find("file://")) 196 return url; 197 198 size_t pos = url.rfind('/'); 199 if (pos == std::string::npos) { 200 #ifdef WIN32 201 pos = url.rfind('\\'); 202 if (pos == std::string::npos) 203 pos = 0; 204 #else 205 pos = 0; 206 #endif 207 } 208 std::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* kLinkClickedString = "link clicked"; 216 const char* kFormSubmittedString = "form submitted"; 217 const char* kBackForwardString = "back/forward"; 218 const char* kReloadString = "reload"; 219 const char* kFormResubmittedString = "form resubmitted"; 220 const char* kOtherString = "other"; 221 const char* kIllegalString = "illegal value"; 222 223 // Get a debugging string from a WebNavigationType. 224 const char* WebNavigationTypeToString(blink::WebNavigationType type) { 225 switch (type) { 226 case blink::WebNavigationTypeLinkClicked: 227 return kLinkClickedString; 228 case blink::WebNavigationTypeFormSubmitted: 229 return kFormSubmittedString; 230 case blink::WebNavigationTypeBackForward: 231 return kBackForwardString; 232 case blink::WebNavigationTypeReload: 233 return kReloadString; 234 case blink::WebNavigationTypeFormResubmitted: 235 return kFormResubmittedString; 236 case blink::WebNavigationTypeOther: 237 return kOtherString; 238 } 239 return kIllegalString; 240 } 241 242 std::string DumpFrameHeaderIfNeeded(blink::WebFrame* frame) { 243 std::string result; 244 245 // Add header for all but the main frame. Skip empty frames. 246 if (frame->parent() && !frame->document().documentElement().isNull()) { 247 result.append("\n--------\nFrame: '"); 248 result.append(frame->uniqueName().utf8().data()); 249 result.append("'\n--------\n"); 250 } 251 252 return result; 253 } 254 255 std::string DumpFramesAsMarkup(blink::WebFrame* frame, bool recursive) { 256 std::string result = DumpFrameHeaderIfNeeded(frame); 257 result.append(frame->contentAsMarkup().utf8()); 258 result.append("\n"); 259 260 if (recursive) { 261 for (blink::WebFrame* child = frame->firstChild(); child; 262 child = child->nextSibling()) 263 result.append(DumpFramesAsMarkup(child, recursive)); 264 } 265 266 return result; 267 } 268 269 std::string DumpDocumentText(blink::WebFrame* frame) { 270 // We use the document element's text instead of the body text here because 271 // not all documents have a body, such as XML documents. 272 blink::WebElement document_element = frame->document().documentElement(); 273 if (document_element.isNull()) 274 return std::string(); 275 return document_element.innerText().utf8(); 276 } 277 278 std::string DumpFramesAsText(blink::WebFrame* frame, bool recursive) { 279 std::string result = DumpFrameHeaderIfNeeded(frame); 280 result.append(DumpDocumentText(frame)); 281 result.append("\n"); 282 283 if (recursive) { 284 for (blink::WebFrame* child = frame->firstChild(); child; 285 child = child->nextSibling()) 286 result.append(DumpFramesAsText(child, recursive)); 287 } 288 289 return result; 290 } 291 292 std::string DumpFramesAsPrintedText(blink::WebFrame* frame, bool recursive) { 293 // Cannot do printed format for anything other than HTML 294 if (!frame->document().isHTMLDocument()) 295 return std::string(); 296 297 std::string result = DumpFrameHeaderIfNeeded(frame); 298 result.append( 299 frame->renderTreeAsText(blink::WebFrame::RenderAsTextPrinting).utf8()); 300 result.append("\n"); 301 302 if (recursive) { 303 for (blink::WebFrame* child = frame->firstChild(); child; 304 child = child->nextSibling()) 305 result.append(DumpFramesAsPrintedText(child, recursive)); 306 } 307 308 return result; 309 } 310 311 std::string DumpFrameScrollPosition(blink::WebFrame* frame, bool recursive) { 312 std::string result; 313 blink::WebSize offset = frame->scrollOffset(); 314 if (offset.width > 0 || offset.height > 0) { 315 if (frame->parent()) { 316 result = 317 std::string("frame '") + frame->uniqueName().utf8().data() + "' "; 318 } 319 base::StringAppendF( 320 &result, "scrolled to %d,%d\n", offset.width, offset.height); 321 } 322 323 if (!recursive) 324 return result; 325 for (blink::WebFrame* child = frame->firstChild(); child; 326 child = child->nextSibling()) 327 result += DumpFrameScrollPosition(child, recursive); 328 return result; 329 } 330 331 std::string DumpAllBackForwardLists(TestInterfaces* interfaces, 332 WebTestDelegate* delegate) { 333 std::string result; 334 const std::vector<WebTestProxyBase*>& window_list = 335 interfaces->GetWindowList(); 336 for (size_t i = 0; i < window_list.size(); ++i) 337 result.append(delegate->DumpHistoryForWindow(window_list.at(i))); 338 return result; 339 } 340 } 341 342 WebTestProxyBase::WebTestProxyBase() 343 : test_interfaces_(NULL), 344 delegate_(NULL), 345 web_widget_(NULL), 346 spellcheck_(new SpellCheckClient(this)), 347 chooser_count_(0) { 348 // TODO(enne): using the scheduler introduces additional composite steps 349 // that create flakiness. This should go away eventually. 350 base::CommandLine::ForCurrentProcess()->AppendSwitch( 351 switches::kDisableSingleThreadProxyScheduler); 352 Reset(); 353 } 354 355 WebTestProxyBase::~WebTestProxyBase() { 356 test_interfaces_->WindowClosed(this); 357 } 358 359 void WebTestProxyBase::SetInterfaces(WebTestInterfaces* interfaces) { 360 test_interfaces_ = interfaces->GetTestInterfaces(); 361 test_interfaces_->WindowOpened(this); 362 } 363 364 void WebTestProxyBase::SetDelegate(WebTestDelegate* delegate) { 365 delegate_ = delegate; 366 spellcheck_->SetDelegate(delegate); 367 if (speech_recognizer_.get()) 368 speech_recognizer_->SetDelegate(delegate); 369 } 370 371 blink::WebView* WebTestProxyBase::GetWebView() const { 372 DCHECK(web_widget_); 373 // TestRunner does not support popup widgets. So |web_widget|_ is always a 374 // WebView. 375 return static_cast<blink::WebView*>(web_widget_); 376 } 377 378 void WebTestProxyBase::Reset() { 379 animate_scheduled_ = false; 380 resource_identifier_map_.clear(); 381 log_console_output_ = true; 382 if (midi_client_.get()) 383 midi_client_->resetMock(); 384 accept_languages_ = ""; 385 } 386 387 blink::WebSpellCheckClient* WebTestProxyBase::GetSpellCheckClient() const { 388 return spellcheck_.get(); 389 } 390 391 blink::WebColorChooser* WebTestProxyBase::CreateColorChooser( 392 blink::WebColorChooserClient* client, 393 const blink::WebColor& color, 394 const blink::WebVector<blink::WebColorSuggestion>& suggestions) { 395 // This instance is deleted by WebCore::ColorInputType 396 return new MockColorChooser(client, delegate_, this); 397 } 398 399 bool WebTestProxyBase::RunFileChooser( 400 const blink::WebFileChooserParams& params, 401 blink::WebFileChooserCompletion* completion) { 402 delegate_->PrintMessage("Mock: Opening a file chooser.\n"); 403 // FIXME: Add ability to set file names to a file upload control. 404 return false; 405 } 406 407 void WebTestProxyBase::ShowValidationMessage( 408 const base::string16& message, 409 const base::string16& sub_message) { 410 delegate_->PrintMessage("ValidationMessageClient: main-message=" + 411 base::UTF16ToUTF8(message) + " sub-message=" + 412 base::UTF16ToUTF8(sub_message) + "\n"); 413 } 414 415 std::string WebTestProxyBase::CaptureTree(bool debug_render_tree) { 416 bool should_dump_custom_text = 417 test_interfaces_->GetTestRunner()->shouldDumpAsCustomText(); 418 bool should_dump_as_text = 419 test_interfaces_->GetTestRunner()->shouldDumpAsText(); 420 bool should_dump_as_markup = 421 test_interfaces_->GetTestRunner()->shouldDumpAsMarkup(); 422 bool should_dump_as_printed = test_interfaces_->GetTestRunner()->isPrinting(); 423 blink::WebFrame* frame = GetWebView()->mainFrame(); 424 std::string data_utf8; 425 if (should_dump_custom_text) { 426 // Append a newline for the test driver. 427 data_utf8 = test_interfaces_->GetTestRunner()->customDumpText() + "\n"; 428 } else if (should_dump_as_text) { 429 bool recursive = 430 test_interfaces_->GetTestRunner()->shouldDumpChildFramesAsText(); 431 data_utf8 = should_dump_as_printed ? 432 DumpFramesAsPrintedText(frame, recursive) : 433 DumpFramesAsText(frame, recursive); 434 } else if (should_dump_as_markup) { 435 bool recursive = 436 test_interfaces_->GetTestRunner()->shouldDumpChildFramesAsMarkup(); 437 // Append a newline for the test driver. 438 data_utf8 = DumpFramesAsMarkup(frame, recursive); 439 } else { 440 bool recursive = test_interfaces_->GetTestRunner() 441 ->shouldDumpChildFrameScrollPositions(); 442 blink::WebFrame::RenderAsTextControls render_text_behavior = 443 blink::WebFrame::RenderAsTextNormal; 444 if (should_dump_as_printed) 445 render_text_behavior |= blink::WebFrame::RenderAsTextPrinting; 446 if (debug_render_tree) 447 render_text_behavior |= blink::WebFrame::RenderAsTextDebug; 448 data_utf8 = frame->renderTreeAsText(render_text_behavior).utf8(); 449 data_utf8 += DumpFrameScrollPosition(frame, recursive); 450 } 451 452 if (test_interfaces_->GetTestRunner()->ShouldDumpBackForwardList()) 453 data_utf8 += DumpAllBackForwardLists(test_interfaces_, delegate_); 454 455 return data_utf8; 456 } 457 458 void WebTestProxyBase::DrawSelectionRect(SkCanvas* canvas) { 459 // See if we need to draw the selection bounds rect. Selection bounds 460 // rect is the rect enclosing the (possibly transformed) selection. 461 // The rect should be drawn after everything is laid out and painted. 462 if (!test_interfaces_->GetTestRunner()->shouldDumpSelectionRect()) 463 return; 464 // If there is a selection rect - draw a red 1px border enclosing rect 465 blink::WebRect wr = GetWebView()->mainFrame()->selectionBoundsRect(); 466 if (wr.isEmpty()) 467 return; 468 // Render a red rectangle bounding selection rect 469 SkPaint paint; 470 paint.setColor(0xFFFF0000); // Fully opaque red 471 paint.setStyle(SkPaint::kStroke_Style); 472 paint.setFlags(SkPaint::kAntiAlias_Flag); 473 paint.setStrokeWidth(1.0f); 474 SkIRect rect; // Bounding rect 475 rect.set(wr.x, wr.y, wr.x + wr.width, wr.y + wr.height); 476 canvas->drawIRect(rect, paint); 477 } 478 479 void WebTestProxyBase::SetAcceptLanguages(const std::string& accept_languages) { 480 bool notify = accept_languages_ != accept_languages; 481 accept_languages_ = accept_languages; 482 483 if (notify) 484 GetWebView()->acceptLanguagesChanged(); 485 } 486 487 void WebTestProxyBase::CopyImageAtAndCapturePixels( 488 int x, int y, const base::Callback<void(const SkBitmap&)>& callback) { 489 // It may happen that there is a scheduled animation and 490 // no rootGraphicsLayer yet. If so we would run it right now. Otherwise 491 // isAcceleratedCompositingActive will return false; 492 // TODO(enne): remove this: http://crbug.com/397321 493 AnimateNow(); 494 495 DCHECK(!callback.is_null()); 496 uint64_t sequence_number = blink::Platform::current()->clipboard()-> 497 sequenceNumber(blink::WebClipboard::Buffer()); 498 GetWebView()->copyImageAt(blink::WebPoint(x, y)); 499 if (sequence_number == blink::Platform::current()->clipboard()-> 500 sequenceNumber(blink::WebClipboard::Buffer())) { 501 SkBitmap emptyBitmap; 502 callback.Run(emptyBitmap); 503 return; 504 } 505 506 blink::WebData data = blink::Platform::current()->clipboard()->readImage( 507 blink::WebClipboard::Buffer()); 508 blink::WebImage image = blink::WebImage::fromData(data, blink::WebSize()); 509 const SkBitmap& bitmap = image.getSkBitmap(); 510 SkAutoLockPixels autoLock(bitmap); 511 callback.Run(bitmap); 512 } 513 514 void WebTestProxyBase::CapturePixelsForPrinting( 515 const base::Callback<void(const SkBitmap&)>& callback) { 516 web_widget_->layout(); 517 518 blink::WebSize page_size_in_pixels = web_widget_->size(); 519 blink::WebFrame* web_frame = GetWebView()->mainFrame(); 520 521 int page_count = web_frame->printBegin(page_size_in_pixels); 522 int totalHeight = page_count * (page_size_in_pixels.height + 1) - 1; 523 524 bool is_opaque = false; 525 skia::RefPtr<SkCanvas> canvas(skia::AdoptRef(skia::TryCreateBitmapCanvas( 526 page_size_in_pixels.width, totalHeight, is_opaque))); 527 if (!canvas) { 528 callback.Run(SkBitmap()); 529 return; 530 } 531 web_frame->printPagesWithBoundaries(canvas.get(), page_size_in_pixels); 532 web_frame->printEnd(); 533 534 DrawSelectionRect(canvas.get()); 535 SkBaseDevice* device = skia::GetTopDevice(*canvas); 536 const SkBitmap& bitmap = device->accessBitmap(false); 537 callback.Run(bitmap); 538 } 539 540 CaptureCallback::CaptureCallback( 541 const base::Callback<void(const SkBitmap&)>& callback) 542 : callback_(callback), wait_for_popup_(false) { 543 } 544 545 CaptureCallback::~CaptureCallback() { 546 } 547 548 void CaptureCallback::didCompositeAndReadback(const SkBitmap& bitmap) { 549 TRACE_EVENT2("shell", 550 "CaptureCallback::didCompositeAndReadback", 551 "x", 552 bitmap.info().fWidth, 553 "y", 554 bitmap.info().fHeight); 555 if (!wait_for_popup_) { 556 callback_.Run(bitmap); 557 delete this; 558 return; 559 } 560 if (main_bitmap_.isNull()) { 561 bitmap.deepCopyTo(&main_bitmap_); 562 return; 563 } 564 SkCanvas canvas(main_bitmap_); 565 canvas.drawBitmap(bitmap, popup_position_.x(), popup_position_.y()); 566 callback_.Run(main_bitmap_); 567 delete this; 568 } 569 570 void WebTestProxyBase::CapturePixelsAsync( 571 const base::Callback<void(const SkBitmap&)>& callback) { 572 TRACE_EVENT0("shell", "WebTestProxyBase::CapturePixelsAsync"); 573 574 // It may happen that there is a scheduled animation and 575 // no rootGraphicsLayer yet. If so we would run it right now. Otherwise 576 // isAcceleratedCompositingActive will return false; 577 // TODO(enne): remove this: http://crbug.com/397321 578 AnimateNow(); 579 580 DCHECK(!callback.is_null()); 581 582 if (test_interfaces_->GetTestRunner()->isPrinting()) { 583 base::MessageLoopProxy::current()->PostTask( 584 FROM_HERE, 585 base::Bind(&WebTestProxyBase::CapturePixelsForPrinting, 586 base::Unretained(this), 587 callback)); 588 return; 589 } 590 591 CaptureCallback* capture_callback = new CaptureCallback(base::Bind( 592 &WebTestProxyBase::DidCapturePixelsAsync, base::Unretained(this), 593 callback)); 594 web_widget_->compositeAndReadbackAsync(capture_callback); 595 if (blink::WebPagePopup* popup = web_widget_->pagePopup()) { 596 capture_callback->set_wait_for_popup(true); 597 capture_callback->set_popup_position(popup->positionRelativeToOwner()); 598 popup->compositeAndReadbackAsync(capture_callback); 599 } 600 } 601 602 void WebTestProxyBase::DidCapturePixelsAsync(const base::Callback<void(const SkBitmap&)>& callback, 603 const SkBitmap& bitmap) { 604 SkCanvas canvas(bitmap); 605 DrawSelectionRect(&canvas); 606 if (!callback.is_null()) 607 callback.Run(bitmap); 608 } 609 610 void WebTestProxyBase::SetLogConsoleOutput(bool enabled) { 611 log_console_output_ = enabled; 612 } 613 614 void WebTestProxyBase::DidDisplayAsync(const base::Closure& callback, 615 const SkBitmap& bitmap) { 616 // Verify we actually composited. 617 CHECK_NE(0, bitmap.info().fWidth); 618 CHECK_NE(0, bitmap.info().fHeight); 619 if (!callback.is_null()) 620 callback.Run(); 621 } 622 623 void WebTestProxyBase::DisplayAsyncThen(const base::Closure& callback) { 624 TRACE_EVENT0("shell", "WebTestProxyBase::DisplayAsyncThen"); 625 626 // It may happen that there is a scheduled animation and 627 // no rootGraphicsLayer yet. If so we would run it right now. Otherwise 628 // isAcceleratedCompositingActive will return false; 629 // TODO(enne): remove this: http://crbug.com/397321 630 AnimateNow(); 631 632 CapturePixelsAsync(base::Bind( 633 &WebTestProxyBase::DidDisplayAsync, base::Unretained(this), callback)); 634 } 635 636 void WebTestProxyBase::GetScreenOrientationForTesting( 637 blink::WebScreenInfo& screen_info) { 638 if (!screen_orientation_client_) 639 return; 640 // Override screen orientation information with mock data. 641 screen_info.orientationType = 642 screen_orientation_client_->CurrentOrientationType(); 643 screen_info.orientationAngle = 644 screen_orientation_client_->CurrentOrientationAngle(); 645 } 646 647 MockScreenOrientationClient* 648 WebTestProxyBase::GetScreenOrientationClientMock() { 649 if (!screen_orientation_client_.get()) { 650 screen_orientation_client_.reset(new MockScreenOrientationClient); 651 } 652 return screen_orientation_client_.get(); 653 } 654 655 blink::WebMIDIClientMock* WebTestProxyBase::GetMIDIClientMock() { 656 if (!midi_client_.get()) 657 midi_client_.reset(new blink::WebMIDIClientMock); 658 return midi_client_.get(); 659 } 660 661 MockWebSpeechRecognizer* WebTestProxyBase::GetSpeechRecognizerMock() { 662 if (!speech_recognizer_.get()) { 663 speech_recognizer_.reset(new MockWebSpeechRecognizer()); 664 speech_recognizer_->SetDelegate(delegate_); 665 } 666 return speech_recognizer_.get(); 667 } 668 669 MockCredentialManagerClient* 670 WebTestProxyBase::GetCredentialManagerClientMock() { 671 if (!credential_manager_client_.get()) 672 credential_manager_client_.reset(new MockCredentialManagerClient()); 673 return credential_manager_client_.get(); 674 } 675 676 void WebTestProxyBase::ScheduleAnimation() { 677 if (!test_interfaces_->GetTestRunner()->TestIsRunning()) 678 return; 679 680 if (!animate_scheduled_) { 681 animate_scheduled_ = true; 682 delegate_->PostDelayedTask( 683 new HostMethodTask(this, &WebTestProxyBase::AnimateNow), 1); 684 } 685 } 686 687 void WebTestProxyBase::AnimateNow() { 688 if (animate_scheduled_) { 689 animate_scheduled_ = false; 690 web_widget_->animate(0.0); 691 web_widget_->layout(); 692 } 693 } 694 695 void WebTestProxyBase::PostAccessibilityEvent(const blink::WebAXObject& obj, 696 blink::WebAXEvent event) { 697 // Only hook the accessibility events occured during the test run. 698 // This check prevents false positives in WebLeakDetector. 699 // The pending tasks in browser/renderer message queue may trigger 700 // accessibility events, 701 // and AccessibilityController will hold on to their target nodes if we don't 702 // ignore them here. 703 if (!test_interfaces_->GetTestRunner()->TestIsRunning()) 704 return; 705 706 if (event == blink::WebAXEventFocus) 707 test_interfaces_->GetAccessibilityController()->SetFocusedElement(obj); 708 709 const char* event_name = NULL; 710 switch (event) { 711 case blink::WebAXEventActiveDescendantChanged: 712 event_name = "ActiveDescendantChanged"; 713 break; 714 case blink::WebAXEventAlert: 715 event_name = "Alert"; 716 break; 717 case blink::WebAXEventAriaAttributeChanged: 718 event_name = "AriaAttributeChanged"; 719 break; 720 case blink::WebAXEventAutocorrectionOccured: 721 event_name = "AutocorrectionOccured"; 722 break; 723 case blink::WebAXEventBlur: 724 event_name = "Blur"; 725 break; 726 case blink::WebAXEventCheckedStateChanged: 727 event_name = "CheckedStateChanged"; 728 break; 729 case blink::WebAXEventChildrenChanged: 730 event_name = "ChildrenChanged"; 731 break; 732 case blink::WebAXEventFocus: 733 event_name = "Focus"; 734 break; 735 case blink::WebAXEventHide: 736 event_name = "Hide"; 737 break; 738 case blink::WebAXEventInvalidStatusChanged: 739 event_name = "InvalidStatusChanged"; 740 break; 741 case blink::WebAXEventLayoutComplete: 742 event_name = "LayoutComplete"; 743 break; 744 case blink::WebAXEventLiveRegionChanged: 745 event_name = "LiveRegionChanged"; 746 break; 747 case blink::WebAXEventLoadComplete: 748 event_name = "LoadComplete"; 749 break; 750 case blink::WebAXEventLocationChanged: 751 event_name = "LocationChanged"; 752 break; 753 case blink::WebAXEventMenuListItemSelected: 754 event_name = "MenuListItemSelected"; 755 break; 756 case blink::WebAXEventMenuListValueChanged: 757 event_name = "MenuListValueChanged"; 758 break; 759 case blink::WebAXEventRowCollapsed: 760 event_name = "RowCollapsed"; 761 break; 762 case blink::WebAXEventRowCountChanged: 763 event_name = "RowCountChanged"; 764 break; 765 case blink::WebAXEventRowExpanded: 766 event_name = "RowExpanded"; 767 break; 768 case blink::WebAXEventScrollPositionChanged: 769 event_name = "ScrollPositionChanged"; 770 break; 771 case blink::WebAXEventScrolledToAnchor: 772 event_name = "ScrolledToAnchor"; 773 break; 774 case blink::WebAXEventSelectedChildrenChanged: 775 event_name = "SelectedChildrenChanged"; 776 break; 777 case blink::WebAXEventSelectedTextChanged: 778 event_name = "SelectedTextChanged"; 779 break; 780 case blink::WebAXEventShow: 781 event_name = "Show"; 782 break; 783 case blink::WebAXEventTextChanged: 784 event_name = "TextChanged"; 785 break; 786 case blink::WebAXEventTextInserted: 787 event_name = "TextInserted"; 788 break; 789 case blink::WebAXEventTextRemoved: 790 event_name = "TextRemoved"; 791 break; 792 case blink::WebAXEventValueChanged: 793 event_name = "ValueChanged"; 794 break; 795 default: 796 event_name = "Unknown"; 797 break; 798 } 799 800 test_interfaces_->GetAccessibilityController()->NotificationReceived( 801 obj, event_name); 802 803 if (test_interfaces_->GetAccessibilityController() 804 ->ShouldLogAccessibilityEvents()) { 805 std::string message("AccessibilityNotification - "); 806 message += event_name; 807 808 blink::WebNode node = obj.node(); 809 if (!node.isNull() && node.isElementNode()) { 810 blink::WebElement element = node.to<blink::WebElement>(); 811 if (element.hasAttribute("id")) { 812 message += " - id:"; 813 message += element.getAttribute("id").utf8().data(); 814 } 815 } 816 817 delegate_->PrintMessage(message + "\n"); 818 } 819 } 820 821 void WebTestProxyBase::StartDragging(blink::WebLocalFrame* frame, 822 const blink::WebDragData& data, 823 blink::WebDragOperationsMask mask, 824 const blink::WebImage& image, 825 const blink::WebPoint& point) { 826 // When running a test, we need to fake a drag drop operation otherwise 827 // Windows waits for real mouse events to know when the drag is over. 828 test_interfaces_->GetEventSender()->DoDragDrop(data, mask); 829 } 830 831 // The output from these methods in layout test mode should match that 832 // expected by the layout tests. See EditingDelegate.m in DumpRenderTree. 833 834 void WebTestProxyBase::DidChangeSelection(bool is_empty_callback) { 835 if (test_interfaces_->GetTestRunner()->shouldDumpEditingCallbacks()) 836 delegate_->PrintMessage( 837 "EDITING DELEGATE: " 838 "webViewDidChangeSelection:WebViewDidChangeSelectionNotification\n"); 839 } 840 841 void WebTestProxyBase::DidChangeContents() { 842 if (test_interfaces_->GetTestRunner()->shouldDumpEditingCallbacks()) 843 delegate_->PrintMessage( 844 "EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification\n"); 845 } 846 847 bool WebTestProxyBase::CreateView(blink::WebLocalFrame* frame, 848 const blink::WebURLRequest& request, 849 const blink::WebWindowFeatures& features, 850 const blink::WebString& frame_name, 851 blink::WebNavigationPolicy policy, 852 bool suppress_opener) { 853 if (!test_interfaces_->GetTestRunner()->canOpenWindows()) 854 return false; 855 if (test_interfaces_->GetTestRunner()->shouldDumpCreateView()) 856 delegate_->PrintMessage(std::string("createView(") + 857 URLDescription(request.url()) + ")\n"); 858 return true; 859 } 860 861 blink::WebPlugin* WebTestProxyBase::CreatePlugin( 862 blink::WebLocalFrame* frame, 863 const blink::WebPluginParams& params) { 864 if (TestPlugin::IsSupportedMimeType(params.mimeType)) 865 return TestPlugin::create(frame, params, delegate_); 866 return 0; 867 } 868 869 void WebTestProxyBase::SetStatusText(const blink::WebString& text) { 870 if (!test_interfaces_->GetTestRunner()->shouldDumpStatusCallbacks()) 871 return; 872 delegate_->PrintMessage( 873 std::string("UI DELEGATE STATUS CALLBACK: setStatusText:") + 874 text.utf8().data() + "\n"); 875 } 876 877 void WebTestProxyBase::DidStopLoading() { 878 if (test_interfaces_->GetTestRunner()->shouldDumpProgressFinishedCallback()) 879 delegate_->PrintMessage("postProgressFinishedNotification\n"); 880 } 881 882 void WebTestProxyBase::ShowContextMenu( 883 blink::WebLocalFrame* frame, 884 const blink::WebContextMenuData& context_menu_data) { 885 test_interfaces_->GetEventSender()->SetContextMenuData(context_menu_data); 886 } 887 888 blink::WebUserMediaClient* WebTestProxyBase::GetUserMediaClient() { 889 if (!user_media_client_.get()) 890 user_media_client_.reset(new MockWebUserMediaClient(delegate_)); 891 return user_media_client_.get(); 892 } 893 894 // Simulate a print by going into print mode and then exit straight away. 895 void WebTestProxyBase::PrintPage(blink::WebLocalFrame* frame) { 896 blink::WebSize page_size_in_pixels = web_widget_->size(); 897 if (page_size_in_pixels.isEmpty()) 898 return; 899 blink::WebPrintParams printParams(page_size_in_pixels); 900 frame->printBegin(printParams); 901 frame->printEnd(); 902 } 903 904 blink::WebNotificationPresenter* WebTestProxyBase::GetNotificationPresenter() { 905 return test_interfaces_->GetTestRunner()->notification_presenter(); 906 } 907 908 blink::WebMIDIClient* WebTestProxyBase::GetWebMIDIClient() { 909 return GetMIDIClientMock(); 910 } 911 912 blink::WebSpeechRecognizer* WebTestProxyBase::GetSpeechRecognizer() { 913 return GetSpeechRecognizerMock(); 914 } 915 916 bool WebTestProxyBase::RequestPointerLock() { 917 return test_interfaces_->GetTestRunner()->RequestPointerLock(); 918 } 919 920 void WebTestProxyBase::RequestPointerUnlock() { 921 test_interfaces_->GetTestRunner()->RequestPointerUnlock(); 922 } 923 924 bool WebTestProxyBase::IsPointerLocked() { 925 return test_interfaces_->GetTestRunner()->isPointerLocked(); 926 } 927 928 void WebTestProxyBase::DidFocus() { 929 delegate_->SetFocus(this, true); 930 } 931 932 void WebTestProxyBase::DidBlur() { 933 delegate_->SetFocus(this, false); 934 } 935 936 void WebTestProxyBase::SetToolTipText(const blink::WebString& text, 937 blink::WebTextDirection direction) { 938 test_interfaces_->GetTestRunner()->setToolTipText(text); 939 } 940 941 void WebTestProxyBase::DidOpenChooser() { 942 chooser_count_++; 943 } 944 945 void WebTestProxyBase::DidCloseChooser() { 946 chooser_count_--; 947 } 948 949 bool WebTestProxyBase::IsChooserShown() { 950 return 0 < chooser_count_; 951 } 952 953 void WebTestProxyBase::LoadURLExternally( 954 blink::WebLocalFrame* frame, 955 const blink::WebURLRequest& request, 956 blink::WebNavigationPolicy policy, 957 const blink::WebString& suggested_name) { 958 if (test_interfaces_->GetTestRunner()->shouldWaitUntilExternalURLLoad()) { 959 if (policy == blink::WebNavigationPolicyDownload) { 960 delegate_->PrintMessage( 961 std::string("Downloading URL with suggested filename \"") + 962 suggested_name.utf8() + "\"\n"); 963 } else { 964 delegate_->PrintMessage(std::string("Loading URL externally - \"") + 965 URLDescription(request.url()) + "\"\n"); 966 } 967 delegate_->TestFinished(); 968 } 969 } 970 971 void WebTestProxyBase::DidStartProvisionalLoad(blink::WebLocalFrame* frame) { 972 if (!test_interfaces_->GetTestRunner()->topLoadingFrame()) 973 test_interfaces_->GetTestRunner()->setTopLoadingFrame(frame, false); 974 975 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) { 976 PrintFrameDescription(delegate_, frame); 977 delegate_->PrintMessage(" - didStartProvisionalLoadForFrame\n"); 978 } 979 980 if (test_interfaces_->GetTestRunner() 981 ->shouldDumpUserGestureInFrameLoadCallbacks()) { 982 PrintFrameuserGestureStatus( 983 delegate_, frame, " - in didStartProvisionalLoadForFrame\n"); 984 } 985 } 986 987 void WebTestProxyBase::DidReceiveServerRedirectForProvisionalLoad( 988 blink::WebLocalFrame* frame) { 989 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) { 990 PrintFrameDescription(delegate_, frame); 991 delegate_->PrintMessage( 992 " - didReceiveServerRedirectForProvisionalLoadForFrame\n"); 993 } 994 } 995 996 bool WebTestProxyBase::DidFailProvisionalLoad(blink::WebLocalFrame* frame, 997 const blink::WebURLError& error) { 998 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) { 999 PrintFrameDescription(delegate_, frame); 1000 delegate_->PrintMessage(" - didFailProvisionalLoadWithError\n"); 1001 } 1002 CheckDone(frame, MainResourceLoadFailed); 1003 return !frame->provisionalDataSource(); 1004 } 1005 1006 void WebTestProxyBase::DidCommitProvisionalLoad( 1007 blink::WebLocalFrame* frame, 1008 const blink::WebHistoryItem& history_item, 1009 blink::WebHistoryCommitType history_type) { 1010 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) { 1011 PrintFrameDescription(delegate_, frame); 1012 delegate_->PrintMessage(" - didCommitLoadForFrame\n"); 1013 } 1014 } 1015 1016 void WebTestProxyBase::DidReceiveTitle(blink::WebLocalFrame* frame, 1017 const blink::WebString& title, 1018 blink::WebTextDirection direction) { 1019 blink::WebCString title8 = title.utf8(); 1020 1021 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) { 1022 PrintFrameDescription(delegate_, frame); 1023 delegate_->PrintMessage(std::string(" - didReceiveTitle: ") + 1024 title8.data() + "\n"); 1025 } 1026 1027 if (test_interfaces_->GetTestRunner()->shouldDumpTitleChanges()) 1028 delegate_->PrintMessage(std::string("TITLE CHANGED: '") + title8.data() + 1029 "'\n"); 1030 } 1031 1032 void WebTestProxyBase::DidChangeIcon(blink::WebLocalFrame* frame, 1033 blink::WebIconURL::Type icon_type) { 1034 if (test_interfaces_->GetTestRunner()->shouldDumpIconChanges()) { 1035 PrintFrameDescription(delegate_, frame); 1036 delegate_->PrintMessage(std::string(" - didChangeIcons\n")); 1037 } 1038 } 1039 1040 void WebTestProxyBase::DidFinishDocumentLoad(blink::WebLocalFrame* frame) { 1041 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) { 1042 PrintFrameDescription(delegate_, frame); 1043 delegate_->PrintMessage(" - didFinishDocumentLoadForFrame\n"); 1044 } else { 1045 unsigned pendingUnloadEvents = frame->unloadListenerCount(); 1046 if (pendingUnloadEvents) { 1047 PrintFrameDescription(delegate_, frame); 1048 delegate_->PrintMessage(base::StringPrintf( 1049 " - has %u onunload handler(s)\n", pendingUnloadEvents)); 1050 } 1051 } 1052 } 1053 1054 void WebTestProxyBase::DidHandleOnloadEvents(blink::WebLocalFrame* frame) { 1055 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) { 1056 PrintFrameDescription(delegate_, frame); 1057 delegate_->PrintMessage(" - didHandleOnloadEventsForFrame\n"); 1058 } 1059 } 1060 1061 void WebTestProxyBase::DidFailLoad(blink::WebLocalFrame* frame, 1062 const blink::WebURLError& error) { 1063 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) { 1064 PrintFrameDescription(delegate_, frame); 1065 delegate_->PrintMessage(" - didFailLoadWithError\n"); 1066 } 1067 CheckDone(frame, MainResourceLoadFailed); 1068 } 1069 1070 void WebTestProxyBase::DidFinishLoad(blink::WebLocalFrame* frame) { 1071 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) { 1072 PrintFrameDescription(delegate_, frame); 1073 delegate_->PrintMessage(" - didFinishLoadForFrame\n"); 1074 } 1075 CheckDone(frame, LoadFinished); 1076 } 1077 1078 void WebTestProxyBase::DidDetectXSS(blink::WebLocalFrame* frame, 1079 const blink::WebURL& insecure_url, 1080 bool did_block_entire_page) { 1081 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) 1082 delegate_->PrintMessage("didDetectXSS\n"); 1083 } 1084 1085 void WebTestProxyBase::DidDispatchPingLoader(blink::WebLocalFrame* frame, 1086 const blink::WebURL& url) { 1087 if (test_interfaces_->GetTestRunner()->shouldDumpPingLoaderCallbacks()) 1088 delegate_->PrintMessage(std::string("PingLoader dispatched to '") + 1089 URLDescription(url).c_str() + "'.\n"); 1090 } 1091 1092 void WebTestProxyBase::WillRequestResource( 1093 blink::WebLocalFrame* frame, 1094 const blink::WebCachedURLRequest& request) { 1095 if (test_interfaces_->GetTestRunner()->shouldDumpResourceRequestCallbacks()) { 1096 PrintFrameDescription(delegate_, frame); 1097 delegate_->PrintMessage(std::string(" - ") + 1098 request.initiatorName().utf8().data()); 1099 delegate_->PrintMessage(std::string(" requested '") + 1100 URLDescription(request.urlRequest().url()).c_str() + 1101 "'\n"); 1102 } 1103 } 1104 1105 void WebTestProxyBase::WillSendRequest( 1106 blink::WebLocalFrame* frame, 1107 unsigned identifier, 1108 blink::WebURLRequest& request, 1109 const blink::WebURLResponse& redirect_response) { 1110 // Need to use GURL for host() and SchemeIs() 1111 GURL url = request.url(); 1112 std::string request_url = url.possibly_invalid_spec(); 1113 1114 GURL main_document_url = request.firstPartyForCookies(); 1115 1116 if (redirect_response.isNull() && 1117 (test_interfaces_->GetTestRunner()->shouldDumpResourceLoadCallbacks() || 1118 test_interfaces_->GetTestRunner()->shouldDumpResourcePriorities())) { 1119 DCHECK(resource_identifier_map_.find(identifier) == 1120 resource_identifier_map_.end()); 1121 resource_identifier_map_[identifier] = 1122 DescriptionSuitableForTestResult(request_url); 1123 } 1124 1125 if (test_interfaces_->GetTestRunner()->shouldDumpResourceLoadCallbacks()) { 1126 if (resource_identifier_map_.find(identifier) == 1127 resource_identifier_map_.end()) 1128 delegate_->PrintMessage("<unknown>"); 1129 else 1130 delegate_->PrintMessage(resource_identifier_map_[identifier]); 1131 delegate_->PrintMessage(" - willSendRequest <NSURLRequest URL "); 1132 delegate_->PrintMessage( 1133 DescriptionSuitableForTestResult(request_url).c_str()); 1134 delegate_->PrintMessage(", main document URL "); 1135 delegate_->PrintMessage(URLDescription(main_document_url).c_str()); 1136 delegate_->PrintMessage(", http method "); 1137 delegate_->PrintMessage(request.httpMethod().utf8().data()); 1138 delegate_->PrintMessage("> redirectResponse "); 1139 PrintResponseDescription(delegate_, redirect_response); 1140 delegate_->PrintMessage("\n"); 1141 } 1142 1143 if (test_interfaces_->GetTestRunner()->shouldDumpResourcePriorities()) { 1144 delegate_->PrintMessage( 1145 DescriptionSuitableForTestResult(request_url).c_str()); 1146 delegate_->PrintMessage(" has priority "); 1147 delegate_->PrintMessage(PriorityDescription(request.priority())); 1148 delegate_->PrintMessage("\n"); 1149 } 1150 1151 if (test_interfaces_->GetTestRunner()->httpHeadersToClear()) { 1152 const std::set<std::string>* clearHeaders = 1153 test_interfaces_->GetTestRunner()->httpHeadersToClear(); 1154 for (std::set<std::string>::const_iterator header = clearHeaders->begin(); 1155 header != clearHeaders->end(); 1156 ++header) 1157 request.clearHTTPHeaderField(blink::WebString::fromUTF8(*header)); 1158 } 1159 1160 std::string host = url.host(); 1161 if (!host.empty() && 1162 (url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme))) { 1163 if (!IsLocalHost(host) && !IsTestHost(host) && 1164 !HostIsUsedBySomeTestsToGenerateError(host) && 1165 ((!main_document_url.SchemeIs(url::kHttpScheme) && 1166 !main_document_url.SchemeIs(url::kHttpsScheme)) || 1167 IsLocalHost(main_document_url.host())) && 1168 !delegate_->AllowExternalPages()) { 1169 delegate_->PrintMessage(std::string("Blocked access to external URL ") + 1170 request_url + "\n"); 1171 BlockRequest(request); 1172 return; 1173 } 1174 } 1175 1176 // Set the new substituted URL. 1177 request.setURL(delegate_->RewriteLayoutTestsURL(request.url().spec())); 1178 } 1179 1180 void WebTestProxyBase::DidReceiveResponse( 1181 blink::WebLocalFrame* frame, 1182 unsigned identifier, 1183 const blink::WebURLResponse& response) { 1184 if (test_interfaces_->GetTestRunner()->shouldDumpResourceLoadCallbacks()) { 1185 if (resource_identifier_map_.find(identifier) == 1186 resource_identifier_map_.end()) 1187 delegate_->PrintMessage("<unknown>"); 1188 else 1189 delegate_->PrintMessage(resource_identifier_map_[identifier]); 1190 delegate_->PrintMessage(" - didReceiveResponse "); 1191 PrintResponseDescription(delegate_, response); 1192 delegate_->PrintMessage("\n"); 1193 } 1194 if (test_interfaces_->GetTestRunner() 1195 ->shouldDumpResourceResponseMIMETypes()) { 1196 GURL url = response.url(); 1197 blink::WebString mime_type = response.mimeType(); 1198 delegate_->PrintMessage(url.ExtractFileName()); 1199 delegate_->PrintMessage(" has MIME type "); 1200 // Simulate NSURLResponse's mapping of empty/unknown MIME types to 1201 // application/octet-stream 1202 delegate_->PrintMessage(mime_type.isEmpty() ? "application/octet-stream" 1203 : mime_type.utf8().data()); 1204 delegate_->PrintMessage("\n"); 1205 } 1206 } 1207 1208 void WebTestProxyBase::DidChangeResourcePriority( 1209 blink::WebLocalFrame* frame, 1210 unsigned identifier, 1211 const blink::WebURLRequest::Priority& priority, 1212 int intra_priority_value) { 1213 if (test_interfaces_->GetTestRunner()->shouldDumpResourcePriorities()) { 1214 if (resource_identifier_map_.find(identifier) == 1215 resource_identifier_map_.end()) 1216 delegate_->PrintMessage("<unknown>"); 1217 else 1218 delegate_->PrintMessage(resource_identifier_map_[identifier]); 1219 delegate_->PrintMessage( 1220 base::StringPrintf(" changed priority to %s, intra_priority %d\n", 1221 PriorityDescription(priority).c_str(), 1222 intra_priority_value)); 1223 } 1224 } 1225 1226 void WebTestProxyBase::DidFinishResourceLoad(blink::WebLocalFrame* frame, 1227 unsigned identifier) { 1228 if (test_interfaces_->GetTestRunner()->shouldDumpResourceLoadCallbacks()) { 1229 if (resource_identifier_map_.find(identifier) == 1230 resource_identifier_map_.end()) 1231 delegate_->PrintMessage("<unknown>"); 1232 else 1233 delegate_->PrintMessage(resource_identifier_map_[identifier]); 1234 delegate_->PrintMessage(" - didFinishLoading\n"); 1235 } 1236 resource_identifier_map_.erase(identifier); 1237 #if !defined(ENABLE_LOAD_COMPLETION_HACKS) 1238 CheckDone(frame, ResourceLoadCompleted); 1239 #endif 1240 } 1241 1242 void WebTestProxyBase::DidAddMessageToConsole( 1243 const blink::WebConsoleMessage& message, 1244 const blink::WebString& source_name, 1245 unsigned source_line) { 1246 // This matches win DumpRenderTree's UIDelegate.cpp. 1247 if (!log_console_output_) 1248 return; 1249 std::string level; 1250 switch (message.level) { 1251 case blink::WebConsoleMessage::LevelDebug: 1252 level = "DEBUG"; 1253 break; 1254 case blink::WebConsoleMessage::LevelLog: 1255 level = "MESSAGE"; 1256 break; 1257 case blink::WebConsoleMessage::LevelInfo: 1258 level = "INFO"; 1259 break; 1260 case blink::WebConsoleMessage::LevelWarning: 1261 level = "WARNING"; 1262 break; 1263 case blink::WebConsoleMessage::LevelError: 1264 level = "ERROR"; 1265 break; 1266 } 1267 delegate_->PrintMessage(std::string("CONSOLE ") + level + ": "); 1268 if (source_line) { 1269 delegate_->PrintMessage(base::StringPrintf("line %d: ", source_line)); 1270 } 1271 if (!message.text.isEmpty()) { 1272 std::string new_message; 1273 new_message = message.text.utf8(); 1274 size_t file_protocol = new_message.find("file://"); 1275 if (file_protocol != std::string::npos) { 1276 new_message = new_message.substr(0, file_protocol) + 1277 URLSuitableForTestResult(new_message.substr(file_protocol)); 1278 } 1279 delegate_->PrintMessage(new_message); 1280 } 1281 delegate_->PrintMessage(std::string("\n")); 1282 } 1283 1284 void WebTestProxyBase::CheckDone(blink::WebLocalFrame* frame, 1285 CheckDoneReason reason) { 1286 if (frame != test_interfaces_->GetTestRunner()->topLoadingFrame()) 1287 return; 1288 1289 #if !defined(ENABLE_LOAD_COMPLETION_HACKS) 1290 // Quirk for MHTML prematurely completing on resource load completion. 1291 std::string mime_type = frame->dataSource()->response().mimeType().utf8(); 1292 if (reason == ResourceLoadCompleted && mime_type == "multipart/related") 1293 return; 1294 1295 if (reason != MainResourceLoadFailed && 1296 (frame->isResourceLoadInProgress() || frame->isLoading())) 1297 return; 1298 #endif 1299 test_interfaces_->GetTestRunner()->setTopLoadingFrame(frame, true); 1300 } 1301 1302 blink::WebNavigationPolicy WebTestProxyBase::DecidePolicyForNavigation( 1303 const blink::WebFrameClient::NavigationPolicyInfo& info) { 1304 blink::WebNavigationPolicy result; 1305 if (!test_interfaces_->GetTestRunner()->policyDelegateEnabled()) 1306 return info.defaultPolicy; 1307 1308 delegate_->PrintMessage( 1309 std::string("Policy delegate: attempt to load ") + 1310 URLDescription(info.urlRequest.url()) + " with navigation type '" + 1311 WebNavigationTypeToString(info.navigationType) + "'\n"); 1312 if (test_interfaces_->GetTestRunner()->policyDelegateIsPermissive()) 1313 result = blink::WebNavigationPolicyCurrentTab; 1314 else 1315 result = blink::WebNavigationPolicyIgnore; 1316 1317 if (test_interfaces_->GetTestRunner()->policyDelegateShouldNotifyDone()) 1318 test_interfaces_->GetTestRunner()->policyDelegateDone(); 1319 return result; 1320 } 1321 1322 bool WebTestProxyBase::WillCheckAndDispatchMessageEvent( 1323 blink::WebLocalFrame* source_frame, 1324 blink::WebFrame* target_frame, 1325 blink::WebSecurityOrigin target, 1326 blink::WebDOMMessageEvent event) { 1327 if (test_interfaces_->GetTestRunner()->shouldInterceptPostMessage()) { 1328 delegate_->PrintMessage("intercepted postMessage\n"); 1329 return true; 1330 } 1331 1332 return false; 1333 } 1334 1335 void WebTestProxyBase::PostSpellCheckEvent(const blink::WebString& event_name) { 1336 if (test_interfaces_->GetTestRunner()->shouldDumpSpellCheckCallbacks()) { 1337 delegate_->PrintMessage(std::string("SpellCheckEvent: ") + 1338 event_name.utf8().data() + "\n"); 1339 } 1340 } 1341 1342 void WebTestProxyBase::ResetInputMethod() { 1343 // If a composition text exists, then we need to let the browser process 1344 // to cancel the input method's ongoing composition session. 1345 if (web_widget_) 1346 web_widget_->confirmComposition(); 1347 } 1348 1349 blink::WebString WebTestProxyBase::acceptLanguages() { 1350 return blink::WebString::fromUTF8(accept_languages_); 1351 } 1352 1353 MockWebPushClient* WebTestProxyBase::GetPushClientMock() { 1354 if (!push_client_.get()) 1355 push_client_.reset(new MockWebPushClient); 1356 return push_client_.get(); 1357 } 1358 1359 blink::WebPushClient* WebTestProxyBase::GetWebPushClient() { 1360 return GetPushClientMock(); 1361 } 1362 1363 } // namespace content 1364