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