2 * Copyright (C) 2010, 2011, 2012 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/WKBundlePrivate.h>
45 #include <WebKit2/WKSecurityOrigin.h>
46 #include <WebKit2/WKURLRequest.h>
47 #include <wtf/HashMap.h>
48 #include <wtf/text/CString.h>
49 #include <wtf/text/StringBuilder.h>
52 #include "WebArchiveDumpSupport.h"
59 static bool hasPrefix(const WTF::String& searchString, const WTF::String& prefix)
61 return searchString.length() >= prefix.length() && searchString.substring(0, prefix.length()) == prefix;
64 static JSValueRef propertyValue(JSContextRef context, JSObjectRef object, const char* propertyName)
68 JSRetainPtr<JSStringRef> propertyNameString(Adopt, JSStringCreateWithUTF8CString(propertyName));
69 return JSObjectGetProperty(context, object, propertyNameString.get(), 0);
72 static double propertyValueDouble(JSContextRef context, JSObjectRef object, const char* propertyName)
74 JSValueRef value = propertyValue(context, object, propertyName);
77 return JSValueToNumber(context, value, 0);
80 static int propertyValueInt(JSContextRef context, JSObjectRef object, const char* propertyName)
82 return static_cast<int>(propertyValueDouble(context, object, propertyName));
85 static double numericWindowPropertyValue(WKBundleFrameRef frame, const char* propertyName)
87 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
88 return propertyValueDouble(context, JSContextGetGlobalObject(context), propertyName);
91 static WTF::String dumpPath(JSGlobalContextRef context, JSObjectRef nodeValue)
93 JSValueRef nodeNameValue = propertyValue(context, nodeValue, "nodeName");
94 JSRetainPtr<JSStringRef> jsStringNodeName(Adopt, JSValueToStringCopy(context, nodeNameValue, 0));
95 WKRetainPtr<WKStringRef> nodeName = toWK(jsStringNodeName);
97 JSValueRef parentNode = propertyValue(context, nodeValue, "parentNode");
99 StringBuilder stringBuilder;
100 stringBuilder.append(toWTFString(nodeName));
102 if (parentNode && JSValueIsObject(context, parentNode)) {
103 stringBuilder.appendLiteral(" > ");
104 stringBuilder.append(dumpPath(context, (JSObjectRef)parentNode));
107 return stringBuilder.toString();
110 static WTF::String dumpPath(WKBundlePageRef page, WKBundleScriptWorldRef world, WKBundleNodeHandleRef node)
115 WKBundleFrameRef frame = WKBundlePageGetMainFrame(page);
117 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world);
118 JSValueRef nodeValue = WKBundleFrameGetJavaScriptWrapperForNodeForWorld(frame, node, world);
119 ASSERT(JSValueIsObject(context, nodeValue));
120 JSObjectRef nodeObject = (JSObjectRef)nodeValue;
122 return dumpPath(context, nodeObject);
125 static WTF::String rangeToStr(WKBundlePageRef page, WKBundleScriptWorldRef world, WKBundleRangeHandleRef rangeRef)
130 WKBundleFrameRef frame = WKBundlePageGetMainFrame(page);
132 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world);
133 JSValueRef rangeValue = WKBundleFrameGetJavaScriptWrapperForRangeForWorld(frame, rangeRef, world);
134 ASSERT(JSValueIsObject(context, rangeValue));
135 JSObjectRef rangeObject = (JSObjectRef)rangeValue;
137 JSValueRef startNodeValue = propertyValue(context, rangeObject, "startContainer");
138 ASSERT(JSValueIsObject(context, startNodeValue));
139 JSObjectRef startNodeObject = (JSObjectRef)startNodeValue;
141 JSValueRef endNodeValue = propertyValue(context, rangeObject, "endContainer");
142 ASSERT(JSValueIsObject(context, endNodeValue));
143 JSObjectRef endNodeObject = (JSObjectRef)endNodeValue;
145 int startOffset = propertyValueInt(context, rangeObject, "startOffset");
146 int endOffset = propertyValueInt(context, rangeObject, "endOffset");
148 StringBuilder stringBuilder;
149 stringBuilder.appendLiteral("range from ");
150 stringBuilder.appendNumber(startOffset);
151 stringBuilder.appendLiteral(" of ");
152 stringBuilder.append(dumpPath(context, startNodeObject));
153 stringBuilder.appendLiteral(" to ");
154 stringBuilder.appendNumber(endOffset);
155 stringBuilder.appendLiteral(" of ");
156 stringBuilder.append(dumpPath(context, endNodeObject));
157 return stringBuilder.toString();
160 static WKRetainPtr<WKStringRef> NavigationTypeToString(WKFrameNavigationType type)
163 case kWKFrameNavigationTypeLinkClicked:
164 return adoptWK(WKStringCreateWithUTF8CString("link clicked"));
165 case kWKFrameNavigationTypeFormSubmitted:
166 return adoptWK(WKStringCreateWithUTF8CString("form submitted"));
167 case kWKFrameNavigationTypeBackForward:
168 return adoptWK(WKStringCreateWithUTF8CString("back/forward"));
169 case kWKFrameNavigationTypeReload:
170 return adoptWK(WKStringCreateWithUTF8CString("reload"));
171 case kWKFrameNavigationTypeFormResubmitted:
172 return adoptWK(WKStringCreateWithUTF8CString("form resubmitted"));
173 case kWKFrameNavigationTypeOther:
174 return adoptWK(WKStringCreateWithUTF8CString("other"));
176 return adoptWK(WKStringCreateWithUTF8CString("illegal value"));
179 static WTF::String styleDecToStr(WKBundleCSSStyleDeclarationRef style)
181 // DumpRenderTree calls -[DOMCSSStyleDeclaration description], which just dumps class name and object address.
182 // No existing tests actually hit this code path at the time of this writing, because WebCore doesn't call
183 // the editing client if the styling operation source is CommandFromDOM or CommandFromDOMWithUserInterface.
184 StringBuilder stringBuilder;
185 stringBuilder.appendLiteral("<DOMCSSStyleDeclaration ADDRESS>");
186 return stringBuilder.toString();
189 static WTF::String securityOriginToStr(WKSecurityOriginRef origin)
191 StringBuilder stringBuilder;
192 stringBuilder.append('{');
193 stringBuilder.append(toWTFString(adoptWK(WKSecurityOriginCopyProtocol(origin))));
194 stringBuilder.appendLiteral(", ");
195 stringBuilder.append(toWTFString(adoptWK(WKSecurityOriginCopyHost(origin))));
196 stringBuilder.appendLiteral(", ");
197 stringBuilder.appendNumber(WKSecurityOriginGetPort(origin));
198 stringBuilder.append('}');
200 return stringBuilder.toString();
203 static WTF::String frameToStr(WKBundleFrameRef frame)
205 WKRetainPtr<WKStringRef> name(AdoptWK, WKBundleFrameCopyName(frame));
206 StringBuilder stringBuilder;
207 if (WKBundleFrameIsMainFrame(frame)) {
208 if (!WKStringIsEmpty(name.get())) {
209 stringBuilder.appendLiteral("main frame \"");
210 stringBuilder.append(toWTFString(name));
211 stringBuilder.append('"');
213 stringBuilder.appendLiteral("main frame");
215 if (!WKStringIsEmpty(name.get())) {
216 stringBuilder.appendLiteral("frame \"");
217 stringBuilder.append(toWTFString(name));
218 stringBuilder.append('"');
221 stringBuilder.appendLiteral("frame (anonymous)");
224 return stringBuilder.toString();
227 static inline bool isLocalFileScheme(WKStringRef scheme)
229 return WKStringIsEqualToUTF8CStringIgnoringCase(scheme, "file");
232 static const char divider = '/';
234 static inline WTF::String pathSuitableForTestResult(WKURLRef fileUrl)
239 WKRetainPtr<WKStringRef> schemeString = adoptWK(WKURLCopyScheme(fileUrl));
240 if (!isLocalFileScheme(schemeString.get()))
241 return toWTFString(adoptWK(WKURLCopyString(fileUrl)));
243 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
244 WKRetainPtr<WKURLRef> mainFrameURL = adoptWK(WKBundleFrameCopyURL(mainFrame));
246 mainFrameURL = adoptWK(WKBundleFrameCopyProvisionalURL(mainFrame));
248 String pathString = toWTFString(adoptWK(WKURLCopyPath(fileUrl)));
249 String mainFrameURLPathString = toWTFString(adoptWK(WKURLCopyPath(mainFrameURL.get())));
250 String basePath = mainFrameURLPathString.substring(0, mainFrameURLPathString.reverseFind(divider) + 1);
252 if (!basePath.isEmpty() && pathString.startsWith(basePath))
253 return pathString.substring(basePath.length());
254 return toWTFString(adoptWK(WKURLCopyLastPathComponent(fileUrl))); // We lose some information here, but it's better than exposing a full path, which is always machine specific.
257 static HashMap<uint64_t, String> assignedUrlsCache;
259 static inline void dumpResourceURL(uint64_t identifier, StringBuilder& stringBuilder)
261 if (assignedUrlsCache.contains(identifier))
262 stringBuilder.append(assignedUrlsCache.get(identifier));
264 stringBuilder.appendLiteral("<unknown>");
267 InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page)
269 , m_world(AdoptWK, WKBundleScriptWorldCreateWorld())
271 WKBundlePageLoaderClientV7 loaderClient = {
273 didStartProvisionalLoadForFrame,
274 didReceiveServerRedirectForProvisionalLoadForFrame,
275 didFailProvisionalLoadWithErrorForFrame,
276 didCommitLoadForFrame,
277 didFinishDocumentLoadForFrame,
278 didFinishLoadForFrame,
279 didFailLoadWithErrorForFrame,
280 didSameDocumentNavigationForFrame,
281 didReceiveTitleForFrame,
282 0, // didFirstLayoutForFrame
283 0, // didFirstVisuallyNonEmptyLayoutForFrame
284 0, // didRemoveFrameFromHierarchy
285 didDisplayInsecureContentForFrame,
286 didRunInsecureContentForFrame,
287 didClearWindowForFrame,
288 didCancelClientRedirectForFrame,
289 willPerformClientRedirectForFrame,
290 didHandleOnloadEventsForFrame,
291 0, // didLayoutForFrame
292 0, // didNewFirstVisuallyNonEmptyLayout_unavailable
293 didDetectXSSForFrame,
294 0, // shouldGoToBackForwardListItem
295 0, // didCreateGlobalObjectForFrame
296 0, // willDisconnectDOMWindowExtensionFromGlobalObject
297 0, // didReconnectDOMWindowExtensionToGlobalObject
298 0, // willDestroyGlobalObjectForDOMWindowExtension
299 didFinishProgress, // didFinishProgress
300 0, // shouldForceUniversalAccessFromLocalURL
301 0, // didReceiveIntentForFrame
302 0, // registerIntentServiceForFrame
304 0, // featuresUsedInPage
305 0, // willLoadURLRequest
306 0, // willLoadDataRequest
307 0, // willDestroyFrame
309 WKBundlePageSetPageLoaderClient(m_page, &loaderClient.base);
311 WKBundlePageResourceLoadClientV1 resourceLoadClient = {
313 didInitiateLoadForResource,
314 willSendRequestForFrame,
315 didReceiveResponseForResource,
316 didReceiveContentLengthForResource,
317 didFinishLoadForResource,
318 didFailLoadForResource,
320 0 // shouldUseCredentialStorage
322 WKBundlePageSetResourceLoadClient(m_page, &resourceLoadClient.base);
324 WKBundlePagePolicyClientV0 policyClient = {
326 decidePolicyForNavigationAction,
327 decidePolicyForNewWindowAction,
328 decidePolicyForResponse,
329 unableToImplementPolicy
331 WKBundlePageSetPolicyClient(m_page, &policyClient.base);
333 WKBundlePageUIClientV2 uiClient = {
335 willAddMessageToConsole,
336 willSetStatusbarText,
337 willRunJavaScriptAlert,
338 willRunJavaScriptConfirm,
339 willRunJavaScriptPrompt,
340 0, /*mouseDidMoveOverElement*/
342 0, /*paintCustomOverhangArea*/
343 0, /*shouldGenerateFileForUpload*/
344 0, /*generateFileForUpload*/
345 0, /*shouldRubberBandInDirection*/
346 0, /*statusBarIsVisible*/
347 0, /*menuBarIsVisible*/
348 0, /*toolbarsAreVisible*/
349 didReachApplicationCacheOriginQuota,
350 didExceedDatabaseQuota,
351 0, /*plugInStartLabelTitle*/
352 0, /*plugInStartLabelSubtitle*/
353 0, /*plugInExtraStyleSheet*/
354 0, /*plugInExtraScript*/
356 WKBundlePageSetUIClient(m_page, &uiClient.base);
358 WKBundlePageEditorClientV1 editorClient = {
365 shouldChangeSelectedRange,
371 0, /* willWriteToPasteboard */
372 0, /* getPasteboardDataForRange */
373 0 /* didWriteToPasteboard */
375 WKBundlePageSetEditorClient(m_page, &editorClient.base);
377 #if ENABLE(FULLSCREEN_API)
378 WKBundlePageFullScreenClientV1 fullScreenClient = {
381 enterFullScreenForElement,
382 exitFullScreenForElement,
383 beganEnterFullScreen,
387 WKBundlePageSetFullScreenClient(m_page, &fullScreenClient.base);
391 InjectedBundlePage::~InjectedBundlePage()
395 void InjectedBundlePage::stopLoading()
397 WKBundlePageStopLoading(m_page);
400 void InjectedBundlePage::prepare()
402 WKBundlePageClearMainFrameName(m_page);
404 WKBundlePageSetPageZoomFactor(m_page, 1);
405 WKBundlePageSetTextZoomFactor(m_page, 1);
407 WKPoint origin = { 0, 0 };
408 WKBundlePageSetScaleAtOrigin(m_page, 1, origin);
410 m_previousTestBackForwardListItem = adoptWK(WKBundleBackForwardListCopyItemAtIndex(WKBundlePageGetBackForwardList(m_page), 0));
412 WKBundleFrameClearOpener(WKBundlePageGetMainFrame(m_page));
414 WKBundlePageSetTracksRepaints(m_page, false);
417 void InjectedBundlePage::resetAfterTest()
419 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
420 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
421 WebCoreTestSupport::resetInternalsObject(context);
422 assignedUrlsCache.clear();
425 // Loader Client Callbacks
427 // String output must be identical to -[WebFrame _drt_descriptionSuitableForTestResult].
428 static void dumpFrameDescriptionSuitableForTestResult(WKBundleFrameRef frame, StringBuilder& stringBuilder)
430 WKRetainPtr<WKStringRef> name(AdoptWK, WKBundleFrameCopyName(frame));
431 if (WKBundleFrameIsMainFrame(frame)) {
432 if (WKStringIsEmpty(name.get())) {
433 stringBuilder.appendLiteral("main frame");
437 stringBuilder.appendLiteral("main frame \"");
438 stringBuilder.append(toWTFString(name));
439 stringBuilder.append('"');
443 if (WKStringIsEmpty(name.get())) {
444 stringBuilder.appendLiteral("frame (anonymous)");
448 stringBuilder.appendLiteral("frame \"");
449 stringBuilder.append(toWTFString(name));
450 stringBuilder.append('"');
453 static void dumpLoadEvent(WKBundleFrameRef frame, const char* eventName)
455 StringBuilder stringBuilder;
456 dumpFrameDescriptionSuitableForTestResult(frame, stringBuilder);
457 stringBuilder.appendLiteral(" - ");
458 stringBuilder.append(eventName);
459 stringBuilder.append('\n');
460 InjectedBundle::shared().outputText(stringBuilder.toString());
463 static inline void dumpRequestDescriptionSuitableForTestResult(WKURLRequestRef request, StringBuilder& stringBuilder)
465 WKRetainPtr<WKURLRef> url = adoptWK(WKURLRequestCopyURL(request));
466 WKRetainPtr<WKURLRef> firstParty = adoptWK(WKURLRequestCopyFirstPartyForCookies(request));
467 WKRetainPtr<WKStringRef> httpMethod = adoptWK(WKURLRequestCopyHTTPMethod(request));
469 stringBuilder.appendLiteral("<NSURLRequest URL ");
470 stringBuilder.append(pathSuitableForTestResult(url.get()));
471 stringBuilder.appendLiteral(", main document URL ");
472 stringBuilder.append(pathSuitableForTestResult(firstParty.get()));
473 stringBuilder.appendLiteral(", http method ");
475 if (WKStringIsEmpty(httpMethod.get()))
476 stringBuilder.appendLiteral("(none)");
478 stringBuilder.append(toWTFString(httpMethod));
480 stringBuilder.append('>');
483 static inline void dumpResponseDescriptionSuitableForTestResult(WKURLResponseRef response, StringBuilder& stringBuilder)
485 WKRetainPtr<WKURLRef> url = adoptWK(WKURLResponseCopyURL(response));
487 stringBuilder.appendLiteral("(null)");
490 stringBuilder.appendLiteral("<NSURLResponse ");
491 stringBuilder.append(pathSuitableForTestResult(url.get()));
492 stringBuilder.appendLiteral(", http status code ");
493 stringBuilder.appendNumber(WKURLResponseHTTPStatusCode(response));
494 stringBuilder.append('>');
497 static inline void dumpErrorDescriptionSuitableForTestResult(WKErrorRef error, StringBuilder& stringBuilder)
499 WKRetainPtr<WKStringRef> errorDomain = adoptWK(WKErrorCopyDomain(error));
500 int errorCode = WKErrorGetErrorCode(error);
502 // We need to do some error mapping here to match the test expectations (Mac error names are expected).
503 if (WKStringIsEqualToUTF8CString(errorDomain.get(), "WebKitNetworkError")) {
504 errorDomain = adoptWK(WKStringCreateWithUTF8CString("NSURLErrorDomain"));
508 if (WKStringIsEqualToUTF8CString(errorDomain.get(), "WebKitPolicyError"))
509 errorDomain = adoptWK(WKStringCreateWithUTF8CString("WebKitErrorDomain"));
511 stringBuilder.appendLiteral("<NSError domain ");
512 stringBuilder.append(toWTFString(errorDomain));
513 stringBuilder.appendLiteral(", code ");
514 stringBuilder.appendNumber(errorCode);
516 WKRetainPtr<WKURLRef> url = adoptWK(WKErrorCopyFailingURL(error));
518 WKRetainPtr<WKStringRef> urlString = adoptWK(WKURLCopyString(url.get()));
519 stringBuilder.appendLiteral(", failing URL \"");
520 stringBuilder.append(toWTFString(urlString));
521 stringBuilder.append('"');
524 stringBuilder.append('>');
527 void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
529 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didStartProvisionalLoadForFrame(frame);
532 void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
534 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveServerRedirectForProvisionalLoadForFrame(frame);
537 void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef*, const void *clientInfo)
539 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailProvisionalLoadWithErrorForFrame(frame, error);
542 void InjectedBundlePage::didCommitLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
544 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didCommitLoadForFrame(frame);
547 void InjectedBundlePage::didFinishLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
549 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(frame);
552 void InjectedBundlePage::didFinishProgress(WKBundlePageRef, const void *clientInfo)
554 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishProgress();
557 void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo)
559 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishDocumentLoadForFrame(frame);
562 void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef*, const void *clientInfo)
564 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailLoadWithErrorForFrame(frame, error);
567 void InjectedBundlePage::didReceiveTitleForFrame(WKBundlePageRef page, WKStringRef title, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
569 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveTitleForFrame(title, frame);
572 void InjectedBundlePage::didClearWindowForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleScriptWorldRef world, const void *clientInfo)
574 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didClearWindowForFrame(frame, world);
577 void InjectedBundlePage::didCancelClientRedirectForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo)
579 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didCancelClientRedirectForFrame(frame);
582 void InjectedBundlePage::willPerformClientRedirectForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKURLRef url, double delay, double date, const void* clientInfo)
584 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willPerformClientRedirectForFrame(page, frame, url, delay, date);
587 void InjectedBundlePage::didSameDocumentNavigationForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef*, const void* clientInfo)
589 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didSameDocumentNavigationForFrame(frame, type);
592 void InjectedBundlePage::didHandleOnloadEventsForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo)
594 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didHandleOnloadEventsForFrame(frame);
597 void InjectedBundlePage::didDisplayInsecureContentForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo)
599 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didDisplayInsecureContentForFrame(frame);
602 void InjectedBundlePage::didDetectXSSForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo)
604 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didDetectXSSForFrame(frame);
607 void InjectedBundlePage::didRunInsecureContentForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void* clientInfo)
609 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didRunInsecureContentForFrame(frame);
612 void InjectedBundlePage::didInitiateLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLRequestRef request, bool pageLoadIsProvisional, const void* clientInfo)
614 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didInitiateLoadForResource(page, frame, identifier, request, pageLoadIsProvisional);
617 WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLRequestRef request, WKURLResponseRef redirectResponse, const void* clientInfo)
619 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willSendRequestForFrame(page, frame, identifier, request, redirectResponse);
622 void InjectedBundlePage::didReceiveResponseForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLResponseRef response, const void* clientInfo)
624 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveResponseForResource(page, frame, identifier, response);
627 void InjectedBundlePage::didReceiveContentLengthForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, uint64_t length, const void* clientInfo)
629 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveContentLengthForResource(page, frame, identifier, length);
632 void InjectedBundlePage::didFinishLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, const void* clientInfo)
634 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForResource(page, frame, identifier);
637 void InjectedBundlePage::didFailLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKErrorRef error, const void* clientInfo)
639 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailLoadForResource(page, frame, identifier, error);
642 bool InjectedBundlePage::shouldCacheResponse(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, const void* clientInfo)
644 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldCacheResponse(page, frame, identifier);
647 void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundleFrameRef frame)
649 if (!InjectedBundle::shared().isTestRunning())
652 platformDidStartProvisionalLoadForFrame(frame);
654 if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
655 dumpLoadEvent(frame, "didStartProvisionalLoadForFrame");
657 if (!InjectedBundle::shared().topLoadingFrame())
658 InjectedBundle::shared().setTopLoadingFrame(frame);
660 if (InjectedBundle::shared().testRunner()->shouldStopProvisionalFrameLoads())
661 dumpLoadEvent(frame, "stopping load in didStartProvisionalLoadForFrame callback");
664 void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundleFrameRef frame)
666 if (!InjectedBundle::shared().isTestRunning())
669 if (!InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
672 dumpLoadEvent(frame, "didReceiveServerRedirectForProvisionalLoadForFrame");
675 void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef)
677 if (!InjectedBundle::shared().isTestRunning())
680 if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
681 dumpLoadEvent(frame, "didFailProvisionalLoadWithError");
683 frameDidChangeLocation(frame);
686 void InjectedBundlePage::didCommitLoadForFrame(WKBundleFrameRef frame)
688 if (!InjectedBundle::shared().isTestRunning())
691 if (!InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
694 dumpLoadEvent(frame, "didCommitLoadForFrame");
697 void InjectedBundlePage::didFinishProgress()
699 if (!InjectedBundle::shared().isTestRunning())
702 if (!InjectedBundle::shared().testRunner()->shouldDumpProgressFinishedCallback())
705 InjectedBundle::shared().outputText("postProgressFinishedNotification\n");
708 enum FrameNamePolicy { ShouldNotIncludeFrameName, ShouldIncludeFrameName };
710 static void dumpFrameScrollPosition(WKBundleFrameRef frame, StringBuilder& stringBuilder, FrameNamePolicy shouldIncludeFrameName = ShouldNotIncludeFrameName)
712 double x = numericWindowPropertyValue(frame, "pageXOffset");
713 double y = numericWindowPropertyValue(frame, "pageYOffset");
714 if (fabs(x) <= 0.00000001 && fabs(y) <= 0.00000001)
717 if (shouldIncludeFrameName) {
718 WKRetainPtr<WKStringRef> name(AdoptWK, WKBundleFrameCopyName(frame));
719 stringBuilder.appendLiteral("frame '");
720 stringBuilder.append(toWTFString(name));
721 stringBuilder.appendLiteral("' ");
723 stringBuilder.appendLiteral("scrolled to ");
724 stringBuilder.append(WTF::String::number(x));
725 stringBuilder.append(',');
726 stringBuilder.append(WTF::String::number(y));
727 stringBuilder.append('\n');
730 static void dumpDescendantFrameScrollPositions(WKBundleFrameRef frame, StringBuilder& stringBuilder)
732 WKRetainPtr<WKArrayRef> childFrames(AdoptWK, WKBundleFrameCopyChildFrames(frame));
733 size_t size = WKArrayGetSize(childFrames.get());
734 for (size_t i = 0; i < size; ++i) {
735 WKBundleFrameRef subframe = static_cast<WKBundleFrameRef>(WKArrayGetItemAtIndex(childFrames.get(), i));
736 dumpFrameScrollPosition(subframe, stringBuilder, ShouldIncludeFrameName);
737 dumpDescendantFrameScrollPositions(subframe, stringBuilder);
741 void InjectedBundlePage::dumpAllFrameScrollPositions(StringBuilder& stringBuilder)
743 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
744 dumpFrameScrollPosition(frame, stringBuilder);
745 dumpDescendantFrameScrollPositions(frame, stringBuilder);
748 static JSRetainPtr<JSStringRef> toJS(const char* string)
750 return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString(string));
753 static bool hasDocumentElement(WKBundleFrameRef frame)
755 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
756 JSObjectRef globalObject = JSContextGetGlobalObject(context);
758 JSValueRef documentValue = JSObjectGetProperty(context, globalObject, toJS("document").get(), 0);
762 ASSERT(JSValueIsObject(context, documentValue));
763 JSObjectRef document = JSValueToObject(context, documentValue, 0);
765 JSValueRef documentElementValue = JSObjectGetProperty(context, document, toJS("documentElement").get(), 0);
766 if (!documentElementValue)
769 return JSValueToBoolean(context, documentElementValue);
772 static void dumpFrameText(WKBundleFrameRef frame, StringBuilder& stringBuilder)
774 // If the frame doesn't have a document element, its inner text will be an empty string, so
775 // we'll end up just appending a single newline below. But DumpRenderTree doesn't append
776 // anything in this case, so we shouldn't either.
777 if (!hasDocumentElement(frame))
780 WKRetainPtr<WKStringRef> text(AdoptWK, WKBundleFrameCopyInnerText(frame));
781 stringBuilder.append(toWTFString(text));
782 stringBuilder.append('\n');
785 static void dumpDescendantFramesText(WKBundleFrameRef frame, StringBuilder& stringBuilder)
787 WKRetainPtr<WKArrayRef> childFrames(AdoptWK, WKBundleFrameCopyChildFrames(frame));
788 size_t size = WKArrayGetSize(childFrames.get());
789 for (size_t i = 0; i < size; ++i) {
790 WKBundleFrameRef subframe = static_cast<WKBundleFrameRef>(WKArrayGetItemAtIndex(childFrames.get(), i));
791 WKRetainPtr<WKStringRef> subframeName(AdoptWK, WKBundleFrameCopyName(subframe));
793 // DumpRenderTree ignores empty frames, so do the same thing here.
794 if (!hasDocumentElement(subframe))
797 stringBuilder.appendLiteral("\n--------\nFrame: '");
798 stringBuilder.append(toWTFString(subframeName));
799 stringBuilder.appendLiteral("'\n--------\n");
801 dumpFrameText(subframe, stringBuilder);
802 dumpDescendantFramesText(subframe, stringBuilder);
806 void InjectedBundlePage::dumpAllFramesText(StringBuilder& stringBuilder)
808 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
809 dumpFrameText(frame, stringBuilder);
810 dumpDescendantFramesText(frame, stringBuilder);
814 void InjectedBundlePage::dumpDOMAsWebArchive(WKBundleFrameRef frame, StringBuilder& stringBuilder)
817 WKRetainPtr<WKDataRef> wkData = adoptWK(WKBundleFrameCopyWebArchive(frame));
818 RetainPtr<CFDataRef> cfData = adoptCF(CFDataCreate(0, WKDataGetBytes(wkData.get()), WKDataGetSize(wkData.get())));
819 RetainPtr<CFStringRef> cfString = adoptCF(createXMLStringFromWebArchiveData(cfData.get()));
820 stringBuilder.append(cfString.get());
824 void InjectedBundlePage::dump()
826 ASSERT(InjectedBundle::shared().isTestRunning());
828 InjectedBundle::shared().testRunner()->invalidateWaitToDumpWatchdogTimer();
830 // Force a paint before dumping. This matches DumpRenderTree on Windows. (DumpRenderTree on Mac
831 // does this at a slightly different time.) See <http://webkit.org/b/55469> for details.
832 WKBundlePageForceRepaint(m_page);
834 WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
835 WKRetainPtr<WKURLRef> urlRef = adoptWK(WKBundleFrameCopyURL(frame));
836 String url = toWTFString(adoptWK(WKURLCopyString(urlRef.get())));
837 WKRetainPtr<WKStringRef> mimeType = adoptWK(WKBundleFrameCopyMIMETypeForResourceWithURL(frame, urlRef.get()));
838 if (url.find("dumpAsText/") != notFound || WKStringIsEqualToUTF8CString(mimeType.get(), "text/plain"))
839 InjectedBundle::shared().testRunner()->dumpAsText(false);
841 StringBuilder stringBuilder;
843 switch (InjectedBundle::shared().testRunner()->whatToDump()) {
844 case TestRunner::RenderTree: {
845 if (InjectedBundle::shared().testRunner()->isPrinting())
846 stringBuilder.append(toWTFString(adoptWK(WKBundlePageCopyRenderTreeExternalRepresentationForPrinting(m_page)).get()));
848 stringBuilder.append(toWTFString(adoptWK(WKBundlePageCopyRenderTreeExternalRepresentation(m_page)).get()));
851 case TestRunner::MainFrameText:
852 dumpFrameText(WKBundlePageGetMainFrame(m_page), stringBuilder);
854 case TestRunner::AllFramesText:
855 dumpAllFramesText(stringBuilder);
857 case TestRunner::Audio:
859 case TestRunner::DOMAsWebArchive:
860 dumpDOMAsWebArchive(frame, stringBuilder);
864 if (InjectedBundle::shared().testRunner()->shouldDumpAllFrameScrollPositions())
865 dumpAllFrameScrollPositions(stringBuilder);
866 else if (InjectedBundle::shared().testRunner()->shouldDumpMainFrameScrollPosition())
867 dumpFrameScrollPosition(WKBundlePageGetMainFrame(m_page), stringBuilder);
869 if (InjectedBundle::shared().testRunner()->shouldDumpBackForwardListsForAllWindows())
870 InjectedBundle::shared().dumpBackForwardListsForAllPages(stringBuilder);
872 if (InjectedBundle::shared().shouldDumpPixels() && InjectedBundle::shared().testRunner()->shouldDumpPixels()) {
873 WKSnapshotOptions options = kWKSnapshotOptionsShareable | kWKSnapshotOptionsInViewCoordinates;
874 if (InjectedBundle::shared().testRunner()->shouldDumpSelectionRect())
875 options |= kWKSnapshotOptionsPaintSelectionRectangle;
877 InjectedBundle::shared().setPixelResult(adoptWK(WKBundlePageCreateSnapshotWithOptions(m_page, WKBundleFrameGetVisibleContentBounds(WKBundlePageGetMainFrame(m_page)), options)).get());
878 if (WKBundlePageIsTrackingRepaints(m_page))
879 InjectedBundle::shared().setRepaintRects(adoptWK(WKBundlePageCopyTrackedRepaintRects(m_page)).get());
882 InjectedBundle::shared().outputText(stringBuilder.toString());
883 InjectedBundle::shared().done();
886 void InjectedBundlePage::didFinishLoadForFrame(WKBundleFrameRef frame)
888 if (!InjectedBundle::shared().isTestRunning())
891 if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
892 dumpLoadEvent(frame, "didFinishLoadForFrame");
894 frameDidChangeLocation(frame, /*shouldDump*/ true);
897 void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef)
899 if (!InjectedBundle::shared().isTestRunning())
902 if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
903 dumpLoadEvent(frame, "didFailLoadWithError");
905 frameDidChangeLocation(frame);
908 void InjectedBundlePage::didReceiveTitleForFrame(WKStringRef title, WKBundleFrameRef frame)
910 if (!InjectedBundle::shared().isTestRunning())
913 StringBuilder stringBuilder;
914 if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) {
915 dumpFrameDescriptionSuitableForTestResult(frame, stringBuilder);
916 stringBuilder.appendLiteral(" - didReceiveTitle: ");
917 stringBuilder.append(toWTFString(title));
918 stringBuilder.append('\n');
921 if (InjectedBundle::shared().testRunner()->shouldDumpTitleChanges()) {
922 stringBuilder.appendLiteral("TITLE CHANGED: '");
923 stringBuilder.append(toWTFString(title));
924 stringBuilder.appendLiteral("'\n");
927 InjectedBundle::shared().outputText(stringBuilder.toString());
930 void InjectedBundlePage::didClearWindowForFrame(WKBundleFrameRef frame, WKBundleScriptWorldRef world)
932 if (!InjectedBundle::shared().isTestRunning())
935 JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world);
936 JSObjectRef window = JSContextGetGlobalObject(context);
938 if (WKBundleScriptWorldNormalWorld() != world) {
939 JSObjectSetProperty(context, window, toJS("__worldID").get(), JSValueMakeNumber(context, TestRunner::worldIDForWorld(world)), kJSPropertyAttributeReadOnly, 0);
943 JSValueRef exception = 0;
944 InjectedBundle::shared().testRunner()->makeWindowObject(context, window, &exception);
945 InjectedBundle::shared().gcController()->makeWindowObject(context, window, &exception);
946 InjectedBundle::shared().eventSendingController()->makeWindowObject(context, window, &exception);
947 InjectedBundle::shared().textInputController()->makeWindowObject(context, window, &exception);
948 InjectedBundle::shared().accessibilityController()->makeWindowObject(context, window, &exception);
950 WebCoreTestSupport::injectInternalsObject(context);
953 void InjectedBundlePage::didCancelClientRedirectForFrame(WKBundleFrameRef frame)
955 if (!InjectedBundle::shared().isTestRunning())
958 if (!InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
961 dumpLoadEvent(frame, "didCancelClientRedirectForFrame");
964 void InjectedBundlePage::willPerformClientRedirectForFrame(WKBundlePageRef, WKBundleFrameRef frame, WKURLRef url, double delay, double date)
966 if (!InjectedBundle::shared().isTestRunning())
969 if (!InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
972 StringBuilder stringBuilder;
973 dumpFrameDescriptionSuitableForTestResult(frame, stringBuilder);
974 stringBuilder.appendLiteral(" - willPerformClientRedirectToURL: ");
975 stringBuilder.append(pathSuitableForTestResult(url));
976 stringBuilder.appendLiteral(" \n");
977 InjectedBundle::shared().outputText(stringBuilder.toString());
980 void InjectedBundlePage::didSameDocumentNavigationForFrame(WKBundleFrameRef frame, WKSameDocumentNavigationType type)
984 void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundleFrameRef frame)
986 if (!InjectedBundle::shared().isTestRunning())
989 if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
990 dumpLoadEvent(frame, "didFinishDocumentLoadForFrame");
992 unsigned pendingFrameUnloadEvents = WKBundleFrameGetPendingUnloadCount(frame);
993 if (pendingFrameUnloadEvents) {
994 StringBuilder stringBuilder;
995 stringBuilder.append(frameToStr(frame));
996 stringBuilder.appendLiteral(" - has ");
997 stringBuilder.appendNumber(pendingFrameUnloadEvents);
998 stringBuilder.appendLiteral(" onunload handler(s)\n");
999 InjectedBundle::shared().outputText(stringBuilder.toString());
1003 void InjectedBundlePage::didHandleOnloadEventsForFrame(WKBundleFrameRef frame)
1005 if (!InjectedBundle::shared().isTestRunning())
1008 if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
1009 dumpLoadEvent(frame, "didHandleOnloadEventsForFrame");
1012 void InjectedBundlePage::didDisplayInsecureContentForFrame(WKBundleFrameRef frame)
1014 if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
1015 InjectedBundle::shared().outputText("didDisplayInsecureContent\n");
1018 void InjectedBundlePage::didRunInsecureContentForFrame(WKBundleFrameRef frame)
1020 if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
1021 InjectedBundle::shared().outputText("didRunInsecureContent\n");
1024 void InjectedBundlePage::didDetectXSSForFrame(WKBundleFrameRef frame)
1026 if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks())
1027 InjectedBundle::shared().outputText("didDetectXSS\n");
1030 void InjectedBundlePage::didInitiateLoadForResource(WKBundlePageRef page, WKBundleFrameRef, uint64_t identifier, WKURLRequestRef request, bool)
1032 if (!InjectedBundle::shared().isTestRunning())
1035 WKRetainPtr<WKURLRef> url = adoptWK(WKURLRequestCopyURL(request));
1036 assignedUrlsCache.add(identifier, pathSuitableForTestResult(url.get()));
1039 // Resource Load Client Callbacks
1041 static inline bool isLocalHost(WKStringRef host)
1043 return WKStringIsEqualToUTF8CString(host, "127.0.0.1") || WKStringIsEqualToUTF8CString(host, "localhost");
1046 static inline bool isHTTPOrHTTPSScheme(WKStringRef scheme)
1048 return WKStringIsEqualToUTF8CStringIgnoringCase(scheme, "http") || WKStringIsEqualToUTF8CStringIgnoringCase(scheme, "https");
1051 WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLRequestRef request, WKURLResponseRef response)
1053 if (InjectedBundle::shared().isTestRunning()
1054 && InjectedBundle::shared().testRunner()->shouldDumpResourceLoadCallbacks()) {
1055 StringBuilder stringBuilder;
1056 dumpResourceURL(identifier, stringBuilder);
1057 stringBuilder.appendLiteral(" - willSendRequest ");
1058 dumpRequestDescriptionSuitableForTestResult(request, stringBuilder);
1059 stringBuilder.appendLiteral(" redirectResponse ");
1060 dumpResponseDescriptionSuitableForTestResult(response, stringBuilder);
1061 stringBuilder.append('\n');
1062 InjectedBundle::shared().outputText(stringBuilder.toString());
1065 if (InjectedBundle::shared().isTestRunning() && InjectedBundle::shared().testRunner()->willSendRequestReturnsNull())
1068 WKRetainPtr<WKURLRef> redirectURL = adoptWK(WKURLResponseCopyURL(response));
1069 if (InjectedBundle::shared().isTestRunning() && InjectedBundle::shared().testRunner()->willSendRequestReturnsNullOnRedirect() && redirectURL) {
1070 InjectedBundle::shared().outputText("Returning null for this redirect\n");
1074 WKRetainPtr<WKURLRef> url = adoptWK(WKURLRequestCopyURL(request));
1075 WKRetainPtr<WKStringRef> host = adoptWK(WKURLCopyHostName(url.get()));
1076 WKRetainPtr<WKStringRef> scheme = adoptWK(WKURLCopyScheme(url.get()));
1077 WKRetainPtr<WKStringRef> urlString = adoptWK(WKURLCopyString(url.get()));
1078 if (host && !WKStringIsEmpty(host.get())
1079 && isHTTPOrHTTPSScheme(scheme.get())
1080 && !WKStringIsEqualToUTF8CString(host.get(), "255.255.255.255") // Used in some tests that expect to get back an error.
1081 && !isLocalHost(host.get())) {
1082 bool mainFrameIsExternal = false;
1083 if (InjectedBundle::shared().isTestRunning()) {
1084 WKBundleFrameRef mainFrame = InjectedBundle::shared().topLoadingFrame();
1085 WKRetainPtr<WKURLRef> mainFrameURL = adoptWK(WKBundleFrameCopyURL(mainFrame));
1086 if (!mainFrameURL || WKStringIsEqualToUTF8CString(adoptWK(WKURLCopyString(mainFrameURL.get())).get(), "about:blank"))
1087 mainFrameURL = adoptWK(WKBundleFrameCopyProvisionalURL(mainFrame));
1089 WKRetainPtr<WKStringRef> mainFrameHost = adoptWK(WKURLCopyHostName(mainFrameURL.get()));
1090 WKRetainPtr<WKStringRef> mainFrameScheme = adoptWK(WKURLCopyScheme(mainFrameURL.get()));
1091 mainFrameIsExternal = isHTTPOrHTTPSScheme(mainFrameScheme.get()) && !isLocalHost(mainFrameHost.get());
1093 if (!mainFrameIsExternal) {
1094 StringBuilder stringBuilder;
1095 stringBuilder.appendLiteral("Blocked access to external URL ");
1096 stringBuilder.append(toWTFString(urlString));
1097 stringBuilder.append('\n');
1098 InjectedBundle::shared().outputText(stringBuilder.toString());
1107 void InjectedBundlePage::didReceiveResponseForResource(WKBundlePageRef page, WKBundleFrameRef, uint64_t identifier, WKURLResponseRef response)
1109 if (!InjectedBundle::shared().isTestRunning())
1112 if (InjectedBundle::shared().testRunner()->shouldDumpResourceLoadCallbacks()) {
1113 StringBuilder stringBuilder;
1114 dumpResourceURL(identifier, stringBuilder);
1115 stringBuilder.appendLiteral(" - didReceiveResponse ");
1116 dumpResponseDescriptionSuitableForTestResult(response, stringBuilder);
1117 stringBuilder.append('\n');
1118 InjectedBundle::shared().outputText(stringBuilder.toString());
1122 if (!InjectedBundle::shared().testRunner()->shouldDumpResourceResponseMIMETypes())
1125 WKRetainPtr<WKURLRef> url = adoptWK(WKURLResponseCopyURL(response));
1126 WKRetainPtr<WKStringRef> urlString = adoptWK(WKURLCopyLastPathComponent(url.get()));
1127 WKRetainPtr<WKStringRef> mimeTypeString = adoptWK(WKURLResponseCopyMIMEType(response));
1129 StringBuilder stringBuilder;
1130 stringBuilder.append(toWTFString(urlString));
1131 stringBuilder.appendLiteral(" has MIME type ");
1132 stringBuilder.append(toWTFString(mimeTypeString));
1133 stringBuilder.append('\n');
1134 InjectedBundle::shared().outputText(stringBuilder.toString());
1137 void InjectedBundlePage::didReceiveContentLengthForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t, uint64_t)
1141 void InjectedBundlePage::didFinishLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t identifier)
1143 if (!InjectedBundle::shared().isTestRunning())
1146 if (!InjectedBundle::shared().testRunner()->shouldDumpResourceLoadCallbacks())
1149 StringBuilder stringBuilder;
1150 dumpResourceURL(identifier, stringBuilder);
1151 stringBuilder.appendLiteral(" - didFinishLoading\n");
1152 InjectedBundle::shared().outputText(stringBuilder.toString());
1155 void InjectedBundlePage::didFailLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t identifier, WKErrorRef error)
1157 if (!InjectedBundle::shared().isTestRunning())
1160 if (!InjectedBundle::shared().testRunner()->shouldDumpResourceLoadCallbacks())
1163 StringBuilder stringBuilder;
1164 dumpResourceURL(identifier, stringBuilder);
1165 stringBuilder.appendLiteral(" - didFailLoadingWithError: ");
1167 dumpErrorDescriptionSuitableForTestResult(error, stringBuilder);
1168 stringBuilder.append('\n');
1169 InjectedBundle::shared().outputText(stringBuilder.toString());
1172 bool InjectedBundlePage::shouldCacheResponse(WKBundlePageRef, WKBundleFrameRef, uint64_t identifier)
1174 if (!InjectedBundle::shared().isTestRunning())
1177 if (!InjectedBundle::shared().testRunner()->shouldDumpWillCacheResponse())
1180 StringBuilder stringBuilder;
1181 stringBuilder.appendNumber(identifier);
1182 stringBuilder.appendLiteral(" - willCacheResponse: called\n");
1183 InjectedBundle::shared().outputText(stringBuilder.toString());
1185 // The default behavior is the cache the response.
1190 // Policy Client Callbacks
1192 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNavigationAction(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleNavigationActionRef navigationAction, WKURLRequestRef request, WKTypeRef* userData, const void* clientInfo)
1194 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->decidePolicyForNavigationAction(page, frame, navigationAction, request, userData);
1197 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNewWindowAction(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleNavigationActionRef navigationAction, WKURLRequestRef request, WKStringRef frameName, WKTypeRef* userData, const void* clientInfo)
1199 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->decidePolicyForNewWindowAction(page, frame, navigationAction, request, frameName, userData);
1202 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForResponse(WKBundlePageRef page, WKBundleFrameRef frame, WKURLResponseRef response, WKURLRequestRef request, WKTypeRef* userData, const void* clientInfo)
1204 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->decidePolicyForResponse(page, frame, response, request, userData);
1207 void InjectedBundlePage::unableToImplementPolicy(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef* userData, const void* clientInfo)
1209 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->unableToImplementPolicy(page, frame, error, userData);
1212 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNavigationAction(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleNavigationActionRef navigationAction, WKURLRequestRef request, WKTypeRef* userData)
1214 if (!InjectedBundle::shared().isTestRunning())
1215 return WKBundlePagePolicyActionUse;
1217 if (!InjectedBundle::shared().testRunner()->isPolicyDelegateEnabled())
1218 return WKBundlePagePolicyActionUse;
1220 WKRetainPtr<WKURLRef> url = adoptWK(WKURLRequestCopyURL(request));
1221 WKRetainPtr<WKStringRef> urlScheme = adoptWK(WKURLCopyScheme(url.get()));
1223 StringBuilder stringBuilder;
1224 stringBuilder.appendLiteral("Policy delegate: attempt to load ");
1225 if (isLocalFileScheme(urlScheme.get())) {
1226 WKRetainPtr<WKStringRef> filename = adoptWK(WKURLCopyLastPathComponent(url.get()));
1227 stringBuilder.append(toWTFString(filename));
1229 WKRetainPtr<WKStringRef> urlString = adoptWK(WKURLCopyString(url.get()));
1230 stringBuilder.append(toWTFString(urlString));
1232 stringBuilder.appendLiteral(" with navigation type \'");
1233 stringBuilder.append(toWTFString(NavigationTypeToString(WKBundleNavigationActionGetNavigationType(navigationAction))));
1234 stringBuilder.appendLiteral("\'");
1235 WKBundleHitTestResultRef hitTestResultRef = WKBundleNavigationActionCopyHitTestResult(navigationAction);
1236 if (hitTestResultRef) {
1237 stringBuilder.appendLiteral(" originating from ");
1238 stringBuilder.append(dumpPath(m_page, m_world.get(), WKBundleHitTestResultCopyNodeHandle(hitTestResultRef)));
1241 stringBuilder.append('\n');
1242 InjectedBundle::shared().outputText(stringBuilder.toString());
1243 InjectedBundle::shared().testRunner()->notifyDone();
1245 if (InjectedBundle::shared().testRunner()->isPolicyDelegatePermissive())
1246 return WKBundlePagePolicyActionUse;
1247 return WKBundlePagePolicyActionPassThrough;
1250 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNewWindowAction(WKBundlePageRef, WKBundleFrameRef, WKBundleNavigationActionRef, WKURLRequestRef, WKStringRef, WKTypeRef*)
1252 return WKBundlePagePolicyActionUse;
1255 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForResponse(WKBundlePageRef page, WKBundleFrameRef, WKURLResponseRef response, WKURLRequestRef, WKTypeRef*)
1257 if (WKURLResponseIsAttachment(response)) {
1258 StringBuilder stringBuilder;
1259 WKRetainPtr<WKStringRef> filename = adoptWK(WKURLResponseCopySuggestedFilename(response));
1260 stringBuilder.appendLiteral("Policy delegate: resource is an attachment, suggested file name \'");
1261 stringBuilder.append(toWTFString(filename));
1262 stringBuilder.appendLiteral("\'\n");
1263 InjectedBundle::shared().outputText(stringBuilder.toString());
1266 WKRetainPtr<WKStringRef> mimeType = adoptWK(WKURLResponseCopyMIMEType(response));
1267 return WKBundlePageCanShowMIMEType(page, mimeType.get()) ? WKBundlePagePolicyActionUse : WKBundlePagePolicyActionPassThrough;
1270 void InjectedBundlePage::unableToImplementPolicy(WKBundlePageRef, WKBundleFrameRef, WKErrorRef, WKTypeRef*)
1274 // UI Client Callbacks
1276 void InjectedBundlePage::willAddMessageToConsole(WKBundlePageRef page, WKStringRef message, uint32_t lineNumber, const void *clientInfo)
1278 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willAddMessageToConsole(message, lineNumber);
1281 void InjectedBundlePage::willSetStatusbarText(WKBundlePageRef page, WKStringRef statusbarText, const void *clientInfo)
1283 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willSetStatusbarText(statusbarText);
1286 void InjectedBundlePage::willRunJavaScriptAlert(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo)
1288 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptAlert(message, frame);
1291 void InjectedBundlePage::willRunJavaScriptConfirm(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo)
1293 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptConfirm(message, frame);
1296 void InjectedBundlePage::willRunJavaScriptPrompt(WKBundlePageRef page, WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef frame, const void *clientInfo)
1298 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptPrompt(message, defaultValue, frame);
1301 void InjectedBundlePage::didReachApplicationCacheOriginQuota(WKBundlePageRef page, WKSecurityOriginRef origin, int64_t totalBytesNeeded, const void* clientInfo)
1303 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReachApplicationCacheOriginQuota(origin, totalBytesNeeded);
1306 uint64_t InjectedBundlePage::didExceedDatabaseQuota(WKBundlePageRef page, WKSecurityOriginRef origin, WKStringRef databaseName, WKStringRef databaseDisplayName, uint64_t currentQuotaBytes, uint64_t currentOriginUsageBytes, uint64_t currentDatabaseUsageBytes, uint64_t expectedUsageBytes, const void* clientInfo)
1308 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didExceedDatabaseQuota(origin, databaseName, databaseDisplayName, currentQuotaBytes, currentOriginUsageBytes, currentDatabaseUsageBytes, expectedUsageBytes);
1311 static WTF::String lastFileURLPathComponent(const WTF::String& path)
1313 size_t pos = path.find("file://");
1314 ASSERT(WTF::notFound != pos);
1316 WTF::String tmpPath = path.substring(pos + 7);
1317 if (tmpPath.length() < 2) // Keep the lone slash to avoid empty output.
1320 // Remove the trailing delimiter
1321 if (tmpPath[tmpPath.length() - 1] == '/')
1322 tmpPath.remove(tmpPath.length() - 1);
1324 pos = tmpPath.reverseFind('/');
1325 if (WTF::notFound != pos)
1326 return tmpPath.substring(pos + 1);
1331 void InjectedBundlePage::willAddMessageToConsole(WKStringRef message, uint32_t lineNumber)
1333 if (!InjectedBundle::shared().isTestRunning())
1336 WTF::String messageString = toWTFString(message);
1337 size_t nullCharPos = messageString.find(UChar(0));
1338 if (nullCharPos != WTF::notFound)
1339 messageString.truncate(nullCharPos);
1341 size_t fileProtocolStart = messageString.find("file://");
1342 if (fileProtocolStart != WTF::notFound)
1343 // FIXME: The code below does not handle additional text after url nor multiple urls. This matches DumpRenderTree implementation.
1344 messageString = messageString.substring(0, fileProtocolStart) + lastFileURLPathComponent(messageString.substring(fileProtocolStart));
1346 StringBuilder stringBuilder;
1347 stringBuilder.appendLiteral("CONSOLE MESSAGE: ");
1349 stringBuilder.appendLiteral("line ");
1350 stringBuilder.appendNumber(lineNumber);
1351 stringBuilder.appendLiteral(": ");
1353 stringBuilder.append(messageString);
1354 stringBuilder.append('\n');
1355 InjectedBundle::shared().outputText(stringBuilder.toString());
1358 void InjectedBundlePage::willSetStatusbarText(WKStringRef statusbarText)
1360 if (!InjectedBundle::shared().isTestRunning())
1363 if (!InjectedBundle::shared().testRunner()->shouldDumpStatusCallbacks())
1366 StringBuilder stringBuilder;
1367 stringBuilder.appendLiteral("UI DELEGATE STATUS CALLBACK: setStatusText:");
1368 stringBuilder.append(toWTFString(statusbarText));
1369 stringBuilder.append('\n');
1370 InjectedBundle::shared().outputText(stringBuilder.toString());
1373 void InjectedBundlePage::willRunJavaScriptAlert(WKStringRef message, WKBundleFrameRef)
1375 if (!InjectedBundle::shared().isTestRunning())
1378 StringBuilder stringBuilder;
1379 stringBuilder.appendLiteral("ALERT: ");
1380 stringBuilder.append(toWTFString(message));
1381 stringBuilder.append('\n');
1382 InjectedBundle::shared().outputText(stringBuilder.toString());
1385 void InjectedBundlePage::willRunJavaScriptConfirm(WKStringRef message, WKBundleFrameRef)
1387 if (!InjectedBundle::shared().isTestRunning())
1390 StringBuilder stringBuilder;
1391 stringBuilder.appendLiteral("CONFIRM: ");
1392 stringBuilder.append(toWTFString(message));
1393 stringBuilder.append('\n');
1394 InjectedBundle::shared().outputText(stringBuilder.toString());
1397 void InjectedBundlePage::willRunJavaScriptPrompt(WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef)
1399 StringBuilder stringBuilder;
1400 stringBuilder.appendLiteral("PROMPT: ");
1401 stringBuilder.append(toWTFString(message));
1402 stringBuilder.appendLiteral(", default text: ");
1403 stringBuilder.append(toWTFString(defaultValue));
1404 stringBuilder.append('\n');
1405 InjectedBundle::shared().outputText(stringBuilder.toString());
1408 void InjectedBundlePage::didReachApplicationCacheOriginQuota(WKSecurityOriginRef origin, int64_t totalBytesNeeded)
1410 if (InjectedBundle::shared().testRunner()->shouldDumpApplicationCacheDelegateCallbacks()) {
1411 // For example, numbers from 30000 - 39999 will output as 30000.
1412 // Rounding up or down does not really matter for these tests. It's
1413 // sufficient to just get a range of 10000 to determine if we were
1414 // above or below a threshold.
1415 int64_t truncatedSpaceNeeded = (totalBytesNeeded / 10000) * 10000;
1417 StringBuilder stringBuilder;
1418 stringBuilder.appendLiteral("UI DELEGATE APPLICATION CACHE CALLBACK: exceededApplicationCacheOriginQuotaForSecurityOrigin:");
1419 stringBuilder.append(securityOriginToStr(origin));
1420 stringBuilder.appendLiteral(" totalSpaceNeeded:~");
1421 stringBuilder.appendNumber(truncatedSpaceNeeded);
1422 stringBuilder.append('\n');
1423 InjectedBundle::shared().outputText(stringBuilder.toString());
1426 if (InjectedBundle::shared().testRunner()->shouldDisallowIncreaseForApplicationCacheQuota())
1429 // Reset default application cache quota.
1430 WKBundleResetApplicationCacheOriginQuota(InjectedBundle::shared().bundle(), adoptWK(WKSecurityOriginCopyToString(origin)).get());
1433 uint64_t InjectedBundlePage::didExceedDatabaseQuota(WKSecurityOriginRef origin, WKStringRef databaseName, WKStringRef databaseDisplayName, uint64_t currentQuotaBytes, uint64_t currentOriginUsageBytes, uint64_t currentDatabaseUsageBytes, uint64_t expectedUsageBytes)
1435 if (InjectedBundle::shared().testRunner()->shouldDumpDatabaseCallbacks()) {
1436 StringBuilder stringBuilder;
1437 stringBuilder.appendLiteral("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:");
1438 stringBuilder.append(securityOriginToStr(origin));
1439 stringBuilder.appendLiteral(" database:");
1440 stringBuilder.append(toWTFString(databaseName));
1441 stringBuilder.append('\n');
1442 InjectedBundle::shared().outputText(stringBuilder.toString());
1445 uint64_t defaultQuota = 5 * 1024 * 1024;
1446 double testDefaultQuota = InjectedBundle::shared().testRunner()->databaseDefaultQuota();
1447 if (testDefaultQuota >= 0)
1448 defaultQuota = testDefaultQuota;
1450 unsigned long long newQuota = defaultQuota;
1452 double maxQuota = InjectedBundle::shared().testRunner()->databaseMaxQuota();
1453 if (maxQuota >= 0) {
1454 if (defaultQuota < expectedUsageBytes && expectedUsageBytes <= maxQuota) {
1455 newQuota = expectedUsageBytes;
1457 StringBuilder stringBuilder;
1458 stringBuilder.appendLiteral("UI DELEGATE DATABASE CALLBACK: increased quota to ");
1459 stringBuilder.appendNumber(newQuota);
1460 stringBuilder.append('\n');
1461 InjectedBundle::shared().outputText(stringBuilder.toString());
1467 // Editor Client Callbacks
1469 bool InjectedBundlePage::shouldBeginEditing(WKBundlePageRef page, WKBundleRangeHandleRef range, const void* clientInfo)
1471 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldBeginEditing(range);
1474 bool InjectedBundlePage::shouldEndEditing(WKBundlePageRef page, WKBundleRangeHandleRef range, const void* clientInfo)
1476 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldEndEditing(range);
1479 bool InjectedBundlePage::shouldInsertNode(WKBundlePageRef page, WKBundleNodeHandleRef node, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action, const void* clientInfo)
1481 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldInsertNode(node, rangeToReplace, action);
1484 bool InjectedBundlePage::shouldInsertText(WKBundlePageRef page, WKStringRef text, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action, const void* clientInfo)
1486 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldInsertText(text, rangeToReplace, action);
1489 bool InjectedBundlePage::shouldDeleteRange(WKBundlePageRef page, WKBundleRangeHandleRef range, const void* clientInfo)
1491 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldDeleteRange(range);
1494 bool InjectedBundlePage::shouldChangeSelectedRange(WKBundlePageRef page, WKBundleRangeHandleRef fromRange, WKBundleRangeHandleRef toRange, WKAffinityType affinity, bool stillSelecting, const void* clientInfo)
1496 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldChangeSelectedRange(fromRange, toRange, affinity, stillSelecting);
1499 bool InjectedBundlePage::shouldApplyStyle(WKBundlePageRef page, WKBundleCSSStyleDeclarationRef style, WKBundleRangeHandleRef range, const void* clientInfo)
1501 return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldApplyStyle(style, range);
1504 void InjectedBundlePage::didBeginEditing(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo)
1506 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didBeginEditing(notificationName);
1509 void InjectedBundlePage::didEndEditing(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo)
1511 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didEndEditing(notificationName);
1514 void InjectedBundlePage::didChange(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo)
1516 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didChange(notificationName);
1519 void InjectedBundlePage::didChangeSelection(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo)
1521 static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didChangeSelection(notificationName);
1524 bool InjectedBundlePage::shouldBeginEditing(WKBundleRangeHandleRef range)
1526 if (!InjectedBundle::shared().isTestRunning())
1529 if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) {
1530 StringBuilder stringBuilder;
1531 stringBuilder.appendLiteral("EDITING DELEGATE: shouldBeginEditingInDOMRange:");
1532 stringBuilder.append(rangeToStr(m_page, m_world.get(), range));
1533 stringBuilder.append('\n');
1534 InjectedBundle::shared().outputText(stringBuilder.toString());
1536 return InjectedBundle::shared().testRunner()->shouldAllowEditing();
1539 bool InjectedBundlePage::shouldEndEditing(WKBundleRangeHandleRef range)
1541 if (!InjectedBundle::shared().isTestRunning())
1544 if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) {
1545 StringBuilder stringBuilder;
1546 stringBuilder.appendLiteral("EDITING DELEGATE: shouldEndEditingInDOMRange:");
1547 stringBuilder.append(rangeToStr(m_page, m_world.get(), range));
1548 stringBuilder.append('\n');
1549 InjectedBundle::shared().outputText(stringBuilder.toString());
1551 return InjectedBundle::shared().testRunner()->shouldAllowEditing();
1554 bool InjectedBundlePage::shouldInsertNode(WKBundleNodeHandleRef node, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action)
1556 if (!InjectedBundle::shared().isTestRunning())
1559 static const char* insertactionstring[] = {
1560 "WebViewInsertActionTyped",
1561 "WebViewInsertActionPasted",
1562 "WebViewInsertActionDropped",
1565 if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) {
1566 StringBuilder stringBuilder;
1567 stringBuilder.appendLiteral("EDITING DELEGATE: shouldInsertNode:");
1568 stringBuilder.append(dumpPath(m_page, m_world.get(), node));
1569 stringBuilder.appendLiteral(" replacingDOMRange:");
1570 stringBuilder.append(rangeToStr(m_page, m_world.get(), rangeToReplace));
1571 stringBuilder.appendLiteral(" givenAction:");
1572 stringBuilder.append(insertactionstring[action]);
1573 stringBuilder.append('\n');
1574 InjectedBundle::shared().outputText(stringBuilder.toString());
1576 return InjectedBundle::shared().testRunner()->shouldAllowEditing();
1579 bool InjectedBundlePage::shouldInsertText(WKStringRef text, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action)
1581 if (!InjectedBundle::shared().isTestRunning())
1584 static const char *insertactionstring[] = {
1585 "WebViewInsertActionTyped",
1586 "WebViewInsertActionPasted",
1587 "WebViewInsertActionDropped",
1590 if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) {
1591 StringBuilder stringBuilder;
1592 stringBuilder.appendLiteral("EDITING DELEGATE: shouldInsertText:");
1593 stringBuilder.append(toWTFString(text));
1594 stringBuilder.appendLiteral(" replacingDOMRange:");
1595 stringBuilder.append(rangeToStr(m_page, m_world.get(), rangeToReplace));
1596 stringBuilder.appendLiteral(" givenAction:");
1597 stringBuilder.append(insertactionstring[action]);
1598 stringBuilder.append('\n');
1599 InjectedBundle::shared().outputText(stringBuilder.toString());
1601 return InjectedBundle::shared().testRunner()->shouldAllowEditing();
1604 bool InjectedBundlePage::shouldDeleteRange(WKBundleRangeHandleRef range)
1606 if (!InjectedBundle::shared().isTestRunning())
1609 if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) {
1610 StringBuilder stringBuilder;
1611 stringBuilder.appendLiteral("EDITING DELEGATE: shouldDeleteDOMRange:");
1612 stringBuilder.append(rangeToStr(m_page, m_world.get(), range));
1613 stringBuilder.append('\n');
1614 InjectedBundle::shared().outputText(stringBuilder.toString());
1616 return InjectedBundle::shared().testRunner()->shouldAllowEditing();
1619 bool InjectedBundlePage::shouldChangeSelectedRange(WKBundleRangeHandleRef fromRange, WKBundleRangeHandleRef toRange, WKAffinityType affinity, bool stillSelecting)
1621 if (!InjectedBundle::shared().isTestRunning())
1624 static const char *affinitystring[] = {
1625 "NSSelectionAffinityUpstream",
1626 "NSSelectionAffinityDownstream"
1628 static const char *boolstring[] = {
1633 if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) {
1634 StringBuilder stringBuilder;
1635 stringBuilder.appendLiteral("EDITING DELEGATE: shouldChangeSelectedDOMRange:");
1636 stringBuilder.append(rangeToStr(m_page, m_world.get(), fromRange));
1637 stringBuilder.appendLiteral(" toDOMRange:");
1638 stringBuilder.append(rangeToStr(m_page, m_world.get(), toRange));
1639 stringBuilder.appendLiteral(" affinity:");
1640 stringBuilder.append(affinitystring[affinity]);
1641 stringBuilder.appendLiteral(" stillSelecting:");
1642 stringBuilder.append(boolstring[stillSelecting]);
1643 stringBuilder.append('\n');
1644 InjectedBundle::shared().outputText(stringBuilder.toString());
1646 return InjectedBundle::shared().testRunner()->shouldAllowEditing();
1649 bool InjectedBundlePage::shouldApplyStyle(WKBundleCSSStyleDeclarationRef style, WKBundleRangeHandleRef range)
1651 if (!InjectedBundle::shared().isTestRunning())
1654 if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) {
1655 StringBuilder stringBuilder;
1656 stringBuilder.appendLiteral("EDITING DELEGATE: shouldApplyStyle:");
1657 stringBuilder.append(styleDecToStr(style));
1658 stringBuilder.appendLiteral(" toElementsInDOMRange:");
1659 stringBuilder.append(rangeToStr(m_page, m_world.get(), range));
1660 stringBuilder.append('\n');
1661 InjectedBundle::shared().outputText(stringBuilder.toString());
1663 return InjectedBundle::shared().testRunner()->shouldAllowEditing();
1666 void InjectedBundlePage::didBeginEditing(WKStringRef notificationName)
1668 if (!InjectedBundle::shared().isTestRunning())
1670 if (!InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks())
1673 StringBuilder stringBuilder;
1674 stringBuilder.appendLiteral("EDITING DELEGATE: webViewDidBeginEditing:");
1675 stringBuilder.append(toWTFString(notificationName));
1676 stringBuilder.append('\n');
1677 InjectedBundle::shared().outputText(stringBuilder.toString());
1680 void InjectedBundlePage::didEndEditing(WKStringRef notificationName)
1682 if (!InjectedBundle::shared().isTestRunning())
1684 if (!InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks())
1687 StringBuilder stringBuilder;
1688 stringBuilder.appendLiteral("EDITING DELEGATE: webViewDidEndEditing:");
1689 stringBuilder.append(toWTFString(notificationName));
1690 stringBuilder.append('\n');
1691 InjectedBundle::shared().outputText(stringBuilder.toString());
1694 void InjectedBundlePage::didChange(WKStringRef notificationName)
1696 if (!InjectedBundle::shared().isTestRunning())
1698 if (!InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks())
1701 StringBuilder stringBuilder;
1702 stringBuilder.appendLiteral("EDITING DELEGATE: webViewDidChange:");
1703 stringBuilder.append(toWTFString(notificationName));
1704 stringBuilder.append('\n');
1705 InjectedBundle::shared().outputText(stringBuilder.toString());
1708 void InjectedBundlePage::didChangeSelection(WKStringRef notificationName)
1710 if (!InjectedBundle::shared().isTestRunning())
1712 if (!InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks())
1715 StringBuilder stringBuilder;
1716 stringBuilder.appendLiteral("EDITING DELEGATE: webViewDidChangeSelection:");
1717 stringBuilder.append(toWTFString(notificationName));
1718 stringBuilder.append('\n');
1719 InjectedBundle::shared().outputText(stringBuilder.toString());
1722 #if ENABLE(FULLSCREEN_API)
1723 bool InjectedBundlePage::supportsFullScreen(WKBundlePageRef pageRef, WKFullScreenKeyboardRequestType requestType)
1725 if (InjectedBundle::shared().testRunner()->shouldDumpFullScreenCallbacks())
1726 InjectedBundle::shared().outputText("supportsFullScreen() == true\n");
1730 void InjectedBundlePage::enterFullScreenForElement(WKBundlePageRef pageRef, WKBundleNodeHandleRef elementRef)
1732 if (InjectedBundle::shared().testRunner()->shouldDumpFullScreenCallbacks())
1733 InjectedBundle::shared().outputText("enterFullScreenForElement()\n");
1735 if (!InjectedBundle::shared().testRunner()->hasCustomFullScreenBehavior()) {
1736 WKBundlePageWillEnterFullScreen(pageRef);
1737 WKBundlePageDidEnterFullScreen(pageRef);
1741 void InjectedBundlePage::exitFullScreenForElement(WKBundlePageRef pageRef, WKBundleNodeHandleRef elementRef)
1743 if (InjectedBundle::shared().testRunner()->shouldDumpFullScreenCallbacks())
1744 InjectedBundle::shared().outputText("exitFullScreenForElement()\n");
1746 if (!InjectedBundle::shared().testRunner()->hasCustomFullScreenBehavior()) {
1747 WKBundlePageWillExitFullScreen(pageRef);
1748 WKBundlePageDidExitFullScreen(pageRef);
1752 void InjectedBundlePage::beganEnterFullScreen(WKBundlePageRef, WKRect, WKRect)
1754 if (InjectedBundle::shared().testRunner()->shouldDumpFullScreenCallbacks())
1755 InjectedBundle::shared().outputText("beganEnterFullScreen()\n");
1758 void InjectedBundlePage::beganExitFullScreen(WKBundlePageRef, WKRect, WKRect)
1760 if (InjectedBundle::shared().testRunner()->shouldDumpFullScreenCallbacks())
1761 InjectedBundle::shared().outputText("beganExitFullScreen()\n");
1764 void InjectedBundlePage::closeFullScreen(WKBundlePageRef pageRef)
1766 if (InjectedBundle::shared().testRunner()->shouldDumpFullScreenCallbacks())
1767 InjectedBundle::shared().outputText("closeFullScreen()\n");
1769 if (!InjectedBundle::shared().testRunner()->hasCustomFullScreenBehavior()) {
1770 WKBundlePageWillExitFullScreen(pageRef);
1771 WKBundlePageDidExitFullScreen(pageRef);
1776 static bool compareByTargetName(WKBundleBackForwardListItemRef item1, WKBundleBackForwardListItemRef item2)
1778 return toSTD(adoptWK(WKBundleBackForwardListItemCopyTarget(item1))) < toSTD(adoptWK(WKBundleBackForwardListItemCopyTarget(item2)));
1781 static void dumpBackForwardListItem(WKBundleBackForwardListItemRef item, unsigned indent, bool isCurrentItem, StringBuilder& stringBuilder)
1783 unsigned column = 0;
1784 if (isCurrentItem) {
1785 stringBuilder.appendLiteral("curr->");
1788 for (unsigned i = column; i < indent; i++)
1789 stringBuilder.append(' ');
1791 WTF::String url = toWTFString(adoptWK(WKURLCopyString(adoptWK(WKBundleBackForwardListItemCopyURL(item)).get())));
1792 if (hasPrefix(url, "file:")) {
1793 WTF::String directoryName = "/LayoutTests/";
1794 size_t start = url.find(directoryName);
1795 if (start == WTF::notFound)
1798 start += directoryName.length();
1799 stringBuilder.appendLiteral("(file test):");
1800 stringBuilder.append(url.substring(start));
1802 stringBuilder.append(url);
1804 WTF::String target = toWTFString(adoptWK(WKBundleBackForwardListItemCopyTarget(item)));
1805 if (target.length()) {
1806 stringBuilder.appendLiteral(" (in frame \"");
1807 stringBuilder.append(target);
1808 stringBuilder.appendLiteral("\")");
1811 // FIXME: Need WKBackForwardListItemIsTargetItem.
1812 if (WKBundleBackForwardListItemIsTargetItem(item))
1813 stringBuilder.appendLiteral(" **nav target**");
1815 stringBuilder.append('\n');
1817 if (WKRetainPtr<WKArrayRef> kids = adoptWK(WKBundleBackForwardListItemCopyChildren(item))) {
1818 // Sort to eliminate arbitrary result ordering which defeats reproducible testing.
1819 size_t size = WKArrayGetSize(kids.get());
1820 Vector<WKBundleBackForwardListItemRef> sortedKids(size);
1821 for (size_t i = 0; i < size; ++i)
1822 sortedKids[i] = static_cast<WKBundleBackForwardListItemRef>(WKArrayGetItemAtIndex(kids.get(), i));
1823 stable_sort(sortedKids.begin(), sortedKids.end(), compareByTargetName);
1824 for (size_t i = 0; i < size; ++i)
1825 dumpBackForwardListItem(sortedKids[i], indent + 4, false, stringBuilder);
1829 void InjectedBundlePage::dumpBackForwardList(StringBuilder& stringBuilder)
1831 stringBuilder.appendLiteral("\n============== Back Forward List ==============\n");
1833 WKBundleBackForwardListRef list = WKBundlePageGetBackForwardList(m_page);
1835 // Print out all items in the list after m_previousTestBackForwardListItem.
1836 // Gather items from the end of the list, then print them out from oldest to newest.
1837 Vector<WKRetainPtr<WKBundleBackForwardListItemRef> > itemsToPrint;
1838 for (unsigned i = WKBundleBackForwardListGetForwardListCount(list); i; --i) {
1839 WKRetainPtr<WKBundleBackForwardListItemRef> item = adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, i));
1840 // Something is wrong if the item from the last test is in the forward part of the list.
1841 ASSERT(!WKBundleBackForwardListItemIsSame(item.get(), m_previousTestBackForwardListItem.get()));
1842 itemsToPrint.append(item);
1845 ASSERT(!WKBundleBackForwardListItemIsSame(adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, 0)).get(), m_previousTestBackForwardListItem.get()));
1847 itemsToPrint.append(adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, 0)));
1849 int currentItemIndex = itemsToPrint.size() - 1;
1851 int backListCount = WKBundleBackForwardListGetBackListCount(list);
1852 for (int i = -1; i >= -backListCount; --i) {
1853 WKRetainPtr<WKBundleBackForwardListItemRef> item = adoptWK(WKBundleBackForwardListCopyItemAtIndex(list, i));
1854 if (WKBundleBackForwardListItemIsSame(item.get(), m_previousTestBackForwardListItem.get()))
1856 itemsToPrint.append(item);
1859 for (int i = itemsToPrint.size() - 1; i >= 0; i--)
1860 dumpBackForwardListItem(itemsToPrint[i].get(), 8, i == currentItemIndex, stringBuilder);
1862 stringBuilder.appendLiteral("===============================================\n");
1865 #if !PLATFORM(COCOA)
1866 void InjectedBundlePage::platformDidStartProvisionalLoadForFrame(WKBundleFrameRef)
1871 void InjectedBundlePage::frameDidChangeLocation(WKBundleFrameRef frame, bool shouldDump)
1873 if (frame != InjectedBundle::shared().topLoadingFrame())
1876 InjectedBundle::shared().setTopLoadingFrame(0);
1878 if (InjectedBundle::shared().testRunner()->waitToDump())
1881 if (InjectedBundle::shared().shouldProcessWorkQueue()) {
1882 InjectedBundle::shared().processWorkQueue();
1887 InjectedBundle::shared().page()->dump();
1889 InjectedBundle::shared().done();