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.
5 #include "content/shell/renderer/test_runner/web_test_proxy.h"
9 #include "base/callback_helpers.h"
10 #include "base/debug/trace_event.h"
11 #include "base/logging.h"
12 #include "base/strings/stringprintf.h"
13 #include "content/shell/renderer/test_runner/TestPlugin.h"
14 #include "content/shell/renderer/test_runner/WebTestDelegate.h"
15 #include "content/shell/renderer/test_runner/WebTestInterfaces.h"
16 #include "content/shell/renderer/test_runner/accessibility_controller.h"
17 #include "content/shell/renderer/test_runner/event_sender.h"
18 #include "content/shell/renderer/test_runner/mock_color_chooser.h"
19 #include "content/shell/renderer/test_runner/mock_screen_orientation_client.h"
20 #include "content/shell/renderer/test_runner/mock_web_push_client.h"
21 #include "content/shell/renderer/test_runner/mock_web_speech_recognizer.h"
22 #include "content/shell/renderer/test_runner/mock_web_user_media_client.h"
23 #include "content/shell/renderer/test_runner/spell_check_client.h"
24 #include "content/shell/renderer/test_runner/test_interfaces.h"
25 #include "content/shell/renderer/test_runner/test_runner.h"
26 #include "content/shell/renderer/test_runner/web_test_runner.h"
27 // FIXME: Including platform_canvas.h here is a layering violation.
28 #include "skia/ext/platform_canvas.h"
29 #include "third_party/WebKit/public/platform/Platform.h"
30 #include "third_party/WebKit/public/platform/WebCString.h"
31 #include "third_party/WebKit/public/platform/WebClipboard.h"
32 #include "third_party/WebKit/public/platform/WebURLError.h"
33 #include "third_party/WebKit/public/platform/WebURLRequest.h"
34 #include "third_party/WebKit/public/platform/WebURLResponse.h"
35 #include "third_party/WebKit/public/web/WebAXEnums.h"
36 #include "third_party/WebKit/public/web/WebAXObject.h"
37 #include "third_party/WebKit/public/web/WebCachedURLRequest.h"
38 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
39 #include "third_party/WebKit/public/web/WebDataSource.h"
40 #include "third_party/WebKit/public/web/WebDocument.h"
41 #include "third_party/WebKit/public/web/WebElement.h"
42 #include "third_party/WebKit/public/web/WebHistoryItem.h"
43 #include "third_party/WebKit/public/web/WebLocalFrame.h"
44 #include "third_party/WebKit/public/web/WebMIDIClientMock.h"
45 #include "third_party/WebKit/public/web/WebNode.h"
46 #include "third_party/WebKit/public/web/WebPluginParams.h"
47 #include "third_party/WebKit/public/web/WebPrintParams.h"
48 #include "third_party/WebKit/public/web/WebRange.h"
49 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
50 #include "third_party/WebKit/public/web/WebView.h"
56 class HostMethodTask : public WebMethodTask<WebTestProxyBase> {
58 typedef void (WebTestProxyBase::*CallbackMethodType)();
59 HostMethodTask(WebTestProxyBase* object, CallbackMethodType callback)
60 : WebMethodTask<WebTestProxyBase>(object), callback_(callback) {}
62 virtual void runIfValid() OVERRIDE { (m_object->*callback_)(); }
65 CallbackMethodType callback_;
68 void PrintFrameDescription(WebTestDelegate* delegate, blink::WebFrame* frame) {
69 std::string name8 = frame->uniqueName().utf8();
70 if (frame == frame->view()->mainFrame()) {
71 if (!name8.length()) {
72 delegate->printMessage("main frame");
75 delegate->printMessage(std::string("main frame \"") + name8 + "\"");
78 if (!name8.length()) {
79 delegate->printMessage("frame (anonymous)");
82 delegate->printMessage(std::string("frame \"") + name8 + "\"");
85 void PrintFrameuserGestureStatus(WebTestDelegate* delegate,
86 blink::WebFrame* frame,
88 bool is_user_gesture =
89 blink::WebUserGestureIndicator::isProcessingUserGesture();
90 delegate->printMessage(std::string("Frame with user gesture \"") +
91 (is_user_gesture ? "true" : "false") + "\"" + msg);
94 // Used to write a platform neutral file:/// URL by taking the
95 // filename and its directory. (e.g., converts
96 // "file:///tmp/foo/bar.txt" to just "bar.txt").
97 std::string DescriptionSuitableForTestResult(const std::string& url) {
98 if (url.empty() || std::string::npos == url.find("file://"))
101 size_t pos = url.rfind('/');
102 if (pos == std::string::npos || !pos)
103 return "ERROR:" + url;
104 pos = url.rfind('/', pos - 1);
105 if (pos == std::string::npos)
106 return "ERROR:" + url;
108 return url.substr(pos + 1);
111 void PrintResponseDescription(WebTestDelegate* delegate,
112 const blink::WebURLResponse& response) {
113 if (response.isNull()) {
114 delegate->printMessage("(null)");
117 delegate->printMessage(base::StringPrintf(
118 "<NSURLResponse %s, http status code %d>",
119 DescriptionSuitableForTestResult(response.url().spec()).c_str(),
120 response.httpStatusCode()));
123 std::string URLDescription(const GURL& url) {
124 if (url.SchemeIs("file"))
125 return url.ExtractFileName();
126 return url.possibly_invalid_spec();
129 std::string PriorityDescription(
130 const blink::WebURLRequest::Priority& priority) {
132 case blink::WebURLRequest::PriorityVeryLow:
134 case blink::WebURLRequest::PriorityLow:
136 case blink::WebURLRequest::PriorityMedium:
138 case blink::WebURLRequest::PriorityHigh:
140 case blink::WebURLRequest::PriorityVeryHigh:
142 case blink::WebURLRequest::PriorityUnresolved:
148 void BlockRequest(blink::WebURLRequest& request) {
149 request.setURL(GURL("255.255.255.255"));
152 bool IsLocalHost(const std::string& host) {
153 return host == "127.0.0.1" || host == "localhost";
156 bool HostIsUsedBySomeTestsToGenerateError(const std::string& host) {
157 return host == "255.255.255.255";
160 // Used to write a platform neutral file:/// URL by only taking the filename
161 // (e.g., converts "file:///tmp/foo.txt" to just "foo.txt").
162 std::string URLSuitableForTestResult(const std::string& url) {
163 if (url.empty() || std::string::npos == url.find("file://"))
166 size_t pos = url.rfind('/');
167 if (pos == std::string::npos) {
169 pos = url.rfind('\\');
170 if (pos == std::string::npos)
176 std::string filename = url.substr(pos + 1);
177 if (filename.empty())
178 return "file:"; // A WebKit test has this in its expected output.
182 // WebNavigationType debugging strings taken from PolicyDelegate.mm.
183 const char* kLinkClickedString = "link clicked";
184 const char* kFormSubmittedString = "form submitted";
185 const char* kBackForwardString = "back/forward";
186 const char* kReloadString = "reload";
187 const char* kFormResubmittedString = "form resubmitted";
188 const char* kOtherString = "other";
189 const char* kIllegalString = "illegal value";
191 // Get a debugging string from a WebNavigationType.
192 const char* WebNavigationTypeToString(blink::WebNavigationType type) {
194 case blink::WebNavigationTypeLinkClicked:
195 return kLinkClickedString;
196 case blink::WebNavigationTypeFormSubmitted:
197 return kFormSubmittedString;
198 case blink::WebNavigationTypeBackForward:
199 return kBackForwardString;
200 case blink::WebNavigationTypeReload:
201 return kReloadString;
202 case blink::WebNavigationTypeFormResubmitted:
203 return kFormResubmittedString;
204 case blink::WebNavigationTypeOther:
207 return kIllegalString;
210 std::string DumpFrameHeaderIfNeeded(blink::WebFrame* frame) {
213 // Add header for all but the main frame. Skip empty frames.
214 if (frame->parent() && !frame->document().documentElement().isNull()) {
215 result.append("\n--------\nFrame: '");
216 result.append(frame->uniqueName().utf8().data());
217 result.append("'\n--------\n");
223 std::string DumpFramesAsMarkup(blink::WebFrame* frame, bool recursive) {
224 std::string result = DumpFrameHeaderIfNeeded(frame);
225 result.append(frame->contentAsMarkup().utf8());
229 for (blink::WebFrame* child = frame->firstChild(); child;
230 child = child->nextSibling())
231 result.append(DumpFramesAsMarkup(child, recursive));
237 std::string DumpDocumentText(blink::WebFrame* frame) {
238 // We use the document element's text instead of the body text here because
239 // not all documents have a body, such as XML documents.
240 blink::WebElement document_element = frame->document().documentElement();
241 if (document_element.isNull())
242 return std::string();
243 return document_element.innerText().utf8();
246 std::string DumpFramesAsText(blink::WebFrame* frame, bool recursive) {
247 std::string result = DumpFrameHeaderIfNeeded(frame);
248 result.append(DumpDocumentText(frame));
252 for (blink::WebFrame* child = frame->firstChild(); child;
253 child = child->nextSibling())
254 result.append(DumpFramesAsText(child, recursive));
260 std::string DumpFramesAsPrintedText(blink::WebFrame* frame, bool recursive) {
261 // Cannot do printed format for anything other than HTML
262 if (!frame->document().isHTMLDocument())
263 return std::string();
265 std::string result = DumpFrameHeaderIfNeeded(frame);
267 frame->renderTreeAsText(blink::WebFrame::RenderAsTextPrinting).utf8());
271 for (blink::WebFrame* child = frame->firstChild(); child;
272 child = child->nextSibling())
273 result.append(DumpFramesAsPrintedText(child, recursive));
279 std::string DumpFrameScrollPosition(blink::WebFrame* frame, bool recursive) {
281 blink::WebSize offset = frame->scrollOffset();
282 if (offset.width > 0 || offset.height > 0) {
283 if (frame->parent()) {
285 std::string("frame '") + frame->uniqueName().utf8().data() + "' ";
288 &result, "scrolled to %d,%d\n", offset.width, offset.height);
293 for (blink::WebFrame* child = frame->firstChild(); child;
294 child = child->nextSibling())
295 result += DumpFrameScrollPosition(child, recursive);
299 std::string DumpAllBackForwardLists(TestInterfaces* interfaces,
300 WebTestDelegate* delegate) {
302 const std::vector<WebTestProxyBase*>& window_list =
303 interfaces->GetWindowList();
304 for (size_t i = 0; i < window_list.size(); ++i)
305 result.append(delegate->dumpHistoryForWindow(window_list.at(i)));
310 WebTestProxyBase::WebTestProxyBase()
311 : test_interfaces_(NULL),
314 spellcheck_(new SpellCheckClient(this)),
319 WebTestProxyBase::~WebTestProxyBase() {
320 test_interfaces_->WindowClosed(this);
321 // Tests must wait for readback requests to finish before notifying that
323 CHECK_EQ(0u, composite_and_readback_callbacks_.size());
326 void WebTestProxyBase::SetInterfaces(WebTestInterfaces* interfaces) {
327 test_interfaces_ = interfaces->testInterfaces();
328 test_interfaces_->WindowOpened(this);
331 void WebTestProxyBase::SetDelegate(WebTestDelegate* delegate) {
332 delegate_ = delegate;
333 spellcheck_->SetDelegate(delegate);
334 if (speech_recognizer_.get())
335 speech_recognizer_->SetDelegate(delegate);
338 blink::WebView* WebTestProxyBase::GetWebView() const {
340 // TestRunner does not support popup widgets. So |web_widget|_ is always a
342 return static_cast<blink::WebView*>(web_widget_);
345 void WebTestProxyBase::Reset() {
346 animate_scheduled_ = false;
347 resource_identifier_map_.clear();
348 log_console_output_ = true;
349 if (midi_client_.get())
350 midi_client_->resetMock();
351 accept_languages_ = "";
354 blink::WebSpellCheckClient* WebTestProxyBase::GetSpellCheckClient() const {
355 return spellcheck_.get();
358 blink::WebColorChooser* WebTestProxyBase::CreateColorChooser(
359 blink::WebColorChooserClient* client,
360 const blink::WebColor& color,
361 const blink::WebVector<blink::WebColorSuggestion>& suggestions) {
362 // This instance is deleted by WebCore::ColorInputType
363 return new MockColorChooser(client, delegate_, this);
366 bool WebTestProxyBase::RunFileChooser(
367 const blink::WebFileChooserParams& params,
368 blink::WebFileChooserCompletion* completion) {
369 delegate_->printMessage("Mock: Opening a file chooser.\n");
370 // FIXME: Add ability to set file names to a file upload control.
374 void WebTestProxyBase::ShowValidationMessage(
375 const blink::WebRect& anchor_in_root_view,
376 const blink::WebString& message,
377 const blink::WebString& sub_message,
378 blink::WebTextDirection hint) {
379 delegate_->printMessage(
380 std::string("ValidationMessageClient: main-message=") +
381 std::string(message.utf8()) + " sub-message=" +
382 std::string(sub_message.utf8()) + "\n");
385 std::string WebTestProxyBase::CaptureTree(bool debug_render_tree) {
386 bool should_dump_custom_text =
387 test_interfaces_->GetTestRunner()->shouldDumpAsCustomText();
388 bool should_dump_as_text =
389 test_interfaces_->GetTestRunner()->shouldDumpAsText();
390 bool should_dump_as_markup =
391 test_interfaces_->GetTestRunner()->shouldDumpAsMarkup();
392 bool should_dump_as_printed = test_interfaces_->GetTestRunner()->isPrinting();
393 blink::WebFrame* frame = GetWebView()->mainFrame();
394 std::string data_utf8;
395 if (should_dump_custom_text) {
396 // Append a newline for the test driver.
397 data_utf8 = test_interfaces_->GetTestRunner()->customDumpText() + "\n";
398 } else if (should_dump_as_text) {
400 test_interfaces_->GetTestRunner()->shouldDumpChildFramesAsText();
401 data_utf8 = should_dump_as_printed ?
402 DumpFramesAsPrintedText(frame, recursive) :
403 DumpFramesAsText(frame, recursive);
404 } else if (should_dump_as_markup) {
406 test_interfaces_->GetTestRunner()->shouldDumpChildFramesAsMarkup();
407 // Append a newline for the test driver.
408 data_utf8 = DumpFramesAsMarkup(frame, recursive);
410 bool recursive = test_interfaces_->GetTestRunner()
411 ->shouldDumpChildFrameScrollPositions();
412 blink::WebFrame::RenderAsTextControls render_text_behavior =
413 blink::WebFrame::RenderAsTextNormal;
414 if (should_dump_as_printed)
415 render_text_behavior |= blink::WebFrame::RenderAsTextPrinting;
416 if (debug_render_tree)
417 render_text_behavior |= blink::WebFrame::RenderAsTextDebug;
418 data_utf8 = frame->renderTreeAsText(render_text_behavior).utf8();
419 data_utf8 += DumpFrameScrollPosition(frame, recursive);
422 if (test_interfaces_->GetTestRunner()->ShouldDumpBackForwardList())
423 data_utf8 += DumpAllBackForwardLists(test_interfaces_, delegate_);
428 void WebTestProxyBase::DrawSelectionRect(SkCanvas* canvas) {
429 // See if we need to draw the selection bounds rect. Selection bounds
430 // rect is the rect enclosing the (possibly transformed) selection.
431 // The rect should be drawn after everything is laid out and painted.
432 if (!test_interfaces_->GetTestRunner()->shouldDumpSelectionRect())
434 // If there is a selection rect - draw a red 1px border enclosing rect
435 blink::WebRect wr = GetWebView()->mainFrame()->selectionBoundsRect();
438 // Render a red rectangle bounding selection rect
440 paint.setColor(0xFFFF0000); // Fully opaque red
441 paint.setStyle(SkPaint::kStroke_Style);
442 paint.setFlags(SkPaint::kAntiAlias_Flag);
443 paint.setStrokeWidth(1.0f);
444 SkIRect rect; // Bounding rect
445 rect.set(wr.x, wr.y, wr.x + wr.width, wr.y + wr.height);
446 canvas->drawIRect(rect, paint);
449 void WebTestProxyBase::didCompositeAndReadback(const SkBitmap& bitmap) {
450 TRACE_EVENT2("shell",
451 "WebTestProxyBase::didCompositeAndReadback",
453 bitmap.info().fWidth,
455 bitmap.info().fHeight);
456 SkCanvas canvas(bitmap);
457 DrawSelectionRect(&canvas);
458 DCHECK(!composite_and_readback_callbacks_.empty());
459 composite_and_readback_callbacks_.front().Run(bitmap);
460 composite_and_readback_callbacks_.pop_front();
463 void WebTestProxyBase::SetAcceptLanguages(const std::string& accept_languages) {
464 bool notify = accept_languages_ != accept_languages;
465 accept_languages_ = accept_languages;
468 GetWebView()->acceptLanguagesChanged();
471 void WebTestProxyBase::CopyImageAtAndCapturePixels(
472 int x, int y, const base::Callback<void(const SkBitmap&)>& callback) {
473 DCHECK(web_widget_->isAcceleratedCompositingActive());
474 DCHECK(!callback.is_null());
475 uint64_t sequence_number = blink::Platform::current()->clipboard()->
476 sequenceNumber(blink::WebClipboard::Buffer());
477 GetWebView()->copyImageAt(blink::WebPoint(x, y));
478 if (sequence_number == blink::Platform::current()->clipboard()->
479 sequenceNumber(blink::WebClipboard::Buffer())) {
480 SkBitmap emptyBitmap;
481 callback.Run(emptyBitmap);
485 blink::WebData data = blink::Platform::current()->clipboard()->readImage(
486 blink::WebClipboard::Buffer());
487 blink::WebImage image = blink::WebImage::fromData(data, blink::WebSize());
488 const SkBitmap& bitmap = image.getSkBitmap();
489 SkAutoLockPixels autoLock(bitmap);
490 callback.Run(bitmap);
493 void WebTestProxyBase::CapturePixelsForPrinting(
494 const base::Callback<void(const SkBitmap&)>& callback) {
495 web_widget_->layout();
497 blink::WebSize page_size_in_pixels = web_widget_->size();
498 blink::WebFrame* web_frame = GetWebView()->mainFrame();
500 int page_count = web_frame->printBegin(page_size_in_pixels);
501 int totalHeight = page_count * (page_size_in_pixels.height + 1) - 1;
503 bool is_opaque = false;
504 skia::RefPtr<SkCanvas> canvas(skia::AdoptRef(skia::TryCreateBitmapCanvas(
505 page_size_in_pixels.width, totalHeight, is_opaque)));
507 callback.Run(SkBitmap());
510 web_frame->printPagesWithBoundaries(canvas.get(), page_size_in_pixels);
511 web_frame->printEnd();
513 DrawSelectionRect(canvas.get());
514 SkBaseDevice* device = skia::GetTopDevice(*canvas);
515 const SkBitmap& bitmap = device->accessBitmap(false);
516 callback.Run(bitmap);
519 void WebTestProxyBase::CapturePixelsAsync(
520 const base::Callback<void(const SkBitmap&)>& callback) {
521 TRACE_EVENT0("shell", "WebTestProxyBase::CapturePixelsAsync");
523 DCHECK(web_widget_->isAcceleratedCompositingActive());
524 DCHECK(!callback.is_null());
526 if (test_interfaces_->GetTestRunner()->isPrinting()) {
527 base::MessageLoopProxy::current()->PostTask(
529 base::Bind(&WebTestProxyBase::CapturePixelsForPrinting,
530 base::Unretained(this),
535 composite_and_readback_callbacks_.push_back(callback);
536 web_widget_->compositeAndReadbackAsync(this);
539 void WebTestProxyBase::SetLogConsoleOutput(bool enabled) {
540 log_console_output_ = enabled;
543 void WebTestProxyBase::DidDisplayAsync(const base::Closure& callback,
544 const SkBitmap& bitmap) {
545 // Verify we actually composited.
546 CHECK_NE(0, bitmap.info().fWidth);
547 CHECK_NE(0, bitmap.info().fHeight);
548 if (!callback.is_null())
552 void WebTestProxyBase::DisplayAsyncThen(const base::Closure& callback) {
553 TRACE_EVENT0("shell", "WebTestProxyBase::DisplayAsyncThen");
555 CHECK(web_widget_->isAcceleratedCompositingActive());
556 CapturePixelsAsync(base::Bind(
557 &WebTestProxyBase::DidDisplayAsync, base::Unretained(this), callback));
560 void WebTestProxyBase::GetScreenOrientationForTesting(
561 blink::WebScreenInfo& screen_info) {
562 if (!screen_orientation_client_)
564 // Override screen orientation information with mock data.
565 screen_info.orientationType =
566 screen_orientation_client_->CurrentOrientationType();
567 screen_info.orientationAngle =
568 screen_orientation_client_->CurrentOrientationAngle();
571 MockScreenOrientationClient*
572 WebTestProxyBase::GetScreenOrientationClientMock() {
573 if (!screen_orientation_client_.get()) {
574 screen_orientation_client_.reset(new MockScreenOrientationClient);
576 return screen_orientation_client_.get();
579 blink::WebMIDIClientMock* WebTestProxyBase::GetMIDIClientMock() {
580 if (!midi_client_.get())
581 midi_client_.reset(new blink::WebMIDIClientMock);
582 return midi_client_.get();
585 MockWebSpeechRecognizer* WebTestProxyBase::GetSpeechRecognizerMock() {
586 if (!speech_recognizer_.get()) {
587 speech_recognizer_.reset(new MockWebSpeechRecognizer());
588 speech_recognizer_->SetDelegate(delegate_);
590 return speech_recognizer_.get();
593 void WebTestProxyBase::ScheduleAnimation() {
594 if (!test_interfaces_->GetTestRunner()->TestIsRunning())
597 if (!animate_scheduled_) {
598 animate_scheduled_ = true;
599 delegate_->postDelayedTask(
600 new HostMethodTask(this, &WebTestProxyBase::AnimateNow), 1);
604 void WebTestProxyBase::AnimateNow() {
605 if (animate_scheduled_) {
606 animate_scheduled_ = false;
607 web_widget_->animate(0.0);
608 web_widget_->layout();
612 void WebTestProxyBase::PostAccessibilityEvent(const blink::WebAXObject& obj,
613 blink::WebAXEvent event) {
614 // Only hook the accessibility events occured during the test run.
615 // This check prevents false positives in WebLeakDetector.
616 // The pending tasks in browser/renderer message queue may trigger
617 // accessibility events,
618 // and AccessibilityController will hold on to their target nodes if we don't
620 if (!test_interfaces_->GetTestRunner()->TestIsRunning())
623 if (event == blink::WebAXEventFocus)
624 test_interfaces_->GetAccessibilityController()->SetFocusedElement(obj);
626 const char* event_name = NULL;
628 case blink::WebAXEventActiveDescendantChanged:
629 event_name = "ActiveDescendantChanged";
631 case blink::WebAXEventAlert:
632 event_name = "Alert";
634 case blink::WebAXEventAriaAttributeChanged:
635 event_name = "AriaAttributeChanged";
637 case blink::WebAXEventAutocorrectionOccured:
638 event_name = "AutocorrectionOccured";
640 case blink::WebAXEventBlur:
643 case blink::WebAXEventCheckedStateChanged:
644 event_name = "CheckedStateChanged";
646 case blink::WebAXEventChildrenChanged:
647 event_name = "ChildrenChanged";
649 case blink::WebAXEventFocus:
650 event_name = "Focus";
652 case blink::WebAXEventHide:
655 case blink::WebAXEventInvalidStatusChanged:
656 event_name = "InvalidStatusChanged";
658 case blink::WebAXEventLayoutComplete:
659 event_name = "LayoutComplete";
661 case blink::WebAXEventLiveRegionChanged:
662 event_name = "LiveRegionChanged";
664 case blink::WebAXEventLoadComplete:
665 event_name = "LoadComplete";
667 case blink::WebAXEventLocationChanged:
668 event_name = "LocationChanged";
670 case blink::WebAXEventMenuListItemSelected:
671 event_name = "MenuListItemSelected";
673 case blink::WebAXEventMenuListValueChanged:
674 event_name = "MenuListValueChanged";
676 case blink::WebAXEventRowCollapsed:
677 event_name = "RowCollapsed";
679 case blink::WebAXEventRowCountChanged:
680 event_name = "RowCountChanged";
682 case blink::WebAXEventRowExpanded:
683 event_name = "RowExpanded";
685 case blink::WebAXEventScrollPositionChanged:
686 event_name = "ScrollPositionChanged";
688 case blink::WebAXEventScrolledToAnchor:
689 event_name = "ScrolledToAnchor";
691 case blink::WebAXEventSelectedChildrenChanged:
692 event_name = "SelectedChildrenChanged";
694 case blink::WebAXEventSelectedTextChanged:
695 event_name = "SelectedTextChanged";
697 case blink::WebAXEventShow:
700 case blink::WebAXEventTextChanged:
701 event_name = "TextChanged";
703 case blink::WebAXEventTextInserted:
704 event_name = "TextInserted";
706 case blink::WebAXEventTextRemoved:
707 event_name = "TextRemoved";
709 case blink::WebAXEventValueChanged:
710 event_name = "ValueChanged";
713 event_name = "Unknown";
717 test_interfaces_->GetAccessibilityController()->NotificationReceived(
720 if (test_interfaces_->GetAccessibilityController()
721 ->ShouldLogAccessibilityEvents()) {
722 std::string message("AccessibilityNotification - ");
723 message += event_name;
725 blink::WebNode node = obj.node();
726 if (!node.isNull() && node.isElementNode()) {
727 blink::WebElement element = node.to<blink::WebElement>();
728 if (element.hasAttribute("id")) {
730 message += element.getAttribute("id").utf8().data();
734 delegate_->printMessage(message + "\n");
738 void WebTestProxyBase::StartDragging(blink::WebLocalFrame* frame,
739 const blink::WebDragData& data,
740 blink::WebDragOperationsMask mask,
741 const blink::WebImage& image,
742 const blink::WebPoint& point) {
743 // When running a test, we need to fake a drag drop operation otherwise
744 // Windows waits for real mouse events to know when the drag is over.
745 test_interfaces_->GetEventSender()->DoDragDrop(data, mask);
748 // The output from these methods in layout test mode should match that
749 // expected by the layout tests. See EditingDelegate.m in DumpRenderTree.
751 void WebTestProxyBase::DidChangeSelection(bool is_empty_callback) {
752 if (test_interfaces_->GetTestRunner()->shouldDumpEditingCallbacks())
753 delegate_->printMessage(
755 "webViewDidChangeSelection:WebViewDidChangeSelectionNotification\n");
758 void WebTestProxyBase::DidChangeContents() {
759 if (test_interfaces_->GetTestRunner()->shouldDumpEditingCallbacks())
760 delegate_->printMessage(
761 "EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification\n");
764 bool WebTestProxyBase::CreateView(blink::WebLocalFrame* frame,
765 const blink::WebURLRequest& request,
766 const blink::WebWindowFeatures& features,
767 const blink::WebString& frame_name,
768 blink::WebNavigationPolicy policy,
769 bool suppress_opener) {
770 if (!test_interfaces_->GetTestRunner()->canOpenWindows())
772 if (test_interfaces_->GetTestRunner()->shouldDumpCreateView())
773 delegate_->printMessage(std::string("createView(") +
774 URLDescription(request.url()) + ")\n");
778 blink::WebPlugin* WebTestProxyBase::CreatePlugin(
779 blink::WebLocalFrame* frame,
780 const blink::WebPluginParams& params) {
781 if (TestPlugin::isSupportedMimeType(params.mimeType))
782 return TestPlugin::create(frame, params, delegate_);
786 void WebTestProxyBase::SetStatusText(const blink::WebString& text) {
787 if (!test_interfaces_->GetTestRunner()->shouldDumpStatusCallbacks())
789 delegate_->printMessage(
790 std::string("UI DELEGATE STATUS CALLBACK: setStatusText:") +
791 text.utf8().data() + "\n");
794 void WebTestProxyBase::DidStopLoading() {
795 if (test_interfaces_->GetTestRunner()->shouldDumpProgressFinishedCallback())
796 delegate_->printMessage("postProgressFinishedNotification\n");
799 void WebTestProxyBase::ShowContextMenu(
800 blink::WebLocalFrame* frame,
801 const blink::WebContextMenuData& context_menu_data) {
802 test_interfaces_->GetEventSender()->SetContextMenuData(context_menu_data);
805 blink::WebUserMediaClient* WebTestProxyBase::GetUserMediaClient() {
806 if (!user_media_client_.get())
807 user_media_client_.reset(new MockWebUserMediaClient(delegate_));
808 return user_media_client_.get();
811 // Simulate a print by going into print mode and then exit straight away.
812 void WebTestProxyBase::PrintPage(blink::WebLocalFrame* frame) {
813 blink::WebSize page_size_in_pixels = web_widget_->size();
814 if (page_size_in_pixels.isEmpty())
816 blink::WebPrintParams printParams(page_size_in_pixels);
817 frame->printBegin(printParams);
821 blink::WebNotificationPresenter* WebTestProxyBase::GetNotificationPresenter() {
822 return test_interfaces_->GetTestRunner()->notification_presenter();
825 blink::WebMIDIClient* WebTestProxyBase::GetWebMIDIClient() {
826 return GetMIDIClientMock();
829 blink::WebSpeechRecognizer* WebTestProxyBase::GetSpeechRecognizer() {
830 return GetSpeechRecognizerMock();
833 bool WebTestProxyBase::RequestPointerLock() {
834 return test_interfaces_->GetTestRunner()->RequestPointerLock();
837 void WebTestProxyBase::RequestPointerUnlock() {
838 test_interfaces_->GetTestRunner()->RequestPointerUnlock();
841 bool WebTestProxyBase::IsPointerLocked() {
842 return test_interfaces_->GetTestRunner()->isPointerLocked();
845 void WebTestProxyBase::DidFocus() {
846 delegate_->setFocus(this, true);
849 void WebTestProxyBase::DidBlur() {
850 delegate_->setFocus(this, false);
853 void WebTestProxyBase::SetToolTipText(const blink::WebString& text,
854 blink::WebTextDirection direction) {
855 test_interfaces_->GetTestRunner()->setToolTipText(text);
858 void WebTestProxyBase::DidOpenChooser() {
862 void WebTestProxyBase::DidCloseChooser() {
866 bool WebTestProxyBase::IsChooserShown() {
867 return 0 < chooser_count_;
870 void WebTestProxyBase::LoadURLExternally(
871 blink::WebLocalFrame* frame,
872 const blink::WebURLRequest& request,
873 blink::WebNavigationPolicy policy,
874 const blink::WebString& suggested_name) {
875 if (test_interfaces_->GetTestRunner()->shouldWaitUntilExternalURLLoad()) {
876 if (policy == blink::WebNavigationPolicyDownload) {
877 delegate_->printMessage(
878 std::string("Downloading URL with suggested filename \"") +
879 suggested_name.utf8() + "\"\n");
881 delegate_->printMessage(std::string("Loading URL externally - \"") +
882 URLDescription(request.url()) + "\"\n");
884 delegate_->testFinished();
888 void WebTestProxyBase::DidStartProvisionalLoad(blink::WebLocalFrame* frame) {
889 if (!test_interfaces_->GetTestRunner()->topLoadingFrame())
890 test_interfaces_->GetTestRunner()->setTopLoadingFrame(frame, false);
892 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
893 PrintFrameDescription(delegate_, frame);
894 delegate_->printMessage(" - didStartProvisionalLoadForFrame\n");
897 if (test_interfaces_->GetTestRunner()
898 ->shouldDumpUserGestureInFrameLoadCallbacks()) {
899 PrintFrameuserGestureStatus(
900 delegate_, frame, " - in didStartProvisionalLoadForFrame\n");
904 void WebTestProxyBase::DidReceiveServerRedirectForProvisionalLoad(
905 blink::WebLocalFrame* frame) {
906 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
907 PrintFrameDescription(delegate_, frame);
908 delegate_->printMessage(
909 " - didReceiveServerRedirectForProvisionalLoadForFrame\n");
913 bool WebTestProxyBase::DidFailProvisionalLoad(blink::WebLocalFrame* frame,
914 const blink::WebURLError& error) {
915 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
916 PrintFrameDescription(delegate_, frame);
917 delegate_->printMessage(" - didFailProvisionalLoadWithError\n");
919 LocationChangeDone(frame);
920 return !frame->provisionalDataSource();
923 void WebTestProxyBase::DidCommitProvisionalLoad(
924 blink::WebLocalFrame* frame,
925 const blink::WebHistoryItem& history_item,
926 blink::WebHistoryCommitType history_type) {
927 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
928 PrintFrameDescription(delegate_, frame);
929 delegate_->printMessage(" - didCommitLoadForFrame\n");
933 void WebTestProxyBase::DidReceiveTitle(blink::WebLocalFrame* frame,
934 const blink::WebString& title,
935 blink::WebTextDirection direction) {
936 blink::WebCString title8 = title.utf8();
938 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
939 PrintFrameDescription(delegate_, frame);
940 delegate_->printMessage(std::string(" - didReceiveTitle: ") +
941 title8.data() + "\n");
944 if (test_interfaces_->GetTestRunner()->shouldDumpTitleChanges())
945 delegate_->printMessage(std::string("TITLE CHANGED: '") + title8.data() +
949 void WebTestProxyBase::DidChangeIcon(blink::WebLocalFrame* frame,
950 blink::WebIconURL::Type icon_type) {
951 if (test_interfaces_->GetTestRunner()->shouldDumpIconChanges()) {
952 PrintFrameDescription(delegate_, frame);
953 delegate_->printMessage(std::string(" - didChangeIcons\n"));
957 void WebTestProxyBase::DidFinishDocumentLoad(blink::WebLocalFrame* frame) {
958 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
959 PrintFrameDescription(delegate_, frame);
960 delegate_->printMessage(" - didFinishDocumentLoadForFrame\n");
962 unsigned pendingUnloadEvents = frame->unloadListenerCount();
963 if (pendingUnloadEvents) {
964 PrintFrameDescription(delegate_, frame);
965 delegate_->printMessage(base::StringPrintf(
966 " - has %u onunload handler(s)\n", pendingUnloadEvents));
971 void WebTestProxyBase::DidHandleOnloadEvents(blink::WebLocalFrame* frame) {
972 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
973 PrintFrameDescription(delegate_, frame);
974 delegate_->printMessage(" - didHandleOnloadEventsForFrame\n");
978 void WebTestProxyBase::DidFailLoad(blink::WebLocalFrame* frame,
979 const blink::WebURLError& error) {
980 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
981 PrintFrameDescription(delegate_, frame);
982 delegate_->printMessage(" - didFailLoadWithError\n");
984 LocationChangeDone(frame);
987 void WebTestProxyBase::DidFinishLoad(blink::WebLocalFrame* frame) {
988 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
989 PrintFrameDescription(delegate_, frame);
990 delegate_->printMessage(" - didFinishLoadForFrame\n");
992 LocationChangeDone(frame);
995 void WebTestProxyBase::DidDetectXSS(blink::WebLocalFrame* frame,
996 const blink::WebURL& insecure_url,
997 bool did_block_entire_page) {
998 if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks())
999 delegate_->printMessage("didDetectXSS\n");
1002 void WebTestProxyBase::DidDispatchPingLoader(blink::WebLocalFrame* frame,
1003 const blink::WebURL& url) {
1004 if (test_interfaces_->GetTestRunner()->shouldDumpPingLoaderCallbacks())
1005 delegate_->printMessage(std::string("PingLoader dispatched to '") +
1006 URLDescription(url).c_str() + "'.\n");
1009 void WebTestProxyBase::WillRequestResource(
1010 blink::WebLocalFrame* frame,
1011 const blink::WebCachedURLRequest& request) {
1012 if (test_interfaces_->GetTestRunner()->shouldDumpResourceRequestCallbacks()) {
1013 PrintFrameDescription(delegate_, frame);
1014 delegate_->printMessage(std::string(" - ") +
1015 request.initiatorName().utf8().data());
1016 delegate_->printMessage(std::string(" requested '") +
1017 URLDescription(request.urlRequest().url()).c_str() +
1022 void WebTestProxyBase::WillSendRequest(
1023 blink::WebLocalFrame* frame,
1024 unsigned identifier,
1025 blink::WebURLRequest& request,
1026 const blink::WebURLResponse& redirect_response) {
1027 // Need to use GURL for host() and SchemeIs()
1028 GURL url = request.url();
1029 std::string request_url = url.possibly_invalid_spec();
1031 GURL main_document_url = request.firstPartyForCookies();
1033 if (redirect_response.isNull() &&
1034 (test_interfaces_->GetTestRunner()->shouldDumpResourceLoadCallbacks() ||
1035 test_interfaces_->GetTestRunner()->shouldDumpResourcePriorities())) {
1036 DCHECK(resource_identifier_map_.find(identifier) ==
1037 resource_identifier_map_.end());
1038 resource_identifier_map_[identifier] =
1039 DescriptionSuitableForTestResult(request_url);
1042 if (test_interfaces_->GetTestRunner()->shouldDumpResourceLoadCallbacks()) {
1043 if (resource_identifier_map_.find(identifier) ==
1044 resource_identifier_map_.end())
1045 delegate_->printMessage("<unknown>");
1047 delegate_->printMessage(resource_identifier_map_[identifier]);
1048 delegate_->printMessage(" - willSendRequest <NSURLRequest URL ");
1049 delegate_->printMessage(
1050 DescriptionSuitableForTestResult(request_url).c_str());
1051 delegate_->printMessage(", main document URL ");
1052 delegate_->printMessage(URLDescription(main_document_url).c_str());
1053 delegate_->printMessage(", http method ");
1054 delegate_->printMessage(request.httpMethod().utf8().data());
1055 delegate_->printMessage("> redirectResponse ");
1056 PrintResponseDescription(delegate_, redirect_response);
1057 delegate_->printMessage("\n");
1060 if (test_interfaces_->GetTestRunner()->shouldDumpResourcePriorities()) {
1061 delegate_->printMessage(
1062 DescriptionSuitableForTestResult(request_url).c_str());
1063 delegate_->printMessage(" has priority ");
1064 delegate_->printMessage(PriorityDescription(request.priority()));
1065 delegate_->printMessage("\n");
1068 if (test_interfaces_->GetTestRunner()->httpHeadersToClear()) {
1069 const std::set<std::string>* clearHeaders =
1070 test_interfaces_->GetTestRunner()->httpHeadersToClear();
1071 for (std::set<std::string>::const_iterator header = clearHeaders->begin();
1072 header != clearHeaders->end();
1074 request.clearHTTPHeaderField(blink::WebString::fromUTF8(*header));
1077 std::string host = url.host();
1078 if (!host.empty() && (url.SchemeIs("http") || url.SchemeIs("https"))) {
1079 if (!IsLocalHost(host) && !HostIsUsedBySomeTestsToGenerateError(host) &&
1080 ((!main_document_url.SchemeIs("http") &&
1081 !main_document_url.SchemeIs("https")) ||
1082 IsLocalHost(main_document_url.host())) &&
1083 !delegate_->allowExternalPages()) {
1084 delegate_->printMessage(std::string("Blocked access to external URL ") +
1085 request_url + "\n");
1086 BlockRequest(request);
1091 // Set the new substituted URL.
1092 request.setURL(delegate_->rewriteLayoutTestsURL(request.url().spec()));
1095 void WebTestProxyBase::DidReceiveResponse(
1096 blink::WebLocalFrame* frame,
1097 unsigned identifier,
1098 const blink::WebURLResponse& response) {
1099 if (test_interfaces_->GetTestRunner()->shouldDumpResourceLoadCallbacks()) {
1100 if (resource_identifier_map_.find(identifier) ==
1101 resource_identifier_map_.end())
1102 delegate_->printMessage("<unknown>");
1104 delegate_->printMessage(resource_identifier_map_[identifier]);
1105 delegate_->printMessage(" - didReceiveResponse ");
1106 PrintResponseDescription(delegate_, response);
1107 delegate_->printMessage("\n");
1109 if (test_interfaces_->GetTestRunner()
1110 ->shouldDumpResourceResponseMIMETypes()) {
1111 GURL url = response.url();
1112 blink::WebString mime_type = response.mimeType();
1113 delegate_->printMessage(url.ExtractFileName());
1114 delegate_->printMessage(" has MIME type ");
1115 // Simulate NSURLResponse's mapping of empty/unknown MIME types to
1116 // application/octet-stream
1117 delegate_->printMessage(mime_type.isEmpty() ? "application/octet-stream"
1118 : mime_type.utf8().data());
1119 delegate_->printMessage("\n");
1123 void WebTestProxyBase::DidChangeResourcePriority(
1124 blink::WebLocalFrame* frame,
1125 unsigned identifier,
1126 const blink::WebURLRequest::Priority& priority,
1127 int intra_priority_value) {
1128 if (test_interfaces_->GetTestRunner()->shouldDumpResourcePriorities()) {
1129 if (resource_identifier_map_.find(identifier) ==
1130 resource_identifier_map_.end())
1131 delegate_->printMessage("<unknown>");
1133 delegate_->printMessage(resource_identifier_map_[identifier]);
1134 delegate_->printMessage(
1135 base::StringPrintf(" changed priority to %s, intra_priority %d\n",
1136 PriorityDescription(priority).c_str(),
1137 intra_priority_value));
1141 void WebTestProxyBase::DidFinishResourceLoad(blink::WebLocalFrame* frame,
1142 unsigned identifier) {
1143 if (test_interfaces_->GetTestRunner()->shouldDumpResourceLoadCallbacks()) {
1144 if (resource_identifier_map_.find(identifier) ==
1145 resource_identifier_map_.end())
1146 delegate_->printMessage("<unknown>");
1148 delegate_->printMessage(resource_identifier_map_[identifier]);
1149 delegate_->printMessage(" - didFinishLoading\n");
1151 resource_identifier_map_.erase(identifier);
1154 void WebTestProxyBase::DidAddMessageToConsole(
1155 const blink::WebConsoleMessage& message,
1156 const blink::WebString& source_name,
1157 unsigned source_line) {
1158 // This matches win DumpRenderTree's UIDelegate.cpp.
1159 if (!log_console_output_)
1162 switch (message.level) {
1163 case blink::WebConsoleMessage::LevelDebug:
1166 case blink::WebConsoleMessage::LevelLog:
1169 case blink::WebConsoleMessage::LevelInfo:
1172 case blink::WebConsoleMessage::LevelWarning:
1175 case blink::WebConsoleMessage::LevelError:
1179 delegate_->printMessage(std::string("CONSOLE ") + level + ": ");
1181 delegate_->printMessage(base::StringPrintf("line %d: ", source_line));
1183 if (!message.text.isEmpty()) {
1184 std::string new_message;
1185 new_message = message.text.utf8();
1186 size_t file_protocol = new_message.find("file://");
1187 if (file_protocol != std::string::npos) {
1188 new_message = new_message.substr(0, file_protocol) +
1189 URLSuitableForTestResult(new_message.substr(file_protocol));
1191 delegate_->printMessage(new_message);
1193 delegate_->printMessage(std::string("\n"));
1196 void WebTestProxyBase::LocationChangeDone(blink::WebFrame* frame) {
1197 if (frame != test_interfaces_->GetTestRunner()->topLoadingFrame())
1199 test_interfaces_->GetTestRunner()->setTopLoadingFrame(frame, true);
1202 blink::WebNavigationPolicy WebTestProxyBase::DecidePolicyForNavigation(
1203 const blink::WebFrameClient::NavigationPolicyInfo& info) {
1204 blink::WebNavigationPolicy result;
1205 if (!test_interfaces_->GetTestRunner()->policyDelegateEnabled())
1206 return info.defaultPolicy;
1208 delegate_->printMessage(std::string("Policy delegate: attempt to load ") +
1209 URLDescription(info.urlRequest.url()) +
1210 " with navigation type '" +
1211 WebNavigationTypeToString(info.navigationType) + "'\n");
1212 if (test_interfaces_->GetTestRunner()->policyDelegateIsPermissive())
1213 result = blink::WebNavigationPolicyCurrentTab;
1215 result = blink::WebNavigationPolicyIgnore;
1217 if (test_interfaces_->GetTestRunner()->policyDelegateShouldNotifyDone())
1218 test_interfaces_->GetTestRunner()->policyDelegateDone();
1222 bool WebTestProxyBase::WillCheckAndDispatchMessageEvent(
1223 blink::WebLocalFrame* source_frame,
1224 blink::WebFrame* target_frame,
1225 blink::WebSecurityOrigin target,
1226 blink::WebDOMMessageEvent event) {
1227 if (test_interfaces_->GetTestRunner()->shouldInterceptPostMessage()) {
1228 delegate_->printMessage("intercepted postMessage\n");
1235 void WebTestProxyBase::PostSpellCheckEvent(const blink::WebString& event_name) {
1236 if (test_interfaces_->GetTestRunner()->shouldDumpSpellCheckCallbacks()) {
1237 delegate_->printMessage(std::string("SpellCheckEvent: ") +
1238 event_name.utf8().data() + "\n");
1242 void WebTestProxyBase::ResetInputMethod() {
1243 // If a composition text exists, then we need to let the browser process
1244 // to cancel the input method's ongoing composition session.
1246 web_widget_->confirmComposition();
1249 blink::WebString WebTestProxyBase::acceptLanguages() {
1250 return blink::WebString::fromUTF8(accept_languages_);
1253 MockWebPushClient* WebTestProxyBase::GetPushClientMock() {
1254 if (!push_client_.get())
1255 push_client_.reset(new MockWebPushClient);
1256 return push_client_.get();
1259 blink::WebPushClient* WebTestProxyBase::GetWebPushClient() {
1260 return GetPushClientMock();
1263 } // namespace content