Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / shell / renderer / test_runner / web_test_proxy.cc
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   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   DCHECK(!callback.is_null());
490   uint64_t sequence_number =  blink::Platform::current()->clipboard()->
491       sequenceNumber(blink::WebClipboard::Buffer());
492   GetWebView()->copyImageAt(blink::WebPoint(x, y));
493   if (sequence_number == blink::Platform::current()->clipboard()->
494       sequenceNumber(blink::WebClipboard::Buffer())) {
495     SkBitmap emptyBitmap;
496     callback.Run(emptyBitmap);
497     return;
498   }
499
500   blink::WebData data = blink::Platform::current()->clipboard()->readImage(
501       blink::WebClipboard::Buffer());
502   blink::WebImage image = blink::WebImage::fromData(data, blink::WebSize());
503   const SkBitmap& bitmap = image.getSkBitmap();
504   SkAutoLockPixels autoLock(bitmap);
505   callback.Run(bitmap);
506 }
507
508 void WebTestProxyBase::CapturePixelsForPrinting(
509     const base::Callback<void(const SkBitmap&)>& callback) {
510   web_widget_->layout();
511
512   blink::WebSize page_size_in_pixels = web_widget_->size();
513   blink::WebFrame* web_frame = GetWebView()->mainFrame();
514
515   int page_count = web_frame->printBegin(page_size_in_pixels);
516   int totalHeight = page_count * (page_size_in_pixels.height + 1) - 1;
517
518   bool is_opaque = false;
519   skia::RefPtr<SkCanvas> canvas(skia::AdoptRef(skia::TryCreateBitmapCanvas(
520       page_size_in_pixels.width, totalHeight, is_opaque)));
521   if (!canvas) {
522     callback.Run(SkBitmap());
523     return;
524   }
525   web_frame->printPagesWithBoundaries(canvas.get(), page_size_in_pixels);
526   web_frame->printEnd();
527
528   DrawSelectionRect(canvas.get());
529   SkBaseDevice* device = skia::GetTopDevice(*canvas);
530   const SkBitmap& bitmap = device->accessBitmap(false);
531   callback.Run(bitmap);
532 }
533
534 CaptureCallback::CaptureCallback(
535     const base::Callback<void(const SkBitmap&)>& callback)
536     : callback_(callback), wait_for_popup_(false) {
537 }
538
539 CaptureCallback::~CaptureCallback() {
540 }
541
542 void CaptureCallback::didCompositeAndReadback(const SkBitmap& bitmap) {
543   TRACE_EVENT2("shell",
544                "CaptureCallback::didCompositeAndReadback",
545                "x",
546                bitmap.info().fWidth,
547                "y",
548                bitmap.info().fHeight);
549   if (!wait_for_popup_) {
550     callback_.Run(bitmap);
551     delete this;
552     return;
553   }
554   if (main_bitmap_.isNull()) {
555     bitmap.deepCopyTo(&main_bitmap_);
556     return;
557   }
558   SkCanvas canvas(main_bitmap_);
559   canvas.drawBitmap(bitmap, popup_position_.x(), popup_position_.y());
560   callback_.Run(main_bitmap_);
561   delete this;
562 }
563
564 void WebTestProxyBase::CapturePixelsAsync(
565     const base::Callback<void(const SkBitmap&)>& callback) {
566   TRACE_EVENT0("shell", "WebTestProxyBase::CapturePixelsAsync");
567   DCHECK(!callback.is_null());
568
569   if (test_interfaces_->GetTestRunner()->isPrinting()) {
570     base::MessageLoopProxy::current()->PostTask(
571         FROM_HERE,
572         base::Bind(&WebTestProxyBase::CapturePixelsForPrinting,
573                    base::Unretained(this),
574                    callback));
575     return;
576   }
577
578   CaptureCallback* capture_callback = new CaptureCallback(base::Bind(
579       &WebTestProxyBase::DidCapturePixelsAsync, base::Unretained(this),
580       callback));
581   web_widget_->compositeAndReadbackAsync(capture_callback);
582   if (blink::WebPagePopup* popup = web_widget_->pagePopup()) {
583     capture_callback->set_wait_for_popup(true);
584     capture_callback->set_popup_position(popup->positionRelativeToOwner());
585     popup->compositeAndReadbackAsync(capture_callback);
586   }
587 }
588
589 void WebTestProxyBase::DidCapturePixelsAsync(const base::Callback<void(const SkBitmap&)>& callback,
590                                              const SkBitmap& bitmap) {
591   SkCanvas canvas(bitmap);
592   DrawSelectionRect(&canvas);
593   if (!callback.is_null())
594     callback.Run(bitmap);
595 }
596
597 void WebTestProxyBase::SetLogConsoleOutput(bool enabled) {
598   log_console_output_ = enabled;
599 }
600
601 void WebTestProxyBase::DidDisplayAsync(const base::Closure& callback,
602                                        const SkBitmap& bitmap) {
603   // Verify we actually composited.
604   CHECK_NE(0, bitmap.info().fWidth);
605   CHECK_NE(0, bitmap.info().fHeight);
606   if (!callback.is_null())
607     callback.Run();
608 }
609
610 void WebTestProxyBase::DisplayAsyncThen(const base::Closure& callback) {
611   TRACE_EVENT0("shell", "WebTestProxyBase::DisplayAsyncThen");
612   CapturePixelsAsync(base::Bind(
613       &WebTestProxyBase::DidDisplayAsync, base::Unretained(this), callback));
614 }
615
616 void WebTestProxyBase::GetScreenOrientationForTesting(
617     blink::WebScreenInfo& screen_info) {
618   if (!screen_orientation_client_)
619     return;
620   // Override screen orientation information with mock data.
621   screen_info.orientationType =
622       screen_orientation_client_->CurrentOrientationType();
623   screen_info.orientationAngle =
624       screen_orientation_client_->CurrentOrientationAngle();
625 }
626
627 MockScreenOrientationClient*
628 WebTestProxyBase::GetScreenOrientationClientMock() {
629   if (!screen_orientation_client_.get()) {
630     screen_orientation_client_.reset(new MockScreenOrientationClient);
631   }
632   return screen_orientation_client_.get();
633 }
634
635 blink::WebMIDIClientMock* WebTestProxyBase::GetMIDIClientMock() {
636   if (!midi_client_.get())
637     midi_client_.reset(new blink::WebMIDIClientMock);
638   return midi_client_.get();
639 }
640
641 MockWebSpeechRecognizer* WebTestProxyBase::GetSpeechRecognizerMock() {
642   if (!speech_recognizer_.get()) {
643     speech_recognizer_.reset(new MockWebSpeechRecognizer());
644     speech_recognizer_->SetDelegate(delegate_);
645   }
646   return speech_recognizer_.get();
647 }
648
649 MockCredentialManagerClient*
650 WebTestProxyBase::GetCredentialManagerClientMock() {
651   if (!credential_manager_client_.get())
652     credential_manager_client_.reset(new MockCredentialManagerClient());
653   return credential_manager_client_.get();
654 }
655
656 void WebTestProxyBase::ScheduleAnimation() {
657   if (!test_interfaces_->GetTestRunner()->TestIsRunning())
658     return;
659
660   if (!animate_scheduled_) {
661     animate_scheduled_ = true;
662     delegate_->PostDelayedTask(
663         new HostMethodTask(this, &WebTestProxyBase::AnimateNow), 1);
664   }
665 }
666
667 void WebTestProxyBase::AnimateNow() {
668   if (animate_scheduled_) {
669     animate_scheduled_ = false;
670     web_widget_->animate(0.0);
671     web_widget_->layout();
672     if (blink::WebPagePopup* popup = web_widget_->pagePopup()) {
673       popup->animate(0.0);
674       popup->layout();
675     }
676   }
677 }
678
679 void WebTestProxyBase::PostAccessibilityEvent(const blink::WebAXObject& obj,
680                                               blink::WebAXEvent event) {
681   // Only hook the accessibility events occured during the test run.
682   // This check prevents false positives in WebLeakDetector.
683   // The pending tasks in browser/renderer message queue may trigger
684   // accessibility events,
685   // and AccessibilityController will hold on to their target nodes if we don't
686   // ignore them here.
687   if (!test_interfaces_->GetTestRunner()->TestIsRunning())
688     return;
689
690   if (event == blink::WebAXEventFocus)
691     test_interfaces_->GetAccessibilityController()->SetFocusedElement(obj);
692
693   const char* event_name = NULL;
694   switch (event) {
695     case blink::WebAXEventActiveDescendantChanged:
696       event_name = "ActiveDescendantChanged";
697       break;
698     case blink::WebAXEventAlert:
699       event_name = "Alert";
700       break;
701     case blink::WebAXEventAriaAttributeChanged:
702       event_name = "AriaAttributeChanged";
703       break;
704     case blink::WebAXEventAutocorrectionOccured:
705       event_name = "AutocorrectionOccured";
706       break;
707     case blink::WebAXEventBlur:
708       event_name = "Blur";
709       break;
710     case blink::WebAXEventCheckedStateChanged:
711       event_name = "CheckedStateChanged";
712       break;
713     case blink::WebAXEventChildrenChanged:
714       event_name = "ChildrenChanged";
715       break;
716     case blink::WebAXEventFocus:
717       event_name = "Focus";
718       break;
719     case blink::WebAXEventHide:
720       event_name = "Hide";
721       break;
722     case blink::WebAXEventInvalidStatusChanged:
723       event_name = "InvalidStatusChanged";
724       break;
725     case blink::WebAXEventLayoutComplete:
726       event_name = "LayoutComplete";
727       break;
728     case blink::WebAXEventLiveRegionChanged:
729       event_name = "LiveRegionChanged";
730       break;
731     case blink::WebAXEventLoadComplete:
732       event_name = "LoadComplete";
733       break;
734     case blink::WebAXEventLocationChanged:
735       event_name = "LocationChanged";
736       break;
737     case blink::WebAXEventMenuListItemSelected:
738       event_name = "MenuListItemSelected";
739       break;
740     case blink::WebAXEventMenuListValueChanged:
741       event_name = "MenuListValueChanged";
742       break;
743     case blink::WebAXEventRowCollapsed:
744       event_name = "RowCollapsed";
745       break;
746     case blink::WebAXEventRowCountChanged:
747       event_name = "RowCountChanged";
748       break;
749     case blink::WebAXEventRowExpanded:
750       event_name = "RowExpanded";
751       break;
752     case blink::WebAXEventScrollPositionChanged:
753       event_name = "ScrollPositionChanged";
754       break;
755     case blink::WebAXEventScrolledToAnchor:
756       event_name = "ScrolledToAnchor";
757       break;
758     case blink::WebAXEventSelectedChildrenChanged:
759       event_name = "SelectedChildrenChanged";
760       break;
761     case blink::WebAXEventSelectedTextChanged:
762       event_name = "SelectedTextChanged";
763       break;
764     case blink::WebAXEventShow:
765       event_name = "Show";
766       break;
767     case blink::WebAXEventTextChanged:
768       event_name = "TextChanged";
769       break;
770     case blink::WebAXEventTextInserted:
771       event_name = "TextInserted";
772       break;
773     case blink::WebAXEventTextRemoved:
774       event_name = "TextRemoved";
775       break;
776     case blink::WebAXEventValueChanged:
777       event_name = "ValueChanged";
778       break;
779     default:
780       event_name = "Unknown";
781       break;
782   }
783
784   test_interfaces_->GetAccessibilityController()->NotificationReceived(
785       obj, event_name);
786
787   if (test_interfaces_->GetAccessibilityController()
788           ->ShouldLogAccessibilityEvents()) {
789     std::string message("AccessibilityNotification - ");
790     message += event_name;
791
792     blink::WebNode node = obj.node();
793     if (!node.isNull() && node.isElementNode()) {
794       blink::WebElement element = node.to<blink::WebElement>();
795       if (element.hasAttribute("id")) {
796         message += " - id:";
797         message += element.getAttribute("id").utf8().data();
798       }
799     }
800
801     delegate_->PrintMessage(message + "\n");
802   }
803 }
804
805 void WebTestProxyBase::StartDragging(blink::WebLocalFrame* frame,
806                                      const blink::WebDragData& data,
807                                      blink::WebDragOperationsMask mask,
808                                      const blink::WebImage& image,
809                                      const blink::WebPoint& point) {
810   // When running a test, we need to fake a drag drop operation otherwise
811   // Windows waits for real mouse events to know when the drag is over.
812   test_interfaces_->GetEventSender()->DoDragDrop(data, mask);
813 }
814
815 // The output from these methods in layout test mode should match that
816 // expected by the layout tests. See EditingDelegate.m in DumpRenderTree.
817
818 void WebTestProxyBase::DidChangeSelection(bool is_empty_callback) {
819   if (test_interfaces_->GetTestRunner()->shouldDumpEditingCallbacks())
820     delegate_->PrintMessage(
821         "EDITING DELEGATE: "
822         "webViewDidChangeSelection:WebViewDidChangeSelectionNotification\n");
823 }
824
825 void WebTestProxyBase::DidChangeContents() {
826   if (test_interfaces_->GetTestRunner()->shouldDumpEditingCallbacks())
827     delegate_->PrintMessage(
828         "EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification\n");
829 }
830
831 bool WebTestProxyBase::CreateView(blink::WebLocalFrame* frame,
832                                   const blink::WebURLRequest& request,
833                                   const blink::WebWindowFeatures& features,
834                                   const blink::WebString& frame_name,
835                                   blink::WebNavigationPolicy policy,
836                                   bool suppress_opener) {
837   if (!test_interfaces_->GetTestRunner()->canOpenWindows())
838     return false;
839   if (test_interfaces_->GetTestRunner()->shouldDumpCreateView())
840     delegate_->PrintMessage(std::string("createView(") +
841                             URLDescription(request.url()) + ")\n");
842   return true;
843 }
844
845 blink::WebPlugin* WebTestProxyBase::CreatePlugin(
846     blink::WebLocalFrame* frame,
847     const blink::WebPluginParams& params) {
848   if (TestPlugin::IsSupportedMimeType(params.mimeType))
849     return TestPlugin::create(frame, params, delegate_);
850   return 0;
851 }
852
853 void WebTestProxyBase::SetStatusText(const blink::WebString& text) {
854   if (!test_interfaces_->GetTestRunner()->shouldDumpStatusCallbacks())
855     return;
856   delegate_->PrintMessage(
857       std::string("UI DELEGATE STATUS CALLBACK: setStatusText:") +
858       text.utf8().data() + "\n");
859 }
860
861 void WebTestProxyBase::DidStopLoading() {
862   if (test_interfaces_->GetTestRunner()->shouldDumpProgressFinishedCallback())
863     delegate_->PrintMessage("postProgressFinishedNotification\n");
864 }
865
866 void WebTestProxyBase::ShowContextMenu(
867     blink::WebLocalFrame* frame,
868     const blink::WebContextMenuData& context_menu_data) {
869   test_interfaces_->GetEventSender()->SetContextMenuData(context_menu_data);
870 }
871
872 blink::WebUserMediaClient* WebTestProxyBase::GetUserMediaClient() {
873   if (!user_media_client_.get())
874     user_media_client_.reset(new MockWebUserMediaClient(delegate_));
875   return user_media_client_.get();
876 }
877
878 // Simulate a print by going into print mode and then exit straight away.
879 void WebTestProxyBase::PrintPage(blink::WebLocalFrame* frame) {
880   blink::WebSize page_size_in_pixels = web_widget_->size();
881   if (page_size_in_pixels.isEmpty())
882     return;
883   blink::WebPrintParams printParams(page_size_in_pixels);
884   frame->printBegin(printParams);
885   frame->printEnd();
886 }
887
888 blink::WebNotificationPresenter* WebTestProxyBase::GetNotificationPresenter() {
889   return test_interfaces_->GetTestRunner()->notification_presenter();
890 }
891
892 blink::WebMIDIClient* WebTestProxyBase::GetWebMIDIClient() {
893   return GetMIDIClientMock();
894 }
895
896 blink::WebSpeechRecognizer* WebTestProxyBase::GetSpeechRecognizer() {
897   return GetSpeechRecognizerMock();
898 }
899
900 bool WebTestProxyBase::RequestPointerLock() {
901   return test_interfaces_->GetTestRunner()->RequestPointerLock();
902 }
903
904 void WebTestProxyBase::RequestPointerUnlock() {
905   test_interfaces_->GetTestRunner()->RequestPointerUnlock();
906 }
907
908 bool WebTestProxyBase::IsPointerLocked() {
909   return test_interfaces_->GetTestRunner()->isPointerLocked();
910 }
911
912 void WebTestProxyBase::DidFocus() {
913   delegate_->SetFocus(this, true);
914 }
915
916 void WebTestProxyBase::DidBlur() {
917   delegate_->SetFocus(this, false);
918 }
919
920 void WebTestProxyBase::SetToolTipText(const blink::WebString& text,
921                                       blink::WebTextDirection direction) {
922   test_interfaces_->GetTestRunner()->setToolTipText(text);
923 }
924
925 void WebTestProxyBase::DidOpenChooser() {
926   chooser_count_++;
927 }
928
929 void WebTestProxyBase::DidCloseChooser() {
930   chooser_count_--;
931 }
932
933 bool WebTestProxyBase::IsChooserShown() {
934   return 0 < chooser_count_;
935 }
936
937 void WebTestProxyBase::LoadURLExternally(
938     blink::WebLocalFrame* frame,
939     const blink::WebURLRequest& request,
940     blink::WebNavigationPolicy policy,
941     const blink::WebString& suggested_name) {
942   if (test_interfaces_->GetTestRunner()->shouldWaitUntilExternalURLLoad()) {
943     if (policy == blink::WebNavigationPolicyDownload) {
944       delegate_->PrintMessage(
945           std::string("Downloading URL with suggested filename \"") +
946           suggested_name.utf8() + "\"\n");
947     } else {
948       delegate_->PrintMessage(std::string("Loading URL externally - \"") +
949                               URLDescription(request.url()) + "\"\n");
950     }
951     delegate_->TestFinished();
952   }
953 }
954
955 void WebTestProxyBase::DidStartProvisionalLoad(blink::WebLocalFrame* frame) {
956   if (!test_interfaces_->GetTestRunner()->topLoadingFrame())
957     test_interfaces_->GetTestRunner()->setTopLoadingFrame(frame, false);
958
959   if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
960     PrintFrameDescription(delegate_, frame);
961     delegate_->PrintMessage(" - didStartProvisionalLoadForFrame\n");
962   }
963
964   if (test_interfaces_->GetTestRunner()
965           ->shouldDumpUserGestureInFrameLoadCallbacks()) {
966     PrintFrameuserGestureStatus(
967         delegate_, frame, " - in didStartProvisionalLoadForFrame\n");
968   }
969 }
970
971 void WebTestProxyBase::DidReceiveServerRedirectForProvisionalLoad(
972     blink::WebLocalFrame* frame) {
973   if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
974     PrintFrameDescription(delegate_, frame);
975     delegate_->PrintMessage(
976         " - didReceiveServerRedirectForProvisionalLoadForFrame\n");
977   }
978 }
979
980 bool WebTestProxyBase::DidFailProvisionalLoad(blink::WebLocalFrame* frame,
981                                               const blink::WebURLError& error) {
982   if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
983     PrintFrameDescription(delegate_, frame);
984     delegate_->PrintMessage(" - didFailProvisionalLoadWithError\n");
985   }
986   CheckDone(frame, MainResourceLoadFailed);
987   return !frame->provisionalDataSource();
988 }
989
990 void WebTestProxyBase::DidCommitProvisionalLoad(
991     blink::WebLocalFrame* frame,
992     const blink::WebHistoryItem& history_item,
993     blink::WebHistoryCommitType history_type) {
994   if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
995     PrintFrameDescription(delegate_, frame);
996     delegate_->PrintMessage(" - didCommitLoadForFrame\n");
997   }
998 }
999
1000 void WebTestProxyBase::DidReceiveTitle(blink::WebLocalFrame* frame,
1001                                        const blink::WebString& title,
1002                                        blink::WebTextDirection direction) {
1003   blink::WebCString title8 = title.utf8();
1004
1005   if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
1006     PrintFrameDescription(delegate_, frame);
1007     delegate_->PrintMessage(std::string(" - didReceiveTitle: ") +
1008                             title8.data() + "\n");
1009   }
1010
1011   if (test_interfaces_->GetTestRunner()->shouldDumpTitleChanges())
1012     delegate_->PrintMessage(std::string("TITLE CHANGED: '") + title8.data() +
1013                             "'\n");
1014 }
1015
1016 void WebTestProxyBase::DidChangeIcon(blink::WebLocalFrame* frame,
1017                                      blink::WebIconURL::Type icon_type) {
1018   if (test_interfaces_->GetTestRunner()->shouldDumpIconChanges()) {
1019     PrintFrameDescription(delegate_, frame);
1020     delegate_->PrintMessage(std::string(" - didChangeIcons\n"));
1021   }
1022 }
1023
1024 void WebTestProxyBase::DidFinishDocumentLoad(blink::WebLocalFrame* frame) {
1025   if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
1026     PrintFrameDescription(delegate_, frame);
1027     delegate_->PrintMessage(" - didFinishDocumentLoadForFrame\n");
1028   } else {
1029     unsigned pendingUnloadEvents = frame->unloadListenerCount();
1030     if (pendingUnloadEvents) {
1031       PrintFrameDescription(delegate_, frame);
1032       delegate_->PrintMessage(base::StringPrintf(
1033           " - has %u onunload handler(s)\n", pendingUnloadEvents));
1034     }
1035   }
1036 }
1037
1038 void WebTestProxyBase::DidHandleOnloadEvents(blink::WebLocalFrame* frame) {
1039   if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
1040     PrintFrameDescription(delegate_, frame);
1041     delegate_->PrintMessage(" - didHandleOnloadEventsForFrame\n");
1042   }
1043 }
1044
1045 void WebTestProxyBase::DidFailLoad(blink::WebLocalFrame* frame,
1046                                    const blink::WebURLError& error) {
1047   if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
1048     PrintFrameDescription(delegate_, frame);
1049     delegate_->PrintMessage(" - didFailLoadWithError\n");
1050   }
1051   CheckDone(frame, MainResourceLoadFailed);
1052 }
1053
1054 void WebTestProxyBase::DidFinishLoad(blink::WebLocalFrame* frame) {
1055   if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks()) {
1056     PrintFrameDescription(delegate_, frame);
1057     delegate_->PrintMessage(" - didFinishLoadForFrame\n");
1058   }
1059   CheckDone(frame, LoadFinished);
1060 }
1061
1062 void WebTestProxyBase::DidDetectXSS(blink::WebLocalFrame* frame,
1063                                     const blink::WebURL& insecure_url,
1064                                     bool did_block_entire_page) {
1065   if (test_interfaces_->GetTestRunner()->shouldDumpFrameLoadCallbacks())
1066     delegate_->PrintMessage("didDetectXSS\n");
1067 }
1068
1069 void WebTestProxyBase::DidDispatchPingLoader(blink::WebLocalFrame* frame,
1070                                              const blink::WebURL& url) {
1071   if (test_interfaces_->GetTestRunner()->shouldDumpPingLoaderCallbacks())
1072     delegate_->PrintMessage(std::string("PingLoader dispatched to '") +
1073                             URLDescription(url).c_str() + "'.\n");
1074 }
1075
1076 void WebTestProxyBase::WillRequestResource(
1077     blink::WebLocalFrame* frame,
1078     const blink::WebCachedURLRequest& request) {
1079   if (test_interfaces_->GetTestRunner()->shouldDumpResourceRequestCallbacks()) {
1080     PrintFrameDescription(delegate_, frame);
1081     delegate_->PrintMessage(std::string(" - ") +
1082                             request.initiatorName().utf8().data());
1083     delegate_->PrintMessage(std::string(" requested '") +
1084                             URLDescription(request.urlRequest().url()).c_str() +
1085                             "'\n");
1086   }
1087 }
1088
1089 void WebTestProxyBase::WillSendRequest(
1090     blink::WebLocalFrame* frame,
1091     unsigned identifier,
1092     blink::WebURLRequest& request,
1093     const blink::WebURLResponse& redirect_response) {
1094   // Need to use GURL for host() and SchemeIs()
1095   GURL url = request.url();
1096   std::string request_url = url.possibly_invalid_spec();
1097
1098   GURL main_document_url = request.firstPartyForCookies();
1099
1100   if (redirect_response.isNull() &&
1101       (test_interfaces_->GetTestRunner()->shouldDumpResourceLoadCallbacks() ||
1102        test_interfaces_->GetTestRunner()->shouldDumpResourcePriorities())) {
1103     DCHECK(resource_identifier_map_.find(identifier) ==
1104            resource_identifier_map_.end());
1105     resource_identifier_map_[identifier] =
1106         DescriptionSuitableForTestResult(request_url);
1107   }
1108
1109   if (test_interfaces_->GetTestRunner()->shouldDumpResourceLoadCallbacks()) {
1110     if (resource_identifier_map_.find(identifier) ==
1111         resource_identifier_map_.end())
1112       delegate_->PrintMessage("<unknown>");
1113     else
1114       delegate_->PrintMessage(resource_identifier_map_[identifier]);
1115     delegate_->PrintMessage(" - willSendRequest <NSURLRequest URL ");
1116     delegate_->PrintMessage(
1117         DescriptionSuitableForTestResult(request_url).c_str());
1118     delegate_->PrintMessage(", main document URL ");
1119     delegate_->PrintMessage(URLDescription(main_document_url).c_str());
1120     delegate_->PrintMessage(", http method ");
1121     delegate_->PrintMessage(request.httpMethod().utf8().data());
1122     delegate_->PrintMessage("> redirectResponse ");
1123     PrintResponseDescription(delegate_, redirect_response);
1124     delegate_->PrintMessage("\n");
1125   }
1126
1127   if (test_interfaces_->GetTestRunner()->shouldDumpResourcePriorities()) {
1128     delegate_->PrintMessage(
1129         DescriptionSuitableForTestResult(request_url).c_str());
1130     delegate_->PrintMessage(" has priority ");
1131     delegate_->PrintMessage(PriorityDescription(request.priority()));
1132     delegate_->PrintMessage("\n");
1133   }
1134
1135   if (test_interfaces_->GetTestRunner()->httpHeadersToClear()) {
1136     const std::set<std::string>* clearHeaders =
1137         test_interfaces_->GetTestRunner()->httpHeadersToClear();
1138     for (std::set<std::string>::const_iterator header = clearHeaders->begin();
1139          header != clearHeaders->end();
1140          ++header)
1141       request.clearHTTPHeaderField(blink::WebString::fromUTF8(*header));
1142   }
1143
1144   std::string host = url.host();
1145   if (!host.empty() &&
1146       (url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme))) {
1147     if (!IsLocalHost(host) && !IsTestHost(host) &&
1148         !HostIsUsedBySomeTestsToGenerateError(host) &&
1149         ((!main_document_url.SchemeIs(url::kHttpScheme) &&
1150           !main_document_url.SchemeIs(url::kHttpsScheme)) ||
1151          IsLocalHost(main_document_url.host())) &&
1152         !delegate_->AllowExternalPages()) {
1153       delegate_->PrintMessage(std::string("Blocked access to external URL ") +
1154                               request_url + "\n");
1155       BlockRequest(request);
1156       return;
1157     }
1158   }
1159
1160   // Set the new substituted URL.
1161   request.setURL(delegate_->RewriteLayoutTestsURL(request.url().spec()));
1162 }
1163
1164 void WebTestProxyBase::DidReceiveResponse(
1165     blink::WebLocalFrame* frame,
1166     unsigned identifier,
1167     const blink::WebURLResponse& response) {
1168   if (test_interfaces_->GetTestRunner()->shouldDumpResourceLoadCallbacks()) {
1169     if (resource_identifier_map_.find(identifier) ==
1170         resource_identifier_map_.end())
1171       delegate_->PrintMessage("<unknown>");
1172     else
1173       delegate_->PrintMessage(resource_identifier_map_[identifier]);
1174     delegate_->PrintMessage(" - didReceiveResponse ");
1175     PrintResponseDescription(delegate_, response);
1176     delegate_->PrintMessage("\n");
1177   }
1178   if (test_interfaces_->GetTestRunner()
1179           ->shouldDumpResourceResponseMIMETypes()) {
1180     GURL url = response.url();
1181     blink::WebString mime_type = response.mimeType();
1182     delegate_->PrintMessage(url.ExtractFileName());
1183     delegate_->PrintMessage(" has MIME type ");
1184     // Simulate NSURLResponse's mapping of empty/unknown MIME types to
1185     // application/octet-stream
1186     delegate_->PrintMessage(mime_type.isEmpty() ? "application/octet-stream"
1187                                                 : mime_type.utf8().data());
1188     delegate_->PrintMessage("\n");
1189   }
1190 }
1191
1192 void WebTestProxyBase::DidChangeResourcePriority(
1193     blink::WebLocalFrame* frame,
1194     unsigned identifier,
1195     const blink::WebURLRequest::Priority& priority,
1196     int intra_priority_value) {
1197   if (test_interfaces_->GetTestRunner()->shouldDumpResourcePriorities()) {
1198     if (resource_identifier_map_.find(identifier) ==
1199         resource_identifier_map_.end())
1200       delegate_->PrintMessage("<unknown>");
1201     else
1202       delegate_->PrintMessage(resource_identifier_map_[identifier]);
1203     delegate_->PrintMessage(
1204         base::StringPrintf(" changed priority to %s, intra_priority %d\n",
1205                            PriorityDescription(priority).c_str(),
1206                            intra_priority_value));
1207   }
1208 }
1209
1210 void WebTestProxyBase::DidFinishResourceLoad(blink::WebLocalFrame* frame,
1211                                              unsigned identifier) {
1212   if (test_interfaces_->GetTestRunner()->shouldDumpResourceLoadCallbacks()) {
1213     if (resource_identifier_map_.find(identifier) ==
1214         resource_identifier_map_.end())
1215       delegate_->PrintMessage("<unknown>");
1216     else
1217       delegate_->PrintMessage(resource_identifier_map_[identifier]);
1218     delegate_->PrintMessage(" - didFinishLoading\n");
1219   }
1220   resource_identifier_map_.erase(identifier);
1221 #if !defined(ENABLE_LOAD_COMPLETION_HACKS)
1222   CheckDone(frame, ResourceLoadCompleted);
1223 #endif
1224 }
1225
1226 void WebTestProxyBase::DidAddMessageToConsole(
1227     const blink::WebConsoleMessage& message,
1228     const blink::WebString& source_name,
1229     unsigned source_line) {
1230   // This matches win DumpRenderTree's UIDelegate.cpp.
1231   if (!log_console_output_)
1232     return;
1233   std::string level;
1234   switch (message.level) {
1235     case blink::WebConsoleMessage::LevelDebug:
1236       level = "DEBUG";
1237       break;
1238     case blink::WebConsoleMessage::LevelLog:
1239       level = "MESSAGE";
1240       break;
1241     case blink::WebConsoleMessage::LevelInfo:
1242       level = "INFO";
1243       break;
1244     case blink::WebConsoleMessage::LevelWarning:
1245       level = "WARNING";
1246       break;
1247     case blink::WebConsoleMessage::LevelError:
1248       level = "ERROR";
1249       break;
1250   }
1251   delegate_->PrintMessage(std::string("CONSOLE ") + level + ": ");
1252   if (source_line) {
1253     delegate_->PrintMessage(base::StringPrintf("line %d: ", source_line));
1254   }
1255   if (!message.text.isEmpty()) {
1256     std::string new_message;
1257     new_message = message.text.utf8();
1258     size_t file_protocol = new_message.find("file://");
1259     if (file_protocol != std::string::npos) {
1260       new_message = new_message.substr(0, file_protocol) +
1261                     URLSuitableForTestResult(new_message.substr(file_protocol));
1262     }
1263     delegate_->PrintMessage(new_message);
1264   }
1265   delegate_->PrintMessage(std::string("\n"));
1266 }
1267
1268 void WebTestProxyBase::CheckDone(blink::WebLocalFrame* frame,
1269                                  CheckDoneReason reason) {
1270   if (frame != test_interfaces_->GetTestRunner()->topLoadingFrame())
1271     return;
1272
1273 #if !defined(ENABLE_LOAD_COMPLETION_HACKS)
1274   // Quirk for MHTML prematurely completing on resource load completion.
1275   std::string mime_type = frame->dataSource()->response().mimeType().utf8();
1276   if (reason == ResourceLoadCompleted && mime_type == "multipart/related")
1277     return;
1278
1279   if (reason != MainResourceLoadFailed &&
1280       (frame->isResourceLoadInProgress() || frame->isLoading()))
1281     return;
1282 #endif
1283   test_interfaces_->GetTestRunner()->setTopLoadingFrame(frame, true);
1284 }
1285
1286 blink::WebNavigationPolicy WebTestProxyBase::DecidePolicyForNavigation(
1287     const blink::WebFrameClient::NavigationPolicyInfo& info) {
1288   blink::WebNavigationPolicy result;
1289   if (!test_interfaces_->GetTestRunner()->policyDelegateEnabled())
1290     return info.defaultPolicy;
1291
1292   delegate_->PrintMessage(
1293       std::string("Policy delegate: attempt to load ") +
1294       URLDescription(info.urlRequest.url()) + " with navigation type '" +
1295       WebNavigationTypeToString(info.navigationType) + "'\n");
1296   if (test_interfaces_->GetTestRunner()->policyDelegateIsPermissive())
1297     result = blink::WebNavigationPolicyCurrentTab;
1298   else
1299     result = blink::WebNavigationPolicyIgnore;
1300
1301   if (test_interfaces_->GetTestRunner()->policyDelegateShouldNotifyDone())
1302     test_interfaces_->GetTestRunner()->policyDelegateDone();
1303   return result;
1304 }
1305
1306 bool WebTestProxyBase::WillCheckAndDispatchMessageEvent(
1307     blink::WebLocalFrame* source_frame,
1308     blink::WebFrame* target_frame,
1309     blink::WebSecurityOrigin target,
1310     blink::WebDOMMessageEvent event) {
1311   if (test_interfaces_->GetTestRunner()->shouldInterceptPostMessage()) {
1312     delegate_->PrintMessage("intercepted postMessage\n");
1313     return true;
1314   }
1315
1316   return false;
1317 }
1318
1319 void WebTestProxyBase::PostSpellCheckEvent(const blink::WebString& event_name) {
1320   if (test_interfaces_->GetTestRunner()->shouldDumpSpellCheckCallbacks()) {
1321     delegate_->PrintMessage(std::string("SpellCheckEvent: ") +
1322                             event_name.utf8().data() + "\n");
1323   }
1324 }
1325
1326 void WebTestProxyBase::ResetInputMethod() {
1327   // If a composition text exists, then we need to let the browser process
1328   // to cancel the input method's ongoing composition session.
1329   if (web_widget_)
1330     web_widget_->confirmComposition();
1331 }
1332
1333 blink::WebString WebTestProxyBase::acceptLanguages() {
1334   return blink::WebString::fromUTF8(accept_languages_);
1335 }
1336
1337 MockWebPushClient* WebTestProxyBase::GetPushClientMock() {
1338   if (!push_client_.get())
1339     push_client_.reset(new MockWebPushClient);
1340   return push_client_.get();
1341 }
1342
1343 blink::WebPushClient* WebTestProxyBase::GetWebPushClient() {
1344   return GetPushClientMock();
1345 }
1346
1347 }  // namespace content