Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2012 Google Inc. All rights reserved. |
| 3 | * |
| 4 | * Redistribution and use in source and binary forms, with or without |
| 5 | * modification, are permitted provided that the following conditions are |
| 6 | * met: |
| 7 | * |
| 8 | * * Redistributions of source code must retain the above copyright |
| 9 | * notice, this list of conditions and the following disclaimer. |
| 10 | * * Redistributions in binary form must reproduce the above |
| 11 | * copyright notice, this list of conditions and the following disclaimer |
| 12 | * in the documentation and/or other materials provided with the |
| 13 | * distribution. |
| 14 | * * Neither the name of Google Inc. nor the names of its |
| 15 | * contributors may be used to endorse or promote products derived from |
| 16 | * this software without specific prior written permission. |
| 17 | * |
| 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | */ |
| 30 | |
Ben Murdoch | 591b958 | 2013-07-10 11:41:44 +0100 | [diff] [blame] | 31 | #include "public/testing/WebTestProxy.h" |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 32 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 33 | #include "AccessibilityControllerChromium.h" |
| 34 | #include "EventSender.h" |
Torne (Richard Coles) | 93ac45c | 2013-05-29 14:40:20 +0100 | [diff] [blame] | 35 | #include "MockColorChooser.h" |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 36 | #include "MockWebSpeechInputController.h" |
| 37 | #include "MockWebSpeechRecognizer.h" |
Torne (Richard Coles) | 521d96e | 2013-06-19 11:58:24 +0100 | [diff] [blame] | 38 | #include "MockWebValidationMessageClient.h" |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 39 | #include "SpellCheckClient.h" |
| 40 | #include "TestCommon.h" |
| 41 | #include "TestInterfaces.h" |
| 42 | #include "TestPlugin.h" |
| 43 | #include "TestRunner.h" |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 44 | #include "WebUserMediaClientMock.h" |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 45 | #include "public/platform/WebCString.h" |
| 46 | #include "public/platform/WebURLError.h" |
| 47 | #include "public/platform/WebURLRequest.h" |
| 48 | #include "public/platform/WebURLResponse.h" |
Ben Murdoch | 591b958 | 2013-07-10 11:41:44 +0100 | [diff] [blame] | 49 | #include "public/testing/WebTestDelegate.h" |
| 50 | #include "public/testing/WebTestInterfaces.h" |
| 51 | #include "public/testing/WebTestRunner.h" |
| 52 | #include "public/web/WebAccessibilityNotification.h" |
| 53 | #include "public/web/WebAccessibilityObject.h" |
| 54 | #include "public/web/WebCachedURLRequest.h" |
| 55 | #include "public/web/WebConsoleMessage.h" |
| 56 | #include "public/web/WebDataSource.h" |
| 57 | #include "public/web/WebDeviceOrientationClientMock.h" |
| 58 | #include "public/web/WebDocument.h" |
| 59 | #include "public/web/WebElement.h" |
| 60 | #include "public/web/WebFrame.h" |
| 61 | #include "public/web/WebGeolocationClientMock.h" |
| 62 | #include "public/web/WebHistoryItem.h" |
| 63 | #include "public/web/WebNode.h" |
| 64 | #include "public/web/WebPluginParams.h" |
| 65 | #include "public/web/WebPrintParams.h" |
| 66 | #include "public/web/WebRange.h" |
| 67 | #include "public/web/WebScriptController.h" |
| 68 | #include "public/web/WebUserGestureIndicator.h" |
| 69 | #include "public/web/WebView.h" |
| 70 | |
| 71 | // FIXME: Including platform_canvas.h here is a layering violation. |
| 72 | #include <cctype> |
| 73 | #include "skia/ext/platform_canvas.h" |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 74 | |
| 75 | using namespace WebKit; |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 76 | using namespace std; |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 77 | |
| 78 | namespace WebTestRunner { |
| 79 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 80 | namespace { |
| 81 | |
Torne (Richard Coles) | 521d96e | 2013-06-19 11:58:24 +0100 | [diff] [blame] | 82 | class HostMethodTask : public WebMethodTask<WebTestProxyBase> { |
| 83 | public: |
| 84 | typedef void (WebTestProxyBase::*CallbackMethodType)(); |
| 85 | HostMethodTask(WebTestProxyBase* object, CallbackMethodType callback) |
| 86 | : WebMethodTask<WebTestProxyBase>(object) |
| 87 | , m_callback(callback) |
| 88 | { } |
| 89 | |
| 90 | virtual void runIfValid() { (m_object->*m_callback)(); } |
| 91 | |
| 92 | private: |
| 93 | CallbackMethodType m_callback; |
| 94 | }; |
| 95 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 96 | void printNodeDescription(WebTestDelegate* delegate, const WebNode& node, int exception) |
| 97 | { |
| 98 | if (exception) { |
| 99 | delegate->printMessage("ERROR"); |
| 100 | return; |
| 101 | } |
| 102 | if (node.isNull()) { |
| 103 | delegate->printMessage("(null)"); |
| 104 | return; |
| 105 | } |
| 106 | delegate->printMessage(node.nodeName().utf8().data()); |
| 107 | const WebNode& parent = node.parentNode(); |
| 108 | if (!parent.isNull()) { |
| 109 | delegate->printMessage(" > "); |
| 110 | printNodeDescription(delegate, parent, 0); |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | void printRangeDescription(WebTestDelegate* delegate, const WebRange& range) |
| 115 | { |
| 116 | if (range.isNull()) { |
| 117 | delegate->printMessage("(null)"); |
| 118 | return; |
| 119 | } |
| 120 | char buffer[100]; |
| 121 | snprintf(buffer, sizeof(buffer), "range from %d of ", range.startOffset()); |
| 122 | delegate->printMessage(buffer); |
| 123 | int exception = 0; |
| 124 | WebNode startNode = range.startContainer(exception); |
| 125 | printNodeDescription(delegate, startNode, exception); |
| 126 | snprintf(buffer, sizeof(buffer), " to %d of ", range.endOffset()); |
| 127 | delegate->printMessage(buffer); |
| 128 | WebNode endNode = range.endContainer(exception); |
| 129 | printNodeDescription(delegate, endNode, exception); |
| 130 | } |
| 131 | |
| 132 | string editingActionDescription(WebEditingAction action) |
| 133 | { |
| 134 | switch (action) { |
| 135 | case WebKit::WebEditingActionTyped: |
| 136 | return "WebViewInsertActionTyped"; |
| 137 | case WebKit::WebEditingActionPasted: |
| 138 | return "WebViewInsertActionPasted"; |
| 139 | case WebKit::WebEditingActionDropped: |
| 140 | return "WebViewInsertActionDropped"; |
| 141 | } |
| 142 | return "(UNKNOWN ACTION)"; |
| 143 | } |
| 144 | |
| 145 | string textAffinityDescription(WebTextAffinity affinity) |
| 146 | { |
| 147 | switch (affinity) { |
| 148 | case WebKit::WebTextAffinityUpstream: |
| 149 | return "NSSelectionAffinityUpstream"; |
| 150 | case WebKit::WebTextAffinityDownstream: |
| 151 | return "NSSelectionAffinityDownstream"; |
| 152 | } |
| 153 | return "(UNKNOWN AFFINITY)"; |
| 154 | } |
| 155 | |
| 156 | void printFrameDescription(WebTestDelegate* delegate, WebFrame* frame) |
| 157 | { |
| 158 | string name8 = frame->uniqueName().utf8(); |
| 159 | if (frame == frame->view()->mainFrame()) { |
| 160 | if (!name8.length()) { |
| 161 | delegate->printMessage("main frame"); |
| 162 | return; |
| 163 | } |
| 164 | delegate->printMessage(string("main frame \"") + name8 + "\""); |
| 165 | return; |
| 166 | } |
| 167 | if (!name8.length()) { |
| 168 | delegate->printMessage("frame (anonymous)"); |
| 169 | return; |
| 170 | } |
| 171 | delegate->printMessage(string("frame \"") + name8 + "\""); |
| 172 | } |
| 173 | |
| 174 | void printFrameUserGestureStatus(WebTestDelegate* delegate, WebFrame* frame, const char* msg) |
| 175 | { |
| 176 | bool isUserGesture = WebUserGestureIndicator::isProcessingUserGesture(); |
| 177 | delegate->printMessage(string("Frame with user gesture \"") + (isUserGesture ? "true" : "false") + "\"" + msg); |
| 178 | } |
| 179 | |
| 180 | // Used to write a platform neutral file:/// URL by taking the |
| 181 | // filename and its directory. (e.g., converts |
| 182 | // "file:///tmp/foo/bar.txt" to just "bar.txt"). |
| 183 | string descriptionSuitableForTestResult(const string& url) |
| 184 | { |
| 185 | if (url.empty() || string::npos == url.find("file://")) |
| 186 | return url; |
| 187 | |
| 188 | size_t pos = url.rfind('/'); |
| 189 | if (pos == string::npos || !pos) |
| 190 | return "ERROR:" + url; |
| 191 | pos = url.rfind('/', pos - 1); |
| 192 | if (pos == string::npos) |
| 193 | return "ERROR:" + url; |
| 194 | |
| 195 | return url.substr(pos + 1); |
| 196 | } |
| 197 | |
| 198 | void printResponseDescription(WebTestDelegate* delegate, const WebURLResponse& response) |
| 199 | { |
| 200 | if (response.isNull()) { |
| 201 | delegate->printMessage("(null)"); |
| 202 | return; |
| 203 | } |
| 204 | string url = response.url().spec(); |
| 205 | char data[100]; |
| 206 | snprintf(data, sizeof(data), "%d", response. httpStatusCode()); |
| 207 | delegate->printMessage(string("<NSURLResponse ") + descriptionSuitableForTestResult(url) + ", http status code " + data + ">"); |
| 208 | } |
| 209 | |
| 210 | string URLDescription(const GURL& url) |
| 211 | { |
| 212 | if (url.SchemeIs("file")) |
| 213 | return url.ExtractFileName(); |
| 214 | return url.possibly_invalid_spec(); |
| 215 | } |
| 216 | |
| 217 | string PriorityDescription(const WebURLRequest::Priority& priority) |
| 218 | { |
| 219 | switch (priority) { |
| 220 | case WebURLRequest::PriorityVeryLow: |
| 221 | return "VeryLow"; |
| 222 | case WebURLRequest::PriorityLow: |
| 223 | return "Low"; |
| 224 | case WebURLRequest::PriorityMedium: |
| 225 | return "Medium"; |
| 226 | case WebURLRequest::PriorityHigh: |
| 227 | return "High"; |
| 228 | case WebURLRequest::PriorityVeryHigh: |
| 229 | return "VeryHigh"; |
| 230 | case WebURLRequest::PriorityUnresolved: |
| 231 | default: |
| 232 | return "Unresolved"; |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | void blockRequest(WebURLRequest& request) |
| 237 | { |
| 238 | request.setURL(WebURL()); |
| 239 | } |
| 240 | |
| 241 | bool isLocalhost(const string& host) |
| 242 | { |
| 243 | return host == "127.0.0.1" || host == "localhost"; |
| 244 | } |
| 245 | |
| 246 | bool hostIsUsedBySomeTestsToGenerateError(const string& host) |
| 247 | { |
| 248 | return host == "255.255.255.255"; |
| 249 | } |
| 250 | |
| 251 | // Used to write a platform neutral file:/// URL by only taking the filename |
| 252 | // (e.g., converts "file:///tmp/foo.txt" to just "foo.txt"). |
| 253 | string urlSuitableForTestResult(const string& url) |
| 254 | { |
| 255 | if (url.empty() || string::npos == url.find("file://")) |
| 256 | return url; |
| 257 | |
| 258 | size_t pos = url.rfind('/'); |
| 259 | if (pos == string::npos) { |
| 260 | #ifdef WIN32 |
| 261 | pos = url.rfind('\\'); |
| 262 | if (pos == string::npos) |
| 263 | pos = 0; |
| 264 | #else |
| 265 | pos = 0; |
| 266 | #endif |
| 267 | } |
| 268 | string filename = url.substr(pos + 1); |
| 269 | if (filename.empty()) |
| 270 | return "file:"; // A WebKit test has this in its expected output. |
| 271 | return filename; |
| 272 | } |
| 273 | |
| 274 | // WebNavigationType debugging strings taken from PolicyDelegate.mm. |
| 275 | const char* linkClickedString = "link clicked"; |
| 276 | const char* formSubmittedString = "form submitted"; |
| 277 | const char* backForwardString = "back/forward"; |
| 278 | const char* reloadString = "reload"; |
| 279 | const char* formResubmittedString = "form resubmitted"; |
| 280 | const char* otherString = "other"; |
| 281 | const char* illegalString = "illegal value"; |
| 282 | |
| 283 | // Get a debugging string from a WebNavigationType. |
| 284 | const char* webNavigationTypeToString(WebNavigationType type) |
| 285 | { |
| 286 | switch (type) { |
| 287 | case WebKit::WebNavigationTypeLinkClicked: |
| 288 | return linkClickedString; |
| 289 | case WebKit::WebNavigationTypeFormSubmitted: |
| 290 | return formSubmittedString; |
| 291 | case WebKit::WebNavigationTypeBackForward: |
| 292 | return backForwardString; |
| 293 | case WebKit::WebNavigationTypeReload: |
| 294 | return reloadString; |
| 295 | case WebKit::WebNavigationTypeFormResubmitted: |
| 296 | return formResubmittedString; |
| 297 | case WebKit::WebNavigationTypeOther: |
| 298 | return otherString; |
| 299 | } |
| 300 | return illegalString; |
| 301 | } |
| 302 | |
| 303 | string dumpDocumentText(WebFrame* frame) |
| 304 | { |
| 305 | // We use the document element's text instead of the body text here because |
| 306 | // not all documents have a body, such as XML documents. |
| 307 | WebElement documentElement = frame->document().documentElement(); |
| 308 | if (documentElement.isNull()) |
| 309 | return string(); |
| 310 | return documentElement.innerText().utf8(); |
| 311 | } |
| 312 | |
| 313 | string dumpFramesAsText(WebFrame* frame, bool recursive) |
| 314 | { |
| 315 | string result; |
| 316 | |
| 317 | // Add header for all but the main frame. Skip empty frames. |
| 318 | if (frame->parent() && !frame->document().documentElement().isNull()) { |
| 319 | result.append("\n--------\nFrame: '"); |
| 320 | result.append(frame->uniqueName().utf8().data()); |
| 321 | result.append("'\n--------\n"); |
| 322 | } |
| 323 | |
| 324 | result.append(dumpDocumentText(frame)); |
| 325 | result.append("\n"); |
| 326 | |
| 327 | if (recursive) { |
| 328 | for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling()) |
| 329 | result.append(dumpFramesAsText(child, recursive)); |
| 330 | } |
| 331 | |
| 332 | return result; |
| 333 | } |
| 334 | |
| 335 | string dumpFramesAsPrintedText(WebFrame* frame, bool recursive) |
| 336 | { |
| 337 | string result; |
| 338 | |
| 339 | // Cannot do printed format for anything other than HTML |
| 340 | if (!frame->document().isHTMLDocument()) |
| 341 | return string(); |
| 342 | |
| 343 | // Add header for all but the main frame. Skip empty frames. |
| 344 | if (frame->parent() && !frame->document().documentElement().isNull()) { |
| 345 | result.append("\n--------\nFrame: '"); |
| 346 | result.append(frame->uniqueName().utf8().data()); |
| 347 | result.append("'\n--------\n"); |
| 348 | } |
| 349 | |
| 350 | result.append(frame->renderTreeAsText(WebFrame::RenderAsTextPrinting).utf8()); |
| 351 | result.append("\n"); |
| 352 | |
| 353 | if (recursive) { |
| 354 | for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling()) |
| 355 | result.append(dumpFramesAsPrintedText(child, recursive)); |
| 356 | } |
| 357 | |
| 358 | return result; |
| 359 | } |
| 360 | |
| 361 | string dumpFrameScrollPosition(WebFrame* frame, bool recursive) |
| 362 | { |
| 363 | string result; |
| 364 | WebSize offset = frame->scrollOffset(); |
| 365 | if (offset.width > 0 || offset.height > 0) { |
| 366 | if (frame->parent()) |
| 367 | result = string("frame '") + frame->uniqueName().utf8().data() + "' "; |
| 368 | char data[100]; |
| 369 | snprintf(data, sizeof(data), "scrolled to %d,%d\n", offset.width, offset.height); |
| 370 | result += data; |
| 371 | } |
| 372 | |
| 373 | if (!recursive) |
| 374 | return result; |
| 375 | for (WebFrame* child = frame->firstChild(); child; child = child->nextSibling()) |
| 376 | result += dumpFrameScrollPosition(child, recursive); |
| 377 | return result; |
| 378 | } |
| 379 | |
| 380 | struct ToLower { |
| 381 | char16 operator()(char16 c) { return tolower(c); } |
| 382 | }; |
| 383 | |
| 384 | // Returns True if item1 < item2. |
| 385 | bool HistoryItemCompareLess(const WebHistoryItem& item1, const WebHistoryItem& item2) |
| 386 | { |
| 387 | string16 target1 = item1.target(); |
| 388 | string16 target2 = item2.target(); |
| 389 | std::transform(target1.begin(), target1.end(), target1.begin(), ToLower()); |
| 390 | std::transform(target2.begin(), target2.end(), target2.begin(), ToLower()); |
| 391 | return target1 < target2; |
| 392 | } |
| 393 | |
| 394 | string dumpHistoryItem(const WebHistoryItem& item, int indent, bool isCurrent) |
| 395 | { |
| 396 | string result; |
| 397 | |
| 398 | if (isCurrent) { |
| 399 | result.append("curr->"); |
| 400 | result.append(indent - 6, ' '); // 6 == "curr->".length() |
| 401 | } else |
| 402 | result.append(indent, ' '); |
| 403 | |
| 404 | string url = normalizeLayoutTestURL(item.urlString().utf8()); |
| 405 | result.append(url); |
| 406 | if (!item.target().isEmpty()) { |
| 407 | result.append(" (in frame \""); |
| 408 | result.append(item.target().utf8()); |
| 409 | result.append("\")"); |
| 410 | } |
| 411 | if (item.isTargetItem()) |
| 412 | result.append(" **nav target**"); |
| 413 | result.append("\n"); |
| 414 | |
| 415 | const WebVector<WebHistoryItem>& children = item.children(); |
| 416 | if (!children.isEmpty()) { |
| 417 | // Must sort to eliminate arbitrary result ordering which defeats |
| 418 | // reproducible testing. |
| 419 | // FIXME: WebVector should probably just be a std::vector!! |
| 420 | std::vector<WebHistoryItem> sortedChildren; |
| 421 | for (size_t i = 0; i < children.size(); ++i) |
| 422 | sortedChildren.push_back(children[i]); |
| 423 | std::sort(sortedChildren.begin(), sortedChildren.end(), HistoryItemCompareLess); |
| 424 | for (size_t i = 0; i < sortedChildren.size(); ++i) |
| 425 | result += dumpHistoryItem(sortedChildren[i], indent + 4, false); |
| 426 | } |
| 427 | |
| 428 | return result; |
| 429 | } |
| 430 | |
| 431 | void dumpBackForwardList(const WebVector<WebHistoryItem>& history, size_t currentEntryIndex, string& result) |
| 432 | { |
| 433 | result.append("\n============== Back Forward List ==============\n"); |
| 434 | for (size_t index = 0; index < history.size(); ++index) |
| 435 | result.append(dumpHistoryItem(history[index], 8, index == currentEntryIndex)); |
| 436 | result.append("===============================================\n"); |
| 437 | } |
| 438 | |
| 439 | string dumpAllBackForwardLists(TestInterfaces* interfaces, WebTestDelegate* delegate) |
| 440 | { |
| 441 | string result; |
| 442 | const vector<WebTestProxyBase*>& windowList = interfaces->windowList(); |
| 443 | for (unsigned i = 0; i < windowList.size(); ++i) { |
| 444 | size_t currentEntryIndex = 0; |
| 445 | WebVector<WebHistoryItem> history; |
| 446 | delegate->captureHistoryForWindow(windowList.at(i), &history, ¤tEntryIndex); |
| 447 | dumpBackForwardList(history, currentEntryIndex, result); |
| 448 | } |
| 449 | return result; |
| 450 | } |
| 451 | |
| 452 | } |
| 453 | |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 454 | WebTestProxyBase::WebTestProxyBase() |
| 455 | : m_testInterfaces(0) |
| 456 | , m_delegate(0) |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 457 | , m_webWidget(0) |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 458 | , m_spellcheck(new SpellCheckClient) |
Torne (Richard Coles) | 93ac45c | 2013-05-29 14:40:20 +0100 | [diff] [blame] | 459 | , m_chooserCount(0) |
Torne (Richard Coles) | 521d96e | 2013-06-19 11:58:24 +0100 | [diff] [blame] | 460 | , m_validationMessageClient(new MockWebValidationMessageClient()) |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 461 | { |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 462 | reset(); |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 463 | } |
| 464 | |
| 465 | WebTestProxyBase::~WebTestProxyBase() |
| 466 | { |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 467 | m_testInterfaces->windowClosed(this); |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 468 | } |
| 469 | |
| 470 | void WebTestProxyBase::setInterfaces(WebTestInterfaces* interfaces) |
| 471 | { |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 472 | m_testInterfaces = interfaces->testInterfaces(); |
| 473 | m_testInterfaces->windowOpened(this); |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 474 | } |
| 475 | |
| 476 | void WebTestProxyBase::setDelegate(WebTestDelegate* delegate) |
| 477 | { |
| 478 | m_delegate = delegate; |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 479 | m_spellcheck->setDelegate(delegate); |
Torne (Richard Coles) | 521d96e | 2013-06-19 11:58:24 +0100 | [diff] [blame] | 480 | m_validationMessageClient->setDelegate(delegate); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 481 | #if ENABLE_INPUT_SPEECH |
| 482 | if (m_speechInputController.get()) |
| 483 | m_speechInputController->setDelegate(delegate); |
| 484 | #endif |
| 485 | if (m_speechRecognizer.get()) |
| 486 | m_speechRecognizer->setDelegate(delegate); |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 487 | } |
| 488 | |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 489 | void WebTestProxyBase::setWidget(WebWidget* widget) |
| 490 | { |
| 491 | m_webWidget = widget; |
| 492 | } |
| 493 | |
| 494 | WebWidget* WebTestProxyBase::webWidget() |
| 495 | { |
| 496 | return m_webWidget; |
| 497 | } |
| 498 | |
| 499 | WebView* WebTestProxyBase::webView() |
| 500 | { |
| 501 | WEBKIT_ASSERT(m_webWidget); |
| 502 | // TestRunner does not support popup widgets. So m_webWidget is always a WebView. |
| 503 | return static_cast<WebView*>(m_webWidget); |
| 504 | } |
| 505 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 506 | void WebTestProxyBase::reset() |
| 507 | { |
| 508 | m_paintRect = WebRect(); |
| 509 | m_canvas.reset(); |
| 510 | m_isPainting = false; |
Torne (Richard Coles) | 521d96e | 2013-06-19 11:58:24 +0100 | [diff] [blame] | 511 | m_animateScheduled = false; |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 512 | m_resourceIdentifierMap.clear(); |
| 513 | m_logConsoleOutput = true; |
| 514 | if (m_geolocationClient.get()) |
| 515 | m_geolocationClient->resetMock(); |
| 516 | #if ENABLE_INPUT_SPEECH |
| 517 | if (m_speechInputController.get()) |
| 518 | m_speechInputController->clearResults(); |
| 519 | #endif |
| 520 | } |
| 521 | |
| 522 | WebSpellCheckClient* WebTestProxyBase::spellCheckClient() const |
| 523 | { |
| 524 | return m_spellcheck.get(); |
| 525 | } |
| 526 | |
Torne (Richard Coles) | 521d96e | 2013-06-19 11:58:24 +0100 | [diff] [blame] | 527 | WebValidationMessageClient* WebTestProxyBase::validationMessageClient() |
| 528 | { |
| 529 | return m_validationMessageClient.get(); |
| 530 | } |
| 531 | |
Torne (Richard Coles) | 93ac45c | 2013-05-29 14:40:20 +0100 | [diff] [blame] | 532 | WebColorChooser* WebTestProxyBase::createColorChooser(WebColorChooserClient* client, const WebKit::WebColor& color) |
| 533 | { |
| 534 | // This instance is deleted by WebCore::ColorInputType |
| 535 | return new MockColorChooser(client, m_delegate, this); |
| 536 | } |
| 537 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 538 | string WebTestProxyBase::captureTree(bool debugRenderTree) |
| 539 | { |
| 540 | WebScriptController::flushConsoleMessages(); |
| 541 | |
| 542 | bool shouldDumpAsText = m_testInterfaces->testRunner()->shouldDumpAsText(); |
| 543 | bool shouldDumpAsPrinted = m_testInterfaces->testRunner()->isPrinting(); |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 544 | WebFrame* frame = webView()->mainFrame(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 545 | string dataUtf8; |
| 546 | if (shouldDumpAsText) { |
| 547 | bool recursive = m_testInterfaces->testRunner()->shouldDumpChildFramesAsText(); |
| 548 | dataUtf8 = shouldDumpAsPrinted ? dumpFramesAsPrintedText(frame, recursive) : dumpFramesAsText(frame, recursive); |
| 549 | } else { |
| 550 | bool recursive = m_testInterfaces->testRunner()->shouldDumpChildFrameScrollPositions(); |
| 551 | WebFrame::RenderAsTextControls renderTextBehavior = WebFrame::RenderAsTextNormal; |
| 552 | if (shouldDumpAsPrinted) |
| 553 | renderTextBehavior |= WebFrame::RenderAsTextPrinting; |
| 554 | if (debugRenderTree) |
| 555 | renderTextBehavior |= WebFrame::RenderAsTextDebug; |
| 556 | dataUtf8 = frame->renderTreeAsText(renderTextBehavior).utf8(); |
| 557 | dataUtf8 += dumpFrameScrollPosition(frame, recursive); |
| 558 | } |
| 559 | |
| 560 | if (m_testInterfaces->testRunner()->shouldDumpBackForwardList()) |
| 561 | dataUtf8 += dumpAllBackForwardLists(m_testInterfaces, m_delegate); |
| 562 | |
| 563 | return dataUtf8; |
| 564 | } |
| 565 | |
| 566 | SkCanvas* WebTestProxyBase::capturePixels() |
| 567 | { |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 568 | webWidget()->layout(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 569 | if (m_testInterfaces->testRunner()->testRepaint()) { |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 570 | WebSize viewSize = webWidget()->size(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 571 | int width = viewSize.width; |
| 572 | int height = viewSize.height; |
| 573 | if (m_testInterfaces->testRunner()->sweepHorizontally()) { |
| 574 | for (WebRect column(0, 0, 1, height); column.x < width; column.x++) |
| 575 | paintRect(column); |
| 576 | } else { |
| 577 | for (WebRect line(0, 0, width, 1); line.y < height; line.y++) |
| 578 | paintRect(line); |
| 579 | } |
| 580 | } else if (m_testInterfaces->testRunner()->isPrinting()) |
| 581 | paintPagesWithBoundaries(); |
| 582 | else |
| 583 | paintInvalidatedRegion(); |
| 584 | |
| 585 | // See if we need to draw the selection bounds rect. Selection bounds |
| 586 | // rect is the rect enclosing the (possibly transformed) selection. |
| 587 | // The rect should be drawn after everything is laid out and painted. |
| 588 | if (m_testInterfaces->testRunner()->shouldDumpSelectionRect()) { |
| 589 | // If there is a selection rect - draw a red 1px border enclosing rect |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 590 | WebRect wr = webView()->mainFrame()->selectionBoundsRect(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 591 | if (!wr.isEmpty()) { |
| 592 | // Render a red rectangle bounding selection rect |
| 593 | SkPaint paint; |
| 594 | paint.setColor(0xFFFF0000); // Fully opaque red |
| 595 | paint.setStyle(SkPaint::kStroke_Style); |
| 596 | paint.setFlags(SkPaint::kAntiAlias_Flag); |
| 597 | paint.setStrokeWidth(1.0f); |
| 598 | SkIRect rect; // Bounding rect |
| 599 | rect.set(wr.x, wr.y, wr.x + wr.width, wr.y + wr.height); |
| 600 | canvas()->drawIRect(rect, paint); |
| 601 | } |
| 602 | } |
| 603 | |
| 604 | return canvas(); |
| 605 | } |
| 606 | |
| 607 | void WebTestProxyBase::setLogConsoleOutput(bool enabled) |
| 608 | { |
| 609 | m_logConsoleOutput = enabled; |
| 610 | } |
| 611 | |
| 612 | void WebTestProxyBase::paintRect(const WebRect& rect) |
| 613 | { |
| 614 | WEBKIT_ASSERT(!m_isPainting); |
| 615 | WEBKIT_ASSERT(canvas()); |
| 616 | m_isPainting = true; |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 617 | float deviceScaleFactor = webView()->deviceScaleFactor(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 618 | int scaledX = static_cast<int>(static_cast<float>(rect.x) * deviceScaleFactor); |
| 619 | int scaledY = static_cast<int>(static_cast<float>(rect.y) * deviceScaleFactor); |
| 620 | int scaledWidth = static_cast<int>(ceil(static_cast<float>(rect.width) * deviceScaleFactor)); |
| 621 | int scaledHeight = static_cast<int>(ceil(static_cast<float>(rect.height) * deviceScaleFactor)); |
| 622 | WebRect deviceRect(scaledX, scaledY, scaledWidth, scaledHeight); |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 623 | webWidget()->paint(canvas(), deviceRect); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 624 | m_isPainting = false; |
| 625 | } |
| 626 | |
| 627 | void WebTestProxyBase::paintInvalidatedRegion() |
| 628 | { |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 629 | webWidget()->animate(0.0); |
| 630 | webWidget()->layout(); |
| 631 | WebSize widgetSize = webWidget()->size(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 632 | WebRect clientRect(0, 0, widgetSize.width, widgetSize.height); |
| 633 | |
| 634 | // Paint the canvas if necessary. Allow painting to generate extra rects |
| 635 | // for the first two calls. This is necessary because some WebCore rendering |
| 636 | // objects update their layout only when painted. |
| 637 | // Store the total area painted in total_paint. Then tell the gdk window |
| 638 | // to update that area after we're done painting it. |
| 639 | for (int i = 0; i < 3; ++i) { |
| 640 | // rect = intersect(m_paintRect , clientRect) |
| 641 | WebRect damageRect = m_paintRect; |
| 642 | int left = max(damageRect.x, clientRect.x); |
| 643 | int top = max(damageRect.y, clientRect.y); |
| 644 | int right = min(damageRect.x + damageRect.width, clientRect.x + clientRect.width); |
| 645 | int bottom = min(damageRect.y + damageRect.height, clientRect.y + clientRect.height); |
| 646 | WebRect rect; |
| 647 | if (left < right && top < bottom) |
| 648 | rect = WebRect(left, top, right - left, bottom - top); |
| 649 | |
| 650 | m_paintRect = WebRect(); |
| 651 | if (rect.isEmpty()) |
| 652 | continue; |
| 653 | paintRect(rect); |
| 654 | } |
| 655 | WEBKIT_ASSERT(m_paintRect.isEmpty()); |
| 656 | } |
| 657 | |
| 658 | void WebTestProxyBase::paintPagesWithBoundaries() |
| 659 | { |
| 660 | WEBKIT_ASSERT(!m_isPainting); |
| 661 | WEBKIT_ASSERT(canvas()); |
| 662 | m_isPainting = true; |
| 663 | |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 664 | WebSize pageSizeInPixels = webWidget()->size(); |
| 665 | WebFrame* webFrame = webView()->mainFrame(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 666 | |
| 667 | int pageCount = webFrame->printBegin(pageSizeInPixels); |
| 668 | int totalHeight = pageCount * (pageSizeInPixels.height + 1) - 1; |
| 669 | |
| 670 | SkCanvas* testCanvas = skia::TryCreateBitmapCanvas(pageSizeInPixels.width, totalHeight, true); |
| 671 | if (testCanvas) { |
| 672 | discardBackingStore(); |
| 673 | m_canvas.reset(testCanvas); |
| 674 | } else { |
| 675 | webFrame->printEnd(); |
| 676 | return; |
| 677 | } |
| 678 | |
| 679 | webFrame->printPagesWithBoundaries(canvas(), pageSizeInPixels); |
| 680 | webFrame->printEnd(); |
| 681 | |
| 682 | m_isPainting = false; |
| 683 | } |
| 684 | |
| 685 | SkCanvas* WebTestProxyBase::canvas() |
| 686 | { |
| 687 | if (m_canvas.get()) |
| 688 | return m_canvas.get(); |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 689 | WebSize widgetSize = webWidget()->size(); |
| 690 | float deviceScaleFactor = webView()->deviceScaleFactor(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 691 | int scaledWidth = static_cast<int>(ceil(static_cast<float>(widgetSize.width) * deviceScaleFactor)); |
| 692 | int scaledHeight = static_cast<int>(ceil(static_cast<float>(widgetSize.height) * deviceScaleFactor)); |
| 693 | m_canvas.reset(skia::CreateBitmapCanvas(scaledWidth, scaledHeight, true)); |
| 694 | return m_canvas.get(); |
| 695 | } |
| 696 | |
| 697 | // Paints the entire canvas a semi-transparent black (grayish). This is used |
| 698 | // by the layout tests in fast/repaint. The alpha value matches upstream. |
| 699 | void WebTestProxyBase::displayRepaintMask() |
| 700 | { |
| 701 | canvas()->drawARGB(167, 0, 0, 0); |
| 702 | } |
| 703 | |
| 704 | void WebTestProxyBase::display() |
| 705 | { |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 706 | const WebKit::WebSize& size = webWidget()->size(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 707 | WebRect rect(0, 0, size.width, size.height); |
| 708 | m_paintRect = rect; |
| 709 | paintInvalidatedRegion(); |
| 710 | displayRepaintMask(); |
| 711 | } |
| 712 | |
| 713 | void WebTestProxyBase::displayInvalidatedRegion() |
| 714 | { |
| 715 | paintInvalidatedRegion(); |
| 716 | displayRepaintMask(); |
| 717 | } |
| 718 | |
| 719 | void WebTestProxyBase::discardBackingStore() |
| 720 | { |
| 721 | m_canvas.reset(); |
| 722 | } |
| 723 | |
| 724 | WebGeolocationClientMock* WebTestProxyBase::geolocationClientMock() |
| 725 | { |
| 726 | if (!m_geolocationClient.get()) |
| 727 | m_geolocationClient.reset(WebGeolocationClientMock::create()); |
| 728 | return m_geolocationClient.get(); |
| 729 | } |
| 730 | |
| 731 | WebDeviceOrientationClientMock* WebTestProxyBase::deviceOrientationClientMock() |
| 732 | { |
| 733 | if (!m_deviceOrientationClient.get()) |
| 734 | m_deviceOrientationClient.reset(WebDeviceOrientationClientMock::create()); |
| 735 | return m_deviceOrientationClient.get(); |
| 736 | } |
| 737 | |
| 738 | #if ENABLE_INPUT_SPEECH |
| 739 | MockWebSpeechInputController* WebTestProxyBase::speechInputControllerMock() |
| 740 | { |
| 741 | WEBKIT_ASSERT(m_speechInputController.get()); |
| 742 | return m_speechInputController.get(); |
| 743 | } |
| 744 | #endif |
| 745 | |
| 746 | MockWebSpeechRecognizer* WebTestProxyBase::speechRecognizerMock() |
| 747 | { |
| 748 | if (!m_speechRecognizer.get()) { |
| 749 | m_speechRecognizer.reset(new MockWebSpeechRecognizer()); |
| 750 | m_speechRecognizer->setDelegate(m_delegate); |
| 751 | } |
| 752 | return m_speechRecognizer.get(); |
| 753 | } |
| 754 | |
| 755 | void WebTestProxyBase::didInvalidateRect(const WebRect& rect) |
| 756 | { |
| 757 | // m_paintRect = m_paintRect U rect |
| 758 | if (rect.isEmpty()) |
| 759 | return; |
| 760 | if (m_paintRect.isEmpty()) { |
| 761 | m_paintRect = rect; |
| 762 | return; |
| 763 | } |
| 764 | int left = min(m_paintRect.x, rect.x); |
| 765 | int top = min(m_paintRect.y, rect.y); |
| 766 | int right = max(m_paintRect.x + m_paintRect.width, rect.x + rect.width); |
| 767 | int bottom = max(m_paintRect.y + m_paintRect.height, rect.y + rect.height); |
| 768 | m_paintRect = WebRect(left, top, right - left, bottom - top); |
| 769 | } |
| 770 | |
| 771 | void WebTestProxyBase::didScrollRect(int, int, const WebRect& clipRect) |
| 772 | { |
| 773 | didInvalidateRect(clipRect); |
| 774 | } |
| 775 | |
Torne (Richard Coles) | 521d96e | 2013-06-19 11:58:24 +0100 | [diff] [blame] | 776 | void WebTestProxyBase::invalidateAll() |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 777 | { |
| 778 | m_paintRect = WebRect(0, 0, INT_MAX, INT_MAX); |
| 779 | } |
| 780 | |
Torne (Richard Coles) | 521d96e | 2013-06-19 11:58:24 +0100 | [diff] [blame] | 781 | void WebTestProxyBase::scheduleComposite() |
| 782 | { |
| 783 | invalidateAll(); |
| 784 | } |
| 785 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 786 | void WebTestProxyBase::scheduleAnimation() |
| 787 | { |
Torne (Richard Coles) | 521d96e | 2013-06-19 11:58:24 +0100 | [diff] [blame] | 788 | if (!m_testInterfaces->testRunner()->testIsRunning()) |
| 789 | return; |
| 790 | |
| 791 | if (!m_animateScheduled) { |
| 792 | m_animateScheduled = true; |
| 793 | m_delegate->postDelayedTask(new HostMethodTask(this, &WebTestProxyBase::animateNow), 1); |
| 794 | } |
| 795 | } |
| 796 | |
| 797 | void WebTestProxyBase::animateNow() |
| 798 | { |
| 799 | if (m_animateScheduled) { |
| 800 | m_animateScheduled = false; |
| 801 | webWidget()->animate(0.0); |
| 802 | } |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 803 | } |
| 804 | |
| 805 | void WebTestProxyBase::show(WebNavigationPolicy) |
| 806 | { |
Torne (Richard Coles) | 521d96e | 2013-06-19 11:58:24 +0100 | [diff] [blame] | 807 | invalidateAll(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 808 | } |
| 809 | |
| 810 | void WebTestProxyBase::setWindowRect(const WebRect& rect) |
| 811 | { |
Torne (Richard Coles) | 521d96e | 2013-06-19 11:58:24 +0100 | [diff] [blame] | 812 | invalidateAll(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 813 | discardBackingStore(); |
| 814 | } |
| 815 | |
| 816 | void WebTestProxyBase::didAutoResize(const WebSize&) |
| 817 | { |
Torne (Richard Coles) | 521d96e | 2013-06-19 11:58:24 +0100 | [diff] [blame] | 818 | invalidateAll(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 819 | } |
| 820 | |
| 821 | void WebTestProxyBase::postAccessibilityNotification(const WebKit::WebAccessibilityObject& obj, WebKit::WebAccessibilityNotification notification) |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 822 | { |
| 823 | if (notification == WebKit::WebAccessibilityNotificationFocusedUIElementChanged) |
| 824 | m_testInterfaces->accessibilityController()->setFocusedElement(obj); |
| 825 | |
| 826 | const char* notificationName; |
| 827 | switch (notification) { |
| 828 | case WebKit::WebAccessibilityNotificationActiveDescendantChanged: |
| 829 | notificationName = "ActiveDescendantChanged"; |
| 830 | break; |
| 831 | case WebKit::WebAccessibilityNotificationAutocorrectionOccured: |
| 832 | notificationName = "AutocorrectionOccured"; |
| 833 | break; |
| 834 | case WebKit::WebAccessibilityNotificationCheckedStateChanged: |
| 835 | notificationName = "CheckedStateChanged"; |
| 836 | break; |
| 837 | case WebKit::WebAccessibilityNotificationChildrenChanged: |
| 838 | notificationName = "ChildrenChanged"; |
| 839 | break; |
| 840 | case WebKit::WebAccessibilityNotificationFocusedUIElementChanged: |
| 841 | notificationName = "FocusedUIElementChanged"; |
| 842 | break; |
| 843 | case WebKit::WebAccessibilityNotificationLayoutComplete: |
| 844 | notificationName = "LayoutComplete"; |
| 845 | break; |
| 846 | case WebKit::WebAccessibilityNotificationLoadComplete: |
| 847 | notificationName = "LoadComplete"; |
| 848 | break; |
| 849 | case WebKit::WebAccessibilityNotificationSelectedChildrenChanged: |
| 850 | notificationName = "SelectedChildrenChanged"; |
| 851 | break; |
| 852 | case WebKit::WebAccessibilityNotificationSelectedTextChanged: |
| 853 | notificationName = "SelectedTextChanged"; |
| 854 | break; |
| 855 | case WebKit::WebAccessibilityNotificationValueChanged: |
| 856 | notificationName = "ValueChanged"; |
| 857 | break; |
| 858 | case WebKit::WebAccessibilityNotificationScrolledToAnchor: |
| 859 | notificationName = "ScrolledToAnchor"; |
| 860 | break; |
| 861 | case WebKit::WebAccessibilityNotificationLiveRegionChanged: |
| 862 | notificationName = "LiveRegionChanged"; |
| 863 | break; |
| 864 | case WebKit::WebAccessibilityNotificationMenuListItemSelected: |
| 865 | notificationName = "MenuListItemSelected"; |
| 866 | break; |
| 867 | case WebKit::WebAccessibilityNotificationMenuListValueChanged: |
| 868 | notificationName = "MenuListValueChanged"; |
| 869 | break; |
| 870 | case WebKit::WebAccessibilityNotificationRowCountChanged: |
| 871 | notificationName = "RowCountChanged"; |
| 872 | break; |
| 873 | case WebKit::WebAccessibilityNotificationRowCollapsed: |
| 874 | notificationName = "RowCollapsed"; |
| 875 | break; |
| 876 | case WebKit::WebAccessibilityNotificationRowExpanded: |
| 877 | notificationName = "RowExpanded"; |
| 878 | break; |
| 879 | case WebKit::WebAccessibilityNotificationInvalidStatusChanged: |
| 880 | notificationName = "InvalidStatusChanged"; |
| 881 | break; |
| 882 | case WebKit::WebAccessibilityNotificationTextChanged: |
| 883 | notificationName = "TextChanged"; |
| 884 | break; |
| 885 | case WebKit::WebAccessibilityNotificationAriaAttributeChanged: |
| 886 | notificationName = "AriaAttributeChanged"; |
| 887 | break; |
| 888 | default: |
| 889 | notificationName = "UnknownNotification"; |
| 890 | break; |
| 891 | } |
| 892 | |
| 893 | m_testInterfaces->accessibilityController()->notificationReceived(obj, notificationName); |
| 894 | |
| 895 | if (m_testInterfaces->accessibilityController()->shouldLogAccessibilityEvents()) { |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 896 | string message("AccessibilityNotification - "); |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 897 | message += notificationName; |
| 898 | |
| 899 | WebKit::WebNode node = obj.node(); |
| 900 | if (!node.isNull() && node.isElementNode()) { |
| 901 | WebKit::WebElement element = node.to<WebKit::WebElement>(); |
| 902 | if (element.hasAttribute("id")) { |
| 903 | message += " - id:"; |
| 904 | message += element.getAttribute("id").utf8().data(); |
| 905 | } |
| 906 | } |
| 907 | |
| 908 | m_delegate->printMessage(message + "\n"); |
| 909 | } |
| 910 | } |
| 911 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 912 | void WebTestProxyBase::startDragging(WebFrame*, const WebDragData& data, WebDragOperationsMask mask, const WebImage&, const WebPoint&) |
| 913 | { |
| 914 | // When running a test, we need to fake a drag drop operation otherwise |
| 915 | // Windows waits for real mouse events to know when the drag is over. |
| 916 | m_testInterfaces->eventSender()->doDragDrop(data, mask); |
| 917 | } |
| 918 | |
| 919 | // The output from these methods in layout test mode should match that |
| 920 | // expected by the layout tests. See EditingDelegate.m in DumpRenderTree. |
| 921 | |
| 922 | bool WebTestProxyBase::shouldBeginEditing(const WebRange& range) |
| 923 | { |
| 924 | if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) { |
| 925 | m_delegate->printMessage("EDITING DELEGATE: shouldBeginEditingInDOMRange:"); |
| 926 | printRangeDescription(m_delegate, range); |
| 927 | m_delegate->printMessage("\n"); |
| 928 | } |
| 929 | return true; |
| 930 | } |
| 931 | |
| 932 | bool WebTestProxyBase::shouldEndEditing(const WebRange& range) |
| 933 | { |
| 934 | if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) { |
| 935 | m_delegate->printMessage("EDITING DELEGATE: shouldEndEditingInDOMRange:"); |
| 936 | printRangeDescription(m_delegate, range); |
| 937 | m_delegate->printMessage("\n"); |
| 938 | } |
| 939 | return true; |
| 940 | } |
| 941 | |
| 942 | bool WebTestProxyBase::shouldInsertNode(const WebNode& node, const WebRange& range, WebEditingAction action) |
| 943 | { |
| 944 | if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) { |
| 945 | m_delegate->printMessage("EDITING DELEGATE: shouldInsertNode:"); |
| 946 | printNodeDescription(m_delegate, node, 0); |
| 947 | m_delegate->printMessage(" replacingDOMRange:"); |
| 948 | printRangeDescription(m_delegate, range); |
| 949 | m_delegate->printMessage(string(" givenAction:") + editingActionDescription(action) + "\n"); |
| 950 | } |
| 951 | return true; |
| 952 | } |
| 953 | |
| 954 | bool WebTestProxyBase::shouldInsertText(const WebString& text, const WebRange& range, WebEditingAction action) |
| 955 | { |
| 956 | if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) { |
| 957 | m_delegate->printMessage(string("EDITING DELEGATE: shouldInsertText:") + text.utf8().data() + " replacingDOMRange:"); |
| 958 | printRangeDescription(m_delegate, range); |
| 959 | m_delegate->printMessage(string(" givenAction:") + editingActionDescription(action) + "\n"); |
| 960 | } |
| 961 | return true; |
| 962 | } |
| 963 | |
| 964 | bool WebTestProxyBase::shouldChangeSelectedRange( |
| 965 | const WebRange& fromRange, const WebRange& toRange, WebTextAffinity affinity, bool stillSelecting) |
| 966 | { |
| 967 | if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) { |
| 968 | m_delegate->printMessage("EDITING DELEGATE: shouldChangeSelectedDOMRange:"); |
| 969 | printRangeDescription(m_delegate, fromRange); |
| 970 | m_delegate->printMessage(" toDOMRange:"); |
| 971 | printRangeDescription(m_delegate, toRange); |
| 972 | m_delegate->printMessage(string(" affinity:") + textAffinityDescription(affinity) + " stillSelecting:" + (stillSelecting ? "TRUE" : "FALSE") + "\n"); |
| 973 | } |
| 974 | return true; |
| 975 | } |
| 976 | |
| 977 | bool WebTestProxyBase::shouldDeleteRange(const WebRange& range) |
| 978 | { |
| 979 | if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) { |
| 980 | m_delegate->printMessage("EDITING DELEGATE: shouldDeleteDOMRange:"); |
| 981 | printRangeDescription(m_delegate, range); |
| 982 | m_delegate->printMessage("\n"); |
| 983 | } |
| 984 | return true; |
| 985 | } |
| 986 | |
| 987 | bool WebTestProxyBase::shouldApplyStyle(const WebString& style, const WebRange& range) |
| 988 | { |
| 989 | if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) { |
| 990 | m_delegate->printMessage(string("EDITING DELEGATE: shouldApplyStyle:") + style.utf8().data() + " toElementsInDOMRange:"); |
| 991 | printRangeDescription(m_delegate, range); |
| 992 | m_delegate->printMessage("\n"); |
| 993 | } |
| 994 | return true; |
| 995 | } |
| 996 | |
| 997 | void WebTestProxyBase::didBeginEditing() |
| 998 | { |
| 999 | if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) |
| 1000 | m_delegate->printMessage("EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification\n"); |
| 1001 | } |
| 1002 | |
| 1003 | void WebTestProxyBase::didChangeSelection(bool isEmptySelection) |
| 1004 | { |
| 1005 | if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) |
| 1006 | m_delegate->printMessage("EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification\n"); |
| 1007 | } |
| 1008 | |
| 1009 | void WebTestProxyBase::didChangeContents() |
| 1010 | { |
| 1011 | if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) |
| 1012 | m_delegate->printMessage("EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification\n"); |
| 1013 | } |
| 1014 | |
| 1015 | void WebTestProxyBase::didEndEditing() |
| 1016 | { |
| 1017 | if (m_testInterfaces->testRunner()->shouldDumpEditingCallbacks()) |
| 1018 | m_delegate->printMessage("EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification\n"); |
| 1019 | } |
| 1020 | |
| 1021 | bool WebTestProxyBase::createView(WebFrame*, const WebURLRequest& request, const WebWindowFeatures&, const WebString&, WebNavigationPolicy) |
| 1022 | { |
| 1023 | if (!m_testInterfaces->testRunner()->canOpenWindows()) |
| 1024 | return false; |
| 1025 | if (m_testInterfaces->testRunner()->shouldDumpCreateView()) |
| 1026 | m_delegate->printMessage(string("createView(") + URLDescription(request.url()) + ")\n"); |
| 1027 | return true; |
| 1028 | } |
| 1029 | |
| 1030 | WebPlugin* WebTestProxyBase::createPlugin(WebFrame* frame, const WebPluginParams& params) |
| 1031 | { |
| 1032 | if (params.mimeType == TestPlugin::mimeType()) |
| 1033 | return TestPlugin::create(frame, params, m_delegate); |
| 1034 | return 0; |
| 1035 | } |
| 1036 | |
| 1037 | void WebTestProxyBase::setStatusText(const WebString& text) |
| 1038 | { |
| 1039 | if (!m_testInterfaces->testRunner()->shouldDumpStatusCallbacks()) |
| 1040 | return; |
| 1041 | m_delegate->printMessage(string("UI DELEGATE STATUS CALLBACK: setStatusText:") + text.utf8().data() + "\n"); |
| 1042 | } |
| 1043 | |
| 1044 | void WebTestProxyBase::didStopLoading() |
| 1045 | { |
| 1046 | if (m_testInterfaces->testRunner()->shouldDumpProgressFinishedCallback()) |
| 1047 | m_delegate->printMessage("postProgressFinishedNotification\n"); |
| 1048 | } |
| 1049 | |
| 1050 | void WebTestProxyBase::showContextMenu(WebFrame*, const WebContextMenuData& contextMenuData) |
| 1051 | { |
| 1052 | m_testInterfaces->eventSender()->setContextMenuData(contextMenuData); |
| 1053 | } |
| 1054 | |
| 1055 | WebUserMediaClient* WebTestProxyBase::userMediaClient() |
| 1056 | { |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1057 | if (!m_userMediaClient.get()) |
| 1058 | m_userMediaClient.reset(new WebUserMediaClientMock(m_delegate)); |
| 1059 | return m_userMediaClient.get(); |
Torne (Richard Coles) | 53e740f | 2013-05-09 18:38:43 +0100 | [diff] [blame] | 1060 | } |
| 1061 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1062 | // Simulate a print by going into print mode and then exit straight away. |
| 1063 | void WebTestProxyBase::printPage(WebFrame* frame) |
| 1064 | { |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 1065 | WebSize pageSizeInPixels = webWidget()->size(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1066 | WebPrintParams printParams(pageSizeInPixels); |
| 1067 | frame->printBegin(printParams); |
| 1068 | frame->printEnd(); |
| 1069 | } |
| 1070 | |
| 1071 | WebNotificationPresenter* WebTestProxyBase::notificationPresenter() |
| 1072 | { |
| 1073 | #if ENABLE_NOTIFICATIONS |
| 1074 | return m_testInterfaces->testRunner()->notificationPresenter(); |
| 1075 | #else |
| 1076 | return 0; |
| 1077 | #endif |
| 1078 | } |
| 1079 | |
| 1080 | WebGeolocationClient* WebTestProxyBase::geolocationClient() |
| 1081 | { |
| 1082 | return geolocationClientMock(); |
| 1083 | } |
| 1084 | |
| 1085 | WebSpeechInputController* WebTestProxyBase::speechInputController(WebSpeechInputListener* listener) |
| 1086 | { |
| 1087 | #if ENABLE_INPUT_SPEECH |
| 1088 | if (!m_speechInputController.get()) { |
| 1089 | m_speechInputController.reset(new MockWebSpeechInputController(listener)); |
| 1090 | m_speechInputController->setDelegate(m_delegate); |
| 1091 | } |
| 1092 | return m_speechInputController.get(); |
| 1093 | #else |
| 1094 | WEBKIT_ASSERT(listener); |
| 1095 | return 0; |
| 1096 | #endif |
| 1097 | } |
| 1098 | |
| 1099 | WebSpeechRecognizer* WebTestProxyBase::speechRecognizer() |
| 1100 | { |
| 1101 | return speechRecognizerMock(); |
| 1102 | } |
| 1103 | |
| 1104 | WebDeviceOrientationClient* WebTestProxyBase::deviceOrientationClient() |
| 1105 | { |
| 1106 | return deviceOrientationClientMock(); |
| 1107 | } |
| 1108 | |
| 1109 | bool WebTestProxyBase::requestPointerLock() |
| 1110 | { |
| 1111 | return m_testInterfaces->testRunner()->requestPointerLock(); |
| 1112 | } |
| 1113 | |
| 1114 | void WebTestProxyBase::requestPointerUnlock() |
| 1115 | { |
| 1116 | m_testInterfaces->testRunner()->requestPointerUnlock(); |
| 1117 | } |
| 1118 | |
| 1119 | bool WebTestProxyBase::isPointerLocked() |
| 1120 | { |
| 1121 | return m_testInterfaces->testRunner()->isPointerLocked(); |
| 1122 | } |
| 1123 | |
| 1124 | void WebTestProxyBase::didFocus() |
| 1125 | { |
| 1126 | m_delegate->setFocus(this, true); |
| 1127 | } |
| 1128 | |
| 1129 | void WebTestProxyBase::didBlur() |
| 1130 | { |
| 1131 | m_delegate->setFocus(this, false); |
| 1132 | } |
| 1133 | |
Torne (Richard Coles) | e524955 | 2013-05-15 11:35:13 +0100 | [diff] [blame] | 1134 | void WebTestProxyBase::setToolTipText(const WebString& text, WebTextDirection) |
| 1135 | { |
| 1136 | m_testInterfaces->testRunner()->setToolTipText(text); |
| 1137 | } |
| 1138 | |
Torne (Richard Coles) | 93ac45c | 2013-05-29 14:40:20 +0100 | [diff] [blame] | 1139 | void WebTestProxyBase::didOpenChooser() |
| 1140 | { |
| 1141 | m_chooserCount++; |
| 1142 | } |
| 1143 | |
| 1144 | void WebTestProxyBase::didCloseChooser() |
| 1145 | { |
| 1146 | m_chooserCount--; |
| 1147 | } |
| 1148 | |
| 1149 | bool WebTestProxyBase::isChooserShown() |
| 1150 | { |
| 1151 | return 0 < m_chooserCount; |
| 1152 | } |
| 1153 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1154 | void WebTestProxyBase::didStartProvisionalLoad(WebFrame* frame) |
| 1155 | { |
| 1156 | if (!m_testInterfaces->testRunner()->topLoadingFrame()) |
| 1157 | m_testInterfaces->testRunner()->setTopLoadingFrame(frame, false); |
| 1158 | |
| 1159 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) { |
| 1160 | printFrameDescription(m_delegate, frame); |
| 1161 | m_delegate->printMessage(" - didStartProvisionalLoadForFrame\n"); |
| 1162 | } |
| 1163 | |
| 1164 | if (m_testInterfaces->testRunner()->shouldDumpUserGestureInFrameLoadCallbacks()) |
| 1165 | printFrameUserGestureStatus(m_delegate, frame, " - in didStartProvisionalLoadForFrame\n"); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1166 | } |
| 1167 | |
| 1168 | void WebTestProxyBase::didReceiveServerRedirectForProvisionalLoad(WebFrame* frame) |
| 1169 | { |
| 1170 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) { |
| 1171 | printFrameDescription(m_delegate, frame); |
| 1172 | m_delegate->printMessage(" - didReceiveServerRedirectForProvisionalLoadForFrame\n"); |
| 1173 | } |
| 1174 | } |
| 1175 | |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 1176 | bool WebTestProxyBase::didFailProvisionalLoad(WebFrame* frame, const WebURLError&) |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1177 | { |
| 1178 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) { |
| 1179 | printFrameDescription(m_delegate, frame); |
| 1180 | m_delegate->printMessage(" - didFailProvisionalLoadWithError\n"); |
| 1181 | } |
| 1182 | locationChangeDone(frame); |
Torne (Richard Coles) | 5267f70 | 2013-06-11 10:57:24 +0100 | [diff] [blame] | 1183 | return !frame->provisionalDataSource(); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1184 | } |
| 1185 | |
| 1186 | void WebTestProxyBase::didCommitProvisionalLoad(WebFrame* frame, bool) |
| 1187 | { |
| 1188 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) { |
| 1189 | printFrameDescription(m_delegate, frame); |
| 1190 | m_delegate->printMessage(" - didCommitLoadForFrame\n"); |
| 1191 | } |
| 1192 | } |
| 1193 | |
| 1194 | void WebTestProxyBase::didReceiveTitle(WebFrame* frame, const WebString& title, WebTextDirection direction) |
| 1195 | { |
| 1196 | WebCString title8 = title.utf8(); |
| 1197 | |
| 1198 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) { |
| 1199 | printFrameDescription(m_delegate, frame); |
| 1200 | m_delegate->printMessage(string(" - didReceiveTitle: ") + title8.data() + "\n"); |
| 1201 | } |
| 1202 | |
| 1203 | if (m_testInterfaces->testRunner()->shouldDumpTitleChanges()) |
| 1204 | m_delegate->printMessage(string("TITLE CHANGED: '") + title8.data() + "'\n"); |
| 1205 | |
| 1206 | m_testInterfaces->testRunner()->setTitleTextDirection(direction); |
| 1207 | } |
| 1208 | |
| 1209 | void WebTestProxyBase::didChangeIcon(WebFrame* frame, WebIconURL::Type) |
| 1210 | { |
| 1211 | if (m_testInterfaces->testRunner()->shouldDumpIconChanges()) { |
| 1212 | printFrameDescription(m_delegate, frame); |
| 1213 | m_delegate->printMessage(string(" - didChangeIcons\n")); |
| 1214 | } |
| 1215 | } |
| 1216 | |
| 1217 | void WebTestProxyBase::didFinishDocumentLoad(WebFrame* frame) |
| 1218 | { |
| 1219 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) { |
| 1220 | printFrameDescription(m_delegate, frame); |
| 1221 | m_delegate->printMessage(" - didFinishDocumentLoadForFrame\n"); |
| 1222 | } else { |
| 1223 | unsigned pendingUnloadEvents = frame->unloadListenerCount(); |
| 1224 | if (pendingUnloadEvents) { |
| 1225 | printFrameDescription(m_delegate, frame); |
| 1226 | char buffer[100]; |
| 1227 | snprintf(buffer, sizeof(buffer), " - has %u onunload handler(s)\n", pendingUnloadEvents); |
| 1228 | m_delegate->printMessage(buffer); |
| 1229 | } |
| 1230 | } |
| 1231 | } |
| 1232 | |
| 1233 | void WebTestProxyBase::didHandleOnloadEvents(WebFrame* frame) |
| 1234 | { |
| 1235 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) { |
| 1236 | printFrameDescription(m_delegate, frame); |
| 1237 | m_delegate->printMessage(" - didHandleOnloadEventsForFrame\n"); |
| 1238 | } |
| 1239 | } |
| 1240 | |
| 1241 | void WebTestProxyBase::didFailLoad(WebFrame* frame, const WebURLError&) |
| 1242 | { |
| 1243 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) { |
| 1244 | printFrameDescription(m_delegate, frame); |
| 1245 | m_delegate->printMessage(" - didFailLoadWithError\n"); |
| 1246 | } |
| 1247 | locationChangeDone(frame); |
| 1248 | } |
| 1249 | |
| 1250 | void WebTestProxyBase::didFinishLoad(WebFrame* frame) |
| 1251 | { |
| 1252 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) { |
| 1253 | printFrameDescription(m_delegate, frame); |
| 1254 | m_delegate->printMessage(" - didFinishLoadForFrame\n"); |
| 1255 | } |
| 1256 | locationChangeDone(frame); |
| 1257 | } |
| 1258 | |
| 1259 | void WebTestProxyBase::didChangeLocationWithinPage(WebFrame* frame) |
| 1260 | { |
| 1261 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) { |
| 1262 | printFrameDescription(m_delegate, frame); |
| 1263 | m_delegate->printMessage(" - didChangeLocationWithinPageForFrame\n"); |
| 1264 | } |
| 1265 | } |
| 1266 | |
| 1267 | void WebTestProxyBase::didDisplayInsecureContent(WebFrame*) |
| 1268 | { |
| 1269 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) |
| 1270 | m_delegate->printMessage("didDisplayInsecureContent\n"); |
| 1271 | } |
| 1272 | |
| 1273 | void WebTestProxyBase::didRunInsecureContent(WebFrame*, const WebSecurityOrigin&, const WebURL&) |
| 1274 | { |
| 1275 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) |
| 1276 | m_delegate->printMessage("didRunInsecureContent\n"); |
| 1277 | } |
| 1278 | |
| 1279 | void WebTestProxyBase::didDetectXSS(WebFrame*, const WebURL&, bool) |
| 1280 | { |
| 1281 | if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) |
| 1282 | m_delegate->printMessage("didDetectXSS\n"); |
| 1283 | } |
| 1284 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1285 | void WebTestProxyBase::willRequestResource(WebFrame* frame, const WebKit::WebCachedURLRequest& request) |
| 1286 | { |
| 1287 | if (m_testInterfaces->testRunner()->shouldDumpResourceRequestCallbacks()) { |
| 1288 | printFrameDescription(m_delegate, frame); |
Torne (Richard Coles) | 93ac45c | 2013-05-29 14:40:20 +0100 | [diff] [blame] | 1289 | m_delegate->printMessage(string(" - ") + request.initiatorName().utf8().data()); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1290 | m_delegate->printMessage(string(" requested '") + URLDescription(request.urlRequest().url()).c_str() + "'\n"); |
| 1291 | } |
| 1292 | } |
| 1293 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1294 | WebURLError WebTestProxyBase::cannotHandleRequestError(WebFrame*, const WebURLRequest& request) |
| 1295 | { |
| 1296 | WebURLError error; |
| 1297 | // A WebKit layout test expects the following values. |
| 1298 | // unableToImplementPolicyWithError() below prints them. |
| 1299 | error.domain = WebString::fromUTF8("WebKitErrorDomain"); |
| 1300 | error.reason = 101; |
| 1301 | error.unreachableURL = request.url(); |
| 1302 | return error; |
| 1303 | } |
| 1304 | |
| 1305 | void WebTestProxyBase::didCreateDataSource(WebFrame*, WebDataSource* ds) |
| 1306 | { |
| 1307 | if (!m_testInterfaces->testRunner()->deferMainResourceDataLoad()) |
| 1308 | ds->setDeferMainResourceDataLoad(false); |
| 1309 | } |
| 1310 | |
| 1311 | void WebTestProxyBase::willSendRequest(WebFrame*, unsigned identifier, WebKit::WebURLRequest& request, const WebKit::WebURLResponse& redirectResponse) |
| 1312 | { |
| 1313 | // Need to use GURL for host() and SchemeIs() |
| 1314 | GURL url = request.url(); |
| 1315 | string requestURL = url.possibly_invalid_spec(); |
| 1316 | |
| 1317 | GURL mainDocumentURL = request.firstPartyForCookies(); |
| 1318 | |
Torne (Richard Coles) | 53e740f | 2013-05-09 18:38:43 +0100 | [diff] [blame] | 1319 | if (redirectResponse.isNull() && (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks() || m_testInterfaces->testRunner()->shouldDumpResourcePriorities())) { |
| 1320 | WEBKIT_ASSERT(m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end()); |
| 1321 | m_resourceIdentifierMap[identifier] = descriptionSuitableForTestResult(requestURL); |
| 1322 | } |
| 1323 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1324 | if (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks()) { |
| 1325 | if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end()) |
| 1326 | m_delegate->printMessage("<unknown>"); |
| 1327 | else |
| 1328 | m_delegate->printMessage(m_resourceIdentifierMap[identifier]); |
| 1329 | m_delegate->printMessage(" - willSendRequest <NSURLRequest URL "); |
| 1330 | m_delegate->printMessage(descriptionSuitableForTestResult(requestURL).c_str()); |
| 1331 | m_delegate->printMessage(", main document URL "); |
| 1332 | m_delegate->printMessage(URLDescription(mainDocumentURL).c_str()); |
| 1333 | m_delegate->printMessage(", http method "); |
| 1334 | m_delegate->printMessage(request.httpMethod().utf8().data()); |
| 1335 | m_delegate->printMessage("> redirectResponse "); |
| 1336 | printResponseDescription(m_delegate, redirectResponse); |
| 1337 | m_delegate->printMessage("\n"); |
| 1338 | } |
| 1339 | |
| 1340 | if (m_testInterfaces->testRunner()->shouldDumpResourcePriorities()) { |
| 1341 | m_delegate->printMessage(descriptionSuitableForTestResult(requestURL).c_str()); |
| 1342 | m_delegate->printMessage(" has priority "); |
| 1343 | m_delegate->printMessage(PriorityDescription(request.priority())); |
| 1344 | m_delegate->printMessage("\n"); |
| 1345 | } |
| 1346 | |
| 1347 | if (!redirectResponse.isNull() && m_testInterfaces->testRunner()->shouldBlockRedirects()) { |
| 1348 | m_delegate->printMessage("Returning null for this redirect\n"); |
| 1349 | blockRequest(request); |
| 1350 | return; |
| 1351 | } |
| 1352 | |
| 1353 | if (m_testInterfaces->testRunner()->willSendRequestShouldReturnNull()) { |
| 1354 | blockRequest(request); |
| 1355 | return; |
| 1356 | } |
| 1357 | |
| 1358 | if (m_testInterfaces->testRunner()->httpHeadersToClear()) { |
| 1359 | const set<string> *clearHeaders = m_testInterfaces->testRunner()->httpHeadersToClear(); |
| 1360 | for (set<string>::const_iterator header = clearHeaders->begin(); header != clearHeaders->end(); ++header) |
| 1361 | request.clearHTTPHeaderField(WebString::fromUTF8(*header)); |
| 1362 | } |
| 1363 | |
| 1364 | string host = url.host(); |
| 1365 | if (!host.empty() && (url.SchemeIs("http") || url.SchemeIs("https"))) { |
| 1366 | if (!isLocalhost(host) && !hostIsUsedBySomeTestsToGenerateError(host) |
| 1367 | && ((!mainDocumentURL.SchemeIs("http") && !mainDocumentURL.SchemeIs("https")) || isLocalhost(mainDocumentURL.host())) |
| 1368 | && !m_delegate->allowExternalPages()) { |
| 1369 | m_delegate->printMessage(string("Blocked access to external URL ") + requestURL + "\n"); |
| 1370 | blockRequest(request); |
| 1371 | return; |
| 1372 | } |
| 1373 | } |
| 1374 | |
| 1375 | // Set the new substituted URL. |
| 1376 | request.setURL(m_delegate->rewriteLayoutTestsURL(request.url().spec())); |
| 1377 | } |
| 1378 | |
| 1379 | void WebTestProxyBase::didReceiveResponse(WebFrame*, unsigned identifier, const WebKit::WebURLResponse& response) |
| 1380 | { |
| 1381 | if (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks()) { |
| 1382 | if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end()) |
| 1383 | m_delegate->printMessage("<unknown>"); |
| 1384 | else |
| 1385 | m_delegate->printMessage(m_resourceIdentifierMap[identifier]); |
| 1386 | m_delegate->printMessage(" - didReceiveResponse "); |
| 1387 | printResponseDescription(m_delegate, response); |
| 1388 | m_delegate->printMessage("\n"); |
| 1389 | } |
| 1390 | if (m_testInterfaces->testRunner()->shouldDumpResourceResponseMIMETypes()) { |
| 1391 | GURL url = response.url(); |
| 1392 | WebString mimeType = response.mimeType(); |
| 1393 | m_delegate->printMessage(url.ExtractFileName()); |
| 1394 | m_delegate->printMessage(" has MIME type "); |
| 1395 | // Simulate NSURLResponse's mapping of empty/unknown MIME types to application/octet-stream |
| 1396 | m_delegate->printMessage(mimeType.isEmpty() ? "application/octet-stream" : mimeType.utf8().data()); |
| 1397 | m_delegate->printMessage("\n"); |
| 1398 | } |
| 1399 | } |
| 1400 | |
| 1401 | void WebTestProxyBase::didChangeResourcePriority(WebFrame*, unsigned identifier, const WebKit::WebURLRequest::Priority& priority) |
| 1402 | { |
| 1403 | if (m_testInterfaces->testRunner()->shouldDumpResourcePriorities()) { |
| 1404 | if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end()) |
| 1405 | m_delegate->printMessage("<unknown>"); |
| 1406 | else |
| 1407 | m_delegate->printMessage(m_resourceIdentifierMap[identifier]); |
| 1408 | m_delegate->printMessage(" changed priority to "); |
| 1409 | m_delegate->printMessage(PriorityDescription(priority)); |
| 1410 | m_delegate->printMessage("\n"); |
| 1411 | } |
| 1412 | } |
| 1413 | |
| 1414 | void WebTestProxyBase::didFinishResourceLoad(WebFrame*, unsigned identifier) |
| 1415 | { |
| 1416 | if (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks()) { |
| 1417 | if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end()) |
| 1418 | m_delegate->printMessage("<unknown>"); |
| 1419 | else |
| 1420 | m_delegate->printMessage(m_resourceIdentifierMap[identifier]); |
| 1421 | m_delegate->printMessage(" - didFinishLoading\n"); |
| 1422 | } |
| 1423 | m_resourceIdentifierMap.erase(identifier); |
| 1424 | } |
| 1425 | |
| 1426 | void WebTestProxyBase::didFailResourceLoad(WebFrame*, unsigned identifier, const WebKit::WebURLError& error) |
| 1427 | { |
| 1428 | if (m_testInterfaces->testRunner()->shouldDumpResourceLoadCallbacks()) { |
| 1429 | if (m_resourceIdentifierMap.find(identifier) == m_resourceIdentifierMap.end()) |
| 1430 | m_delegate->printMessage("<unknown>"); |
| 1431 | else |
| 1432 | m_delegate->printMessage(m_resourceIdentifierMap[identifier]); |
| 1433 | m_delegate->printMessage(" - didFailLoadingWithError: "); |
| 1434 | m_delegate->printMessage(m_delegate->makeURLErrorDescription(error)); |
| 1435 | m_delegate->printMessage("\n"); |
| 1436 | } |
| 1437 | m_resourceIdentifierMap.erase(identifier); |
| 1438 | } |
| 1439 | |
| 1440 | void WebTestProxyBase::unableToImplementPolicyWithError(WebKit::WebFrame* frame, const WebKit::WebURLError& error) |
| 1441 | { |
| 1442 | char errorBuffer[40]; |
| 1443 | snprintf(errorBuffer, sizeof(errorBuffer), "%d", error.reason); |
| 1444 | m_delegate->printMessage(string("Policy delegate: unable to implement policy with error domain '") + error.domain.utf8().data() + |
| 1445 | "', error code " + errorBuffer + |
| 1446 | ", in frame '" + frame->uniqueName().utf8().data() + "'\n"); |
| 1447 | } |
| 1448 | |
| 1449 | void WebTestProxyBase::didAddMessageToConsole(const WebConsoleMessage& message, const WebString& sourceName, unsigned sourceLine) |
| 1450 | { |
| 1451 | // This matches win DumpRenderTree's UIDelegate.cpp. |
| 1452 | if (!m_logConsoleOutput) |
| 1453 | return; |
| 1454 | m_delegate->printMessage(string("CONSOLE MESSAGE: ")); |
| 1455 | if (sourceLine) { |
| 1456 | char buffer[40]; |
| 1457 | snprintf(buffer, sizeof(buffer), "line %d: ", sourceLine); |
| 1458 | m_delegate->printMessage(buffer); |
| 1459 | } |
| 1460 | if (!message.text.isEmpty()) { |
| 1461 | string newMessage; |
| 1462 | newMessage = message.text.utf8(); |
| 1463 | size_t fileProtocol = newMessage.find("file://"); |
| 1464 | if (fileProtocol != string::npos) { |
| 1465 | newMessage = newMessage.substr(0, fileProtocol) |
| 1466 | + urlSuitableForTestResult(newMessage.substr(fileProtocol)); |
| 1467 | } |
| 1468 | m_delegate->printMessage(newMessage); |
| 1469 | } |
| 1470 | m_delegate->printMessage(string("\n")); |
| 1471 | } |
| 1472 | |
| 1473 | void WebTestProxyBase::runModalAlertDialog(WebFrame*, const WebString& message) |
| 1474 | { |
| 1475 | m_delegate->printMessage(string("ALERT: ") + message.utf8().data() + "\n"); |
| 1476 | } |
| 1477 | |
| 1478 | bool WebTestProxyBase::runModalConfirmDialog(WebFrame*, const WebString& message) |
| 1479 | { |
| 1480 | m_delegate->printMessage(string("CONFIRM: ") + message.utf8().data() + "\n"); |
| 1481 | return true; |
| 1482 | } |
| 1483 | |
| 1484 | bool WebTestProxyBase::runModalPromptDialog(WebFrame* frame, const WebString& message, const WebString& defaultValue, WebString*) |
| 1485 | { |
| 1486 | m_delegate->printMessage(string("PROMPT: ") + message.utf8().data() + ", default text: " + defaultValue.utf8().data() + "\n"); |
| 1487 | return true; |
| 1488 | } |
| 1489 | |
| 1490 | bool WebTestProxyBase::runModalBeforeUnloadDialog(WebFrame*, const WebString& message) |
| 1491 | { |
| 1492 | m_delegate->printMessage(string("CONFIRM NAVIGATION: ") + message.utf8().data() + "\n"); |
| 1493 | return !m_testInterfaces->testRunner()->shouldStayOnPageAfterHandlingBeforeUnload(); |
| 1494 | } |
| 1495 | |
| 1496 | void WebTestProxyBase::locationChangeDone(WebFrame* frame) |
| 1497 | { |
| 1498 | if (frame != m_testInterfaces->testRunner()->topLoadingFrame()) |
| 1499 | return; |
| 1500 | m_testInterfaces->testRunner()->setTopLoadingFrame(frame, true); |
| 1501 | } |
| 1502 | |
Torne (Richard Coles) | 53e740f | 2013-05-09 18:38:43 +0100 | [diff] [blame] | 1503 | WebNavigationPolicy WebTestProxyBase::decidePolicyForNavigation(WebFrame*, const WebURLRequest& request, WebNavigationType type, WebNavigationPolicy defaultPolicy, bool isRedirect) |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1504 | { |
| 1505 | WebNavigationPolicy result; |
| 1506 | if (!m_testInterfaces->testRunner()->policyDelegateEnabled()) |
| 1507 | return defaultPolicy; |
| 1508 | |
Torne (Richard Coles) | 53e740f | 2013-05-09 18:38:43 +0100 | [diff] [blame] | 1509 | m_delegate->printMessage(string("Policy delegate: attempt to load ") + URLDescription(request.url()) + " with navigation type '" + webNavigationTypeToString(type) + "'\n"); |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 1510 | if (m_testInterfaces->testRunner()->policyDelegateIsPermissive()) |
| 1511 | result = WebKit::WebNavigationPolicyCurrentTab; |
| 1512 | else |
| 1513 | result = WebKit::WebNavigationPolicyIgnore; |
| 1514 | |
| 1515 | if (m_testInterfaces->testRunner()->policyDelegateShouldNotifyDone()) |
| 1516 | m_testInterfaces->testRunner()->policyDelegateDone(); |
| 1517 | return result; |
| 1518 | } |
| 1519 | |
| 1520 | bool WebTestProxyBase::willCheckAndDispatchMessageEvent(WebFrame*, WebFrame*, WebSecurityOrigin, WebDOMMessageEvent) |
| 1521 | { |
| 1522 | if (m_testInterfaces->testRunner()->shouldInterceptPostMessage()) { |
| 1523 | m_delegate->printMessage("intercepted postMessage\n"); |
| 1524 | return true; |
| 1525 | } |
| 1526 | |
| 1527 | return false; |
| 1528 | } |
| 1529 | |
Ben Murdoch | 591b958 | 2013-07-10 11:41:44 +0100 | [diff] [blame] | 1530 | void WebTestProxyBase::resetInputMethod() |
| 1531 | { |
| 1532 | // If a composition text exists, then we need to let the browser process |
| 1533 | // to cancel the input method's ongoing composition session. |
| 1534 | if (m_webWidget) |
| 1535 | m_webWidget->confirmComposition(); |
| 1536 | } |
| 1537 | |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 1538 | } |