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
232 0 // shouldUseCredentialStorage
234 WKBundlePageSetResourceLoadClient(m_page, &resourceLoadClient);
236 WKBundlePagePolicyClient policyClient = {
237 kWKBundlePagePolicyClientCurrentVersion,
239 decidePolicyForNavigationAction,
240 decidePolicyForNewWindowAction,
241 decidePolicyForResponse,
242 unableToImplementPolicy
244 WKBundlePageSetPolicyClient(m_page, &policyClient);
246 WKBundlePageUIClient uiClient = {
247 kWKBundlePageUIClientCurrentVersion,
249 willAddMessageToConsole,
250 willSetStatusbarText,
251 willRunJavaScriptAlert,
252 willRunJavaScriptConfirm,
253 willRunJavaScriptPrompt,
254 0, /*mouseDidMoveOverElement*/
256 0, /*paintCustomOverhangArea*/
257 0, /*shouldGenerateFileForUpload*/
258 0, /*generateFileForUpload*/
259 0, /*shouldRubberBandInDirection*/
260 0, /*statusBarIsVisible*/
261 0, /*menuBarIsVisible*/
262 0, /*toolbarsAreVisible*/
264 WKBundlePageSetUIClient(m_page, &uiClient);
266 WKBundlePageEditorClient editorClient = {
267 kWKBundlePageEditorClientCurrentVersion,
274 shouldChangeSelectedRange,
281 WKBundlePageSetEditorClient(m_page, &editorClient);
283 #if ENABLE(FULLSCREEN_API)
284 WKBundlePageFullScreenClient fullScreenClient = {
285 kWKBundlePageFullScreenClientCurrentVersion,
288 enterFullScreenForElement,
289 exitFullScreenForElement,
291 WKBundlePageSetFullScreenClient(m_page, &fullScreenClient);
295 InjectedBundlePage::~InjectedBundlePage()
299 void InjectedBundlePage::stopLoading()
301 WKBundlePageStopLoading(m_page);
304 void InjectedBundlePage::reset()
306 WKBundlePageClearMainFrameName(m_page);
308 WKBundlePageSetPageZoomFactor(m_page, 1);
309 WKBundlePageSetTextZoomFactor(m_page, 1);
311 WKPoint origin = { 0, 0 };
312 WKBundlePageSetScaleAtOrigin(m_page, 1, origin);
314 m_previousTestBackForwardListItem = adoptWK(WKBundleBackForwardListCopyItemAtIndex(WKBundlePageGetBackForwardList(m_page), 0));
316 WKBundleFrameClearOpener(WKBundlePageGetMainFrame(m_page));
318 WKBundlePageSetTracksRepaints(m_page, false);
321 // Loader Client Callbacks
323 void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
325 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didStartProvisionalLoadForFrame(frame);
328 void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
330 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveServerRedirectForProvisionalLoadForFrame(frame);
333 void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef*, const void *clientInfo)
335 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailProvisionalLoadWithErrorForFrame(frame, error);
338 void InjectedBundlePage::didCommitLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
340 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didCommitLoadForFrame(frame);
343 void InjectedBundlePage::didFinishLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
345 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(frame);
348 void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo)
350 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishDocumentLoadForFrame(frame);
353 void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef*, const void *clientInfo)
355 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailLoadWithErrorForFrame(frame, error);
358 void InjectedBundlePage::didReceiveTitleForFrame(WKBundlePageRef page, WKStringRef title, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
360 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveTitleForFrame(title, frame);
363 void InjectedBundlePage::didClearWindowForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleScriptWorldRef world, const void *clientInfo)
365 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didClearWindowForFrame(frame, world);
368 void InjectedBundlePage::didCancelClientRedirectForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo)
370 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didCancelClientRedirectForFrame(frame);
373 void InjectedBundlePage::willPerformClientRedirectForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKURLRef url, double delay, double date, const void* clientInfo)
375 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willPerformClientRedirectForFrame(frame, url, delay, date);
378 void InjectedBundlePage::didSameDocumentNavigationForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef*, const void* clientInfo)
380 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didSameDocumentNavigationForFrame(frame, type);
383 void InjectedBundlePage::didHandleOnloadEventsForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo)
385 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didHandleOnloadEventsForFrame(frame);
388 void InjectedBundlePage::didDisplayInsecureContentForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo)
390 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didDisplayInsecureContentForFrame(frame);
393 void InjectedBundlePage::didDetectXSSForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo)
395 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didDetectXSSForFrame(frame);
398 void InjectedBundlePage::didRunInsecureContentForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo)
400 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didRunInsecureContentForFrame(frame);
403 void InjectedBundlePage::didInitiateLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLRequestRef request, bool pageLoadIsProvisional, const void* clientInfo)
405 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didInitiateLoadForResource(page, frame, identifier, request, pageLoadIsProvisional);
408 WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLRequestRef request, WKURLResponseRef redirectResponse, const void* clientInfo)
410 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willSendRequestForFrame(page, frame, identifier, request, redirectResponse);
413 void InjectedBundlePage::didReceiveResponseForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLResponseRef response, const void* clientInfo)
415 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveResponseForResource(page, frame, identifier, response);
418 void InjectedBundlePage::didReceiveContentLengthForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, uint64_t length, const void* clientInfo)
420 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveContentLengthForResource(page, frame, identifier, length);
423 void InjectedBundlePage::didFinishLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, const void* clientInfo)
425 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForResource(page, frame, identifier);
428 void InjectedBundlePage::didFailLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKErrorRef error, const void* clientInfo)
430 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForResource(page, frame, identifier, error);
433 void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundleFrameRef frame)
435 if (!InjectedBundle::shared().isTestRunning())
438 if (InjectedBundle::shared().topLoadingFrame())
440 InjectedBundle::shared().setTopLoadingFrame(frame);
443 void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundleFrameRef frame)
447 void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef error)
449 if (!InjectedBundle::shared().isTestRunning())
452 if (frame != InjectedBundle::shared().topLoadingFrame())
454 InjectedBundle::shared().setTopLoadingFrame(0);
456 if (InjectedBundle::shared().layoutTestController()->waitToDump())
459 InjectedBundle::shared().done();
462 void InjectedBundlePage::didCommitLoadForFrame(WKBundleFrameRef frame)
466 enum FrameNamePolicy { ShouldNotIncludeFrameName, ShouldIncludeFrameName };
468 static void dumpFrameScrollPosition(WKBundleFrameRef frame, FrameNamePolicy shouldIncludeFrameName = ShouldNotIncludeFrameName)
470 double x = numericWindowPropertyValue(frame, "pageXOffset");
471 double y = numericWindowPropertyValue(frame, "pageYOffset");
472 if (fabs(x) > 0.00000001 || fabs(y) > 0.00000001) {
473 if (shouldIncludeFrameName) {
474 WKRetainPtr<WKStringRef> name(AdoptWK, WKBundleFrameCopyName(frame));
475 InjectedBundle::shared().os() << "frame '" << name << "' ";
477 InjectedBundle::shared().os() << "scrolled to " << x << "," << y << "\n";
481 static void dumpDescendantFrameScrollPositions(WKBundleFrameRef frame)
483 WKRetainPtr<WKArrayRef> childFrames(AdoptWK, WKBundleFrameCopyChildFrames(frame));
484 size_t size = WKArrayGetSize(childFrames.get());
485 for (size_t i = 0; i < size; ++i) {
486 WKBundleFrameRef subframe = static_cast<WKBundleFrameRef>(WKArrayGetItemAtIndex(childFrames.get(), i));
487 dumpFrameScrollPosition(subframe, ShouldIncludeFrameName);
488 dumpDescendantFrameScrollPositions(subframe);
492 void InjectedBundlePage::dumpAllFrameScrollPositions()
494 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
495 dumpFrameScrollPosition(frame);
496 dumpDescendantFrameScrollPositions(frame);
499 static JSRetainPtr<JSStringRef> toJS(const char* string)
501 return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString(string));
504 static bool hasDocumentElement(WKBundleFrameRef frame)
506 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
507 JSObjectRef globalObject = JSContextGetGlobalObject(context);
509 JSValueRef documentValue = JSObjectGetProperty(context, globalObject, toJS("document").get(), 0);
513 ASSERT(JSValueIsObject(context, documentValue));
514 JSObjectRef document = JSValueToObject(context, documentValue, 0);
516 JSValueRef documentElementValue = JSObjectGetProperty(context, document, toJS("documentElement").get(), 0);
517 if (!documentElementValue)
520 return JSValueToBoolean(context, documentElementValue);
523 static void dumpFrameText(WKBundleFrameRef frame)
525 // If the frame doesn't have a document element, its inner text will be an empty string, so
526 // we'll end up just appending a single newline below. But DumpRenderTree doesn't append
527 // anything in this case, so we shouldn't either.
528 if (!hasDocumentElement(frame))
531 WKRetainPtr<WKStringRef> text(AdoptWK, WKBundleFrameCopyInnerText(frame));
532 InjectedBundle::shared().os() << text << "\n";
535 static void dumpDescendantFramesText(WKBundleFrameRef frame)
537 WKRetainPtr<WKArrayRef> childFrames(AdoptWK, WKBundleFrameCopyChildFrames(frame));
538 size_t size = WKArrayGetSize(childFrames.get());
539 for (size_t i = 0; i < size; ++i) {
540 WKBundleFrameRef subframe = static_cast<WKBundleFrameRef>(WKArrayGetItemAtIndex(childFrames.get(), i));
541 WKRetainPtr<WKStringRef> subframeName(AdoptWK, WKBundleFrameCopyName(subframe));
542 InjectedBundle::shared().os() << "\n--------\nFrame: '" << subframeName << "'\n--------\n";
543 dumpFrameText(subframe);
544 dumpDescendantFramesText(subframe);
548 void InjectedBundlePage::dumpAllFramesText()
550 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
551 dumpFrameText(frame);
552 dumpDescendantFramesText(frame);
555 void InjectedBundlePage::dump()
557 ASSERT(InjectedBundle::shared().isTestRunning());
559 InjectedBundle::shared().layoutTestController()->invalidateWaitToDumpWatchdogTimer();
561 // Force a paint before dumping. This matches DumpRenderTree on Windows. (DumpRenderTree on Mac
562 // does this at a slightly different time.) See <http://webkit.org/b/55469> for details.
563 WKBundlePageForceRepaint(m_page);
565 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
566 string url = toSTD(adoptWK(WKURLCopyString(adoptWK(WKBundleFrameCopyURL(frame)).get())));
567 if (strstr(url.c_str(), "dumpAsText/"))
568 InjectedBundle::shared().layoutTestController()->dumpAsText(false);
570 switch (InjectedBundle::shared().layoutTestController()->whatToDump()) {
571 case LayoutTestController::RenderTree: {
572 WKRetainPtr<WKStringRef> text(AdoptWK, WKBundlePageCopyRenderTreeExternalRepresentation(m_page));
573 InjectedBundle::shared().os() << text;
576 case LayoutTestController::MainFrameText:
577 dumpFrameText(WKBundlePageGetMainFrame(m_page));
579 case LayoutTestController::AllFramesText:
584 if (InjectedBundle::shared().layoutTestController()->shouldDumpAllFrameScrollPositions())
585 dumpAllFrameScrollPositions();
586 else if (InjectedBundle::shared().layoutTestController()->shouldDumpMainFrameScrollPosition())
587 dumpFrameScrollPosition(WKBundlePageGetMainFrame(m_page));
589 if (InjectedBundle::shared().layoutTestController()->shouldDumpBackForwardListsForAllWindows())
590 InjectedBundle::shared().dumpBackForwardListsForAllPages();
592 if (InjectedBundle::shared().shouldDumpPixels() && InjectedBundle::shared().layoutTestController()->shouldDumpPixels()) {
593 InjectedBundle::shared().setPixelResult(adoptWK(WKBundlePageCreateSnapshotInViewCoordinates(m_page, WKBundleFrameGetVisibleContentBounds(WKBundlePageGetMainFrame(m_page)), kWKImageOptionsShareable)).get());
594 if (WKBundlePageIsTrackingRepaints(m_page))
595 InjectedBundle::shared().setRepaintRects(adoptWK(WKBundlePageCopyTrackedRepaintRects(m_page)).get());
598 InjectedBundle::shared().done();
601 void InjectedBundlePage::didFinishLoadForFrame(WKBundleFrameRef frame)
603 if (!InjectedBundle::shared().isTestRunning())
606 if (frame != InjectedBundle::shared().topLoadingFrame())
608 InjectedBundle::shared().setTopLoadingFrame(0);
610 if (InjectedBundle::shared().layoutTestController()->waitToDump())
613 InjectedBundle::shared().page()->dump();
616 void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef)
618 if (!InjectedBundle::shared().isTestRunning())
621 if (frame != InjectedBundle::shared().topLoadingFrame())
623 InjectedBundle::shared().setTopLoadingFrame(0);
625 if (InjectedBundle::shared().layoutTestController()->waitToDump())
628 InjectedBundle::shared().done();
631 void InjectedBundlePage::didReceiveTitleForFrame(WKStringRef title, WKBundleFrameRef frame)
633 if (!InjectedBundle::shared().isTestRunning())
636 if (!InjectedBundle::shared().layoutTestController()->shouldDumpTitleChanges())
639 InjectedBundle::shared().os() << "TITLE CHANGED: " << title << "\n";
642 void InjectedBundlePage::didClearWindowForFrame(WKBundleFrameRef frame, WKBundleScriptWorldRef world)
644 if (!InjectedBundle::shared().isTestRunning())
647 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world);
648 JSObjectRef window = JSContextGetGlobalObject(context);
650 if (WKBundleScriptWorldNormalWorld() != world) {
651 JSObjectSetProperty(context, window, toJS("__worldID").get(), JSValueMakeNumber(context, LayoutTestController::worldIDForWorld(world)), kJSPropertyAttributeReadOnly, 0);
655 JSValueRef exception = 0;
656 InjectedBundle::shared().layoutTestController()->makeWindowObject(context, window, &exception);
657 InjectedBundle::shared().gcController()->makeWindowObject(context, window, &exception);
658 InjectedBundle::shared().eventSendingController()->makeWindowObject(context, window, &exception);
659 InjectedBundle::shared().textInputController()->makeWindowObject(context, window, &exception);
660 InjectedBundle::shared().accessibilityController()->makeWindowObject(context, window, &exception);
663 DumpRenderTreeSupportQt::injectInternalsObject(context);
665 WebCoreTestSupport::injectInternalsObject(context);
669 void InjectedBundlePage::didCancelClientRedirectForFrame(WKBundleFrameRef frame)
673 void InjectedBundlePage::willPerformClientRedirectForFrame(WKBundleFrameRef frame, WKURLRef url, double delay, double date)
677 void InjectedBundlePage::didSameDocumentNavigationForFrame(WKBundleFrameRef frame, WKSameDocumentNavigationType type)
681 void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundleFrameRef frame)
683 if (!InjectedBundle::shared().isTestRunning())
686 unsigned pendingFrameUnloadEvents = WKBundleFrameGetPendingUnloadCount(frame);
687 if (pendingFrameUnloadEvents)
688 InjectedBundle::shared().os() << frame << " - has " << pendingFrameUnloadEvents << " onunload handler(s)\n";
691 void InjectedBundlePage::didHandleOnloadEventsForFrame(WKBundleFrameRef frame)
695 void InjectedBundlePage::didDisplayInsecureContentForFrame(WKBundleFrameRef frame)
699 void InjectedBundlePage::didRunInsecureContentForFrame(WKBundleFrameRef frame)
703 void InjectedBundlePage::didDetectXSSForFrame(WKBundleFrameRef frame)
707 void InjectedBundlePage::didInitiateLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t identifier, WKURLRequestRef, bool)
711 // Resource Load Client Callbacks
713 WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef, WKBundleFrameRef, uint64_t, WKURLRequestRef request, WKURLResponseRef)
715 if (InjectedBundle::shared().isTestRunning() && InjectedBundle::shared().layoutTestController()->willSendRequestReturnsNull())
718 WKRetainPtr<WKURLRef> url = adoptWK(WKURLRequestCopyURL(request));
719 WKRetainPtr<WKStringRef> host = adoptWK(WKURLCopyHostName(url.get()));
720 WKRetainPtr<WKStringRef> scheme = adoptWK(WKURLCopyScheme(url.get()));
721 if (host && !WKStringIsEmpty(host.get())
722 && (WKStringIsEqualToUTF8CStringIgnoringCase(scheme.get(), "http") || WKStringIsEqualToUTF8CStringIgnoringCase(scheme.get(), "https"))
723 && !WKStringIsEqualToUTF8CString(host.get(), "127.0.0.1")
724 && !WKStringIsEqualToUTF8CString(host.get(), "255.255.255.255") // Used in some tests that expect to get back an error.
725 && !WKStringIsEqualToUTF8CStringIgnoringCase(host.get(), "localhost")) {
726 InjectedBundle::shared().os() << "Blocked access to external URL " << url << "\n";
734 void InjectedBundlePage::didReceiveResponseForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t, WKURLResponseRef)
738 void InjectedBundlePage::didReceiveContentLengthForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t, uint64_t)
742 void InjectedBundlePage::didFinishLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t)
746 void InjectedBundlePage::didFailLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t, WKErrorRef)
751 // Policy Client Callbacks
753 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNavigationAction(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleNavigationActionRef navigationAction, WKURLRequestRef request, WKTypeRef* userData, const void* clientInfo)
755 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->decidePolicyForNavigationAction(page, frame, navigationAction, request, userData);
758 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNewWindowAction(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleNavigationActionRef navigationAction, WKURLRequestRef request, WKStringRef frameName, WKTypeRef* userData, const void* clientInfo)
760 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->decidePolicyForNewWindowAction(page, frame, navigationAction, request, frameName, userData);
763 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForResponse(WKBundlePageRef page, WKBundleFrameRef frame, WKURLResponseRef response, WKURLRequestRef request, WKTypeRef* userData, const void* clientInfo)
765 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->decidePolicyForResponse(page, frame, response, request, userData);
768 void InjectedBundlePage::unableToImplementPolicy(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef* userData, const void* clientInfo)
770 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->unableToImplementPolicy(page, frame, error, userData);
773 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNavigationAction(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleNavigationActionRef navigationAction, WKURLRequestRef request, WKTypeRef* userData)
775 if (!InjectedBundle::shared().isTestRunning())
776 return WKBundlePagePolicyActionUse;
778 if (!InjectedBundle::shared().layoutTestController()->isPolicyDelegateEnabled())
779 return WKBundlePagePolicyActionUse;
781 if (InjectedBundle::shared().layoutTestController()->waitToDump()) {
782 InjectedBundle::shared().os() << "Policy delegate: attempt to load " << adoptWK(WKURLRequestCopyURL(request)) << " with navigation type \'" << navigationTypeToString(WKBundleNavigationActionGetNavigationType(navigationAction)) << "\'";
783 WKBundleHitTestResultRef hitTestResultRef = WKBundleNavigationActionCopyHitTestResult(navigationAction);
784 if (hitTestResultRef)
785 InjectedBundle::shared().os() << " originating from " << dumpPath(m_page, m_world.get(), WKBundleHitTestResultCopyNodeHandle(hitTestResultRef));
787 InjectedBundle::shared().os() << "\n";
788 InjectedBundle::shared().layoutTestController()->notifyDone();
791 if (InjectedBundle::shared().layoutTestController()->isPolicyDelegatePermissive())
792 return WKBundlePagePolicyActionUse;
793 return WKBundlePagePolicyActionPassThrough;
796 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNewWindowAction(WKBundlePageRef, WKBundleFrameRef, WKBundleNavigationActionRef, WKURLRequestRef, WKStringRef, WKTypeRef*)
798 return WKBundlePagePolicyActionUse;
801 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForResponse(WKBundlePageRef, WKBundleFrameRef, WKURLResponseRef, WKURLRequestRef, WKTypeRef*)
803 return WKBundlePagePolicyActionUse;
806 void InjectedBundlePage::unableToImplementPolicy(WKBundlePageRef, WKBundleFrameRef, WKErrorRef, WKTypeRef*)
810 // UI Client Callbacks
812 void InjectedBundlePage::willAddMessageToConsole(WKBundlePageRef page, WKStringRef message, uint32_t lineNumber, const void *clientInfo)
814 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willAddMessageToConsole(message, lineNumber);
817 void InjectedBundlePage::willSetStatusbarText(WKBundlePageRef page, WKStringRef statusbarText, const void *clientInfo)
819 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willSetStatusbarText(statusbarText);
822 void InjectedBundlePage::willRunJavaScriptAlert(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo)
824 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptAlert(message, frame);
827 void InjectedBundlePage::willRunJavaScriptConfirm(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo)
829 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptConfirm(message, frame);
832 void InjectedBundlePage::willRunJavaScriptPrompt(WKBundlePageRef page, WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef frame, const void *clientInfo)
834 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptPrompt(message, defaultValue, frame);
837 static string lastFileURLPathComponent(const string& path)
839 size_t pos = path.find("file://");
840 ASSERT(string::npos != pos);
842 string tmpPath = path.substr(pos + 7);
843 if (tmpPath.length() < 2) // Keep the lone slash to avoid empty output.
846 // Remove the trailing delimiter
847 if (tmpPath[tmpPath.length() - 1] == '/')
848 tmpPath.erase(tmpPath.length() - 1);
850 pos = tmpPath.rfind('/');
851 if (string::npos != pos)
852 return tmpPath.substr(pos + 1);
857 void InjectedBundlePage::willAddMessageToConsole(WKStringRef message, uint32_t lineNumber)
859 if (!InjectedBundle::shared().isTestRunning())
862 string messageString = toSTD(message);
863 size_t fileProtocolStart = messageString.find("file://");
864 if (fileProtocolStart != string::npos)
865 // FIXME: The code below does not handle additional text after url nor multiple urls. This matches DumpRenderTree implementation.
866 messageString = messageString.substr(0, fileProtocolStart) + lastFileURLPathComponent(messageString.substr(fileProtocolStart));
868 InjectedBundle::shared().os() << "CONSOLE MESSAGE: ";
870 InjectedBundle::shared().os() << "line " << lineNumber << ": ";
871 InjectedBundle::shared().os() << messageString << "\n";
875 void InjectedBundlePage::willSetStatusbarText(WKStringRef statusbarText)
877 if (!InjectedBundle::shared().isTestRunning())
880 if (!InjectedBundle::shared().layoutTestController()->shouldDumpStatusCallbacks())
883 InjectedBundle::shared().os() << "UI DELEGATE STATUS CALLBACK: setStatusText:" << statusbarText << "\n";
886 void InjectedBundlePage::willRunJavaScriptAlert(WKStringRef message, WKBundleFrameRef)
888 if (!InjectedBundle::shared().isTestRunning())
891 InjectedBundle::shared().os() << "ALERT: " << message << "\n";
894 void InjectedBundlePage::willRunJavaScriptConfirm(WKStringRef message, WKBundleFrameRef)
896 if (!InjectedBundle::shared().isTestRunning())
899 InjectedBundle::shared().os() << "CONFIRM: " << message << "\n";
902 void InjectedBundlePage::willRunJavaScriptPrompt(WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef)
904 InjectedBundle::shared().os() << "PROMPT: " << message << ", default text: " << defaultValue << "\n";
907 // Editor Client Callbacks
909 bool InjectedBundlePage::shouldBeginEditing(WKBundlePageRef page, WKBundleRangeHandleRef range, const void* clientInfo)
911 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldBeginEditing(range);
914 bool InjectedBundlePage::shouldEndEditing(WKBundlePageRef page, WKBundleRangeHandleRef range, const void* clientInfo)
916 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldEndEditing(range);
919 bool InjectedBundlePage::shouldInsertNode(WKBundlePageRef page, WKBundleNodeHandleRef node, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action, const void* clientInfo)
921 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldInsertNode(node, rangeToReplace, action);
924 bool InjectedBundlePage::shouldInsertText(WKBundlePageRef page, WKStringRef text, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action, const void* clientInfo)
926 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldInsertText(text, rangeToReplace, action);
929 bool InjectedBundlePage::shouldDeleteRange(WKBundlePageRef page, WKBundleRangeHandleRef range, const void* clientInfo)
931 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldDeleteRange(range);
934 bool InjectedBundlePage::shouldChangeSelectedRange(WKBundlePageRef page, WKBundleRangeHandleRef fromRange, WKBundleRangeHandleRef toRange, WKAffinityType affinity, bool stillSelecting, const void* clientInfo)
936 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldChangeSelectedRange(fromRange, toRange, affinity, stillSelecting);
939 bool InjectedBundlePage::shouldApplyStyle(WKBundlePageRef page, WKBundleCSSStyleDeclarationRef style, WKBundleRangeHandleRef range, const void* clientInfo)
941 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldApplyStyle(style, range);
944 void InjectedBundlePage::didBeginEditing(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo)
946 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didBeginEditing(notificationName);
949 void InjectedBundlePage::didEndEditing(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo)
951 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didEndEditing(notificationName);
954 void InjectedBundlePage::didChange(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo)
956 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didChange(notificationName);
959 void InjectedBundlePage::didChangeSelection(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo)
961 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didChangeSelection(notificationName);
964 bool InjectedBundlePage::shouldBeginEditing(WKBundleRangeHandleRef range)
966 if (!InjectedBundle::shared().isTestRunning())
969 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
970 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldBeginEditingInDOMRange:" << toStr(m_page, m_world.get(), range) << "\n";
971 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
974 bool InjectedBundlePage::shouldEndEditing(WKBundleRangeHandleRef range)
976 if (!InjectedBundle::shared().isTestRunning())
979 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
980 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldEndEditingInDOMRange:" << toStr(m_page, m_world.get(), range) << "\n";
981 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
984 bool InjectedBundlePage::shouldInsertNode(WKBundleNodeHandleRef node, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action)
986 if (!InjectedBundle::shared().isTestRunning())
989 static const char* insertactionstring[] = {
990 "WebViewInsertActionTyped",
991 "WebViewInsertActionPasted",
992 "WebViewInsertActionDropped",
995 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
996 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";
997 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
1000 bool InjectedBundlePage::shouldInsertText(WKStringRef text, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action)
1002 if (!InjectedBundle::shared().isTestRunning())
1005 static const char *insertactionstring[] = {
1006 "WebViewInsertActionTyped",
1007 "WebViewInsertActionPasted",
1008 "WebViewInsertActionDropped",
1011 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1012 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldInsertText:" << text << " replacingDOMRange:" << toStr(m_page, m_world.get(), rangeToReplace) << " givenAction:" << insertactionstring[action] << "\n";
1013 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
1016 bool InjectedBundlePage::shouldDeleteRange(WKBundleRangeHandleRef range)
1018 if (!InjectedBundle::shared().isTestRunning())
1021 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1022 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldDeleteDOMRange:" << toStr(m_page, m_world.get(), range) << "\n";
1023 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
1026 bool InjectedBundlePage::shouldChangeSelectedRange(WKBundleRangeHandleRef fromRange, WKBundleRangeHandleRef toRange, WKAffinityType affinity, bool stillSelecting)
1028 if (!InjectedBundle::shared().isTestRunning())
1031 static const char *affinitystring[] = {
1032 "NSSelectionAffinityUpstream",
1033 "NSSelectionAffinityDownstream"
1035 static const char *boolstring[] = {
1040 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1041 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";
1042 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
1045 bool InjectedBundlePage::shouldApplyStyle(WKBundleCSSStyleDeclarationRef style, WKBundleRangeHandleRef range)
1047 if (!InjectedBundle::shared().isTestRunning())
1050 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1051 InjectedBundle::shared().os() << "EDITING DELEGATE: shouldApplyStyle:" << style << " toElementsInDOMRange:" << toStr(m_page, m_world.get(), range) << "\n";
1052 return InjectedBundle::shared().layoutTestController()->shouldAllowEditing();
1055 void InjectedBundlePage::didBeginEditing(WKStringRef notificationName)
1057 if (!InjectedBundle::shared().isTestRunning())
1060 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1061 InjectedBundle::shared().os() << "EDITING DELEGATE: webViewDidBeginEditing:" << notificationName << "\n";
1064 void InjectedBundlePage::didEndEditing(WKStringRef notificationName)
1066 if (!InjectedBundle::shared().isTestRunning())
1069 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1070 InjectedBundle::shared().os() << "EDITING DELEGATE: webViewDidEndEditing:" << notificationName << "\n";
1073 void InjectedBundlePage::didChange(WKStringRef notificationName)
1075 if (!InjectedBundle::shared().isTestRunning())
1078 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1079 InjectedBundle::shared().os() << "EDITING DELEGATE: webViewDidChange:" << notificationName << "\n";
1082 void InjectedBundlePage::didChangeSelection(WKStringRef notificationName)
1084 if (!InjectedBundle::shared().isTestRunning())
1087 if (InjectedBundle::shared().layoutTestController()->shouldDumpEditingCallbacks())
1088 InjectedBundle::shared().os() << "EDITING DELEGATE: webViewDidChangeSelection:" << notificationName << "\n";
1091 #if ENABLE(FULLSCREEN_API)
1092 bool InjectedBundlePage::supportsFullScreen(WKBundlePageRef pageRef, WKFullScreenKeyboardRequestType requestType)
1094 if (InjectedBundle::shared().layoutTestController()->shouldDumpFullScreenCallbacks())
1095 InjectedBundle::shared().os() << "supportsFullScreen() == true\n";
1099 void InjectedBundlePage::enterFullScreenForElement(WKBundlePageRef pageRef, WKBundleNodeHandleRef elementRef)
1101 if (InjectedBundle::shared().layoutTestController()->shouldDumpFullScreenCallbacks())
1102 InjectedBundle::shared().os() << "enterFullScreenForElement()\n";
1103 WKBundlePageWillEnterFullScreen(pageRef);
1104 WKBundlePageDidEnterFullScreen(pageRef);
1107 void InjectedBundlePage::exitFullScreenForElement(WKBundlePageRef pageRef, WKBundleNodeHandleRef elementRef)
1109 if (InjectedBundle::shared().layoutTestController()->shouldDumpFullScreenCallbacks())
1110 InjectedBundle::shared().os() << "exitFullScreenForElement()\n";
1111 WKBundlePageWillExitFullScreen(pageRef);
1112 WKBundlePageDidExitFullScreen(pageRef);
1116 static bool compareByTargetName(WKBundleBackForwardListItemRef item1, WKBundleBackForwardListItemRef item2)
1118 return toSTD(adoptWK(WKBundleBackForwardListItemCopyTarget(item1))) < toSTD(adoptWK(WKBundleBackForwardListItemCopyTarget(item2)));
1121 static void dumpBackForwardListItem(WKBundleBackForwardListItemRef item, unsigned indent, bool isCurrentItem)
1123 unsigned column = 0;
1124 if (isCurrentItem) {
1125 InjectedBundle::shared().os() << "curr->";
1128 for (unsigned i = column; i < indent; i++)
1129 InjectedBundle::shared().os() << ' ';
1131 string url = toSTD(adoptWK(WKURLCopyString(adoptWK(WKBundleBackForwardListItemCopyURL(item)).get())));
1132 if (hasPrefix(url, "file:")) {
1133 string directoryName = "/LayoutTests/";
1134 size_t start = url.find(directoryName);
1135 if (start == string::npos)
1138 start += directoryName.size();
1139 InjectedBundle::shared().os() << "(file test):" << url.substr(start);
1141 InjectedBundle::shared().os() << url;
1143 string target = toSTD(adoptWK(WKBundleBackForwardListItemCopyTarget(item)));
1144 if (target.length())
1145 InjectedBundle::shared().os() << " (in frame \"" << target << "\")";
1147 // FIXME: Need WKBackForwardListItemIsTargetItem.
1148 if (WKBundleBackForwardListItemIsTargetItem(item))
1149 InjectedBundle::shared().os() << " **nav target**";
1151 InjectedBundle::shared().os() << '\n';
1153 if (WKRetainPtr<WKArrayRef> kids = adoptWK(WKBundleBackForwardListItemCopyChildren(item))) {
1154 // Sort to eliminate arbitrary result ordering which defeats reproducible testing.
1155 size_t size = WKArrayGetSize(kids.get());
1156 Vector<WKBundleBackForwardListItemRef> sortedKids(size);
1157 for (size_t i = 0; i < size; ++i)
1158 sortedKids[i] = static_cast<WKBundleBackForwardListItemRef>(WKArrayGetItemAtIndex(kids.get(), i));
1159 stable_sort(sortedKids.begin(), sortedKids.end(), compareByTargetName);
1160 for (size_t i = 0; i < size; ++i)
1161 dumpBackForwardListItem(sortedKids[i], indent + 4, false);
1165 void InjectedBundlePage::dumpBackForwardList()
1167 InjectedBundle::shared().os() << "\n============== Back Forward List ==============\n";
1169 WKBundleBackForwardListRef list = WKBundlePageGetBackForwardList(m_page);
1171 // Print out all items in the list after m_previousTestBackForwardListItem.
1172 // Gather items from the end of the list, then print them out from oldest to newest.
1173 Vector<WKRetainPtr<WKBundleBackForwardListItemRef> > itemsToPrint;
1174 for (unsigned i = WKBundleBackForwardListGetForwardListCount(list); i; --i) {
1175 WKRetainPtr<WKBundleBackForwardListItemRef> item = adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, i));
1176 // Something is wrong if the item from the last test is in the forward part of the list.
1177 ASSERT(!WKBundleBackForwardListItemIsSame(item.get(), m_previousTestBackForwardListItem.get()));
1178 itemsToPrint.append(item);
1181 ASSERT(!WKBundleBackForwardListItemIsSame(adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, 0)).get(), m_previousTestBackForwardListItem.get()));
1183 itemsToPrint.append(adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, 0)));
1185 int currentItemIndex = itemsToPrint.size() - 1;
1187 int backListCount = WKBundleBackForwardListGetBackListCount(list);
1188 for (int i = -1; i >= -backListCount; --i) {
1189 WKRetainPtr<WKBundleBackForwardListItemRef> item = adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, i));
1190 if (WKBundleBackForwardListItemIsSame(item.get(), m_previousTestBackForwardListItem.get()))
1192 itemsToPrint.append(item);
1195 for (int i = itemsToPrint.size() - 1; i >= 0; i--)
1196 dumpBackForwardListItem(itemsToPrint[i].get(), 8, i == currentItemIndex);
1198 InjectedBundle::shared().os() << "===============================================\n";