Home | History | Annotate | Download | only in mac
      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 "PolicyDelegate.h"
     35 #import "WorkQueue.h"
     36 #import "WorkQueueItem.h"
     37 #import <Foundation/Foundation.h>
     38 #import <JavaScriptCore/JSRetainPtr.h>
     39 #import <JavaScriptCore/JSStringRef.h>
     40 #import <JavaScriptCore/JSStringRefCF.h>
     41 #import <WebKit/DOMDocument.h>
     42 #import <WebKit/DOMElement.h>
     43 #import <WebKit/WebApplicationCache.h>
     44 #import <WebKit/WebBackForwardList.h>
     45 #import <WebKit/WebCoreStatistics.h>
     46 #import <WebKit/WebDataSource.h>
     47 #import <WebKit/WebDatabaseManagerPrivate.h>
     48 #import <WebKit/WebFrame.h>
     49 #import <WebKit/WebFrameViewPrivate.h>
     50 #import <WebKit/WebGeolocationMockPrivate.h>
     51 #import <WebKit/WebHTMLRepresentation.h>
     52 #import <WebKit/WebHTMLViewPrivate.h>
     53 #import <WebKit/WebHistory.h>
     54 #import <WebKit/WebHistoryPrivate.h>
     55 #import <WebKit/WebIconDatabasePrivate.h>
     56 #import <WebKit/WebInspectorPrivate.h>
     57 #import <WebKit/WebNSURLExtras.h>
     58 #import <WebKit/WebPreferences.h>
     59 #import <WebKit/WebPreferencesPrivate.h>
     60 #import <WebKit/WebScriptWorld.h>
     61 #import <WebKit/WebSecurityOriginPrivate.h>
     62 #import <WebKit/WebTypesInternal.h>
     63 #import <WebKit/WebView.h>
     64 #import <WebKit/WebViewPrivate.h>
     65 #import <WebKit/WebWorkersPrivate.h>
     66 #import <wtf/HashMap.h>
     67 #import <wtf/RetainPtr.h>
     68 
     69 @interface CommandValidationTarget : NSObject <NSValidatedUserInterfaceItem>
     70 {
     71     SEL _action;
     72 }
     73 - (id)initWithAction:(SEL)action;
     74 @end
     75 
     76 @implementation CommandValidationTarget
     77 
     78 - (id)initWithAction:(SEL)action
     79 {
     80     self = [super init];
     81     if (!self)
     82         return nil;
     83 
     84     _action = action;
     85     return self;
     86 }
     87 
     88 - (SEL)action
     89 {
     90     return _action;
     91 }
     92 
     93 - (NSInteger)tag
     94 {
     95     return 0;
     96 }
     97 
     98 @end
     99 
    100 LayoutTestController::~LayoutTestController()
    101 {
    102 }
    103 
    104 void LayoutTestController::addDisallowedURL(JSStringRef url)
    105 {
    106     RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url));
    107 
    108     if (!disallowedURLs)
    109         disallowedURLs = CFSetCreateMutable(kCFAllocatorDefault, 0, NULL);
    110 
    111     // Canonicalize the URL
    112     NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:(NSString *)urlCF.get()]];
    113     request = [NSURLProtocol canonicalRequestForRequest:request];
    114 
    115     CFSetAddValue(disallowedURLs, [request URL]);
    116 }
    117 
    118 void LayoutTestController::clearAllDatabases()
    119 {
    120     [[WebDatabaseManager sharedWebDatabaseManager] deleteAllDatabases];
    121 }
    122 
    123 void LayoutTestController::clearBackForwardList()
    124 {
    125     WebBackForwardList *backForwardList = [[mainFrame webView] backForwardList];
    126     WebHistoryItem *item = [[backForwardList currentItem] retain];
    127 
    128     // We clear the history by setting the back/forward list's capacity to 0
    129     // then restoring it back and adding back the current item.
    130     int capacity = [backForwardList capacity];
    131     [backForwardList setCapacity:0];
    132     [backForwardList setCapacity:capacity];
    133     [backForwardList addItem:item];
    134     [backForwardList goToItem:item];
    135     [item release];
    136 }
    137 
    138 JSStringRef LayoutTestController::copyDecodedHostName(JSStringRef name)
    139 {
    140     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
    141     NSString *nameNS = (NSString *)nameCF.get();
    142     return JSStringCreateWithCFString((CFStringRef)[nameNS _web_decodeHostName]);
    143 }
    144 
    145 JSStringRef LayoutTestController::copyEncodedHostName(JSStringRef name)
    146 {
    147     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
    148     NSString *nameNS = (NSString *)nameCF.get();
    149     return JSStringCreateWithCFString((CFStringRef)[nameNS _web_encodeHostName]);
    150 }
    151 
    152 void LayoutTestController::display()
    153 {
    154     displayWebView();
    155 }
    156 
    157 JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id)
    158 {
    159     RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, id));
    160     NSString *idNS = (NSString *)idCF.get();
    161 
    162     DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS];
    163     if (!element)
    164         return 0;
    165 
    166     JSRetainPtr<JSStringRef> counterValue(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame counterValueForElement:element]));
    167     return counterValue;
    168 }
    169 
    170 void LayoutTestController::keepWebHistory()
    171 {
    172     if (![WebHistory optionalSharedHistory]) {
    173         WebHistory *history = [[WebHistory alloc] init];
    174         [WebHistory setOptionalSharedHistory:history];
    175         [history release];
    176     }
    177 }
    178 
    179 int LayoutTestController::pageNumberForElementById(JSStringRef id, float pageWidthInPixels, float pageHeightInPixels)
    180 {
    181     RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, id));
    182     NSString *idNS = (NSString *)idCF.get();
    183 
    184     DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS];
    185     if (!element)
    186         return -1;
    187 
    188     return [mainFrame pageNumberForElement:element:pageWidthInPixels:pageHeightInPixels];
    189 }
    190 
    191 int LayoutTestController::numberOfPages(float pageWidthInPixels, float pageHeightInPixels)
    192 {
    193     return [mainFrame numberOfPages:pageWidthInPixels:pageHeightInPixels];
    194 }
    195 
    196 size_t LayoutTestController::webHistoryItemCount()
    197 {
    198     return [[[WebHistory optionalSharedHistory] allItems] count];
    199 }
    200 
    201 unsigned LayoutTestController::workerThreadCount() const
    202 {
    203     return [WebWorkersPrivate workerThreadCount];
    204 }
    205 
    206 void LayoutTestController::notifyDone()
    207 {
    208     if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count())
    209         dump();
    210     m_waitToDump = false;
    211 }
    212 
    213 JSStringRef LayoutTestController::pathToLocalResource(JSContextRef context, JSStringRef url)
    214 {
    215     return JSStringRetain(url); // Do nothing on mac.
    216 }
    217 
    218 void LayoutTestController::queueLoad(JSStringRef url, JSStringRef target)
    219 {
    220     RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url));
    221     NSString *urlNS = (NSString *)urlCF.get();
    222 
    223     NSURL *nsurl = [NSURL URLWithString:urlNS relativeToURL:[[[mainFrame dataSource] response] URL]];
    224     NSString* nsurlString = [nsurl absoluteString];
    225 
    226     JSRetainPtr<JSStringRef> absoluteURL(Adopt, JSStringCreateWithUTF8CString([nsurlString UTF8String]));
    227     WorkQueue::shared()->queue(new LoadItem(absoluteURL.get(), target));
    228 }
    229 
    230 void LayoutTestController::setAcceptsEditing(bool newAcceptsEditing)
    231 {
    232     [(EditingDelegate *)[[mainFrame webView] editingDelegate] setAcceptsEditing:newAcceptsEditing];
    233 }
    234 
    235 void LayoutTestController::setAlwaysAcceptCookies(bool alwaysAcceptCookies)
    236 {
    237     if (alwaysAcceptCookies == m_alwaysAcceptCookies)
    238         return;
    239 
    240     m_alwaysAcceptCookies = alwaysAcceptCookies;
    241     NSHTTPCookieAcceptPolicy cookieAcceptPolicy = alwaysAcceptCookies ? NSHTTPCookieAcceptPolicyAlways : NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain;
    242     [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:cookieAcceptPolicy];
    243 }
    244 
    245 void LayoutTestController::setAppCacheMaximumSize(unsigned long long size)
    246 {
    247     [WebApplicationCache setMaximumSize:size];
    248 }
    249 
    250 void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag)
    251 {
    252     [[[mainFrame webView] preferences] setAuthorAndUserStylesEnabled:flag];
    253 }
    254 
    255 void LayoutTestController::setCustomPolicyDelegate(bool setDelegate, bool permissive)
    256 {
    257     if (setDelegate) {
    258         [policyDelegate setPermissive:permissive];
    259         [[mainFrame webView] setPolicyDelegate:policyDelegate];
    260     } else
    261         [[mainFrame webView] setPolicyDelegate:nil];
    262 }
    263 
    264 void LayoutTestController::setDatabaseQuota(unsigned long long quota)
    265 {
    266     WebSecurityOrigin *origin = [[WebSecurityOrigin alloc] initWithURL:[NSURL URLWithString:@"file:///"]];
    267     [origin setQuota:quota];
    268     [origin release];
    269 }
    270 
    271 void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme)
    272 {
    273     RetainPtr<CFStringRef> schemeCFString(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, scheme));
    274     [WebView _setDomainRelaxationForbidden:forbidden forURLScheme:(NSString *)schemeCFString.get()];
    275 }
    276 
    277 void LayoutTestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy)
    278 {
    279     [WebGeolocationMock setPosition:latitude:longitude:accuracy];
    280 }
    281 
    282 void LayoutTestController::setMockGeolocationError(int code, JSStringRef message)
    283 {
    284     RetainPtr<CFStringRef> messageCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, message));
    285     NSString *messageNS = (NSString *)messageCF.get();
    286     [WebGeolocationMock setError:code:messageNS];
    287 }
    288 
    289 void LayoutTestController::setIconDatabaseEnabled(bool iconDatabaseEnabled)
    290 {
    291     // FIXME: Workaround <rdar://problem/6480108>
    292     static WebIconDatabase* sharedWebIconDatabase = NULL;
    293     if (!sharedWebIconDatabase) {
    294         if (!iconDatabaseEnabled)
    295             return;
    296         sharedWebIconDatabase = [WebIconDatabase sharedIconDatabase];
    297         if ([sharedWebIconDatabase isEnabled] == iconDatabaseEnabled)
    298             return;
    299     }
    300     [sharedWebIconDatabase setEnabled:iconDatabaseEnabled];
    301 }
    302 
    303 void LayoutTestController::setJavaScriptProfilingEnabled(bool profilingEnabled)
    304 {
    305     [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:profilingEnabled];
    306     [[[mainFrame webView] inspector] setJavaScriptProfilingEnabled:profilingEnabled];
    307 }
    308 
    309 void LayoutTestController::setMainFrameIsFirstResponder(bool flag)
    310 {
    311     NSView *documentView = [[mainFrame frameView] documentView];
    312 
    313     NSResponder *firstResponder = flag ? documentView : nil;
    314     [[[mainFrame webView] window] makeFirstResponder:firstResponder];
    315 }
    316 
    317 void LayoutTestController::setPrivateBrowsingEnabled(bool privateBrowsingEnabled)
    318 {
    319     [[[mainFrame webView] preferences] setPrivateBrowsingEnabled:privateBrowsingEnabled];
    320 }
    321 
    322 void LayoutTestController::setXSSAuditorEnabled(bool enabled)
    323 {
    324     [[[mainFrame webView] preferences] setXSSAuditorEnabled:enabled];
    325 }
    326 
    327 void LayoutTestController::setFrameSetFlatteningEnabled(bool enabled)
    328 {
    329     [[[mainFrame webView] preferences] setFrameSetFlatteningEnabled:enabled];
    330 }
    331 
    332 void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
    333 {
    334     [[[mainFrame webView] preferences] setAllowUniversalAccessFromFileURLs:enabled];
    335 }
    336 
    337 void LayoutTestController::setPopupBlockingEnabled(bool popupBlockingEnabled)
    338 {
    339     [[[mainFrame webView] preferences] setJavaScriptCanOpenWindowsAutomatically:!popupBlockingEnabled];
    340 }
    341 
    342 void LayoutTestController::setTabKeyCyclesThroughElements(bool cycles)
    343 {
    344     [[mainFrame webView] setTabKeyCyclesThroughElements:cycles];
    345 }
    346 
    347 void LayoutTestController::setTimelineProfilingEnabled(bool enabled)
    348 {
    349     [[[mainFrame webView] inspector] setTimelineProfilingEnabled:enabled];
    350 }
    351 
    352 void LayoutTestController::setUseDashboardCompatibilityMode(bool flag)
    353 {
    354     [[mainFrame webView] _setDashboardBehavior:WebDashboardBehaviorUseBackwardCompatibilityMode to:flag];
    355 }
    356 
    357 void LayoutTestController::setUserStyleSheetEnabled(bool flag)
    358 {
    359     [[WebPreferences standardPreferences] setUserStyleSheetEnabled:flag];
    360 }
    361 
    362 void LayoutTestController::setUserStyleSheetLocation(JSStringRef path)
    363 {
    364     RetainPtr<CFStringRef> pathCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, path));
    365     NSURL *url = [NSURL URLWithString:(NSString *)pathCF.get()];
    366     [[WebPreferences standardPreferences] setUserStyleSheetLocation:url];
    367 }
    368 
    369 void LayoutTestController::disableImageLoading()
    370 {
    371     [[WebPreferences standardPreferences] setLoadsImagesAutomatically:NO];
    372 }
    373 
    374 void LayoutTestController::dispatchPendingLoadRequests()
    375 {
    376     [[mainFrame webView] _dispatchPendingLoadRequests];
    377 }
    378 
    379 void LayoutTestController::overridePreference(JSStringRef key, JSStringRef value)
    380 {
    381     RetainPtr<CFStringRef> keyCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, key));
    382     NSString *keyNS = (NSString *)keyCF.get();
    383 
    384     RetainPtr<CFStringRef> valueCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, value));
    385     NSString *valueNS = (NSString *)valueCF.get();
    386 
    387     [[WebPreferences standardPreferences] _setPreferenceForTestWithValue:valueNS forKey:keyNS];
    388 }
    389 
    390 void LayoutTestController::removeAllVisitedLinks()
    391 {
    392     [WebHistory _removeAllVisitedLinks];
    393 }
    394 
    395 void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL)
    396 {
    397     RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
    398     ::setPersistentUserStyleSheetLocation(urlString.get());
    399 }
    400 
    401 void LayoutTestController::clearPersistentUserStyleSheet()
    402 {
    403     ::setPersistentUserStyleSheetLocation(0);
    404 }
    405 
    406 void LayoutTestController::setWindowIsKey(bool windowIsKey)
    407 {
    408     m_windowIsKey = windowIsKey;
    409     [[mainFrame webView] _updateActiveState];
    410 }
    411 
    412 void LayoutTestController::setSmartInsertDeleteEnabled(bool flag)
    413 {
    414     [[mainFrame webView] setSmartInsertDeleteEnabled:flag];
    415 }
    416 
    417 void LayoutTestController::setSelectTrailingWhitespaceEnabled(bool flag)
    418 {
    419     [[mainFrame webView] setSelectTrailingWhitespaceEnabled:flag];
    420 }
    421 
    422 static const CFTimeInterval waitToDumpWatchdogInterval = 15.0;
    423 
    424 static void waitUntilDoneWatchdogFired(CFRunLoopTimerRef timer, void* info)
    425 {
    426     gLayoutTestController->waitToDumpWatchdogTimerFired();
    427 }
    428 
    429 void LayoutTestController::setWaitToDump(bool waitUntilDone)
    430 {
    431     m_waitToDump = waitUntilDone;
    432     if (m_waitToDump && !waitToDumpWatchdog) {
    433         waitToDumpWatchdog = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + waitToDumpWatchdogInterval, 0, 0, 0, waitUntilDoneWatchdogFired, NULL);
    434         CFRunLoopAddTimer(CFRunLoopGetCurrent(), waitToDumpWatchdog, kCFRunLoopCommonModes);
    435     }
    436 }
    437 
    438 int LayoutTestController::windowCount()
    439 {
    440     return CFArrayGetCount(openWindowsRef);
    441 }
    442 
    443 bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef id)
    444 {
    445     RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, id));
    446     NSString *idNS = (NSString *)idCF.get();
    447 
    448     DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS];
    449     id rep = [[mainFrame dataSource] representation];
    450 
    451     if ([rep class] == [WebHTMLRepresentation class])
    452         return [(WebHTMLRepresentation *)rep elementDoesAutoComplete:element];
    453 
    454     return false;
    455 }
    456 
    457 void LayoutTestController::execCommand(JSStringRef name, JSStringRef value)
    458 {
    459     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
    460     NSString *nameNS = (NSString *)nameCF.get();
    461 
    462     RetainPtr<CFStringRef> valueCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, value));
    463     NSString *valueNS = (NSString *)valueCF.get();
    464 
    465     [[mainFrame webView] _executeCoreCommandByName:nameNS value:valueNS];
    466 }
    467 
    468 void LayoutTestController::setCacheModel(int cacheModel)
    469 {
    470     [[WebPreferences standardPreferences] setCacheModel:cacheModel];
    471 }
    472 
    473 bool LayoutTestController::isCommandEnabled(JSStringRef name)
    474 {
    475     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
    476     NSString *nameNS = reinterpret_cast<const NSString *>(nameCF.get());
    477 
    478     // Accept command strings with capital letters for first letter without trailing colon.
    479     if (![nameNS hasSuffix:@":"] && [nameNS length]) {
    480         nameNS = [[[[nameNS substringToIndex:1] lowercaseString]
    481             stringByAppendingString:[nameNS substringFromIndex:1]]
    482             stringByAppendingString:@":"];
    483     }
    484 
    485     SEL selector = NSSelectorFromString(nameNS);
    486     RetainPtr<CommandValidationTarget> target(AdoptNS, [[CommandValidationTarget alloc] initWithAction:selector]);
    487     id validator = [NSApp targetForAction:selector to:[mainFrame webView] from:target.get()];
    488     if (!validator)
    489         return false;
    490     if (![validator respondsToSelector:selector])
    491         return false;
    492     if (![validator respondsToSelector:@selector(validateUserInterfaceItem:)])
    493         return true;
    494     return [validator validateUserInterfaceItem:target.get()];
    495 }
    496 
    497 bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId)
    498 {
    499     RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, elementId));
    500     NSString *idNS = (NSString *)idCF.get();
    501     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, animationName));
    502     NSString *nameNS = (NSString *)nameCF.get();
    503 
    504     return [mainFrame _pauseAnimation:nameNS onNode:[[mainFrame DOMDocument] getElementById:idNS] atTime:time];
    505 }
    506 
    507 bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(JSStringRef propertyName, double time, JSStringRef elementId)
    508 {
    509     RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, elementId));
    510     NSString *idNS = (NSString *)idCF.get();
    511     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, propertyName));
    512     NSString *nameNS = (NSString *)nameCF.get();
    513 
    514     return [mainFrame _pauseTransitionOfProperty:nameNS onNode:[[mainFrame DOMDocument] getElementById:idNS] atTime:time];
    515 }
    516 
    517 bool LayoutTestController::sampleSVGAnimationForElementAtTime(JSStringRef animationId, double time, JSStringRef elementId)
    518 {
    519     RetainPtr<CFStringRef> animationIDCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, animationId));
    520     NSString *animationIDNS = (NSString *)animationIDCF.get();
    521     RetainPtr<CFStringRef> elementIDCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, elementId));
    522     NSString *elementIDNS = (NSString *)elementIDCF.get();
    523 
    524     return [mainFrame _pauseSVGAnimation:elementIDNS onSMILNode:[[mainFrame DOMDocument] getElementById:animationIDNS] atTime:time];
    525 }
    526 
    527 unsigned LayoutTestController::numberOfActiveAnimations() const
    528 {
    529     return [mainFrame _numberOfActiveAnimations];
    530 }
    531 
    532 void LayoutTestController::waitForPolicyDelegate()
    533 {
    534     setWaitToDump(true);
    535     [policyDelegate setControllerToNotifyDone:this];
    536     [[mainFrame webView] setPolicyDelegate:policyDelegate];
    537 }
    538 
    539 void LayoutTestController::whiteListAccessFromOrigin(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
    540 {
    541     RetainPtr<CFStringRef> sourceOriginCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, sourceOrigin));
    542     NSString *sourceOriginNS = (NSString *)sourceOriginCF.get();
    543     RetainPtr<CFStringRef> protocolCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationProtocol));
    544     NSString *destinationProtocolNS = (NSString *)protocolCF.get();
    545     RetainPtr<CFStringRef> hostCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationHost));
    546     NSString *destinationHostNS = (NSString *)hostCF.get();
    547     [WebView _whiteListAccessFromOrigin:sourceOriginNS destinationProtocol:destinationProtocolNS destinationHost:destinationHostNS allowDestinationSubdomains:allowDestinationSubdomains];
    548 }
    549 
    550 void LayoutTestController::addUserScript(JSStringRef source, bool runAtStart)
    551 {
    552     RetainPtr<CFStringRef> sourceCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, source));
    553     NSString *sourceNS = (NSString *)sourceCF.get();
    554     [WebView _addUserScriptToGroup:@"org.webkit.DumpRenderTree" world:[WebScriptWorld world] source:sourceNS url:nil whitelist:nil blacklist:nil injectionTime:(runAtStart ? WebInjectAtDocumentStart : WebInjectAtDocumentEnd)];
    555 }
    556 
    557 void LayoutTestController::addUserStyleSheet(JSStringRef source)
    558 {
    559     RetainPtr<CFStringRef> sourceCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, source));
    560     NSString *sourceNS = (NSString *)sourceCF.get();
    561     [WebView _addUserStyleSheetToGroup:@"org.webkit.DumpRenderTree" world:[WebScriptWorld world] source:sourceNS url:nil whitelist:nil blacklist:nil];
    562 }
    563 
    564 void LayoutTestController::showWebInspector()
    565 {
    566     [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:true];
    567     [[[mainFrame webView] inspector] show:nil];
    568 }
    569 
    570 void LayoutTestController::closeWebInspector()
    571 {
    572     [[[mainFrame webView] inspector] close:nil];
    573     [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:false];
    574 }
    575 
    576 void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef script)
    577 {
    578     RetainPtr<CFStringRef> scriptCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, script));
    579     NSString *scriptNS = (NSString *)scriptCF.get();
    580     [[[mainFrame webView] inspector] evaluateInFrontend:nil callId:callId script:scriptNS];
    581 }
    582 
    583 typedef HashMap<unsigned, RetainPtr<WebScriptWorld> > WorldMap;
    584 static WorldMap& worldMap()
    585 {
    586     static WorldMap& map = *new WorldMap;
    587     return map;
    588 }
    589 
    590 unsigned worldIDForWorld(WebScriptWorld *world)
    591 {
    592     WorldMap::const_iterator end = worldMap().end();
    593     for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
    594         if (it->second == world)
    595             return it->first;
    596     }
    597 
    598     return 0;
    599 }
    600 
    601 void LayoutTestController::evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
    602 {
    603     RetainPtr<CFStringRef> scriptCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, script));
    604     NSString *scriptNS = (NSString *)scriptCF.get();
    605 
    606     // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
    607     // that is created once and cached forever.
    608     WebScriptWorld *world;
    609     if (!worldID)
    610         world = [WebScriptWorld world];
    611     else {
    612         RetainPtr<WebScriptWorld>& worldSlot = worldMap().add(worldID, 0).first->second;
    613         if (!worldSlot)
    614             worldSlot.adoptNS([[WebScriptWorld alloc] init]);
    615         world = worldSlot.get();
    616     }
    617 
    618     [mainFrame _stringByEvaluatingJavaScriptFromString:scriptNS withGlobalObject:globalObject inScriptWorld:world];
    619 }
    620