1 /*
2 * Copyright (C) 2006, 2007, 2008 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 "WebHistory.h"
32 #include "WebMutableURLRequest.h"
33 #include "WebSecurityOrigin.h"
34 #include "WebView.h"
35 #pragma warning(push, 0)
36 #include <WebCore/BString.h>
37 #include <WebCore/ContextMenu.h>
38 #include <WebCore/FileChooser.h>
39 #include <WebCore/FloatRect.h>
40 #include <WebCore/FrameLoadRequest.h>
41 #include <WebCore/FrameView.h>
42 #include <WebCore/LocalizedStrings.h>
43 #include <WebCore/NotImplemented.h>
44 #include <WebCore/Page.h>
45 #include <WebCore/WindowFeatures.h>
46 #pragma warning(pop)
47
48 #include <tchar.h>
49
50 using namespace WebCore;
51
52 // When you call GetOpenFileName, if the size of the buffer is too small,
53 // MSDN says that the first two bytes of the buffer contain the required size for the file selection, in bytes or characters
54 // So we can assume the required size can't be more than the maximum value for a short.
55 static const size_t maxFilePathsListSize = USHRT_MAX;
56
WebChromeClient(WebView * webView)57 WebChromeClient::WebChromeClient(WebView* webView)
58 : m_webView(webView)
59 {
60 }
61
chromeDestroyed()62 void WebChromeClient::chromeDestroyed()
63 {
64 delete this;
65 }
66
setWindowRect(const FloatRect & r)67 void WebChromeClient::setWindowRect(const FloatRect& r)
68 {
69 IWebUIDelegate* uiDelegate = 0;
70 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
71 RECT rect = IntRect(r);
72 uiDelegate->setFrame(m_webView, &rect);
73 uiDelegate->Release();
74 }
75 }
76
windowRect()77 FloatRect WebChromeClient::windowRect()
78 {
79 IWebUIDelegate* uiDelegate = 0;
80 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
81 RECT rect;
82 HRESULT retval = uiDelegate->webViewFrame(m_webView, &rect);
83
84 uiDelegate->Release();
85
86 if (SUCCEEDED(retval))
87 return rect;
88 }
89
90 return FloatRect();
91 }
92
pageRect()93 FloatRect WebChromeClient::pageRect()
94 {
95 RECT rect;
96 m_webView->frameRect(&rect);
97 return rect;
98 }
99
scaleFactor()100 float WebChromeClient::scaleFactor()
101 {
102 // Windows doesn't support UI scaling.
103 return 1.0;
104 }
105
focus()106 void WebChromeClient::focus()
107 {
108 IWebUIDelegate* uiDelegate = 0;
109 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
110 uiDelegate->webViewFocus(m_webView);
111 uiDelegate->Release();
112 }
113 // Normally this would happen on a timer, but JS might need to know this earlier, so we'll update here.
114 m_webView->updateActiveState();
115 }
116
unfocus()117 void WebChromeClient::unfocus()
118 {
119 IWebUIDelegate* uiDelegate = 0;
120 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
121 uiDelegate->webViewUnfocus(m_webView);
122 uiDelegate->Release();
123 }
124 // Normally this would happen on a timer, but JS might need to know this earlier, so we'll update here.
125 m_webView->updateActiveState();
126 }
127
canTakeFocus(FocusDirection direction)128 bool WebChromeClient::canTakeFocus(FocusDirection direction)
129 {
130 IWebUIDelegate* uiDelegate = 0;
131 BOOL bForward = (direction == FocusDirectionForward) ? TRUE : FALSE;
132 BOOL result = FALSE;
133 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
134 uiDelegate->canTakeFocus(m_webView, bForward, &result);
135 uiDelegate->Release();
136 }
137
138 return !!result;
139 }
140
takeFocus(FocusDirection direction)141 void WebChromeClient::takeFocus(FocusDirection direction)
142 {
143 IWebUIDelegate* uiDelegate = 0;
144 BOOL bForward = (direction == FocusDirectionForward) ? TRUE : FALSE;
145 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
146 uiDelegate->takeFocus(m_webView, bForward);
147 uiDelegate->Release();
148 }
149 }
150
createWindow(Frame *,const FrameLoadRequest & frameLoadRequest,const WindowFeatures & features)151 Page* WebChromeClient::createWindow(Frame*, const FrameLoadRequest& frameLoadRequest, const WindowFeatures& features)
152 {
153 if (features.dialog) {
154 COMPtr<IWebUIDelegate3> delegate = uiDelegate3();
155 if (!delegate)
156 return 0;
157 COMPtr<IWebMutableURLRequest> request(AdoptCOM, WebMutableURLRequest::createInstance(frameLoadRequest.resourceRequest()));
158 COMPtr<IWebView> dialog;
159 if (FAILED(delegate->createModalDialog(m_webView, request.get(), &dialog)))
160 return 0;
161 return core(dialog.get());
162 }
163
164 Page* page = 0;
165 IWebUIDelegate* uiDelegate = 0;
166 IWebMutableURLRequest* request = WebMutableURLRequest::createInstance(frameLoadRequest.resourceRequest());
167
168 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
169 IWebView* webView = 0;
170 if (SUCCEEDED(uiDelegate->createWebViewWithRequest(m_webView, request, &webView))) {
171 page = core(webView);
172 webView->Release();
173 }
174
175 uiDelegate->Release();
176 }
177
178 request->Release();
179 return page;
180 }
181
show()182 void WebChromeClient::show()
183 {
184 IWebUIDelegate* uiDelegate = 0;
185 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
186 uiDelegate->webViewShow(m_webView);
187 uiDelegate->Release();
188 }
189 }
190
canRunModal()191 bool WebChromeClient::canRunModal()
192 {
193 BOOL result = FALSE;
194 if (COMPtr<IWebUIDelegate3> delegate = uiDelegate3())
195 delegate->canRunModal(m_webView, &result);
196 return result;
197 }
198
runModal()199 void WebChromeClient::runModal()
200 {
201 if (COMPtr<IWebUIDelegate3> delegate = uiDelegate3())
202 delegate->runModal(m_webView);
203 }
204
setToolbarsVisible(bool visible)205 void WebChromeClient::setToolbarsVisible(bool visible)
206 {
207 IWebUIDelegate* uiDelegate = 0;
208 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
209 uiDelegate->setToolbarsVisible(m_webView, visible);
210 uiDelegate->Release();
211 }
212 }
213
toolbarsVisible()214 bool WebChromeClient::toolbarsVisible()
215 {
216 BOOL result = false;
217 IWebUIDelegate* uiDelegate = 0;
218 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
219 uiDelegate->webViewAreToolbarsVisible(m_webView, &result);
220 uiDelegate->Release();
221 }
222 return result != false;
223 }
224
setStatusbarVisible(bool visible)225 void WebChromeClient::setStatusbarVisible(bool visible)
226 {
227 IWebUIDelegate* uiDelegate = 0;
228 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
229 uiDelegate->setStatusBarVisible(m_webView, visible);
230 uiDelegate->Release();
231 }
232 }
233
statusbarVisible()234 bool WebChromeClient::statusbarVisible()
235 {
236 BOOL result = false;
237 IWebUIDelegate* uiDelegate = 0;
238 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
239 uiDelegate->webViewIsStatusBarVisible(m_webView, &result);
240 uiDelegate->Release();
241 }
242 return result != false;
243 }
244
setScrollbarsVisible(bool b)245 void WebChromeClient::setScrollbarsVisible(bool b)
246 {
247 WebFrame* webFrame = m_webView->topLevelFrame();
248 if (webFrame)
249 webFrame->setAllowsScrolling(b);
250 }
251
scrollbarsVisible()252 bool WebChromeClient::scrollbarsVisible()
253 {
254 WebFrame* webFrame = m_webView->topLevelFrame();
255 BOOL b = false;
256 if (webFrame)
257 webFrame->allowsScrolling(&b);
258
259 return !!b;
260 }
261
setMenubarVisible(bool visible)262 void WebChromeClient::setMenubarVisible(bool visible)
263 {
264 COMPtr<IWebUIDelegate3> delegate = uiDelegate3();
265 if (!delegate)
266 return;
267 delegate->setMenuBarVisible(m_webView, visible);
268 }
269
menubarVisible()270 bool WebChromeClient::menubarVisible()
271 {
272 COMPtr<IWebUIDelegate3> delegate = uiDelegate3();
273 if (!delegate)
274 return true;
275 BOOL result = true;
276 delegate->isMenuBarVisible(m_webView, &result);
277 return result;
278 }
279
setResizable(bool resizable)280 void WebChromeClient::setResizable(bool resizable)
281 {
282 IWebUIDelegate* uiDelegate = 0;
283 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
284 uiDelegate->setResizable(m_webView, resizable);
285 uiDelegate->Release();
286 }
287 }
288
addMessageToConsole(const String & message,unsigned line,const String & url)289 void WebChromeClient::addMessageToConsole(const String& message, unsigned line, const String& url)
290 {
291 COMPtr<IWebUIDelegate> uiDelegate;
292 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
293 COMPtr<IWebUIDelegatePrivate> uiPrivate;
294 if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate)))
295 uiPrivate->webViewAddMessageToConsole(m_webView, BString(message), line, BString(url), true);
296 }
297 }
298
canRunBeforeUnloadConfirmPanel()299 bool WebChromeClient::canRunBeforeUnloadConfirmPanel()
300 {
301 IWebUIDelegate* ui;
302 if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) {
303 ui->Release();
304 return true;
305 }
306 return false;
307 }
308
runBeforeUnloadConfirmPanel(const String & message,Frame * frame)309 bool WebChromeClient::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
310 {
311 BOOL result = TRUE;
312 IWebUIDelegate* ui;
313 if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) {
314 WebFrame* webFrame = kit(frame);
315 ui->runBeforeUnloadConfirmPanelWithMessage(m_webView, BString(message), webFrame, &result);
316 ui->Release();
317 }
318 return !!result;
319 }
320
closeWindowSoon()321 void WebChromeClient::closeWindowSoon()
322 {
323 // We need to remove the parent WebView from WebViewSets here, before it actually
324 // closes, to make sure that JavaScript code that executes before it closes
325 // can't find it. Otherwise, window.open will select a closed WebView instead of
326 // opening a new one <rdar://problem/3572585>.
327
328 // We also need to stop the load to prevent further parsing or JavaScript execution
329 // after the window has torn down <rdar://problem/4161660>.
330
331 // FIXME: This code assumes that the UI delegate will respond to a webViewClose
332 // message by actually closing the WebView. Safari guarantees this behavior, but other apps might not.
333 // This approach is an inherent limitation of not making a close execute immediately
334 // after a call to window.close.
335
336 m_webView->setGroupName(0);
337 m_webView->stopLoading(0);
338 m_webView->closeWindowSoon();
339 }
340
runJavaScriptAlert(Frame *,const String & message)341 void WebChromeClient::runJavaScriptAlert(Frame*, const String& message)
342 {
343 COMPtr<IWebUIDelegate> ui;
344 if (SUCCEEDED(m_webView->uiDelegate(&ui)))
345 ui->runJavaScriptAlertPanelWithMessage(m_webView, BString(message));
346 }
347
runJavaScriptConfirm(Frame *,const String & message)348 bool WebChromeClient::runJavaScriptConfirm(Frame*, const String& message)
349 {
350 BOOL result = FALSE;
351 COMPtr<IWebUIDelegate> ui;
352 if (SUCCEEDED(m_webView->uiDelegate(&ui)))
353 ui->runJavaScriptConfirmPanelWithMessage(m_webView, BString(message), &result);
354 return !!result;
355 }
356
runJavaScriptPrompt(Frame *,const String & message,const String & defaultValue,String & result)357 bool WebChromeClient::runJavaScriptPrompt(Frame*, const String& message, const String& defaultValue, String& result)
358 {
359 COMPtr<IWebUIDelegate> ui;
360 if (FAILED(m_webView->uiDelegate(&ui)))
361 return false;
362
363 TimerBase::fireTimersInNestedEventLoop();
364
365 BSTR resultBSTR = 0;
366 if (FAILED(ui->runJavaScriptTextInputPanelWithPrompt(m_webView, BString(message), BString(defaultValue), &resultBSTR)))
367 return false;
368
369 if (resultBSTR) {
370 result = String(resultBSTR, SysStringLen(resultBSTR));
371 SysFreeString(resultBSTR);
372 return true;
373 }
374
375 return false;
376 }
377
setStatusbarText(const String & statusText)378 void WebChromeClient::setStatusbarText(const String& statusText)
379 {
380 COMPtr<IWebUIDelegate> uiDelegate;
381 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
382 uiDelegate->setStatusText(m_webView, BString(statusText));
383 }
384 }
385
shouldInterruptJavaScript()386 bool WebChromeClient::shouldInterruptJavaScript()
387 {
388 COMPtr<IWebUIDelegate> uiDelegate;
389 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
390 COMPtr<IWebUIDelegatePrivate> uiPrivate;
391 if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) {
392 BOOL result;
393 if (SUCCEEDED(uiPrivate->webViewShouldInterruptJavaScript(m_webView, &result)))
394 return !!result;
395 }
396 }
397 return false;
398 }
399
tabsToLinks() const400 bool WebChromeClient::tabsToLinks() const
401 {
402 BOOL enabled = FALSE;
403 IWebPreferences* preferences;
404 if (SUCCEEDED(m_webView->preferences(&preferences)))
405 preferences->tabsToLinks(&enabled);
406
407 return !!enabled;
408 }
409
windowResizerRect() const410 IntRect WebChromeClient::windowResizerRect() const
411 {
412 IntRect intRect;
413
414 IWebUIDelegate* ui;
415 if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) {
416 IWebUIDelegatePrivate* uiPrivate;
417 if (SUCCEEDED(ui->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) {
418 RECT r;
419 if (SUCCEEDED(uiPrivate->webViewResizerRect(m_webView, &r)))
420 intRect = IntRect(r.left, r.top, r.right-r.left, r.bottom-r.top);
421 uiPrivate->Release();
422 }
423 ui->Release();
424 }
425 return intRect;
426 }
427
repaint(const IntRect & windowRect,bool contentChanged,bool immediate,bool repaintContentOnly)428 void WebChromeClient::repaint(const IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly)
429 {
430 ASSERT(core(m_webView->topLevelFrame()));
431 m_webView->repaint(windowRect, contentChanged, immediate, repaintContentOnly);
432 }
433
scroll(const IntSize & delta,const IntRect & scrollViewRect,const IntRect & clipRect)434 void WebChromeClient::scroll(const IntSize& delta, const IntRect& scrollViewRect, const IntRect& clipRect)
435 {
436 ASSERT(core(m_webView->topLevelFrame()));
437
438 m_webView->scrollBackingStore(core(m_webView->topLevelFrame())->view(), delta.width(), delta.height(), scrollViewRect, clipRect);
439 }
440
windowToScreen(const IntRect & rect) const441 IntRect WebChromeClient::windowToScreen(const IntRect& rect) const
442 {
443 HWND viewWindow;
444 if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))))
445 return rect;
446
447 // Find the top left corner of the Widget's containing window in screen coords,
448 // and adjust the result rect's position by this amount.
449 POINT topLeft = {0, 0};
450 IntRect result = rect;
451 ::ClientToScreen(viewWindow, &topLeft);
452 result.move(topLeft.x, topLeft.y);
453
454 return result;
455 }
456
screenToWindow(const IntPoint & point) const457 IntPoint WebChromeClient::screenToWindow(const IntPoint& point) const
458 {
459 POINT result = point;
460
461 HWND viewWindow;
462 if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))))
463 return point;
464
465 ::ScreenToClient(viewWindow, &result);
466
467 return result;
468 }
469
platformWindow() const470 PlatformWidget WebChromeClient::platformWindow() const
471 {
472 HWND viewWindow;
473 if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))))
474 return 0;
475 return viewWindow;
476 }
477
contentsSizeChanged(Frame *,const IntSize &) const478 void WebChromeClient::contentsSizeChanged(Frame*, const IntSize&) const
479 {
480 notImplemented();
481 }
482
mouseDidMoveOverElement(const HitTestResult & result,unsigned modifierFlags)483 void WebChromeClient::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags)
484 {
485 COMPtr<IWebUIDelegate> uiDelegate;
486 if (FAILED(m_webView->uiDelegate(&uiDelegate)))
487 return;
488
489 COMPtr<WebElementPropertyBag> element;
490 element.adoptRef(WebElementPropertyBag::createInstance(result));
491
492 uiDelegate->mouseDidMoveOverElement(m_webView, element.get(), modifierFlags);
493 }
494
setToolTip(const String & toolTip)495 void WebChromeClient::setToolTip(const String& toolTip)
496 {
497 m_webView->setToolTip(toolTip);
498 }
499
print(Frame * frame)500 void WebChromeClient::print(Frame* frame)
501 {
502 COMPtr<IWebUIDelegate> uiDelegate;
503 COMPtr<IWebUIDelegate2> uiDelegate2;
504 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate)))
505 if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegate2, (void**)&uiDelegate2)))
506 uiDelegate2->printFrame(m_webView, kit(frame));
507 }
508
exceededDatabaseQuota(Frame * frame,const String & databaseIdentifier)509 void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseIdentifier)
510 {
511 COMPtr<WebSecurityOrigin> origin(AdoptCOM, WebSecurityOrigin::createInstance(frame->document()->securityOrigin()));
512 COMPtr<IWebUIDelegate> uiDelegate;
513 if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
514 COMPtr<IWebUIDelegatePrivate3> uiDelegatePrivate3(Query, uiDelegate);
515 if (uiDelegatePrivate3)
516 uiDelegatePrivate3->exceededDatabaseQuota(m_webView, kit(frame), origin.get(), BString(databaseIdentifier));
517 else {
518 // FIXME: remove this workaround once shipping Safari has the necessary delegate implemented.
519 TCHAR path[MAX_PATH];
520 HMODULE safariHandle = GetModuleHandle(TEXT("Safari.exe"));
521 if (!safariHandle)
522 return;
523 GetModuleFileName(safariHandle, path, ARRAYSIZE(path));
524 DWORD handle;
525 DWORD versionSize = GetFileVersionInfoSize(path, &handle);
526 if (!versionSize)
527 return;
528 Vector<char> data(versionSize);
529 if (!GetFileVersionInfo(path, 0, versionSize, data.data()))
530 return;
531
532 LPCTSTR productVersion;
533 UINT productVersionLength;
534 if (!VerQueryValue(data.data(), TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), (void**)&productVersion, &productVersionLength))
535 return;
536 if (_tcsncmp(TEXT("3.1"), productVersion, productVersionLength) > 0) {
537 const unsigned long long defaultQuota = 5 * 1024 * 1024; // 5 megabytes should hopefully be enough to test storage support.
538 origin->setQuota(defaultQuota);
539 }
540 }
541 }
542 }
543
populateVisitedLinks()544 void WebChromeClient::populateVisitedLinks()
545 {
546 WebHistory* history = WebHistory::sharedHistory();
547 if (!history)
548 return;
549 history->addVisitedLinksToPageGroup(m_webView->page()->group());
550 }
551
paintCustomScrollbar(GraphicsContext * context,const FloatRect & rect,ScrollbarControlSize size,ScrollbarControlState state,ScrollbarPart pressedPart,bool vertical,float value,float proportion,ScrollbarControlPartMask parts)552 bool WebChromeClient::paintCustomScrollbar(GraphicsContext* context, const FloatRect& rect, ScrollbarControlSize size,
553 ScrollbarControlState state, ScrollbarPart pressedPart, bool vertical,
554 float value, float proportion, ScrollbarControlPartMask parts)
555 {
556 if (context->paintingDisabled())
557 return false;
558
559 COMPtr<IWebUIDelegate4> delegate = uiDelegate4();
560 if (!delegate)
561 return false;
562
563 WebScrollbarControlPartMask webParts = WebNoScrollPart;
564 if (parts & BackButtonStartPart) // FIXME: Hyatt, what about BackButtonEndPart?
565 webParts |= WebBackButtonPart;
566 if (parts & BackTrackPart)
567 webParts |= WebBackTrackPart;
568 if (parts & ThumbPart)
569 webParts |= WebThumbPart;
570 if (parts & ForwardTrackPart)
571 webParts |= WebForwardTrackPart;
572 if (parts & ForwardButtonStartPart) // FIXME: Hyatt, what about ForwardButtonEndPart?
573 webParts |= WebForwardButtonPart;
574
575 WebScrollbarControlPart webPressedPart = WebNoScrollPart;
576 switch (pressedPart) {
577 case BackButtonStartPart: // FIXME: Hyatt, what about BackButtonEndPart?
578 webPressedPart = WebBackButtonPart;
579 break;
580 case BackTrackPart:
581 webPressedPart = WebBackTrackPart;
582 break;
583 case ThumbPart:
584 webPressedPart = WebThumbPart;
585 break;
586 case ForwardTrackPart:
587 webPressedPart = WebForwardTrackPart;
588 break;
589 case ForwardButtonStartPart: // FIXME: Hyatt, what about ForwardButtonEndPart?
590 webPressedPart = WebForwardButtonPart;
591 break;
592 default:
593 break;
594 }
595
596 WebScrollBarControlSize webSize;
597 switch (size) {
598 case SmallScrollbar:
599 webSize = WebSmallScrollbar;
600 break;
601 case RegularScrollbar:
602 default:
603 webSize = WebRegularScrollbar;
604 }
605 WebScrollbarControlState webState = 0;
606 if (state & ActiveScrollbarState)
607 webState |= WebActiveScrollbarState;
608 if (state & EnabledScrollbarState)
609 webState |= WebEnabledScrollbarState;
610 if (state & PressedScrollbarState)
611 webState |= WebPressedScrollbarState;
612
613 RECT webRect = enclosingIntRect(rect);
614 HDC hDC = context->getWindowsContext(webRect);
615 HRESULT hr = delegate->paintCustomScrollbar(m_webView, hDC, webRect, webSize, webState, webPressedPart,
616 vertical, value, proportion, webParts);
617 context->releaseWindowsContext(hDC, webRect);
618 return SUCCEEDED(hr);
619 }
620
paintCustomScrollCorner(GraphicsContext * context,const FloatRect & rect)621 bool WebChromeClient::paintCustomScrollCorner(GraphicsContext* context, const FloatRect& rect)
622 {
623 if (context->paintingDisabled())
624 return false;
625
626 COMPtr<IWebUIDelegate4> delegate = uiDelegate4();
627 if (!delegate)
628 return false;
629
630 RECT webRect = enclosingIntRect(rect);
631 HDC hDC = context->getWindowsContext(webRect);
632 HRESULT hr = delegate->paintCustomScrollCorner(m_webView, hDC, webRect);
633 context->releaseWindowsContext(hDC, webRect);
634 return SUCCEEDED(hr);
635 }
636
runOpenPanel(Frame *,PassRefPtr<FileChooser> prpFileChooser)637 void WebChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser)
638 {
639 RefPtr<FileChooser> fileChooser = prpFileChooser;
640
641 HWND viewWindow;
642 if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))))
643 return;
644
645 bool multiFile = fileChooser->allowsMultipleFiles();
646 Vector<TCHAR> fileBuf(multiFile ? maxFilePathsListSize : MAX_PATH);
647
648 OPENFILENAME ofn;
649
650 memset(&ofn, 0, sizeof(ofn));
651
652 // Need to zero out the first char of fileBuf so GetOpenFileName doesn't think it's an initialization string
653 fileBuf[0] = '\0';
654
655 ofn.lStructSize = sizeof(ofn);
656 ofn.hwndOwner = viewWindow;
657 String allFiles = allFilesText();
658 allFiles.append(TEXT("\0*.*\0\0"), 6);
659 ofn.lpstrFilter = allFiles.charactersWithNullTermination();
660 ofn.lpstrFile = fileBuf.data();
661 ofn.nMaxFile = fileBuf.size();
662 String dialogTitle = uploadFileText();
663 ofn.lpstrTitle = dialogTitle.charactersWithNullTermination();
664 ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER;
665 if (multiFile)
666 ofn.Flags = ofn.Flags | OFN_ALLOWMULTISELECT;
667
668 if (GetOpenFileName(&ofn)) {
669 TCHAR* files = fileBuf.data();
670 Vector<String> fileList;
671 String file(files);
672 if (multiFile) {
673 while (!file.isEmpty()) {
674 // When using the OFN_EXPLORER flag, the file list is null delimited.
675 // When you create a String from a ptr to this list, it will use strlen to look for the null character.
676 // Then we find the next file path string by using the length of the string we just created.
677 TCHAR* nextFilePtr = files + file.length() + 1;
678 String nextFile(nextFilePtr);
679 // If multiple files are selected, there will be a directory name first, which we don't want to add to the vector.
680 // We know a single file was selected if there is only one filename in the list.
681 // In that case, we don't want to skip adding the first (and only) name.
682 if (files != fileBuf.data() || nextFile.isEmpty())
683 fileList.append(file);
684 files = nextFilePtr;
685 file = nextFile;
686 }
687 } else
688 fileList.append(file);
689 ASSERT(fileList.size());
690 fileChooser->chooseFiles(fileList);
691 }
692 // FIXME: Show some sort of error if too many files are selected and the buffer is too small. For now, this will fail silently.
693 }
694
uiDelegate()695 COMPtr<IWebUIDelegate> WebChromeClient::uiDelegate()
696 {
697 COMPtr<IWebUIDelegate> delegate;
698 m_webView->uiDelegate(&delegate);
699 return delegate;
700 }
701
uiDelegate2()702 COMPtr<IWebUIDelegate2> WebChromeClient::uiDelegate2()
703 {
704 return COMPtr<IWebUIDelegate2>(Query, uiDelegate());
705 }
706
uiDelegate3()707 COMPtr<IWebUIDelegate3> WebChromeClient::uiDelegate3()
708 {
709 return COMPtr<IWebUIDelegate3>(Query, uiDelegate());
710 }
711
uiDelegate4()712 COMPtr<IWebUIDelegate4> WebChromeClient::uiDelegate4()
713 {
714 return COMPtr<IWebUIDelegate4>(Query, uiDelegate());
715 }
716