1/*
2 * Copyright (C) 2006. 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 "config.h"
30#import "UIDelegate.h"
31
32#import "DumpRenderTree.h"
33#import "DumpRenderTreeDraggingInfo.h"
34#import "EventSendingController.h"
35#import "LayoutTestController.h"
36#import <WebKit/WebApplicationCache.h>
37#import <WebKit/WebFramePrivate.h>
38#import <WebKit/WebHTMLViewPrivate.h>
39#import <WebKit/WebQuotaManager.h>
40#import <WebKit/WebSecurityOriginPrivate.h>
41#import <WebKit/WebUIDelegatePrivate.h>
42#import <WebKit/WebView.h>
43#import <WebKit/WebViewPrivate.h>
44#import <wtf/Assertions.h>
45
46DumpRenderTreeDraggingInfo *draggingInfo = nil;
47
48@implementation UIDelegate
49
50- (void)webView:(WebView *)sender setFrame:(NSRect)frame
51{
52    m_frame = frame;
53}
54
55- (NSRect)webViewFrame:(WebView *)sender
56{
57    return m_frame;
58}
59
60- (void)webView:(WebView *)sender addMessageToConsole:(NSDictionary *)dictionary withSource:(NSString *)source
61{
62    NSString *message = [dictionary objectForKey:@"message"];
63    NSNumber *lineNumber = [dictionary objectForKey:@"lineNumber"];
64
65    NSRange range = [message rangeOfString:@"file://"];
66    if (range.location != NSNotFound)
67        message = [[message substringToIndex:range.location] stringByAppendingString:[[message substringFromIndex:NSMaxRange(range)] lastPathComponent]];
68
69    printf ("CONSOLE MESSAGE: line %d: %s\n", [lineNumber intValue], [message UTF8String]);
70}
71
72- (void)modalWindowWillClose:(NSNotification *)notification
73{
74    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:nil];
75    [NSApp abortModal];
76}
77
78- (void)webViewRunModal:(WebView *)sender
79{
80    gLayoutTestController->setWindowIsKey(false);
81    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(modalWindowWillClose:) name:NSWindowWillCloseNotification object:nil];
82    [NSApp runModalForWindow:[sender window]];
83    gLayoutTestController->setWindowIsKey(true);
84}
85
86- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame
87{
88    if (!done)
89        printf("ALERT: %s\n", [message UTF8String]);
90}
91
92- (BOOL)webView:(WebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame
93{
94    if (!done)
95        printf("CONFIRM: %s\n", [message UTF8String]);
96    return YES;
97}
98
99- (NSString *)webView:(WebView *)sender runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WebFrame *)frame
100{
101    if (!done)
102        printf("PROMPT: %s, default text: %s\n", [prompt UTF8String], [defaultText UTF8String]);
103    return defaultText;
104}
105
106- (BOOL)webView:(WebView *)c runBeforeUnloadConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame
107{
108    if (!done)
109        printf("CONFIRM NAVIGATION: %s\n", [message UTF8String]);
110    return YES;
111}
112
113
114- (void)webView:(WebView *)sender dragImage:(NSImage *)anImage at:(NSPoint)viewLocation offset:(NSSize)initialOffset event:(NSEvent *)event pasteboard:(NSPasteboard *)pboard source:(id)sourceObj slideBack:(BOOL)slideFlag forView:(NSView *)view
115{
116     assert(!draggingInfo);
117     draggingInfo = [[DumpRenderTreeDraggingInfo alloc] initWithImage:anImage offset:initialOffset pasteboard:pboard source:sourceObj];
118     [sender draggingUpdated:draggingInfo];
119     [EventSendingController replaySavedEvents];
120}
121
122- (void)webViewFocus:(WebView *)webView
123{
124    gLayoutTestController->setWindowIsKey(true);
125}
126
127- (void)webViewUnfocus:(WebView *)webView
128{
129    gLayoutTestController->setWindowIsKey(false);
130}
131
132- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request
133{
134    if (!gLayoutTestController->canOpenWindows())
135        return nil;
136
137    // Make sure that waitUntilDone has been called.
138    ASSERT(gLayoutTestController->waitToDump());
139
140    WebView *webView = createWebViewAndOffscreenWindow();
141
142    if (gLayoutTestController->newWindowsCopyBackForwardList())
143        [webView _loadBackForwardListFromOtherView:sender];
144
145    return [webView autorelease];
146}
147
148- (void)webViewClose:(WebView *)sender
149{
150    NSWindow* window = [sender window];
151
152    if (gLayoutTestController->callCloseOnWebViews())
153        [sender close];
154
155    [window close];
156}
157
158- (void)webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(WebSecurityOrigin *)origin database:(NSString *)databaseIdentifier
159{
160    if (!done && gLayoutTestController->dumpDatabaseCallbacks()) {
161        printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%s, %s, %i} database:%s\n", [[origin protocol] UTF8String], [[origin host] UTF8String],
162            [origin port], [databaseIdentifier UTF8String]);
163    }
164
165    static const unsigned long long defaultQuota = 5 * 1024 * 1024;
166    [[origin databaseQuotaManager] setQuota:defaultQuota];
167}
168
169- (void)webView:(WebView *)sender exceededApplicationCacheOriginQuotaForSecurityOrigin:(WebSecurityOrigin *)origin
170{
171    if (!done && gLayoutTestController->dumpApplicationCacheDelegateCallbacks()) {
172        printf("UI DELEGATE APPLICATION CACHE CALLBACK: exceededApplicationCacheOriginQuotaForSecurityOrigin:{%s, %s, %i}\n",
173            [[origin protocol] UTF8String], [[origin host] UTF8String], [origin port]);
174    }
175
176    static const unsigned long long defaultOriginQuota = [WebApplicationCache defaultOriginQuota];
177    [[origin applicationCacheQuotaManager] setQuota:defaultOriginQuota];
178}
179
180- (void)webView:(WebView *)sender setStatusText:(NSString *)text
181{
182    if (gLayoutTestController->dumpStatusCallbacks())
183        printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", [text UTF8String]);
184}
185
186- (void)webView:(WebView *)webView decidePolicyForGeolocationRequestFromOrigin:(WebSecurityOrigin *)origin frame:(WebFrame *)frame listener:(id<WebGeolocationPolicyListener>)listener
187{
188    if (!gLayoutTestController->isGeolocationPermissionSet()) {
189        if (!m_pendingGeolocationPermissionListeners)
190            m_pendingGeolocationPermissionListeners = [[NSMutableSet set] retain];
191        [m_pendingGeolocationPermissionListeners addObject:listener];
192        return;
193    }
194
195    if (gLayoutTestController->geolocationPermission())
196        [listener allow];
197    else
198        [listener deny];
199}
200
201- (void)didSetMockGeolocationPermission
202{
203    ASSERT(gLayoutTestController->isGeolocationPermissionSet());
204    if (m_pendingGeolocationPermissionListeners && !m_timer)
205        m_timer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(timerFired) userInfo:0 repeats:NO];
206}
207
208- (int)numberOfPendingGeolocationPermissionRequests
209{
210    if (!m_pendingGeolocationPermissionListeners)
211        return 0;
212    return [m_pendingGeolocationPermissionListeners count];
213}
214
215
216- (void)timerFired
217{
218    ASSERT(gLayoutTestController->isGeolocationPermissionSet());
219    m_timer = 0;
220    NSEnumerator* enumerator = [m_pendingGeolocationPermissionListeners objectEnumerator];
221    id<WebGeolocationPolicyListener> listener;
222    while ((listener = [enumerator nextObject])) {
223        if (gLayoutTestController->geolocationPermission())
224            [listener allow];
225        else
226            [listener deny];
227    }
228    [m_pendingGeolocationPermissionListeners removeAllObjects];
229    [m_pendingGeolocationPermissionListeners release];
230    m_pendingGeolocationPermissionListeners = nil;
231}
232
233- (BOOL)webView:(WebView *)sender shouldHaltPlugin:(DOMNode *)pluginNode
234{
235    return NO;
236}
237
238- (BOOL)webView:(WebView *)webView supportsFullScreenForElement:(DOMElement*)element withKeyboard:(BOOL)withKeyboard
239{
240    return YES;
241}
242
243- (void)webView:(WebView *)webView enterFullScreenForElement:(DOMElement*)element listener:(NSObject<WebKitFullScreenListener>*)listener
244{
245    [listener webkitWillEnterFullScreen];
246    [listener webkitDidEnterFullScreen];
247}
248
249- (void)webView:(WebView *)webView exitFullScreenForElement:(DOMElement*)element listener:(NSObject<WebKitFullScreenListener>*)listener
250{
251    [listener webkitWillExitFullScreen];
252    [listener webkitDidExitFullScreen];
253}
254
255- (BOOL)webView:(WebView *)webView didPressMissingPluginButton:(DOMElement *)element
256{
257    printf("MISSING PLUGIN BUTTON PRESSED\n");
258    return TRUE;
259}
260
261- (void)dealloc
262{
263    [draggingInfo release];
264    draggingInfo = nil;
265    [m_pendingGeolocationPermissionListeners release];
266    m_pendingGeolocationPermissionListeners = nil;
267
268    [super dealloc];
269}
270
271@end
272