WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     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 "WorkQueue.h"
       
    37 #import "WorkQueueItem.h"
       
    38 #import <Foundation/Foundation.h>
       
    39 #import <JavaScriptCore/JSRetainPtr.h>
       
    40 #import <JavaScriptCore/JSStringRef.h>
       
    41 #import <JavaScriptCore/JSStringRefCF.h>
       
    42 #import <WebKit/DOMDocument.h>
       
    43 #import <WebKit/DOMElement.h>
       
    44 #import <WebKit/WebApplicationCache.h>
       
    45 #import <WebKit/WebBackForwardList.h>
       
    46 #import <WebKit/WebCoreStatistics.h>
       
    47 #import <WebKit/WebDataSource.h>
       
    48 #import <WebKit/WebDatabaseManagerPrivate.h>
       
    49 #import <WebKit/WebDOMOperationsPrivate.h>
       
    50 #import <WebKit/WebFrame.h>
       
    51 #import <WebKit/WebFrameViewPrivate.h>
       
    52 #import <WebKit/WebGeolocationPosition.h>
       
    53 #import <WebKit/WebHTMLRepresentation.h>
       
    54 #import <WebKit/WebHTMLViewPrivate.h>
       
    55 #import <WebKit/WebHistory.h>
       
    56 #import <WebKit/WebHistoryPrivate.h>
       
    57 #import <WebKit/WebIconDatabasePrivate.h>
       
    58 #import <WebKit/WebInspectorPrivate.h>
       
    59 #import <WebKit/WebNSURLExtras.h>
       
    60 #import <WebKit/WebKitErrors.h>
       
    61 #import <WebKit/WebPreferences.h>
       
    62 #import <WebKit/WebPreferencesPrivate.h>
       
    63 #import <WebKit/WebScriptWorld.h>
       
    64 #import <WebKit/WebSecurityOriginPrivate.h>
       
    65 #import <WebKit/WebTypesInternal.h>
       
    66 #import <WebKit/WebView.h>
       
    67 #import <WebKit/WebViewPrivate.h>
       
    68 #import <WebKit/WebWorkersPrivate.h>
       
    69 #import <wtf/HashMap.h>
       
    70 #import <wtf/RetainPtr.h>
       
    71 
       
    72 @interface CommandValidationTarget : NSObject <NSValidatedUserInterfaceItem>
       
    73 {
       
    74     SEL _action;
       
    75 }
       
    76 - (id)initWithAction:(SEL)action;
       
    77 @end
       
    78 
       
    79 @implementation CommandValidationTarget
       
    80 
       
    81 - (id)initWithAction:(SEL)action
       
    82 {
       
    83     self = [super init];
       
    84     if (!self)
       
    85         return nil;
       
    86 
       
    87     _action = action;
       
    88     return self;
       
    89 }
       
    90 
       
    91 - (SEL)action
       
    92 {
       
    93     return _action;
       
    94 }
       
    95 
       
    96 - (NSInteger)tag
       
    97 {
       
    98     return 0;
       
    99 }
       
   100 
       
   101 @end
       
   102 
       
   103 LayoutTestController::~LayoutTestController()
       
   104 {
       
   105 }
       
   106 
       
   107 void LayoutTestController::addDisallowedURL(JSStringRef url)
       
   108 {
       
   109     RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url));
       
   110 
       
   111     if (!disallowedURLs)
       
   112         disallowedURLs = CFSetCreateMutable(kCFAllocatorDefault, 0, NULL);
       
   113 
       
   114     // Canonicalize the URL
       
   115     NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:(NSString *)urlCF.get()]];
       
   116     request = [NSURLProtocol canonicalRequestForRequest:request];
       
   117 
       
   118     CFSetAddValue(disallowedURLs, [request URL]);
       
   119 }
       
   120 
       
   121 bool LayoutTestController::callShouldCloseOnWebView()
       
   122 {
       
   123     return [[mainFrame webView] shouldClose];
       
   124 }
       
   125 
       
   126 void LayoutTestController::clearAllDatabases()
       
   127 {
       
   128     [[WebDatabaseManager sharedWebDatabaseManager] deleteAllDatabases];
       
   129 }
       
   130 
       
   131 void LayoutTestController::clearBackForwardList()
       
   132 {
       
   133     WebBackForwardList *backForwardList = [[mainFrame webView] backForwardList];
       
   134     WebHistoryItem *item = [[backForwardList currentItem] retain];
       
   135 
       
   136     // We clear the history by setting the back/forward list's capacity to 0
       
   137     // then restoring it back and adding back the current item.
       
   138     int capacity = [backForwardList capacity];
       
   139     [backForwardList setCapacity:0];
       
   140     [backForwardList setCapacity:capacity];
       
   141     [backForwardList addItem:item];
       
   142     [backForwardList goToItem:item];
       
   143     [item release];
       
   144 }
       
   145 
       
   146 JSStringRef LayoutTestController::copyDecodedHostName(JSStringRef name)
       
   147 {
       
   148     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
       
   149     NSString *nameNS = (NSString *)nameCF.get();
       
   150     return JSStringCreateWithCFString((CFStringRef)[nameNS _web_decodeHostName]);
       
   151 }
       
   152 
       
   153 JSStringRef LayoutTestController::copyEncodedHostName(JSStringRef name)
       
   154 {
       
   155     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
       
   156     NSString *nameNS = (NSString *)nameCF.get();
       
   157     return JSStringCreateWithCFString((CFStringRef)[nameNS _web_encodeHostName]);
       
   158 }
       
   159 
       
   160 void LayoutTestController::display()
       
   161 {
       
   162     displayWebView();
       
   163 }
       
   164 
       
   165 JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id)
       
   166 {
       
   167     RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, id));
       
   168     NSString *idNS = (NSString *)idCF.get();
       
   169 
       
   170     DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS];
       
   171     if (!element)
       
   172         return 0;
       
   173 
       
   174     JSRetainPtr<JSStringRef> counterValue(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame counterValueForElement:element]));
       
   175     return counterValue;
       
   176 }
       
   177 
       
   178 void LayoutTestController::keepWebHistory()
       
   179 {
       
   180     if (![WebHistory optionalSharedHistory]) {
       
   181         WebHistory *history = [[WebHistory alloc] init];
       
   182         [WebHistory setOptionalSharedHistory:history];
       
   183         [history release];
       
   184     }
       
   185 }
       
   186 
       
   187 JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSContextRef context, JSValueRef value)
       
   188 {   
       
   189     return [[mainFrame webView] _computedStyleIncludingVisitedInfo:context forElement:value];
       
   190 }
       
   191 
       
   192 JSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const
       
   193 {
       
   194     JSRetainPtr<JSStringRef> string(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame _layerTreeAsText]));
       
   195     return string;
       
   196 }
       
   197 
       
   198 JSRetainPtr<JSStringRef> LayoutTestController::markerTextForListItem(JSContextRef context, JSValueRef nodeObject) const
       
   199 {
       
   200     DOMElement *element = [DOMElement _DOMElementFromJSContext:context value:nodeObject];
       
   201     if (!element)
       
   202         return JSRetainPtr<JSStringRef>();
       
   203 
       
   204     JSRetainPtr<JSStringRef> markerText(Adopt, JSStringCreateWithCFString((CFStringRef)[element _markerTextForListItem]));
       
   205     return markerText;
       
   206 }
       
   207 
       
   208 int LayoutTestController::pageNumberForElementById(JSStringRef id, float pageWidthInPixels, float pageHeightInPixels)
       
   209 {
       
   210     RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, id));
       
   211     NSString *idNS = (NSString *)idCF.get();
       
   212 
       
   213     DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS];
       
   214     if (!element)
       
   215         return -1;
       
   216 
       
   217     return [mainFrame pageNumberForElement:element:pageWidthInPixels:pageHeightInPixels];
       
   218 }
       
   219 
       
   220 JSRetainPtr<JSStringRef> LayoutTestController::pageProperty(const char* propertyName, int pageNumber) const
       
   221 {
       
   222     JSRetainPtr<JSStringRef> propertyValue(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame pageProperty:propertyName:pageNumber]));
       
   223     return propertyValue;
       
   224 }
       
   225 
       
   226 bool LayoutTestController::isPageBoxVisible(int pageNumber) const
       
   227 {
       
   228     return [mainFrame isPageBoxVisible:pageNumber];
       
   229 }
       
   230 
       
   231 JSRetainPtr<JSStringRef> LayoutTestController::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) const
       
   232 {
       
   233     JSRetainPtr<JSStringRef> propertyValue(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame pageSizeAndMarginsInPixels:pageNumber:width:height:marginTop:marginRight:marginBottom:marginLeft]));
       
   234     return propertyValue;
       
   235 }
       
   236 
       
   237 int LayoutTestController::numberOfPages(float pageWidthInPixels, float pageHeightInPixels)
       
   238 {
       
   239     return [mainFrame numberOfPages:pageWidthInPixels:pageHeightInPixels];
       
   240 }
       
   241 
       
   242 size_t LayoutTestController::webHistoryItemCount()
       
   243 {
       
   244     return [[[WebHistory optionalSharedHistory] allItems] count];
       
   245 }
       
   246 
       
   247 unsigned LayoutTestController::workerThreadCount() const
       
   248 {
       
   249     return [WebWorkersPrivate workerThreadCount];
       
   250 }
       
   251 
       
   252 void LayoutTestController::notifyDone()
       
   253 {
       
   254     if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count())
       
   255         dump();
       
   256     m_waitToDump = false;
       
   257 }
       
   258 
       
   259 JSStringRef LayoutTestController::pathToLocalResource(JSContextRef context, JSStringRef url)
       
   260 {
       
   261     return JSStringRetain(url); // Do nothing on mac.
       
   262 }
       
   263 
       
   264 void LayoutTestController::queueLoad(JSStringRef url, JSStringRef target)
       
   265 {
       
   266     RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url));
       
   267     NSString *urlNS = (NSString *)urlCF.get();
       
   268 
       
   269     NSURL *nsurl = [NSURL URLWithString:urlNS relativeToURL:[[[mainFrame dataSource] response] URL]];
       
   270     NSString* nsurlString = [nsurl absoluteString];
       
   271 
       
   272     JSRetainPtr<JSStringRef> absoluteURL(Adopt, JSStringCreateWithUTF8CString([nsurlString UTF8String]));
       
   273     WorkQueue::shared()->queue(new LoadItem(absoluteURL.get(), target));
       
   274 }
       
   275 
       
   276 void LayoutTestController::setAcceptsEditing(bool newAcceptsEditing)
       
   277 {
       
   278     [(EditingDelegate *)[[mainFrame webView] editingDelegate] setAcceptsEditing:newAcceptsEditing];
       
   279 }
       
   280 
       
   281 void LayoutTestController::setAlwaysAcceptCookies(bool alwaysAcceptCookies)
       
   282 {
       
   283     if (alwaysAcceptCookies == m_alwaysAcceptCookies)
       
   284         return;
       
   285 
       
   286     m_alwaysAcceptCookies = alwaysAcceptCookies;
       
   287     NSHTTPCookieAcceptPolicy cookieAcceptPolicy = alwaysAcceptCookies ? NSHTTPCookieAcceptPolicyAlways : NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain;
       
   288     [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:cookieAcceptPolicy];
       
   289 }
       
   290 
       
   291 void LayoutTestController::setAppCacheMaximumSize(unsigned long long size)
       
   292 {
       
   293     [WebApplicationCache setMaximumSize:size];
       
   294 }
       
   295 
       
   296 void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag)
       
   297 {
       
   298     [[[mainFrame webView] preferences] setAuthorAndUserStylesEnabled:flag];
       
   299 }
       
   300 
       
   301 void LayoutTestController::setCustomPolicyDelegate(bool setDelegate, bool permissive)
       
   302 {
       
   303     if (setDelegate) {
       
   304         [policyDelegate setPermissive:permissive];
       
   305         [[mainFrame webView] setPolicyDelegate:policyDelegate];
       
   306     } else
       
   307         [[mainFrame webView] setPolicyDelegate:nil];
       
   308 }
       
   309 
       
   310 void LayoutTestController::setDatabaseQuota(unsigned long long quota)
       
   311 {    
       
   312     WebSecurityOrigin *origin = [[WebSecurityOrigin alloc] initWithURL:[NSURL URLWithString:@"file:///"]];
       
   313     [origin setQuota:quota];
       
   314     [origin release];
       
   315 }
       
   316 
       
   317 void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme)
       
   318 {
       
   319     RetainPtr<CFStringRef> schemeCFString(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, scheme));
       
   320     [WebView _setDomainRelaxationForbidden:forbidden forURLScheme:(NSString *)schemeCFString.get()];
       
   321 }
       
   322 
       
   323 void LayoutTestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy)
       
   324 {
       
   325     WebGeolocationPosition *position = [[WebGeolocationPosition alloc] initWithTimestamp:0 latitude:latitude longitude:longitude accuracy:accuracy];
       
   326     [[MockGeolocationProvider shared] setPosition:position];
       
   327     [position release];
       
   328 }
       
   329 
       
   330 void LayoutTestController::setMockGeolocationError(int code, JSStringRef message)
       
   331 {
       
   332     RetainPtr<CFStringRef> messageCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, message));
       
   333     NSString *messageNS = (NSString *)messageCF.get();
       
   334     NSError *error = [NSError errorWithDomain:WebKitErrorDomain code:code userInfo:[NSDictionary dictionaryWithObject:messageNS forKey:NSLocalizedDescriptionKey]];
       
   335     [[MockGeolocationProvider shared] setError:error];
       
   336 }
       
   337 
       
   338 void LayoutTestController::setIconDatabaseEnabled(bool iconDatabaseEnabled)
       
   339 {
       
   340     // FIXME: Workaround <rdar://problem/6480108>
       
   341     static WebIconDatabase* sharedWebIconDatabase = NULL;
       
   342     if (!sharedWebIconDatabase) {
       
   343         if (!iconDatabaseEnabled)
       
   344             return;
       
   345         sharedWebIconDatabase = [WebIconDatabase sharedIconDatabase];
       
   346         if ([sharedWebIconDatabase isEnabled] == iconDatabaseEnabled)
       
   347             return;
       
   348     }
       
   349     [sharedWebIconDatabase setEnabled:iconDatabaseEnabled];
       
   350 }
       
   351 
       
   352 void LayoutTestController::setJavaScriptProfilingEnabled(bool profilingEnabled)
       
   353 {
       
   354     setDeveloperExtrasEnabled(profilingEnabled);
       
   355     [[[mainFrame webView] inspector] setJavaScriptProfilingEnabled:profilingEnabled];
       
   356 }
       
   357 
       
   358 void LayoutTestController::setMainFrameIsFirstResponder(bool flag)
       
   359 {
       
   360     NSView *documentView = [[mainFrame frameView] documentView];
       
   361     
       
   362     NSResponder *firstResponder = flag ? documentView : nil;
       
   363     [[[mainFrame webView] window] makeFirstResponder:firstResponder];
       
   364 }
       
   365 
       
   366 void LayoutTestController::setPrivateBrowsingEnabled(bool privateBrowsingEnabled)
       
   367 {
       
   368     [[[mainFrame webView] preferences] setPrivateBrowsingEnabled:privateBrowsingEnabled];
       
   369 }
       
   370 
       
   371 void LayoutTestController::setXSSAuditorEnabled(bool enabled)
       
   372 {
       
   373     [[[mainFrame webView] preferences] setXSSAuditorEnabled:enabled];
       
   374 }
       
   375 
       
   376 void LayoutTestController::setFrameFlatteningEnabled(bool enabled)
       
   377 {
       
   378     [[[mainFrame webView] preferences] setFrameFlatteningEnabled:enabled];
       
   379 }
       
   380 
       
   381 void LayoutTestController::setSpatialNavigationEnabled(bool enabled)
       
   382 {
       
   383     // FIXME: Implement for SpatialNavigation layout tests.
       
   384 }
       
   385 
       
   386 void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
       
   387 {
       
   388     [[[mainFrame webView] preferences] setAllowUniversalAccessFromFileURLs:enabled];
       
   389 }
       
   390 
       
   391 void LayoutTestController::setAllowFileAccessFromFileURLs(bool enabled)
       
   392 {
       
   393     [[[mainFrame webView] preferences] setAllowFileAccessFromFileURLs:enabled];
       
   394 }
       
   395 
       
   396 void LayoutTestController::setPopupBlockingEnabled(bool popupBlockingEnabled)
       
   397 {
       
   398     [[[mainFrame webView] preferences] setJavaScriptCanOpenWindowsAutomatically:!popupBlockingEnabled];
       
   399 }
       
   400 
       
   401 void LayoutTestController::setPluginsEnabled(bool pluginsEnabled)
       
   402 {
       
   403     [[[mainFrame webView] preferences] setPlugInsEnabled:pluginsEnabled];
       
   404 }
       
   405 
       
   406 void LayoutTestController::setJavaScriptCanAccessClipboard(bool enabled)
       
   407 {
       
   408     [[[mainFrame webView] preferences] setJavaScriptCanAccessClipboard:enabled];
       
   409 }
       
   410 
       
   411 void LayoutTestController::setTabKeyCyclesThroughElements(bool cycles)
       
   412 {
       
   413     [[mainFrame webView] setTabKeyCyclesThroughElements:cycles];
       
   414 }
       
   415 
       
   416 void LayoutTestController::setTimelineProfilingEnabled(bool enabled)
       
   417 {
       
   418     [[[mainFrame webView] inspector] setTimelineProfilingEnabled:enabled];
       
   419 }
       
   420 
       
   421 void LayoutTestController::setUseDashboardCompatibilityMode(bool flag)
       
   422 {
       
   423     [[mainFrame webView] _setDashboardBehavior:WebDashboardBehaviorUseBackwardCompatibilityMode to:flag];
       
   424 }
       
   425 
       
   426 void LayoutTestController::setUserStyleSheetEnabled(bool flag)
       
   427 {
       
   428     [[WebPreferences standardPreferences] setUserStyleSheetEnabled:flag];
       
   429 }
       
   430 
       
   431 void LayoutTestController::setUserStyleSheetLocation(JSStringRef path)
       
   432 {
       
   433     RetainPtr<CFStringRef> pathCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, path));
       
   434     NSURL *url = [NSURL URLWithString:(NSString *)pathCF.get()];
       
   435     [[WebPreferences standardPreferences] setUserStyleSheetLocation:url];
       
   436 }
       
   437 
       
   438 void LayoutTestController::disableImageLoading()
       
   439 {
       
   440     [[WebPreferences standardPreferences] setLoadsImagesAutomatically:NO];
       
   441 }
       
   442 
       
   443 void LayoutTestController::dispatchPendingLoadRequests()
       
   444 {
       
   445     [[mainFrame webView] _dispatchPendingLoadRequests];
       
   446 }
       
   447 
       
   448 void LayoutTestController::overridePreference(JSStringRef key, JSStringRef value)
       
   449 {
       
   450     RetainPtr<CFStringRef> keyCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, key));
       
   451     NSString *keyNS = (NSString *)keyCF.get();
       
   452 
       
   453     RetainPtr<CFStringRef> valueCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, value));
       
   454     NSString *valueNS = (NSString *)valueCF.get();
       
   455 
       
   456     [[WebPreferences standardPreferences] _setPreferenceForTestWithValue:valueNS forKey:keyNS];
       
   457 }
       
   458 
       
   459 void LayoutTestController::removeAllVisitedLinks()
       
   460 {
       
   461     [WebHistory _removeAllVisitedLinks];
       
   462 }
       
   463 
       
   464 void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL)
       
   465 {
       
   466     RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
       
   467     ::setPersistentUserStyleSheetLocation(urlString.get());
       
   468 }
       
   469 
       
   470 void LayoutTestController::clearPersistentUserStyleSheet()
       
   471 {
       
   472     ::setPersistentUserStyleSheetLocation(0);
       
   473 }
       
   474 
       
   475 void LayoutTestController::setWindowIsKey(bool windowIsKey)
       
   476 {
       
   477     m_windowIsKey = windowIsKey;
       
   478     [[mainFrame webView] _updateActiveState];
       
   479 }
       
   480 
       
   481 void LayoutTestController::setSmartInsertDeleteEnabled(bool flag)
       
   482 {
       
   483     [[mainFrame webView] setSmartInsertDeleteEnabled:flag];
       
   484 }
       
   485 
       
   486 void LayoutTestController::setSelectTrailingWhitespaceEnabled(bool flag)
       
   487 {
       
   488     [[mainFrame webView] setSelectTrailingWhitespaceEnabled:flag];
       
   489 }
       
   490 
       
   491 static const CFTimeInterval waitToDumpWatchdogInterval = 30.0;
       
   492 
       
   493 static void waitUntilDoneWatchdogFired(CFRunLoopTimerRef timer, void* info)
       
   494 {
       
   495     gLayoutTestController->waitToDumpWatchdogTimerFired();
       
   496 }
       
   497 
       
   498 void LayoutTestController::setWaitToDump(bool waitUntilDone)
       
   499 {
       
   500     m_waitToDump = waitUntilDone;
       
   501     if (m_waitToDump && !waitToDumpWatchdog) {
       
   502         waitToDumpWatchdog = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + waitToDumpWatchdogInterval, 0, 0, 0, waitUntilDoneWatchdogFired, NULL);
       
   503         CFRunLoopAddTimer(CFRunLoopGetCurrent(), waitToDumpWatchdog, kCFRunLoopCommonModes);
       
   504     }
       
   505 }
       
   506 
       
   507 int LayoutTestController::windowCount()
       
   508 {
       
   509     return CFArrayGetCount(openWindowsRef);
       
   510 }
       
   511 
       
   512 bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef jsString)
       
   513 {
       
   514     RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, jsString));
       
   515     NSString *idNS = (NSString *)idCF.get();
       
   516     
       
   517     DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS];
       
   518     id rep = [[mainFrame dataSource] representation];
       
   519     
       
   520     if ([rep class] == [WebHTMLRepresentation class])
       
   521         return [(WebHTMLRepresentation *)rep elementDoesAutoComplete:element];
       
   522 
       
   523     return false;
       
   524 }
       
   525 
       
   526 void LayoutTestController::execCommand(JSStringRef name, JSStringRef value)
       
   527 {
       
   528     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
       
   529     NSString *nameNS = (NSString *)nameCF.get();
       
   530 
       
   531     RetainPtr<CFStringRef> valueCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, value));
       
   532     NSString *valueNS = (NSString *)valueCF.get();
       
   533 
       
   534     [[mainFrame webView] _executeCoreCommandByName:nameNS value:valueNS];
       
   535 }
       
   536 
       
   537 void LayoutTestController::setCacheModel(int cacheModel)
       
   538 {
       
   539     [[WebPreferences standardPreferences] setCacheModel:cacheModel];
       
   540 }
       
   541 
       
   542 bool LayoutTestController::isCommandEnabled(JSStringRef name)
       
   543 {
       
   544     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
       
   545     NSString *nameNS = (NSString *)nameCF.get();
       
   546 
       
   547     // Accept command strings with capital letters for first letter without trailing colon.
       
   548     if (![nameNS hasSuffix:@":"] && [nameNS length]) {
       
   549         nameNS = [[[[nameNS substringToIndex:1] lowercaseString]
       
   550             stringByAppendingString:[nameNS substringFromIndex:1]]
       
   551             stringByAppendingString:@":"];
       
   552     }
       
   553 
       
   554     SEL selector = NSSelectorFromString(nameNS);
       
   555     RetainPtr<CommandValidationTarget> target(AdoptNS, [[CommandValidationTarget alloc] initWithAction:selector]);
       
   556     id validator = [NSApp targetForAction:selector to:[mainFrame webView] from:target.get()];
       
   557     if (!validator)
       
   558         return false;
       
   559     if (![validator respondsToSelector:selector])
       
   560         return false;
       
   561     if (![validator respondsToSelector:@selector(validateUserInterfaceItem:)])
       
   562         return true;
       
   563     return [validator validateUserInterfaceItem:target.get()];
       
   564 }
       
   565 
       
   566 bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId)
       
   567 {
       
   568     RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, elementId));
       
   569     NSString *idNS = (NSString *)idCF.get();
       
   570     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, animationName));
       
   571     NSString *nameNS = (NSString *)nameCF.get();
       
   572     
       
   573     return [mainFrame _pauseAnimation:nameNS onNode:[[mainFrame DOMDocument] getElementById:idNS] atTime:time];
       
   574 }
       
   575 
       
   576 bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(JSStringRef propertyName, double time, JSStringRef elementId)
       
   577 {
       
   578     RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, elementId));
       
   579     NSString *idNS = (NSString *)idCF.get();
       
   580     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, propertyName));
       
   581     NSString *nameNS = (NSString *)nameCF.get();
       
   582     
       
   583     return [mainFrame _pauseTransitionOfProperty:nameNS onNode:[[mainFrame DOMDocument] getElementById:idNS] atTime:time];
       
   584 }
       
   585 
       
   586 bool LayoutTestController::sampleSVGAnimationForElementAtTime(JSStringRef animationId, double time, JSStringRef elementId)
       
   587 {
       
   588     RetainPtr<CFStringRef> animationIDCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, animationId));
       
   589     NSString *animationIDNS = (NSString *)animationIDCF.get();
       
   590     RetainPtr<CFStringRef> elementIDCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, elementId));
       
   591     NSString *elementIDNS = (NSString *)elementIDCF.get();
       
   592 
       
   593     return [mainFrame _pauseSVGAnimation:elementIDNS onSMILNode:[[mainFrame DOMDocument] getElementById:animationIDNS] atTime:time];
       
   594 }
       
   595 
       
   596 unsigned LayoutTestController::numberOfActiveAnimations() const
       
   597 {
       
   598     return [mainFrame _numberOfActiveAnimations];
       
   599 }
       
   600 
       
   601 void LayoutTestController::waitForPolicyDelegate()
       
   602 {
       
   603     setWaitToDump(true);
       
   604     [policyDelegate setControllerToNotifyDone:this];
       
   605     [[mainFrame webView] setPolicyDelegate:policyDelegate];
       
   606 }
       
   607 
       
   608 void LayoutTestController::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
       
   609 {
       
   610     RetainPtr<CFStringRef> sourceOriginCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, sourceOrigin));
       
   611     NSString *sourceOriginNS = (NSString *)sourceOriginCF.get();
       
   612     RetainPtr<CFStringRef> protocolCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationProtocol));
       
   613     NSString *destinationProtocolNS = (NSString *)protocolCF.get();
       
   614     RetainPtr<CFStringRef> hostCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationHost));
       
   615     NSString *destinationHostNS = (NSString *)hostCF.get();
       
   616     [WebView _addOriginAccessWhitelistEntryWithSourceOrigin:sourceOriginNS destinationProtocol:destinationProtocolNS destinationHost:destinationHostNS allowDestinationSubdomains:allowDestinationSubdomains];
       
   617 }
       
   618 
       
   619 void LayoutTestController::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
       
   620 {
       
   621     RetainPtr<CFStringRef> sourceOriginCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, sourceOrigin));
       
   622     NSString *sourceOriginNS = (NSString *)sourceOriginCF.get();
       
   623     RetainPtr<CFStringRef> protocolCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationProtocol));
       
   624     NSString *destinationProtocolNS = (NSString *)protocolCF.get();
       
   625     RetainPtr<CFStringRef> hostCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationHost));
       
   626     NSString *destinationHostNS = (NSString *)hostCF.get();
       
   627     [WebView _removeOriginAccessWhitelistEntryWithSourceOrigin:sourceOriginNS destinationProtocol:destinationProtocolNS destinationHost:destinationHostNS allowDestinationSubdomains:allowDestinationSubdomains];
       
   628 }
       
   629 
       
   630 void LayoutTestController::setScrollbarPolicy(JSStringRef orientation, JSStringRef policy)
       
   631 {
       
   632     // FIXME: implement
       
   633 }
       
   634 
       
   635 void LayoutTestController::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
       
   636 {
       
   637     RetainPtr<CFStringRef> sourceCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, source));
       
   638     NSString *sourceNS = (NSString *)sourceCF.get();
       
   639     [WebView _addUserScriptToGroup:@"org.webkit.DumpRenderTree" world:[WebScriptWorld world] source:sourceNS url:nil whitelist:nil blacklist:nil injectionTime:(runAtStart ? WebInjectAtDocumentStart : WebInjectAtDocumentEnd) injectedFrames:(allFrames ? WebInjectInAllFrames : WebInjectInTopFrameOnly)];
       
   640 }
       
   641 
       
   642 void LayoutTestController::addUserStyleSheet(JSStringRef source, bool allFrames)
       
   643 {
       
   644     RetainPtr<CFStringRef> sourceCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, source));
       
   645     NSString *sourceNS = (NSString *)sourceCF.get();
       
   646     [WebView _addUserStyleSheetToGroup:@"org.webkit.DumpRenderTree" world:[WebScriptWorld world] source:sourceNS url:nil whitelist:nil blacklist:nil injectedFrames:(allFrames ? WebInjectInAllFrames : WebInjectInTopFrameOnly)];
       
   647 }
       
   648 
       
   649 void LayoutTestController::setDeveloperExtrasEnabled(bool enabled)
       
   650 {
       
   651     [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:enabled];
       
   652 }
       
   653 
       
   654 void LayoutTestController::showWebInspector()
       
   655 {
       
   656     [[[mainFrame webView] inspector] show:nil];
       
   657 }
       
   658 
       
   659 void LayoutTestController::closeWebInspector()
       
   660 {
       
   661     [[[mainFrame webView] inspector] close:nil];
       
   662 }
       
   663 
       
   664 void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef script)
       
   665 {
       
   666     RetainPtr<CFStringRef> scriptCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, script));
       
   667     NSString *scriptNS = (NSString *)scriptCF.get();
       
   668     [[[mainFrame webView] inspector] evaluateInFrontend:nil callId:callId script:scriptNS];
       
   669 }
       
   670 
       
   671 typedef HashMap<unsigned, RetainPtr<WebScriptWorld> > WorldMap;
       
   672 static WorldMap& worldMap()
       
   673 {
       
   674     static WorldMap& map = *new WorldMap;
       
   675     return map;
       
   676 }
       
   677 
       
   678 unsigned worldIDForWorld(WebScriptWorld *world)
       
   679 {
       
   680     WorldMap::const_iterator end = worldMap().end();
       
   681     for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
       
   682         if (it->second == world)
       
   683             return it->first;
       
   684     }
       
   685 
       
   686     return 0;
       
   687 }
       
   688 
       
   689 void LayoutTestController::evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
       
   690 {
       
   691     RetainPtr<CFStringRef> scriptCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, script));
       
   692     NSString *scriptNS = (NSString *)scriptCF.get();
       
   693 
       
   694     // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
       
   695     // that is created once and cached forever.
       
   696     WebScriptWorld *world;
       
   697     if (!worldID)
       
   698         world = [WebScriptWorld world];
       
   699     else {
       
   700         RetainPtr<WebScriptWorld>& worldSlot = worldMap().add(worldID, 0).first->second;
       
   701         if (!worldSlot)
       
   702             worldSlot.adoptNS([[WebScriptWorld alloc] init]);
       
   703         world = worldSlot.get();
       
   704     }
       
   705 
       
   706     [mainFrame _stringByEvaluatingJavaScriptFromString:scriptNS withGlobalObject:globalObject inScriptWorld:world];
       
   707 }
       
   708 
       
   709 @interface APITestDelegate : NSObject
       
   710 {
       
   711     bool* m_condition;
       
   712 }
       
   713 @end
       
   714 
       
   715 @implementation APITestDelegate
       
   716 
       
   717 - (id)initWithCompletionCondition:(bool*)condition
       
   718 {
       
   719     [super init];
       
   720     ASSERT(condition);
       
   721     m_condition = condition;
       
   722     *m_condition = false;
       
   723     return self;
       
   724 }
       
   725 
       
   726 - (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
       
   727 {
       
   728     printf("API Test load failed\n");
       
   729     *m_condition = true;
       
   730 }
       
   731 
       
   732 - (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
       
   733 {
       
   734     printf("API Test load failed provisional\n");
       
   735     *m_condition = true;
       
   736 }
       
   737 
       
   738 - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
       
   739 {
       
   740     printf("API Test load succeeded\n");
       
   741     *m_condition = true;
       
   742 }
       
   743 
       
   744 @end
       
   745 
       
   746 void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
       
   747 {
       
   748     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       
   749 
       
   750     RetainPtr<CFStringRef> utf8DataCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, utf8Data));
       
   751     RetainPtr<CFStringRef> baseURLCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, baseURL));
       
   752     
       
   753     WebView *webView = [[WebView alloc] initWithFrame:NSZeroRect frameName:@"" groupName:@""];
       
   754 
       
   755     bool done = false;
       
   756     APITestDelegate *delegate = [[APITestDelegate alloc] initWithCompletionCondition:&done];
       
   757     [webView setFrameLoadDelegate:delegate];
       
   758 
       
   759     [[webView mainFrame] loadData:[(NSString *)utf8DataCF.get() dataUsingEncoding:NSUTF8StringEncoding] MIMEType:@"text/html" textEncodingName:@"utf-8" baseURL:[NSURL URLWithString:(NSString *)baseURLCF.get()]];
       
   760     
       
   761     while (!done) {
       
   762         NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       
   763         [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]];
       
   764         [pool release];
       
   765     }
       
   766         
       
   767     [webView close];
       
   768     [webView release];
       
   769     [delegate release];
       
   770     [pool release];
       
   771 }
       
   772 
       
   773 void LayoutTestController::apiTestGoToCurrentBackForwardItem()
       
   774 {
       
   775     WebView *view = [mainFrame webView];
       
   776     [view goToBackForwardItem:[[view backForwardList] currentItem]];
       
   777 }
       
   778 
       
   779 void LayoutTestController::setWebViewEditable(bool editable)
       
   780 {
       
   781     WebView *view = [mainFrame webView];
       
   782     [view setEditable:editable];
       
   783 }
       
   784 
       
   785 #ifndef BUILDING_ON_TIGER
       
   786 static NSString *SynchronousLoaderRunLoopMode = @"DumpRenderTreeSynchronousLoaderRunLoopMode";
       
   787 
       
   788 #if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD)
       
   789 @protocol NSURLConnectionDelegate <NSObject>
       
   790 @end
       
   791 #endif
       
   792 
       
   793 @interface SynchronousLoader : NSObject <NSURLConnectionDelegate>
       
   794 {
       
   795     NSString *m_username;
       
   796     NSString *m_password;
       
   797     BOOL m_isDone;
       
   798 }
       
   799 + (void)makeRequest:(NSURLRequest *)request withUsername:(NSString *)username password:(NSString *)password;
       
   800 @end
       
   801 
       
   802 @implementation SynchronousLoader : NSObject
       
   803 - (void)dealloc
       
   804 {
       
   805     [m_username release];
       
   806     [m_password release];
       
   807 
       
   808     [super dealloc];
       
   809 }
       
   810 
       
   811 - (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection
       
   812 {
       
   813     return YES;
       
   814 }
       
   815 
       
   816 - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
       
   817 {
       
   818     if ([challenge previousFailureCount] == 0) {
       
   819         NSURLCredential *credential = [[NSURLCredential alloc]  initWithUser:m_username password:m_password persistence:NSURLCredentialPersistenceForSession];
       
   820         [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
       
   821         return;
       
   822     }
       
   823     [[challenge sender] cancelAuthenticationChallenge:challenge];
       
   824 }
       
   825 
       
   826 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
       
   827 {
       
   828     printf("SynchronousLoader failed: %s\n", [[error description] UTF8String]);
       
   829     m_isDone = YES;
       
   830 }
       
   831 
       
   832 - (void)connectionDidFinishLoading:(NSURLConnection *)connection
       
   833 {
       
   834     m_isDone = YES;
       
   835 }
       
   836 
       
   837 + (void)makeRequest:(NSURLRequest *)request withUsername:(NSString *)username password:(NSString *)password
       
   838 {
       
   839     ASSERT(![[request URL] user]);
       
   840     ASSERT(![[request URL] password]);
       
   841 
       
   842     SynchronousLoader *delegate = [[SynchronousLoader alloc] init];
       
   843     delegate->m_username = [username copy];
       
   844     delegate->m_password = [password copy];
       
   845 
       
   846     NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate startImmediately:NO];
       
   847     [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:SynchronousLoaderRunLoopMode];
       
   848     [connection start];
       
   849     
       
   850     while (!delegate->m_isDone)
       
   851         [[NSRunLoop currentRunLoop] runMode:SynchronousLoaderRunLoopMode beforeDate:[NSDate distantFuture]];
       
   852 
       
   853     [connection cancel];
       
   854     
       
   855     [connection release];
       
   856     [delegate release];
       
   857 }
       
   858 
       
   859 @end
       
   860 #endif
       
   861 
       
   862 void LayoutTestController::authenticateSession(JSStringRef url, JSStringRef username, JSStringRef password)
       
   863 {
       
   864     // See <rdar://problem/7880699>.
       
   865 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
       
   866     RetainPtr<CFStringRef> urlStringCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url));
       
   867     RetainPtr<CFStringRef> usernameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, username));
       
   868     RetainPtr<CFStringRef> passwordCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, password));
       
   869 
       
   870     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:(NSString *)urlStringCF.get()]];
       
   871 
       
   872     [SynchronousLoader makeRequest:request withUsername:(NSString *)usernameCF.get() password:(NSString *)passwordCF.get()];
       
   873 #endif
       
   874 }
       
   875 
       
   876 void LayoutTestController::setEditingBehavior(const char* editingBehavior)
       
   877 {
       
   878     NSString* editingBehaviorNS = [[NSString alloc] initWithUTF8String:editingBehavior];
       
   879     if ([editingBehaviorNS isEqualToString:@"mac"])
       
   880         [[WebPreferences standardPreferences] setEditingBehavior:WebKitEditingMacBehavior];
       
   881     if ([editingBehaviorNS isEqualToString:@"win"])
       
   882         [[WebPreferences standardPreferences] setEditingBehavior:WebKitEditingWinBehavior];
       
   883     [editingBehaviorNS release];
       
   884 }
       
   885 
       
   886 void LayoutTestController::abortModal()
       
   887 {
       
   888     [NSApp abortModal];
       
   889 }