1 /* 2 * Copyright (C) 2010 Apple 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 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "InjectedBundlePage.h" 28 29 #include "InjectedBundle.h" 30 #include "StringFunctions.h" 31 #include <cmath> 32 #include <JavaScriptCore/JSRetainPtr.h> 33 #include <WebKit2/WKArray.h> 34 #include <WebKit2/WKBundle.h> 35 #include <WebKit2/WKBundleBackForwardList.h> 36 #include <WebKit2/WKBundleBackForwardListItem.h> 37 #include <WebKit2/WKBundleFrame.h> 38 #include <WebKit2/WKBundleFramePrivate.h> 39 #include <WebKit2/WKBundlePagePrivate.h> 40 #include <WebKit2/WKURLRequest.h> 41 42 using namespace std; 43 44 namespace WTR { 45 46 static bool hasPrefix(const string& searchString, const string& prefix) 47 { 48 return searchString.length() >= prefix.length() && searchString.substr(0, prefix.length()) == prefix; 49 } 50 51 static JSValueRef propertyValue(JSContextRef context, JSObjectRef object, const char* propertyName) 52 { 53 if (!object) 54 return 0; 55 JSRetainPtr<JSStringRef> propertyNameString(Adopt, JSStringCreateWithUTF8CString(propertyName)); 56 return JSObjectGetProperty(context, object, propertyNameString.get(), 0); 57 } 58 59 static double propertyValueDouble(JSContextRef context, JSObjectRef object, const char* propertyName) 60 { 61 JSValueRef value = propertyValue(context, object, propertyName); 62 if (!value) 63 return 0; 64 return JSValueToNumber(context, value, 0); 65 } 66 67 static int propertyValueInt(JSContextRef context, JSObjectRef object, const char* propertyName) 68 { 69 return static_cast<int>(propertyValueDouble(context, object, propertyName)); 70 } 71 72 static double numericWindowPropertyValue(WKBundleFrameRef frame, const char* propertyName) 73 { 74 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame); 75 return propertyValueDouble(context, JSContextGetGlobalObject(context), propertyName); 76 } 77 78 static string dumpPath(JSGlobalContextRef context, JSObjectRef nodeValue) 79 { 80 JSValueRef nodeNameValue = propertyValue(context, nodeValue, "nodeName"); 81 JSRetainPtr<JSStringRef> jsStringNodeName(Adopt, JSValueToStringCopy(context, nodeNameValue, 0)); 82 WKRetainPtr<WKStringRef> nodeName = toWK(jsStringNodeName); 83 84 JSValueRef parentNode = propertyValue(context, nodeValue, "parentNode"); 85 86 ostringstream out; 87 out << nodeName; 88 89 if (parentNode && JSValueIsObject(context, parentNode)) 90 out << " > " << dumpPath(context, (JSObjectRef)parentNode); 91 92 return out.str(); 93 } 94 95 static string dumpPath(WKBundlePageRef page, WKBundleScriptWorldRef world, WKBundleNodeHandleRef node) 96 { 97 if (!node) 98 return "(null)"; 99 100 WKBundleFrameRef frame = WKBundlePageGetMainFrame(page); 101 102 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world); 103 JSValueRef nodeValue = WKBundleFrameGetJavaScriptWrapperForNodeForWorld(frame, node, world); 104 ASSERT(JSValueIsObject(context, nodeValue)); 105 JSObjectRef nodeObject = (JSObjectRef)nodeValue; 106 107 return dumpPath(context, nodeObject); 108 } 109 110 static string toStr(WKBundlePageRef page, WKBundleScriptWorldRef world, WKBundleRangeHandleRef rangeRef) 111 { 112 if (!rangeRef) 113 return "(null)"; 114 115 WKBundleFrameRef frame = WKBundlePageGetMainFrame(page); 116 117 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world); 118 JSValueRef rangeValue = WKBundleFrameGetJavaScriptWrapperForRangeForWorld(frame, rangeRef, world); 119 ASSERT(JSValueIsObject(context, rangeValue)); 120 JSObjectRef rangeObject = (JSObjectRef)rangeValue; 121 122 JSValueRef startNodeValue = propertyValue(context, rangeObject, "startContainer"); 123 ASSERT(JSValueIsObject(context, startNodeValue)); 124 JSObjectRef startNodeObject = (JSObjectRef)startNodeValue; 125 126 JSValueRef endNodeValue = propertyValue(context, rangeObject, "endContainer"); 127 ASSERT(JSValueIsObject(context, endNodeValue)); 128 JSObjectRef endNodeObject = (JSObjectRef)endNodeValue; 129 130 int startOffset = propertyValueInt(context, rangeObject, "startOffset"); 131 int endOffset = propertyValueInt(context, rangeObject, "endOffset"); 132 133 ostringstream out; 134 out << "range from " << startOffset << " of " << dumpPath(context, startNodeObject) << " to " << endOffset << " of " << dumpPath(context, endNodeObject); 135 return out.str(); 136 } 137 138 static ostream& operator<<(ostream& out, WKBundleCSSStyleDeclarationRef style) 139 { 140 // DumpRenderTree calls -[DOMCSSStyleDeclaration description], which just dumps class name and object address. 141 // No existing tests actually hit this code path at the time of this writing, because WebCore doesn't call 142 // the editing client if the styling operation source is CommandFromDOM or CommandFromDOMWithUserInterface. 143 out << "<DOMCSSStyleDeclaration ADDRESS>"; 144 return out; 145 } 146 147 static ostream& operator<<(ostream& out, WKBundleFrameRef frame) 148 { 149 WKRetainPtr<WKStringRef> name(AdoptWK, WKBundleFrameCopyName(frame)); 150 if (WKBundleFrameIsMainFrame(frame)) { 151 if (!WKStringIsEmpty(name.get())) 152 out << "main frame \"" << name << "\""; 153 else 154 out << "main frame"; 155 } else { 156 if (!WKStringIsEmpty(name.get())) 157 out << "frame \"" << name << "\""; 158 else 159 out << "frame (anonymous)"; 160 } 161 162 return out; 163 } 164 165 InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page) 166 : m_page(page) 167 , m_world(AdoptWK, WKBundleScriptWorldCreateWorld()) 168 { 169 WKBundlePageLoaderClient loaderClient = { 170 0, 171 this, 172 didStartProvisionalLoadForFrame, 173 didReceiveServerRedirectForProvisionalLoadForFrame, 174 didFailProvisionalLoadWithErrorForFrame, 175 didCommitLoadForFrame, 176 didFinishDocumentLoadForFrame, 177 didFinishLoadForFrame, 178 didFailLoadWithErrorForFrame, 179 didSameDocumentNavigationForFrame, 180 didReceiveTitleForFrame, 181 0, 182 0, 183 0, 184 didDisplayInsecureContentForFrame, 185 didRunInsecureContentForFrame, 186 didClearWindowForFrame, 187 didCancelClientRedirectForFrame, 188 willPerformClientRedirectForFrame, 189 didHandleOnloadEventsForFrame, 190 }; 191 WKBundlePageSetPageLoaderClient(m_page, &loaderClient); 192 193 WKBundlePageResourceLoadClient resourceLoadClient = { 194 0, 195 this, 196 didInitiateLoadForResource, 197 willSendRequestForFrame, 198 didReceiveResponseForResource, 199 didReceiveContentLengthForResource, 200 didFinishLoadForResource, 201 didFailLoadForResource 202 }; 203 WKBundlePageSetResourceLoadClient(m_page, &resourceLoadClient); 204 205 WKBundlePagePolicyClient policyClient = { 206 0, 207 this, 208 decidePolicyForNavigationAction, 209 decidePolicyForNewWindowAction, 210 decidePolicyForResponse, 211 unableToImplementPolicy 212 }; 213 WKBundlePageSetPolicyClient(m_page, &policyClient); 214 215 WKBundlePageUIClient uiClient = { 216 0, 217 this, 218 willAddMessageToConsole, 219 willSetStatusbarText, 220 willRunJavaScriptAlert, 221 willRunJavaScriptConfirm, 222 willRunJavaScriptPrompt, 223 0, /*mouseDidMoveOverElement*/ 224 0, /*pageDidScroll*/ 225 0, /*paintCustomOverhangArea*/ 226 0, /*shouldGenerateFileForUpload*/ 227 0, /*generateFileForUpload*/ 228 }; 229 WKBundlePageSetUIClient(m_page, &uiClient); 230 231 WKBundlePageEditorClient editorClient = { 232 0, 233 this, 234 shouldBeginEditing, 235 shouldEndEditing, 236 shouldInsertNode, 237 shouldInsertText, 238 shouldDeleteRange, 239 shouldChangeSelectedRange, 240 shouldApplyStyle, 241 didBeginEditing, 242 didEndEditing, 243 didChange, 244 didChangeSelection 245 }; 246 WKBundlePageSetEditorClient(m_page, &editorClient); 247 248 #if ENABLE(FULLSCREEN_API) 249 WKBundlePageFullScreenClient fullScreenClient = { 250 0, 251 this, 252 supportsFullScreen, 253 enterFullScreenForElement, 254 exitFullScreenForElement, 255 }; 256 WKBundlePageSetFullScreenClient(m_page, &fullScreenClient); 257 #endif 258 } 259 260 InjectedBundlePage::~InjectedBundlePage() 261 { 262 } 263 264 void InjectedBundlePage::stopLoading() 265 { 266 WKBundlePageStopLoading(m_page); 267 } 268 269 void InjectedBundlePage::reset() 270 { 271 WKBundlePageClearMainFrameName(m_page); 272 273 WKBundlePageSetPageZoomFactor(m_page, 1); 274 WKBundlePageSetTextZoomFactor(m_page, 1); 275 276 WKPoint origin = { 0, 0 }; 277 WKBundlePageSetScaleAtOrigin(m_page, 1, origin); 278 279 m_previousTestBackForwardListItem = adoptWK(WKBundleBackForwardListCopyItemAtIndex(WKBundlePageGetBackForwardList(m_page), 0)); 280 281 WKBundleFrameClearOpener(WKBundlePageGetMainFrame(m_page)); 282 } 283 284 // Loader Client Callbacks 285 286 void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo) 287 { 288 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didStartProvisionalLoadForFrame(frame); 289 } 290 291 void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo) 292 { 293 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveServerRedirectForProvisionalLoadForFrame(frame); 294 } 295 296 void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef*, const void *clientInfo) 297 { 298 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailProvisionalLoadWithErrorForFrame(frame, error); 299 } 300 301 void InjectedBundlePage::didCommitLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo) 302 { 303 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didCommitLoadForFrame(frame); 304 } 305 306 void InjectedBundlePage::didFinishLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo) 307 { 308 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(frame); 309 } 310 311 void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo) 312 { 313 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishDocumentLoadForFrame(frame); 314 } 315 316 void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef*, const void *clientInfo) 317 { 318 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailLoadWithErrorForFrame(frame, error); 319 } 320 321 void InjectedBundlePage::didReceiveTitleForFrame(WKBundlePageRef page, WKStringRef title, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo) 322 { 323 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveTitleForFrame(title, frame); 324 } 325 326 void InjectedBundlePage::didClearWindowForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleScriptWorldRef world, const void *clientInfo) 327 { 328 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didClearWindowForFrame(frame, world); 329 } 330 331 void InjectedBundlePage::didCancelClientRedirectForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo) 332 { 333 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didCancelClientRedirectForFrame(frame); 334 } 335 336 void InjectedBundlePage::willPerformClientRedirectForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKURLRef url, double delay, double date, const void* clientInfo) 337 { 338 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willPerformClientRedirectForFrame(frame, url, delay, date); 339 } 340 341 void InjectedBundlePage::didSameDocumentNavigationForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef*, const void* clientInfo) 342 { 343 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didSameDocumentNavigationForFrame(frame, type); 344 } 345 346 void InjectedBundlePage::didHandleOnloadEventsForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo) 347 { 348 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didHandleOnloadEventsForFrame(frame); 349 } 350 351 void InjectedBundlePage::didDisplayInsecureContentForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo) 352 { 353 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didDisplayInsecureContentForFrame(frame); 354 } 355 356 void InjectedBundlePage::didRunInsecureContentForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo) 357 { 358 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didRunInsecureContentForFrame(frame); 359 } 360 361 void InjectedBundlePage::didInitiateLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLRequestRef request, bool pageLoadIsProvisional, const void* clientInfo) 362 { 363 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didInitiateLoadForResource(page, frame, identifier, request, pageLoadIsProvisional); 364 } 365 366 WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLRequestRef request, WKURLResponseRef redirectResponse, const void* clientInfo) 367 { 368 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willSendRequestForFrame(page, frame, identifier, request, redirectResponse); 369 } 370 371 void InjectedBundlePage::didReceiveResponseForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLResponseRef response, const void* clientInfo) 372 { 373 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveResponseForResource(page, frame, identifier, response); 374 } 375 376 void InjectedBundlePage::didReceiveContentLengthForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, uint64_t length, const void* clientInfo) 377 { 378 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveContentLengthForResource(page, frame, identifier, length); 379 } 380 381 void InjectedBundlePage::didFinishLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, const void* clientInfo) 382 { 383 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForResource(page, frame, identifier); 384 } 385 386 void InjectedBundlePage::didFailLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKErrorRef error, const void* clientInfo) 387 { 388 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForResource(page, frame, identifier, error); 389 } 390 391 void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundleFrameRef frame) 392 { 393 if (!InjectedBundle::shared().isTestRunning()) 394 return; 395 396 if (InjectedBundle::shared().topLoadingFrame()) 397 return; 398 InjectedBundle::shared().setTopLoadingFrame(frame); 399 } 400 401 void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundleFrameRef frame) 402 { 403 } 404 405 void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef error) 406 { 407 if (!InjectedBundle::shared().isTestRunning()) 408 return; 409 410 if (frame != InjectedBundle::shared().topLoadingFrame()) 411 return; 412 InjectedBundle::shared().setTopLoadingFrame(0); 413 414 if (InjectedBundle::shared().layoutTestController()->waitToDump()) 415 return; 416 417 InjectedBundle::shared().done(); 418 } 419 420 void InjectedBundlePage::didCommitLoadForFrame(WKBundleFrameRef frame) 421 { 422 } 423 424 enum FrameNamePolicy { ShouldNotIncludeFrameName, ShouldIncludeFrameName }; 425 426 static void dumpFrameScrollPosition(WKBundleFrameRef frame, FrameNamePolicy shouldIncludeFrameName = ShouldNotIncludeFrameName) 427 { 428 double x = numericWindowPropertyValue(frame, "pageXOffset"); 429 double y = numericWindowPropertyValue(frame, "pageYOffset"); 430 if (fabs(x) > 0.00000001 || fabs(y) > 0.00000001) { 431 if (shouldIncludeFrameName) { 432 WKRetainPtr<WKStringRef> name(AdoptWK, WKBundleFrameCopyName(frame)); 433 InjectedBundle::shared().os() << "frame '" << name << "' "; 434 } 435 InjectedBundle::shared().os() << "scrolled to " << x << "," << y << "\n"; 436 } 437 } 438 439 static void dumpDescendantFrameScrollPositions(WKBundleFrameRef frame) 440 { 441 WKRetainPtr<WKArrayRef> childFrames(AdoptWK, WKBundleFrameCopyChildFrames(frame)); 442 size_t size = WKArrayGetSize(childFrames.get()); 443 for (size_t i = 0; i < size; ++i) { 444 WKBundleFrameRef subframe = static_cast<WKBundleFrameRef>(WKArrayGetItemAtIndex(childFrames.get(), i)); 445 dumpFrameScrollPosition(subframe, ShouldIncludeFrameName); 446 dumpDescendantFrameScrollPositions(subframe); 447 } 448 } 449 450 void InjectedBundlePage::dumpAllFrameScrollPositions() 451 { 452 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page); 453 dumpFrameScrollPosition(frame); 454 dumpDescendantFrameScrollPositions(frame); 455 } 456 457 static JSRetainPtr<JSStringRef> toJS(const char* string) 458 { 459 return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString(string)); 460 } 461 462 static bool hasDocumentElement(WKBundleFrameRef frame) 463 { 464 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame); 465 JSObjectRef globalObject = JSContextGetGlobalObject(context); 466 467 JSValueRef documentValue = JSObjectGetProperty(context, globalObject, toJS("document").get(), 0); 468 if (!documentValue) 469 return false; 470 471 ASSERT(JSValueIsObject(context, documentValue)); 472 JSObjectRef document = JSValueToObject(context, documentValue, 0); 473 474 JSValueRef documentElementValue = JSObjectGetProperty(context, document, toJS("documentElement").get(), 0); 475 if (!documentElementValue) 476 return false; 477 478 return JSValueToBoolean(context, documentElementValue); 479 } 480 481 static void dumpFrameText(WKBundleFrameRef frame) 482 { 483 // If the frame doesn't have a document element, its inner text will be an empty string, so 484 // we'll end up just appending a single newline below. But DumpRenderTree doesn't append 485 // anything in this case, so we shouldn't either. 486 if (!hasDocumentElement(frame)) 487 return; 488 489 WKRetainPtr<WKStringRef> text(AdoptWK, WKBundleFrameCopyInnerText(frame)); 490 InjectedBundle::shared().os() << text << "\n"; 491 } 492 493 static void dumpDescendantFramesText(WKBundleFrameRef frame) 494 { 495 WKRetainPtr<WKArrayRef> childFrames(AdoptWK, WKBundleFrameCopyChildFrames(frame)); 496 size_t size = WKArrayGetSize(childFrames.get()); 497 for (size_t i = 0; i < size; ++i) { 498 WKBundleFrameRef subframe = static_cast<WKBundleFrameRef>(WKArrayGetItemAtIndex(childFrames.get(), i)); 499 WKRetainPtr<WKStringRef> subframeName(AdoptWK, WKBundleFrameCopyName(subframe)); 500 InjectedBundle::shared().os() << "\n--------\nFrame: '" << subframeName << "'\n--------\n"; 501 dumpFrameText(subframe); 502 dumpDescendantFramesText(subframe); 503 } 504 } 505 506 void InjectedBundlePage::dumpAllFramesText() 507 { 508 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page); 509 dumpFrameText(frame); 510 dumpDescendantFramesText(frame); 511 } 512 513 void InjectedBundlePage::dump() 514 { 515 ASSERT(InjectedBundle::shared().isTestRunning()); 516 517 InjectedBundle::shared().layoutTestController()->invalidateWaitToDumpWatchdogTimer(); 518 519 // Force a paint before dumping. This matches DumpRenderTree on Windows. (DumpRenderTree on Mac 520 // does this at a slightly different time.) See <http://webkit.org/b/55469> for details. 521 WKBundlePageForceRepaint(m_page); 522 523 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page); 524 string url = toSTD(adoptWK(WKURLCopyString(adoptWK(WKBundleFrameCopyURL(frame)).get()))); 525 if (strstr(url.c_str(), "dumpAsText/")) 526 InjectedBundle::shared().layoutTestController()->dumpAsText(); 527 528 switch (InjectedBundle::shared().layoutTestController()->whatToDump()) { 529 case LayoutTestController::RenderTree: { 530 WKRetainPtr<WKStringRef> text(AdoptWK, WKBundlePageCopyRenderTreeExternalRepresentation(m_page)); 531 InjectedBundle::shared().os() << text; 532 break; 533 } 534 case LayoutTestController::MainFrameText: 535 dumpFrameText(WKBundlePageGetMainFrame(m_page)); 536 break; 537 case LayoutTestController::AllFramesText: 538 dumpAllFramesText(); 539 break; 540 } 541 542 if (InjectedBundle::shared().layoutTestController()->shouldDumpAllFrameScrollPositions()) 543 dumpAllFrameScrollPositions(); 544 else if (InjectedBundle::shared().layoutTestController()->shouldDumpMainFrameScrollPosition()) 545 dumpFrameScrollPosition(WKBundlePageGetMainFrame(m_page)); 546 547 if (InjectedBundle::shared().layoutTestController()->shouldDumpBackForwardListsForAllWindows()) 548 InjectedBundle::shared().dumpBackForwardListsForAllPages(); 549 550 if (InjectedBundle::shared().shouldDumpPixels() && InjectedBundle::shared().layoutTestController()->shouldDumpPixels()) 551 InjectedBundle::shared().setPixelResult(adoptWK(WKBundlePageCreateSnapshotInViewCoordinates(m_page, WKBundleFrameGetVisibleContentBounds(WKBundlePageGetMainFrame(m_page)), kWKImageOptionsShareable)).get()); 552 553 InjectedBundle::shared().done(); 554 } 555 556 void InjectedBundlePage::didFinishLoadForFrame(WKBundleFrameRef frame) 557 { 558 if (!InjectedBundle::shared().isTestRunning()) 559 return; 560 561 if (frame != InjectedBundle::shared().topLoadingFrame()) 562 return; 563 InjectedBundle::shared().setTopLoadingFrame(0); 564 565 if (InjectedBundle::shared().layoutTestController()->waitToDump()) 566 return; 567 568 InjectedBundle::shared().page()->dump(); 569 } 570 571 void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef) 572 { 573 if (!InjectedBundle::shared().isTestRunning()) 574 return; 575 576 if (frame != InjectedBundle::shared().topLoadingFrame()) 577 return; 578 InjectedBundle::shared().setTopLoadingFrame(0); 579 580 if (InjectedBundle::shared().layoutTestController()->waitToDump()) 581 return; 582 583 InjectedBundle::shared().done(); 584 } 585 586 void InjectedBundlePage::didReceiveTitleForFrame(WKStringRef title, WKBundleFrameRef frame) 587 { 588 if (!InjectedBundle::shared().isTestRunning()) 589 return; 590 591 if (!InjectedBundle::shared().layoutTestController()->shouldDumpTitleChanges()) 592 return; 593 594 InjectedBundle::shared().os() << "TITLE CHANGED: " << title << "\n"; 595 } 596 597 void InjectedBundlePage::didClearWindowForFrame(WKBundleFrameRef frame, WKBundleScriptWorldRef world) 598 { 599 if (!InjectedBundle::shared().isTestRunning()) 600 return; 601 602 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world); 603 JSObjectRef window = JSContextGetGlobalObject(context); 604 605 if (WKBundleScriptWorldNormalWorld() != world) { 606 JSObjectSetProperty(context, window, toJS("__worldID").get(), JSValueMakeNumber(context, LayoutTestController::worldIDForWorld(world)), kJSPropertyAttributeReadOnly, 0); 607 return; 608 } 609 610 JSValueRef exception = 0; 611 InjectedBundle::shared().layoutTestController()->makeWindowObject(context, window, &exception); 612 InjectedBundle::shared().gcController()->makeWindowObject(context, window, &exception); 613 InjectedBundle::shared().eventSendingController()->makeWindowObject(context, window, &exception); 614 } 615 616 void InjectedBundlePage::didCancelClientRedirectForFrame(WKBundleFrameRef frame) 617 { 618 } 619 620 void InjectedBundlePage::willPerformClientRedirectForFrame(WKBundleFrameRef frame, WKURLRef url, double delay, double date) 621 { 622 } 623 624 void InjectedBundlePage::didSameDocumentNavigationForFrame(WKBundleFrameRef frame, WKSameDocumentNavigationType type) 625 { 626 } 627 628 void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundleFrameRef frame) 629 { 630 if (!InjectedBundle::shared().isTestRunning()) 631 return; 632 633 unsigned pendingFrameUnloadEvents = WKBundleFrameGetPendingUnloadCount(frame); 634 if (pendingFrameUnloadEvents) 635 InjectedBundle::shared().os() << frame << " - has " << pendingFrameUnloadEvents << " onunload handler(s)\n"; 636 } 637 638 void InjectedBundlePage::didHandleOnloadEventsForFrame(WKBundleFrameRef frame) 639 { 640 } 641 642 void InjectedBundlePage::didDisplayInsecureContentForFrame(WKBundleFrameRef frame) 643 { 644 } 645 646 void InjectedBundlePage::didRunInsecureContentForFrame(WKBundleFrameRef frame) 647 { 648 } 649 650 void InjectedBundlePage::didInitiateLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t identifier, WKURLRequestRef, bool) 651 { 652 } 653 654 // Resource Load Client Callbacks 655 656 WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef, WKBundleFrameRef, uint64_t, WKURLRequestRef request, WKURLResponseRef) 657 { 658 if (InjectedBundle::shared().isTestRunning() && InjectedBundle::shared().layoutTestController()->willSendRequestReturnsNull()) 659 return 0; 660 661 WKRetainPtr<WKURLRef> url = adoptWK(WKURLRequestCopyURL(request)); 662 WKRetainPtr<WKStringRef> host = adoptWK(WKURLCopyHostName(url.get())); 663 WKRetainPtr<WKStringRef> scheme = adoptWK(WKURLCopyScheme(url.get())); 664 if (host && !WKStringIsEmpty(host.get()) 665 && (WKStringIsEqualToUTF8CStringIgnoringCase(scheme.get(), "http") || WKStringIsEqualToUTF8CStringIgnoringCase(scheme.get(), "https")) 666 && !WKStringIsEqualToUTF8CString(host.get(), "127.0.0.1") 667 && !WKStringIsEqualToUTF8CString(host.get(), "255.255.255.255") // Used in some tests that expect to get back an error. 668 && !WKStringIsEqualToUTF8CStringIgnoringCase(host.get(), "localhost")) { 669 InjectedBundle::shared().os() << "Blocked access to external URL " << url << "\n"; 670 return 0; 671 } 672 673 WKRetain(request); 674 return request; 675 } 676 677 void InjectedBundlePage::didReceiveResponseForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t, WKURLResponseRef) 678 { 679 } 680 681 void InjectedBundlePage::didReceiveContentLengthForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t, uint64_t) 682 { 683 } 684 685 void InjectedBundlePage::didFinishLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t) 686 { 687 } 688 689 void InjectedBundlePage::didFailLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t, WKErrorRef) 690 { 691 } 692 693 694 // Policy Client Callbacks 695 696 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNavigationAction(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleNavigationActionRef navigationAction, WKURLRequestRef request, WKTypeRef* userData, const void* clientInfo) 697 { 698 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->decidePolicyForNavigationAction(page, frame, navigationAction, request, userData); 699 } 700 701 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNewWindowAction(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleNavigationActionRef navigationAction, WKURLRequestRef request, WKStringRef frameName, WKTypeRef* userData, const void* clientInfo) 702 { 703 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->decidePolicyForNewWindowAction(page, frame, navigationAction, request, frameName, userData); 704 } 705 706 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForResponse(WKBundlePageRef page, WKBundleFrameRef frame, WKURLResponseRef response, WKURLRequestRef request, WKTypeRef* userData, const void* clientInfo) 707 { 708 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->decidePolicyForResponse(page, frame, response, request, userData); 709 } 710 711 void InjectedBundlePage::unableToImplementPolicy(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef* userData, const void* clientInfo) 712 { 713 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->unableToImplementPolicy(page, frame, error, userData); 714 } 715 716 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNavigationAction(WKBundlePageRef, WKBundleFrameRef, WKBundleNavigationActionRef, WKURLRequestRef request, WKTypeRef*) 717 { 718 return WKBundlePagePolicyActionUse; 719 } 720 721 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNewWindowAction(WKBundlePageRef, WKBundleFrameRef, WKBundleNavigationActionRef, WKURLRequestRef, WKStringRef, WKTypeRef*) 722 { 723 return WKBundlePagePolicyActionUse; 724 } 725 726 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForResponse(WKBundlePageRef, WKBundleFrameRef, WKURLResponseRef, WKURLRequestRef, WKTypeRef*) 727 { 728 return WKBundlePagePolicyActionUse; 729 } 730 731 void InjectedBundlePage::unableToImplementPolicy(WKBundlePageRef, WKBundleFrameRef, WKErrorRef, WKTypeRef*) 732 { 733 } 734 735 // UI Client Callbacks 736 737 void InjectedBundlePage::willAddMessageToConsole(WKBundlePageRef page, WKStringRef message, uint32_t lineNumber, const void *clientInfo) 738 { 739 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willAddMessageToConsole(message, lineNumber); 740 } 741 742 void InjectedBundlePage::willSetStatusbarText(WKBundlePageRef page, WKStringRef statusbarText, const void *clientInfo) 743 { 744 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willSetStatusbarText(statusbarText); 745 } 746 747 void InjectedBundlePage::willRunJavaScriptAlert(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo) 748 { 749 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptAlert(message, frame); 750 } 751 752 void InjectedBundlePage::willRunJavaScriptConfirm(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo) 753 { 754 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptConfirm(message, frame); 755 } 756 757 void InjectedBundlePage::willRunJavaScriptPrompt(WKBundlePageRef page, WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef frame, const void *clientInfo) 758 { 759 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptPrompt(message, defaultValue, frame); 760 } 761 762 static string lastFileURLPathComponent(const string& path) 763 { 764 size_t pos = path.find("file://"); 765 ASSERT(string::npos != pos); 766 767 string tmpPath = path.substr(pos + 7); 768 if (tmpPath.empty()) 769 return tmpPath; 770 771 // Remove the trailing delimiter 772 if (tmpPath[tmpPath.length() - 1] == '/') 773 tmpPath.erase(tmpPath.length() - 1); 774 775 pos = tmpPath.rfind('/'); 776 if (string::npos != pos) 777 return tmpPath.substr(pos + 1); 778 779 return tmpPath; 780 } 781 782 void InjectedBundlePage::willAddMessageToConsole(WKStringRef message, uint32_t lineNumber) 783 { 784 if (!InjectedBundle::shared().isTestRunning()) 785 return; 786 787 string messageString = toSTD(message); 788 size_t fileProtocolStart = messageString.find("file://"); 789 if (fileProtocolStart != string::npos) 790 // FIXME: The code below does not handle additional text after url nor multiple urls. This matches DumpRenderTree implementation. 791 messageString = messageString.substr(0, fileProtocolStart) + lastFileURLPathComponent(messageString.substr(fileProtocolStart)); 792 793 InjectedBundle::shared().os() << "CONSOLE MESSAGE: line " << lineNumber << ": " << messageString << "\n"; 794 } 795 796 void InjectedBundlePage::willSetStatusbarText(WKStringRef statusbarText) 797 { 798 if (!InjectedBundle::shared().isTestRunning()) 799 return; 800 801 if (!InjectedBundle::shared().layoutTestController()->shouldDumpStatusCallbacks()) 802 return; 803 804 InjectedBundle::shared().os() << "UI DELEGATE STATUS CALLBACK: setStatusText:" << statusbarText << "\n"; 805 } 806 807 void InjectedBundlePage::willRunJavaScriptAlert(WKStringRef message, WKBundleFrameRef) 808 { 809 if (!InjectedBundle::shared().isTestRunning()) 810 return; 811 812 InjectedBundle::shared().os() << "ALERT: " << message << "\n"; 813 } 814 815 void InjectedBundlePage::willRunJavaScriptConfirm(WKStringRef message, WKBundleFrameRef) 816 { 817 if (!InjectedBundle::shared().isTestRunning()) 818 return; 819 820 InjectedBundle::shared().os() << "CONFIRM: " << message << "\n"; 821 } 822 823 void InjectedBundlePage::willRunJavaScriptPrompt(WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef) 824 { 825 InjectedBundle::shared().os() << "PROMPT: " << message << ", default text: " << defaultValue << "\n"; 826 } 827 828 // Editor Client Callbacks 829 830 bool InjectedBundlePage::shouldBeginEditing(WKBundlePageRef page, WKBundleRangeHandleRef range, const void* clientInfo) 831 { 832 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldBeginEditing(range); 833 } 834 835 bool InjectedBundlePage::shouldEndEditing(WKBundlePageRef page, WKBundleRangeHandleRef range, const void* clientInfo) 836 { 837 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldEndEditing(range); 838 } 839 840 bool InjectedBundlePage::shouldInsertNode(WKBundlePageRef page, WKBundleNodeHandleRef node, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action, const void* clientInfo) 841 { 842 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldInsertNode(node, rangeToReplace, action); 843 } 844 845 bool InjectedBundlePage::shouldInsertText(WKBundlePageRef page, WKStringRef text, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action, const void* clientInfo) 846 { 847 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldInsertText(text, rangeToReplace, action); 848 } 849 850 bool InjectedBundlePage::shouldDeleteRange(WKBundlePageRef page, WKBundleRangeHandleRef range, const void* clientInfo) 851 { 852 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldDeleteRange(range); 853 } 854 855 bool InjectedBundlePage::shouldChangeSelectedRange(WKBundlePageRef page, WKBundleRangeHandleRef fromRange, WKBundleRangeHandleRef toRange, WKAffinityType affinity, bool stillSelecting, const void* clientInfo) 856 { 857 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldChangeSelectedRange(fromRange, toRange, affinity, stillSelecting); 858 } 859 860 bool InjectedBundlePage::shouldApplyStyle(WKBundlePageRef page, WKBundleCSSStyleDeclarationRef style, WKBundleRangeHandleRef range, const void* clientInfo) 861 { 862 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldApplyStyle(style, range); 863 } 864 865 void InjectedBundlePage::didBeginEditing(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo) 866 { 867 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didBeginEditing(notificationName); 868 } 869 870 void InjectedBundlePage::didEndEditing(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo) 871 { 872 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didEndEditing(notificationName); 873 } 874 875 void InjectedBundlePage::didChange(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo) 876 { 877 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didChange(notificationName); 878 } 879 880 void InjectedBundlePage::didChangeSelection(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo) 881 { 882 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didChangeSelection(notificationName); 883 } 884 885 bool InjectedBundlePage::shouldBeginEditing(WKBundleRangeHandleRef range) 886 { 887 if (!InjectedBundle::shared().isTestRunning()) 888 return true; 889 890 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks()) 891 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldBeginEditingInDOMRange:" << toStr(m_page, m_world.get(), range) << "\n"; 892 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing(); 893 } 894 895 bool InjectedBundlePage::shouldEndEditing(WKBundleRangeHandleRef range) 896 { 897 if (!InjectedBundle::shared().isTestRunning()) 898 return true; 899 900 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks()) 901 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldEndEditingInDOMRange:" << toStr(m_page, m_world.get(), range) << "\n"; 902 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing(); 903 } 904 905 bool InjectedBundlePage::shouldInsertNode(WKBundleNodeHandleRef node, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action) 906 { 907 if (!InjectedBundle::shared().isTestRunning()) 908 return true; 909 910 static const char* insertactionstring[] = { 911 "WebViewInsertActionTyped", 912 "WebViewInsertActionPasted", 913 "WebViewInsertActionDropped", 914 }; 915 916 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks()) 917 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldInsertNode:" << dumpPath(m_page, m_world.get(), node) << " replacingDOMRange:" << toStr(m_page, m_world.get(), rangeToReplace) << " givenAction:" << insertactionstring[action] << "\n"; 918 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing(); 919 } 920 921 bool InjectedBundlePage::shouldInsertText(WKStringRef text, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action) 922 { 923 if (!InjectedBundle::shared().isTestRunning()) 924 return true; 925 926 static const char *insertactionstring[] = { 927 "WebViewInsertActionTyped", 928 "WebViewInsertActionPasted", 929 "WebViewInsertActionDropped", 930 }; 931 932 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks()) 933 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldInsertText:" << text << " replacingDOMRange:" << toStr(m_page, m_world.get(), rangeToReplace) << " givenAction:" << insertactionstring[action] << "\n"; 934 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing(); 935 } 936 937 bool InjectedBundlePage::shouldDeleteRange(WKBundleRangeHandleRef range) 938 { 939 if (!InjectedBundle::shared().isTestRunning()) 940 return true; 941 942 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks()) 943 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldDeleteDOMRange:" << toStr(m_page, m_world.get(), range) << "\n"; 944 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing(); 945 } 946 947 bool InjectedBundlePage::shouldChangeSelectedRange(WKBundleRangeHandleRef fromRange, WKBundleRangeHandleRef toRange, WKAffinityType affinity, bool stillSelecting) 948 { 949 if (!InjectedBundle::shared().isTestRunning()) 950 return true; 951 952 static const char *affinitystring[] = { 953 "NSSelectionAffinityUpstream", 954 "NSSelectionAffinityDownstream" 955 }; 956 static const char *boolstring[] = { 957 "FALSE", 958 "TRUE" 959 }; 960 961 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks()) 962 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldChangeSelectedDOMRange:" << toStr(m_page, m_world.get(), fromRange) << " toDOMRange:" << toStr(m_page, m_world.get(), toRange) << " affinity:" << affinitystring[affinity] << " stillSelecting:" << boolstring[stillSelecting] << "\n"; 963 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing(); 964 } 965 966 bool InjectedBundlePage::shouldApplyStyle(WKBundleCSSStyleDeclarationRef style, WKBundleRangeHandleRef range) 967 { 968 if (!InjectedBundle::shared().isTestRunning()) 969 return true; 970 971 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks()) 972 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldApplyStyle:" << style << " toElementsInDOMRange:" << toStr(m_page, m_world.get(), range) << "\n"; 973 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing(); 974 } 975 976 void InjectedBundlePage::didBeginEditing(WKStringRef notificationName) 977 { 978 if (!InjectedBundle::shared().isTestRunning()) 979 return; 980 981 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks()) 982 InjectedBundle::shared().os() << "EDITING DELEGATE: webViewDidBeginEditing:" << notificationName << "\n"; 983 } 984 985 void InjectedBundlePage::didEndEditing(WKStringRef notificationName) 986 { 987 if (!InjectedBundle::shared().isTestRunning()) 988 return; 989 990 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks()) 991 InjectedBundle::shared().os() << "EDITING DELEGATE: webViewDidEndEditing:" << notificationName << "\n"; 992 } 993 994 void InjectedBundlePage::didChange(WKStringRef notificationName) 995 { 996 if (!InjectedBundle::shared().isTestRunning()) 997 return; 998 999 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks()) 1000 InjectedBundle::shared().os() << "EDITING DELEGATE: webViewDidChange:" << notificationName << "\n"; 1001 } 1002 1003 void InjectedBundlePage::didChangeSelection(WKStringRef notificationName) 1004 { 1005 if (!InjectedBundle::shared().isTestRunning()) 1006 return; 1007 1008 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks()) 1009 InjectedBundle::shared().os() << "EDITING DELEGATE: webViewDidChangeSelection:" << notificationName << "\n"; 1010 } 1011 1012 #if ENABLE(FULLSCREEN_API) 1013 bool InjectedBundlePage::supportsFullScreen(WKBundlePageRef pageRef, WKFullScreenKeyboardRequestType requestType) 1014 { 1015 if (InjectedBundle::shared().layoutTestController()->shouldDumpFullScreenCallbacks()) 1016 InjectedBundle::shared().os() << "supportsFullScreen() == true\n"; 1017 return true; 1018 } 1019 1020 void InjectedBundlePage::enterFullScreenForElement(WKBundlePageRef pageRef, WKBundleNodeHandleRef elementRef) 1021 { 1022 if (InjectedBundle::shared().layoutTestController()->shouldDumpFullScreenCallbacks()) 1023 InjectedBundle::shared().os() << "enterFullScreenForElement()\n"; 1024 WKBundlePageWillEnterFullScreen(pageRef); 1025 WKBundlePageDidEnterFullScreen(pageRef); 1026 } 1027 1028 void InjectedBundlePage::exitFullScreenForElement(WKBundlePageRef pageRef, WKBundleNodeHandleRef elementRef) 1029 { 1030 if (InjectedBundle::shared().layoutTestController()->shouldDumpFullScreenCallbacks()) 1031 InjectedBundle::shared().os() << "exitFullScreenForElement()\n"; 1032 WKBundlePageWillExitFullScreen(pageRef); 1033 WKBundlePageDidExitFullScreen(pageRef); 1034 } 1035 #endif 1036 1037 static bool compareByTargetName(WKBundleBackForwardListItemRef item1, WKBundleBackForwardListItemRef item2) 1038 { 1039 return toSTD(adoptWK(WKBundleBackForwardListItemCopyTarget(item1))) < toSTD(adoptWK(WKBundleBackForwardListItemCopyTarget(item2))); 1040 } 1041 1042 static void dumpBackForwardListItem(WKBundleBackForwardListItemRef item, unsigned indent, bool isCurrentItem) 1043 { 1044 unsigned column = 0; 1045 if (isCurrentItem) { 1046 InjectedBundle::shared().os() << "curr->"; 1047 column = 6; 1048 } 1049 for (unsigned i = column; i < indent; i++) 1050 InjectedBundle::shared().os() << ' '; 1051 1052 string url = toSTD(adoptWK(WKURLCopyString(adoptWK(WKBundleBackForwardListItemCopyURL(item)).get()))); 1053 if (hasPrefix(url, "file:")) { 1054 string directoryName = "/LayoutTests/"; 1055 size_t start = url.find(directoryName); 1056 if (start == string::npos) 1057 start = 0; 1058 else 1059 start += directoryName.size(); 1060 InjectedBundle::shared().os() << "(file test):" << url.substr(start); 1061 } else 1062 InjectedBundle::shared().os() << url; 1063 1064 string target = toSTD(adoptWK(WKBundleBackForwardListItemCopyTarget(item))); 1065 if (target.length()) 1066 InjectedBundle::shared().os() << " (in frame \"" << target << "\")"; 1067 1068 // FIXME: Need WKBackForwardListItemIsTargetItem. 1069 if (WKBundleBackForwardListItemIsTargetItem(item)) 1070 InjectedBundle::shared().os() << " **nav target**"; 1071 1072 InjectedBundle::shared().os() << '\n'; 1073 1074 if (WKRetainPtr<WKArrayRef> kids = adoptWK(WKBundleBackForwardListItemCopyChildren(item))) { 1075 // Sort to eliminate arbitrary result ordering which defeats reproducible testing. 1076 size_t size = WKArrayGetSize(kids.get()); 1077 Vector<WKBundleBackForwardListItemRef> sortedKids(size); 1078 for (size_t i = 0; i < size; ++i) 1079 sortedKids[i] = static_cast<WKBundleBackForwardListItemRef>(WKArrayGetItemAtIndex(kids.get(), i)); 1080 stable_sort(sortedKids.begin(), sortedKids.end(), compareByTargetName); 1081 for (size_t i = 0; i < size; ++i) 1082 dumpBackForwardListItem(sortedKids[i], indent + 4, false); 1083 } 1084 } 1085 1086 void InjectedBundlePage::dumpBackForwardList() 1087 { 1088 InjectedBundle::shared().os() << "\n============== Back Forward List ==============\n"; 1089 1090 WKBundleBackForwardListRef list = WKBundlePageGetBackForwardList(m_page); 1091 1092 // Print out all items in the list after m_previousTestBackForwardListItem. 1093 // Gather items from the end of the list, then print them out from oldest to newest. 1094 Vector<WKRetainPtr<WKBundleBackForwardListItemRef> > itemsToPrint; 1095 for (unsigned i = WKBundleBackForwardListGetForwardListCount(list); i; --i) { 1096 WKRetainPtr<WKBundleBackForwardListItemRef> item = adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, i)); 1097 // Something is wrong if the item from the last test is in the forward part of the list. 1098 ASSERT(!WKBundleBackForwardListItemIsSame(item.get(), m_previousTestBackForwardListItem.get())); 1099 itemsToPrint.append(item); 1100 } 1101 1102 ASSERT(!WKBundleBackForwardListItemIsSame(adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, 0)).get(), m_previousTestBackForwardListItem.get())); 1103 1104 itemsToPrint.append(adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, 0))); 1105 1106 int currentItemIndex = itemsToPrint.size() - 1; 1107 1108 int backListCount = WKBundleBackForwardListGetBackListCount(list); 1109 for (int i = -1; i >= -backListCount; --i) { 1110 WKRetainPtr<WKBundleBackForwardListItemRef> item = adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, i)); 1111 if (WKBundleBackForwardListItemIsSame(item.get(), m_previousTestBackForwardListItem.get())) 1112 break; 1113 itemsToPrint.append(item); 1114 } 1115 1116 for (int i = itemsToPrint.size() - 1; i >= 0; i--) 1117 dumpBackForwardListItem(itemsToPrint[i].get(), 8, i == currentItemIndex); 1118 1119 InjectedBundle::shared().os() << "===============================================\n"; 1120 } 1121 1122 } // namespace WTR 1123