WebChromeClient.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. /*
  2. * Copyright (C) 2006, 2007, 2008 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 COMPUTER, 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 COMPUTER, 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. #include "config.h"
  27. #include "WebChromeClient.h"
  28. #include "COMPropertyBag.h"
  29. #include "COMVariantSetter.h"
  30. #include "DOMCoreClasses.h"
  31. #include "WebElementPropertyBag.h"
  32. #include "WebFrame.h"
  33. #include "WebHistory.h"
  34. #include "WebMutableURLRequest.h"
  35. #include "WebDesktopNotificationsDelegate.h"
  36. #include "WebSecurityOrigin.h"
  37. #include "WebView.h"
  38. #include <WebCore/BString.h>
  39. #include <WebCore/Console.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/HTMLNames.h>
  50. #include <WebCore/Icon.h>
  51. #include <WebCore/LocalWindowsContext.h>
  52. #include <WebCore/LocalizedStrings.h>
  53. #include <WebCore/NavigationAction.h>
  54. #include <WebCore/NotImplemented.h>
  55. #include <WebCore/Page.h>
  56. #include <WebCore/SecurityOrigin.h>
  57. #include <WebCore/PopupMenuWin.h>
  58. #include <WebCore/SearchPopupMenuWin.h>
  59. #include <WebCore/WindowFeatures.h>
  60. #include <wchar.h>
  61. #if USE(ACCELERATED_COMPOSITING)
  62. #include <WebCore/GraphicsLayer.h>
  63. #endif
  64. using namespace WebCore;
  65. // When you call GetOpenFileName, if the size of the buffer is too small,
  66. // MSDN says that the first two bytes of the buffer contain the required size for the file selection, in bytes or characters
  67. // So we can assume the required size can't be more than the maximum value for a short.
  68. static const size_t maxFilePathsListSize = USHRT_MAX;
  69. WebChromeClient::WebChromeClient(WebView* webView)
  70. : m_webView(webView)
  71. #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
  72. , m_notificationsDelegate(new WebDesktopNotificationsDelegate(webView))
  73. #endif
  74. {
  75. }
  76. void WebChromeClient::chromeDestroyed()
  77. {
  78. delete this;
  79. }
  80. void WebChromeClient::setWindowRect(const FloatRect& r)
  81. {
  82. IWebUIDelegate* uiDelegate = 0;
  83. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  84. RECT rect = IntRect(r);
  85. uiDelegate->setFrame(m_webView, &rect);
  86. uiDelegate->Release();
  87. }
  88. }
  89. FloatRect WebChromeClient::windowRect()
  90. {
  91. IWebUIDelegate* uiDelegate = 0;
  92. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  93. RECT rect;
  94. HRESULT retval = uiDelegate->webViewFrame(m_webView, &rect);
  95. uiDelegate->Release();
  96. if (SUCCEEDED(retval))
  97. return rect;
  98. }
  99. return FloatRect();
  100. }
  101. FloatRect WebChromeClient::pageRect()
  102. {
  103. RECT rect;
  104. m_webView->frameRect(&rect);
  105. return rect;
  106. }
  107. void WebChromeClient::focus()
  108. {
  109. IWebUIDelegate* uiDelegate = 0;
  110. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  111. uiDelegate->webViewFocus(m_webView);
  112. uiDelegate->Release();
  113. }
  114. // Normally this would happen on a timer, but JS might need to know this earlier, so we'll update here.
  115. m_webView->updateActiveState();
  116. }
  117. void WebChromeClient::unfocus()
  118. {
  119. IWebUIDelegate* uiDelegate = 0;
  120. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  121. uiDelegate->webViewUnfocus(m_webView);
  122. uiDelegate->Release();
  123. }
  124. // Normally this would happen on a timer, but JS might need to know this earlier, so we'll update here.
  125. m_webView->updateActiveState();
  126. }
  127. bool WebChromeClient::canTakeFocus(FocusDirection direction)
  128. {
  129. IWebUIDelegate* uiDelegate = 0;
  130. BOOL bForward = (direction == FocusDirectionForward) ? TRUE : FALSE;
  131. BOOL result = FALSE;
  132. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  133. uiDelegate->canTakeFocus(m_webView, bForward, &result);
  134. uiDelegate->Release();
  135. }
  136. return !!result;
  137. }
  138. void WebChromeClient::takeFocus(FocusDirection direction)
  139. {
  140. IWebUIDelegate* uiDelegate = 0;
  141. BOOL bForward = (direction == FocusDirectionForward) ? TRUE : FALSE;
  142. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  143. uiDelegate->takeFocus(m_webView, bForward);
  144. uiDelegate->Release();
  145. }
  146. }
  147. void WebChromeClient::focusedNodeChanged(Node*)
  148. {
  149. }
  150. void WebChromeClient::focusedFrameChanged(Frame*)
  151. {
  152. }
  153. static COMPtr<IPropertyBag> createWindowFeaturesPropertyBag(const WindowFeatures& features)
  154. {
  155. HashMap<String, COMVariant> map;
  156. if (features.xSet)
  157. map.set(WebWindowFeaturesXKey, features.x);
  158. if (features.ySet)
  159. map.set(WebWindowFeaturesYKey, features.y);
  160. if (features.widthSet)
  161. map.set(WebWindowFeaturesWidthKey, features.width);
  162. if (features.heightSet)
  163. map.set(WebWindowFeaturesHeightKey, features.height);
  164. map.set(WebWindowFeaturesMenuBarVisibleKey, features.menuBarVisible);
  165. map.set(WebWindowFeaturesStatusBarVisibleKey, features.statusBarVisible);
  166. map.set(WebWindowFeaturesToolBarVisibleKey, features.toolBarVisible);
  167. map.set(WebWindowFeaturesScrollbarsVisibleKey, features.scrollbarsVisible);
  168. map.set(WebWindowFeaturesResizableKey, features.resizable);
  169. map.set(WebWindowFeaturesFullscreenKey, features.fullscreen);
  170. map.set(WebWindowFeaturesDialogKey, features.dialog);
  171. return COMPtr<IPropertyBag>(AdoptCOM, COMPropertyBag<COMVariant>::adopt(map));
  172. }
  173. Page* WebChromeClient::createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures& features, const NavigationAction&)
  174. {
  175. COMPtr<IWebUIDelegate> delegate = uiDelegate();
  176. if (!delegate)
  177. return 0;
  178. // Just create a blank request because createWindow() is only required to create window but not to load URL.
  179. COMPtr<IWebMutableURLRequest> request(AdoptCOM, WebMutableURLRequest::createInstance());
  180. COMPtr<IWebUIDelegatePrivate2> delegatePrivate(Query, delegate);
  181. if (delegatePrivate) {
  182. COMPtr<IWebView> newWebView;
  183. HRESULT hr = delegatePrivate->createWebViewWithRequest(m_webView, request.get(), createWindowFeaturesPropertyBag(features).get(), &newWebView);
  184. if (SUCCEEDED(hr) && newWebView)
  185. return core(newWebView.get());
  186. // If the delegate doesn't implement the IWebUIDelegatePrivate2 version of the call, fall back
  187. // to the old versions (even if they support the IWebUIDelegatePrivate2 interface).
  188. if (hr != E_NOTIMPL)
  189. return 0;
  190. }
  191. COMPtr<IWebView> newWebView;
  192. if (features.dialog) {
  193. if (FAILED(delegate->createModalDialog(m_webView, request.get(), &newWebView)))
  194. return 0;
  195. } else if (FAILED(delegate->createWebViewWithRequest(m_webView, request.get(), &newWebView)))
  196. return 0;
  197. return newWebView ? core(newWebView.get()) : 0;
  198. }
  199. void WebChromeClient::show()
  200. {
  201. IWebUIDelegate* uiDelegate = 0;
  202. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  203. uiDelegate->webViewShow(m_webView);
  204. uiDelegate->Release();
  205. }
  206. }
  207. bool WebChromeClient::canRunModal()
  208. {
  209. BOOL result = FALSE;
  210. if (COMPtr<IWebUIDelegate> delegate = uiDelegate())
  211. delegate->canRunModal(m_webView, &result);
  212. return result;
  213. }
  214. void WebChromeClient::runModal()
  215. {
  216. if (COMPtr<IWebUIDelegate> delegate = uiDelegate())
  217. delegate->runModal(m_webView);
  218. }
  219. void WebChromeClient::setToolbarsVisible(bool visible)
  220. {
  221. IWebUIDelegate* uiDelegate = 0;
  222. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  223. uiDelegate->setToolbarsVisible(m_webView, visible);
  224. uiDelegate->Release();
  225. }
  226. }
  227. bool WebChromeClient::toolbarsVisible()
  228. {
  229. BOOL result = false;
  230. IWebUIDelegate* uiDelegate = 0;
  231. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  232. uiDelegate->webViewAreToolbarsVisible(m_webView, &result);
  233. uiDelegate->Release();
  234. }
  235. return result != false;
  236. }
  237. void WebChromeClient::setStatusbarVisible(bool visible)
  238. {
  239. IWebUIDelegate* uiDelegate = 0;
  240. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  241. uiDelegate->setStatusBarVisible(m_webView, visible);
  242. uiDelegate->Release();
  243. }
  244. }
  245. bool WebChromeClient::statusbarVisible()
  246. {
  247. BOOL result = false;
  248. IWebUIDelegate* uiDelegate = 0;
  249. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  250. uiDelegate->webViewIsStatusBarVisible(m_webView, &result);
  251. uiDelegate->Release();
  252. }
  253. return result != false;
  254. }
  255. void WebChromeClient::setScrollbarsVisible(bool b)
  256. {
  257. WebFrame* webFrame = m_webView->topLevelFrame();
  258. if (webFrame)
  259. webFrame->setAllowsScrolling(b);
  260. }
  261. bool WebChromeClient::scrollbarsVisible()
  262. {
  263. WebFrame* webFrame = m_webView->topLevelFrame();
  264. BOOL b = false;
  265. if (webFrame)
  266. webFrame->allowsScrolling(&b);
  267. return !!b;
  268. }
  269. void WebChromeClient::setMenubarVisible(bool visible)
  270. {
  271. COMPtr<IWebUIDelegate> delegate = uiDelegate();
  272. if (!delegate)
  273. return;
  274. delegate->setMenuBarVisible(m_webView, visible);
  275. }
  276. bool WebChromeClient::menubarVisible()
  277. {
  278. COMPtr<IWebUIDelegate> delegate = uiDelegate();
  279. if (!delegate)
  280. return true;
  281. BOOL result = true;
  282. delegate->isMenuBarVisible(m_webView, &result);
  283. return result;
  284. }
  285. void WebChromeClient::setResizable(bool resizable)
  286. {
  287. IWebUIDelegate* uiDelegate = 0;
  288. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  289. uiDelegate->setResizable(m_webView, resizable);
  290. uiDelegate->Release();
  291. }
  292. }
  293. void WebChromeClient::addMessageToConsole(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, unsigned columnNumber, const String& url)
  294. {
  295. UNUSED_PARAM(columnNumber);
  296. COMPtr<IWebUIDelegate> uiDelegate;
  297. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  298. COMPtr<IWebUIDelegatePrivate> uiPrivate;
  299. if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate)))
  300. uiPrivate->webViewAddMessageToConsole(m_webView, BString(message), lineNumber, BString(url), true);
  301. }
  302. }
  303. bool WebChromeClient::canRunBeforeUnloadConfirmPanel()
  304. {
  305. IWebUIDelegate* ui;
  306. if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) {
  307. ui->Release();
  308. return true;
  309. }
  310. return false;
  311. }
  312. bool WebChromeClient::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
  313. {
  314. BOOL result = TRUE;
  315. IWebUIDelegate* ui;
  316. if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) {
  317. WebFrame* webFrame = kit(frame);
  318. ui->runBeforeUnloadConfirmPanelWithMessage(m_webView, BString(message), webFrame, &result);
  319. ui->Release();
  320. }
  321. return !!result;
  322. }
  323. void WebChromeClient::closeWindowSoon()
  324. {
  325. // We need to remove the parent WebView from WebViewSets here, before it actually
  326. // closes, to make sure that JavaScript code that executes before it closes
  327. // can't find it. Otherwise, window.open will select a closed WebView instead of
  328. // opening a new one <rdar://problem/3572585>.
  329. // We also need to stop the load to prevent further parsing or JavaScript execution
  330. // after the window has torn down <rdar://problem/4161660>.
  331. // FIXME: This code assumes that the UI delegate will respond to a webViewClose
  332. // message by actually closing the WebView. Safari guarantees this behavior, but other apps might not.
  333. // This approach is an inherent limitation of not making a close execute immediately
  334. // after a call to window.close.
  335. m_webView->setGroupName(0);
  336. m_webView->stopLoading(0);
  337. m_webView->closeWindowSoon();
  338. }
  339. void WebChromeClient::runJavaScriptAlert(Frame*, const String& message)
  340. {
  341. COMPtr<IWebUIDelegate> ui;
  342. if (SUCCEEDED(m_webView->uiDelegate(&ui)))
  343. ui->runJavaScriptAlertPanelWithMessage(m_webView, BString(message));
  344. }
  345. bool WebChromeClient::runJavaScriptConfirm(Frame*, const String& message)
  346. {
  347. BOOL result = FALSE;
  348. COMPtr<IWebUIDelegate> ui;
  349. if (SUCCEEDED(m_webView->uiDelegate(&ui)))
  350. ui->runJavaScriptConfirmPanelWithMessage(m_webView, BString(message), &result);
  351. return !!result;
  352. }
  353. bool WebChromeClient::runJavaScriptPrompt(Frame*, const String& message, const String& defaultValue, String& result)
  354. {
  355. COMPtr<IWebUIDelegate> ui;
  356. if (FAILED(m_webView->uiDelegate(&ui)))
  357. return false;
  358. TimerBase::fireTimersInNestedEventLoop();
  359. BString resultBSTR;
  360. if (FAILED(ui->runJavaScriptTextInputPanelWithPrompt(m_webView, BString(message), BString(defaultValue), &resultBSTR)))
  361. return false;
  362. if (!resultBSTR)
  363. return false;
  364. result = String(resultBSTR, SysStringLen(resultBSTR));
  365. return true;
  366. }
  367. void WebChromeClient::setStatusbarText(const String& statusText)
  368. {
  369. COMPtr<IWebUIDelegate> uiDelegate;
  370. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  371. uiDelegate->setStatusText(m_webView, BString(statusText));
  372. }
  373. }
  374. bool WebChromeClient::shouldInterruptJavaScript()
  375. {
  376. COMPtr<IWebUIDelegate> uiDelegate;
  377. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  378. COMPtr<IWebUIDelegatePrivate> uiPrivate;
  379. if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) {
  380. BOOL result;
  381. if (SUCCEEDED(uiPrivate->webViewShouldInterruptJavaScript(m_webView, &result)))
  382. return !!result;
  383. }
  384. }
  385. return false;
  386. }
  387. KeyboardUIMode WebChromeClient::keyboardUIMode()
  388. {
  389. BOOL enabled = FALSE;
  390. IWebPreferences* preferences;
  391. if (SUCCEEDED(m_webView->preferences(&preferences)))
  392. preferences->tabsToLinks(&enabled);
  393. return enabled ? KeyboardAccessTabsToLinks : KeyboardAccessDefault;
  394. }
  395. IntRect WebChromeClient::windowResizerRect() const
  396. {
  397. return IntRect();
  398. }
  399. void WebChromeClient::invalidateRootView(const IntRect& windowRect, bool immediate)
  400. {
  401. ASSERT(core(m_webView->topLevelFrame()));
  402. m_webView->repaint(windowRect, false /*contentChanged*/, immediate, false /*repaintContentOnly*/);
  403. }
  404. void WebChromeClient::invalidateContentsAndRootView(const IntRect& windowRect, bool immediate)
  405. {
  406. ASSERT(core(m_webView->topLevelFrame()));
  407. m_webView->repaint(windowRect, true /*contentChanged*/, immediate /*immediate*/, false /*repaintContentOnly*/);
  408. }
  409. void WebChromeClient::invalidateContentsForSlowScroll(const IntRect& windowRect, bool immediate)
  410. {
  411. ASSERT(core(m_webView->topLevelFrame()));
  412. m_webView->repaint(windowRect, true /*contentChanged*/, immediate, true /*repaintContentOnly*/);
  413. }
  414. void WebChromeClient::scroll(const IntSize& delta, const IntRect& scrollViewRect, const IntRect& clipRect)
  415. {
  416. ASSERT(core(m_webView->topLevelFrame()));
  417. m_webView->scrollBackingStore(core(m_webView->topLevelFrame())->view(), delta.width(), delta.height(), scrollViewRect, clipRect);
  418. }
  419. IntRect WebChromeClient::rootViewToScreen(const IntRect& rect) const
  420. {
  421. HWND viewWindow;
  422. if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))))
  423. return rect;
  424. // Find the top left corner of the Widget's containing window in screen coords,
  425. // and adjust the result rect's position by this amount.
  426. POINT topLeft = {0, 0};
  427. IntRect result = rect;
  428. ::ClientToScreen(viewWindow, &topLeft);
  429. result.move(topLeft.x, topLeft.y);
  430. return result;
  431. }
  432. IntPoint WebChromeClient::screenToRootView(const IntPoint& point) const
  433. {
  434. POINT result = point;
  435. HWND viewWindow;
  436. if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))))
  437. return point;
  438. ::ScreenToClient(viewWindow, &result);
  439. return result;
  440. }
  441. PlatformPageClient WebChromeClient::platformPageClient() const
  442. {
  443. HWND viewWindow;
  444. if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))))
  445. return 0;
  446. return viewWindow;
  447. }
  448. void WebChromeClient::contentsSizeChanged(Frame*, const IntSize&) const
  449. {
  450. notImplemented();
  451. }
  452. void WebChromeClient::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags)
  453. {
  454. COMPtr<IWebUIDelegate> uiDelegate;
  455. if (FAILED(m_webView->uiDelegate(&uiDelegate)))
  456. return;
  457. COMPtr<WebElementPropertyBag> element;
  458. element.adoptRef(WebElementPropertyBag::createInstance(result));
  459. uiDelegate->mouseDidMoveOverElement(m_webView, element.get(), modifierFlags);
  460. }
  461. bool WebChromeClient::shouldUnavailablePluginMessageBeButton(RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason) const
  462. {
  463. if (pluginUnavailabilityReason != RenderEmbeddedObject::PluginMissing)
  464. return false;
  465. COMPtr<IWebUIDelegate> uiDelegate;
  466. if (FAILED(m_webView->uiDelegate(&uiDelegate)))
  467. return false;
  468. // If the UI delegate implements IWebUIDelegatePrivate3,
  469. // which contains didPressMissingPluginButton, then the message should be a button.
  470. COMPtr<IWebUIDelegatePrivate3> uiDelegatePrivate3(Query, uiDelegate);
  471. return uiDelegatePrivate3;
  472. }
  473. void WebChromeClient::unavailablePluginButtonClicked(Element* element, RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason) const
  474. {
  475. ASSERT_UNUSED(pluginUnavailabilityReason, pluginUnavailabilityReason == RenderEmbeddedObject::PluginMissing);
  476. COMPtr<IWebUIDelegate> uiDelegate;
  477. if (FAILED(m_webView->uiDelegate(&uiDelegate)))
  478. return;
  479. COMPtr<IWebUIDelegatePrivate3> uiDelegatePrivate3(Query, uiDelegate);
  480. if (!uiDelegatePrivate3)
  481. return;
  482. COMPtr<IDOMElement> e(AdoptCOM, DOMElement::createInstance(element));
  483. uiDelegatePrivate3->didPressMissingPluginButton(e.get());
  484. }
  485. void WebChromeClient::setToolTip(const String& toolTip, TextDirection)
  486. {
  487. m_webView->setToolTip(toolTip);
  488. }
  489. void WebChromeClient::print(Frame* frame)
  490. {
  491. COMPtr<IWebUIDelegate> uiDelegate;
  492. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate)))
  493. uiDelegate->printFrame(m_webView, kit(frame));
  494. }
  495. #if ENABLE(SQL_DATABASE)
  496. void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseIdentifier, DatabaseDetails)
  497. {
  498. COMPtr<WebSecurityOrigin> origin(AdoptCOM, WebSecurityOrigin::createInstance(frame->document()->securityOrigin()));
  499. COMPtr<IWebUIDelegate> uiDelegate;
  500. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  501. COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate(Query, uiDelegate);
  502. if (uiDelegatePrivate)
  503. uiDelegatePrivate->exceededDatabaseQuota(m_webView, kit(frame), origin.get(), BString(databaseIdentifier));
  504. else {
  505. // FIXME: remove this workaround once shipping Safari has the necessary delegate implemented.
  506. WCHAR path[MAX_PATH];
  507. HMODULE safariHandle = GetModuleHandleW(L"Safari.exe");
  508. if (!safariHandle)
  509. return;
  510. GetModuleFileName(safariHandle, path, WTF_ARRAY_LENGTH(path));
  511. DWORD handle;
  512. DWORD versionSize = GetFileVersionInfoSize(path, &handle);
  513. if (!versionSize)
  514. return;
  515. Vector<char> data(versionSize);
  516. if (!GetFileVersionInfo(path, 0, versionSize, data.data()))
  517. return;
  518. LPCTSTR productVersion;
  519. UINT productVersionLength;
  520. if (!VerQueryValueW(data.data(), L"\\StringFileInfo\\040904b0\\ProductVersion", (void**)&productVersion, &productVersionLength))
  521. return;
  522. if (wcsncmp(L"3.1", productVersion, productVersionLength) > 0) {
  523. const unsigned long long defaultQuota = 5 * 1024 * 1024; // 5 megabytes should hopefully be enough to test storage support.
  524. origin->setQuota(defaultQuota);
  525. }
  526. }
  527. }
  528. }
  529. #endif
  530. // FIXME: Move this include to the top of the file with the other includes.
  531. #include "ApplicationCacheStorage.h"
  532. void WebChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded)
  533. {
  534. // FIXME: Free some space.
  535. notImplemented();
  536. }
  537. void WebChromeClient::reachedApplicationCacheOriginQuota(SecurityOrigin*, int64_t)
  538. {
  539. notImplemented();
  540. }
  541. void WebChromeClient::populateVisitedLinks()
  542. {
  543. COMPtr<IWebHistoryDelegate> historyDelegate;
  544. m_webView->historyDelegate(&historyDelegate);
  545. if (historyDelegate) {
  546. historyDelegate->populateVisitedLinksForWebView(m_webView);
  547. return;
  548. }
  549. WebHistory* history = WebHistory::sharedHistory();
  550. if (!history)
  551. return;
  552. history->addVisitedLinksToPageGroup(m_webView->page()->group());
  553. }
  554. void WebChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser)
  555. {
  556. RefPtr<FileChooser> fileChooser = prpFileChooser;
  557. HWND viewWindow;
  558. if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))))
  559. return;
  560. bool multiFile = fileChooser->settings().allowsMultipleFiles;
  561. Vector<WCHAR> fileBuf(multiFile ? maxFilePathsListSize : MAX_PATH);
  562. OPENFILENAME ofn;
  563. memset(&ofn, 0, sizeof(ofn));
  564. // Need to zero out the first char of fileBuf so GetOpenFileName doesn't think it's an initialization string
  565. fileBuf[0] = '\0';
  566. ofn.lStructSize = sizeof(ofn);
  567. ofn.hwndOwner = viewWindow;
  568. String allFiles = allFilesText();
  569. allFiles.append(L"\0*.*\0\0", 6);
  570. ofn.lpstrFilter = allFiles.charactersWithNullTermination();
  571. ofn.lpstrFile = fileBuf.data();
  572. ofn.nMaxFile = fileBuf.size();
  573. String dialogTitle = uploadFileText();
  574. ofn.lpstrTitle = dialogTitle.charactersWithNullTermination();
  575. ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER;
  576. if (multiFile)
  577. ofn.Flags = ofn.Flags | OFN_ALLOWMULTISELECT;
  578. if (GetOpenFileName(&ofn)) {
  579. WCHAR* files = fileBuf.data();
  580. Vector<String> fileList;
  581. String file(files);
  582. if (multiFile) {
  583. while (!file.isEmpty()) {
  584. // When using the OFN_EXPLORER flag, the file list is null delimited.
  585. // When you create a String from a ptr to this list, it will use strlen to look for the null character.
  586. // Then we find the next file path string by using the length of the string we just created.
  587. WCHAR* nextFilePtr = files + file.length() + 1;
  588. String nextFile(nextFilePtr);
  589. // If multiple files are selected, there will be a directory name first, which we don't want to add to the vector.
  590. // We know a single file was selected if there is only one filename in the list.
  591. // In that case, we don't want to skip adding the first (and only) name.
  592. if (files != fileBuf.data() || nextFile.isEmpty())
  593. fileList.append(file);
  594. files = nextFilePtr;
  595. file = nextFile;
  596. }
  597. } else
  598. fileList.append(file);
  599. ASSERT(fileList.size());
  600. fileChooser->chooseFiles(fileList);
  601. }
  602. // FIXME: Show some sort of error if too many files are selected and the buffer is too small. For now, this will fail silently.
  603. }
  604. void WebChromeClient::loadIconForFiles(const Vector<WTF::String>& filenames, WebCore::FileIconLoader* loader)
  605. {
  606. loader->notifyFinished(Icon::createIconForFiles(filenames));
  607. }
  608. void WebChromeClient::setCursor(const Cursor& cursor)
  609. {
  610. HCURSOR platformCursor = cursor.platformCursor()->nativeCursor();
  611. if (!platformCursor)
  612. return;
  613. bool shouldSetCursor = true;
  614. if (COMPtr<IWebUIDelegate> delegate = uiDelegate()) {
  615. COMPtr<IWebUIDelegatePrivate> delegatePrivate(Query, delegate);
  616. if (delegatePrivate) {
  617. if (SUCCEEDED(delegatePrivate->webViewSetCursor(m_webView, reinterpret_cast<OLE_HANDLE>(platformCursor))))
  618. shouldSetCursor = false;
  619. }
  620. }
  621. if (shouldSetCursor)
  622. ::SetCursor(platformCursor);
  623. setLastSetCursorToCurrentCursor();
  624. }
  625. void WebChromeClient::setCursorHiddenUntilMouseMoves(bool)
  626. {
  627. notImplemented();
  628. }
  629. void WebChromeClient::setLastSetCursorToCurrentCursor()
  630. {
  631. m_webView->setLastCursor(::GetCursor());
  632. }
  633. #if USE(ACCELERATED_COMPOSITING)
  634. void WebChromeClient::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer)
  635. {
  636. m_webView->setRootChildLayer(graphicsLayer);
  637. }
  638. void WebChromeClient::scheduleCompositingLayerFlush()
  639. {
  640. m_webView->flushPendingGraphicsLayerChangesSoon();
  641. }
  642. #endif
  643. #if PLATFORM(WIN) && USE(AVFOUNDATION)
  644. WebCore::GraphicsDeviceAdapter* WebChromeClient::graphicsDeviceAdapter() const
  645. {
  646. return m_webView->graphicsDeviceAdapter();
  647. }
  648. #endif
  649. COMPtr<IWebUIDelegate> WebChromeClient::uiDelegate()
  650. {
  651. COMPtr<IWebUIDelegate> delegate;
  652. m_webView->uiDelegate(&delegate);
  653. return delegate;
  654. }
  655. #if ENABLE(VIDEO)
  656. bool WebChromeClient::supportsFullscreenForNode(const Node* node)
  657. {
  658. return node->hasTagName(HTMLNames::videoTag);
  659. }
  660. void WebChromeClient::enterFullscreenForNode(Node* node)
  661. {
  662. m_webView->enterFullscreenForNode(node);
  663. }
  664. void WebChromeClient::exitFullscreenForNode(Node*)
  665. {
  666. m_webView->exitFullscreen();
  667. }
  668. #endif
  669. bool WebChromeClient::selectItemWritingDirectionIsNatural()
  670. {
  671. return true;
  672. }
  673. bool WebChromeClient::selectItemAlignmentFollowsMenuWritingDirection()
  674. {
  675. return false;
  676. }
  677. bool WebChromeClient::hasOpenedPopup() const
  678. {
  679. notImplemented();
  680. return false;
  681. }
  682. PassRefPtr<PopupMenu> WebChromeClient::createPopupMenu(PopupMenuClient* client) const
  683. {
  684. return adoptRef(new PopupMenuWin(client));
  685. }
  686. PassRefPtr<SearchPopupMenu> WebChromeClient::createSearchPopupMenu(PopupMenuClient* client) const
  687. {
  688. return adoptRef(new SearchPopupMenuWin(client));
  689. }
  690. #if ENABLE(FULLSCREEN_API)
  691. bool WebChromeClient::supportsFullScreenForElement(const Element* element, bool requestingKeyboardAccess)
  692. {
  693. COMPtr<IWebUIDelegate> uiDelegate;
  694. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  695. COMPtr<IWebUIDelegatePrivate4> uiDelegatePrivate4(Query, uiDelegate);
  696. BOOL supports = FALSE;
  697. COMPtr<IDOMElement> domElement(AdoptCOM, DOMElement::createInstance(const_cast<Element*>(element)));
  698. if (uiDelegatePrivate4 && SUCCEEDED(uiDelegatePrivate4->supportsFullScreenForElement(domElement.get(), requestingKeyboardAccess, &supports)))
  699. return supports;
  700. }
  701. return m_webView->supportsFullScreenForElement(element, requestingKeyboardAccess);
  702. }
  703. void WebChromeClient::enterFullScreenForElement(Element* element)
  704. {
  705. COMPtr<IWebUIDelegate> uiDelegate;
  706. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  707. COMPtr<IWebUIDelegatePrivate4> uiDelegatePrivate4(Query, uiDelegate);
  708. COMPtr<IDOMElement> domElement(AdoptCOM, DOMElement::createInstance(element));
  709. if (uiDelegatePrivate4 && SUCCEEDED(uiDelegatePrivate4->enterFullScreenForElement(domElement.get())))
  710. return;
  711. }
  712. m_webView->setFullScreenElement(element);
  713. m_webView->fullScreenController()->enterFullScreen();
  714. }
  715. void WebChromeClient::exitFullScreenForElement(Element* element)
  716. {
  717. COMPtr<IWebUIDelegate> uiDelegate;
  718. if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) {
  719. COMPtr<IWebUIDelegatePrivate4> uiDelegatePrivate4(Query, uiDelegate);
  720. COMPtr<IDOMElement> domElement(AdoptCOM, DOMElement::createInstance(element));
  721. if (uiDelegatePrivate4 && SUCCEEDED(uiDelegatePrivate4->exitFullScreenForElement(domElement.get())))
  722. return;
  723. }
  724. ASSERT(element == m_webView->fullScreenElement());
  725. m_webView->fullScreenController()->exitFullScreen();
  726. }
  727. void WebChromeClient::AXStartFrameLoad()
  728. {
  729. COMPtr<IAccessibilityDelegate> delegate;
  730. m_webView->accessibilityDelegate(&delegate);
  731. if (delegate)
  732. delegate->fireFrameLoadStartedEvents();
  733. }
  734. void WebChromeClient::AXFinishFrameLoad()
  735. {
  736. COMPtr<IAccessibilityDelegate> delegate;
  737. m_webView->accessibilityDelegate(&delegate);
  738. if (delegate)
  739. delegate->fireFrameLoadFinishedEvents();
  740. }
  741. #endif