• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2007, 2008, 2009 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 *
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 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#import "config.h"
30#import "DumpRenderTree.h"
31#import "LayoutTestController.h"
32
33#import "EditingDelegate.h"
34#import "MockGeolocationProvider.h"
35#import "PolicyDelegate.h"
36#import "StorageTrackerDelegate.h"
37#import "UIDelegate.h"
38#import "WorkQueue.h"
39#import "WorkQueueItem.h"
40#import <Foundation/Foundation.h>
41#import <JavaScriptCore/JSRetainPtr.h>
42#import <JavaScriptCore/JSStringRef.h>
43#import <JavaScriptCore/JSStringRefCF.h>
44#import <WebKit/DOMDocument.h>
45#import <WebKit/DOMElement.h>
46#import <WebKit/WebApplicationCache.h>
47#import <WebKit/WebBackForwardList.h>
48#import <WebKit/WebCoreStatistics.h>
49#import <WebKit/WebDOMOperationsPrivate.h>
50#import <WebKit/WebDataSource.h>
51#import <WebKit/WebDatabaseManagerPrivate.h>
52#import <WebKit/WebDeviceOrientation.h>
53#import <WebKit/WebDeviceOrientationProviderMock.h>
54#import <WebKit/WebFrame.h>
55#import <WebKit/WebFrameViewPrivate.h>
56#import <WebKit/WebGeolocationPosition.h>
57#import <WebKit/WebHTMLRepresentation.h>
58#import <WebKit/WebHTMLViewPrivate.h>
59#import <WebKit/WebHistory.h>
60#import <WebKit/WebHistoryPrivate.h>
61#import <WebKit/WebIconDatabasePrivate.h>
62#import <WebKit/WebInspectorPrivate.h>
63#import <WebKit/WebNSURLExtras.h>
64#import <WebKit/WebKitErrors.h>
65#import <WebKit/WebPreferences.h>
66#import <WebKit/WebPreferencesPrivate.h>
67#import <WebKit/WebQuotaManager.h>
68#import <WebKit/WebScriptWorld.h>
69#import <WebKit/WebSecurityOriginPrivate.h>
70#import <WebKit/WebStorageManagerPrivate.h>
71#import <WebKit/WebTypesInternal.h>
72#import <WebKit/WebView.h>
73#import <WebKit/WebViewPrivate.h>
74#import <WebKit/WebWorkersPrivate.h>
75#import <wtf/CurrentTime.h>
76#import <wtf/HashMap.h>
77#import <wtf/RetainPtr.h>
78
79@interface CommandValidationTarget : NSObject <NSValidatedUserInterfaceItem>
80{
81    SEL _action;
82}
83- (id)initWithAction:(SEL)action;
84@end
85
86@implementation CommandValidationTarget
87
88- (id)initWithAction:(SEL)action
89{
90    self = [super init];
91    if (!self)
92        return nil;
93
94    _action = action;
95    return self;
96}
97
98- (SEL)action
99{
100    return _action;
101}
102
103- (NSInteger)tag
104{
105    return 0;
106}
107
108@end
109
110LayoutTestController::~LayoutTestController()
111{
112}
113
114void LayoutTestController::addDisallowedURL(JSStringRef url)
115{
116    RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url));
117
118    if (!disallowedURLs)
119        disallowedURLs = CFSetCreateMutable(kCFAllocatorDefault, 0, NULL);
120
121    // Canonicalize the URL
122    NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:(NSString *)urlCF.get()]];
123    request = [NSURLProtocol canonicalRequestForRequest:request];
124
125    CFSetAddValue(disallowedURLs, [request URL]);
126}
127
128bool LayoutTestController::callShouldCloseOnWebView()
129{
130    return [[mainFrame webView] shouldClose];
131}
132
133void LayoutTestController::clearAllApplicationCaches()
134{
135    [WebApplicationCache deleteAllApplicationCaches];
136}
137
138void LayoutTestController::syncLocalStorage()
139{
140    [[WebStorageManager sharedWebStorageManager] syncLocalStorage];
141}
142
143void LayoutTestController::observeStorageTrackerNotifications(unsigned number)
144{
145    [storageDelegate logNotifications:number controller:this];
146}
147
148void LayoutTestController::clearApplicationCacheForOrigin(JSStringRef url)
149{
150    RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url));
151
152    WebSecurityOrigin *origin = [[WebSecurityOrigin alloc] initWithURL:[NSURL URLWithString:(NSString *)urlCF.get()]];
153    [WebApplicationCache deleteCacheForOrigin:origin];
154    [origin release];
155}
156
157JSValueRef originsArrayToJS(JSContextRef context, NSArray* origins)
158{
159    NSUInteger count = [origins count];
160
161    JSValueRef jsOriginsArray[count];
162    for (NSUInteger i = 0; i < count; i++) {
163        NSString *origin = [[origins objectAtIndex:i] databaseIdentifier];
164        JSRetainPtr<JSStringRef> originJS(Adopt, JSStringCreateWithCFString((CFStringRef)origin));
165        jsOriginsArray[i] = JSValueMakeString(context, originJS.get());
166    }
167
168    return JSObjectMakeArray(context, count, jsOriginsArray, NULL);
169}
170
171JSValueRef LayoutTestController::originsWithApplicationCache(JSContextRef context)
172{
173    return originsArrayToJS(context, [WebApplicationCache originsWithCache]);
174}
175
176void LayoutTestController::clearAllDatabases()
177{
178    [[WebDatabaseManager sharedWebDatabaseManager] deleteAllDatabases];
179}
180
181void LayoutTestController::deleteAllLocalStorage()
182{
183    [[WebStorageManager sharedWebStorageManager] deleteAllOrigins];
184}
185
186JSValueRef LayoutTestController::originsWithLocalStorage(JSContextRef context)
187{
188    return originsArrayToJS(context, [[WebStorageManager sharedWebStorageManager] origins]);
189}
190
191void LayoutTestController::deleteLocalStorageForOrigin(JSStringRef URL)
192{
193    RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, URL));
194
195    WebSecurityOrigin *origin = [[WebSecurityOrigin alloc] initWithURL:[NSURL URLWithString:(NSString *)urlCF.get()]];
196    [[WebStorageManager sharedWebStorageManager] deleteOrigin:origin];
197    [origin release];
198}
199
200void LayoutTestController::clearBackForwardList()
201{
202    WebBackForwardList *backForwardList = [[mainFrame webView] backForwardList];
203    WebHistoryItem *item = [[backForwardList currentItem] retain];
204
205    // We clear the history by setting the back/forward list's capacity to 0
206    // then restoring it back and adding back the current item.
207    int capacity = [backForwardList capacity];
208    [backForwardList setCapacity:0];
209    [backForwardList setCapacity:capacity];
210    [backForwardList addItem:item];
211    [backForwardList goToItem:item];
212    [item release];
213}
214
215JSStringRef LayoutTestController::copyDecodedHostName(JSStringRef name)
216{
217    RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
218    NSString *nameNS = (NSString *)nameCF.get();
219    return JSStringCreateWithCFString((CFStringRef)[nameNS _web_decodeHostName]);
220}
221
222JSStringRef LayoutTestController::copyEncodedHostName(JSStringRef name)
223{
224    RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
225    NSString *nameNS = (NSString *)nameCF.get();
226    return JSStringCreateWithCFString((CFStringRef)[nameNS _web_encodeHostName]);
227}
228
229void LayoutTestController::display()
230{
231    displayWebView();
232}
233
234JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id)
235{
236    RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, id));
237    NSString *idNS = (NSString *)idCF.get();
238
239    DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS];
240    if (!element)
241        return 0;
242
243    JSRetainPtr<JSStringRef> counterValue(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame counterValueForElement:element]));
244    return counterValue;
245}
246
247void LayoutTestController::keepWebHistory()
248{
249    if (![WebHistory optionalSharedHistory]) {
250        WebHistory *history = [[WebHistory alloc] init];
251        [WebHistory setOptionalSharedHistory:history];
252        [history release];
253    }
254}
255
256JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSContextRef context, JSValueRef value)
257{
258    return [[mainFrame webView] _computedStyleIncludingVisitedInfo:context forElement:value];
259}
260
261JSValueRef LayoutTestController::nodesFromRect(JSContextRef context, JSValueRef value, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping)
262{
263    return [[mainFrame webView] _nodesFromRect:context forDocument:value x:x y:y top:top right:right bottom:bottom left:left ignoreClipping:ignoreClipping];
264}
265
266JSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const
267{
268    JSRetainPtr<JSStringRef> string(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame _layerTreeAsText]));
269    return string;
270}
271
272JSRetainPtr<JSStringRef> LayoutTestController::markerTextForListItem(JSContextRef context, JSValueRef nodeObject) const
273{
274    DOMElement *element = [DOMElement _DOMElementFromJSContext:context value:nodeObject];
275    if (!element)
276        return JSRetainPtr<JSStringRef>();
277
278    JSRetainPtr<JSStringRef> markerText(Adopt, JSStringCreateWithCFString((CFStringRef)[element _markerTextForListItem]));
279    return markerText;
280}
281
282int LayoutTestController::pageNumberForElementById(JSStringRef id, float pageWidthInPixels, float pageHeightInPixels)
283{
284    RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, id));
285    NSString *idNS = (NSString *)idCF.get();
286
287    DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS];
288    if (!element)
289        return -1;
290
291    return [mainFrame pageNumberForElement:element:pageWidthInPixels:pageHeightInPixels];
292}
293
294JSRetainPtr<JSStringRef> LayoutTestController::pageProperty(const char* propertyName, int pageNumber) const
295{
296    JSRetainPtr<JSStringRef> propertyValue(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame pageProperty:propertyName:pageNumber]));
297    return propertyValue;
298}
299
300bool LayoutTestController::isPageBoxVisible(int pageNumber) const
301{
302    return [mainFrame isPageBoxVisible:pageNumber];
303}
304
305JSRetainPtr<JSStringRef> LayoutTestController::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) const
306{
307    JSRetainPtr<JSStringRef> propertyValue(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame pageSizeAndMarginsInPixels:pageNumber:width:height:marginTop:marginRight:marginBottom:marginLeft]));
308    return propertyValue;
309}
310
311int LayoutTestController::numberOfPages(float pageWidthInPixels, float pageHeightInPixels)
312{
313    return [mainFrame numberOfPages:pageWidthInPixels:pageHeightInPixels];
314}
315
316int LayoutTestController::numberOfPendingGeolocationPermissionRequests()
317{
318    return [[[mainFrame webView] UIDelegate] numberOfPendingGeolocationPermissionRequests];
319}
320
321size_t LayoutTestController::webHistoryItemCount()
322{
323    return [[[WebHistory optionalSharedHistory] allItems] count];
324}
325
326unsigned LayoutTestController::workerThreadCount() const
327{
328    return [WebWorkersPrivate workerThreadCount];
329}
330
331void LayoutTestController::notifyDone()
332{
333    if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count())
334        dump();
335    m_waitToDump = false;
336}
337
338JSStringRef LayoutTestController::pathToLocalResource(JSContextRef context, JSStringRef url)
339{
340    return JSStringRetain(url); // Do nothing on mac.
341}
342
343void LayoutTestController::queueLoad(JSStringRef url, JSStringRef target)
344{
345    RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url));
346    NSString *urlNS = (NSString *)urlCF.get();
347
348    NSURL *nsurl = [NSURL URLWithString:urlNS relativeToURL:[[[mainFrame dataSource] response] URL]];
349    NSString* nsurlString = [nsurl absoluteString];
350
351    JSRetainPtr<JSStringRef> absoluteURL(Adopt, JSStringCreateWithUTF8CString([nsurlString UTF8String]));
352    WorkQueue::shared()->queue(new LoadItem(absoluteURL.get(), target));
353}
354
355void LayoutTestController::setAcceptsEditing(bool newAcceptsEditing)
356{
357    [(EditingDelegate *)[[mainFrame webView] editingDelegate] setAcceptsEditing:newAcceptsEditing];
358}
359
360void LayoutTestController::setAlwaysAcceptCookies(bool alwaysAcceptCookies)
361{
362    if (alwaysAcceptCookies == m_alwaysAcceptCookies)
363        return;
364
365    m_alwaysAcceptCookies = alwaysAcceptCookies;
366    NSHTTPCookieAcceptPolicy cookieAcceptPolicy = alwaysAcceptCookies ? NSHTTPCookieAcceptPolicyAlways : NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain;
367    [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:cookieAcceptPolicy];
368}
369
370void LayoutTestController::setAppCacheMaximumSize(unsigned long long size)
371{
372    [WebApplicationCache setMaximumSize:size];
373}
374
375void LayoutTestController::setApplicationCacheOriginQuota(unsigned long long quota)
376{
377    WebSecurityOrigin *origin = [[WebSecurityOrigin alloc] initWithURL:[NSURL URLWithString:@"http://127.0.0.1:8000"]];
378    [[origin applicationCacheQuotaManager] setQuota:quota];
379    [origin release];
380}
381
382void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag)
383{
384    [[[mainFrame webView] preferences] setAuthorAndUserStylesEnabled:flag];
385}
386
387void LayoutTestController::setAutofilled(JSContextRef context, JSValueRef nodeObject, bool autofilled)
388{
389    DOMElement *element = [DOMElement _DOMElementFromJSContext:context value:nodeObject];
390    if (!element || ![element isKindOfClass:[DOMHTMLInputElement class]])
391        return;
392
393    [(DOMHTMLInputElement *)element _setAutofilled:autofilled];
394}
395
396void LayoutTestController::setCustomPolicyDelegate(bool setDelegate, bool permissive)
397{
398    if (setDelegate) {
399        [policyDelegate setPermissive:permissive];
400        [[mainFrame webView] setPolicyDelegate:policyDelegate];
401    } else
402        [[mainFrame webView] setPolicyDelegate:nil];
403}
404
405void LayoutTestController::setDatabaseQuota(unsigned long long quota)
406{
407    WebSecurityOrigin *origin = [[WebSecurityOrigin alloc] initWithURL:[NSURL URLWithString:@"file:///"]];
408    [[origin databaseQuotaManager] setQuota:quota];
409    [origin release];
410}
411
412void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme)
413{
414    RetainPtr<CFStringRef> schemeCFString(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, scheme));
415    [WebView _setDomainRelaxationForbidden:forbidden forURLScheme:(NSString *)schemeCFString.get()];
416}
417
418void LayoutTestController::setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma)
419{
420    // DumpRenderTree configured the WebView to use WebDeviceOrientationProviderMock.
421    id<WebDeviceOrientationProvider> provider = [[mainFrame webView] _deviceOrientationProvider];
422    WebDeviceOrientationProviderMock* mockProvider = static_cast<WebDeviceOrientationProviderMock*>(provider);
423    WebDeviceOrientation* orientation = [[WebDeviceOrientation alloc] initWithCanProvideAlpha:canProvideAlpha alpha:alpha canProvideBeta:canProvideBeta beta:beta canProvideGamma:canProvideGamma gamma:gamma];
424    [mockProvider setOrientation:orientation];
425    [orientation release];
426}
427
428void LayoutTestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy)
429{
430    WebGeolocationPosition *position = [[WebGeolocationPosition alloc] initWithTimestamp:currentTime() latitude:latitude longitude:longitude accuracy:accuracy];
431    [[MockGeolocationProvider shared] setPosition:position];
432    [position release];
433}
434
435void LayoutTestController::setMockGeolocationError(int code, JSStringRef message)
436{
437    RetainPtr<CFStringRef> messageCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, message));
438    NSString *messageNS = (NSString *)messageCF.get();
439    NSError *error = [NSError errorWithDomain:WebKitErrorDomain code:code userInfo:[NSDictionary dictionaryWithObject:messageNS forKey:NSLocalizedDescriptionKey]];
440    [[MockGeolocationProvider shared] setError:error];
441}
442
443void LayoutTestController::setGeolocationPermission(bool allow)
444{
445    setGeolocationPermissionCommon(allow);
446    [[[mainFrame webView] UIDelegate] didSetMockGeolocationPermission];
447}
448
449void LayoutTestController::addMockSpeechInputResult(JSStringRef result, double confidence, JSStringRef language)
450{
451    // FIXME: Implement for speech input layout tests.
452    // See https://bugs.webkit.org/show_bug.cgi?id=39485.
453}
454
455void LayoutTestController::setIconDatabaseEnabled(bool iconDatabaseEnabled)
456{
457    // FIXME: Workaround <rdar://problem/6480108>
458    static WebIconDatabase* sharedWebIconDatabase = NULL;
459    if (!sharedWebIconDatabase) {
460        if (!iconDatabaseEnabled)
461            return;
462        sharedWebIconDatabase = [WebIconDatabase sharedIconDatabase];
463        if ([sharedWebIconDatabase isEnabled] == iconDatabaseEnabled)
464            return;
465    }
466    [sharedWebIconDatabase setEnabled:iconDatabaseEnabled];
467}
468
469void LayoutTestController::setJavaScriptProfilingEnabled(bool profilingEnabled)
470{
471    setDeveloperExtrasEnabled(profilingEnabled);
472    [[[mainFrame webView] inspector] setJavaScriptProfilingEnabled:profilingEnabled];
473}
474
475void LayoutTestController::setMainFrameIsFirstResponder(bool flag)
476{
477    NSView *documentView = [[mainFrame frameView] documentView];
478
479    NSResponder *firstResponder = flag ? documentView : nil;
480    [[[mainFrame webView] window] makeFirstResponder:firstResponder];
481}
482
483void LayoutTestController::setPrivateBrowsingEnabled(bool privateBrowsingEnabled)
484{
485    [[[mainFrame webView] preferences] setPrivateBrowsingEnabled:privateBrowsingEnabled];
486}
487
488void LayoutTestController::setXSSAuditorEnabled(bool enabled)
489{
490    [[[mainFrame webView] preferences] setXSSAuditorEnabled:enabled];
491}
492
493void LayoutTestController::setFrameFlatteningEnabled(bool enabled)
494{
495    [[[mainFrame webView] preferences] setFrameFlatteningEnabled:enabled];
496}
497
498void LayoutTestController::setSpatialNavigationEnabled(bool enabled)
499{
500    [[[mainFrame webView] preferences] setSpatialNavigationEnabled:enabled];
501}
502
503void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
504{
505    [[[mainFrame webView] preferences] setAllowUniversalAccessFromFileURLs:enabled];
506}
507
508void LayoutTestController::setAllowFileAccessFromFileURLs(bool enabled)
509{
510    [[[mainFrame webView] preferences] setAllowFileAccessFromFileURLs:enabled];
511}
512
513void LayoutTestController::setPopupBlockingEnabled(bool popupBlockingEnabled)
514{
515    [[[mainFrame webView] preferences] setJavaScriptCanOpenWindowsAutomatically:!popupBlockingEnabled];
516}
517
518void LayoutTestController::setPluginsEnabled(bool pluginsEnabled)
519{
520    [[[mainFrame webView] preferences] setPlugInsEnabled:pluginsEnabled];
521}
522
523void LayoutTestController::setJavaScriptCanAccessClipboard(bool enabled)
524{
525    [[[mainFrame webView] preferences] setJavaScriptCanAccessClipboard:enabled];
526}
527
528void LayoutTestController::setTabKeyCyclesThroughElements(bool cycles)
529{
530    [[mainFrame webView] setTabKeyCyclesThroughElements:cycles];
531}
532
533void LayoutTestController::setTimelineProfilingEnabled(bool enabled)
534{
535    [[[mainFrame webView] inspector] setTimelineProfilingEnabled:enabled];
536}
537
538void LayoutTestController::setUseDashboardCompatibilityMode(bool flag)
539{
540    [[mainFrame webView] _setDashboardBehavior:WebDashboardBehaviorUseBackwardCompatibilityMode to:flag];
541}
542
543void LayoutTestController::setUserStyleSheetEnabled(bool flag)
544{
545    [[WebPreferences standardPreferences] setUserStyleSheetEnabled:flag];
546}
547
548void LayoutTestController::setUserStyleSheetLocation(JSStringRef path)
549{
550    RetainPtr<CFStringRef> pathCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, path));
551    NSURL *url = [NSURL URLWithString:(NSString *)pathCF.get()];
552    [[WebPreferences standardPreferences] setUserStyleSheetLocation:url];
553}
554
555void LayoutTestController::setValueForUser(JSContextRef context, JSValueRef nodeObject, JSStringRef value)
556{
557    DOMElement *element = [DOMElement _DOMElementFromJSContext:context value:nodeObject];
558    if (!element || ![element isKindOfClass:[DOMHTMLInputElement class]])
559        return;
560
561    RetainPtr<CFStringRef> valueCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, value));
562    [(DOMHTMLInputElement *)element _setValueForUser:(NSString *)valueCF.get()];
563}
564
565void LayoutTestController::setViewModeMediaFeature(JSStringRef mode)
566{
567    // FIXME: implement
568}
569
570void LayoutTestController::disableImageLoading()
571{
572    [[WebPreferences standardPreferences] setLoadsImagesAutomatically:NO];
573}
574
575void LayoutTestController::dispatchPendingLoadRequests()
576{
577    [[mainFrame webView] _dispatchPendingLoadRequests];
578}
579
580void LayoutTestController::overridePreference(JSStringRef key, JSStringRef value)
581{
582    RetainPtr<CFStringRef> keyCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, key));
583    NSString *keyNS = (NSString *)keyCF.get();
584
585    RetainPtr<CFStringRef> valueCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, value));
586    NSString *valueNS = (NSString *)valueCF.get();
587
588    [[WebPreferences standardPreferences] _setPreferenceForTestWithValue:valueNS forKey:keyNS];
589}
590
591void LayoutTestController::removeAllVisitedLinks()
592{
593    [WebHistory _removeAllVisitedLinks];
594}
595
596void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL)
597{
598    RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
599    ::setPersistentUserStyleSheetLocation(urlString.get());
600}
601
602void LayoutTestController::clearPersistentUserStyleSheet()
603{
604    ::setPersistentUserStyleSheetLocation(0);
605}
606
607void LayoutTestController::setWindowIsKey(bool windowIsKey)
608{
609    m_windowIsKey = windowIsKey;
610    [[mainFrame webView] _updateActiveState];
611}
612
613void LayoutTestController::setSmartInsertDeleteEnabled(bool flag)
614{
615    [[mainFrame webView] setSmartInsertDeleteEnabled:flag];
616}
617
618void LayoutTestController::setSelectTrailingWhitespaceEnabled(bool flag)
619{
620    [[mainFrame webView] setSelectTrailingWhitespaceEnabled:flag];
621}
622
623static const CFTimeInterval waitToDumpWatchdogInterval = 30.0;
624
625static void waitUntilDoneWatchdogFired(CFRunLoopTimerRef timer, void* info)
626{
627    gLayoutTestController->waitToDumpWatchdogTimerFired();
628}
629
630void LayoutTestController::setWaitToDump(bool waitUntilDone)
631{
632    m_waitToDump = waitUntilDone;
633    if (m_waitToDump && !waitToDumpWatchdog) {
634        waitToDumpWatchdog = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + waitToDumpWatchdogInterval, 0, 0, 0, waitUntilDoneWatchdogFired, NULL);
635        CFRunLoopAddTimer(CFRunLoopGetCurrent(), waitToDumpWatchdog, kCFRunLoopCommonModes);
636    }
637}
638
639int LayoutTestController::windowCount()
640{
641    return CFArrayGetCount(openWindowsRef);
642}
643
644bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef jsString)
645{
646    RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, jsString));
647    NSString *idNS = (NSString *)idCF.get();
648
649    DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS];
650    id rep = [[mainFrame dataSource] representation];
651
652    if ([rep class] == [WebHTMLRepresentation class])
653        return [(WebHTMLRepresentation *)rep elementDoesAutoComplete:element];
654
655    return false;
656}
657
658void LayoutTestController::execCommand(JSStringRef name, JSStringRef value)
659{
660    RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
661    NSString *nameNS = (NSString *)nameCF.get();
662
663    RetainPtr<CFStringRef> valueCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, value));
664    NSString *valueNS = (NSString *)valueCF.get();
665
666    [[mainFrame webView] _executeCoreCommandByName:nameNS value:valueNS];
667}
668
669bool LayoutTestController::findString(JSContextRef context, JSStringRef target, JSObjectRef optionsArray)
670{
671    WebFindOptions options = 0;
672
673    JSRetainPtr<JSStringRef> lengthPropertyName(Adopt, JSStringCreateWithUTF8CString("length"));
674    JSValueRef lengthValue = JSObjectGetProperty(context, optionsArray, lengthPropertyName.get(), 0);
675    if (!JSValueIsNumber(context, lengthValue))
676        return false;
677
678    RetainPtr<CFStringRef> targetCFString(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, target));
679
680    size_t length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0));
681    for (size_t i = 0; i < length; ++i) {
682        JSValueRef value = JSObjectGetPropertyAtIndex(context, optionsArray, i, 0);
683        if (!JSValueIsString(context, value))
684            continue;
685
686        JSRetainPtr<JSStringRef> optionName(Adopt, JSValueToStringCopy(context, value, 0));
687
688        if (JSStringIsEqualToUTF8CString(optionName.get(), "CaseInsensitive"))
689            options |= WebFindOptionsCaseInsensitive;
690        else if (JSStringIsEqualToUTF8CString(optionName.get(), "AtWordStarts"))
691            options |= WebFindOptionsAtWordStarts;
692        else if (JSStringIsEqualToUTF8CString(optionName.get(), "TreatMedialCapitalAsWordStart"))
693            options |= WebFindOptionsTreatMedialCapitalAsWordStart;
694        else if (JSStringIsEqualToUTF8CString(optionName.get(), "Backwards"))
695            options |= WebFindOptionsBackwards;
696        else if (JSStringIsEqualToUTF8CString(optionName.get(), "WrapAround"))
697            options |= WebFindOptionsWrapAround;
698        else if (JSStringIsEqualToUTF8CString(optionName.get(), "StartInSelection"))
699            options |= WebFindOptionsStartInSelection;
700    }
701
702    return [[mainFrame webView] findString:(NSString *)targetCFString.get() options:options];
703}
704
705void LayoutTestController::setCacheModel(int cacheModel)
706{
707    [[WebPreferences standardPreferences] setCacheModel:cacheModel];
708}
709
710bool LayoutTestController::isCommandEnabled(JSStringRef name)
711{
712    RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
713    NSString *nameNS = (NSString *)nameCF.get();
714
715    // Accept command strings with capital letters for first letter without trailing colon.
716    if (![nameNS hasSuffix:@":"] && [nameNS length]) {
717        nameNS = [[[[nameNS substringToIndex:1] lowercaseString]
718            stringByAppendingString:[nameNS substringFromIndex:1]]
719            stringByAppendingString:@":"];
720    }
721
722    SEL selector = NSSelectorFromString(nameNS);
723    RetainPtr<CommandValidationTarget> target(AdoptNS, [[CommandValidationTarget alloc] initWithAction:selector]);
724    id validator = [NSApp targetForAction:selector to:[mainFrame webView] from:target.get()];
725    if (!validator)
726        return false;
727    if (![validator respondsToSelector:selector])
728        return false;
729    if (![validator respondsToSelector:@selector(validateUserInterfaceItem:)])
730        return true;
731    return [validator validateUserInterfaceItem:target.get()];
732}
733
734bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId)
735{
736    RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, elementId));
737    NSString *idNS = (NSString *)idCF.get();
738    RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, animationName));
739    NSString *nameNS = (NSString *)nameCF.get();
740
741    return [mainFrame _pauseAnimation:nameNS onNode:[[mainFrame DOMDocument] getElementById:idNS] atTime:time];
742}
743
744bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(JSStringRef propertyName, double time, JSStringRef elementId)
745{
746    RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, elementId));
747    NSString *idNS = (NSString *)idCF.get();
748    RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, propertyName));
749    NSString *nameNS = (NSString *)nameCF.get();
750
751    return [mainFrame _pauseTransitionOfProperty:nameNS onNode:[[mainFrame DOMDocument] getElementById:idNS] atTime:time];
752}
753
754bool LayoutTestController::sampleSVGAnimationForElementAtTime(JSStringRef animationId, double time, JSStringRef elementId)
755{
756    RetainPtr<CFStringRef> animationIDCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, animationId));
757    NSString *animationIDNS = (NSString *)animationIDCF.get();
758    RetainPtr<CFStringRef> elementIDCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, elementId));
759    NSString *elementIDNS = (NSString *)elementIDCF.get();
760
761    return [mainFrame _pauseSVGAnimation:elementIDNS onSMILNode:[[mainFrame DOMDocument] getElementById:animationIDNS] atTime:time];
762}
763
764unsigned LayoutTestController::numberOfActiveAnimations() const
765{
766    return [mainFrame _numberOfActiveAnimations];
767}
768
769void LayoutTestController::suspendAnimations() const
770{
771    return [mainFrame _suspendAnimations];
772}
773
774void LayoutTestController::resumeAnimations() const
775{
776    return [mainFrame _resumeAnimations];
777}
778
779void LayoutTestController::waitForPolicyDelegate()
780{
781    setWaitToDump(true);
782    [policyDelegate setControllerToNotifyDone:this];
783    [[mainFrame webView] setPolicyDelegate:policyDelegate];
784}
785
786void LayoutTestController::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
787{
788    RetainPtr<CFStringRef> sourceOriginCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, sourceOrigin));
789    NSString *sourceOriginNS = (NSString *)sourceOriginCF.get();
790    RetainPtr<CFStringRef> protocolCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationProtocol));
791    NSString *destinationProtocolNS = (NSString *)protocolCF.get();
792    RetainPtr<CFStringRef> hostCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationHost));
793    NSString *destinationHostNS = (NSString *)hostCF.get();
794    [WebView _addOriginAccessWhitelistEntryWithSourceOrigin:sourceOriginNS destinationProtocol:destinationProtocolNS destinationHost:destinationHostNS allowDestinationSubdomains:allowDestinationSubdomains];
795}
796
797void LayoutTestController::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
798{
799    RetainPtr<CFStringRef> sourceOriginCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, sourceOrigin));
800    NSString *sourceOriginNS = (NSString *)sourceOriginCF.get();
801    RetainPtr<CFStringRef> protocolCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationProtocol));
802    NSString *destinationProtocolNS = (NSString *)protocolCF.get();
803    RetainPtr<CFStringRef> hostCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationHost));
804    NSString *destinationHostNS = (NSString *)hostCF.get();
805    [WebView _removeOriginAccessWhitelistEntryWithSourceOrigin:sourceOriginNS destinationProtocol:destinationProtocolNS destinationHost:destinationHostNS allowDestinationSubdomains:allowDestinationSubdomains];
806}
807
808void LayoutTestController::setScrollbarPolicy(JSStringRef orientation, JSStringRef policy)
809{
810    // FIXME: implement
811}
812
813void LayoutTestController::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
814{
815    RetainPtr<CFStringRef> sourceCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, source));
816    NSString *sourceNS = (NSString *)sourceCF.get();
817    [WebView _addUserScriptToGroup:@"org.webkit.DumpRenderTree" world:[WebScriptWorld world] source:sourceNS url:nil whitelist:nil blacklist:nil injectionTime:(runAtStart ? WebInjectAtDocumentStart : WebInjectAtDocumentEnd) injectedFrames:(allFrames ? WebInjectInAllFrames : WebInjectInTopFrameOnly)];
818}
819
820void LayoutTestController::addUserStyleSheet(JSStringRef source, bool allFrames)
821{
822    RetainPtr<CFStringRef> sourceCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, source));
823    NSString *sourceNS = (NSString *)sourceCF.get();
824    [WebView _addUserStyleSheetToGroup:@"org.webkit.DumpRenderTree" world:[WebScriptWorld world] source:sourceNS url:nil whitelist:nil blacklist:nil injectedFrames:(allFrames ? WebInjectInAllFrames : WebInjectInTopFrameOnly)];
825}
826
827void LayoutTestController::setDeveloperExtrasEnabled(bool enabled)
828{
829    [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:enabled];
830}
831
832void LayoutTestController::setAsynchronousSpellCheckingEnabled(bool enabled)
833{
834    [[[mainFrame webView] preferences] setAsynchronousSpellCheckingEnabled:enabled];
835}
836
837void LayoutTestController::showWebInspector()
838{
839    [[[mainFrame webView] inspector] show:nil];
840}
841
842void LayoutTestController::closeWebInspector()
843{
844    [[[mainFrame webView] inspector] close:nil];
845}
846
847void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef script)
848{
849    RetainPtr<CFStringRef> scriptCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, script));
850    NSString *scriptNS = (NSString *)scriptCF.get();
851    [[[mainFrame webView] inspector] evaluateInFrontend:nil callId:callId script:scriptNS];
852}
853
854typedef HashMap<unsigned, RetainPtr<WebScriptWorld> > WorldMap;
855static WorldMap& worldMap()
856{
857    static WorldMap& map = *new WorldMap;
858    return map;
859}
860
861unsigned worldIDForWorld(WebScriptWorld *world)
862{
863    WorldMap::const_iterator end = worldMap().end();
864    for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
865        if (it->second == world)
866            return it->first;
867    }
868
869    return 0;
870}
871
872void LayoutTestController::evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
873{
874    RetainPtr<CFStringRef> scriptCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, script));
875    NSString *scriptNS = (NSString *)scriptCF.get();
876
877    // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
878    // that is created once and cached forever.
879    WebScriptWorld *world;
880    if (!worldID)
881        world = [WebScriptWorld world];
882    else {
883        RetainPtr<WebScriptWorld>& worldSlot = worldMap().add(worldID, 0).first->second;
884        if (!worldSlot)
885            worldSlot.adoptNS([[WebScriptWorld alloc] init]);
886        world = worldSlot.get();
887    }
888
889    [mainFrame _stringByEvaluatingJavaScriptFromString:scriptNS withGlobalObject:globalObject inScriptWorld:world];
890}
891
892@interface APITestDelegate : NSObject
893{
894    bool* m_condition;
895}
896@end
897
898@implementation APITestDelegate
899
900- (id)initWithCompletionCondition:(bool*)condition
901{
902    [super init];
903    ASSERT(condition);
904    m_condition = condition;
905    *m_condition = false;
906    return self;
907}
908
909- (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
910{
911    printf("API Test load failed\n");
912    *m_condition = true;
913}
914
915- (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
916{
917    printf("API Test load failed provisional\n");
918    *m_condition = true;
919}
920
921- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
922{
923    printf("API Test load succeeded\n");
924    *m_condition = true;
925}
926
927@end
928
929void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
930{
931    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
932
933    RetainPtr<CFStringRef> utf8DataCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, utf8Data));
934    RetainPtr<CFStringRef> baseURLCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, baseURL));
935
936    WebView *webView = [[WebView alloc] initWithFrame:NSZeroRect frameName:@"" groupName:@""];
937
938    bool done = false;
939    APITestDelegate *delegate = [[APITestDelegate alloc] initWithCompletionCondition:&done];
940    [webView setFrameLoadDelegate:delegate];
941
942    [[webView mainFrame] loadData:[(NSString *)utf8DataCF.get() dataUsingEncoding:NSUTF8StringEncoding] MIMEType:@"text/html" textEncodingName:@"utf-8" baseURL:[NSURL URLWithString:(NSString *)baseURLCF.get()]];
943
944    while (!done) {
945        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
946        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]];
947        [pool release];
948    }
949
950    [webView close];
951    [webView release];
952    [delegate release];
953    [pool release];
954}
955
956void LayoutTestController::apiTestGoToCurrentBackForwardItem()
957{
958    WebView *view = [mainFrame webView];
959    [view goToBackForwardItem:[[view backForwardList] currentItem]];
960}
961
962void LayoutTestController::setWebViewEditable(bool editable)
963{
964    WebView *view = [mainFrame webView];
965    [view setEditable:editable];
966}
967
968#ifndef BUILDING_ON_TIGER
969static NSString *SynchronousLoaderRunLoopMode = @"DumpRenderTreeSynchronousLoaderRunLoopMode";
970
971#if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD)
972@protocol NSURLConnectionDelegate <NSObject>
973@end
974#endif
975
976@interface SynchronousLoader : NSObject <NSURLConnectionDelegate>
977{
978    NSString *m_username;
979    NSString *m_password;
980    BOOL m_isDone;
981}
982+ (void)makeRequest:(NSURLRequest *)request withUsername:(NSString *)username password:(NSString *)password;
983@end
984
985@implementation SynchronousLoader : NSObject
986- (void)dealloc
987{
988    [m_username release];
989    [m_password release];
990
991    [super dealloc];
992}
993
994- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection
995{
996    return YES;
997}
998
999- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
1000{
1001    if ([challenge previousFailureCount] == 0) {
1002        RetainPtr<NSURLCredential> credential(AdoptNS, [[NSURLCredential alloc]  initWithUser:m_username password:m_password persistence:NSURLCredentialPersistenceForSession]);
1003        [[challenge sender] useCredential:credential.get() forAuthenticationChallenge:challenge];
1004        return;
1005    }
1006    [[challenge sender] cancelAuthenticationChallenge:challenge];
1007}
1008
1009- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
1010{
1011    printf("SynchronousLoader failed: %s\n", [[error description] UTF8String]);
1012    m_isDone = YES;
1013}
1014
1015- (void)connectionDidFinishLoading:(NSURLConnection *)connection
1016{
1017    m_isDone = YES;
1018}
1019
1020+ (void)makeRequest:(NSURLRequest *)request withUsername:(NSString *)username password:(NSString *)password
1021{
1022    ASSERT(![[request URL] user]);
1023    ASSERT(![[request URL] password]);
1024
1025    SynchronousLoader *delegate = [[SynchronousLoader alloc] init];
1026    delegate->m_username = [username copy];
1027    delegate->m_password = [password copy];
1028
1029    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate startImmediately:NO];
1030    [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:SynchronousLoaderRunLoopMode];
1031    [connection start];
1032
1033    while (!delegate->m_isDone)
1034        [[NSRunLoop currentRunLoop] runMode:SynchronousLoaderRunLoopMode beforeDate:[NSDate distantFuture]];
1035
1036    [connection cancel];
1037
1038    [connection release];
1039    [delegate release];
1040}
1041
1042@end
1043#endif
1044
1045void LayoutTestController::authenticateSession(JSStringRef url, JSStringRef username, JSStringRef password)
1046{
1047    // See <rdar://problem/7880699>.
1048#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
1049    RetainPtr<CFStringRef> urlStringCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url));
1050    RetainPtr<CFStringRef> usernameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, username));
1051    RetainPtr<CFStringRef> passwordCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, password));
1052
1053    RetainPtr<NSURLRequest> request(AdoptNS, [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:(NSString *)urlStringCF.get()]]);
1054
1055    [SynchronousLoader makeRequest:request.get() withUsername:(NSString *)usernameCF.get() password:(NSString *)passwordCF.get()];
1056#endif
1057}
1058
1059void LayoutTestController::setEditingBehavior(const char* editingBehavior)
1060{
1061    NSString* editingBehaviorNS = [[NSString alloc] initWithUTF8String:editingBehavior];
1062    if ([editingBehaviorNS isEqualToString:@"mac"])
1063        [[WebPreferences standardPreferences] setEditingBehavior:WebKitEditingMacBehavior];
1064    else if ([editingBehaviorNS isEqualToString:@"win"])
1065        [[WebPreferences standardPreferences] setEditingBehavior:WebKitEditingWinBehavior];
1066    else if ([editingBehaviorNS isEqualToString:@"unix"])
1067        [[WebPreferences standardPreferences] setEditingBehavior:WebKitEditingUnixBehavior];
1068    [editingBehaviorNS release];
1069}
1070
1071JSValueRef LayoutTestController::shadowRoot(JSContextRef context, JSValueRef jsElement)
1072{
1073    DOMElement *element = [DOMElement _DOMElementFromJSContext:context value:jsElement];
1074    if (!element)
1075        return JSValueMakeNull(context);
1076    return [element _shadowRoot:context];
1077}
1078
1079void LayoutTestController::abortModal()
1080{
1081    [NSApp abortModal];
1082}
1083
1084bool LayoutTestController::hasSpellingMarker(int from, int length)
1085{
1086    return [mainFrame hasSpellingMarker:from length:length];
1087}
1088
1089bool LayoutTestController::hasGrammarMarker(int from, int length)
1090{
1091    return [mainFrame hasGrammarMarker:from length:length];
1092}
1093
1094void LayoutTestController::dumpConfigurationForViewport(int /*deviceDPI*/, int /*deviceWidth*/, int /*deviceHeight*/, int /*availableWidth*/, int /*availableHeight*/)
1095{
1096
1097}
1098
1099void LayoutTestController::setSerializeHTTPLoads(bool serialize)
1100{
1101    [WebView _setLoadResourcesSerially:serialize];
1102}
1103
1104void LayoutTestController::setMinimumTimerInterval(double minimumTimerInterval)
1105{
1106    [[mainFrame webView] _setMinimumTimerInterval:minimumTimerInterval];
1107}
1108