• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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