~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions
 
6
 * are met:
 
7
 * 1. Redistributions of source code must retain the above copyright
 
8
 *    notice, this list of conditions and the following disclaimer.
 
9
 * 2. Redistributions in binary form must reproduce the above copyright
 
10
 *    notice, this list of conditions and the following disclaimer in the
 
11
 *    documentation and/or other materials provided with the distribution.
 
12
 *
 
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 
14
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 
15
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
16
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 
17
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
19
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
21
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
22
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 
23
 * THE POSSIBILITY OF SUCH DAMAGE.
 
24
 */
 
25
 
 
26
#include "config.h"
 
27
#include "TestRunner.h"
 
28
 
 
29
#include "InjectedBundle.h"
 
30
#include "InjectedBundlePage.h"
 
31
#include "JSTestRunner.h"
 
32
#include "PlatformWebView.h"
 
33
#include "StringFunctions.h"
 
34
#include "TestController.h"
 
35
#include <WebCore/PageVisibilityState.h>
 
36
#include <WebKit2/WKBundleBackForwardList.h>
 
37
#include <WebKit2/WKBundleFrame.h>
 
38
#include <WebKit2/WKBundleFramePrivate.h>
 
39
#include <WebKit2/WKBundleInspector.h>
 
40
#include <WebKit2/WKBundleNodeHandlePrivate.h>
 
41
#include <WebKit2/WKBundlePagePrivate.h>
 
42
#include <WebKit2/WKBundlePrivate.h>
 
43
#include <WebKit2/WKBundleScriptWorld.h>
 
44
#include <WebKit2/WKRetainPtr.h>
 
45
#include <WebKit2/WKSerializedScriptValue.h>
 
46
#include <WebKit2/WebKit2_C.h>
 
47
#include <wtf/CurrentTime.h>
 
48
#include <wtf/HashMap.h>
 
49
#include <wtf/OwnArrayPtr.h>
 
50
#include <wtf/PassOwnArrayPtr.h>
 
51
#include <wtf/text/CString.h>
 
52
#include <wtf/text/StringBuilder.h>
 
53
 
 
54
#if ENABLE(WEB_INTENTS)
 
55
#include <WebKit2/WKBundleIntent.h>
 
56
#include <WebKit2/WKBundleIntentRequest.h>
 
57
#endif
 
58
 
 
59
namespace WTR {
 
60
 
 
61
const double TestRunner::waitToDumpWatchdogTimerInterval = 30;
 
62
 
 
63
PassRefPtr<TestRunner> TestRunner::create()
 
64
{
 
65
    return adoptRef(new TestRunner);
 
66
}
 
67
 
 
68
TestRunner::TestRunner()
 
69
    : m_whatToDump(RenderTree)
 
70
    , m_shouldDumpAllFrameScrollPositions(false)
 
71
    , m_shouldDumpBackForwardListsForAllWindows(false)
 
72
    , m_shouldAllowEditing(true)
 
73
    , m_shouldCloseExtraWindows(false)
 
74
    , m_dumpEditingCallbacks(false)
 
75
    , m_dumpStatusCallbacks(false)
 
76
    , m_dumpTitleChanges(false)
 
77
    , m_dumpPixels(true)
 
78
    , m_dumpSelectionRect(false)
 
79
    , m_dumpFullScreenCallbacks(false)
 
80
    , m_dumpFrameLoadCallbacks(false)
 
81
    , m_dumpProgressFinishedCallback(false)
 
82
    , m_dumpResourceLoadCallbacks(false)
 
83
    , m_dumpResourceResponseMIMETypes(false)
 
84
    , m_dumpWillCacheResponse(false)
 
85
    , m_dumpApplicationCacheDelegateCallbacks(false)
 
86
    , m_dumpDatabaseCallbacks(false)
 
87
    , m_disallowIncreaseForApplicationCacheQuota(false)
 
88
    , m_waitToDump(false)
 
89
    , m_testRepaint(false)
 
90
    , m_testRepaintSweepHorizontally(false)
 
91
    , m_willSendRequestReturnsNull(false)
 
92
    , m_willSendRequestReturnsNullOnRedirect(false)
 
93
    , m_shouldStopProvisionalFrameLoads(false)
 
94
    , m_policyDelegateEnabled(false)
 
95
    , m_policyDelegatePermissive(false)
 
96
    , m_globalFlag(false)
 
97
    , m_customFullScreenBehavior(false)
 
98
    , m_userStyleSheetEnabled(false)
 
99
    , m_userStyleSheetLocation(adoptWK(WKStringCreateWithUTF8CString("")))
 
100
{
 
101
    platformInitialize();
 
102
}
 
103
 
 
104
TestRunner::~TestRunner()
 
105
{
 
106
}
 
107
 
 
108
JSClassRef TestRunner::wrapperClass()
 
109
{
 
110
    return JSTestRunner::testRunnerClass();
 
111
}
 
112
 
 
113
void TestRunner::display()
 
114
{
 
115
    WKBundlePageRef page = InjectedBundle::shared().page()->page();
 
116
    WKBundlePageForceRepaint(page);
 
117
    WKBundlePageSetTracksRepaints(page, true);
 
118
    WKBundlePageResetTrackedRepaints(page);
 
119
}
 
120
 
 
121
void TestRunner::dumpAsText(bool dumpPixels)
 
122
{
 
123
    if (m_whatToDump < MainFrameText)
 
124
        m_whatToDump = MainFrameText;
 
125
    m_dumpPixels = dumpPixels;
 
126
}
 
127
 
 
128
void TestRunner::setCustomPolicyDelegate(bool enabled, bool permissive)
 
129
{
 
130
    m_policyDelegateEnabled = enabled;
 
131
    m_policyDelegatePermissive = permissive;
 
132
 
 
133
    InjectedBundle::shared().setCustomPolicyDelegate(enabled, permissive);
 
134
}
 
135
 
 
136
void TestRunner::waitForPolicyDelegate()
 
137
{
 
138
    setCustomPolicyDelegate(true);
 
139
    waitUntilDone();
 
140
}
 
141
 
 
142
void TestRunner::waitUntilDone()
 
143
{
 
144
    m_waitToDump = true;
 
145
    if (InjectedBundle::shared().useWaitToDumpWatchdogTimer())
 
146
        initializeWaitToDumpWatchdogTimerIfNeeded();
 
147
}
 
148
 
 
149
void TestRunner::waitToDumpWatchdogTimerFired()
 
150
{
 
151
    invalidateWaitToDumpWatchdogTimer();
 
152
    const char* message = "FAIL: Timed out waiting for notifyDone to be called\n";
 
153
    InjectedBundle::shared().stringBuilder()->append(message);
 
154
    InjectedBundle::shared().stringBuilder()->append("\n");
 
155
    InjectedBundle::shared().done();
 
156
}
 
157
 
 
158
void TestRunner::notifyDone()
 
159
{
 
160
    if (!InjectedBundle::shared().isTestRunning())
 
161
        return;
 
162
 
 
163
    if (m_waitToDump && !InjectedBundle::shared().topLoadingFrame())
 
164
        InjectedBundle::shared().page()->dump();
 
165
 
 
166
    m_waitToDump = false;
 
167
}
 
168
 
 
169
unsigned TestRunner::numberOfActiveAnimations() const
 
170
{
 
171
    // FIXME: Is it OK this works only for the main frame?
 
172
    // FIXME: If this is needed only for the main frame, then why is the function on WKBundleFrame instead of WKBundlePage?
 
173
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
174
    return WKBundleFrameGetNumberOfActiveAnimations(mainFrame);
 
175
}
 
176
 
 
177
bool TestRunner::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId)
 
