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