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