178
{
 
179
    // FIXME: Is it OK this works only for the main frame?
 
180
    // FIXME: If this is needed only for the main frame, then why is the function on WKBundleFrame instead of WKBundlePage?
 
181
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
182
    return WKBundleFramePauseAnimationOnElementWithId(mainFrame, toWK(animationName).get(), toWK(elementId).get(), time);
 
183
}
 
184
 
 
185
bool TestRunner::pauseTransitionAtTimeOnElementWithId(JSStringRef propertyName, double time, JSStringRef elementId)
 
186
{
 
187
    // FIXME: Is it OK this works only for the main frame?
 
188
    // FIXME: If this is needed only for the main frame, then why is the function on WKBundleFrame instead of WKBundlePage?
 
189
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
190
    return WKBundleFramePauseTransitionOnElementWithId(mainFrame, toWK(propertyName).get(), toWK(elementId).get(), time);
 
191
}
 
192
 
 
193
void TestRunner::suspendAnimations()
 
194
{
 
195
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
196
    WKBundleFrameSuspendAnimations(mainFrame);
 
197
}
 
198
 
 
199
void TestRunner::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
 
200
{
 
201
    WKRetainPtr<WKStringRef> sourceWK = toWK(source);
 
202
    WKRetainPtr<WKBundleScriptWorldRef> scriptWorld(AdoptWK, WKBundleScriptWorldCreateWorld());
 
203
 
 
204
    WKBundleAddUserScript(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), scriptWorld.get(), sourceWK.get(), 0, 0, 0,
 
205
        (runAtStart ? kWKInjectAtDocumentStart : kWKInjectAtDocumentEnd),
 
206
        (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly));
 
207
}
 
208
 
 
209
void TestRunner::addUserStyleSheet(JSStringRef source, bool allFrames)
 
210
{
 
211
    WKRetainPtr<WKStringRef> sourceWK = toWK(source);
 
212
    WKRetainPtr<WKBundleScriptWorldRef> scriptWorld(AdoptWK, WKBundleScriptWorldCreateWorld());
 
213
 
 
214
    WKBundleAddUserStyleSheet(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), scriptWorld.get(), sourceWK.get(), 0, 0, 0,
 
215
        (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly));
 
216
}
 
217
 
 
218
void TestRunner::keepWebHistory()
 
219
{
 
220
    WKBundleSetShouldTrackVisitedLinks(InjectedBundle::shared().bundle(), true);
 
221
}
 
222
 
 
223
JSValueRef TestRunner::computedStyleIncludingVisitedInfo(JSValueRef element)
 
224
{
 
225
    // FIXME: Is it OK this works only for the main frame?
 
226
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
227
    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
 
228
    if (!JSValueIsObject(context, element))
 
229
        return JSValueMakeUndefined(context);
 
230
    JSValueRef value = WKBundleFrameGetComputedStyleIncludingVisitedInfo(mainFrame, const_cast<JSObjectRef>(element));
 
231
    if (!value)
 
232
        return JSValueMakeUndefined(context);
 
233
    return value;
 
234
}
 
