Reduce PassRefPtr in WebKit2 - 3
[WebKit-https.git] / Source / WebKit / win / WebCoreSupport / WebChromeClient.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "WebChromeClient.h"
28
29 #include "COMPropertyBag.h"
30 #include "COMVariantSetter.h"
31 #include "DOMCoreClasses.h"
32 #include "WebElementPropertyBag.h"
33 #include "WebFrame.h"
34 #include "WebHistory.h"
35 #include "WebMutableURLRequest.h"
36 #include "WebDesktopNotificationsDelegate.h"
37 #include "WebSecurityOrigin.h"
38 #include "WebView.h"
39 #include <WebCore/BString.h>
40 #include <WebCore/ContextMenu.h>
41 #include <WebCore/Cursor.h>
42 #include <WebCore/FileChooser.h>
43 #include <WebCore/FileIconLoader.h>
44 #include <WebCore/FloatRect.h>
45 #include <WebCore/Frame.h>
46 #include <WebCore/FrameLoadRequest.h>
47 #include <WebCore/FrameView.h>
48 #include <WebCore/FullScreenController.h>
49 #include <WebCore/GraphicsLayer.h>
50 #include <WebCore/HTMLNames.h>
51 #include <WebCore/HTMLVideoElement.h>
52 #include <WebCore/Icon.h>
53 #include <WebCore/LocalWindowsContext.h>
54 #include <WebCore/LocalizedStrings.h>
55 #include <WebCore/NavigationAction.h>
56 #include <WebCore/NotImplemented.h>
57 #include <WebCore/Page.h>
58 #include <WebCore/SecurityOrigin.h>
59 #include <WebCore/PopupMenuWin.h>
60 #include <WebCore/SearchPopupMenuWin.h>
61 #include <WebCore/WindowFeatures.h>
62 #include <wchar.h>
63
64 using namespace WebCore;
65
66 // When you call GetOpenFileName, if the size of the buffer is too small,
67 // MSDN says that the first two bytes of the buffer contain the required size for the file selection, in bytes or characters
68 // So we can assume the required size can't be more than the maximum value for a short.
69 static const size_t maxFilePathsListSize = USHRT_MAX;
70
71 WebChromeClient::WebChromeClient(WebView* webView)
72     : m_webView(webView)
73 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
74     , m_notificationsDelegate(std::make_unique<WebDesktopNotificationsDelegate>(webView))
75 #endif
76 {
77 }
78
79 void WebChromeClient::chromeDestroyed()
80 {
81     delete this;
82 }
83
84 void WebChromeClient::setWindowRect(const FloatRect& r)
85 {
86     IWebUIDelegate* uiDelegate = 0;
87     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
88         RECT rect = IntRect(r);
89         uiDelegate->setFrame(m_webView, &rect);
90         uiDelegate->Release();
91     }
92 }
93
94 FloatRect WebChromeClient::windowRect()
95 {
96     IWebUIDelegate* uiDelegate = 0;
97     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
98         RECT rect;
99         HRESULT retval = uiDelegate->webViewFrame(m_webView, &rect);
100
101         uiDelegate->Release();
102
103         if (SUCCEEDED(retval))
104             return rect;
105     }
106
107     return FloatRect();
108 }
109
110 FloatRect WebChromeClient::pageRect()
111 {
112     RECT rect;
113     m_webView->frameRect(&rect);
114     return rect;
115 }
116
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
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
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
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
162 void WebChromeClient::focusedElementChanged(Element*)
163 {
164 }
165
166 void WebChromeClient::focusedFrameChanged(Frame*)
167 {
168 }
169
170 static COMPtr<IPropertyBag> createWindowFeaturesPropertyBag(const WindowFeatures& features)
171 {
172     HashMap<String, COMVariant> map;
173     if (features.xSet)
174         map.set(WebWindowFeaturesXKey, features.x);
175     if (features.ySet)
176         map.set(WebWindowFeaturesYKey, features.y);
177     if (features.widthSet)
178         map.set(WebWindowFeaturesWidthKey, features.width);
179     if (features.heightSet)
180         map.set(WebWindowFeaturesHeightKey, features.height);
181     map.set(WebWindowFeaturesMenuBarVisibleKey, features.menuBarVisible);
182     map.set(WebWindowFeaturesStatusBarVisibleKey, features.statusBarVisible);
183     map.set(WebWindowFeaturesToolBarVisibleKey, features.toolBarVisible);
184     map.set(WebWindowFeaturesScrollbarsVisibleKey, features.scrollbarsVisible);
185     map.set(WebWindowFeaturesResizableKey, features.resizable);
186     map.set(WebWindowFeaturesFullscreenKey, features.fullscreen);
187     map.set(WebWindowFeaturesDialogKey, features.dialog);
188
189     return COMPtr<IPropertyBag>(AdoptCOM, COMPropertyBag<COMVariant>::adopt(map));
190 }
191
192 Page* WebChromeClient::createWindow(Frame* frame, const FrameLoadRequest&, const WindowFeatures& features, const NavigationAction& navigationAction)
193 {
194     COMPtr<IWebUIDelegate> delegate = uiDelegate();
195     if (!delegate)
196         return 0;
197
198 #if ENABLE(FULLSCREEN_API)
199     if (frame->document() && frame->document()->webkitCurrentFullScreenElement())
200         frame->document()->webkitCancelFullScreen();
201 #endif
202
203     COMPtr<WebMutableURLRequest> request = adoptCOM(WebMutableURLRequest::createInstance(ResourceRequest(navigationAction.url())));
204
205     COMPtr<IWebUIDelegatePrivate2> delegatePrivate(Query, delegate);
206     if (delegatePrivate) {
207         COMPtr<IWebView> newWebView;
208         HRESULT hr = delegatePrivate->createWebViewWithRequest(m_webView, request.get(), createWindowFeaturesPropertyBag(features).get(), &newWebView);
209
210         if (SUCCEEDED(hr) && newWebView)
211             return core(newWebView.get());
212
213         // If the delegate doesn't implement the IWebUIDelegatePrivate2 version of the call, fall back
214         // to the old versions (even if they support the IWebUIDelegatePrivate2 interface).
215         if (hr != E_NOTIMPL)
216             return 0;
217     }
218
219     COMPtr<IWebView> newWebView;
220
221     if (features.dialog) {
222         if (FAILED(delegate->createModalDialog(m_webView, request.get(), &newWebView)))
223             return 0;
224     } else if (FAILED(delegate->createWebViewWithRequest(m_webView, request.get(), &newWebView)))
225         return 0;
226
227     return newWebView ? core(newWebView.get()) : 0;
228 }
229
230 void WebChromeClient::show()
231 {
232     IWebUIDelegate* uiDelegate = 0;
233     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
234         uiDelegate->webViewShow(m_webView);
235         uiDelegate->Release();
236     }
237 }
238
239 bool WebChromeClient::canRunModal()
240 {
241     BOOL result = FALSE;
242     if (COMPtr<IWebUIDelegate> delegate = uiDelegate())
243         delegate->canRunModal(m_webView, &result);
244     return result;
245 }
246
247 void WebChromeClient::runModal()
248 {
249     if (COMPtr<IWebUIDelegate> delegate = uiDelegate())
250         delegate->runModal(m_webView);
251 }
252
253 void WebChromeClient::setToolbarsVisible(bool visible)
254 {
255     IWebUIDelegate* uiDelegate = 0;
256     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
257         uiDelegate->setToolbarsVisible(m_webView, visible);
258         uiDelegate->Release();
259     }
260 }
261
262 bool WebChromeClient::toolbarsVisible()
263 {
264     BOOL result = false;
265     IWebUIDelegate* uiDelegate = 0;
266     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
267         uiDelegate->webViewAreToolbarsVisible(m_webView, &result);
268         uiDelegate->Release();
269     }
270     return result != false;
271 }
272
273 void WebChromeClient::setStatusbarVisible(bool visible)
274 {
275     IWebUIDelegate* uiDelegate = 0;
276     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
277         uiDelegate->setStatusBarVisible(m_webView, visible);
278         uiDelegate->Release();
279     }
280 }
281
282 bool WebChromeClient::statusbarVisible()
283 {
284     BOOL result = false;
285     IWebUIDelegate* uiDelegate = 0;
286     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
287         uiDelegate->webViewIsStatusBarVisible(m_webView, &result);
288         uiDelegate->Release();
289     }
290     return result != false;
291 }
292
293 void WebChromeClient::setScrollbarsVisible(bool b)
294 {
295     WebFrame* webFrame = m_webView->topLevelFrame();
296     if (webFrame)
297         webFrame->setAllowsScrolling(b);
298 }
299
300 bool WebChromeClient::scrollbarsVisible()
301 {
302     WebFrame* webFrame = m_webView->topLevelFrame();
303     BOOL b = false;
304     if (webFrame)
305         webFrame->allowsScrolling(&b);
306
307     return !!b;
308 }
309
310 void WebChromeClient::setMenubarVisible(bool visible)
311 {
312     COMPtr<IWebUIDelegate> delegate = uiDelegate();
313     if (!delegate)
314         return;
315     delegate->setMenuBarVisible(m_webView, visible);
316 }
317
318 bool WebChromeClient::menubarVisible()
319 {
320     COMPtr<IWebUIDelegate> delegate = uiDelegate();
321     if (!delegate)
322         return true;
323     BOOL result = true;
324     delegate->isMenuBarVisible(m_webView, &result);
325     return result;
326 }
327
328 void WebChromeClient::setResizable(bool resizable)
329 {
330     IWebUIDelegate* uiDelegate = 0;
331     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
332         uiDelegate->setResizable(m_webView, resizable);
333         uiDelegate->Release();
334     }
335 }
336
337 static BOOL messageIsError(MessageLevel level)
338 {
339     return level == MessageLevel::Error;
340 }
341
342 void WebChromeClient::addMessageToConsole(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, unsigned columnNumber, const String& url)
343 {
344     UNUSED_PARAM(columnNumber);
345
346     COMPtr<IWebUIDelegate> uiDelegate;
347     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
348         COMPtr<IWebUIDelegatePrivate> uiPrivate;
349         if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate)))
350             uiPrivate->webViewAddMessageToConsole(m_webView, BString(message), lineNumber, BString(url), messageIsError(level));
351     }
352 }
353
354 bool WebChromeClient::canRunBeforeUnloadConfirmPanel()
355 {
356     IWebUIDelegate* ui;
357     if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) {
358         ui->Release();
359         return true;
360     }
361     return false;
362 }
363
364 bool WebChromeClient::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
365 {
366     BOOL result = TRUE;
367     IWebUIDelegate* ui;
368     if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) {
369         WebFrame* webFrame = kit(frame);
370         ui->runBeforeUnloadConfirmPanelWithMessage(m_webView, BString(message), webFrame, &result);
371         ui->Release();
372     }
373     return !!result;
374 }
375
376 void WebChromeClient::closeWindowSoon()
377 {
378     // We need to remove the parent WebView from WebViewSets here, before it actually
379     // closes, to make sure that JavaScript code that executes before it closes
380     // can't find it. Otherwise, window.open will select a closed WebView instead of 
381     // opening a new one <rdar://problem/3572585>.
382
383     // We also need to stop the load to prevent further parsing or JavaScript execution
384     // after the window has torn down <rdar://problem/4161660>.
385   
386     // FIXME: This code assumes that the UI delegate will respond to a webViewClose
387     // message by actually closing the WebView. Safari guarantees this behavior, but other apps might not.
388     // This approach is an inherent limitation of not making a close execute immediately
389     // after a call to window.close.
390
391     m_webView->setGroupName(0);
392     m_webView->stopLoading(0);
393     m_webView->closeWindowSoon();
394 }
395
396 void WebChromeClient::runJavaScriptAlert(Frame*, const String& message)
397 {
398     COMPtr<IWebUIDelegate> ui;
399     if (SUCCEEDED(m_webView->uiDelegate(&ui)))
400         ui->runJavaScriptAlertPanelWithMessage(m_webView, BString(message));
401 }
402
403 bool WebChromeClient::runJavaScriptConfirm(Frame*, const String& message)
404 {
405     BOOL result = FALSE;
406     COMPtr<IWebUIDelegate> ui;
407     if (SUCCEEDED(m_webView->uiDelegate(&ui)))
408         ui->runJavaScriptConfirmPanelWithMessage(m_webView, BString(message), &result);
409     return !!result;
410 }
411
412 bool WebChromeClient::runJavaScriptPrompt(Frame*, const String& message, const String& defaultValue, String& result)
413 {
414     COMPtr<IWebUIDelegate> ui;
415     if (FAILED(m_webView->uiDelegate(&ui)))
416         return false;
417
418     TimerBase::fireTimersInNestedEventLoop();
419
420     BString resultBSTR;
421     if (FAILED(ui->runJavaScriptTextInputPanelWithPrompt(m_webView, BString(message), BString(defaultValue), &resultBSTR)))
422         return false;
423
424     if (!resultBSTR)
425         return false;
426
427     result = String(resultBSTR, SysStringLen(resultBSTR));
428     return true;
429 }
430
431 void WebChromeClient::setStatusbarText(const String& statusText)
432 {
433     COMPtr<IWebUIDelegate> uiDelegate;
434     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
435         uiDelegate->setStatusText(m_webView, BString(statusText));
436     }
437 }
438
439 KeyboardUIMode WebChromeClient::keyboardUIMode()
440 {
441     BOOL enabled = FALSE;
442     IWebPreferences* preferences;
443     if (SUCCEEDED(m_webView->preferences(&preferences)))
444         preferences->tabsToLinks(&enabled);
445
446     return enabled ? KeyboardAccessTabsToLinks : KeyboardAccessDefault;
447 }
448
449 void WebChromeClient::invalidateRootView(const IntRect& windowRect)
450 {
451     ASSERT(core(m_webView->topLevelFrame()));
452     m_webView->repaint(windowRect, false /*contentChanged*/, false /*immediate*/, false /*repaintContentOnly*/);
453 }
454
455 void WebChromeClient::invalidateContentsAndRootView(const IntRect& windowRect)
456 {
457     ASSERT(core(m_webView->topLevelFrame()));
458     m_webView->repaint(windowRect, true /*contentChanged*/, false /*immediate*/, false /*repaintContentOnly*/);
459 }
460
461 void WebChromeClient::invalidateContentsForSlowScroll(const IntRect& windowRect)
462 {
463     ASSERT(core(m_webView->topLevelFrame()));
464     m_webView->repaint(windowRect, true /*contentChanged*/, false /*immediate*/, true /*repaintContentOnly*/);
465 }
466
467 void WebChromeClient::scroll(const IntSize& delta, const IntRect& scrollViewRect, const IntRect& clipRect)
468 {
469     ASSERT(core(m_webView->topLevelFrame()));
470
471     m_webView->scrollBackingStore(core(m_webView->topLevelFrame())->view(), delta.width(), delta.height(), scrollViewRect, clipRect);
472 }
473
474 IntRect WebChromeClient::rootViewToScreen(const IntRect& rect) const
475 {
476     HWND viewWindow;
477     if (FAILED(m_webView->viewWindow(&viewWindow)))
478         return rect;
479
480     // Find the top left corner of the Widget's containing window in screen coords,
481     // and adjust the result rect's position by this amount.
482     POINT topLeft = {0, 0};
483     IntRect result = rect;
484     ::ClientToScreen(viewWindow, &topLeft);
485     result.move(topLeft.x, topLeft.y);
486
487     return result;
488 }
489
490 IntPoint WebChromeClient::screenToRootView(const IntPoint& point) const
491 {
492     POINT result = point;
493
494     HWND viewWindow;
495     if (FAILED(m_webView->viewWindow(&viewWindow)))
496         return point;
497
498     ::ScreenToClient(viewWindow, &result);
499
500     return result;
501 }
502
503 PlatformPageClient WebChromeClient::platformPageClient() const
504 {
505     HWND viewWindow;
506     if (FAILED(m_webView->viewWindow(&viewWindow)))
507         return 0;
508     return viewWindow;
509 }
510
511 void WebChromeClient::contentsSizeChanged(Frame*, const IntSize&) const
512 {
513     notImplemented();
514 }
515
516 void WebChromeClient::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags)
517 {
518     COMPtr<IWebUIDelegate> uiDelegate;
519     if (FAILED(m_webView->uiDelegate(&uiDelegate)))
520         return;
521
522     COMPtr<WebElementPropertyBag> element;
523     element.adoptRef(WebElementPropertyBag::createInstance(result));
524
525     uiDelegate->mouseDidMoveOverElement(m_webView, element.get(), modifierFlags);
526 }
527
528 bool WebChromeClient::shouldUnavailablePluginMessageBeButton(RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason) const
529 {
530     if (pluginUnavailabilityReason != RenderEmbeddedObject::PluginMissing)
531         return false;
532
533     COMPtr<IWebUIDelegate> uiDelegate;
534     if (FAILED(m_webView->uiDelegate(&uiDelegate)))
535         return false;
536     
537     // If the UI delegate implements IWebUIDelegatePrivate3, 
538     // which contains didPressMissingPluginButton, then the message should be a button.
539     COMPtr<IWebUIDelegatePrivate3> uiDelegatePrivate3(Query, uiDelegate);
540     return uiDelegatePrivate3;
541 }
542
543 void WebChromeClient::unavailablePluginButtonClicked(Element* element, RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason) const
544 {
545     ASSERT_UNUSED(pluginUnavailabilityReason, pluginUnavailabilityReason == RenderEmbeddedObject::PluginMissing);
546
547     COMPtr<IWebUIDelegate> uiDelegate;
548     if (FAILED(m_webView->uiDelegate(&uiDelegate)))
549         return;
550
551     COMPtr<IWebUIDelegatePrivate3> uiDelegatePrivate3(Query, uiDelegate);
552     if (!uiDelegatePrivate3)
553         return;
554
555     COMPtr<IDOMElement> e(AdoptCOM, DOMElement::createInstance(element));
556     uiDelegatePrivate3->didPressMissingPluginButton(e.get());
557 }
558
559 void WebChromeClient::setToolTip(const String& toolTip, TextDirection)
560 {
561     m_webView->setToolTip(toolTip);
562 }
563
564 void WebChromeClient::print(Frame* frame)
565 {
566     COMPtr<IWebUIDelegate> uiDelegate;
567     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate)))
568         uiDelegate->printFrame(m_webView, kit(frame));
569 }
570
571 void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseIdentifier, DatabaseDetails)
572 {
573     COMPtr<WebSecurityOrigin> origin(AdoptCOM, WebSecurityOrigin::createInstance(frame->document()->securityOrigin()));
574     COMPtr<IWebUIDelegate> uiDelegate;
575     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
576         COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate(Query, uiDelegate);
577         if (uiDelegatePrivate)
578             uiDelegatePrivate->exceededDatabaseQuota(m_webView, kit(frame), origin.get(), BString(databaseIdentifier));
579         else {
580             // FIXME: remove this workaround once shipping Safari has the necessary delegate implemented.
581             WCHAR path[MAX_PATH];
582             HMODULE safariHandle = GetModuleHandleW(L"Safari.exe");
583             if (!safariHandle)
584                 return;
585             if (!::GetModuleFileName(safariHandle, path, WTF_ARRAY_LENGTH(path)))
586                 return;
587             DWORD handle = 0;
588             DWORD versionSize = GetFileVersionInfoSize(path, &handle);
589             if (!versionSize)
590                 return;
591             Vector<char> data(versionSize);
592             if (!GetFileVersionInfo(path, 0, versionSize, data.data()))
593                 return;
594
595             LPCTSTR productVersion;
596             UINT productVersionLength;
597             if (!VerQueryValueW(data.data(), L"\\StringFileInfo\\040904b0\\ProductVersion", (void**)&productVersion, &productVersionLength))
598                 return;
599             if (wcsncmp(L"3.1", productVersion, productVersionLength) > 0) {
600                 const unsigned long long defaultQuota = 5 * 1024 * 1024; // 5 megabytes should hopefully be enough to test storage support.
601                 origin->setQuota(defaultQuota);
602             }
603         }
604     }
605 }
606
607 // FIXME: Move this include to the top of the file with the other includes.
608 #include "ApplicationCacheStorage.h"
609
610 void WebChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded)
611 {
612     // FIXME: Free some space.
613     notImplemented();
614 }
615
616 void WebChromeClient::reachedApplicationCacheOriginQuota(SecurityOrigin*, int64_t)
617 {
618     notImplemented();
619 }
620
621 void WebChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser)
622 {
623     RefPtr<FileChooser> fileChooser = prpFileChooser;
624
625     HWND viewWindow;
626     if (FAILED(m_webView->viewWindow(&viewWindow)))
627         return;
628
629     bool multiFile = fileChooser->settings().allowsMultipleFiles;
630     Vector<WCHAR> fileBuf(multiFile ? maxFilePathsListSize : MAX_PATH);
631
632     OPENFILENAME ofn;
633
634     memset(&ofn, 0, sizeof(ofn));
635
636     // Need to zero out the first char of fileBuf so GetOpenFileName doesn't think it's an initialization string
637     fileBuf[0] = '\0';
638
639     ofn.lStructSize = sizeof(ofn);
640     ofn.hwndOwner = viewWindow;
641     String allFiles = allFilesText();
642     allFiles.append(L"\0*.*\0\0", 6);
643
644     Vector<UChar> filterCharacters = allFiles.charactersWithNullTermination(); // Retain buffer long enough to make the GetOpenFileName call
645     ofn.lpstrFilter = filterCharacters.data();
646
647     ofn.lpstrFile = fileBuf.data();
648     ofn.nMaxFile = fileBuf.size();
649     String dialogTitle = uploadFileText();
650     Vector<UChar> dialogTitleCharacters = dialogTitle.charactersWithNullTermination(); // Retain buffer long enough to make the GetOpenFileName call
651     ofn.lpstrTitle = dialogTitleCharacters.data();
652     ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER;
653     if (multiFile)
654         ofn.Flags = ofn.Flags | OFN_ALLOWMULTISELECT;
655
656     if (GetOpenFileName(&ofn)) {
657         WCHAR* files = fileBuf.data();
658         Vector<String> fileList;
659         String file(files);
660         if (multiFile) {
661             while (!file.isEmpty()) {
662                 // When using the OFN_EXPLORER flag, the file list is null delimited.
663                 // When you create a String from a ptr to this list, it will use strlen to look for the null character.
664                 // Then we find the next file path string by using the length of the string we just created.
665                 WCHAR* nextFilePtr = files + file.length() + 1;
666                 String nextFile(nextFilePtr);
667                 // If multiple files are selected, there will be a directory name first, which we don't want to add to the vector.
668                 // We know a single file was selected if there is only one filename in the list.  
669                 // In that case, we don't want to skip adding the first (and only) name.
670                 if (files != fileBuf.data() || nextFile.isEmpty())
671                     fileList.append(file);
672                 files = nextFilePtr;
673                 file = nextFile;
674             }
675         } else
676             fileList.append(file);
677         ASSERT(fileList.size());
678         fileChooser->chooseFiles(fileList);
679     }
680     // FIXME: Show some sort of error if too many files are selected and the buffer is too small.  For now, this will fail silently.
681 }
682
683 void WebChromeClient::loadIconForFiles(const Vector<WTF::String>& filenames, WebCore::FileIconLoader* loader)
684 {
685     loader->notifyFinished(Icon::createIconForFiles(filenames));
686 }
687
688 void WebChromeClient::setCursor(const Cursor& cursor)
689 {
690     HCURSOR platformCursor = cursor.platformCursor()->nativeCursor();
691     if (!platformCursor)
692         return;
693
694     bool shouldSetCursor = true;
695     if (COMPtr<IWebUIDelegate> delegate = uiDelegate()) {
696         COMPtr<IWebUIDelegatePrivate> delegatePrivate(Query, delegate);
697         if (delegatePrivate) {
698             if (SUCCEEDED(delegatePrivate->webViewSetCursor(m_webView, platformCursor)))
699                 shouldSetCursor = false;
700         }
701     }
702
703     if (shouldSetCursor)
704         ::SetCursor(platformCursor);
705
706     setLastSetCursorToCurrentCursor();
707 }
708
709 void WebChromeClient::setCursorHiddenUntilMouseMoves(bool)
710 {
711     notImplemented();
712 }
713
714 void WebChromeClient::setLastSetCursorToCurrentCursor()
715 {
716     m_webView->setLastCursor(::GetCursor());
717 }
718
719 void WebChromeClient::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer)
720 {
721     m_webView->setRootChildLayer(graphicsLayer);
722 }
723
724 void WebChromeClient::attachViewOverlayGraphicsLayer(Frame*, GraphicsLayer*)
725 {
726     // FIXME: If we want view-relative page overlays in Legacy WebKit on Windows, this would be the place to hook them up.
727 }
728
729 void WebChromeClient::scheduleCompositingLayerFlush()
730 {
731     m_webView->flushPendingGraphicsLayerChangesSoon();
732 }
733
734 #if PLATFORM(WIN) && USE(AVFOUNDATION)
735 WebCore::GraphicsDeviceAdapter* WebChromeClient::graphicsDeviceAdapter() const
736 {
737     return m_webView->graphicsDeviceAdapter();
738 }
739 #endif
740
741 COMPtr<IWebUIDelegate> WebChromeClient::uiDelegate()
742 {
743     COMPtr<IWebUIDelegate> delegate;
744     m_webView->uiDelegate(&delegate);
745     return delegate;
746 }
747
748 #if ENABLE(VIDEO)
749
750 bool WebChromeClient::supportsVideoFullscreen()
751 {
752     return true;
753 }
754
755 void WebChromeClient::enterVideoFullscreenForVideoElement(HTMLVideoElement& videoElement)
756 {
757     m_webView->enterVideoFullscreenForVideoElement(videoElement);
758 }
759
760 void WebChromeClient::exitVideoFullscreenForVideoElement(HTMLVideoElement& videoElement)
761 {
762     m_webView->exitVideoFullscreenForVideoElement(videoElement);
763 }
764
765 #endif
766
767 bool WebChromeClient::selectItemWritingDirectionIsNatural()
768 {
769     return false;
770 }
771
772 bool WebChromeClient::selectItemAlignmentFollowsMenuWritingDirection()
773 {
774     return true;
775 }
776
777 bool WebChromeClient::hasOpenedPopup() const
778 {
779     notImplemented();
780     return false;
781 }
782
783 RefPtr<PopupMenu> WebChromeClient::createPopupMenu(PopupMenuClient* client) const
784 {
785     return adoptRef(new PopupMenuWin(client));
786 }
787
788 RefPtr<SearchPopupMenu> WebChromeClient::createSearchPopupMenu(PopupMenuClient* client) const
789 {
790     return adoptRef(new SearchPopupMenuWin(client));
791 }
792
793 #if ENABLE(FULLSCREEN_API)
794 bool WebChromeClient::supportsFullScreenForElement(const Element* element, bool requestingKeyboardAccess)
795 {
796     COMPtr<IWebUIDelegate> uiDelegate;
797     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
798         COMPtr<IWebUIDelegatePrivate4> uiDelegatePrivate4(Query, uiDelegate);
799         BOOL supports = FALSE;
800         COMPtr<IDOMElement> domElement(AdoptCOM, DOMElement::createInstance(const_cast<Element*>(element)));
801
802         if (uiDelegatePrivate4 && SUCCEEDED(uiDelegatePrivate4->supportsFullScreenForElement(domElement.get(), requestingKeyboardAccess, &supports)))
803             return supports;
804     }
805
806     return m_webView->supportsFullScreenForElement(element, requestingKeyboardAccess);
807 }
808
809 void WebChromeClient::enterFullScreenForElement(Element* element)
810 {
811     COMPtr<IWebUIDelegate> uiDelegate;
812     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
813         COMPtr<IWebUIDelegatePrivate4> uiDelegatePrivate4(Query, uiDelegate);
814         COMPtr<IDOMElement> domElement(AdoptCOM, DOMElement::createInstance(element));
815         if (uiDelegatePrivate4 && SUCCEEDED(uiDelegatePrivate4->enterFullScreenForElement(domElement.get())))
816             return;
817     } 
818
819     m_webView->setFullScreenElement(element);
820     m_webView->fullScreenController()->enterFullScreen();
821 }
822
823 void WebChromeClient::exitFullScreenForElement(Element* element)
824 {
825     COMPtr<IWebUIDelegate> uiDelegate;
826     if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
827         COMPtr<IWebUIDelegatePrivate4> uiDelegatePrivate4(Query, uiDelegate);
828         COMPtr<IDOMElement> domElement(AdoptCOM, DOMElement::createInstance(element));
829         if (uiDelegatePrivate4 && SUCCEEDED(uiDelegatePrivate4->exitFullScreenForElement(domElement.get())))
830             return;
831     }
832
833     ASSERT(element == m_webView->fullScreenElement());
834     m_webView->fullScreenController()->exitFullScreen();
835 }
836 #endif
837
838 void WebChromeClient::AXStartFrameLoad()
839 {
840     COMPtr<IAccessibilityDelegate> delegate;
841     m_webView->accessibilityDelegate(&delegate);
842     if (delegate)
843         delegate->fireFrameLoadStartedEvents();
844 }
845
846 void WebChromeClient::AXFinishFrameLoad()
847 {
848     COMPtr<IAccessibilityDelegate> delegate;
849     m_webView->accessibilityDelegate(&delegate);
850     if (delegate)
851         delegate->fireFrameLoadFinishedEvents();
852 }