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