235
 
 
236
JSRetainPtr<JSStringRef> TestRunner::markerTextForListItem(JSValueRef element)
 
237
{
 
238
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
239
    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
 
240
    if (!element || !JSValueIsObject(context, element))
 
241
        return 0;
 
242
    WKRetainPtr<WKStringRef> text(AdoptWK, WKBundleFrameCopyMarkerText(mainFrame, const_cast<JSObjectRef>(element)));
 
243
    if (WKStringIsEmpty(text.get()))
 
244
        return 0;
 
245
    return toJS(text);
 
246
}
 
247
 
 
248
void TestRunner::execCommand(JSStringRef name, JSStringRef argument)
 
249
{
 
250
    WKBundlePageExecuteEditingCommand(InjectedBundle::shared().page()->page(), toWK(name).get(), toWK(argument).get());
 
251
}
 
252
 
 
253
bool TestRunner::findString(JSStringRef target, JSValueRef optionsArrayAsValue)
 
254
{
 
255
    WKFindOptions options = 0;
 
256
 
 
257
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
258
    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
 
259
    JSRetainPtr<JSStringRef> lengthPropertyName(Adopt, JSStringCreateWithUTF8CString("length"));
 
260
    JSObjectRef optionsArray = JSValueToObject(context, optionsArrayAsValue, 0);
 
261
    JSValueRef lengthValue = JSObjectGetProperty(context, optionsArray, lengthPropertyName.get(), 0);
 
262
    if (!JSValueIsNumber(context, lengthValue))
 
263
        return false;
 
264
 
 
265
    size_t length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0));
 
266
    for (size_t i = 0; i < length; ++i) {
 
267
        JSValueRef value = JSObjectGetPropertyAtIndex(context, optionsArray, i, 0);
 
268
        if (!JSValueIsString(context, value))
 
269
            continue;
 
270
 
 
271
        JSRetainPtr<JSStringRef> optionName(Adopt, JSValueToStringCopy(context, value, 0));
 
272
 
 
273
        if (JSStringIsEqualToUTF8CString(optionName.get(), "CaseInsensitive"))
 
274
            options |= kWKFindOptionsCaseInsensitive;
 
275
        else if (JSStringIsEqualToUTF8CString(optionName.get(), "AtWordStarts"))
 
276
            options |= kWKFindOptionsAtWordStarts;
 
277
        else if (JSStringIsEqualToUTF8CString(optionName.get(), "TreatMedialCapitalAsWordStart"))
 
278
            options |= kWKFindOptionsTreatMedialCapitalAsWordStart;
 
279
        else if (JSStringIsEqualToUTF8CString(optionName.get(), "Backwards"))
 
280
            options |= kWKFindOptionsBackwards;
 
281
        else if (JSStringIsEqualToUTF8CString(optionName.get(), "WrapAround"))
 
282
            options |= kWKFindOptionsWrapAround;
 
283
        else if (JSStringIsEqualToUTF8CString(optionName.get(), "StartInSelection")) {
 
284
            // FIXME: No kWKFindOptionsStartInSelection.
 
285
        }
 
286
    }
 
287
 
 
288
    return WKBundlePageFindString(InjectedBundle::shared().page()->page(), toWK(target).get(), options);
 
289
}
 
290
 
 
291
void TestRunner::clearAllDatabases()
 
292
{
 
293
    WKBundleClearAllDatabases(InjectedBundle::shared().bundle());
 
294
}
 
295
 
 
296
void TestRunner::setDatabaseQuota(uint64_t quota)
 
297
{
 
298
    return WKBundleSetDatabaseQuota(InjectedBundle::shared().bundle(), quota);
 
299
}
 
300
 
 
301
void TestRunner::clearAllApplicationCaches()
 
302
{
 
303
    WKBundleClearApplicationCache(InjectedBundle::shared().bundle());
 
304
}
 
305
 
 
306
void TestRunner::clearApplicationCacheForOrigin(JSStringRef origin)
 
307
{
 
308
    WKBundleClearApplicationCacheForOrigin(InjectedBundle::shared().bundle(), toWK(origin).get());
 
309
}
 
310
 
 
311
void TestRunner::setAppCacheMaximumSize(uint64_t size)
 
312
{
 
313
    WKBundleSetAppCacheMaximumSize(InjectedBundle::shared().bundle(), size);
 
314
}
 
315
 
 
316
long long TestRunner::applicationCacheDiskUsageForOrigin(JSStringRef origin)
 
317
{
 
318
    return WKBundleGetAppCacheUsageForOrigin(InjectedBundle::shared().bundle(), toWK(origin).get());
 
319
}
 
320
 
 
321
void TestRunner::setApplicationCacheOriginQuota(unsigned long long bytes)
 
322
{
 
323
    WKRetainPtr<WKStringRef> origin(AdoptWK, WKStringCreateWithUTF8CString("http://127.0.0.1:8000"));
 
324
    WKBundleSetApplicationCacheOriginQuota(InjectedBundle::shared().bundle(), origin.get(), bytes);
 
325
}
 
326
 
 
327
void TestRunner::disallowIncreaseForApplicationCacheQuota()
 
328
{
 
329
    m_disallowIncreaseForApplicationCacheQuota = true;
 
330
}
 
331
 
 
332
static inline JSValueRef stringArrayToJS(JSContextRef context, WKArrayRef strings)
 
