WebKitTestRunner needs support for setHandlesAuthenticationChallenges
[WebKit-https.git] / Tools / WebKitTestRunner / TestInvocation.cpp
1 /*
2  * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved.
3  * Copyright (C) 2012 Intel Corporation. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "TestInvocation.h"
29
30 #include "PlatformWebView.h"
31 #include "StringFunctions.h"
32 #include "TestController.h"
33 #include <climits>
34 #include <cstdio>
35 #include <WebKit2/WKContextPrivate.h>
36 #include <WebKit2/WKData.h>
37 #include <WebKit2/WKDictionary.h>
38 #include <WebKit2/WKInspector.h>
39 #include <WebKit2/WKRetainPtr.h>
40 #include <wtf/OwnArrayPtr.h>
41 #include <wtf/PassOwnArrayPtr.h>
42 #include <wtf/PassOwnPtr.h>
43 #include <wtf/text/CString.h>
44
45 #if PLATFORM(MAC)
46 #include <WebKit2/WKPagePrivateMac.h>
47 #endif
48
49 #if OS(WINDOWS)
50 #include <direct.h> // For _getcwd.
51 #define getcwd _getcwd // MSDN says getcwd is deprecated.
52 #define PATH_MAX _MAX_PATH
53 #else
54 #include <unistd.h> // For getcwd.
55 #endif
56
57 using namespace WebKit;
58 using namespace std;
59
60 namespace WTR {
61
62 static WKURLRef createWKURL(const char* pathOrURL)
63 {
64     if (strstr(pathOrURL, "http://") || strstr(pathOrURL, "https://") || strstr(pathOrURL, "file://"))
65         return WKURLCreateWithUTF8CString(pathOrURL);
66
67     // Creating from filesytem path.
68     size_t length = strlen(pathOrURL);
69     if (!length)
70         return 0;
71
72 #if OS(WINDOWS)
73     const char separator = '\\';
74     bool isAbsolutePath = length >= 3 && pathOrURL[1] == ':' && pathOrURL[2] == separator;
75     // FIXME: Remove the "localhost/" suffix once <http://webkit.org/b/55683> is fixed.
76     const char* filePrefix = "file://localhost/";
77 #else
78     const char separator = '/';
79     bool isAbsolutePath = pathOrURL[0] == separator;
80     const char* filePrefix = "file://";
81 #endif
82     static const size_t prefixLength = strlen(filePrefix);
83
84     OwnArrayPtr<char> buffer;
85     if (isAbsolutePath) {
86         buffer = adoptArrayPtr(new char[prefixLength + length + 1]);
87         strcpy(buffer.get(), filePrefix);
88         strcpy(buffer.get() + prefixLength, pathOrURL);
89     } else {
90         buffer = adoptArrayPtr(new char[prefixLength + PATH_MAX + length + 2]); // 1 for the separator
91         strcpy(buffer.get(), filePrefix);
92         if (!getcwd(buffer.get() + prefixLength, PATH_MAX))
93             return 0;
94         size_t numCharacters = strlen(buffer.get());
95         buffer[numCharacters] = separator;
96         strcpy(buffer.get() + numCharacters + 1, pathOrURL);
97     }
98
99     return WKURLCreateWithUTF8CString(buffer.get());
100 }
101
102 TestInvocation::TestInvocation(const std::string& pathOrURL)
103     : m_url(AdoptWK, createWKURL(pathOrURL.c_str()))
104     , m_pathOrURL(pathOrURL)
105     , m_dumpPixels(false)
106     , m_gotInitialResponse(false)
107     , m_gotFinalMessage(false)
108     , m_gotRepaint(false)
109     , m_error(false)
110     , m_webProcessIsUnresponsive(false)
111 {
112 }
113
114 TestInvocation::~TestInvocation()
115 {
116 }
117
118 void TestInvocation::setIsPixelTest(const std::string& expectedPixelHash)
119 {
120     m_dumpPixels = true;
121     m_expectedPixelHash = expectedPixelHash;
122 }
123
124 static const unsigned w3cSVGWidth = 480;
125 static const unsigned w3cSVGHeight = 360;
126 static const unsigned normalWidth = 800;
127 static const unsigned normalHeight = 600;
128
129 static void sizeWebViewForCurrentTest(const char* pathOrURL)
130 {
131     bool isSVGW3CTest = strstr(pathOrURL, "svg/W3C-SVG-1.1") || strstr(pathOrURL, "svg\\W3C-SVG-1.1");
132
133     if (isSVGW3CTest)
134         TestController::shared().mainWebView()->resizeTo(w3cSVGWidth, w3cSVGHeight);
135     else
136         TestController::shared().mainWebView()->resizeTo(normalWidth, normalHeight);
137 }
138 static bool shouldLogFrameLoadDelegates(const char* pathOrURL)
139 {
140     return strstr(pathOrURL, "loading/");
141 }
142
143 #if ENABLE(INSPECTOR)
144 static bool shouldOpenWebInspector(const char* pathOrURL)
145 {
146     return strstr(pathOrURL, "inspector/") || strstr(pathOrURL, "inspector\\");
147 }
148 #endif
149
150 #if PLATFORM(MAC)
151 static bool shouldUseTiledDrawing(const char* pathOrURL)
152 {
153     return strstr(pathOrURL, "tiled-drawing/") || strstr(pathOrURL, "tiled-drawing\\");
154 }
155 #endif
156
157 static void updateTiledDrawingForCurrentTest(const char* pathOrURL)
158 {
159 #if PLATFORM(MAC)
160     WKRetainPtr<WKMutableDictionaryRef> viewOptions = adoptWK(WKMutableDictionaryCreate());
161     WKRetainPtr<WKStringRef> useTiledDrawingKey = adoptWK(WKStringCreateWithUTF8CString("TiledDrawing"));
162     WKRetainPtr<WKBooleanRef> useTiledDrawingValue = adoptWK(WKBooleanCreate(shouldUseTiledDrawing(pathOrURL)));
163     WKDictionaryAddItem(viewOptions.get(), useTiledDrawingKey.get(), useTiledDrawingValue.get());
164
165     TestController::shared().ensureViewSupportsOptions(viewOptions.get());
166 #else
167     UNUSED_PARAM(pathOrURL);
168 #endif
169 }
170
171 #if ENABLE(CSS_DEVICE_ADAPTATION)
172 static bool shouldUseFixedLayout(const char* pathOrURL)
173 {
174     return strstr(pathOrURL, "device-adapt/") || strstr(pathOrURL, "device-adapt\\");
175 }
176 #endif
177
178 static void updateLayoutType(const char* pathOrURL)
179 {
180 #if ENABLE(CSS_DEVICE_ADAPTATION)
181     WKRetainPtr<WKMutableDictionaryRef> viewOptions = adoptWK(WKMutableDictionaryCreate());
182     WKRetainPtr<WKStringRef> useFixedLayoutKey = adoptWK(WKStringCreateWithUTF8CString("UseFixedLayout"));
183     WKRetainPtr<WKBooleanRef> useFixedLayoutValue = adoptWK(WKBooleanCreate(shouldUseFixedLayout(pathOrURL)));
184     WKDictionaryAddItem(viewOptions.get(), useFixedLayoutKey.get(), useFixedLayoutValue.get());
185
186     TestController::shared().ensureViewSupportsOptions(viewOptions.get());
187 #else
188     UNUSED_PARAM(pathOrURL);
189 #endif
190 }
191
192 void TestInvocation::invoke()
193 {
194     sizeWebViewForCurrentTest(m_pathOrURL.c_str());
195     updateLayoutType(m_pathOrURL.c_str());
196     updateTiledDrawingForCurrentTest(m_pathOrURL.c_str());
197
198     m_textOutput.clear();
199
200     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("BeginTest"));
201     WKRetainPtr<WKMutableDictionaryRef> beginTestMessageBody = adoptWK(WKMutableDictionaryCreate());
202
203     WKRetainPtr<WKStringRef> dumpFrameLoadDelegatesKey = adoptWK(WKStringCreateWithUTF8CString("DumpFrameLoadDelegates"));
204     WKRetainPtr<WKBooleanRef> dumpFrameLoadDelegatesValue = adoptWK(WKBooleanCreate(shouldLogFrameLoadDelegates(m_pathOrURL.c_str())));
205     WKDictionaryAddItem(beginTestMessageBody.get(), dumpFrameLoadDelegatesKey.get(), dumpFrameLoadDelegatesValue.get());
206
207     WKRetainPtr<WKStringRef> dumpPixelsKey = adoptWK(WKStringCreateWithUTF8CString("DumpPixels"));
208     WKRetainPtr<WKBooleanRef> dumpPixelsValue = adoptWK(WKBooleanCreate(m_dumpPixels));
209     WKDictionaryAddItem(beginTestMessageBody.get(), dumpPixelsKey.get(), dumpPixelsValue.get());
210
211     WKRetainPtr<WKStringRef> useWaitToDumpWatchdogTimerKey = adoptWK(WKStringCreateWithUTF8CString("UseWaitToDumpWatchdogTimer"));
212     WKRetainPtr<WKBooleanRef> useWaitToDumpWatchdogTimerValue = adoptWK(WKBooleanCreate(TestController::shared().useWaitToDumpWatchdogTimer()));
213     WKDictionaryAddItem(beginTestMessageBody.get(), useWaitToDumpWatchdogTimerKey.get(), useWaitToDumpWatchdogTimerValue.get());
214
215     WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), beginTestMessageBody.get());
216
217     TestController::shared().runUntil(m_gotInitialResponse, TestController::ShortTimeout);
218     if (!m_gotInitialResponse) {
219         m_errorMessage = "Timed out waiting for initial response from web process\n";
220         m_webProcessIsUnresponsive = true;
221         goto end;
222     }
223     if (m_error)
224         goto end;
225
226 #if ENABLE(INSPECTOR)
227     if (shouldOpenWebInspector(m_pathOrURL.c_str()))
228         WKInspectorShow(WKPageGetInspector(TestController::shared().mainWebView()->page()));
229 #endif // ENABLE(INSPECTOR)        
230
231     WKPageLoadURL(TestController::shared().mainWebView()->page(), m_url.get());
232
233     TestController::shared().runUntil(m_gotFinalMessage, TestController::shared().useWaitToDumpWatchdogTimer() ? TestController::LongTimeout : TestController::NoTimeout);
234     if (!m_gotFinalMessage) {
235         m_errorMessage = "Timed out waiting for final message from web process\n";
236         m_webProcessIsUnresponsive = true;
237         goto end;
238     }
239     if (m_error)
240         goto end;
241
242     dumpResults();
243
244 end:
245 #if ENABLE(INSPECTOR)
246     if (m_gotInitialResponse)
247         WKInspectorClose(WKPageGetInspector(TestController::shared().mainWebView()->page()));
248 #endif // ENABLE(INSPECTOR)
249
250     if (m_webProcessIsUnresponsive)
251         dumpWebProcessUnresponsiveness();
252     else if (!TestController::shared().resetStateToConsistentValues()) {
253         m_errorMessage = "Timed out loading about:blank before the next test";
254         dumpWebProcessUnresponsiveness();
255     }
256 }
257
258 void TestInvocation::dumpWebProcessUnresponsiveness()
259 {
260     const char* errorMessageToStderr = 0;
261 #if PLATFORM(MAC)
262     char buffer[64];
263     pid_t pid = WKPageGetProcessIdentifier(TestController::shared().mainWebView()->page());
264     sprintf(buffer, "#PROCESS UNRESPONSIVE - WebProcess (pid %ld)\n", static_cast<long>(pid));
265     errorMessageToStderr = buffer;
266 #else
267     errorMessageToStderr = "#PROCESS UNRESPONSIVE - WebProcess";
268 #endif
269
270     dump(m_errorMessage.c_str(), errorMessageToStderr, true);
271 }
272
273 void TestInvocation::dump(const char* textToStdout, const char* textToStderr, bool seenError)
274 {
275     printf("Content-Type: text/plain\n");
276     if (textToStdout)
277         fputs(textToStdout, stdout);
278     if (textToStderr)
279         fputs(textToStderr, stderr);
280
281     fputs("#EOF\n", stdout);
282     fputs("#EOF\n", stderr);
283     if (seenError)
284         fputs("#EOF\n", stdout);
285     fflush(stdout);
286     fflush(stderr);
287 }
288
289 void TestInvocation::dumpResults()
290 {
291     if (m_textOutput.length() || !m_audioResult)
292         dump(m_textOutput.toString().utf8().data());
293     else
294         dumpAudio(m_audioResult.get());
295
296     if (m_dumpPixels && m_pixelResult)
297         dumpPixelsAndCompareWithExpected(m_pixelResult.get(), m_repaintRects.get());
298
299     fputs("#EOF\n", stdout);
300     fflush(stdout);
301     fflush(stderr);
302 }
303
304 void TestInvocation::dumpAudio(WKDataRef audioData)
305 {
306     size_t length = WKDataGetSize(audioData);
307     if (!length)
308         return;
309
310     const unsigned char* data = WKDataGetBytes(audioData);
311
312     printf("Content-Type: audio/wav\n");
313     printf("Content-Length: %lu\n", static_cast<unsigned long>(length));
314
315     const size_t bytesToWriteInOneChunk = 1 << 15;
316     size_t dataRemainingToWrite = length;
317     while (dataRemainingToWrite) {
318         size_t bytesToWriteInThisChunk = std::min(dataRemainingToWrite, bytesToWriteInOneChunk);
319         size_t bytesWritten = fwrite(data, 1, bytesToWriteInThisChunk, stdout);
320         if (bytesWritten != bytesToWriteInThisChunk)
321             break;
322         dataRemainingToWrite -= bytesWritten;
323         data += bytesWritten;
324     }
325     printf("#EOF\n");
326     fprintf(stderr, "#EOF\n");
327 }
328
329 bool TestInvocation::compareActualHashToExpectedAndDumpResults(const char actualHash[33])
330 {
331     // Compute the hash of the bitmap context pixels
332     fprintf(stdout, "\nActualHash: %s\n", actualHash);
333
334     if (!m_expectedPixelHash.length())
335         return false;
336
337     ASSERT(m_expectedPixelHash.length() == 32);
338     fprintf(stdout, "\nExpectedHash: %s\n", m_expectedPixelHash.c_str());
339
340     // FIXME: Do case insensitive compare.
341     return m_expectedPixelHash == actualHash;
342 }
343
344 void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
345 {
346     if (WKStringIsEqualToUTF8CString(messageName, "Error")) {
347         // Set all states to true to stop spinning the runloop.
348         m_gotInitialResponse = true;
349         m_gotFinalMessage = true;
350         m_error = true;
351         m_errorMessage = "FAIL\n";
352         TestController::shared().notifyDone();
353         return;
354     }
355
356     if (WKStringIsEqualToUTF8CString(messageName, "Ack")) {
357         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
358         WKStringRef messageBodyString = static_cast<WKStringRef>(messageBody);
359         if (WKStringIsEqualToUTF8CString(messageBodyString, "BeginTest")) {
360             m_gotInitialResponse = true;
361             TestController::shared().notifyDone();
362             return;
363         }
364
365         ASSERT_NOT_REACHED();
366     }
367
368     if (WKStringIsEqualToUTF8CString(messageName, "Done")) {
369         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
370         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
371
372         WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult"));
373         m_pixelResult = static_cast<WKImageRef>(WKDictionaryGetItemForKey(messageBodyDictionary, pixelResultKey.get()));
374         ASSERT(!m_pixelResult || m_dumpPixels);
375
376         WKRetainPtr<WKStringRef> repaintRectsKey = adoptWK(WKStringCreateWithUTF8CString("RepaintRects"));
377         m_repaintRects = static_cast<WKArrayRef>(WKDictionaryGetItemForKey(messageBodyDictionary, repaintRectsKey.get()));
378
379         WKRetainPtr<WKStringRef> audioResultKey =  adoptWK(WKStringCreateWithUTF8CString("AudioResult"));
380         m_audioResult = static_cast<WKDataRef>(WKDictionaryGetItemForKey(messageBodyDictionary, audioResultKey.get()));
381
382         m_gotFinalMessage = true;
383         TestController::shared().notifyDone();
384         return;
385     }
386
387     if (WKStringIsEqualToUTF8CString(messageName, "TextOutput")) {
388         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
389         WKStringRef textOutput = static_cast<WKStringRef>(messageBody);
390         m_textOutput.append(toWTFString(textOutput));
391         return;
392     }
393
394     if (WKStringIsEqualToUTF8CString(messageName, "BeforeUnloadReturnValue")) {
395         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
396         WKBooleanRef beforeUnloadReturnValue = static_cast<WKBooleanRef>(messageBody);
397         TestController::shared().setBeforeUnloadReturnValue(WKBooleanGetValue(beforeUnloadReturnValue));
398         return;
399     }
400     
401     if (WKStringIsEqualToUTF8CString(messageName, "AddChromeInputField")) {
402         TestController::shared().mainWebView()->addChromeInputField();
403         WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallAddChromeInputFieldCallback"));
404         WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
405         return;
406     }
407
408     if (WKStringIsEqualToUTF8CString(messageName, "RemoveChromeInputField")) {
409         TestController::shared().mainWebView()->removeChromeInputField();
410         WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallRemoveChromeInputFieldCallback"));
411         WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
412         return;
413     }
414     
415     if (WKStringIsEqualToUTF8CString(messageName, "FocusWebView")) {
416         TestController::shared().mainWebView()->makeWebViewFirstResponder();
417         WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallFocusWebViewCallback"));
418         WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
419         return;
420     }
421
422     if (WKStringIsEqualToUTF8CString(messageName, "SetBackingScaleFactor")) {
423         ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID());
424         double backingScaleFactor = WKDoubleGetValue(static_cast<WKDoubleRef>(messageBody));
425         WKPageSetCustomBackingScaleFactor(TestController::shared().mainWebView()->page(), backingScaleFactor);
426
427         WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallSetBackingScaleFactorCallback"));
428         WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
429         return;
430     }
431
432     if (WKStringIsEqualToUTF8CString(messageName, "SimulateWebNotificationClick")) {
433         ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
434         uint64_t notificationID = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
435         TestController::shared().simulateWebNotificationClick(notificationID);
436         return;
437     }
438
439     if (WKStringIsEqualToUTF8CString(messageName, "SetGeolocationPermission")) {
440         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
441         WKBooleanRef enabledWK = static_cast<WKBooleanRef>(messageBody);
442         TestController::shared().setGeolocationPermission(WKBooleanGetValue(enabledWK));
443         return;
444     }
445
446     if (WKStringIsEqualToUTF8CString(messageName, "SetMockGeolocationPosition")) {
447         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
448         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
449
450         WKRetainPtr<WKStringRef> latitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("latitude"));
451         WKDoubleRef latitudeWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, latitudeKeyWK.get()));
452         double latitude = WKDoubleGetValue(latitudeWK);
453
454         WKRetainPtr<WKStringRef> longitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("longitude"));
455         WKDoubleRef longitudeWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, longitudeKeyWK.get()));
456         double longitude = WKDoubleGetValue(longitudeWK);
457
458         WKRetainPtr<WKStringRef> accuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("accuracy"));
459         WKDoubleRef accuracyWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, accuracyKeyWK.get()));
460         double accuracy = WKDoubleGetValue(accuracyWK);
461
462         WKRetainPtr<WKStringRef> providesAltitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesAltitude"));
463         WKBooleanRef providesAltitudeWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesAltitudeKeyWK.get()));
464         bool providesAltitude = WKBooleanGetValue(providesAltitudeWK);
465
466         WKRetainPtr<WKStringRef> altitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("altitude"));
467         WKDoubleRef altitudeWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, altitudeKeyWK.get()));
468         double altitude = WKDoubleGetValue(altitudeWK);
469
470         WKRetainPtr<WKStringRef> providesAltitudeAccuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesAltitudeAccuracy"));
471         WKBooleanRef providesAltitudeAccuracyWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesAltitudeAccuracyKeyWK.get()));
472         bool providesAltitudeAccuracy = WKBooleanGetValue(providesAltitudeAccuracyWK);
473
474         WKRetainPtr<WKStringRef> altitudeAccuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("altitudeAccuracy"));
475         WKDoubleRef altitudeAccuracyWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, altitudeAccuracyKeyWK.get()));
476         double altitudeAccuracy = WKDoubleGetValue(altitudeAccuracyWK);
477
478         WKRetainPtr<WKStringRef> providesHeadingKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesHeading"));
479         WKBooleanRef providesHeadingWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesHeadingKeyWK.get()));
480         bool providesHeading = WKBooleanGetValue(providesHeadingWK);
481
482         WKRetainPtr<WKStringRef> headingKeyWK(AdoptWK, WKStringCreateWithUTF8CString("heading"));
483         WKDoubleRef headingWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, headingKeyWK.get()));
484         double heading = WKDoubleGetValue(headingWK);
485
486         WKRetainPtr<WKStringRef> providesSpeedKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesSpeed"));
487         WKBooleanRef providesSpeedWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesSpeedKeyWK.get()));
488         bool providesSpeed = WKBooleanGetValue(providesSpeedWK);
489
490         WKRetainPtr<WKStringRef> speedKeyWK(AdoptWK, WKStringCreateWithUTF8CString("speed"));
491         WKDoubleRef speedWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, speedKeyWK.get()));
492         double speed = WKDoubleGetValue(speedWK);
493
494         TestController::shared().setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed);
495         return;
496     }
497
498     if (WKStringIsEqualToUTF8CString(messageName, "SetMockGeolocationPositionUnavailableError")) {
499         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
500         WKStringRef errorMessage = static_cast<WKStringRef>(messageBody);
501         TestController::shared().setMockGeolocationPositionUnavailableError(errorMessage);
502         return;
503     }
504
505     if (WKStringIsEqualToUTF8CString(messageName, "SetCustomPolicyDelegate")) {
506         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
507         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
508
509         WKRetainPtr<WKStringRef> enabledKeyWK(AdoptWK, WKStringCreateWithUTF8CString("enabled"));
510         WKBooleanRef enabledWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, enabledKeyWK.get()));
511         bool enabled = WKBooleanGetValue(enabledWK);
512
513         WKRetainPtr<WKStringRef> permissiveKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permissive"));
514         WKBooleanRef permissiveWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, permissiveKeyWK.get()));
515         bool permissive = WKBooleanGetValue(permissiveWK);
516
517         TestController::shared().setCustomPolicyDelegate(enabled, permissive);
518         return;
519     }
520
521     if (WKStringIsEqualToUTF8CString(messageName, "ProcessWorkQueue")) {
522         if (TestController::shared().workQueueManager().processWorkQueue()) {
523             WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("WorkQueueProcessedCallback"));
524             WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
525         }
526         return;
527     }
528
529     if (WKStringIsEqualToUTF8CString(messageName, "QueueBackNavigation")) {
530         ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
531         uint64_t stepCount = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
532         TestController::shared().workQueueManager().queueBackNavigation(stepCount);
533         return;
534     }
535
536     if (WKStringIsEqualToUTF8CString(messageName, "QueueForwardNavigation")) {
537         ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
538         uint64_t stepCount = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
539         TestController::shared().workQueueManager().queueForwardNavigation(stepCount);
540         return;
541     }
542
543     if (WKStringIsEqualToUTF8CString(messageName, "QueueLoad")) {
544         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
545         WKDictionaryRef loadDataDictionary = static_cast<WKDictionaryRef>(messageBody);
546
547         WKRetainPtr<WKStringRef> urlKey(AdoptWK, WKStringCreateWithUTF8CString("url"));
548         WKStringRef urlWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, urlKey.get()));
549
550         WKRetainPtr<WKStringRef> targetKey(AdoptWK, WKStringCreateWithUTF8CString("target"));
551         WKStringRef targetWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, targetKey.get()));
552
553         TestController::shared().workQueueManager().queueLoad(toWTFString(urlWK), toWTFString(targetWK));
554         return;
555     }
556
557     if (WKStringIsEqualToUTF8CString(messageName, "QueueLoadHTMLString")) {
558         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
559         WKDictionaryRef loadDataDictionary = static_cast<WKDictionaryRef>(messageBody);
560
561         WKRetainPtr<WKStringRef> contentKey(AdoptWK, WKStringCreateWithUTF8CString("content"));
562         WKStringRef contentWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, contentKey.get()));
563
564         WKRetainPtr<WKStringRef> baseURLKey(AdoptWK, WKStringCreateWithUTF8CString("baseURL"));
565         WKStringRef baseURLWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, baseURLKey.get()));
566
567         WKRetainPtr<WKStringRef> unreachableURLKey(AdoptWK, WKStringCreateWithUTF8CString("unreachableURL"));
568         WKStringRef unreachableURLWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, unreachableURLKey.get()));
569
570         TestController::shared().workQueueManager().queueLoadHTMLString(toWTFString(contentWK), baseURLWK ? toWTFString(baseURLWK) : String(), unreachableURLWK ? toWTFString(unreachableURLWK) : String());
571         return;
572     }
573
574     if (WKStringIsEqualToUTF8CString(messageName, "QueueReload")) {
575         TestController::shared().workQueueManager().queueReload();
576         return;
577     }
578
579     if (WKStringIsEqualToUTF8CString(messageName, "QueueLoadingScript")) {
580         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
581         WKStringRef script = static_cast<WKStringRef>(messageBody);
582         TestController::shared().workQueueManager().queueLoadingScript(toWTFString(script));
583         return;
584     }
585
586     if (WKStringIsEqualToUTF8CString(messageName, "QueueNonLoadingScript")) {
587         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
588         WKStringRef script = static_cast<WKStringRef>(messageBody);
589         TestController::shared().workQueueManager().queueNonLoadingScript(toWTFString(script));
590         return;
591     }
592
593     if (WKStringIsEqualToUTF8CString(messageName, "SetHandlesAuthenticationChallenge")) {
594         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
595         WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
596         TestController::shared().setHandlesAuthenticationChallenges(WKBooleanGetValue(value));
597         return;
598     }
599
600     if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationUsername")) {
601         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
602         WKStringRef username = static_cast<WKStringRef>(messageBody);
603         TestController::shared().setAuthenticationUsername(toWTFString(username));
604         return;
605     }
606
607     if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationPassword")) {
608         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
609         WKStringRef password = static_cast<WKStringRef>(messageBody);
610         TestController::shared().setAuthenticationPassword(toWTFString(password));
611         return;
612     }
613
614     ASSERT_NOT_REACHED();
615 }
616
617 WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
618 {
619     if (WKStringIsEqualToUTF8CString(messageName, "SetWindowIsKey")) {
620         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
621         WKBooleanRef isKeyValue = static_cast<WKBooleanRef>(messageBody);
622         TestController::shared().mainWebView()->setWindowIsKey(WKBooleanGetValue(isKeyValue));
623         return 0;
624     }
625
626     if (WKStringIsEqualToUTF8CString(messageName, "IsWorkQueueEmpty")) {
627         bool isEmpty = TestController::shared().workQueueManager().isWorkQueueEmpty();
628         WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(isEmpty));
629         return result;
630     }
631
632     ASSERT_NOT_REACHED();
633     return 0;
634 }
635
636 void TestInvocation::outputText(const WTF::String& text)
637 {
638     m_textOutput.append(text);
639 }
640
641 } // namespace WTR