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