333
{
 
334
    const size_t count = WKArrayGetSize(strings);
 
335
 
 
336
    OwnArrayPtr<JSValueRef> jsStringsArray = adoptArrayPtr(new JSValueRef[count]);
 
337
    for (size_t i = 0; i < count; ++i) {
 
338
        WKStringRef stringRef = static_cast<WKStringRef>(WKArrayGetItemAtIndex(strings, i));
 
339
        JSRetainPtr<JSStringRef> stringJS = toJS(stringRef);
 
340
        jsStringsArray[i] = JSValueMakeString(context, stringJS.get());
 
341
    }
 
342
 
 
343
    return JSObjectMakeArray(context, count, jsStringsArray.get(), 0);
 
344
}
 
345
 
 
346
JSValueRef TestRunner::originsWithApplicationCache()
 
347
{
 
348
    WKRetainPtr<WKArrayRef> origins(AdoptWK, WKBundleCopyOriginsWithApplicationCache(InjectedBundle::shared().bundle()));
 
349
 
 
350
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
351
    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
 
352
 
 
353
    return stringArrayToJS(context, origins.get());
 
354
}
 
355
 
 
356
bool TestRunner::isCommandEnabled(JSStringRef name)
 
357
{
 
358
    return WKBundlePageIsEditingCommandEnabled(InjectedBundle::shared().page()->page(), toWK(name).get());
 
359
}
 
360
 
 
361
void TestRunner::setCanOpenWindows(bool)
 
362
{
 
363
    // It's not clear if or why any tests require opening windows be forbidden.
 
364
    // For now, just ignore this setting, and if we find later it's needed we can add it.
 
365
}
 
366
 
 
367
void TestRunner::setXSSAuditorEnabled(bool enabled)
 
368
{
 
369
    WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitXSSAuditorEnabled"));
 
370
    WKBundleOverrideBoolPreferenceForTestRunner(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), key.get(), enabled);
 
371
}
 
372
 
 
373
void TestRunner::setAllowUniversalAccessFromFileURLs(bool enabled)
 
374
{
 
375
    WKBundleSetAllowUniversalAccessFromFileURLs(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled);
 
376
}
 
377
 
 
378
void TestRunner::setAllowFileAccessFromFileURLs(bool enabled)
 
379
{
 
380
    WKBundleSetAllowFileAccessFromFileURLs(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled);
 
381
}
 
382
 
 
383
void TestRunner::setFrameFlatteningEnabled(bool enabled)
 
384
{
 
385
    WKBundleSetFrameFlatteningEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled);
 
386
}
 
387
 
 
388
void TestRunner::setPluginsEnabled(bool enabled)
 
389
{
 
390
    WKBundleSetPluginsEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled);
 
391
}
 
392
 
 
393
void TestRunner::setJavaScriptCanAccessClipboard(bool enabled)
 
394
{
 
395
     WKBundleSetJavaScriptCanAccessClipboard(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled);
 
396
}
 
397
 
 
398
void TestRunner::setPrivateBrowsingEnabled(bool enabled)
 
399
{
 
400
     WKBundleSetPrivateBrowsingEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled);
 
401
}
 
402
 
 
403
void TestRunner::setPopupBlockingEnabled(bool enabled)
 
404
{
 
405
     WKBundleSetPopupBlockingEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled);
 
406
}
 
407
 
 
408
void TestRunner::setAuthorAndUserStylesEnabled(bool enabled)
 
409
{
 
410
     WKBundleSetAuthorAndUserStylesEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled);
 
411
}
 
412
 
 
413
void TestRunner::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
 
414
{
 
415
    WKBundleAddOriginAccessWhitelistEntry(InjectedBundle::shared().bundle(), toWK(sourceOrigin).get(), toWK(destinationProtocol).get(), toWK(destinationHost).get(), allowDestinationSubdomains);
 
416
}
 
417
 
 
418
void TestRunner::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
 
419
{
 
420
    WKBundleRemoveOriginAccessWhitelistEntry(InjectedBundle::shared().bundle(), toWK(sourceOrigin).get(), toWK(destinationProtocol).get(), toWK(destinationHost).get(), allowDestinationSubdomains);
 
421
}
 
422
 
 
423
bool TestRunner::isPageBoxVisible(int pageIndex)
 
424
{
 
425
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
426
    return WKBundleIsPageBoxVisible(InjectedBundle::shared().bundle(), mainFrame, pageIndex);
 
427
}
 
428
 
 
429
void TestRunner::setValueForUser(JSContextRef context, JSValueRef element, JSStringRef value)
 
430
{
 
431
    if (!element || !JSValueIsObject(context, element))
 
432
        return;
 
433
 
 
434
    WKRetainPtr<WKBundleNodeHandleRef> nodeHandle(AdoptWK, WKBundleNodeHandleCreate(context, const_cast<JSObjectRef>(element)));
 
435
    WKBundleNodeHandleSetHTMLInputElementValueForUser(nodeHandle.get(), toWK(value).get());
 
436
}
 
437
 
 
438
unsigned TestRunner::windowCount()
 
439
{
 
440
    return InjectedBundle::shared().pageCount();
 
441
}
 
442
 
 
443
void TestRunner::clearBackForwardList()
 
444
{
 
445
    WKBundleBackForwardListClear(WKBundlePageGetBackForwardList(InjectedBundle::shared().page()->page()));
 
446
}
 
447
 
 
448
// Object Creation
 
449
 
 
450
void TestRunner::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception)
 
