2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "InjectedBundlePage.h"
29 #include "InjectedBundle.h"
30 #include "StringFunctions.h"
31 #include "WebCoreTestSupport.h"
33 #include <JavaScriptCore/JSRetainPtr.h>
34 #include <WebKit2/WKArray.h>
35 #include <WebKit2/WKBundle.h>
36 #include <WebKit2/WKBundleBackForwardList.h>
37 #include <WebKit2/WKBundleBackForwardListItem.h>
38 #include <WebKit2/WKBundleFrame.h>
39 #include <WebKit2/WKBundleFramePrivate.h>
40 #include <WebKit2/WKBundleHitTestResult.h>
41 #include <WebKit2/WKBundleNavigationAction.h>
42 #include <WebKit2/WKBundleNodeHandlePrivate.h>
43 #include <WebKit2/WKBundlePagePrivate.h>
44 #include <WebKit2/WKURLRequest.h>
47 #include "DumpRenderTreeSupportQt.h"
54 static bool hasPrefix(const string& searchString, const string& prefix)
56 return searchString.length() >= prefix.length() && searchString.substr(0, prefix.length()) == prefix;
59 static JSValueRef propertyValue(JSContextRef context, JSObjectRef object, const char* propertyName)
63 JSRetainPtr<JSStringRef> propertyNameString(Adopt, JSStringCreateWithUTF8CString(propertyName));
64 return JSObjectGetProperty(context, object, propertyNameString.get(), 0);
67 static double propertyValueDouble(JSContextRef context, JSObjectRef object, const char* propertyName)
69 JSValueRef value = propertyValue(context, object, propertyName);
72 return JSValueToNumber(context, value, 0);
75 static int propertyValueInt(JSContextRef context, JSObjectRef object, const char* propertyName)
77 return static_cast<int>(propertyValueDouble(context, object, propertyName));
80 static double numericWindowPropertyValue(WKBundleFrameRef frame, const char* propertyName)
82 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
83 return propertyValueDouble(context, JSContextGetGlobalObject(context), propertyName);
86 static string dumpPath(JSGlobalContextRef context, JSObjectRef nodeValue)
88 JSValueRef nodeNameValue = propertyValue(context, nodeValue, "nodeName");
89 JSRetainPtr<JSStringRef> jsStringNodeName(Adopt, JSValueToStringCopy(context, nodeNameValue, 0));
90 WKRetainPtr<WKStringRef> nodeName = toWK(jsStringNodeName);
92 JSValueRef parentNode = propertyValue(context, nodeValue, "parentNode");
97 if (parentNode && JSValueIsObject(context, parentNode))
98 out << " > " << dumpPath(context, (JSObjectRef)parentNode);
103 static string dumpPath(WKBundlePageRef page, WKBundleScriptWorldRef world, WKBundleNodeHandleRef node)
108 WKBundleFrameRef frame = WKBundlePageGetMainFrame(page);
110 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world);
111 JSValueRef nodeValue = WKBundleFrameGetJavaScriptWrapperForNodeForWorld(frame, node, world);
112 ASSERT(JSValueIsObject(context, nodeValue));
113 JSObjectRef nodeObject = (JSObjectRef)nodeValue;
115 return dumpPath(context, nodeObject);
118 static string toStr(WKBundlePageRef page, WKBundleScriptWorldRef world, WKBundleRangeHandleRef rangeRef)
123 WKBundleFrameRef frame = WKBundlePageGetMainFrame(page);
125 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world);
126 JSValueRef rangeValue = WKBundleFrameGetJavaScriptWrapperForRangeForWorld(frame, rangeRef, world);
127 ASSERT(JSValueIsObject(context, rangeValue));
128 JSObjectRef rangeObject = (JSObjectRef)rangeValue;
130 JSValueRef startNodeValue = propertyValue(context, rangeObject, "startContainer");
131 ASSERT(JSValueIsObject(context, startNodeValue));
132 JSObjectRef startNodeObject = (JSObjectRef)startNodeValue;
134 JSValueRef endNodeValue = propertyValue(context, rangeObject, "endContainer");
135 ASSERT(JSValueIsObject(context, endNodeValue));
136 JSObjectRef endNodeObject = (JSObjectRef)endNodeValue;
138 int startOffset = propertyValueInt(context, rangeObject, "startOffset");
139 int endOffset = propertyValueInt(context, rangeObject, "endOffset");
142 out << "range from " << startOffset << " of " << dumpPath(context, startNodeObject) << " to " << endOffset << " of " << dumpPath(context, endNodeObject);
146 static WKRetainPtr<WKStringRef> navigationTypeToString(WKFrameNavigationType type)
149 case kWKFrameNavigationTypeLinkClicked:
150 return adoptWK(WKStringCreateWithUTF8CString("link clicked"));
151 case kWKFrameNavigationTypeFormSubmitted:
152 return adoptWK(WKStringCreateWithUTF8CString("form submitted"));
153 case kWKFrameNavigationTypeBackForward:
154 return adoptWK(WKStringCreateWithUTF8CString("back/forward"));
155 case kWKFrameNavigationTypeReload:
156 return adoptWK(WKStringCreateWithUTF8CString("reload"));
157 case kWKFrameNavigationTypeFormResubmitted:
158 return adoptWK(WKStringCreateWithUTF8CString("form resubmitted"));
159 case kWKFrameNavigationTypeOther:
160 return adoptWK(WKStringCreateWithUTF8CString("other"));
162 return adoptWK(WKStringCreateWithUTF8CString("illegal value"));
165 static ostream& operator<<(ostream& out, WKBundleCSSStyleDeclarationRef style)
167 // DumpRenderTree calls -[DOMCSSStyleDeclaration description], which just dumps class name and object address.
168 // No existing tests actually hit this code path at the time of this writing, because WebCore doesn't call
169 // the editing client if the styling operation source is CommandFromDOM or CommandFromDOMWithUserInterface.
170 out << "<DOMCSSStyleDeclaration ADDRESS>";
174 static ostream& operator<<(ostream& out, WKBundleFrameRef frame)
176 WKRetainPtr<WKStringRef> name(AdoptWK, WKBundleFrameCopyName(frame));
177 if (WKBundleFrameIsMainFrame(frame)) {
178 if (!WKStringIsEmpty(name.get()))
179 out << "main frame \"" << name << "\"";
183 if (!WKStringIsEmpty(name.get()))
184 out << "frame \"" << name << "\"";
186 out << "frame (anonymous)";
192 InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page)
194 , m_world(AdoptWK, WKBundleScriptWorldCreateWorld())
196 WKBundlePageLoaderClient loaderClient = {
197 kWKBundlePageLoaderClientCurrentVersion,
199 didStartProvisionalLoadForFrame,
200 didReceiveServerRedirectForProvisionalLoadForFrame,
201 didFailProvisionalLoadWithErrorForFrame,
202 didCommitLoadForFrame,
203 didFinishDocumentLoadForFrame,
204 didFinishLoadForFrame,
205 didFailLoadWithErrorForFrame,
206 didSameDocumentNavigationForFrame,
207 didReceiveTitleForFrame,
208 0, // didFirstLayoutForFrame
209 0, // didFirstVisuallyNonEmptyLayoutForFrame
210 0, // didRemoveFrameFromHierarchy
211 didDisplayInsecureContentForFrame,
212 didRunInsecureContentForFrame,
213 didClearWindowForFrame,
214 didCancelClientRedirectForFrame,
215 willPerformClientRedirectForFrame,
216 didHandleOnloadEventsForFrame,
217 0, // didLayoutForFrame
218 didDetectXSSForFrame,
220 WKBundlePageSetPageLoaderClient(m_page, &loaderClient);
222 WKBundlePageResourceLoadClient resourceLoadClient = {
223 kWKBundlePageResourceLoadClientCurrentVersion,
225 didInitiateLoadForResource,
226 willSendRequestForFrame,
227 didReceiveResponseForResource,
228 didReceiveContentLengthForResource,
229 didFinishLoadForResource,
230 didFailLoadForResource,
231 0, // shouldCacheResponse
233 WKBundlePageSetResourceLoadClient(m_page, &resourceLoadClient);
235 WKBundlePagePolicyClient policyClient = {
236 kWKBundlePagePolicyClientCurrentVersion,
238 decidePolicyForNavigationAction,
239 decidePolicyForNewWindowAction,
240 decidePolicyForResponse,
241 unableToImplementPolicy
243 WKBundlePageSetPolicyClient(m_page, &policyClient);
245 WKBundlePageUIClient uiClient = {
246 kWKBundlePageUIClientCurrentVersion,
248 willAddMessageToConsole,
249 willSetStatusbarText,
250 willRunJavaScriptAlert,
251 willRunJavaScriptConfirm,
252 willRunJavaScriptPrompt,
253 0, /*mouseDidMoveOverElement*/
255 0, /*paintCustomOverhangArea*/
256 0, /*shouldGenerateFileForUpload*/
257 0, /*generateFileForUpload*/
258 0, /*shouldRubberBandInDirection*/
259 0, /*statusBarIsVisible*/
260 0, /*menuBarIsVisible*/
261 0, /*toolbarsAreVisible*/
263 WKBundlePageSetUIClient(m_page, &uiClient);
265 WKBundlePageEditorClient editorClient = {
266 kWKBundlePageEditorClientCurrentVersion,
273 shouldChangeSelectedRange,
280 WKBundlePageSetEditorClient(m_page, &editorClient);
282 #if ENABLE(FULLSCREEN_API)
283 WKBundlePageFullScreenClient fullScreenClient = {
284 kWKBundlePageFullScreenClientCurrentVersion,
287 enterFullScreenForElement,
288 exitFullScreenForElement,
290 WKBundlePageSetFullScreenClient(m_page, &fullScreenClient);
294 InjectedBundlePage::~InjectedBundlePage()
298 void InjectedBundlePage::stopLoading()
300 WKBundlePageStopLoading(m_page);
303 void InjectedBundlePage::reset()
305 WKBundlePageClearMainFrameName(m_page);
307 WKBundlePageSetPageZoomFactor(m_page, 1);
308 WKBundlePageSetTextZoomFactor(m_page, 1);
310 WKPoint origin = { 0, 0 };
311 WKBundlePageSetScaleAtOrigin(m_page, 1, origin);
313 m_previousTestBackForwardListItem = adoptWK(WKBundleBackForwardListCopyItemAtIndex(WKBundlePageGetBackForwardList(m_page), 0));
315 WKBundleFrameClearOpener(WKBundlePageGetMainFrame(m_page));
317 WKBundlePageSetTracksRepaints(m_page, false);
320 // Loader Client Callbacks
322 void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
324 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didStartProvisionalLoadForFrame(frame);
327 void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
329 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveServerRedirectForProvisionalLoadForFrame(frame);
332 void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef*, const void *clientInfo)
334 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailProvisionalLoadWithErrorForFrame(frame, error);
337 void InjectedBundlePage::didCommitLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
339 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didCommitLoadForFrame(frame);
342 void InjectedBundlePage::didFinishLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
344 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(frame);
347 void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo)
349 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishDocumentLoadForFrame(frame);
352 void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef*, const void *clientInfo)
354 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailLoadWithErrorForFrame(frame, error);
357 void InjectedBundlePage::didReceiveTitleForFrame(WKBundlePageRef page, WKStringRef title, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
359 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveTitleForFrame(title, frame);
362 void InjectedBundlePage::didClearWindowForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleScriptWorldRef world, const void *clientInfo)
364 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didClearWindowForFrame(frame, world);
367 void InjectedBundlePage::didCancelClientRedirectForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo)
369 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didCancelClientRedirectForFrame(frame);
372 void InjectedBundlePage::willPerformClientRedirectForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKURLRef url, double delay, double date, const void* clientInfo)
374 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willPerformClientRedirectForFrame(frame, url, delay, date);
377 void InjectedBundlePage::didSameDocumentNavigationForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef*, const void* clientInfo)
379 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didSameDocumentNavigationForFrame(frame, type);
382 void InjectedBundlePage::didHandleOnloadEventsForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo)
384 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didHandleOnloadEventsForFrame(frame);
387 void InjectedBundlePage::didDisplayInsecureContentForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo)
389 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didDisplayInsecureContentForFrame(frame);
392 void InjectedBundlePage::didDetectXSSForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo)
394 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didDetectXSSForFrame(frame);
397 void InjectedBundlePage::didRunInsecureContentForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo)
399 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didRunInsecureContentForFrame(frame);
402 void InjectedBundlePage::didInitiateLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLRequestRef request, bool pageLoadIsProvisional, const void* clientInfo)
404 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didInitiateLoadForResource(page, frame, identifier, request, pageLoadIsProvisional);
407 WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLRequestRef request, WKURLResponseRef redirectResponse, const void* clientInfo)
409 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willSendRequestForFrame(page, frame, identifier, request, redirectResponse);
412 void InjectedBundlePage::didReceiveResponseForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLResponseRef response, const void* clientInfo)
414 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveResponseForResource(page, frame, identifier, response);
417 void InjectedBundlePage::didReceiveContentLengthForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, uint64_t length, const void* clientInfo)
419 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveContentLengthForResource(page, frame, identifier, length);
422 void InjectedBundlePage::didFinishLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, const void* clientInfo)
424 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForResource(page, frame, identifier);
427 void InjectedBundlePage::didFailLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKErrorRef error, const void* clientInfo)
429 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForResource(page, frame, identifier, error);
432 void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundleFrameRef frame)
434 if (!InjectedBundle::shared().isTestRunning())
437 if (InjectedBundle::shared().topLoadingFrame())
439 InjectedBundle::shared().setTopLoadingFrame(frame);
442 void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundleFrameRef frame)
446 void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef error)
448 if (!InjectedBundle::shared().isTestRunning())
451 if (frame != InjectedBundle::shared().topLoadingFrame())
453 InjectedBundle::shared().setTopLoadingFrame(0);
455 if (InjectedBundle::shared().layoutTestController()->waitToDump())
458 InjectedBundle::shared().done();
461 void InjectedBundlePage::didCommitLoadForFrame(WKBundleFrameRef frame)
465 enum FrameNamePolicy { ShouldNotIncludeFrameName, ShouldIncludeFrameName };
467 static void dumpFrameScrollPosition(WKBundleFrameRef frame, FrameNamePolicy shouldIncludeFrameName = ShouldNotIncludeFrameName)
469 double x = numericWindowPropertyValue(frame, "pageXOffset");
470 double y = numericWindowPropertyValue(frame, "pageYOffset");
471 if (fabs(x) > 0.00000001 || fabs(y) > 0.00000001) {
472 if (shouldIncludeFrameName) {
473 WKRetainPtr<WKStringRef> name(AdoptWK, WKBundleFrameCopyName(frame));
474 InjectedBundle::shared().os() << "frame '" << name << "' ";
476 InjectedBundle::shared().os() << "scrolled to " << x << "," << y << "\n";
480 static void dumpDescendantFrameScrollPositions(WKBundleFrameRef frame)
482 WKRetainPtr<WKArrayRef> childFrames(AdoptWK, WKBundleFrameCopyChildFrames(frame));
483 size_t size = WKArrayGetSize(childFrames.get());
484 for (size_t i = 0; i < size; ++i) {
485 WKBundleFrameRef subframe = static_cast<WKBundleFrameRef>(WKArrayGetItemAtIndex(childFrames.get(), i));
486 dumpFrameScrollPosition(subframe, ShouldIncludeFrameName);
487 dumpDescendantFrameScrollPositions(subframe);
491 void InjectedBundlePage::dumpAllFrameScrollPositions()
493 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
494 dumpFrameScrollPosition(frame);
495 dumpDescendantFrameScrollPositions(frame);
498 static JSRetainPtr<JSStringRef> toJS(const char* string)
500 return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString(string));
503 static bool hasDocumentElement(WKBundleFrameRef frame)
505 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
506 JSObjectRef globalObject = JSContextGetGlobalObject(context);
508 JSValueRef documentValue = JSObjectGetProperty(context, globalObject, toJS("document").get(), 0);
512 ASSERT(JSValueIsObject(context, documentValue));
513 JSObjectRef document = JSValueToObject(context, documentValue, 0);
515 JSValueRef documentElementValue = JSObjectGetProperty(context, document, toJS("documentElement").get(), 0);
516 if (!documentElementValue)
519 return JSValueToBoolean(context, documentElementValue);
522 static void dumpFrameText(WKBundleFrameRef frame)
524 // If the frame doesn't have a document element, its inner text will be an empty string, so
525 // we'll end up just appending a single newline below. But DumpRenderTree doesn't append
526 // anything in this case, so we shouldn't either.
527 if (!hasDocumentElement(frame))
530 WKRetainPtr<WKStringRef> text(AdoptWK, WKBundleFrameCopyInnerText(frame));
531 InjectedBundle::shared().os() << text << "\n";
534 static void dumpDescendantFramesText(WKBundleFrameRef frame)
536 WKRetainPtr<WKArrayRef> childFrames(AdoptWK, WKBundleFrameCopyChildFrames(frame));
537 size_t size = WKArrayGetSize(childFrames.get());
538 for (size_t i = 0; i < size; ++i) {
539 WKBundleFrameRef subframe = static_cast<WKBundleFrameRef>(WKArrayGetItemAtIndex(childFrames.get(), i));
540 WKRetainPtr<WKStringRef> subframeName(AdoptWK, WKBundleFrameCopyName(subframe));
541 InjectedBundle::shared().os() << "\n--------\nFrame: '" << subframeName << "'\n--------\n";
542 dumpFrameText(subframe);
543 dumpDescendantFramesText(subframe);
547 void InjectedBundlePage::dumpAllFramesText()
549 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
550 dumpFrameText(frame);
551 dumpDescendantFramesText(frame);
554 void InjectedBundlePage::dump()
556 ASSERT(InjectedBundle::shared().isTestRunning());
558 InjectedBundle::shared().layoutTestController()->invalidateWaitToDumpWatchdogTimer();
560 // Force a paint before dumping. This matches DumpRenderTree on Windows. (DumpRenderTree on Mac
561 // does this at a slightly different time.) See <http://webkit.org/b/55469> for details.
562 WKBundlePageForceRepaint(m_page);
564 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
565 string url = toSTD(adoptWK(WKURLCopyString(adoptWK(WKBundleFrameCopyURL(frame)).get())));
566 if (strstr(url.c_str(), "dumpAsText/"))
567 InjectedBundle::shared().layoutTestController()->dumpAsText(false);
569 switch (InjectedBundle::shared().layoutTestController()->whatToDump()) {
570 case LayoutTestController::RenderTree: {
571 WKRetainPtr<WKStringRef> text(AdoptWK, WKBundlePageCopyRenderTreeExternalRepresentation(m_page));
572 InjectedBundle::shared().os() << text;
575 case LayoutTestController::MainFrameText:
576 dumpFrameText(WKBundlePageGetMainFrame(m_page));
578 case LayoutTestController::AllFramesText:
583 if (InjectedBundle::shared().layoutTestController()->shouldDumpAllFrameScrollPositions())
584 dumpAllFrameScrollPositions();
585 else if (InjectedBundle::shared().layoutTestController()->shouldDumpMainFrameScrollPosition())
586 dumpFrameScrollPosition(WKBundlePageGetMainFrame(m_page));
588 if (InjectedBundle::shared().layoutTestController()->shouldDumpBackForwardListsForAllWindows())
589 InjectedBundle::shared().dumpBackForwardListsForAllPages();
591 if (InjectedBundle::shared().shouldDumpPixels() && InjectedBundle::shared().layoutTestController()->shouldDumpPixels()) {
592 InjectedBundle::shared().setPixelResult(adoptWK(WKBundlePageCreateSnapshotInViewCoordinates(m_page, WKBundleFrameGetVisibleContentBounds(WKBundlePageGetMainFrame(m_page)), kWKImageOptionsShareable)).get());
593 if (WKBundlePageIsTrackingRepaints(m_page))
594 InjectedBundle::shared().setRepaintRects(adoptWK(WKBundlePageCopyTrackedRepaintRects(m_page)).get());
597 InjectedBundle::shared().done();
600 void InjectedBundlePage::didFinishLoadForFrame(WKBundleFrameRef frame)
602 if (!InjectedBundle::shared().isTestRunning())
605 if (frame != InjectedBundle::shared().topLoadingFrame())
607 InjectedBundle::shared().setTopLoadingFrame(0);
609 if (InjectedBundle::shared().layoutTestController()->waitToDump())
612 InjectedBundle::shared().page()->dump();
615 void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef)
617 if (!InjectedBundle::shared().isTestRunning())
620 if (frame != InjectedBundle::shared().topLoadingFrame())
622 InjectedBundle::shared().setTopLoadingFrame(0);
624 if (InjectedBundle::shared().layoutTestController()->waitToDump())
627 InjectedBundle::shared().done();
630 void InjectedBundlePage::didReceiveTitleForFrame(WKStringRef title, WKBundleFrameRef frame)
632 if (!InjectedBundle::shared().isTestRunning())
635 if (!InjectedBundle::shared().layoutTestController()->shouldDumpTitleChanges())
638 InjectedBundle::shared().os() << "TITLE CHANGED: " << title << "\n";
641 void InjectedBundlePage::didClearWindowForFrame(WKBundleFrameRef frame, WKBundleScriptWorldRef world)
643 if (!InjectedBundle::shared().isTestRunning())
646 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world);
647 JSObjectRef window = JSContextGetGlobalObject(context);
649 if (WKBundleScriptWorldNormalWorld() != world) {
650 JSObjectSetProperty(context, window, toJS("__worldID").get(), JSValueMakeNumber(context, LayoutTestController::worldIDForWorld(world)), kJSPropertyAttributeReadOnly, 0);
654 JSValueRef exception = 0;
655 InjectedBundle::shared().layoutTestController()->makeWindowObject(context, window, &exception);
656 InjectedBundle::shared().gcController()->makeWindowObject(context, window, &exception);
657 InjectedBundle::shared().eventSendingController()->makeWindowObject(context, window, &exception);
658 InjectedBundle::shared().textInputController()->makeWindowObject(context, window, &exception);
659 InjectedBundle::shared().accessibilityController()->makeWindowObject(context, window, &exception);
662 DumpRenderTreeSupportQt::injectInternalsObject(context);
664 WebCoreTestSupport::injectInternalsObject(context);
668 void InjectedBundlePage::didCancelClientRedirectForFrame(WKBundleFrameRef frame)
672 void InjectedBundlePage::willPerformClientRedirectForFrame(WKBundleFrameRef frame, WKURLRef url, double delay, double date)
676 void InjectedBundlePage::didSameDocumentNavigationForFrame(WKBundleFrameRef frame, WKSameDocumentNavigationType type)
680 void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundleFrameRef frame)
682 if (!InjectedBundle::shared().isTestRunning())
685 unsigned pendingFrameUnloadEvents = WKBundleFrameGetPendingUnloadCount(frame);
686 if (pendingFrameUnloadEvents)
687 InjectedBundle::shared().os() << frame << " - has " << pendingFrameUnloadEvents << " onunload handler(s)\n";
690 void InjectedBundlePage::didHandleOnloadEventsForFrame(WKBundleFrameRef frame)
694 void InjectedBundlePage::didDisplayInsecureContentForFrame(WKBundleFrameRef frame)
698 void InjectedBundlePage::didRunInsecureContentForFrame(WKBundleFrameRef frame)
702 void InjectedBundlePage::didDetectXSSForFrame(WKBundleFrameRef frame)
706 void InjectedBundlePage::didInitiateLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t identifier, WKURLRequestRef, bool)
710 // Resource Load Client Callbacks
712 WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef, WKBundleFrameRef, uint64_t, WKURLRequestRef request, WKURLResponseRef)
714 if (InjectedBundle::shared().isTestRunning() && InjectedBundle::shared().layoutTestController()->willSendRequestReturnsNull())
717 WKRetainPtr<WKURLRef> url = adoptWK(WKURLRequestCopyURL(request));
718 WKRetainPtr<WKStringRef> host = adoptWK(WKURLCopyHostName(url.get()));
719 WKRetainPtr<WKStringRef> scheme = adoptWK(WKURLCopyScheme(url.get()));
720 if (host && !WKStringIsEmpty(host.get())
721 && (WKStringIsEqualToUTF8CStringIgnoringCase(scheme.get(), "http") || WKStringIsEqualToUTF8CStringIgnoringCase(scheme.get(), "https"))
722 && !WKStringIsEqualToUTF8CString(host.get(), "127.0.0.1")
723 && !WKStringIsEqualToUTF8CString(host.get(), "255.255.255.255") // Used in some tests that expect to get back an error.
724 && !WKStringIsEqualToUTF8CStringIgnoringCase(host.get(), "localhost")) {
725 InjectedBundle::shared().os() << "Blocked access to external URL " << url << "\n";
733 void InjectedBundlePage::didReceiveResponseForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t, WKURLResponseRef)
737 void InjectedBundlePage::didReceiveContentLengthForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t, uint64_t)
741 void InjectedBundlePage::didFinishLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t)
745 void InjectedBundlePage::didFailLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t, WKErrorRef)
750 // Policy Client Callbacks
752 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNavigationAction(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleNavigationActionRef navigationAction, WKURLRequestRef request, WKTypeRef* userData, const void* clientInfo)
754 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->decidePolicyForNavigationAction(page, frame, navigationAction, request, userData);
757 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNewWindowAction(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleNavigationActionRef navigationAction, WKURLRequestRef request, WKStringRef frameName, WKTypeRef* userData, const void* clientInfo)
759 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->decidePolicyForNewWindowAction(page, frame, navigationAction, request, frameName, userData);
762 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForResponse(WKBundlePageRef page, WKBundleFrameRef frame, WKURLResponseRef response, WKURLRequestRef request, WKTypeRef* userData, const void* clientInfo)
764 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->decidePolicyForResponse(page, frame, response, request, userData);
767 void InjectedBundlePage::unableToImplementPolicy(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef* userData, const void* clientInfo)
769 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->unableToImplementPolicy(page, frame, error, userData);
772 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNavigationAction(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleNavigationActionRef navigationAction, WKURLRequestRef request, WKTypeRef* userData)
774 if (!InjectedBundle::shared().isTestRunning())
775 return WKBundlePagePolicyActionUse;
777 if (!InjectedBundle::shared().layoutTestController()->isPolicyDelegateEnabled())
778 return WKBundlePagePolicyActionUse;
780 if (InjectedBundle::shared().layoutTestController()->waitToDump()) {
781 InjectedBundle::shared().os() << "Policy delegate: attempt to load " << adoptWK(WKURLRequestCopyURL(request)) << " with navigation type \'" << navigationTypeToString(WKBundleNavigationActionGetNavigationType(navigationAction)) << "\'";
782 WKBundleHitTestResultRef hitTestResultRef = WKBundleNavigationActionCopyHitTestResult(navigationAction);
783 if (hitTestResultRef)
784 InjectedBundle::shared().os() << " originating from " << dumpPath(m_page, m_world.get(), WKBundleHitTestResultCopyNodeHandle(hitTestResultRef));
786 InjectedBundle::shared().os() << "\n";
787 InjectedBundle::shared().layoutTestController()->notifyDone();
790 if (InjectedBundle::shared().layoutTestController()->isPolicyDelegatePermissive())
791 return WKBundlePagePolicyActionUse;
792 return WKBundlePagePolicyActionPassThrough;
795 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNewWindowAction(WKBundlePageRef, WKBundleFrameRef, WKBundleNavigationActionRef, WKURLRequestRef, WKStringRef, WKTypeRef*)
797 return WKBundlePagePolicyActionUse;
800 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForResponse(WKBundlePageRef, WKBundleFrameRef, WKURLResponseRef, WKURLRequestRef, WKTypeRef*)
802 return WKBundlePagePolicyActionUse;
805 void InjectedBundlePage::unableToImplementPolicy(WKBundlePageRef, WKBundleFrameRef, WKErrorRef, WKTypeRef*)
809 // UI Client Callbacks
811 void InjectedBundlePage::willAddMessageToConsole(WKBundlePageRef page, WKStringRef message, uint32_t lineNumber, const void *clientInfo)
813 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willAddMessageToConsole(message, lineNumber);
816 void InjectedBundlePage::willSetStatusbarText(WKBundlePageRef page, WKStringRef statusbarText, const void *clientInfo)
818 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willSetStatusbarText(statusbarText);
821 void InjectedBundlePage::willRunJavaScriptAlert(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo)
823 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptAlert(message, frame);
826 void InjectedBundlePage::willRunJavaScriptConfirm(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo)
828 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptConfirm(message, frame);
831 void InjectedBundlePage::willRunJavaScriptPrompt(WKBundlePageRef page, WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef frame, const void *clientInfo)
833 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptPrompt(message, defaultValue, frame);
836 static string lastFileURLPathComponent(const string& path)
838 size_t pos = path.find("file://");
839 ASSERT(string::npos != pos);
841 string tmpPath = path.substr(pos + 7);
842 if (tmpPath.length() < 2) // Keep the lone slash to avoid empty output.
845 // Remove the trailing delimiter
846 if (tmpPath[tmpPath.length() - 1] == '/')
847 tmpPath.erase(tmpPath.length() - 1);
849 pos = tmpPath.rfind('/');
850 if (string::npos != pos)
851 return tmpPath.substr(pos + 1);
856 void InjectedBundlePage::willAddMessageToConsole(WKStringRef message, uint32_t lineNumber)
858 if (!InjectedBundle::shared().isTestRunning())
861 string messageString = toSTD(message);
862 size_t fileProtocolStart = messageString.find("file://");
863 if (fileProtocolStart != string::npos)
864 // FIXME: The code below does not handle additional text after url nor multiple urls. This matches DumpRenderTree implementation.
865 messageString = messageString.substr(0, fileProtocolStart) + lastFileURLPathComponent(messageString.substr(fileProtocolStart));
867 InjectedBundle::shared().os() << "CONSOLE MESSAGE: ";
869 InjectedBundle::shared().os() << "line " << lineNumber << ": ";
870 InjectedBundle::shared().os() << messageString << "\n";
874 void InjectedBundlePage::willSetStatusbarText(WKStringRef statusbarText)
876 if (!InjectedBundle::shared().isTestRunning())
879 if (!InjectedBundle::shared().layoutTestController()->shouldDumpStatusCallbacks())
882 InjectedBundle::shared().os() << "UI DELEGATE STATUS CALLBACK: setStatusText:" << statusbarText << "\n";
885 void InjectedBundlePage::willRunJavaScriptAlert(WKStringRef message, WKBundleFrameRef)
887 if (!InjectedBundle::shared().isTestRunning())
890 InjectedBundle::shared().os() << "ALERT: " << message << "\n";
893 void InjectedBundlePage::willRunJavaScriptConfirm(WKStringRef message, WKBundleFrameRef)
895 if (!InjectedBundle::shared().isTestRunning())
898 InjectedBundle::shared().os() << "CONFIRM: " << message << "\n";
901 void InjectedBundlePage::willRunJavaScriptPrompt(WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef)
903 InjectedBundle::shared().os() << "PROMPT: " << message << ", default text: " << defaultValue << "\n";
906 // Editor Client Callbacks
908 bool InjectedBundlePage::shouldBeginEditing(WKBundlePageRef page, WKBundleRangeHandleRef range, const void* clientInfo)
910 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldBeginEditing(range);
913 bool InjectedBundlePage::shouldEndEditing(WKBundlePageRef page, WKBundleRangeHandleRef range, const void* clientInfo)
915 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldEndEditing(range);
918 bool InjectedBundlePage::shouldInsertNode(WKBundlePageRef page, WKBundleNodeHandleRef node, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action, const void* clientInfo)
920 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldInsertNode(node, rangeToReplace, action);
923 bool InjectedBundlePage::shouldInsertText(WKBundlePageRef page, WKStringRef text, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action, const void* clientInfo)
925 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldInsertText(text, rangeToReplace, action);
928 bool InjectedBundlePage::shouldDeleteRange(WKBundlePageRef page, WKBundleRangeHandleRef range, const void* clientInfo)
930 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldDeleteRange(range);
933 bool InjectedBundlePage::shouldChangeSelectedRange(WKBundlePageRef page, WKBundleRangeHandleRef fromRange, WKBundleRangeHandleRef toRange, WKAffinityType affinity, bool stillSelecting, const void* clientInfo)
935 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldChangeSelectedRange(fromRange, toRange, affinity, stillSelecting);
938 bool InjectedBundlePage::shouldApplyStyle(WKBundlePageRef page, WKBundleCSSStyleDeclarationRef style, WKBundleRangeHandleRef range, const void* clientInfo)
940 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldApplyStyle(style, range);
943 void InjectedBundlePage::didBeginEditing(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo)
945 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didBeginEditing(notificationName);
948 void InjectedBundlePage::didEndEditing(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo)
950 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didEndEditing(notificationName);
953 void InjectedBundlePage::didChange(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo)
955 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didChange(notificationName);
958 void InjectedBundlePage::didChangeSelection(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo)
960 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didChangeSelection(notificationName);
963 bool InjectedBundlePage::shouldBeginEditing(WKBundleRangeHandleRef range)
965 if (!InjectedBundle::shared().isTestRunning())
968 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
969 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldBeginEditingInDOMRange:" << toStr(m_page, m_world.get(), range) << "\n";
970 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
973 bool InjectedBundlePage::shouldEndEditing(WKBundleRangeHandleRef range)
975 if (!InjectedBundle::shared().isTestRunning())
978 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
979 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldEndEditingInDOMRange:" << toStr(m_page, m_world.get(), range) << "\n";
980 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
983 bool InjectedBundlePage::shouldInsertNode(WKBundleNodeHandleRef node, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action)
985 if (!InjectedBundle::shared().isTestRunning())
988 static const char* insertactionstring[] = {
989 "WebViewInsertActionTyped",
990 "WebViewInsertActionPasted",
991 "WebViewInsertActionDropped",
994 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
995 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";
996 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
999 bool InjectedBundlePage::shouldInsertText(WKStringRef text, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action)
1001 if (!InjectedBundle::shared().isTestRunning())
1004 static const char *insertactionstring[] = {
1005 "WebViewInsertActionTyped",
1006 "WebViewInsertActionPasted",
1007 "WebViewInsertActionDropped",
1010 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1011 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldInsertText:" << text << " replacingDOMRange:" << toStr(m_page, m_world.get(), rangeToReplace) << " givenAction:" << insertactionstring[action] << "\n";
1012 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
1015 bool InjectedBundlePage::shouldDeleteRange(WKBundleRangeHandleRef range)
1017 if (!InjectedBundle::shared().isTestRunning())
1020 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1021 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldDeleteDOMRange:" << toStr(m_page, m_world.get(), range) << "\n";
1022 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
1025 bool InjectedBundlePage::shouldChangeSelectedRange(WKBundleRangeHandleRef fromRange, WKBundleRangeHandleRef toRange, WKAffinityType affinity, bool stillSelecting)
1027 if (!InjectedBundle::shared().isTestRunning())
1030 static const char *affinitystring[] = {
1031 "NSSelectionAffinityUpstream",
1032 "NSSelectionAffinityDownstream"
1034 static const char *boolstring[] = {
1039 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1040 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";
1041 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
1044 bool InjectedBundlePage::shouldApplyStyle(WKBundleCSSStyleDeclarationRef style, WKBundleRangeHandleRef range)
1046 if (!InjectedBundle::shared().isTestRunning())
1049 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1050 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldApplyStyle:" << style << " toElementsInDOMRange:" << toStr(m_page, m_world.get(), range) << "\n";
1051 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
1054 void InjectedBundlePage::didBeginEditing(WKStringRef notificationName)
1056 if (!InjectedBundle::shared().isTestRunning())
1059 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1060 InjectedBundle::shared().os() << "EDITING DELEGATE: webViewDidBeginEditing:" << notificationName << "\n";
1063 void InjectedBundlePage::didEndEditing(WKStringRef notificationName)
1065 if (!InjectedBundle::shared().isTestRunning())
1068 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1069 InjectedBundle::shared().os() << "EDITING DELEGATE: webViewDidEndEditing:" << notificationName << "\n";
1072 void InjectedBundlePage::didChange(WKStringRef notificationName)
1074 if (!InjectedBundle::shared().isTestRunning())
1077 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1078 InjectedBundle::shared().os() << "EDITING DELEGATE: webViewDidChange:" << notificationName << "\n";
1081 void InjectedBundlePage::didChangeSelection(WKStringRef notificationName)
1083 if (!InjectedBundle::shared().isTestRunning())
1086 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1087 InjectedBundle::shared().os() << "EDITING DELEGATE: webViewDidChangeSelection:" << notificationName << "\n";
1090 #if ENABLE(FULLSCREEN_API)
1091 bool InjectedBundlePage::supportsFullScreen(WKBundlePageRef pageRef, WKFullScreenKeyboardRequestType requestType)
1093 if (InjectedBundle::shared().layoutTestController()->shouldDumpFullScreenCallbacks())
1094 InjectedBundle::shared().os() << "supportsFullScreen() == true\n";
1098 void InjectedBundlePage::enterFullScreenForElement(WKBundlePageRef pageRef, WKBundleNodeHandleRef elementRef)
1100 if (InjectedBundle::shared().layoutTestController()->shouldDumpFullScreenCallbacks())
1101 InjectedBundle::shared().os() << "enterFullScreenForElement()\n";
1102 WKBundlePageWillEnterFullScreen(pageRef);
1103 WKBundlePageDidEnterFullScreen(pageRef);
1106 void InjectedBundlePage::exitFullScreenForElement(WKBundlePageRef pageRef, WKBundleNodeHandleRef elementRef)
1108 if (InjectedBundle::shared().layoutTestController()->shouldDumpFullScreenCallbacks())
1109 InjectedBundle::shared().os() << "exitFullScreenForElement()\n";
1110 WKBundlePageWillExitFullScreen(pageRef);
1111 WKBundlePageDidExitFullScreen(pageRef);
1115 static bool compareByTargetName(WKBundleBackForwardListItemRef item1, WKBundleBackForwardListItemRef item2)
1117 return toSTD(adoptWK(WKBundleBackForwardListItemCopyTarget(item1))) < toSTD(adoptWK(WKBundleBackForwardListItemCopyTarget(item2)));
1120 static void dumpBackForwardListItem(WKBundleBackForwardListItemRef item, unsigned indent, bool isCurrentItem)
1122 unsigned column = 0;
1123 if (isCurrentItem) {
1124 InjectedBundle::shared().os() << "curr->";
1127 for (unsigned i = column; i < indent; i++)
1128 InjectedBundle::shared().os() << ' ';
1130 string url = toSTD(adoptWK(WKURLCopyString(adoptWK(WKBundleBackForwardListItemCopyURL(item)).get())));
1131 if (hasPrefix(url, "file:")) {
1132 string directoryName = "/LayoutTests/";
1133 size_t start = url.find(directoryName);
1134 if (start == string::npos)
1137 start += directoryName.size();
1138 InjectedBundle::shared().os() << "(file test):" << url.substr(start);
1140 InjectedBundle::shared().os() << url;
1142 string target = toSTD(adoptWK(WKBundleBackForwardListItemCopyTarget(item)));
1143 if (target.length())
1144 InjectedBundle::shared().os() << " (in frame \"" << target << "\")";
1146 // FIXME: Need WKBackForwardListItemIsTargetItem.
1147 if (WKBundleBackForwardListItemIsTargetItem(item))
1148 InjectedBundle::shared().os() << " **nav target**";
1150 InjectedBundle::shared().os() << '\n';
1152 if (WKRetainPtr<WKArrayRef> kids = adoptWK(WKBundleBackForwardListItemCopyChildren(item))) {
1153 // Sort to eliminate arbitrary result ordering which defeats reproducible testing.
1154 size_t size = WKArrayGetSize(kids.get());
1155 Vector<WKBundleBackForwardListItemRef> sortedKids(size);
1156 for (size_t i = 0; i < size; ++i)
1157 sortedKids[i] = static_cast<WKBundleBackForwardListItemRef>(WKArrayGetItemAtIndex(kids.get(), i));
1158 stable_sort(sortedKids.begin(), sortedKids.end(), compareByTargetName);
1159 for (size_t i = 0; i < size; ++i)
1160 dumpBackForwardListItem(sortedKids[i], indent + 4, false);
1164 void InjectedBundlePage::dumpBackForwardList()
1166 InjectedBundle::shared().os() << "\n============== Back Forward List ==============\n";
1168 WKBundleBackForwardListRef list = WKBundlePageGetBackForwardList(m_page);
1170 // Print out all items in the list after m_previousTestBackForwardListItem.
1171 // Gather items from the end of the list, then print them out from oldest to newest.
1172 Vector<WKRetainPtr<WKBundleBackForwardListItemRef> > itemsToPrint;
1173 for (unsigned i = WKBundleBackForwardListGetForwardListCount(list); i; --i) {
1174 WKRetainPtr<WKBundleBackForwardListItemRef> item = adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, i));
1175 // Something is wrong if the item from the last test is in the forward part of the list.
1176 ASSERT(!WKBundleBackForwardListItemIsSame(item.get(), m_previousTestBackForwardListItem.get()));
1177 itemsToPrint.append(item);
1180 ASSERT(!WKBundleBackForwardListItemIsSame(adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, 0)).get(), m_previousTestBackForwardListItem.get()));
1182 itemsToPrint.append(adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, 0)));
1184 int currentItemIndex = itemsToPrint.size() - 1;
1186 int backListCount = WKBundleBackForwardListGetBackListCount(list);
1187 for (int i = -1; i >= -backListCount; --i) {
1188 WKRetainPtr<WKBundleBackForwardListItemRef> item = adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, i));
1189 if (WKBundleBackForwardListItemIsSame(item.get(), m_previousTestBackForwardListItem.get()))
1191 itemsToPrint.append(item);
1194 for (int i = itemsToPrint.size() - 1; i >= 0; i--)
1195 dumpBackForwardListItem(itemsToPrint[i].get(), 8, i == currentItemIndex);
1197 InjectedBundle::shared().os() << "===============================================\n";