WebCore:
[WebKit-https.git] / WebKitTools / DumpRenderTree / mac / LayoutTestControllerMac.mm
1 /*
2  * Copyright (C) 2007 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 "DumpRenderTree.h"
30 #import "LayoutTestController.h"
31
32 #import "EditingDelegate.h"
33 #import "WorkQueue.h"
34 #import "WorkQueueItem.h"
35 #import <Foundation/Foundation.h>
36 #import <JavaScriptCore/JSRetainPtr.h>
37 #import <JavaScriptCore/JSStringRef.h>
38 #import <JavaScriptCore/JSStringRefCF.h>
39 #import <WebKit/DOMDocument.h>
40 #import <WebKit/WebBackForwardList.h>
41 #import <WebKit/WebDatabaseManagerPrivate.h>
42 #import <WebKit/WebDataSource.h>
43 #import <WebKit/WebFrame.h>
44 #import <WebKit/WebHTMLRepresentation.h>
45 #import <WebKit/WebHTMLViewPrivate.h>
46 #import <WebKit/WebHistory.h>
47 #import <WebKit/WebNSURLExtras.h>
48 #import <WebKit/WebPreferences.h>
49 #import <WebKit/WebPreferencesPrivate.h>
50 #import <WebKit/WebSecurityOriginPrivate.h>
51 #import <WebKit/WebView.h>
52 #import <WebKit/WebViewPrivate.h>
53 #import <wtf/RetainPtr.h>
54
55 LayoutTestController::~LayoutTestController()
56 {
57 }
58
59 void LayoutTestController::addDisallowedURL(JSStringRef url)
60 {
61     RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url));
62
63     if (!disallowedURLs)
64         disallowedURLs = CFSetCreateMutable(kCFAllocatorDefault, 0, NULL);
65
66     // Canonicalize the URL
67     NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:(NSString *)urlCF.get()]];
68     request = [NSURLProtocol canonicalRequestForRequest:request];
69
70     CFSetAddValue(disallowedURLs, [request URL]);
71 }
72
73 void LayoutTestController::clearAllDatabases()
74 {
75     [[WebDatabaseManager sharedWebDatabaseManager] deleteAllDatabases];
76 }
77
78 void LayoutTestController::clearBackForwardList()
79 {
80     WebBackForwardList *backForwardList = [[mainFrame webView] backForwardList];
81     WebHistoryItem *item = [[backForwardList currentItem] retain];
82
83     // We clear the history by setting the back/forward list's capacity to 0
84     // then restoring it back and adding back the current item.
85     int capacity = [backForwardList capacity];
86     [backForwardList setCapacity:0];
87     [backForwardList setCapacity:capacity];
88     [backForwardList addItem:item];
89     [backForwardList goToItem:item];
90     [item release];
91 }
92
93 JSStringRef LayoutTestController::copyDecodedHostName(JSStringRef name)
94 {
95     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
96     NSString *nameNS = (NSString *)nameCF.get();
97     return JSStringCreateWithCFString((CFStringRef)[nameNS _web_decodeHostName]);
98 }
99
100 JSStringRef LayoutTestController::copyEncodedHostName(JSStringRef name)
101 {
102     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
103     NSString *nameNS = (NSString *)nameCF.get();
104     return JSStringCreateWithCFString((CFStringRef)[nameNS _web_encodeHostName]);
105 }
106
107 void LayoutTestController::display()
108 {
109     displayWebView();
110 }
111
112 void LayoutTestController::keepWebHistory()
113 {
114     if (![WebHistory optionalSharedHistory]) {
115         WebHistory *history = [[WebHistory alloc] init];
116         [WebHistory setOptionalSharedHistory:history];
117         [history release];
118     }
119 }
120
121 void LayoutTestController::notifyDone()
122 {
123     if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count())
124         dump();
125     m_waitToDump = false;
126 }
127
128 JSStringRef LayoutTestController::pathToLocalResource(JSContextRef context, JSStringRef url)
129 {
130     return JSStringRetain(url); // Do nothing on mac.
131 }
132
133 void LayoutTestController::queueBackNavigation(int howFarBack)
134 {
135     WorkQueue::shared()->queue(new BackItem(howFarBack));
136 }
137
138 void LayoutTestController::queueForwardNavigation(int howFarForward)
139 {
140     WorkQueue::shared()->queue(new ForwardItem(howFarForward));
141 }
142
143 void LayoutTestController::queueLoad(JSStringRef url, JSStringRef target)
144 {
145     RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url));
146     NSString *urlNS = (NSString *)urlCF.get();
147
148     NSURL *nsurl = [NSURL URLWithString:urlNS relativeToURL:[[[mainFrame dataSource] response] URL]];
149     NSString* nsurlString = [nsurl absoluteString];
150
151     JSRetainPtr<JSStringRef> absoluteURL(Adopt, JSStringCreateWithUTF8CString([nsurlString UTF8String]));
152     WorkQueue::shared()->queue(new LoadItem(absoluteURL.get(), target));
153 }
154
155 void LayoutTestController::queueReload()
156 {
157     WorkQueue::shared()->queue(new ReloadItem);
158 }
159
160 void LayoutTestController::queueScript(JSStringRef script)
161 {
162     WorkQueue::shared()->queue(new ScriptItem(script));
163 }
164
165 void LayoutTestController::setAcceptsEditing(bool newAcceptsEditing)
166 {
167     [(EditingDelegate *)[[mainFrame webView] editingDelegate] setAcceptsEditing:newAcceptsEditing];
168 }
169
170 void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag)
171 {
172     [[[mainFrame webView] preferences] setAuthorAndUserStylesEnabled:flag];
173 }
174
175 void LayoutTestController::setCustomPolicyDelegate(bool setDelegate)
176 {
177     if (setDelegate)
178         [[mainFrame webView] setPolicyDelegate:policyDelegate];
179     else
180         [[mainFrame webView] setPolicyDelegate:nil];
181 }
182
183 void LayoutTestController::setDatabaseQuota(unsigned long long quota)
184 {    
185     WebSecurityOrigin *origin = [[WebSecurityOrigin alloc] initWithURL:[NSURL URLWithString:@"file:///"]];
186     [origin setQuota:quota];
187     [origin release];
188 }
189
190 void LayoutTestController::setMainFrameIsFirstResponder(bool flag)
191 {
192     NSView *documentView = [[mainFrame frameView] documentView];
193     
194     NSResponder *firstResponder = flag ? documentView : nil;
195     [[[mainFrame webView] window] makeFirstResponder:firstResponder];
196         
197     if ([documentView isKindOfClass:[WebHTMLView class]])
198         [(WebHTMLView *)documentView _updateFocusedAndActiveState];
199 }
200
201 void LayoutTestController::setPrivateBrowsingEnabled(bool privateBrowsingEnabled)
202 {
203     [[[mainFrame webView] preferences] setPrivateBrowsingEnabled:privateBrowsingEnabled];
204 }
205
206 void LayoutTestController::setPopupBlockingEnabled(bool popupBlockingEnabled)
207 {
208     [[[mainFrame webView] preferences] setJavaScriptCanOpenWindowsAutomatically:!popupBlockingEnabled];
209 }
210
211 void LayoutTestController::setTabKeyCyclesThroughElements(bool cycles)
212 {
213     [[mainFrame webView] setTabKeyCyclesThroughElements:cycles];
214 }
215
216 void LayoutTestController::setUseDashboardCompatibilityMode(bool flag)
217 {
218     [[mainFrame webView] _setDashboardBehavior:WebDashboardBehaviorUseBackwardCompatibilityMode to:flag];
219 }
220
221 void LayoutTestController::setUserStyleSheetEnabled(bool flag)
222 {
223     [[WebPreferences standardPreferences] setUserStyleSheetEnabled:flag];
224 }
225
226 void LayoutTestController::setUserStyleSheetLocation(JSStringRef path)
227 {
228     RetainPtr<CFStringRef> pathCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, path));
229     NSURL *url = [NSURL URLWithString:(NSString *)pathCF.get()];
230     [[WebPreferences standardPreferences] setUserStyleSheetLocation:url];
231 }
232
233 void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL)
234 {
235     RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
236     ::setPersistentUserStyleSheetLocation(urlString.get());
237 }
238
239 void LayoutTestController::clearPersistentUserStyleSheet()
240 {
241     ::setPersistentUserStyleSheetLocation(0);
242 }
243
244 void LayoutTestController::setWindowIsKey(bool windowIsKey)
245 {
246     m_windowIsKey = windowIsKey;
247     NSView *documentView = [[mainFrame frameView] documentView];
248     if ([documentView isKindOfClass:[WebHTMLView class]])
249         [(WebHTMLView *)documentView _updateFocusedAndActiveState];
250 }
251
252 static const CFTimeInterval waitToDumpWatchdogInterval = 10.0;
253
254 static void waitUntilDoneWatchdogFired(CFRunLoopTimerRef timer, void* info)
255 {
256     const char* message = "FAIL: Timed out waiting for notifyDone to be called\n";
257     fprintf(stderr, message);
258     fprintf(stdout, message);
259     dump();
260 }
261
262 void LayoutTestController::setWaitToDump(bool waitUntilDone)
263 {
264     m_waitToDump = waitUntilDone;
265     if (m_waitToDump && !waitToDumpWatchdog) {
266         waitToDumpWatchdog = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + waitToDumpWatchdogInterval, 0, 0, 0, waitUntilDoneWatchdogFired, NULL);
267         CFRunLoopAddTimer(CFRunLoopGetCurrent(), waitToDumpWatchdog, kCFRunLoopCommonModes);
268     }
269 }
270
271 int LayoutTestController::windowCount()
272 {
273     return CFArrayGetCount(openWindowsRef);
274 }
275
276 bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef id)
277 {
278     RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, id));
279     NSString *idNS = (NSString *)idCF.get();
280     
281     DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS];
282     id rep = [[mainFrame dataSource] representation];
283     
284     if ([rep class] == [WebHTMLRepresentation class])
285         return [(WebHTMLRepresentation *)rep elementDoesAutoComplete:element];
286
287     return false;
288 }
289
290 void LayoutTestController::execCommand(JSStringRef name, JSStringRef value)
291 {
292     RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name));
293     NSString *nameNS = (NSString *)nameCF.get();
294
295     RetainPtr<CFStringRef> valueCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, value));
296     NSString *valueNS = (NSString *)valueCF.get();
297
298     [[mainFrame webView] _executeCoreCommandByName:nameNS value:valueNS];
299 }