451
{
 
452
    setProperty(context, windowObject, "testRunner", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception);
 
453
}
 
454
 
 
455
void TestRunner::showWebInspector()
 
456
{
 
457
#if ENABLE(INSPECTOR)
 
458
    WKBundleInspectorShow(WKBundlePageGetInspector(InjectedBundle::shared().page()->page()));
 
459
#endif // ENABLE(INSPECTOR)
 
460
}
 
461
 
 
462
void TestRunner::closeWebInspector()
 
463
{
 
464
#if ENABLE(INSPECTOR)
 
465
    WKBundleInspectorClose(WKBundlePageGetInspector(InjectedBundle::shared().page()->page()));
 
466
#endif // ENABLE(INSPECTOR)
 
467
}
 
468
 
 
469
void TestRunner::evaluateInWebInspector(long callID, JSStringRef script)
 
470
{
 
471
#if ENABLE(INSPECTOR)
 
472
    WKRetainPtr<WKStringRef> scriptWK = toWK(script);
 
473
    WKBundleInspectorEvaluateScriptForTest(WKBundlePageGetInspector(InjectedBundle::shared().page()->page()), callID, scriptWK.get());
 
474
#endif // ENABLE(INSPECTOR)
 
475
}
 
476
 
 
477
typedef WTF::HashMap<unsigned, WKRetainPtr<WKBundleScriptWorldRef> > WorldMap;
 
478
static WorldMap& worldMap()
 
479
{
 
480
    static WorldMap& map = *new WorldMap;
 
481
    return map;
 
482
}
 
483
 
 
484
unsigned TestRunner::worldIDForWorld(WKBundleScriptWorldRef world)
 
485
{
 
486
    WorldMap::const_iterator end = worldMap().end();
 
487
    for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
 
488
        if (it->value == world)
 
489
            return it->key;
 
490
    }
 
491
 
 
492
    return 0;
 
493
}
 
494
 
 
495
void TestRunner::evaluateScriptInIsolatedWorld(JSContextRef context, unsigned worldID, JSStringRef script)
 
496
{
 
497
    // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
 
498
    // that is created once and cached forever.
 
499
    WKRetainPtr<WKBundleScriptWorldRef> world;
 
500
    if (!worldID)
 
501
        world.adopt(WKBundleScriptWorldCreateWorld());
 
502
    else {
 
503
        WKRetainPtr<WKBundleScriptWorldRef>& worldSlot = worldMap().add(worldID, 0).iterator->value;
 
504
        if (!worldSlot)
 
505
            worldSlot.adopt(WKBundleScriptWorldCreateWorld());
 
506
        world = worldSlot;
 
507
    }
 
508
 
 
509
    WKBundleFrameRef frame = WKBundleFrameForJavaScriptContext(context);
 
510
    if (!frame)
 
511
        frame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
512
 
 
513
    JSGlobalContextRef jsContext = WKBundleFrameGetJavaScriptContextForWorld(frame, world.get());
 
514
    JSEvaluateScript(jsContext, script, 0, 0, 0, 0); 
 
515
}
 
516
 
 
517
void TestRunner::setPOSIXLocale(JSStringRef locale)
 
518
{
 
519
    char localeBuf[32];
 
520
    JSStringGetUTF8CString(locale, localeBuf, sizeof(localeBuf));
 
521
    setlocale(LC_ALL, localeBuf);
 
522
}
 
523
 
 
524
void TestRunner::setTextDirection(JSStringRef direction)
 
525
{
 
526
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
527
    return WKBundleFrameSetTextDirection(mainFrame, toWK(direction).get());
 
528
}
 
529
    
 
530
void TestRunner::setShouldStayOnPageAfterHandlingBeforeUnload(bool shouldStayOnPage)
 
531
{
 
532
    InjectedBundle::shared().postNewBeforeUnloadReturnValue(!shouldStayOnPage);
 
533
}
 
534
 
 
535
void TestRunner::setDefersLoading(bool shouldDeferLoading)
 
536
{
 
537
    WKBundlePageSetDefersLoading(InjectedBundle::shared().page()->page(), shouldDeferLoading);
 
538
}
 
539
 
 
540
void TestRunner::setPageVisibility(JSStringRef state)
 
541
{
 
542
    WebCore::PageVisibilityState visibilityState = WebCore::PageVisibilityStateVisible;
 
543
 
 
544
    if (JSStringIsEqualToUTF8CString(state, "hidden"))
 
545
        visibilityState = WebCore::PageVisibilityStateHidden;
 
546
    else if (JSStringIsEqualToUTF8CString(state, "prerender"))
 
547
        visibilityState = WebCore::PageVisibilityStatePrerender;
 
548
    else if (JSStringIsEqualToUTF8CString(state, "preview"))
 
549
        visibilityState = WebCore::PageVisibilityStatePreview;
 
550
 
 
551
    WKBundleSetPageVisibilityState(InjectedBundle::shared().bundle(), InjectedBundle::shared().page()->page(), visibilityState, /* isInitialState */ false);
 
552
}
 
553
 
 
554
void TestRunner::resetPageVisibility()
 
555
{
 
556
    WKBundleSetPageVisibilityState(InjectedBundle::shared().bundle(), InjectedBundle::shared().page()->page(), WebCore::PageVisibilityStateVisible, /* isInitialState */ true);
 
557
}
 
558
 
 
559
typedef WTF::HashMap<unsigned, JSValueRef> CallbackMap;
 
