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