Home | History | Annotate | Download | only in WebCoreSupport
      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 
     65 WebChromeClient::WebChromeClient(WebView* webView)
     66     : m_webView(webView)
     67 #if ENABLE(NOTIFICATIONS)
     68     , m_notificationsDelegate(new WebDesktopNotificationsDelegate(webView))
     69 #endif
     70 {
     71 }
     72 
     73 void WebChromeClient::chromeDestroyed()
     74 {
     75     delete this;
     76 }
     77 
     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 
     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 
    104 FloatRect WebChromeClient::pageRect()
    105 {
    106     RECT rect;
    107     m_webView->frameRect(&rect);
    108     return rect;
    109 }
    110 
    111 float WebChromeClient::scaleFactor()
    112 {
    113     // Windows doesn't support UI scaling.
    114     return 1.0;
    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::focusedNodeChanged(Node*)
    163 {
    164 }
    165 
    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 
    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 
    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 
    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 
    238 void WebChromeClient::runModal()
    239 {
    240     if (COMPtr<IWebUIDelegate> delegate = uiDelegate())
    241         delegate->runModal(m_webView);
    242 }
    243 
    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 
    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 
    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 
    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 
    284 void WebChromeClient::setScrollbarsVisible(bool b)
    285 {
    286     WebFrame* webFrame = m_webView->topLevelFrame();
    287     if (webFrame)
    288         webFrame->setAllowsScrolling(b);
    289 }
    290 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    439 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 
    449 IntRect WebChromeClient::windowResizerRect() const
    450 {
    451     return IntRect();
    452 }
    453 
    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 
    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 
    467 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 
    483 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 
    496 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 
    504 void WebChromeClient::contentsSizeChanged(Frame*, const IntSize&) const
    505 {
    506     notImplemented();
    507 }
    508 
    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 
    521 void WebChromeClient::setToolTip(const String& toolTip, TextDirection)
    522 {
    523     m_webView->setToolTip(toolTip);
    524 }
    525 
    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)
    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"
    572 void WebChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded)
    573 {
    574     // FIXME: Free some space.
    575     notImplemented();
    576 }
    577 #endif
    578 
    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 
    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 
    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 
    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 
    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 
    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)
    778 void WebChromeClient::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer)
    779 {
    780     m_webView->setRootChildLayer(graphicsLayer ? graphicsLayer->platformLayer() : 0);
    781 }
    782 
    783 void WebChromeClient::scheduleCompositingLayerSync()
    784 {
    785     m_webView->setRootLayerNeedsDisplay();
    786 }
    787 
    788 #endif
    789 
    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 
    799 bool WebChromeClient::supportsFullscreenForNode(const Node* node)
    800 {
    801     return node->hasTagName(HTMLNames::videoTag);
    802 }
    803 
    804 void WebChromeClient::enterFullscreenForNode(Node* node)
    805 {
    806     m_webView->enterFullscreenForNode(node);
    807 }
    808 
    809 void WebChromeClient::exitFullscreenForNode(Node*)
    810 {
    811     m_webView->exitFullscreen();
    812 }
    813 
    814 #endif
    815 
    816