560
static CallbackMap& callbackMap()
 
561
{
 
562
    static CallbackMap& map = *new CallbackMap;
 
563
    return map;
 
564
}
 
565
 
 
566
enum {
 
567
    AddChromeInputFieldCallbackID = 1,
 
568
    RemoveChromeInputFieldCallbackID,
 
569
    FocusWebViewCallbackID,
 
570
    SetBackingScaleFactorCallbackID
 
571
};
 
572
 
 
573
static void cacheTestRunnerCallback(unsigned index, JSValueRef callback)
 
574
{
 
575
    if (!callback)
 
576
        return;
 
577
 
 
578
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
579
    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
 
580
    JSValueProtect(context, callback);
 
581
    callbackMap().add(index, callback);
 
582
}
 
583
 
 
584
static void callTestRunnerCallback(unsigned index)
 
585
{
 
586
    if (!callbackMap().contains(index))
 
587
        return;
 
588
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
589
    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
 
590
    JSObjectRef callback = JSValueToObject(context, callbackMap().take(index), 0);
 
591
    JSObjectCallAsFunction(context, callback, JSContextGetGlobalObject(context), 0, 0, 0);
 
592
    JSValueUnprotect(context, callback);
 
593
}
 
594
 
 
595
unsigned TestRunner::workerThreadCount()
 
596
{
 
597
    return WKBundleGetWorkerThreadCount(InjectedBundle::shared().bundle());
 
598
}
 
599
 
 
600
void TestRunner::addChromeInputField(JSValueRef callback)
 
601
{
 
602
    cacheTestRunnerCallback(AddChromeInputFieldCallbackID, callback);
 
603
    InjectedBundle::shared().postAddChromeInputField();
 
604
}
 
605
 
 
606
void TestRunner::removeChromeInputField(JSValueRef callback)
 
607
{
 
608
    cacheTestRunnerCallback(RemoveChromeInputFieldCallbackID, callback);
 
609
    InjectedBundle::shared().postRemoveChromeInputField();
 
610
}
 
611
 
 
612
void TestRunner::focusWebView(JSValueRef callback)
 
613
{
 
614
    cacheTestRunnerCallback(FocusWebViewCallbackID, callback);
 
615
    InjectedBundle::shared().postFocusWebView();
 
616
}
 
617
 
 
618
void TestRunner::setBackingScaleFactor(double backingScaleFactor, JSValueRef callback)
 
619
{
 
620
    cacheTestRunnerCallback(SetBackingScaleFactorCallbackID, callback);
 
621
    InjectedBundle::shared().postSetBackingScaleFactor(backingScaleFactor);
 
622
}
 
623
 
 
624
void TestRunner::setWindowIsKey(bool isKey)
 
625
{
 
626
    InjectedBundle::shared().postSetWindowIsKey(isKey);
 
627
}
 
628
 
 
629
void TestRunner::callAddChromeInputFieldCallback()
 
630
{
 
631
    callTestRunnerCallback(AddChromeInputFieldCallbackID);
 
632
}
 
633
 
 
634
void TestRunner::callRemoveChromeInputFieldCallback()
 
635
{
 
636
    callTestRunnerCallback(RemoveChromeInputFieldCallbackID);
 
637
}
 
638
 
 
639
void TestRunner::callFocusWebViewCallback()
 
640
{
 
641
    callTestRunnerCallback(FocusWebViewCallbackID);
 
642
}
 
643
 
 
644
void TestRunner::callSetBackingScaleFactorCallback()
 
645
{
 
646
    callTestRunnerCallback(SetBackingScaleFactorCallbackID);
 
647
}
 
648
 
 
649
static inline bool toBool(JSStringRef value)
 
650
{
 
651
    return JSStringIsEqualToUTF8CString(value, "true") || JSStringIsEqualToUTF8CString(value, "1");
 
652
}
 
653
 
 
654
void TestRunner::overridePreference(JSStringRef preference, JSStringRef value)
 
655
{
 
656
    // FIXME: handle non-boolean preferences.
 
657
    WKBundleOverrideBoolPreferenceForTestRunner(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), toWK(preference).get(), toBool(value));
 
658
}
 
659
 
 
660
void TestRunner::sendWebIntentResponse(JSStringRef reply)
 
661
{
 
662
#if ENABLE(WEB_INTENTS)
 
663
    WKRetainPtr<WKBundleIntentRequestRef> currentRequest = InjectedBundle::shared().page()->currentIntentRequest();
 
664
    if (!currentRequest)
 
665
        return;
 
666
 
 
667
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
668
    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
 
669
 
 
670
    if (reply) {
 
671
        WKRetainPtr<WKSerializedScriptValueRef> serializedData(AdoptWK, WKSerializedScriptValueCreate(context, JSValueMakeString(context, reply), 0));
 
672
        WKBundleIntentRequestPostResult(currentRequest.get(), serializedData.get());
 
673
    } else {
 
674
        JSRetainPtr<JSStringRef> errorReply(JSStringCreateWithUTF8CString("ERROR"));
 
675
        WKRetainPtr<WKSerializedScriptValueRef> serializedData(AdoptWK, WKSerializedScriptValueCreate(context, JSValueMakeString(context, errorReply.get()), 0));
 
676
        WKBundleIntentRequestPostFailure(currentRequest.get(), serializedData.get());
 
677
    }
 
678
#endif
 
679
}
 
