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