e94e623cb6d2937353572fd78ad82e36d76265ce
[WebKit-https.git] / WebKit / win / WebChromeClient.cpp
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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "WebChromeClient.h"
28
29 #include "WebElementPropertyBag.h"
30 #include "WebFrame.h"
31 #include "WebMutableURLRequest.h"
32 #include "WebView.h"
33 #pragma warning(push, 0)
34 #include <WebCore/BString.h>
35 #include <WebCore/ContextMenu.h>
36 #include <WebCore/FloatRect.h>
37 #include <WebCore/FrameLoadRequest.h>
38 #include <WebCore/NotImplemented.h>
39 #pragma warning(pop)
40
41 using namespace WebCore;
42
43 WebChromeClient::WebChromeClient(WebView* webView)
44     : m_webView(webView)
45 {
46 }
47
48 void WebChromeClient::chromeDestroyed()
49 {
50     delete this;
51 }
52
53 void WebChromeClient::setWindowRect(const FloatRect& r)
54 {
55     IWebUIDelegate* uiDelegate = 0;
56     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
57         RECT rect = IntRect(r);
58         uiDelegate->setFrame(m_webView, &rect);
59         uiDelegate->Release();
60     }
61 }
62
63 FloatRect WebChromeClient::windowRect()
64 {
65     IWebUIDelegate* uiDelegate = 0;
66     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
67         RECT rect;
68         HRESULT retval = uiDelegate->webViewFrame(m_webView, &rect);
69
70         uiDelegate->Release();
71
72         if (SUCCEEDED(retval))
73             return rect;
74     }
75
76     return FloatRect();
77 }
78
79 FloatRect WebChromeClient::pageRect()
80 {
81     RECT rect;
82     m_webView->frameRect(&rect);
83     return rect;
84 }
85
86 float WebChromeClient::scaleFactor()
87 {
88     // Windows doesn't support UI scaling.
89     return 1.0;
90 }
91
92 void WebChromeClient::focus()
93 {
94     IWebUIDelegate* uiDelegate = 0;
95     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
96         uiDelegate->webViewFocus(m_webView);
97         uiDelegate->Release();
98     }
99 }
100
101 void WebChromeClient::unfocus()
102 {
103     IWebUIDelegate* uiDelegate = 0;
104     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
105         uiDelegate->webViewUnfocus(m_webView);
106         uiDelegate->Release();
107     }
108 }
109
110 bool WebChromeClient::canTakeFocus(FocusDirection direction)
111 {
112     IWebUIDelegate* uiDelegate = 0;
113     BOOL bForward = (direction == FocusDirectionForward) ? TRUE : FALSE;
114     BOOL result = FALSE;
115     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
116         uiDelegate->canTakeFocus(m_webView, bForward, &result);
117         uiDelegate->Release();
118     }
119
120     return !!result;
121 }
122
123 void WebChromeClient::takeFocus(FocusDirection direction)
124 {
125     IWebUIDelegate* uiDelegate = 0;
126     BOOL bForward = (direction == FocusDirectionForward) ? TRUE : FALSE;
127     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
128         uiDelegate->takeFocus(m_webView, bForward);
129         uiDelegate->Release();
130     }
131 }
132
133 Page* WebChromeClient::createWindow(Frame*, const FrameLoadRequest& frameLoadRequest)
134 {
135     Page* page = 0;
136     IWebMutableURLRequest* request = WebMutableURLRequest::createInstance(frameLoadRequest.resourceRequest());
137
138     IWebUIDelegate* uiDelegate = 0;
139     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
140         IWebView* webView = 0;
141         if (SUCCEEDED(uiDelegate->createWebViewWithRequest(m_webView, request, &webView))) {
142             page = core(webView);
143             webView->Release();
144         }
145     
146         uiDelegate->Release();
147     }
148
149     request->Release();
150     return page;
151 }
152
153 Page* WebChromeClient::createModalDialog(Frame*, const FrameLoadRequest&)
154 {
155     Page* page = 0;
156     IWebUIDelegate* uiDelegate = 0;
157     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
158         notImplemented();
159         uiDelegate->Release();
160     }
161     return page;
162 }
163
164 void WebChromeClient::show()
165 {
166     IWebUIDelegate* uiDelegate = 0;
167     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
168         uiDelegate->webViewShow(m_webView);
169         uiDelegate->Release();
170     }
171 }
172
173 bool WebChromeClient::canRunModal()
174 {
175     bool result = false;
176     IWebUIDelegate* uiDelegate = 0;
177     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
178         notImplemented();
179         uiDelegate->Release();
180     }
181     return result;
182 }
183
184 void WebChromeClient::runModal()
185 {
186     IWebUIDelegate* uiDelegate = 0;
187     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
188         notImplemented();
189         uiDelegate->Release();
190     }
191 }
192
193 void WebChromeClient::setToolbarsVisible(bool visible)
194 {
195     IWebUIDelegate* uiDelegate = 0;
196     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
197         uiDelegate->setToolbarsVisible(m_webView, visible);
198         uiDelegate->Release();
199     }
200 }
201
202 bool WebChromeClient::toolbarsVisible()
203 {
204     BOOL result = false;
205     IWebUIDelegate* uiDelegate = 0;
206     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
207         uiDelegate->webViewAreToolbarsVisible(m_webView, &result);
208         uiDelegate->Release();
209     }
210     return result != false;
211 }
212
213 void WebChromeClient::setStatusbarVisible(bool visible)
214 {
215     IWebUIDelegate* uiDelegate = 0;
216     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
217         uiDelegate->setStatusBarVisible(m_webView, visible);
218         uiDelegate->Release();
219     }
220 }
221
222 bool WebChromeClient::statusbarVisible()
223 {
224     BOOL result = false;
225     IWebUIDelegate* uiDelegate = 0;
226     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
227         uiDelegate->webViewIsStatusBarVisible(m_webView, &result);
228         uiDelegate->Release();
229     }
230     return result != false;
231 }
232
233 void WebChromeClient::setScrollbarsVisible(bool)
234 {
235     notImplemented();
236 }
237
238 bool WebChromeClient::scrollbarsVisible()
239 {
240     notImplemented();
241     return false;
242 }
243
244 void WebChromeClient::setMenubarVisible(bool)
245 {
246     IWebUIDelegate* uiDelegate = 0;
247     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
248         notImplemented();
249         uiDelegate->Release();
250     }
251 }
252
253 bool WebChromeClient::menubarVisible()
254 {
255     bool result = false;
256     IWebUIDelegate* uiDelegate = 0;
257     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
258         notImplemented();
259         uiDelegate->Release();
260     }
261     return result;
262 }
263
264 void WebChromeClient::setResizable(bool resizable)
265 {
266     IWebUIDelegate* uiDelegate = 0;
267     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
268         uiDelegate->setResizable(m_webView, resizable);
269         uiDelegate->Release();
270     }
271 }
272
273 void WebChromeClient::addMessageToConsole(const String& message, unsigned line, const String& url)
274 {
275     COMPtr<IWebUIDelegate> uiDelegate;
276     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
277         COMPtr<IWebUIDelegatePrivate> uiPrivate;
278         if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate)))
279             uiPrivate->webViewAddMessageToConsole(m_webView, BString(message), line, BString(url), true);
280     }
281 }
282
283 bool WebChromeClient::canRunBeforeUnloadConfirmPanel()
284 {
285     IWebUIDelegate* ui;
286     if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) {
287         ui->Release();
288         return true;
289     }
290     return false;
291 }
292
293 bool WebChromeClient::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
294 {
295     BOOL result = TRUE;
296     IWebUIDelegate* ui;
297     if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) {
298         WebFrame* webFrame = kit(frame);
299         ui->runBeforeUnloadConfirmPanelWithMessage(m_webView, BString(message), webFrame, &result);
300         ui->Release();
301     }
302     return !!result;
303 }
304
305 void WebChromeClient::closeWindowSoon()
306 {
307     // We need to remove the parent WebView from WebViewSets here, before it actually
308     // closes, to make sure that JavaScript code that executes before it closes
309     // can't find it. Otherwise, window.open will select a closed WebView instead of 
310     // opening a new one <rdar://problem/3572585>.
311
312     // We also need to stop the load to prevent further parsing or JavaScript execution
313     // after the window has torn down <rdar://problem/4161660>.
314   
315     // FIXME: This code assumes that the UI delegate will respond to a webViewClose
316     // message by actually closing the WebView. Safari guarantees this behavior, but other apps might not.
317     // This approach is an inherent limitation of not making a close execute immediately
318     // after a call to window.close.
319
320     m_webView->setGroupName(0);
321     m_webView->stopLoading(0);
322     m_webView->closeWindowSoon();
323 }
324
325 void WebChromeClient::runJavaScriptAlert(Frame*, const String& message)
326 {
327     COMPtr<IWebUIDelegate> ui;
328     if (SUCCEEDED(m_webView->uiDelegate(&ui)))
329         ui->runJavaScriptAlertPanelWithMessage(m_webView, BString(message));
330 }
331
332 bool WebChromeClient::runJavaScriptConfirm(Frame*, const String& message)
333 {
334     BOOL result = FALSE;
335     COMPtr<IWebUIDelegate> ui;
336     if (SUCCEEDED(m_webView->uiDelegate(&ui)))
337         ui->runJavaScriptConfirmPanelWithMessage(m_webView, BString(message), &result);
338     return !!result;
339 }
340
341 bool WebChromeClient::runJavaScriptPrompt(Frame*, const String& message, const String& defaultValue, String& result)
342 {
343     COMPtr<IWebUIDelegate> ui;
344     if (FAILED(m_webView->uiDelegate(&ui)))
345         return false;
346
347     BSTR resultBSTR = 0;
348     if (FAILED(ui->runJavaScriptTextInputPanelWithPrompt(m_webView, BString(message), BString(defaultValue), &resultBSTR)))
349         return false;
350
351     if (resultBSTR) {
352         result = String(resultBSTR, SysStringLen(resultBSTR));
353         SysFreeString(resultBSTR);
354         return true;
355     }
356
357     return false;
358 }
359
360 void WebChromeClient::setStatusbarText(const String& statusText)
361 {
362     COMPtr<IWebUIDelegate> uiDelegate;
363     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
364         uiDelegate->setStatusText(m_webView, BString(statusText));
365     }
366 }
367
368 bool WebChromeClient::shouldInterruptJavaScript()
369 {
370     COMPtr<IWebUIDelegate> uiDelegate;
371     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
372         COMPtr<IWebUIDelegatePrivate> uiPrivate;
373         if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) {
374             BOOL result;
375             if (SUCCEEDED(uiPrivate->webViewShouldInterruptJavaScript(m_webView, &result)))
376                 return !!result;
377         }
378     }
379     return false;
380 }
381
382 bool WebChromeClient::tabsToLinks() const
383 {
384     BOOL enabled = FALSE;
385     IWebPreferences* preferences;
386     if (SUCCEEDED(m_webView->preferences(&preferences)))
387         preferences->tabsToLinks(&enabled);
388
389     return !!enabled;
390 }
391
392 IntRect WebChromeClient::windowResizerRect() const
393 {
394     IntRect intRect;
395
396     IWebUIDelegate* ui;
397     if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) {
398         IWebUIDelegatePrivate* uiPrivate;
399         if (SUCCEEDED(ui->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) {
400             RECT r;
401             if (SUCCEEDED(uiPrivate->webViewResizerRect(m_webView, &r)))
402                 intRect = IntRect(r.left, r.top, r.right-r.left, r.bottom-r.top);
403             uiPrivate->Release();
404         }
405         ui->Release();
406     }
407     return intRect;
408 }
409
410 void WebChromeClient::addToDirtyRegion(const IntRect& dirtyRect)
411 {
412     m_webView->addToDirtyRegion(dirtyRect);
413 }
414
415 void WebChromeClient::scrollBackingStore(int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect)
416 {
417     ASSERT(core(m_webView->topLevelFrame()));
418
419     m_webView->scrollBackingStore(core(m_webView->topLevelFrame())->view(), dx, dy, scrollViewRect, clipRect);
420 }
421
422 void WebChromeClient::updateBackingStore()
423 {
424     ASSERT(core(m_webView->topLevelFrame()));
425
426     m_webView->updateBackingStore(core(m_webView->topLevelFrame())->view(), 0, false);
427 }
428
429 void WebChromeClient::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags)
430 {
431     COMPtr<IWebUIDelegate> uiDelegate;
432     if (FAILED(m_webView->uiDelegate(&uiDelegate)))
433         return;
434
435     COMPtr<WebElementPropertyBag> element;
436     element.adoptRef(WebElementPropertyBag::createInstance(result));
437
438     uiDelegate->mouseDidMoveOverElement(m_webView, element.get(), modifierFlags);
439 }
440
441 void WebChromeClient::setToolTip(const String& toolTip)
442 {
443     m_webView->setToolTip(toolTip);
444 }
445
446 void WebChromeClient::print(Frame* frame)
447 {
448     COMPtr<IWebUIDelegate> uiDelegate;
449     COMPtr<IWebUIDelegate2> uiDelegate2;
450     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate)))
451         if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegate2, (void**)&uiDelegate2)))
452             uiDelegate2->printFrame(m_webView, kit(frame));
453 }