680
 
 
681
void TestRunner::deliverWebIntent(JSStringRef action, JSStringRef type, JSStringRef data)
 
682
{
 
683
#if ENABLE(WEB_INTENTS)
 
684
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
685
    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
 
686
 
 
687
    WKRetainPtr<WKStringRef> actionWK = toWK(action);
 
688
    WKRetainPtr<WKStringRef> typeWK = toWK(type);
 
689
    WKRetainPtr<WKSerializedScriptValueRef> dataWK(AdoptWK, WKSerializedScriptValueCreate(context, JSValueMakeString(context, data), 0));
 
690
 
 
691
    WKRetainPtr<WKMutableDictionaryRef> intentInitDict(AdoptWK, WKMutableDictionaryCreate());
 
692
    WKRetainPtr<WKStringRef> actionKey(AdoptWK, WKStringCreateWithUTF8CString("action"));
 
693
    WKDictionaryAddItem(intentInitDict.get(), actionKey.get(), actionWK.get());
 
694
 
 
695
    WKRetainPtr<WKStringRef> typeKey(AdoptWK, WKStringCreateWithUTF8CString("type"));
 
696
    WKDictionaryAddItem(intentInitDict.get(), typeKey.get(), typeWK.get());
 
697
 
 
698
    WKRetainPtr<WKStringRef> dataKey(AdoptWK, WKStringCreateWithUTF8CString("data"));
 
699
    WKDictionaryAddItem(intentInitDict.get(), dataKey.get(), dataWK.get());
 
700
 
 
701
    WKRetainPtr<WKBundleIntentRef> wkIntent(AdoptWK, WKBundleIntentCreate(intentInitDict.get()));
 
702
    WKBundlePageDeliverIntentToFrame(InjectedBundle::shared().page()->page(), mainFrame, wkIntent.get());
 
703
#endif
 
704
}
 
705
 
 
706
void TestRunner::setAlwaysAcceptCookies(bool accept)
 
707
{
 
708
    WKBundleSetAlwaysAcceptCookies(InjectedBundle::shared().bundle(), accept);
 
709
}
 
710
 
 
711
double TestRunner::preciseTime()
 
712
{
 
713
    return currentTime();
 
714
}
 
715
 
 
716
void TestRunner::setUserStyleSheetEnabled(bool enabled)
 
717
{
 
718
    m_userStyleSheetEnabled = enabled;
 
719
 
 
720
    WKRetainPtr<WKStringRef> emptyUrl = adoptWK(WKStringCreateWithUTF8CString(""));
 
721
    WKStringRef location = enabled ? m_userStyleSheetLocation.get() : emptyUrl.get();
 
722
    WKBundleSetUserStyleSheetLocation(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), location);
 
723
}
 
724
 
 
725
void TestRunner::setUserStyleSheetLocation(JSStringRef location)
 
726
{
 
727
    m_userStyleSheetLocation = adoptWK(WKStringCreateWithJSString(location));
 
728
 
 
729
    if (m_userStyleSheetEnabled)
 
730
        setUserStyleSheetEnabled(true);
 
731
}
 
732
 
 
733
void TestRunner::setMinimumTimerInterval(double seconds)
 
734
{
 
735
    WKBundleSetMinimumTimerInterval(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), seconds);
 
736
}
 
737
 
 
738
void TestRunner::setSpatialNavigationEnabled(bool enabled)
 
739
{
 
740
    WKBundleSetSpatialNavigationEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled);
 
741
}
 
742
 
 
743
void TestRunner::setTabKeyCyclesThroughElements(bool enabled)
 
744
{
 
745
    WKBundleSetTabKeyCyclesThroughElements(InjectedBundle::shared().bundle(), InjectedBundle::shared().page()->page(), enabled);
 
746
}
 
747
 
 
748
void TestRunner::setSerializeHTTPLoads()
 
749
{
 
750
    WKBundleSetSerialLoadingEnabled(InjectedBundle::shared().bundle(), true);
 
751
}
 
752
 
 
753
void TestRunner::dispatchPendingLoadRequests()
 
754
{
 
755
    WKBundleDispatchPendingLoadRequests(InjectedBundle::shared().bundle());
 
756
}
 
757
 
 
758
void TestRunner::setCacheModel(int model)
 
759
{
 
760
    WKBundleSetCacheModel(InjectedBundle::shared().bundle(), model);
 
761
}
 
762
 
 
763
void TestRunner::grantWebNotificationPermission(JSStringRef origin)
 
764
{
 
765
    WKRetainPtr<WKStringRef> originWK = toWK(origin);
 
766
    WKBundleSetWebNotificationPermission(InjectedBundle::shared().bundle(), InjectedBundle::shared().page()->page(), originWK.get(), true);
 
767
}
 
768
 
 
769
void TestRunner::denyWebNotificationPermission(JSStringRef origin)
 
770
{
 
771
    WKRetainPtr<WKStringRef> originWK = toWK(origin);
 
772
    WKBundleSetWebNotificationPermission(InjectedBundle::shared().bundle(), InjectedBundle::shared().page()->page(), originWK.get(), false);
 
773
}
 
774
 
 
775
void TestRunner::removeAllWebNotificationPermissions()
 
776
{
 
777
    WKBundleRemoveAllWebNotificationPermissions(InjectedBundle::shared().bundle(), InjectedBundle::shared().page()->page());
 
778
}
 
779
 
 
780
void TestRunner::simulateWebNotificationClick(JSValueRef notification)
 
