blob: f3beaf73ffe8db225066e44505c80cf922f24331 [file] [log] [blame]
/*
* Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "public/testing/WebTestProxy.h"
#include "AccessibilityControllerChromium.h"
#include "EventSender.h"
#include "MockColorChooser.h"
#include "MockWebSpeechInputController.h"
#include "MockWebSpeechRecognizer.h"
#include "MockWebValidationMessageClient.h"
#include "SpellCheckClient.h"
#include "TestCommon.h"
#include "TestInterfaces.h"
#include "TestPlugin.h"
#include "TestRunner.h"
#include "WebUserMediaClientMock.h"
#include "public/platform/WebCString.h"
#include "public/platform/WebURLError.h"
#include "public/platform/WebURLRequest.h"
#include "public/platform/WebURLResponse.h"
#include "public/testing/WebTestDelegate.h"
#include "public/testing/WebTestInterfaces.h"
#include "public/testing/WebTestRunner.h"
#include "public/web/WebAccessibilityNotification.h"
#include "public/web/WebAccessibilityObject.h"
#include "public/web/WebCachedURLRequest.h"
#include "public/web/WebConsoleMessage.h"
#include "public/web/WebDataSource.h"
#include "public/web/WebDeviceOrientationClientMock.h"
#include "public/web/WebDocument.h"
#include "public/web/WebElement.h"
#include "public/web/WebFrame.h"
#include "public/web/WebGeolocationClientMock.h"
#include "public/web/WebHistoryItem.h"
#include "public/web/WebMIDIClientMock.h"
#include "public/web/WebNode.h"
#include "public/web/WebPluginParams.h"
#include "public/web/WebPrintParams.h"
#include "public/web/WebRange.h"
#include "public/web/WebScriptController.h"
#include "public/web/WebUserGestureIndicator.h"
#include "public/web/WebView.h"
// FIXME: Including platform_canvas.h here is a layering violation.
#include <cctype>
#include "skia/ext/platform_canvas.h"
using namespace WebKit;
using namespace std;
namespace WebTestRunner {
namespace {
class HostMethodTask : public WebMethodTask<WebTestProxyBase> {
public:
typedef void (WebTestProxyBase::*CallbackMethodType)();
HostMethodTask(WebTestProxyBase* object, CallbackMethodType callback)
: WebMethodTask<WebTestProxyBase>(object)
, m_callback(callback)
{ }
virtual void runIfValid() { (m_object->*m_callback)(); }
private:
CallbackMethodType m_callback;
};
void printNodeDescription(WebTestDelegate* delegate, const WebNode& node, int exception)
{
if (exception) {
delegate->printMessage("ERROR");
return;
}
if (node.isNull()) {
delegate->printMessage("(null)");
return;
}
delegate->printMessage(node.nodeName().utf8().data());
const WebNode& parent = node.parentNode();
if (!parent.isNull()) {
delegate->printMessage(" > ");
printNodeDescription(delegate, parent, 0);
}
}
void printRangeDescription(WebTestDelegate* delegate, const WebRange& range)
{
if (range.isNull()) {
delegate->printMessage("(null)");
return;
}
char buffer[100];
snprintf(buffer, sizeof(buffer), "range from %d of ", range.startOffset());
delegate->printMessage(buffer);
int exception = 0;
WebNode startNode = range.startContainer(exception);
printNodeDescription(delegate, startNode, exception);
snprintf(buffer, sizeof(buffer), " to %d of ", range.endOffset());
delegate->printMessage(buffer);
WebNode endNode = range.endContainer(exception);
printNodeDescription(delegate, endNode, exception);
}
string editingActionDescription(WebEditingAction action)
{
switch (action) {
case WebKit::WebEditingActionTyped:
return "WebViewInsertActionTyped";
case WebKit::WebEditingActionPasted:
return "WebViewInsertActionPasted";
case WebKit::WebEditingActionDropped:
return "WebViewInsertActionDropped";
}
return "(UNKNOWN ACTION)";
}
string textAffinityDescription(WebTextAffinity affinity)
{
switch (affinity) {
case WebKit::WebTextAffinityUpstream:
return "NSSelectionAffinityUpstream";
case WebKit::WebTextAffinityDownstream:
return "NSSelectionAffinityDownstream";
}
return "(UNKNOWN AFFINITY)";
}
void printFrameDescription(WebTestDelegate* delegate, WebFrame* frame)
{
string name8 = frame->uniqueName().utf8();
if (frame == frame->view()->mainFrame()) {
if (!name8.length()) {
delegate->printMessage("main frame");
return;
}
delegate->printMessage(string("main frame \"") + name8 + "\"");
return;
}
if (!name8.length()) {
delegate->printMessage("frame (anonymous)");
return;
}
delegate->printMessage(string("frame \"") + name8 + "\"");
}
void printFrameUserGestureStatus(WebTestDelegate* delegate, WebFrame* frame, const char* msg)
{
bool isUserGesture = WebUserGestureIndicator::isProcessingUserGesture();
delegate->printMessage(string("Frame with user gesture \"") + (isUserGesture ? "true" : "false") + "\"" + msg);
}
// Used to write a platform neutral file:/// URL by taking the
// filename and its directory. (e.g., converts
// "file:///tmp/foo/bar.txt" to just "bar.txt").
string descriptionSuitableForTestResult(const string& url)
{
if (url.empty() || string::npos == url.find("file://"))
return url;
size_t pos = url.rfind('/');
if (pos == string::npos || !pos)
return "ERROR:" + url;
pos = url.rfind('/', pos - 1);
if (pos == string::npos)
return "ERROR:" + url;
return url.substr(pos + 1);
}
void printResponseDescription(WebTestDelegate* delegate, const WebURLResponse& response)
{
if (response.isNull()) {
delegate->printMessage("(null)");
return;
}
string url = response.url().spec();
char data[100];
snprintf(data, sizeof(data), "%d", response. httpStatusCode());
delegate->printMessage(string("<NSURLResponse ") + descriptionSuitableForTestResult(url) + ", http status code " + data + ">");
}
string URLDescription(const GURL& url)
{
if (url.SchemeIs("file"))
return url.ExtractFileName();
return url.possibly_invalid_spec();
}
string PriorityDescription(const WebURLRequest::Priority& priority)
{
switch (priority) {
case WebURLRequest::PriorityVeryLow:
return "VeryLow";
case WebURLRequest::PriorityLow:
return "Low";
case WebURLRequest::PriorityMedium:
return "Medium";
case WebURLRequest::PriorityHigh:
return "High";
case WebURLRequest::PriorityVeryHigh:
return "VeryHigh";
case WebURLRequest::PriorityUnresolved:
default:
return "Unresolved";
}
}
void blockRequest(WebURLRequest& request)
{
request.setURL(GURL("255.255.255.255"));
}
bool isLocalhost(const string& host)
{
return host == "127.0.0.1" || host == "localhost";
}
bool hostIsUsedBySomeTestsToGenerateError(const string& host)
{
return host == "255.255.255.255";
}
// Used to write a platform neutral file:/// URL by only taking the filename
// (e.g., converts "file:///tmp/foo.txt" to just "foo.txt").
string urlSuitableForTestResult(const string& url)
{
if (url.empty() || string::npos == url.find("file://"))
return url;
size_t pos = url.rfind('/');
if (pos == string::npos) {
#ifdef WIN32
pos = url.rfind('\\');
if (pos == string::npos)
pos = 0;
#else
pos = 0;
#endif
}
string filename = url.substr(pos + 1);
if (filename.empty())
return "file:"; // A WebKit test has this in its expected output.
return filename;
}
// WebNavigationType debugging strings taken from PolicyDelegate.mm.
const char* linkClickedString = "link clicked";
const char* formSubmittedString = "form submitted";
const char* backForwardString = "back/forward";
const char* reloadString = "reload";
const char* formResubmittedString = "form resubmitted";
const char* otherString = "other";
const char* illegalString = "illegal value";
// Get a debugging string from a WebNavigationType.
const char* webNavigationTypeToString(WebNavigationType type)
{
switch (type) {
case WebKit::WebNavigationTypeLinkClicked:
return linkClickedString;
case WebKit::WebNavigationTypeFormSubmitted:
return formSubmittedString;
case WebKit::WebNavigationTypeBackForward:
return backForwardString;
case WebKit::WebNavigationTypeReload:
return reloadString;
case WebKit::WebNavigationTypeFormResubmitted:
return formResubmittedString;
case WebKit::WebNavigationTypeOther:
return otherString;
}
return illegalString;
}
string dumpDocumentText(WebFrame* frame)
{
// We use the document element's text instead of the body text here because
// not all documents have a body, such as XML documents.
WebElement documentElement = frame->document().documentElement();
if (documentElement.isNull())
return string();
return documentElement.innerText().utf8();
}
string dumpFramesAsText(WebFrame* frame, bool recursive)
{
string result;
// Add header for all but the main frame. Skip empty frames.
if (frame->parent() && !frame->document().documentElement().isNull()) {
result.append("\n--------\nFrame: '");
result.append(frame->uniqueName().utf8().data());
result.append("'\n--------\n");
}
result.append(dumpDocumentText(frame));
result.append("\n");
if (recursive) {
for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling())
result.append(dumpFramesAsText(child, recursive));
}
return result;
}
string dumpFramesAsPrintedText(WebFrame* frame, bool recursive)
{
string result;
// Cannot do printed format for anything other than HTML
if (!frame->document().isHTMLDocument())
return string();
// Add header for all but the main frame. Skip empty frames.
if (frame->parent() && !frame->document().documentElement().isNull()) {
result.append("\n--------\nFrame: '");
result.append(frame->uniqueName().utf8().data());
result.append("'\n--------\n");
}
result.append(frame->renderTreeAsText(WebFrame::RenderAsTextPrinting).utf8());
result.append("\n");
if (recursive) {
for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling())
result.append(dumpFramesAsPrintedText(child, recursive));
}
return result;
}
string dumpFrameScrollPosition(WebFrame* frame, bool recursive)
{
string result;
WebSize offset = frame->scrollOffset();
if (offset.width > 0 || offset.height > 0) {
if (frame->parent())
result = string("frame '") + frame->uniqueName().utf8().data() + "' ";
char data[100];
snprintf(data, sizeof(data), "scrolled to %d,%d\n", offset.width, offset.height);
result += data;
}
if (!recursive)
return result;
for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling())
result += dumpFrameScrollPosition(child, recursive);
return result;
}
struct ToLower {
char16 operator()(char16 c) { return tolower(c); }
};
// Returns True if item1 < item2.
bool HistoryItemCompareLess(const WebHistoryItem& item1, const WebHistoryItem& item2)
{
string16 target1 = item1.target();
string16 target2 = item2.target();
std::transform(target1.begin(), target1.end(), target1.begin(), ToLower());
std::transform(target2.begin(), target2.end(), target2.begin(), ToLower());
return target1 < target2;
}
string dumpHistoryItem(const WebHistoryItem& item, int indent, bool isCurrent)
{
string result;
if (isCurrent) {
result.append("curr->");
result.append(indent - 6, ' '); // 6 == "curr->".length()
} else
result.append(indent, ' ');
string url = normalizeLayoutTestURL(item.urlString().utf8());
result.append(url);
if (!item.target().isEmpty()) {
result.append(" (in frame \"");
result.append(item.target().utf8());
result.append("\")");
}
if (item.isTargetItem())
result.append(" **nav target**");
result.append("\n");
const WebVector<WebHistoryItem>& children = item.children();
if (!children.isEmpty()) {
// Must sort to eliminate arbitrary result ordering which defeats
// reproducible testing.
// FIXME: WebVector should probably just be a std::vector!!
std::vector<WebHistoryItem> sortedChildren;
for (size_t i = 0; i < children.size(); ++i)
sortedChildren.push_back(children[i]);
std::sort(sortedChildren.begin(), sortedChildren.end(), HistoryItemCompareLess);
for (size_t i = 0; i < sortedChildren.size(); ++i)
result += dumpHistoryItem(sortedChildren[i], indent + 4, false);
}
return result;
}
void dumpBackForwardList(const WebVector<WebHistoryItem>& history, size_t currentEntryIndex, string& result)
{
result.append("\n============== Back Forward List ==============\n");
for (size_t index = 0; index < history.size(); ++index)
result.append(dumpHistoryItem(history[index], 8, index == currentEntryIndex));
result.append("===============================================\n");
}
string dumpAllBackForwardLists(TestInterfaces* interfaces, WebTestDelegate* delegate)
{
string result;
const vector<WebTestProxyBase*>& windowList = interfaces->windowList();
for (unsigned i = 0; i < windowList.size(); ++i) {
size_t currentEntryIndex = 0;
WebVector<WebHistoryItem> history;
delegate->captureHistoryForWindow(windowList.at(i), &history, &currentEntryIndex);
dumpBackForwardList(history, currentEntryIndex, result);
}
return result;
}
}
WebTestProxyBase::WebTestProxyBase()
: m_testInterfaces(0)
, m_delegate(0)
, m_webWidget(0)
, m_spellcheck(new SpellCheckClient)
, m_chooserCount(0)
, m_validationMessageClient(new MockWebValidationMessageClient())
{
reset();
}
WebTestProxyBase::~WebTestProxyBase()
{
m_testInterfaces->windowClosed(this);
}
void WebTestProxyBase::setInterfaces(WebTestInterfaces* interfaces)
{
m_testInterfaces = interfaces->testInterfaces();
m_testInterfaces->windowOpened(this);
}
void WebTestProxyBase::setDelegate(WebTestDelegate* delegate)
{
m_delegate = delegate;
m_spellcheck->setDelegate(delegate);
m_validationMessageClient->setDelegate(delegate);
#if ENABLE_INPUT_SPEECH
if (m_speechInputController.get())
m_speechInputController->setDelegate(delegate);
#endif
if (m_speechRecognizer.get())
m_speechRecognizer->setDelegate(delegate);
}
void WebTestProxyBase::setWidget(WebWidget* widget)
{
m_webWidget = widget;
}
WebWidget* WebTestProxyBase::webWidget()
{
return m_webWidget;
}
WebView* WebTestProxyBase::webView()
{
WEBKIT_ASSERT(m_webWidget);
// TestRunner does not support popup widgets. So m_webWidget is always a WebView.
return static_cast<WebView*>(m_webWidget);
}
void WebTestProxyBase::reset()
{
m_paintRect = WebRect();
m_canvas.reset();
m_isPainting = false;
m_animateScheduled = false;
m_resourceIdentifierMap.clear();
m_logConsoleOutput = true;
if (m_geolocationClient.get())
m_geolocationClient->resetMock();
if (m_midiClient.get())
m_midiClient->resetMock();
#if ENABLE_INPUT_SPEECH
if (m_speechInputController.get())
m_speechInputController->clearResults();
#endif
}
WebSpellCheckClient* WebTestProxyBase::spellCheckClient() const
{
return m_spellcheck.get();
}
WebValidationMessageClient* WebTestProxyBase::validationMessageClient()
{
return m_validationMessageClient.get();
}
WebColorChooser* WebTestProxyBase::createColorChooser(WebColorChooserClient* client, const WebKit::WebColor& color)
{
// This instance is deleted by WebCore::ColorInputType
return new MockColorChooser(client, m_delegate, this);
}
string WebTestProxyBase::captureTree(bool debugRenderTree)
{
WebScriptController::flushConsoleMessages();
bool shouldDumpAsText = m_testInterfaces->testRunner()->shouldDumpAsText();
bool shouldDumpAsPrinted = m_testInterfaces->testRunner()->isPrinting();
WebFrame* frame = webView()->mainFrame();
string dataUtf8;
if (shouldDumpAsText) {
bool recursive = m_testInterfaces->testRunner()->shouldDumpChildFramesAsText();
dataUtf8 = shouldDumpAsPrinted ? dumpFramesAsPrintedText(frame, recursive) : dumpFramesAsText(frame, recursive);
} else {
bool recursive = m_testInterfaces->testRunner()->shouldDumpChildFrameScrollPositions();
WebFrame::RenderAsTextControls renderTextBehavior = WebFrame::RenderAsTextNormal;
if (shouldDumpAsPrinted)
renderTextBehavior |= WebFrame::RenderAsTextPrinting;
if (debugRenderTree)
renderTextBehavior |= WebFrame::RenderAsTextDebug;
dataUtf8 = frame->renderTreeAsText(renderTextBehavior).utf8();
dataUtf8 += dumpFrameScrollPosition(frame, recursive);
}
if (m_testInterfaces->testRunner()->shouldDumpBackForwardList())
dataUtf8 += dumpAllBackForwardLists(m_testInterfaces, m_delegate);
return dataUtf8;
}
SkCanvas* WebTestProxyBase::capturePixels()
{
webWidget()->layout();
if (m_testInterfaces->testRunner()->testRepaint()) {
WebSize viewSize = webWidget()->size();
int width = viewSize.width;
int height = viewSize.height;
if (m_testInterfaces->testRunner()->sweepHorizontally()) {
for (WebRect column(0, 0, 1, height); column.x < width; column.x++)
paintRect(column);
} else {
for (WebRect line(0, 0, width, 1); line.y < height; line.y++)
paintRect(line);
}
} else if (m_testInterfaces->testRunner()->isPrinting())
paintPagesWithBoundaries();
else
paintInvalidatedRegion();
// See if we need to draw the selection bounds rect. Selection bounds
// rect is the rect enclosing the (possibly transformed) selection.
// The rect should be drawn after everything is laid out and painted.
if (m_testInterfaces->testRunner()->shouldDumpSelectionRect()) {
// If there is a selection rect - draw a red 1px border enclosing rect
WebRect wr = webView()->mainFrame()->selectionBoundsRect();
if (!wr.isEmpty()) {
// Render a red rectangle bounding selection rect
SkPaint paint;
paint.setColor(0xFFFF0000); // Fully opaque red
paint.setStyle(SkPaint::kStroke_Style);
paint.setFlags(SkPaint::kAntiAlias_Flag);
paint.setStrokeWidth(1.0f);
SkIRect rect; // Bounding rect
rect.set(wr.x, wr.y, wr.x + wr.width, wr.y + wr.height);
canvas()->drawIRect(rect, paint);
}
}
return canvas();
}
void WebTestProxyBase::setLogConsoleOutput(bool enabled)
{
m_logConsoleOutput = enabled;
}
void WebTestProxyBase::paintRect(const WebRect& rect)
{
WEBKIT_ASSERT(!m_isPainting);
WEBKIT_ASSERT(canvas());
m_isPainting = true;
float deviceScaleFactor = webView()->deviceScaleFactor();
int scaledX = static_cast<int>(static_cast<float>(rect.x) * deviceScaleFactor);
int scaledY = static_cast<int>(static_cast<float>(rect.y) * deviceScaleFactor);
int scaledWidth = static_cast<int>(ceil(static_cast<float>(rect.width) * deviceScaleFactor));
int scaledHeight = static_cast<int>(ceil(static_cast<float>(rect.height) * deviceScaleFactor));
WebRect deviceRect(scaledX, scaledY, scaledWidth, scaledHeight);
webWidget()->paint(canvas(), deviceRect);
m_isPainting = false;
}
void WebTestProxyBase::paintInvalidatedRegion()
{
webWidget()->animate(0.0);
webWidget()->layout();
WebSize widgetSize = webWidget()->size();
WebRect clientRect(0, 0, widgetSize.width, widgetSize.height);
// Paint the canvas if necessary. Allow painting to generate extra rects
// for the first two calls. This is necessary because some WebCore rendering
// objects update their layout only when painted.
// Store the total area painted in total_paint. Then tell the gdk window
// to update that area after we're done painting it.
for (int i = 0; i < 3; ++i) {
// rect = intersect(m_paintRect , clientRect)
WebRect damageRect = m_paintRect;
int left = max(damageRect.x, clientRect.x);
int top = max(damageRect.y, clientRect.y);
int right = min(damageRect.x + damageRect.width, clientRect.x + clientRect.width);
int bottom = min(damageRect.y + damageRect.height, clientRect.y + clientRect.height);
WebRect rect;
if (left < right && top < bottom)
rect = WebRect(left, top, right - left, bottom - top);
m_paintRect = WebRect();
if (rect.isEmpty())
continue;
paintRect(rect);
}
WEBKIT_ASSERT(m_paintRect.isEmpty());
}
void WebTestProxyBase::paintPagesWithBoundaries()
{
WEBKIT_ASSERT(!m_isPainting);
WEBKIT_ASSERT(canvas());
m_isPainting = true;
WebSize pageSizeInPixels = webWidget()->size();
WebFrame* webFrame = webView()->mainFrame();
int pageCount = webFrame->printBegin(pageSizeInPixels);
int totalHeight = pageCount * (pageSizeInPixels.height + 1) - 1;
SkCanvas* testCanvas = skia::TryCreateBitmapCanvas(pageSizeInPixels.width, totalHeight, true);
if (testCanvas) {
discardBackingStore();
m_canvas.reset(testCanvas);
} else {
webFrame->printEnd();
return;
}
webFrame->printPagesWithBoundaries(canvas(), pageSizeInPixels);
webFrame->printEnd();
m_isPainting = false;
}
SkCanvas* WebTestProxyBase::canvas()
{
if (m_canvas.get())
return m_canvas.get();
WebSize widgetSize = webWidget()->size();
float deviceScaleFactor = webView()->deviceScaleFactor();
int scaledWidth = static_cast<int>(ceil(static_cast<float>(widgetSize.width) * deviceScaleFactor));
int scaledHeight = static_cast<int>(ceil(static_cast<float>(widgetSize.height) * deviceScaleFactor));
m_canvas.reset(skia::CreateBitmapCanvas(scaledWidth, scaledHeight, true));
return m_canvas.get();
}
// Paints the entire canvas a semi-transparent black (grayish). This is used
// by the layout tests in fast/repaint. The alpha value matches upstream.
void WebTestProxyBase::displayRepaintMask()
{
canvas()->drawARGB(167, 0, 0, 0);
}
void WebTestProxyBase::display()
{
const WebKit::WebSize& size = webWidget()->size();
WebRect rect(0, 0, size.width, size.height);
m_paintRect = rect;
paintInvalidatedRegion();
displayRepaintMask();
}
void WebTestProxyBase::displayInvalidatedRegion()
{
paintInvalidatedRegion();
displayRepaintMask();
}
void WebTestProxyBase::discardBackingStore()
{
m_canvas.reset();
}
WebGeolocationClientMock* WebTestProxyBase::geolocationClientMock()
{
if (!m_geolocationClient.get())
m_geolocationClient.reset(WebGeolocationClientMock::create());
return m_geolocationClient.get();
}
WebMIDIClientMock* WebTestProxyBase::midiClientMock()
{
if (!m_midiClient.get())
m_midiClient.reset(WebMIDIClientMock::create());
return m_midiClient.get();
}
WebDeviceOrientationClientMock* WebTestProxyBase::deviceOrientationClientMock()
{
if (!m_deviceOrientationClient.get())
m_deviceOrientationClient.reset(WebDeviceOrientationClientMock::create());
return m_deviceOrientationClient.get();
}
#if ENABLE_INPUT_SPEECH
MockWebSpeechInputController* WebTestProxyBase::speechInputControllerMock()
{
WEBKIT_ASSERT(m_speechInputController.get());
return m_speechInputController.get();
}
#endif
MockWebSpeechRecognizer* WebTestProxyBase::speechRecognizerMock()
{
if (!m_speechRecognizer.get()) {
m_speechRecognizer.reset(new MockWebSpeechRecognizer());
m_speechRecognizer->setDelegate(m_delegate);
}
return m_speechRecognizer.get();
}
void WebTestProxyBase::didInvalidateRect(const WebRect& rect)
{
// m_paintRect = m_paintRect U rect
if (rect.isEmpty())
return;
if (m_paintRect.isEmpty()) {
m_paintRect = rect;
return;
}
int left = min(m_paintRect.x, rect.x);
int top = min(m_paintRect.y, rect.y);
int right = max(m_paintRect.x + m_paintRect.width, rect.x + rect.width);
int bottom = max(m_paintRect.y + m_paintRect.height, rect.y + rect.height);
m_paintRect = WebRect(left, top, right - left, bottom - top);
}
void WebTestProxyBase::didScrollRect(int, int, const WebRect& clipRect)
{
didInvalidateRect(clipRect);
}
void WebTestProxyBase::invalidateAll()
{
m_paintRect = WebRect(0, 0, INT_MAX, INT_MAX);
}
void WebTestProxyBase::scheduleComposite()
{
invalidateAll();
}
void WebTestProxyBase::scheduleAnimation()
{
if (!m_testInterfaces->testRunner()->testIsRunning())
return;
if (!m_animateScheduled) {
m_animateScheduled = true;
m_delegate->postDelayedTask(new HostMethodTask(this, &WebTestProxyBase::animateNow), 1);
}
}
void WebTestProxyBase::animateNow()
{
if (m_animateScheduled) {
m_animateScheduled = false;
webWidget()->animate(0.0);
}
}
void WebTestProxyBase::show(WebNavigationPolicy)
{
invalidateAll();
}
void WebTestProxyBase::setWindowRect(const WebRect& rect)
{
invalidateAll();
discardBackingStore();
}
void WebTestProxyBase::didAutoResize(const WebSize&)
{
invalidateAll();
}
void WebTestProxyBase::postAccessibilityNotification(const WebKit::WebAccessibilityObject& obj, WebKit::WebAccessibilityNotification notification)
{
if (notification == WebKit::WebAccessibilityNotificationFocusedUIElementChanged)
m_testInterfaces->accessibilityController()->setFocusedElement(obj);
const char* notificationName;
switch (notification) {
case WebKit::WebAccessibilityNotificationActiveDescendantChanged:
notificationName = "ActiveDescendantChanged";
break;
case WebKit::WebAccessibilityNotificationAutocorrectionOccured:
notificationName = "AutocorrectionOccured";
break;
case WebKit::WebAccessibilityNotificationCheckedStateChanged:
notificationName = "CheckedStateChanged";
break;
case WebKit::WebAccessibilityNotificationChildrenChanged:
notificationName = "ChildrenChanged";
break;
case WebKit::WebAccessibilityNotificationFocusedUIElementChanged:
notificationName = "FocusedUIElementChanged";
break;
case WebKit::WebAccessibilityNotificationLayoutComplete:
notificationName = "LayoutComplete";
break;
case WebKit::WebAccessibilityNotificationLoadComplete:
notificationName = "LoadComplete";
break;
case WebKit::WebAccessibilityNotificationSelectedChildrenChanged:
notificationName = "SelectedChildrenChanged";
break;
case WebKit::WebAccessibilityNotificationSelectedTextChanged:
notificationName = "SelectedTextChanged";
break;
case WebKit::WebAccessibilityNotificationValueChanged:
notificationName = "ValueChanged";
break;
case WebKit::WebAccessibilityNotificationScrolledToAnchor:
notificationName = "ScrolledToAnchor";
break;
case WebKit::WebAccessibilityNotificationLiveRegionChanged:
notificationName = "LiveRegionChanged";
break;
case WebKit::WebAccessibilityNotificationMenuListItemSelected:
notificationName = "MenuListItemSelected";
break;
case WebKit::WebAccessibilityNotificationMenuListValueChanged:
notificationName = "MenuListValueChanged";
break;
case WebKit::WebAccessibilityNotificationRowCountChanged:
notificationName = "RowCountChanged";
break;
case WebKit::WebAccessibilityNotificationRowCollapsed:
notificationName = "RowCollapsed";
break;
case WebKit::WebAccessibilityNotificationRowExpanded:
notificationName = "RowExpanded";
break;
case WebKit::WebAccessibilityNotificationInvalidStatusChanged:
notificationName = "InvalidStatusChanged";
break;
case WebKit::WebAccessibilityNotificationTextChanged:
notificationName = "TextChanged";
break;
case WebKit::WebAccessibilityNotificationAriaAttributeChanged:
notificationName = "AriaAttributeChanged";
break;
default:
notificationName = "UnknownNotification";
break;
}
m_testInterfaces->accessibilityController()->notificationReceived(obj, notificationName);
if (m_testInterfaces->accessibilityController()->shouldLogAccessibilityEvents()) {
string message("AccessibilityNotification - ");
message += notificationName;
WebKit::WebNode node = obj.node();
if (!node.isNull() && node.isElementNode()) {
WebKit::WebElement element = node.to<WebKit::WebElement>();
if (element.hasAttribute("id")) {
message += " - id:";
message += element.getAttribute("id").utf8().data();
}
}
m_delegate->printMessage(message + "\n");
}
}
void WebTestProxyBase::startDragging(WebFrame*, const WebDragData& data, WebDragOperationsMask mask, const WebImage&, const WebPoint&)
{
// When running a test, we need to fake a drag drop operation otherwise
// Windows waits for real mouse events to know when the drag is over.
m_testInterfaces->eventSender()->doDragDrop(data, mask);
}
// The output from these methods in layout test mode should match that
// expected by the layout tests. See EditingDelegate.m in DumpRenderTree.
bool WebTestProxyBase::shouldBeginEditing(const WebRange& range)
{
if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
m_delegate->printMessage("EDITING DELEGATE: shouldBeginEditingInDOMRange:");
printRangeDescription(m_delegate, range);
m_delegate->printMessage("\n");
}
return true;
}
bool WebTestProxyBase::shouldEndEditing(const WebRange& range)
{
if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
m_delegate->printMessage("EDITING DELEGATE: shouldEndEditingInDOMRange:");
printRangeDescription(m_delegate, range);
m_delegate->printMessage("\n");
}
return true;
}
bool WebTestProxyBase::shouldInsertNode(const WebNode& node, const WebRange& range, WebEditingAction action)
{
if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
m_delegate->printMessage("EDITING DELEGATE: shouldInsertNode:");
printNodeDescription(m_delegate, node, 0);
m_delegate->printMessage(" replacingDOMRange:");
printRangeDescription(m_delegate, range);
m_delegate->printMessage(string(" givenAction:") + editingActionDescription(action) + "\n");
}
return true;
}
bool WebTestProxyBase::shouldInsertText(const WebString& text, const WebRange& range, WebEditingAction action)
{
if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
m_delegate->printMessage(string("EDITING DELEGATE: shouldInsertText:") + text.utf8().data() + " replacingDOMRange:");
printRangeDescription(m_delegate, range);
m_delegate->printMessage(string(" givenAction:") + editingActionDescription(action) + "\n");
}
return true;
}
bool WebTestProxyBase::shouldChangeSelectedRange(
const WebRange& fromRange, const WebRange& toRange, WebTextAffinity affinity, bool stillSelecting)
{
if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
m_delegate->printMessage("EDITING DELEGATE: shouldChangeSelectedDOMRange:");
printRangeDescription(m_delegate, fromRange);
m_delegate->printMessage(" toDOMRange:");
printRangeDescription(m_delegate, toRange);
m_delegate->printMessage(string(" affinity:") + textAffinityDescription(affinity) + " stillSelecting:" + (stillSelecting ? "TRUE" : "FALSE") + "\n");
}
return true;
}
bool WebTestProxyBase::shouldDeleteRange(const WebRange& range)
{
if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
m_delegate->printMessage("EDITING DELEGATE: shouldDeleteDOMRange:");
printRangeDescription(m_delegate, range);
m_delegate->printMessage("\n");
}
return true;
}
bool WebTestProxyBase::shouldApplyStyle(const WebString& style, const WebRange& range)
{
if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) {
m_delegate->printMessage(string("EDITING DELEGATE: shouldApplyStyle:") + style.utf8().data() + " toElementsInDOMRange:");
printRangeDescription(m_delegate, range);
m_delegate->printMessage("\n");
}
return true;
}
void WebTestProxyBase::didBeginEditing()
{
if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks())
m_delegate->printMessage("EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification\n");
}
void WebTestProxyBase::didChangeSelection(bool isEmptySelection)
{
if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks())
m_delegate->printMessage("EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification\n");
}
void WebTestProxyBase::didChangeContents()
{
if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks())
m_delegate->printMessage("EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification\n");
}
void WebTestProxyBase::didEndEditing()
{
if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks())
m_delegate->printMessage("EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification\n");
}
bool WebTestProxyBase::createView(WebFrame*, const WebURLRequest& request, const WebWindowFeatures&, const WebString&, WebNavigationPolicy)
{
if (!m_testInterfaces->testRunner()->canOpenWindows())
return false;
if (m_testInterfaces->testRunner()->shouldDumpCreateView())
m_delegate->printMessage(string("createView(") + URLDescription(request.url()) + ")\n");
return true;
}
WebPlugin* WebTestProxyBase::createPlugin(WebFrame* frame, const WebPluginParams& params)
{
if (params.mimeType == TestPlugin::mimeType())
return TestPlugin::create(frame, params, m_delegate);
return 0;
}
void WebTestProxyBase::setStatusText(const WebString& text)
{
if (!m_testInterfaces->testRunner()->shouldDumpStatusCallbacks())
return;
m_delegate->printMessage(string("UI DELEGATE STATUS CALLBACK: setStatusText:") + text.utf8().data() + "\n");
}
void WebTestProxyBase::didStopLoading()
{
if (m_testInterfaces->testRunner()->shouldDumpProgressFinishedCallback())
m_delegate->printMessage("postProgressFinishedNotification\n");
}
void WebTestProxyBase::showContextMenu(WebFrame*, const WebContextMenuData& contextMenuData)
{
m_testInterfaces->eventSender()->setContextMenuData(contextMenuData);
}
WebUserMediaClient* WebTestProxyBase::userMediaClient()
{
if (!m_userMediaClient.get())
m_userMediaClient.reset(new WebUserMediaClientMock(m_delegate));
return m_userMediaClient.get();
}
// Simulate a print by going into print mode and then exit straight away.
void WebTestProxyBase::printPage(WebFrame* frame)
{
WebSize pageSizeInPixels = webWidget()->size();
if (pageSizeInPixels.isEmpty())
return;
WebPrintParams printParams(pageSizeInPixels);
frame->printBegin(printParams);
frame->printEnd();
}
WebNotificationPresenter* WebTestProxyBase::notificationPresenter()
{
#if ENABLE_NOTIFICATIONS
return m_testInterfaces->testRunner()->notificationPresenter();
#else
return 0;
#endif
}
WebGeolocationClient* WebTestProxyBase::geolocationClient()
{
return geolocationClientMock();
}
WebMIDIClient* WebTestProxyBase::webMIDIClient()
{
return midiClientMock();
}
WebSpeechInputController* WebTestProxyBase::speechInputController(WebSpeechInputListener* listener)
{
#if ENABLE_INPUT_SPEECH
if (!m_speechInputController.get()) {
m_speechInputController.reset(new MockWebSpeechInputController(listener));
m_speechInputController->setDelegate(m_delegate);
}
return m_speechInputController.get();
#else
WEBKIT_ASSERT(listener);
return 0;
#endif
}
WebSpeechRecognizer* WebTestProxyBase::speechRecognizer()
{
return speechRecognizerMock();
}
WebDeviceOrientationClient* WebTestProxyBase::deviceOrientationClient()
{
return deviceOrientationClientMock();
}
bool WebTestProxyBase::requestPointerLock()
{
return m_testInterfaces->testRunner()->requestPointerLock();
}
void WebTestProxyBase::requestPointerUnlock()
{
m_testInterfaces->testRunner()->requestPointerUnlock();
}
bool WebTestProxyBase::isPointerLocked()
{
return m_testInterfaces->testRunner()->isPointerLocked();
}
void WebTestProxyBase::didFocus()
{
m_delegate->setFocus(this, true);
}
void WebTestProxyBase::didBlur()
{
m_delegate->setFocus(this, false);
}
void WebTestProxyBase::setToolTipText(const WebString& text, WebTextDirection)
{
m_testInterfaces->testRunner()->setToolTipText(text);
}
void WebTestProxyBase::didOpenChooser()
{
m_chooserCount++;
}
void WebTestProxyBase::didCloseChooser()
{
m_chooserCount--;
}
bool WebTestProxyBase::isChooserShown()
{
return 0 < m_chooserCount;
}
void WebTestProxyBase::didStartProvisionalLoad(WebFrame* frame)
{
if (!m_testInterfaces->testRunner()->topLoadingFrame())
m_testInterfaces->testRunner()->setTopLoadingFrame(frame, false);
if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
printFrameDescription(m_delegate, frame);
m_delegate->printMessage(" - didStartProvisionalLoadForFrame\n");
}
if (m_testInterfaces->testRunner()->shouldDumpUserGestureInFrameLoadCallbacks())
printFrameUserGestureStatus(m_delegate, frame, " - in didStartProvisionalLoadForFrame\n");
}
void WebTestProxyBase::didReceiveServerRedirectForProvisionalLoad(WebFrame* frame)
{
if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
printFrameDescription(m_delegate, frame);
m_delegate->printMessage(" - didReceiveServerRedirectForProvisionalLoadForFrame\n");
}
}
bool WebTestProxyBase::didFailProvisionalLoad(WebFrame* frame, const WebURLError&)
{
if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
printFrameDescription(m_delegate, frame);
m_delegate->printMessage(" - didFailProvisionalLoadWithError\n");
}
locationChangeDone(frame);
return !frame->provisionalDataSource();
}
void WebTestProxyBase::didCommitProvisionalLoad(WebFrame* frame, bool)
{
if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
printFrameDescription(m_delegate, frame);
m_delegate->printMessage(" - didCommitLoadForFrame\n");
}
}
void WebTestProxyBase::didReceiveTitle(WebFrame* frame, const WebString& title, WebTextDirection direction)
{
WebCString title8 = title.utf8();
if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
printFrameDescription(m_delegate, frame);
m_delegate->printMessage(string(" - didReceiveTitle: ") + title8.data() + "\n");
}
if (m_testInterfaces->testRunner()->shouldDumpTitleChanges())
m_delegate->printMessage(string("TITLE CHANGED: '") + title8.data() + "'\n");
m_testInterfaces->testRunner()->setTitleTextDirection(direction);
}
void WebTestProxyBase::didChangeIcon(WebFrame* frame, WebIconURL::Type)
{
if (m_testInterfaces->testRunner()->shouldDumpIconChanges()) {
printFrameDescription(m_delegate, frame);
m_delegate->printMessage(string(" - didChangeIcons\n"));
}
}
void WebTestProxyBase::didFinishDocumentLoad(WebFrame* frame)
{
if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
printFrameDescription(m_delegate, frame);
m_delegate->printMessage(" - didFinishDocumentLoadForFrame\n");
} else {
unsigned pendingUnloadEvents = frame->unloadListenerCount();
if (pendingUnloadEvents) {
printFrameDescription(m_delegate, frame);
char buffer[100];
snprintf(buffer, sizeof(buffer), " - has %u onunload handler(s)\n", pendingUnloadEvents);
m_delegate->printMessage(buffer);
}
}
}
void WebTestProxyBase::didHandleOnloadEvents(WebFrame* frame)
{
if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
printFrameDescription(m_delegate, frame);
m_delegate->printMessage(" - didHandleOnloadEventsForFrame\n");
}
}
void WebTestProxyBase::didFailLoad(WebFrame* frame, const WebURLError&)
{
if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
printFrameDescription(m_delegate, frame);
m_delegate->printMessage(" - didFailLoadWithError\n");
}
locationChangeDone(frame);
}
void WebTestProxyBase::didFinishLoad(WebFrame* frame)
{
if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
printFrameDescription(m_delegate, frame);
m_delegate->printMessage(" - didFinishLoadForFrame\n");
}
locationChangeDone(frame);
}
void WebTestProxyBase::didDetectXSS(WebFrame*, const WebURL&, bool)
{
if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks())
m_delegate->printMessage("didDetectXSS\n");
}
void WebTestProxyBase::didDispatchPingLoader(WebFrame*, const WebURL& url)
{
if (m_testInterfaces->testRunner()->shouldDumpPingLoaderCallbacks())
m_delegate->printMessage(string("PingLoader dispatched to '") + URLDescription(url).c_str() + "'.\n");
}
void WebTestProxyBase::willRequestResource(WebFrame* frame, const WebKit::WebCachedURLRequest& request)
{
if (m_testInterfaces->testRunner()->shouldDumpResourceRequestCallbacks()) {
printFrameDescription(m_delegate, frame);
m_delegate->printMessage(string(" - ") + request.initiatorName().utf8().data());
m_delegate->printMessage(string(" requested '") + URLDescription(request.urlRequest().url()).c_str() + "'\n");
}
}
void WebTestProxyBase::didCreateDataSource(WebFrame*, WebDataSource* ds)
{
if (!m_testInterfaces->testRunner()->deferMainResourceDataLoad())
ds->setDeferMainResourceDataLoad(false);
}
void WebTestProxyBase::willSendRequest(WebFrame*, unsigned identifier, WebKit::WebURLRequest& request, const WebKit::WebURLResponse& redirectResponse)
{
// Need to use GURL for host() and SchemeIs()
GURL url = request.url();
string requestURL = url.possibly_invalid_spec();
GURL mainDocumentURL = request.firstPartyForCookies();
if (redirectResponse.isNull() && (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks() || m_testInterfaces->testRunner()->shouldDumpResourcePriorities())) {
WEBKIT_ASSERT(m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end());
m_resourceIdentifierMap[identifier] = descriptionSuitableForTestResult(requestURL);
}
if (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks()) {
if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end())
m_delegate->printMessage("<unknown>");
else
m_delegate->printMessage(m_resourceIdentifierMap[identifier]);
m_delegate->printMessage(" - willSendRequest <NSURLRequest URL ");
m_delegate->printMessage(descriptionSuitableForTestResult(requestURL).c_str());
m_delegate->printMessage(", main document URL ");
m_delegate->printMessage(URLDescription(mainDocumentURL).c_str());
m_delegate->printMessage(", http method ");
m_delegate->printMessage(request.httpMethod().utf8().data());
m_delegate->printMessage("> redirectResponse ");
printResponseDescription(m_delegate, redirectResponse);
m_delegate->printMessage("\n");
}
if (m_testInterfaces->testRunner()->shouldDumpResourcePriorities()) {
m_delegate->printMessage(descriptionSuitableForTestResult(requestURL).c_str());
m_delegate->printMessage(" has priority ");
m_delegate->printMessage(PriorityDescription(request.priority()));
m_delegate->printMessage("\n");
}
if (m_testInterfaces->testRunner()->httpHeadersToClear()) {
const set<string> *clearHeaders = m_testInterfaces->testRunner()->httpHeadersToClear();
for (set<string>::const_iterator header = clearHeaders->begin(); header != clearHeaders->end(); ++header)
request.clearHTTPHeaderField(WebString::fromUTF8(*header));
}
string host = url.host();
if (!host.empty() && (url.SchemeIs("http") || url.SchemeIs("https"))) {
if (!isLocalhost(host) && !hostIsUsedBySomeTestsToGenerateError(host)
&& ((!mainDocumentURL.SchemeIs("http") && !mainDocumentURL.SchemeIs("https")) || isLocalhost(mainDocumentURL.host()))
&& !m_delegate->allowExternalPages()) {
m_delegate->printMessage(string("Blocked access to external URL ") + requestURL + "\n");
blockRequest(request);
return;
}
}
// Set the new substituted URL.
request.setURL(m_delegate->rewriteLayoutTestsURL(request.url().spec()));
}
void WebTestProxyBase::didReceiveResponse(WebFrame*, unsigned identifier, const WebKit::WebURLResponse& response)
{
if (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks()) {
if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end())
m_delegate->printMessage("<unknown>");
else
m_delegate->printMessage(m_resourceIdentifierMap[identifier]);
m_delegate->printMessage(" - didReceiveResponse ");
printResponseDescription(m_delegate, response);
m_delegate->printMessage("\n");
}
if (m_testInterfaces->testRunner()->shouldDumpResourceResponseMIMETypes()) {
GURL url = response.url();
WebString mimeType = response.mimeType();
m_delegate->printMessage(url.ExtractFileName());
m_delegate->printMessage(" has MIME type ");
// Simulate NSURLResponse's mapping of empty/unknown MIME types to application/octet-stream
m_delegate->printMessage(mimeType.isEmpty() ? "application/octet-stream" : mimeType.utf8().data());
m_delegate->printMessage("\n");
}
}
void WebTestProxyBase::didChangeResourcePriority(WebFrame*, unsigned identifier, const WebKit::WebURLRequest::Priority& priority)
{
if (m_testInterfaces->testRunner()->shouldDumpResourcePriorities()) {
if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end())
m_delegate->printMessage("<unknown>");
else
m_delegate->printMessage(m_resourceIdentifierMap[identifier]);
m_delegate->printMessage(" changed priority to ");
m_delegate->printMessage(PriorityDescription(priority));
m_delegate->printMessage("\n");
}
}
void WebTestProxyBase::didFinishResourceLoad(WebFrame*, unsigned identifier)
{
if (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks()) {
if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end())
m_delegate->printMessage("<unknown>");
else
m_delegate->printMessage(m_resourceIdentifierMap[identifier]);
m_delegate->printMessage(" - didFinishLoading\n");
}
m_resourceIdentifierMap.erase(identifier);
}
void WebTestProxyBase::didAddMessageToConsole(const WebConsoleMessage& message, const WebString& sourceName, unsigned sourceLine)
{
// This matches win DumpRenderTree's UIDelegate.cpp.
if (!m_logConsoleOutput)
return;
m_delegate->printMessage(string("CONSOLE MESSAGE: "));
if (sourceLine) {
char buffer[40];
snprintf(buffer, sizeof(buffer), "line %d: ", sourceLine);
m_delegate->printMessage(buffer);
}
if (!message.text.isEmpty()) {
string newMessage;
newMessage = message.text.utf8();
size_t fileProtocol = newMessage.find("file://");
if (fileProtocol != string::npos) {
newMessage = newMessage.substr(0, fileProtocol)
+ urlSuitableForTestResult(newMessage.substr(fileProtocol));
}
m_delegate->printMessage(newMessage);
}
m_delegate->printMessage(string("\n"));
}
void WebTestProxyBase::runModalAlertDialog(WebFrame*, const WebString& message)
{
m_delegate->printMessage(string("ALERT: ") + message.utf8().data() + "\n");
}
bool WebTestProxyBase::runModalConfirmDialog(WebFrame*, const WebString& message)
{
m_delegate->printMessage(string("CONFIRM: ") + message.utf8().data() + "\n");
return true;
}
bool WebTestProxyBase::runModalPromptDialog(WebFrame* frame, const WebString& message, const WebString& defaultValue, WebString*)
{
m_delegate->printMessage(string("PROMPT: ") + message.utf8().data() + ", default text: " + defaultValue.utf8().data() + "\n");
return true;
}
bool WebTestProxyBase::runModalBeforeUnloadDialog(WebFrame*, const WebString& message)
{
m_delegate->printMessage(string("CONFIRM NAVIGATION: ") + message.utf8().data() + "\n");
return !m_testInterfaces->testRunner()->shouldStayOnPageAfterHandlingBeforeUnload();
}
void WebTestProxyBase::locationChangeDone(WebFrame* frame)
{
if (frame != m_testInterfaces->testRunner()->topLoadingFrame())
return;
m_testInterfaces->testRunner()->setTopLoadingFrame(frame, true);
}
WebNavigationPolicy WebTestProxyBase::decidePolicyForNavigation(WebFrame*, WebDataSource::ExtraData*, const WebURLRequest& request, WebNavigationType type, WebNavigationPolicy defaultPolicy, bool isRedirect)
{
WebNavigationPolicy result;
if (!m_testInterfaces->testRunner()->policyDelegateEnabled())
return defaultPolicy;
m_delegate->printMessage(string("Policy delegate: attempt to load ") + URLDescription(request.url()) + " with navigation type '" + webNavigationTypeToString(type) + "'\n");
if (m_testInterfaces->testRunner()->policyDelegateIsPermissive())
result = WebKit::WebNavigationPolicyCurrentTab;
else
result = WebKit::WebNavigationPolicyIgnore;
if (m_testInterfaces->testRunner()->policyDelegateShouldNotifyDone())
m_testInterfaces->testRunner()->policyDelegateDone();
return result;
}
bool WebTestProxyBase::willCheckAndDispatchMessageEvent(WebFrame*, WebFrame*, WebSecurityOrigin, WebDOMMessageEvent)
{
if (m_testInterfaces->testRunner()->shouldInterceptPostMessage()) {
m_delegate->printMessage("intercepted postMessage\n");
return true;
}
return false;
}
void WebTestProxyBase::resetInputMethod()
{
// If a composition text exists, then we need to let the browser process
// to cancel the input method's ongoing composition session.
if (m_webWidget)
m_webWidget->confirmComposition();
}
}