781
{
 
782
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
783
    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
 
784
    uint64_t notificationID = WKBundleGetWebNotificationID(InjectedBundle::shared().bundle(), context, notification);
 
785
    InjectedBundle::shared().postSimulateWebNotificationClick(notificationID);
 
786
}
 
787
 
 
788
void TestRunner::setGeolocationPermission(bool enabled)
 
789
{
 
790
    // FIXME: this should be done by frame.
 
791
    InjectedBundle::shared().setGeolocationPermission(enabled);
 
792
}
 
793
 
 
794
void TestRunner::setMockGeolocationPosition(double latitude, double longitude, double accuracy, JSValueRef jsAltitude, JSValueRef jsAltitudeAccuracy, JSValueRef jsHeading, JSValueRef jsSpeed)
 
795
{
 
796
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
797
    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
 
798
 
 
799
    bool providesAltitude = false;
 
800
    double altitude = 0.;
 
801
    if (!JSValueIsUndefined(context, jsAltitude)) {
 
802
        providesAltitude = true;
 
803
        altitude = JSValueToNumber(context, jsAltitude, 0);
 
804
    }
 
805
 
 
806
    bool providesAltitudeAccuracy = false;
 
807
    double altitudeAccuracy = 0.;
 
808
    if (!JSValueIsUndefined(context, jsAltitudeAccuracy)) {
 
809
        providesAltitudeAccuracy = true;
 
810
        altitudeAccuracy = JSValueToNumber(context, jsAltitudeAccuracy, 0);
 
811
    }
 
812
 
 
813
    bool providesHeading = false;
 
814
    double heading = 0.;
 
815
    if (!JSValueIsUndefined(context, jsHeading)) {
 
816
        providesHeading = true;
 
817
        heading = JSValueToNumber(context, jsHeading, 0);
 
818
    }
 
819
 
 
820
    bool providesSpeed = false;
 
821
    double speed = 0.;
 
822
    if (!JSValueIsUndefined(context, jsSpeed)) {
 
823
        providesSpeed = true;
 
824
        speed = JSValueToNumber(context, jsSpeed, 0);
 
825
    }
 
826
 
 
827
    InjectedBundle::shared().setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed);
 
828
}
 
829
 
 
830
void TestRunner::setMockGeolocationPositionUnavailableError(JSStringRef message)
 
831
{
 
832
    WKRetainPtr<WKStringRef> messageWK = toWK(message);
 
833
    InjectedBundle::shared().setMockGeolocationPositionUnavailableError(messageWK.get());
 
834
}
 
835
 
 
836
bool TestRunner::callShouldCloseOnWebView()
 
837
{
 
838
    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
 
839
    return WKBundleFrameCallShouldCloseOnWebView(mainFrame);
 
840
}
 
841
 
 
842
void TestRunner::queueBackNavigation(unsigned howFarBackward)
 
843
{
 
844
    InjectedBundle::shared().queueBackNavigation(howFarBackward);
 
845
}
 
846
 
 
847
void TestRunner::queueForwardNavigation(unsigned howFarForward)
 
848
{
 
849
    InjectedBundle::shared().queueForwardNavigation(howFarForward);
 
850
}
 
851
 
 
852
void TestRunner::queueLoad(JSStringRef url, JSStringRef target)
 
853
{
 
854
    WKRetainPtr<WKURLRef> baseURLWK(AdoptWK, WKBundleFrameCopyURL(WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page())));
 
855
    WKRetainPtr<WKURLRef> urlWK(AdoptWK, WKURLCreateWithBaseURL(baseURLWK.get(), toWTFString(toWK(url)).utf8().data()));
 
856
    WKRetainPtr<WKStringRef> urlStringWK(AdoptWK, WKURLCopyString(urlWK.get()));
 
857
 
 
858
    InjectedBundle::shared().queueLoad(urlStringWK.get(), toWK(target).get());
 
859
}
 
860
 
 
861
void TestRunner::queueLoadHTMLString(JSStringRef content, JSStringRef baseURL, JSStringRef unreachableURL)
 
862
{
 
863
    WKRetainPtr<WKStringRef> contentWK = toWK(content);
 
864
    WKRetainPtr<WKStringRef> baseURLWK = baseURL ? toWK(baseURL) : WKRetainPtr<WKStringRef>();
 
865
    WKRetainPtr<WKStringRef> unreachableURLWK = unreachableURL ? toWK(unreachableURL) : WKRetainPtr<WKStringRef>();
 
866
 
 
867
    InjectedBundle::shared().queueLoadHTMLString(contentWK.get(), baseURLWK.get(), unreachableURLWK.get());
 
868
}
 
869
 
 
870
void TestRunner::queueReload()
 
871
{
 
872
    InjectedBundle::shared().queueReload();
 
873
}
 
874
 
 
875
void TestRunner::queueLoadingScript(JSStringRef script)
 
876
{
 
877
    WKRetainPtr<WKStringRef> scriptWK = toWK(script);
 
878
    InjectedBundle::shared().queueLoadingScript(scriptWK.get());
 
879
}
 
880
 
 
881
void TestRunner::queueNonLoadingScript(JSStringRef script)
 
882
{
 
883
    WKRetainPtr<WKStringRef> scriptWK = toWK(script);
 
884
    InjectedBundle::shared().queueNonLoadingScript(scriptWK.get());
 
885
}
 
886
 
 
887
} // namespace WTR