1 /* 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 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 "WebView.h" 28 29 #include "CFDictionaryPropertyBag.h" 30 #include "DOMCoreClasses.h" 31 #include "FullscreenVideoController.h" 32 #include "MarshallingHelpers.h" 33 #include "SoftLinking.h" 34 #include "WebBackForwardList.h" 35 #include "WebChromeClient.h" 36 #include "WebContextMenuClient.h" 37 #include "WebCoreTextRenderer.h" 38 #include "WebDatabaseManager.h" 39 #include "WebDocumentLoader.h" 40 #include "WebDownload.h" 41 #include "WebDragClient.h" 42 #include "WebEditorClient.h" 43 #include "WebElementPropertyBag.h" 44 #include "WebFrame.h" 45 #include "WebGeolocationClient.h" 46 #include "WebGeolocationPosition.h" 47 #include "WebIconDatabase.h" 48 #include "WebInspector.h" 49 #include "WebInspectorClient.h" 50 #include "WebKit.h" 51 #include "WebKitDLL.h" 52 #include "WebKitLogging.h" 53 #include "WebKitStatisticsPrivate.h" 54 #include "WebKitSystemBits.h" 55 #include "WebMutableURLRequest.h" 56 #include "WebNotificationCenter.h" 57 #include "WebPlatformStrategies.h" 58 #include "WebPluginHalterClient.h" 59 #include "WebPreferences.h" 60 #include "WebScriptWorld.h" 61 #include "resource.h" 62 #include <JavaScriptCore/APICast.h> 63 #include <JavaScriptCore/InitializeThreading.h> 64 #include <JavaScriptCore/JSLock.h> 65 #include <JavaScriptCore/JSValue.h> 66 #include <WebCore/AbstractDatabase.h> 67 #include <WebCore/AXObjectCache.h> 68 #include <WebCore/ApplicationCacheStorage.h> 69 #include <WebCore/BString.h> 70 #include <WebCore/BackForwardListImpl.h> 71 #include <WebCore/BitmapInfo.h> 72 #include <WebCore/MemoryCache.h> 73 #include <WebCore/Chrome.h> 74 #include <WebCore/ContextMenu.h> 75 #include <WebCore/ContextMenuController.h> 76 #include <WebCore/Cursor.h> 77 #include <WebCore/Document.h> 78 #include <WebCore/DocumentMarkerController.h> 79 #include <WebCore/DragController.h> 80 #include <WebCore/DragData.h> 81 #include <WebCore/Editor.h> 82 #include <WebCore/EventHandler.h> 83 #include <WebCore/EventNames.h> 84 #include <WebCore/FileSystem.h> 85 #include <WebCore/FloatQuad.h> 86 #include <WebCore/FocusController.h> 87 #include <WebCore/FrameLoader.h> 88 #include <WebCore/FrameTree.h> 89 #include <WebCore/FrameView.h> 90 #include <WebCore/FrameWin.h> 91 #include <WebCore/GDIObjectCounter.h> 92 #include <WebCore/GraphicsContext.h> 93 #include <WebCore/HTMLMediaElement.h> 94 #include <WebCore/HTMLNames.h> 95 #include <WebCore/HistoryItem.h> 96 #include <WebCore/HitTestRequest.h> 97 #include <WebCore/HitTestResult.h> 98 #include <WebCore/IntRect.h> 99 #include <WebCore/JSElement.h> 100 #include <WebCore/KeyboardEvent.h> 101 #include <WebCore/Logging.h> 102 #include <WebCore/MIMETypeRegistry.h> 103 #include <WebCore/Page.h> 104 #include <WebCore/PageCache.h> 105 #include <WebCore/PageGroup.h> 106 #include <WebCore/PlatformKeyboardEvent.h> 107 #include <WebCore/PlatformMouseEvent.h> 108 #include <WebCore/PlatformWheelEvent.h> 109 #include <WebCore/PluginData.h> 110 #include <WebCore/PluginDatabase.h> 111 #include <WebCore/PluginView.h> 112 #include <WebCore/PopupMenu.h> 113 #include <WebCore/PopupMenuWin.h> 114 #include <WebCore/ProgressTracker.h> 115 #include <WebCore/RenderLayer.h> 116 #include <WebCore/RenderTheme.h> 117 #include <WebCore/RenderTreeAsText.h> 118 #include <WebCore/RenderView.h> 119 #include <WebCore/RenderWidget.h> 120 #include <WebCore/ResourceHandle.h> 121 #include <WebCore/ResourceHandleClient.h> 122 #include <WebCore/SchemeRegistry.h> 123 #include <WebCore/ScriptValue.h> 124 #include <WebCore/Scrollbar.h> 125 #include <WebCore/ScrollbarTheme.h> 126 #include <WebCore/SecurityOrigin.h> 127 #include <WebCore/SelectionController.h> 128 #include <WebCore/Settings.h> 129 #include <WebCore/SimpleFontData.h> 130 #include <WebCore/SystemInfo.h> 131 #include <WebCore/TypingCommand.h> 132 #include <WebCore/WindowMessageBroadcaster.h> 133 #include <WebCore/WindowsTouch.h> 134 #include <wtf/Threading.h> 135 136 #if ENABLE(CLIENT_BASED_GEOLOCATION) 137 #include <WebCore/GeolocationController.h> 138 #include <WebCore/GeolocationError.h> 139 #endif 140 141 #if USE(CG) 142 #include <CoreGraphics/CGContext.h> 143 #endif 144 145 #if USE(CF) 146 #include <CoreFoundation/CoreFoundation.h> 147 #endif 148 149 #if USE(CFNETWORK) 150 #include <CFNetwork/CFURLCachePriv.h> 151 #include <CFNetwork/CFURLProtocolPriv.h> 152 #include <WebCore/CookieStorageCFNet.h> 153 #include <WebKitSystemInterface/WebKitSystemInterface.h> 154 #endif 155 156 #if USE(ACCELERATED_COMPOSITING) 157 #include <WebCore/CACFLayerTreeHost.h> 158 #include <WebCore/PlatformCALayer.h> 159 #endif 160 161 #include <ShlObj.h> 162 #include <comutil.h> 163 #include <dimm.h> 164 #include <oleacc.h> 165 #include <wchar.h> 166 #include <windowsx.h> 167 #include <wtf/HashSet.h> 168 #include <wtf/text/CString.h> 169 #include <wtf/text/StringConcatenate.h> 170 171 // Soft link functions for gestures and panning feedback 172 SOFT_LINK_LIBRARY(USER32); 173 SOFT_LINK_OPTIONAL(USER32, GetGestureInfo, BOOL, WINAPI, (HGESTUREINFO, PGESTUREINFO)); 174 SOFT_LINK_OPTIONAL(USER32, SetGestureConfig, BOOL, WINAPI, (HWND, DWORD, UINT, PGESTURECONFIG, UINT)); 175 SOFT_LINK_OPTIONAL(USER32, CloseGestureInfoHandle, BOOL, WINAPI, (HGESTUREINFO)); 176 SOFT_LINK_LIBRARY(Uxtheme); 177 SOFT_LINK_OPTIONAL(Uxtheme, BeginPanningFeedback, BOOL, WINAPI, (HWND)); 178 SOFT_LINK_OPTIONAL(Uxtheme, EndPanningFeedback, BOOL, WINAPI, (HWND, BOOL)); 179 SOFT_LINK_OPTIONAL(Uxtheme, UpdatePanningFeedback, BOOL, WINAPI, (HWND, LONG, LONG, BOOL)); 180 181 using namespace WebCore; 182 using namespace std; 183 using JSC::JSLock; 184 185 static HMODULE accessibilityLib; 186 static HashSet<WebView*> pendingDeleteBackingStoreSet; 187 188 static String webKitVersionString(); 189 190 WebView* kit(Page* page) 191 { 192 return page ? static_cast<WebChromeClient*>(page->chrome()->client())->webView() : 0; 193 } 194 195 class PreferencesChangedOrRemovedObserver : public IWebNotificationObserver { 196 public: 197 static PreferencesChangedOrRemovedObserver* sharedInstance(); 198 199 private: 200 PreferencesChangedOrRemovedObserver() {} 201 ~PreferencesChangedOrRemovedObserver() {} 202 203 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) { return E_FAIL; } 204 virtual ULONG STDMETHODCALLTYPE AddRef(void) { return 0; } 205 virtual ULONG STDMETHODCALLTYPE Release(void) { return 0; } 206 207 public: 208 // IWebNotificationObserver 209 virtual HRESULT STDMETHODCALLTYPE onNotify( 210 /* [in] */ IWebNotification* notification); 211 212 private: 213 HRESULT notifyPreferencesChanged(WebCacheModel); 214 HRESULT notifyPreferencesRemoved(WebCacheModel); 215 }; 216 217 PreferencesChangedOrRemovedObserver* PreferencesChangedOrRemovedObserver::sharedInstance() 218 { 219 static PreferencesChangedOrRemovedObserver* shared = new PreferencesChangedOrRemovedObserver; 220 return shared; 221 } 222 223 HRESULT PreferencesChangedOrRemovedObserver::onNotify(IWebNotification* notification) 224 { 225 HRESULT hr = S_OK; 226 227 COMPtr<IUnknown> unkPrefs; 228 hr = notification->getObject(&unkPrefs); 229 if (FAILED(hr)) 230 return hr; 231 232 COMPtr<IWebPreferences> preferences(Query, unkPrefs); 233 if (!preferences) 234 return E_NOINTERFACE; 235 236 WebCacheModel cacheModel; 237 hr = preferences->cacheModel(&cacheModel); 238 if (FAILED(hr)) 239 return hr; 240 241 BSTR nameBSTR; 242 hr = notification->name(&nameBSTR); 243 if (FAILED(hr)) 244 return hr; 245 BString name; 246 name.adoptBSTR(nameBSTR); 247 248 if (wcscmp(name, WebPreferences::webPreferencesChangedNotification()) == 0) 249 return notifyPreferencesChanged(cacheModel); 250 251 if (wcscmp(name, WebPreferences::webPreferencesRemovedNotification()) == 0) 252 return notifyPreferencesRemoved(cacheModel); 253 254 ASSERT_NOT_REACHED(); 255 return E_FAIL; 256 } 257 258 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesChanged(WebCacheModel cacheModel) 259 { 260 HRESULT hr = S_OK; 261 262 if (!WebView::didSetCacheModel() || cacheModel > WebView::cacheModel()) 263 WebView::setCacheModel(cacheModel); 264 else if (cacheModel < WebView::cacheModel()) { 265 WebCacheModel sharedPreferencesCacheModel; 266 hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel); 267 if (FAILED(hr)) 268 return hr; 269 WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance())); 270 } 271 272 return hr; 273 } 274 275 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesRemoved(WebCacheModel cacheModel) 276 { 277 HRESULT hr = S_OK; 278 279 if (cacheModel == WebView::cacheModel()) { 280 WebCacheModel sharedPreferencesCacheModel; 281 hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel); 282 if (FAILED(hr)) 283 return hr; 284 WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance())); 285 } 286 287 return hr; 288 } 289 290 291 const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass"; 292 293 const int WM_XP_THEMECHANGED = 0x031A; 294 const int WM_VISTA_MOUSEHWHEEL = 0x020E; 295 296 static const int maxToolTipWidth = 250; 297 298 static const int delayBeforeDeletingBackingStoreMsec = 5000; 299 300 static ATOM registerWebView(); 301 302 static void initializeStaticObservers(); 303 304 static HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences*); 305 306 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches); 307 308 static bool continuousSpellCheckingEnabled; 309 static bool grammarCheckingEnabled; 310 311 static bool s_didSetCacheModel; 312 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer; 313 314 enum { 315 UpdateActiveStateTimer = 1, 316 DeleteBackingStoreTimer = 2, 317 }; 318 319 // WebView ---------------------------------------------------------------- 320 321 bool WebView::s_allowSiteSpecificHacks = false; 322 323 WebView::WebView() 324 : m_refCount(0) 325 #if !ASSERT_DISABLED 326 , m_deletionHasBegun(false) 327 #endif 328 , m_hostWindow(0) 329 , m_viewWindow(0) 330 , m_mainFrame(0) 331 , m_page(0) 332 , m_hasCustomDropTarget(false) 333 , m_useBackForwardList(true) 334 , m_userAgentOverridden(false) 335 , m_zoomMultiplier(1.0f) 336 , m_zoomsTextOnly(false) 337 , m_mouseActivated(false) 338 , m_dragData(0) 339 , m_currentCharacterCode(0) 340 , m_isBeingDestroyed(false) 341 , m_paintCount(0) 342 , m_hasSpellCheckerDocumentTag(false) 343 , m_smartInsertDeleteEnabled(false) 344 , m_didClose(false) 345 , m_inIMEComposition(0) 346 , m_toolTipHwnd(0) 347 , m_closeWindowTimer(0) 348 , m_topLevelParent(0) 349 , m_deleteBackingStoreTimerActive(false) 350 , m_transparent(false) 351 , m_selectTrailingWhitespaceEnabled(false) 352 , m_lastPanX(0) 353 , m_lastPanY(0) 354 , m_xOverpan(0) 355 , m_yOverpan(0) 356 #if USE(ACCELERATED_COMPOSITING) 357 , m_isAcceleratedCompositing(false) 358 #endif 359 , m_nextDisplayIsSynchronous(false) 360 , m_lastSetCursor(0) 361 { 362 JSC::initializeThreading(); 363 WTF::initializeMainThread(); 364 365 m_backingStoreSize.cx = m_backingStoreSize.cy = 0; 366 367 CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper,(void**)&m_dropTargetHelper); 368 369 initializeStaticObservers(); 370 371 WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences(); 372 BOOL enabled; 373 if (SUCCEEDED(sharedPreferences->continuousSpellCheckingEnabled(&enabled))) 374 continuousSpellCheckingEnabled = !!enabled; 375 if (SUCCEEDED(sharedPreferences->grammarCheckingEnabled(&enabled))) 376 grammarCheckingEnabled = !!enabled; 377 378 WebViewCount++; 379 gClassCount++; 380 gClassNameCount.add("WebView"); 381 } 382 383 WebView::~WebView() 384 { 385 deleteBackingStore(); 386 387 // the tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD 388 if (::IsWindow(m_toolTipHwnd)) 389 ::DestroyWindow(m_toolTipHwnd); 390 391 ASSERT(!m_page); 392 ASSERT(!m_preferences); 393 ASSERT(!m_viewWindow); 394 395 #if USE(ACCELERATED_COMPOSITING) 396 ASSERT(!m_layerTreeHost); 397 ASSERT(!m_backingLayer); 398 #endif 399 400 WebViewCount--; 401 gClassCount--; 402 gClassNameCount.remove("WebView"); 403 } 404 405 WebView* WebView::createInstance() 406 { 407 WebView* instance = new WebView(); 408 instance->AddRef(); 409 return instance; 410 } 411 412 void initializeStaticObservers() 413 { 414 static bool initialized; 415 if (initialized) 416 return; 417 initialized = true; 418 419 IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal(); 420 notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesChangedNotification(), 0); 421 notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesRemovedNotification(), 0); 422 } 423 424 static HashSet<WebView*>& allWebViewsSet() 425 { 426 static HashSet<WebView*> allWebViewsSet; 427 return allWebViewsSet; 428 } 429 430 void WebView::addToAllWebViewsSet() 431 { 432 allWebViewsSet().add(this); 433 } 434 435 void WebView::removeFromAllWebViewsSet() 436 { 437 allWebViewsSet().remove(this); 438 } 439 440 void WebView::setCacheModel(WebCacheModel cacheModel) 441 { 442 #if USE(CFNETWORK) 443 if (s_didSetCacheModel && cacheModel == s_cacheModel) 444 return; 445 446 RetainPtr<CFURLCacheRef> cfurlCache(AdoptCF, CFURLCacheCopySharedURLCache()); 447 RetainPtr<CFStringRef> cfurlCacheDirectory(AdoptCF, wkCopyFoundationCacheDirectory()); 448 if (!cfurlCacheDirectory) 449 cfurlCacheDirectory.adoptCF(WebCore::localUserSpecificStorageDirectory().createCFString()); 450 451 // As a fudge factor, use 1000 instead of 1024, in case the reported byte 452 // count doesn't align exactly to a megabyte boundary. 453 unsigned long long memSize = WebMemorySize() / 1024 / 1000; 454 unsigned long long diskFreeSize = WebVolumeFreeSize(cfurlCacheDirectory.get()) / 1024 / 1000; 455 456 unsigned cacheTotalCapacity = 0; 457 unsigned cacheMinDeadCapacity = 0; 458 unsigned cacheMaxDeadCapacity = 0; 459 double deadDecodedDataDeletionInterval = 0; 460 461 unsigned pageCacheCapacity = 0; 462 463 CFIndex cfurlCacheMemoryCapacity = 0; 464 CFIndex cfurlCacheDiskCapacity = 0; 465 466 switch (cacheModel) { 467 case WebCacheModelDocumentViewer: { 468 // Page cache capacity (in pages) 469 pageCacheCapacity = 0; 470 471 // Object cache capacities (in bytes) 472 if (memSize >= 2048) 473 cacheTotalCapacity = 96 * 1024 * 1024; 474 else if (memSize >= 1536) 475 cacheTotalCapacity = 64 * 1024 * 1024; 476 else if (memSize >= 1024) 477 cacheTotalCapacity = 32 * 1024 * 1024; 478 else if (memSize >= 512) 479 cacheTotalCapacity = 16 * 1024 * 1024; 480 481 cacheMinDeadCapacity = 0; 482 cacheMaxDeadCapacity = 0; 483 484 // Foundation memory cache capacity (in bytes) 485 cfurlCacheMemoryCapacity = 0; 486 487 // Foundation disk cache capacity (in bytes) 488 cfurlCacheDiskCapacity = CFURLCacheDiskCapacity(cfurlCache.get()); 489 490 break; 491 } 492 case WebCacheModelDocumentBrowser: { 493 // Page cache capacity (in pages) 494 if (memSize >= 1024) 495 pageCacheCapacity = 3; 496 else if (memSize >= 512) 497 pageCacheCapacity = 2; 498 else if (memSize >= 256) 499 pageCacheCapacity = 1; 500 else 501 pageCacheCapacity = 0; 502 503 // Object cache capacities (in bytes) 504 if (memSize >= 2048) 505 cacheTotalCapacity = 96 * 1024 * 1024; 506 else if (memSize >= 1536) 507 cacheTotalCapacity = 64 * 1024 * 1024; 508 else if (memSize >= 1024) 509 cacheTotalCapacity = 32 * 1024 * 1024; 510 else if (memSize >= 512) 511 cacheTotalCapacity = 16 * 1024 * 1024; 512 513 cacheMinDeadCapacity = cacheTotalCapacity / 8; 514 cacheMaxDeadCapacity = cacheTotalCapacity / 4; 515 516 // Foundation memory cache capacity (in bytes) 517 if (memSize >= 2048) 518 cfurlCacheMemoryCapacity = 4 * 1024 * 1024; 519 else if (memSize >= 1024) 520 cfurlCacheMemoryCapacity = 2 * 1024 * 1024; 521 else if (memSize >= 512) 522 cfurlCacheMemoryCapacity = 1 * 1024 * 1024; 523 else 524 cfurlCacheMemoryCapacity = 512 * 1024; 525 526 // Foundation disk cache capacity (in bytes) 527 if (diskFreeSize >= 16384) 528 cfurlCacheDiskCapacity = 50 * 1024 * 1024; 529 else if (diskFreeSize >= 8192) 530 cfurlCacheDiskCapacity = 40 * 1024 * 1024; 531 else if (diskFreeSize >= 4096) 532 cfurlCacheDiskCapacity = 30 * 1024 * 1024; 533 else 534 cfurlCacheDiskCapacity = 20 * 1024 * 1024; 535 536 break; 537 } 538 case WebCacheModelPrimaryWebBrowser: { 539 // Page cache capacity (in pages) 540 // (Research indicates that value / page drops substantially after 3 pages.) 541 if (memSize >= 2048) 542 pageCacheCapacity = 5; 543 else if (memSize >= 1024) 544 pageCacheCapacity = 4; 545 else if (memSize >= 512) 546 pageCacheCapacity = 3; 547 else if (memSize >= 256) 548 pageCacheCapacity = 2; 549 else 550 pageCacheCapacity = 1; 551 552 // Object cache capacities (in bytes) 553 // (Testing indicates that value / MB depends heavily on content and 554 // browsing pattern. Even growth above 128MB can have substantial 555 // value / MB for some content / browsing patterns.) 556 if (memSize >= 2048) 557 cacheTotalCapacity = 128 * 1024 * 1024; 558 else if (memSize >= 1536) 559 cacheTotalCapacity = 96 * 1024 * 1024; 560 else if (memSize >= 1024) 561 cacheTotalCapacity = 64 * 1024 * 1024; 562 else if (memSize >= 512) 563 cacheTotalCapacity = 32 * 1024 * 1024; 564 565 cacheMinDeadCapacity = cacheTotalCapacity / 4; 566 cacheMaxDeadCapacity = cacheTotalCapacity / 2; 567 568 // This code is here to avoid a PLT regression. We can remove it if we 569 // can prove that the overall system gain would justify the regression. 570 cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity); 571 572 deadDecodedDataDeletionInterval = 60; 573 574 // Foundation memory cache capacity (in bytes) 575 // (These values are small because WebCore does most caching itself.) 576 if (memSize >= 1024) 577 cfurlCacheMemoryCapacity = 4 * 1024 * 1024; 578 else if (memSize >= 512) 579 cfurlCacheMemoryCapacity = 2 * 1024 * 1024; 580 else if (memSize >= 256) 581 cfurlCacheMemoryCapacity = 1 * 1024 * 1024; 582 else 583 cfurlCacheMemoryCapacity = 512 * 1024; 584 585 // Foundation disk cache capacity (in bytes) 586 if (diskFreeSize >= 16384) 587 cfurlCacheDiskCapacity = 175 * 1024 * 1024; 588 else if (diskFreeSize >= 8192) 589 cfurlCacheDiskCapacity = 150 * 1024 * 1024; 590 else if (diskFreeSize >= 4096) 591 cfurlCacheDiskCapacity = 125 * 1024 * 1024; 592 else if (diskFreeSize >= 2048) 593 cfurlCacheDiskCapacity = 100 * 1024 * 1024; 594 else if (diskFreeSize >= 1024) 595 cfurlCacheDiskCapacity = 75 * 1024 * 1024; 596 else 597 cfurlCacheDiskCapacity = 50 * 1024 * 1024; 598 599 break; 600 } 601 default: 602 ASSERT_NOT_REACHED(); 603 } 604 605 // Don't shrink a big disk cache, since that would cause churn. 606 cfurlCacheDiskCapacity = max(cfurlCacheDiskCapacity, CFURLCacheDiskCapacity(cfurlCache.get())); 607 608 memoryCache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity); 609 memoryCache()->setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval); 610 pageCache()->setCapacity(pageCacheCapacity); 611 612 CFURLCacheSetMemoryCapacity(cfurlCache.get(), cfurlCacheMemoryCapacity); 613 CFURLCacheSetDiskCapacity(cfurlCache.get(), cfurlCacheDiskCapacity); 614 615 s_didSetCacheModel = true; 616 s_cacheModel = cacheModel; 617 return; 618 #endif 619 } 620 621 WebCacheModel WebView::cacheModel() 622 { 623 return s_cacheModel; 624 } 625 626 bool WebView::didSetCacheModel() 627 { 628 return s_didSetCacheModel; 629 } 630 631 WebCacheModel WebView::maxCacheModelInAnyInstance() 632 { 633 WebCacheModel cacheModel = WebCacheModelDocumentViewer; 634 635 HashSet<WebView*>::iterator end = allWebViewsSet().end(); 636 for (HashSet<WebView*>::iterator it = allWebViewsSet().begin(); it != end; ++it) { 637 COMPtr<IWebPreferences> pref; 638 if (FAILED((*it)->preferences(&pref))) 639 continue; 640 WebCacheModel prefCacheModel = WebCacheModelDocumentViewer; 641 if (FAILED(pref->cacheModel(&prefCacheModel))) 642 continue; 643 644 cacheModel = max(cacheModel, prefCacheModel); 645 } 646 647 return cacheModel; 648 } 649 650 HRESULT STDMETHODCALLTYPE WebView::close() 651 { 652 if (m_didClose) 653 return S_OK; 654 655 m_didClose = true; 656 657 #if USE(ACCELERATED_COMPOSITING) 658 setAcceleratedCompositing(false); 659 #endif 660 661 WebNotificationCenter::defaultCenterInternal()->postNotificationName(_bstr_t(WebViewWillCloseNotification).GetBSTR(), static_cast<IWebView*>(this), 0); 662 663 if (m_uiDelegatePrivate) 664 m_uiDelegatePrivate->webViewClosing(this); 665 666 removeFromAllWebViewsSet(); 667 668 if (m_page) { 669 if (Frame* frame = m_page->mainFrame()) 670 frame->loader()->detachFromParent(); 671 } 672 673 if (m_mouseOutTracker) { 674 m_mouseOutTracker->dwFlags = TME_CANCEL; 675 ::TrackMouseEvent(m_mouseOutTracker.get()); 676 m_mouseOutTracker.set(0); 677 } 678 679 revokeDragDrop(); 680 681 if (m_viewWindow) { 682 // We can't check IsWindow(m_viewWindow) here, because that will return true even while 683 // we're already handling WM_DESTROY. So we check !isBeingDestroyed() instead. 684 if (!isBeingDestroyed()) 685 DestroyWindow(m_viewWindow); 686 // Either we just destroyed m_viewWindow, or it's in the process of being destroyed. Either 687 // way, we clear it out to make sure we don't try to use it later. 688 m_viewWindow = 0; 689 } 690 691 setHostWindow(0); 692 693 setDownloadDelegate(0); 694 setEditingDelegate(0); 695 setFrameLoadDelegate(0); 696 setFrameLoadDelegatePrivate(0); 697 setHistoryDelegate(0); 698 setPolicyDelegate(0); 699 setResourceLoadDelegate(0); 700 setUIDelegate(0); 701 setFormDelegate(0); 702 setPluginHalterDelegate(0); 703 704 if (m_webInspector) 705 m_webInspector->webViewClosed(); 706 707 delete m_page; 708 m_page = 0; 709 710 registerForIconNotification(false); 711 IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal(); 712 notifyCenter->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get())); 713 714 if (COMPtr<WebPreferences> preferences = m_preferences) { 715 BSTR identifier = 0; 716 preferences->identifier(&identifier); 717 718 m_preferences = 0; 719 preferences->didRemoveFromWebView(); 720 // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences 721 preferences = 0; 722 if (identifier) { 723 WebPreferences::removeReferenceForIdentifier(identifier); 724 SysFreeString(identifier); 725 } 726 } 727 728 deleteBackingStore(); 729 return S_OK; 730 } 731 732 void WebView::repaint(const WebCore::IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly) 733 { 734 #if USE(ACCELERATED_COMPOSITING) 735 if (isAcceleratedCompositing()) { 736 // The contentChanged, immediate, and repaintContentOnly parameters are all based on a non- 737 // compositing painting/scrolling model. 738 addToDirtyRegion(windowRect); 739 return; 740 } 741 #endif 742 743 if (!repaintContentOnly) { 744 RECT rect = windowRect; 745 ::InvalidateRect(m_viewWindow, &rect, false); 746 } 747 if (contentChanged) 748 addToDirtyRegion(windowRect); 749 if (immediate) { 750 if (repaintContentOnly) 751 updateBackingStore(core(topLevelFrame())->view()); 752 else 753 ::UpdateWindow(m_viewWindow); 754 } 755 } 756 757 void WebView::deleteBackingStore() 758 { 759 pendingDeleteBackingStoreSet.remove(this); 760 761 if (m_deleteBackingStoreTimerActive) { 762 KillTimer(m_viewWindow, DeleteBackingStoreTimer); 763 m_deleteBackingStoreTimerActive = false; 764 } 765 m_backingStoreBitmap.clear(); 766 m_backingStoreDirtyRegion.clear(); 767 m_backingStoreSize.cx = m_backingStoreSize.cy = 0; 768 } 769 770 bool WebView::ensureBackingStore() 771 { 772 RECT windowRect; 773 ::GetClientRect(m_viewWindow, &windowRect); 774 LONG width = windowRect.right - windowRect.left; 775 LONG height = windowRect.bottom - windowRect.top; 776 if (width > 0 && height > 0 && (width != m_backingStoreSize.cx || height != m_backingStoreSize.cy)) { 777 deleteBackingStore(); 778 779 m_backingStoreSize.cx = width; 780 m_backingStoreSize.cy = height; 781 BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(m_backingStoreSize)); 782 783 void* pixels = NULL; 784 m_backingStoreBitmap = RefCountedHBITMAP::create(::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0)); 785 return true; 786 } 787 788 return false; 789 } 790 791 void WebView::addToDirtyRegion(const IntRect& dirtyRect) 792 { 793 // FIXME: We want an assert here saying that the dirtyRect is inside the clienRect, 794 // but it was being hit during our layout tests, and is being investigated in 795 // http://webkit.org/b/29350. 796 797 #if USE(ACCELERATED_COMPOSITING) 798 if (isAcceleratedCompositing()) { 799 m_backingLayer->setNeedsDisplayInRect(dirtyRect); 800 return; 801 } 802 #endif 803 804 HRGN newRegion = ::CreateRectRgn(dirtyRect.x(), dirtyRect.y(), 805 dirtyRect.maxX(), dirtyRect.maxY()); 806 addToDirtyRegion(newRegion); 807 } 808 809 void WebView::addToDirtyRegion(HRGN newRegion) 810 { 811 #if USE(ACCELERATED_COMPOSITING) 812 ASSERT(!isAcceleratedCompositing()); 813 #endif 814 815 LOCAL_GDI_COUNTER(0, __FUNCTION__); 816 817 if (m_backingStoreDirtyRegion) { 818 HRGN combinedRegion = ::CreateRectRgn(0,0,0,0); 819 ::CombineRgn(combinedRegion, m_backingStoreDirtyRegion->handle(), newRegion, RGN_OR); 820 ::DeleteObject(newRegion); 821 m_backingStoreDirtyRegion = RefCountedHRGN::create(combinedRegion); 822 } else 823 m_backingStoreDirtyRegion = RefCountedHRGN::create(newRegion); 824 825 if (m_uiDelegatePrivate) 826 m_uiDelegatePrivate->webViewDidInvalidate(this); 827 } 828 829 void WebView::scrollBackingStore(FrameView* frameView, int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect) 830 { 831 #if USE(ACCELERATED_COMPOSITING) 832 if (isAcceleratedCompositing()) { 833 // FIXME: We should be doing something smarter here, like moving tiles around and painting 834 // any newly-exposed tiles. <http://webkit.org/b/52714> 835 m_backingLayer->setNeedsDisplayInRect(scrollViewRect); 836 return; 837 } 838 #endif 839 840 LOCAL_GDI_COUNTER(0, __FUNCTION__); 841 842 // If there's no backing store we don't need to update it 843 if (!m_backingStoreBitmap) { 844 if (m_uiDelegatePrivate) 845 m_uiDelegatePrivate->webViewScrolled(this); 846 847 return; 848 } 849 850 // Make a region to hold the invalidated scroll area. 851 HRGN updateRegion = ::CreateRectRgn(0, 0, 0, 0); 852 853 // Collect our device context info and select the bitmap to scroll. 854 HDC windowDC = ::GetDC(m_viewWindow); 855 HDC bitmapDC = ::CreateCompatibleDC(windowDC); 856 HGDIOBJ oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->handle()); 857 858 // Scroll the bitmap. 859 RECT scrollRectWin(scrollViewRect); 860 RECT clipRectWin(clipRect); 861 ::ScrollDC(bitmapDC, dx, dy, &scrollRectWin, &clipRectWin, updateRegion, 0); 862 RECT regionBox; 863 ::GetRgnBox(updateRegion, ®ionBox); 864 865 // Flush. 866 GdiFlush(); 867 868 // Add the dirty region to the backing store's dirty region. 869 addToDirtyRegion(updateRegion); 870 871 if (m_uiDelegatePrivate) 872 m_uiDelegatePrivate->webViewScrolled(this); 873 874 // Update the backing store. 875 updateBackingStore(frameView, bitmapDC, false); 876 877 // Clean up. 878 ::SelectObject(bitmapDC, oldBitmap); 879 ::DeleteDC(bitmapDC); 880 ::ReleaseDC(m_viewWindow, windowDC); 881 } 882 883 void WebView::sizeChanged(const IntSize& newSize) 884 { 885 deleteBackingStore(); 886 887 if (Frame* coreFrame = core(topLevelFrame())) 888 coreFrame->view()->resize(newSize); 889 890 #if USE(ACCELERATED_COMPOSITING) 891 if (m_layerTreeHost) 892 m_layerTreeHost->resize(); 893 if (m_backingLayer) { 894 m_backingLayer->setSize(newSize); 895 m_backingLayer->setNeedsDisplay(); 896 } 897 #endif 898 } 899 900 // This emulates the Mac smarts for painting rects intelligently. This is very 901 // important for us, since we double buffer based off dirty rects. 902 static void getUpdateRects(HRGN region, const IntRect& dirtyRect, Vector<IntRect>& rects) 903 { 904 ASSERT_ARG(region, region); 905 906 const int cRectThreshold = 10; 907 const float cWastedSpaceThreshold = 0.75f; 908 909 rects.clear(); 910 911 DWORD regionDataSize = GetRegionData(region, sizeof(RGNDATA), NULL); 912 if (!regionDataSize) { 913 rects.append(dirtyRect); 914 return; 915 } 916 917 Vector<unsigned char> buffer(regionDataSize); 918 RGNDATA* regionData = reinterpret_cast<RGNDATA*>(buffer.data()); 919 GetRegionData(region, regionDataSize, regionData); 920 if (regionData->rdh.nCount > cRectThreshold) { 921 rects.append(dirtyRect); 922 return; 923 } 924 925 double singlePixels = 0.0; 926 unsigned i; 927 RECT* rect; 928 for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++) 929 singlePixels += (rect->right - rect->left) * (rect->bottom - rect->top); 930 931 double unionPixels = dirtyRect.width() * dirtyRect.height(); 932 double wastedSpace = 1.0 - (singlePixels / unionPixels); 933 if (wastedSpace <= cWastedSpaceThreshold) { 934 rects.append(dirtyRect); 935 return; 936 } 937 938 for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++) 939 rects.append(*rect); 940 } 941 942 void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStoreCompletelyDirty, WindowsToPaint windowsToPaint) 943 { 944 #if USE(ACCELERATED_COMPOSITING) 945 ASSERT(!isAcceleratedCompositing()); 946 #endif 947 948 LOCAL_GDI_COUNTER(0, __FUNCTION__); 949 950 HDC windowDC = 0; 951 HDC bitmapDC = dc; 952 if (!dc) { 953 windowDC = ::GetDC(m_viewWindow); 954 bitmapDC = ::CreateCompatibleDC(windowDC); 955 ::SelectObject(bitmapDC, m_backingStoreBitmap->handle()); 956 } 957 958 if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) { 959 // Do a layout first so that everything we render to the backing store is always current. 960 if (Frame* coreFrame = core(m_mainFrame)) 961 if (FrameView* view = coreFrame->view()) 962 view->updateLayoutAndStyleIfNeededRecursive(); 963 964 Vector<IntRect> paintRects; 965 if (!backingStoreCompletelyDirty && m_backingStoreDirtyRegion) { 966 RECT regionBox; 967 ::GetRgnBox(m_backingStoreDirtyRegion->handle(), ®ionBox); 968 getUpdateRects(m_backingStoreDirtyRegion->handle(), regionBox, paintRects); 969 } else { 970 RECT clientRect; 971 ::GetClientRect(m_viewWindow, &clientRect); 972 paintRects.append(clientRect); 973 } 974 975 for (unsigned i = 0; i < paintRects.size(); ++i) 976 paintIntoBackingStore(frameView, bitmapDC, paintRects[i], windowsToPaint); 977 978 if (m_uiDelegatePrivate) 979 m_uiDelegatePrivate->webViewPainted(this); 980 981 m_backingStoreDirtyRegion.clear(); 982 } 983 984 if (!dc) { 985 ::DeleteDC(bitmapDC); 986 ::ReleaseDC(m_viewWindow, windowDC); 987 } 988 989 GdiFlush(); 990 } 991 992 void WebView::paint(HDC dc, LPARAM options) 993 { 994 LOCAL_GDI_COUNTER(0, __FUNCTION__); 995 996 #if USE(ACCELERATED_COMPOSITING) 997 if (isAcceleratedCompositing()) { 998 m_layerTreeHost->flushPendingLayerChangesNow(); 999 // Flushing might have taken us out of compositing mode. 1000 if (isAcceleratedCompositing()) { 1001 // FIXME: We need to paint into dc (if provided). <http://webkit.org/b/52578> 1002 m_layerTreeHost->paint(); 1003 ::ValidateRect(m_viewWindow, 0); 1004 return; 1005 } 1006 } 1007 #endif 1008 1009 Frame* coreFrame = core(m_mainFrame); 1010 if (!coreFrame) 1011 return; 1012 FrameView* frameView = coreFrame->view(); 1013 1014 RECT rcPaint; 1015 HDC hdc; 1016 OwnPtr<HRGN> region; 1017 int regionType = NULLREGION; 1018 PAINTSTRUCT ps; 1019 WindowsToPaint windowsToPaint; 1020 if (!dc) { 1021 region.set(CreateRectRgn(0,0,0,0)); 1022 regionType = GetUpdateRgn(m_viewWindow, region.get(), false); 1023 hdc = BeginPaint(m_viewWindow, &ps); 1024 rcPaint = ps.rcPaint; 1025 // We're painting to the screen, and our child windows can handle 1026 // painting themselves to the screen. 1027 windowsToPaint = PaintWebViewOnly; 1028 } else { 1029 hdc = dc; 1030 ::GetClientRect(m_viewWindow, &rcPaint); 1031 if (options & PRF_ERASEBKGND) 1032 ::FillRect(hdc, &rcPaint, (HBRUSH)GetStockObject(WHITE_BRUSH)); 1033 // Since we aren't painting to the screen, we want to paint all our 1034 // children into the HDC. 1035 windowsToPaint = PaintWebViewAndChildren; 1036 } 1037 1038 bool backingStoreCompletelyDirty = ensureBackingStore(); 1039 if (!m_backingStoreBitmap) { 1040 if (!dc) 1041 EndPaint(m_viewWindow, &ps); 1042 return; 1043 } 1044 1045 m_paintCount++; 1046 1047 HDC bitmapDC = ::CreateCompatibleDC(hdc); 1048 HGDIOBJ oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->handle()); 1049 1050 // Update our backing store if needed. 1051 updateBackingStore(frameView, bitmapDC, backingStoreCompletelyDirty, windowsToPaint); 1052 1053 // Now we blit the updated backing store 1054 IntRect windowDirtyRect = rcPaint; 1055 1056 // Apply the same heuristic for this update region too. 1057 Vector<IntRect> blitRects; 1058 if (region && regionType == COMPLEXREGION) 1059 getUpdateRects(region.get(), windowDirtyRect, blitRects); 1060 else 1061 blitRects.append(windowDirtyRect); 1062 1063 for (unsigned i = 0; i < blitRects.size(); ++i) 1064 paintIntoWindow(bitmapDC, hdc, blitRects[i]); 1065 1066 ::SelectObject(bitmapDC, oldBitmap); 1067 ::DeleteDC(bitmapDC); 1068 1069 if (!dc) 1070 EndPaint(m_viewWindow, &ps); 1071 1072 m_paintCount--; 1073 1074 if (active()) 1075 cancelDeleteBackingStoreSoon(); 1076 else 1077 deleteBackingStoreSoon(); 1078 } 1079 1080 void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, const IntRect& dirtyRect, WindowsToPaint windowsToPaint) 1081 { 1082 // FIXME: This function should never be called in accelerated compositing mode, and we should 1083 // assert as such. But currently it *is* sometimes called, so we can't assert yet. See 1084 // <http://webkit.org/b/58539>. 1085 1086 LOCAL_GDI_COUNTER(0, __FUNCTION__); 1087 1088 // FIXME: We want an assert here saying that the dirtyRect is inside the clienRect, 1089 // but it was being hit during our layout tests, and is being investigated in 1090 // http://webkit.org/b/29350. 1091 1092 RECT rect = dirtyRect; 1093 1094 #if FLASH_BACKING_STORE_REDRAW 1095 HDC dc = ::GetDC(m_viewWindow); 1096 OwnPtr<HBRUSH> yellowBrush(CreateSolidBrush(RGB(255, 255, 0))); 1097 FillRect(dc, &rect, yellowBrush.get()); 1098 GdiFlush(); 1099 Sleep(50); 1100 paintIntoWindow(bitmapDC, dc, dirtyRect); 1101 ::ReleaseDC(m_viewWindow, dc); 1102 #endif 1103 1104 GraphicsContext gc(bitmapDC, m_transparent); 1105 gc.setShouldIncludeChildWindows(windowsToPaint == PaintWebViewAndChildren); 1106 gc.save(); 1107 if (m_transparent) 1108 gc.clearRect(dirtyRect); 1109 else 1110 FillRect(bitmapDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); 1111 1112 COMPtr<IWebUIDelegatePrivate2> uiPrivate(Query, m_uiDelegate); 1113 if (uiPrivate) 1114 uiPrivate->drawBackground(this, reinterpret_cast<OLE_HANDLE>(bitmapDC), &rect); 1115 1116 if (frameView && frameView->frame() && frameView->frame()->contentRenderer()) { 1117 gc.clip(dirtyRect); 1118 frameView->paint(&gc, dirtyRect); 1119 } 1120 gc.restore(); 1121 } 1122 1123 void WebView::paintIntoWindow(HDC bitmapDC, HDC windowDC, const IntRect& dirtyRect) 1124 { 1125 // FIXME: This function should never be called in accelerated compositing mode, and we should 1126 // assert as such. But currently it *is* sometimes called, so we can't assert yet. See 1127 // <http://webkit.org/b/58539>. 1128 1129 LOCAL_GDI_COUNTER(0, __FUNCTION__); 1130 #if FLASH_WINDOW_REDRAW 1131 OwnPtr<HBRUSH> greenBrush = CreateSolidBrush(RGB(0, 255, 0)); 1132 RECT rect = dirtyRect; 1133 FillRect(windowDC, &rect, greenBrush.get()); 1134 GdiFlush(); 1135 Sleep(50); 1136 #endif 1137 1138 // Blit the dirty rect from the backing store into the same position 1139 // in the destination DC. 1140 BitBlt(windowDC, dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), bitmapDC, 1141 dirtyRect.x(), dirtyRect.y(), SRCCOPY); 1142 } 1143 1144 void WebView::frameRect(RECT* rect) 1145 { 1146 ::GetWindowRect(m_viewWindow, rect); 1147 } 1148 1149 class WindowCloseTimer : public WebCore::SuspendableTimer { 1150 public: 1151 static WindowCloseTimer* create(WebView*); 1152 1153 private: 1154 WindowCloseTimer(ScriptExecutionContext*, WebView*); 1155 virtual void contextDestroyed(); 1156 virtual void fired(); 1157 1158 WebView* m_webView; 1159 }; 1160 1161 WindowCloseTimer* WindowCloseTimer::create(WebView* webView) 1162 { 1163 ASSERT_ARG(webView, webView); 1164 Frame* frame = core(webView->topLevelFrame()); 1165 ASSERT(frame); 1166 if (!frame) 1167 return 0; 1168 1169 Document* document = frame->document(); 1170 ASSERT(document); 1171 if (!document) 1172 return 0; 1173 1174 return new WindowCloseTimer(document, webView); 1175 } 1176 1177 WindowCloseTimer::WindowCloseTimer(ScriptExecutionContext* context, WebView* webView) 1178 : SuspendableTimer(context) 1179 , m_webView(webView) 1180 { 1181 ASSERT_ARG(context, context); 1182 ASSERT_ARG(webView, webView); 1183 } 1184 1185 void WindowCloseTimer::contextDestroyed() 1186 { 1187 SuspendableTimer::contextDestroyed(); 1188 delete this; 1189 } 1190 1191 void WindowCloseTimer::fired() 1192 { 1193 m_webView->closeWindowTimerFired(); 1194 } 1195 1196 void WebView::closeWindowSoon() 1197 { 1198 if (m_closeWindowTimer) 1199 return; 1200 1201 m_closeWindowTimer = WindowCloseTimer::create(this); 1202 if (!m_closeWindowTimer) 1203 return; 1204 m_closeWindowTimer->startOneShot(0); 1205 1206 AddRef(); 1207 } 1208 1209 void WebView::closeWindowTimerFired() 1210 { 1211 closeWindow(); 1212 Release(); 1213 } 1214 1215 void WebView::closeWindow() 1216 { 1217 if (m_hasSpellCheckerDocumentTag) { 1218 if (m_editingDelegate) 1219 m_editingDelegate->closeSpellDocument(this); 1220 m_hasSpellCheckerDocumentTag = false; 1221 } 1222 1223 COMPtr<IWebUIDelegate> ui; 1224 if (SUCCEEDED(uiDelegate(&ui))) 1225 ui->webViewClose(this); 1226 } 1227 1228 bool WebView::canHandleRequest(const WebCore::ResourceRequest& request) 1229 { 1230 // On the mac there's an about url protocol implementation but CFNetwork doesn't have that. 1231 if (equalIgnoringCase(String(request.url().protocol()), "about")) 1232 return true; 1233 1234 #if USE(CFNETWORK) 1235 if (CFURLProtocolCanHandleRequest(request.cfURLRequest())) 1236 return true; 1237 1238 // FIXME: Mac WebKit calls _representationExistsForURLScheme here 1239 return false; 1240 #else 1241 return true; 1242 #endif 1243 } 1244 1245 String WebView::standardUserAgentWithApplicationName(const String& applicationName) 1246 { 1247 DEFINE_STATIC_LOCAL(String, osVersion, (windowsVersionForUAString())); 1248 DEFINE_STATIC_LOCAL(String, webKitVersion, (webKitVersionString())); 1249 1250 return makeString("Mozilla/5.0 (", osVersion, ") AppleWebKit/", webKitVersion, " (KHTML, like Gecko)", applicationName.isEmpty() ? "" : " ", applicationName); 1251 } 1252 1253 Page* WebView::page() 1254 { 1255 return m_page; 1256 } 1257 1258 bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam) 1259 { 1260 // Translate the screen coordinates into window coordinates 1261 POINT coords = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; 1262 if (coords.x == -1 || coords.y == -1) { 1263 // The contextMenuController() holds onto the last context menu that was popped up on the 1264 // page until a new one is created. We need to clear this menu before propagating the event 1265 // through the DOM so that we can detect if we create a new menu for this event, since we 1266 // won't create a new menu if the DOM swallows the event and the defaultEventHandler does 1267 // not run. 1268 m_page->contextMenuController()->clearContextMenu(); 1269 1270 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame(); 1271 return focusedFrame->eventHandler()->sendContextMenuEventForKey(); 1272 1273 } else { 1274 if (!::ScreenToClient(m_viewWindow, &coords)) 1275 return false; 1276 } 1277 1278 lParam = MAKELPARAM(coords.x, coords.y); 1279 1280 m_page->contextMenuController()->clearContextMenu(); 1281 1282 IntPoint documentPoint(m_page->mainFrame()->view()->windowToContents(coords)); 1283 HitTestResult result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(documentPoint, false); 1284 Frame* targetFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame(); 1285 1286 targetFrame->view()->setCursor(pointerCursor()); 1287 PlatformMouseEvent mouseEvent(m_viewWindow, WM_RBUTTONUP, wParam, lParam); 1288 bool handledEvent = targetFrame->eventHandler()->sendContextMenuEvent(mouseEvent); 1289 if (!handledEvent) 1290 return false; 1291 1292 ContextMenuController* contextMenuController = m_page->contextMenuController(); 1293 1294 // Show the menu 1295 ContextMenu* coreMenu = contextMenuController->contextMenu(); 1296 if (!coreMenu) 1297 return false; 1298 1299 Node* node = contextMenuController->hitTestResult().innerNonSharedNode(); 1300 if (!node) 1301 return false; 1302 1303 Frame* frame = node->document()->frame(); 1304 if (!frame) 1305 return false; 1306 1307 FrameView* view = frame->view(); 1308 if (!view) 1309 return false; 1310 1311 POINT point(view->contentsToWindow(contextMenuController->hitTestResult().point())); 1312 1313 // Translate the point to screen coordinates 1314 if (!::ClientToScreen(m_viewWindow, &point)) 1315 return false; 1316 1317 BOOL hasCustomMenus = false; 1318 if (m_uiDelegate) 1319 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus); 1320 1321 if (hasCustomMenus) 1322 m_uiDelegate->trackCustomPopupMenu((IWebView*)this, (OLE_HANDLE)(ULONG64)coreMenu->nativeMenu(), &point); 1323 else { 1324 // Surprisingly, TPM_RIGHTBUTTON means that items are selectable with either the right OR left mouse button 1325 UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL 1326 | TPM_LEFTALIGN | TPM_HORPOSANIMATION; 1327 ::TrackPopupMenuEx(coreMenu->nativeMenu(), flags, point.x, point.y, m_viewWindow, 0); 1328 } 1329 1330 return true; 1331 } 1332 1333 bool WebView::onMeasureItem(WPARAM /*wParam*/, LPARAM lParam) 1334 { 1335 if (!m_uiDelegate) 1336 return false; 1337 1338 BOOL hasCustomMenus = false; 1339 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus); 1340 if (!hasCustomMenus) 1341 return false; 1342 1343 m_uiDelegate->measureCustomMenuItem((IWebView*)this, (void*)lParam); 1344 return true; 1345 } 1346 1347 bool WebView::onDrawItem(WPARAM /*wParam*/, LPARAM lParam) 1348 { 1349 if (!m_uiDelegate) 1350 return false; 1351 1352 BOOL hasCustomMenus = false; 1353 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus); 1354 if (!hasCustomMenus) 1355 return false; 1356 1357 m_uiDelegate->drawCustomMenuItem((IWebView*)this, (void*)lParam); 1358 return true; 1359 } 1360 1361 bool WebView::onInitMenuPopup(WPARAM wParam, LPARAM /*lParam*/) 1362 { 1363 if (!m_uiDelegate) 1364 return false; 1365 1366 HMENU menu = (HMENU)wParam; 1367 if (!menu) 1368 return false; 1369 1370 BOOL hasCustomMenus = false; 1371 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus); 1372 if (!hasCustomMenus) 1373 return false; 1374 1375 m_uiDelegate->addCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu); 1376 return true; 1377 } 1378 1379 bool WebView::onUninitMenuPopup(WPARAM wParam, LPARAM /*lParam*/) 1380 { 1381 if (!m_uiDelegate) 1382 return false; 1383 1384 HMENU menu = (HMENU)wParam; 1385 if (!menu) 1386 return false; 1387 1388 BOOL hasCustomMenus = false; 1389 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus); 1390 if (!hasCustomMenus) 1391 return false; 1392 1393 m_uiDelegate->cleanUpCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu); 1394 return true; 1395 } 1396 1397 void WebView::performContextMenuAction(WPARAM wParam, LPARAM lParam, bool byPosition) 1398 { 1399 ContextMenu* menu = m_page->contextMenuController()->contextMenu(); 1400 ASSERT(menu); 1401 1402 ContextMenuItem* item = byPosition ? menu->itemAtIndex((unsigned)wParam) : menu->itemWithAction((ContextMenuAction)wParam); 1403 if (!item) 1404 return; 1405 m_page->contextMenuController()->contextMenuItemSelected(item); 1406 } 1407 1408 bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam) 1409 { 1410 static LONG globalClickCount; 1411 static IntPoint globalPrevPoint; 1412 static MouseButton globalPrevButton; 1413 static LONG globalPrevMouseDownTime; 1414 1415 if (message == WM_CANCELMODE) { 1416 m_page->mainFrame()->eventHandler()->lostMouseCapture(); 1417 return true; 1418 } 1419 1420 // Create our event. 1421 // On WM_MOUSELEAVE we need to create a mouseout event, so we force the position 1422 // of the event to be at (MINSHORT, MINSHORT). 1423 LPARAM position = (message == WM_MOUSELEAVE) ? ((MINSHORT << 16) | MINSHORT) : lParam; 1424 PlatformMouseEvent mouseEvent(m_viewWindow, message, wParam, position, m_mouseActivated); 1425 1426 setMouseActivated(false); 1427 1428 bool insideThreshold = abs(globalPrevPoint.x() - mouseEvent.pos().x()) < ::GetSystemMetrics(SM_CXDOUBLECLK) && 1429 abs(globalPrevPoint.y() - mouseEvent.pos().y()) < ::GetSystemMetrics(SM_CYDOUBLECLK); 1430 LONG messageTime = ::GetMessageTime(); 1431 1432 bool handled = false; 1433 1434 if (message == WM_LBUTTONDOWN || message == WM_MBUTTONDOWN || message == WM_RBUTTONDOWN) { 1435 // FIXME: I'm not sure if this is the "right" way to do this 1436 // but without this call, we never become focused since we don't allow 1437 // the default handling of mouse events. 1438 SetFocus(m_viewWindow); 1439 1440 // Always start capturing events when the mouse goes down in our HWND. 1441 ::SetCapture(m_viewWindow); 1442 1443 if (((messageTime - globalPrevMouseDownTime) < (LONG)::GetDoubleClickTime()) && 1444 insideThreshold && 1445 mouseEvent.button() == globalPrevButton) 1446 globalClickCount++; 1447 else 1448 // Reset the click count. 1449 globalClickCount = 1; 1450 globalPrevMouseDownTime = messageTime; 1451 globalPrevButton = mouseEvent.button(); 1452 globalPrevPoint = mouseEvent.pos(); 1453 1454 mouseEvent.setClickCount(globalClickCount); 1455 handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent); 1456 } else if (message == WM_LBUTTONDBLCLK || message == WM_MBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) { 1457 globalClickCount++; 1458 mouseEvent.setClickCount(globalClickCount); 1459 handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent); 1460 } else if (message == WM_LBUTTONUP || message == WM_MBUTTONUP || message == WM_RBUTTONUP) { 1461 // Record the global position and the button of the up. 1462 globalPrevButton = mouseEvent.button(); 1463 globalPrevPoint = mouseEvent.pos(); 1464 mouseEvent.setClickCount(globalClickCount); 1465 m_page->mainFrame()->eventHandler()->handleMouseReleaseEvent(mouseEvent); 1466 ::ReleaseCapture(); 1467 } else if (message == WM_MOUSELEAVE && m_mouseOutTracker) { 1468 // Once WM_MOUSELEAVE is fired windows clears this tracker 1469 // so there is no need to disable it ourselves. 1470 m_mouseOutTracker.set(0); 1471 m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent); 1472 handled = true; 1473 } else if (message == WM_MOUSEMOVE) { 1474 if (!insideThreshold) 1475 globalClickCount = 0; 1476 mouseEvent.setClickCount(globalClickCount); 1477 handled = m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent); 1478 if (!m_mouseOutTracker) { 1479 m_mouseOutTracker.set(new TRACKMOUSEEVENT); 1480 m_mouseOutTracker->cbSize = sizeof(TRACKMOUSEEVENT); 1481 m_mouseOutTracker->dwFlags = TME_LEAVE; 1482 m_mouseOutTracker->hwndTrack = m_viewWindow; 1483 ::TrackMouseEvent(m_mouseOutTracker.get()); 1484 } 1485 } 1486 return handled; 1487 } 1488 1489 bool WebView::gestureNotify(WPARAM wParam, LPARAM lParam) 1490 { 1491 GESTURENOTIFYSTRUCT* gn = reinterpret_cast<GESTURENOTIFYSTRUCT*>(lParam); 1492 1493 Frame* coreFrame = core(m_mainFrame); 1494 if (!coreFrame) 1495 return false; 1496 1497 ScrollView* view = coreFrame->view(); 1498 if (!view) 1499 return false; 1500 1501 // If we don't have this function, we shouldn't be receiving this message 1502 ASSERT(SetGestureConfigPtr()); 1503 1504 bool hitScrollbar = false; 1505 POINT gestureBeginPoint = {gn->ptsLocation.x, gn->ptsLocation.y}; 1506 HitTestRequest request(HitTestRequest::ReadOnly); 1507 for (Frame* childFrame = m_page->mainFrame(); childFrame; childFrame = EventHandler::subframeForTargetNode(m_gestureTargetNode.get())) { 1508 FrameView* frameView = childFrame->view(); 1509 if (!frameView) 1510 break; 1511 RenderView* renderView = childFrame->document()->renderView(); 1512 if (!renderView) 1513 break; 1514 RenderLayer* layer = renderView->layer(); 1515 if (!layer) 1516 break; 1517 1518 HitTestResult result(frameView->screenToContents(gestureBeginPoint)); 1519 layer->hitTest(request, result); 1520 m_gestureTargetNode = result.innerNode(); 1521 1522 if (!hitScrollbar) 1523 hitScrollbar = result.scrollbar(); 1524 } 1525 1526 if (!hitScrollbar) { 1527 // The hit testing above won't detect if we've hit the main frame's vertical scrollbar. Check that manually now. 1528 RECT webViewRect; 1529 GetWindowRect(m_viewWindow, &webViewRect); 1530 hitScrollbar = view->verticalScrollbar() && (gestureBeginPoint.x > (webViewRect.right - view->verticalScrollbar()->theme()->scrollbarThickness())); 1531 } 1532 1533 bool canBeScrolled = false; 1534 if (m_gestureTargetNode) { 1535 for (RenderObject* renderer = m_gestureTargetNode->renderer(); renderer; renderer = renderer->parent()) { 1536 if (renderer->isBox() && toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()) { 1537 canBeScrolled = true; 1538 break; 1539 } 1540 } 1541 } 1542 1543 // We always allow two-fingered panning with inertia and a gutter (which limits movement to one 1544 // direction in most cases). 1545 DWORD dwPanWant = GC_PAN | GC_PAN_WITH_INERTIA | GC_PAN_WITH_GUTTER; 1546 // We never allow single-fingered horizontal panning. That gesture is reserved for creating text 1547 // selections. This matches IE. 1548 DWORD dwPanBlock = GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY; 1549 1550 if (hitScrollbar || !canBeScrolled) { 1551 // The part of the page under the gesture can't be scrolled, or the gesture is on a scrollbar. 1552 // Disallow single-fingered vertical panning in this case, too, so we'll fall back to the default 1553 // behavior (which allows the scrollbar thumb to be dragged, text selections to be made, etc.). 1554 dwPanBlock |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY; 1555 } else { 1556 // The part of the page the gesture is under can be scrolled, and we're not under a scrollbar. 1557 // Allow single-fingered vertical panning in this case, so the user will be able to pan the page 1558 // with one or two fingers. 1559 dwPanWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY; 1560 } 1561 1562 GESTURECONFIG gc = { GID_PAN, dwPanWant, dwPanBlock }; 1563 return SetGestureConfigPtr()(m_viewWindow, 0, 1, &gc, sizeof(GESTURECONFIG)); 1564 } 1565 1566 bool WebView::gesture(WPARAM wParam, LPARAM lParam) 1567 { 1568 // We want to bail out if we don't have either of these functions 1569 if (!GetGestureInfoPtr() || !CloseGestureInfoHandlePtr()) 1570 return false; 1571 1572 HGESTUREINFO gestureHandle = reinterpret_cast<HGESTUREINFO>(lParam); 1573 1574 GESTUREINFO gi = {0}; 1575 gi.cbSize = sizeof(GESTUREINFO); 1576 1577 if (!GetGestureInfoPtr()(gestureHandle, reinterpret_cast<PGESTUREINFO>(&gi))) 1578 return false; 1579 1580 switch (gi.dwID) { 1581 case GID_BEGIN: 1582 m_lastPanX = gi.ptsLocation.x; 1583 m_lastPanY = gi.ptsLocation.y; 1584 1585 break; 1586 case GID_END: 1587 m_gestureTargetNode = 0; 1588 break; 1589 case GID_PAN: { 1590 // Where are the fingers currently? 1591 long currentX = gi.ptsLocation.x; 1592 long currentY = gi.ptsLocation.y; 1593 // How far did we pan in each direction? 1594 long deltaX = currentX - m_lastPanX; 1595 long deltaY = currentY - m_lastPanY; 1596 // Calculate the overpan for window bounce 1597 m_yOverpan -= m_lastPanY - currentY; 1598 m_xOverpan -= m_lastPanX - currentX; 1599 // Update our class variables with updated values 1600 m_lastPanX = currentX; 1601 m_lastPanY = currentY; 1602 1603 Frame* coreFrame = core(m_mainFrame); 1604 if (!coreFrame) { 1605 CloseGestureInfoHandlePtr()(gestureHandle); 1606 return false; 1607 } 1608 1609 if (!m_gestureTargetNode || !m_gestureTargetNode->renderer()) 1610 return false; 1611 1612 // We negate here since panning up moves the content up, but moves the scrollbar down. 1613 m_gestureTargetNode->renderer()->enclosingLayer()->scrollByRecursively(-deltaX, -deltaY); 1614 1615 if (!(UpdatePanningFeedbackPtr() && BeginPanningFeedbackPtr() && EndPanningFeedbackPtr())) { 1616 CloseGestureInfoHandlePtr()(gestureHandle); 1617 return true; 1618 } 1619 1620 if (gi.dwFlags & GF_BEGIN) { 1621 BeginPanningFeedbackPtr()(m_viewWindow); 1622 m_yOverpan = 0; 1623 } else if (gi.dwFlags & GF_END) { 1624 EndPanningFeedbackPtr()(m_viewWindow, true); 1625 m_yOverpan = 0; 1626 } 1627 1628 ScrollView* view = coreFrame->view(); 1629 if (!view) { 1630 CloseGestureInfoHandlePtr()(gestureHandle); 1631 return true; 1632 } 1633 Scrollbar* vertScrollbar = view->verticalScrollbar(); 1634 if (!vertScrollbar) { 1635 CloseGestureInfoHandlePtr()(gestureHandle); 1636 return true; 1637 } 1638 1639 // FIXME: Support Horizontal Window Bounce. <https://webkit.org/b/28500>. 1640 // FIXME: If the user starts panning down after a window bounce has started, the window doesn't bounce back 1641 // until they release their finger. <https://webkit.org/b/28501>. 1642 if (vertScrollbar->currentPos() == 0) 1643 UpdatePanningFeedbackPtr()(m_viewWindow, 0, m_yOverpan, gi.dwFlags & GF_INERTIA); 1644 else if (vertScrollbar->currentPos() >= vertScrollbar->maximum()) 1645 UpdatePanningFeedbackPtr()(m_viewWindow, 0, m_yOverpan, gi.dwFlags & GF_INERTIA); 1646 1647 CloseGestureInfoHandlePtr()(gestureHandle); 1648 return true; 1649 } 1650 default: 1651 break; 1652 } 1653 1654 // If we get to this point, the gesture has not been handled. We forward 1655 // the call to DefWindowProc by returning false, and we don't need to 1656 // to call CloseGestureInfoHandle. 1657 // http://msdn.microsoft.com/en-us/library/dd353228(VS.85).aspx 1658 return false; 1659 } 1660 1661 bool WebView::mouseWheel(WPARAM wParam, LPARAM lParam, bool isMouseHWheel) 1662 { 1663 // Ctrl+Mouse wheel doesn't ever go into WebCore. It is used to 1664 // zoom instead (Mac zooms the whole Desktop, but Windows browsers trigger their 1665 // own local zoom modes for Ctrl+wheel). 1666 if (wParam & MK_CONTROL) { 1667 short delta = short(HIWORD(wParam)); 1668 if (delta < 0) 1669 makeTextSmaller(0); 1670 else 1671 makeTextLarger(0); 1672 return true; 1673 } 1674 1675 // FIXME: This doesn't fix https://bugs.webkit.org/show_bug.cgi?id=28217. This only fixes https://bugs.webkit.org/show_bug.cgi?id=28203. 1676 HWND focusedWindow = GetFocus(); 1677 if (focusedWindow && focusedWindow != m_viewWindow) { 1678 // Our focus is on a different hwnd, see if it's a PopupMenu and if so, set the focus back on us (which will hide the popup). 1679 WCHAR className[256]; 1680 1681 // Make sure truncation won't affect the comparison. 1682 ASSERT(WTF_ARRAY_LENGTH(className) > wcslen(PopupMenuWin::popupClassName())); 1683 1684 if (GetClassNameW(focusedWindow, className, WTF_ARRAY_LENGTH(className)) && !wcscmp(className, PopupMenuWin::popupClassName())) { 1685 // We don't let the WebView scroll here for two reasons - 1) To match Firefox behavior, 2) If we do scroll, we lose the 1686 // focus ring around the select menu. 1687 SetFocus(m_viewWindow); 1688 return true; 1689 } 1690 } 1691 1692 PlatformWheelEvent wheelEvent(m_viewWindow, wParam, lParam, isMouseHWheel); 1693 Frame* coreFrame = core(m_mainFrame); 1694 if (!coreFrame) 1695 return false; 1696 1697 return coreFrame->eventHandler()->handleWheelEvent(wheelEvent); 1698 } 1699 1700 bool WebView::verticalScroll(WPARAM wParam, LPARAM /*lParam*/) 1701 { 1702 ScrollDirection direction; 1703 ScrollGranularity granularity; 1704 switch (LOWORD(wParam)) { 1705 case SB_LINEDOWN: 1706 granularity = ScrollByLine; 1707 direction = ScrollDown; 1708 break; 1709 case SB_LINEUP: 1710 granularity = ScrollByLine; 1711 direction = ScrollUp; 1712 break; 1713 case SB_PAGEDOWN: 1714 granularity = ScrollByDocument; 1715 direction = ScrollDown; 1716 break; 1717 case SB_PAGEUP: 1718 granularity = ScrollByDocument; 1719 direction = ScrollUp; 1720 break; 1721 default: 1722 return false; 1723 break; 1724 } 1725 1726 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 1727 return frame->eventHandler()->scrollRecursively(direction, granularity); 1728 } 1729 1730 bool WebView::horizontalScroll(WPARAM wParam, LPARAM /*lParam*/) 1731 { 1732 ScrollDirection direction; 1733 ScrollGranularity granularity; 1734 switch (LOWORD(wParam)) { 1735 case SB_LINELEFT: 1736 granularity = ScrollByLine; 1737 direction = ScrollLeft; 1738 break; 1739 case SB_LINERIGHT: 1740 granularity = ScrollByLine; 1741 direction = ScrollRight; 1742 break; 1743 case SB_PAGELEFT: 1744 granularity = ScrollByDocument; 1745 direction = ScrollLeft; 1746 break; 1747 case SB_PAGERIGHT: 1748 granularity = ScrollByDocument; 1749 direction = ScrollRight; 1750 break; 1751 default: 1752 return false; 1753 } 1754 1755 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 1756 return frame->eventHandler()->scrollRecursively(direction, granularity); 1757 } 1758 1759 1760 bool WebView::execCommand(WPARAM wParam, LPARAM /*lParam*/) 1761 { 1762 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 1763 switch (LOWORD(wParam)) { 1764 case SelectAll: 1765 return frame->editor()->command("SelectAll").execute(); 1766 case Undo: 1767 return frame->editor()->command("Undo").execute(); 1768 case Redo: 1769 return frame->editor()->command("Redo").execute(); 1770 } 1771 return false; 1772 } 1773 1774 bool WebView::keyUp(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown) 1775 { 1776 PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformKeyboardEvent::KeyUp, systemKeyDown); 1777 1778 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 1779 m_currentCharacterCode = 0; 1780 1781 return frame->eventHandler()->keyEvent(keyEvent); 1782 } 1783 1784 static const unsigned CtrlKey = 1 << 0; 1785 static const unsigned AltKey = 1 << 1; 1786 static const unsigned ShiftKey = 1 << 2; 1787 1788 1789 struct KeyDownEntry { 1790 unsigned virtualKey; 1791 unsigned modifiers; 1792 const char* name; 1793 }; 1794 1795 struct KeyPressEntry { 1796 unsigned charCode; 1797 unsigned modifiers; 1798 const char* name; 1799 }; 1800 1801 static const KeyDownEntry keyDownEntries[] = { 1802 { VK_LEFT, 0, "MoveLeft" }, 1803 { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" }, 1804 { VK_LEFT, CtrlKey, "MoveWordLeft" }, 1805 { VK_LEFT, CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection" }, 1806 { VK_RIGHT, 0, "MoveRight" }, 1807 { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" }, 1808 { VK_RIGHT, CtrlKey, "MoveWordRight" }, 1809 { VK_RIGHT, CtrlKey | ShiftKey, "MoveWordRightAndModifySelection" }, 1810 { VK_UP, 0, "MoveUp" }, 1811 { VK_UP, ShiftKey, "MoveUpAndModifySelection" }, 1812 { VK_PRIOR, ShiftKey, "MovePageUpAndModifySelection" }, 1813 { VK_DOWN, 0, "MoveDown" }, 1814 { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" }, 1815 { VK_NEXT, ShiftKey, "MovePageDownAndModifySelection" }, 1816 { VK_PRIOR, 0, "MovePageUp" }, 1817 { VK_NEXT, 0, "MovePageDown" }, 1818 { VK_HOME, 0, "MoveToBeginningOfLine" }, 1819 { VK_HOME, ShiftKey, "MoveToBeginningOfLineAndModifySelection" }, 1820 { VK_HOME, CtrlKey, "MoveToBeginningOfDocument" }, 1821 { VK_HOME, CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" }, 1822 1823 { VK_END, 0, "MoveToEndOfLine" }, 1824 { VK_END, ShiftKey, "MoveToEndOfLineAndModifySelection" }, 1825 { VK_END, CtrlKey, "MoveToEndOfDocument" }, 1826 { VK_END, CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection" }, 1827 1828 { VK_BACK, 0, "DeleteBackward" }, 1829 { VK_BACK, ShiftKey, "DeleteBackward" }, 1830 { VK_DELETE, 0, "DeleteForward" }, 1831 { VK_BACK, CtrlKey, "DeleteWordBackward" }, 1832 { VK_DELETE, CtrlKey, "DeleteWordForward" }, 1833 1834 { 'B', CtrlKey, "ToggleBold" }, 1835 { 'I', CtrlKey, "ToggleItalic" }, 1836 1837 { VK_ESCAPE, 0, "Cancel" }, 1838 { VK_OEM_PERIOD, CtrlKey, "Cancel" }, 1839 { VK_TAB, 0, "InsertTab" }, 1840 { VK_TAB, ShiftKey, "InsertBacktab" }, 1841 { VK_RETURN, 0, "InsertNewline" }, 1842 { VK_RETURN, CtrlKey, "InsertNewline" }, 1843 { VK_RETURN, AltKey, "InsertNewline" }, 1844 { VK_RETURN, ShiftKey, "InsertNewline" }, 1845 { VK_RETURN, AltKey | ShiftKey, "InsertNewline" }, 1846 1847 // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled 1848 // in the application or in WebKit. We chose WebKit. 1849 { 'C', CtrlKey, "Copy" }, 1850 { 'V', CtrlKey, "Paste" }, 1851 { 'X', CtrlKey, "Cut" }, 1852 { 'A', CtrlKey, "SelectAll" }, 1853 { VK_INSERT, CtrlKey, "Copy" }, 1854 { VK_DELETE, ShiftKey, "Cut" }, 1855 { VK_INSERT, ShiftKey, "Paste" }, 1856 { 'Z', CtrlKey, "Undo" }, 1857 { 'Z', CtrlKey | ShiftKey, "Redo" }, 1858 }; 1859 1860 static const KeyPressEntry keyPressEntries[] = { 1861 { '\t', 0, "InsertTab" }, 1862 { '\t', ShiftKey, "InsertBacktab" }, 1863 { '\r', 0, "InsertNewline" }, 1864 { '\r', CtrlKey, "InsertNewline" }, 1865 { '\r', AltKey, "InsertNewline" }, 1866 { '\r', ShiftKey, "InsertNewline" }, 1867 { '\r', AltKey | ShiftKey, "InsertNewline" }, 1868 }; 1869 1870 const char* WebView::interpretKeyEvent(const KeyboardEvent* evt) 1871 { 1872 ASSERT(evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent); 1873 1874 static HashMap<int, const char*>* keyDownCommandsMap = 0; 1875 static HashMap<int, const char*>* keyPressCommandsMap = 0; 1876 1877 if (!keyDownCommandsMap) { 1878 keyDownCommandsMap = new HashMap<int, const char*>; 1879 keyPressCommandsMap = new HashMap<int, const char*>; 1880 1881 for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyDownEntries); ++i) 1882 keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name); 1883 1884 for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyPressEntries); ++i) 1885 keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); 1886 } 1887 1888 unsigned modifiers = 0; 1889 if (evt->shiftKey()) 1890 modifiers |= ShiftKey; 1891 if (evt->altKey()) 1892 modifiers |= AltKey; 1893 if (evt->ctrlKey()) 1894 modifiers |= CtrlKey; 1895 1896 if (evt->type() == eventNames().keydownEvent) { 1897 int mapKey = modifiers << 16 | evt->keyCode(); 1898 return mapKey ? keyDownCommandsMap->get(mapKey) : 0; 1899 } 1900 1901 int mapKey = modifiers << 16 | evt->charCode(); 1902 return mapKey ? keyPressCommandsMap->get(mapKey) : 0; 1903 } 1904 1905 bool WebView::handleEditingKeyboardEvent(KeyboardEvent* evt) 1906 { 1907 Node* node = evt->target()->toNode(); 1908 ASSERT(node); 1909 Frame* frame = node->document()->frame(); 1910 ASSERT(frame); 1911 1912 const PlatformKeyboardEvent* keyEvent = evt->keyEvent(); 1913 if (!keyEvent || keyEvent->isSystemKey()) // do not treat this as text input if it's a system key event 1914 return false; 1915 1916 Editor::Command command = frame->editor()->command(interpretKeyEvent(evt)); 1917 1918 if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) { 1919 // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated, 1920 // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated 1921 // (e.g. Tab that inserts a Tab character, or Enter). 1922 return !command.isTextInsertion() && command.execute(evt); 1923 } 1924 1925 if (command.execute(evt)) 1926 return true; 1927 1928 // Don't insert null or control characters as they can result in unexpected behaviour 1929 if (evt->charCode() < ' ') 1930 return false; 1931 1932 return frame->editor()->insertText(evt->keyEvent()->text(), evt); 1933 } 1934 1935 bool WebView::keyDown(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown) 1936 { 1937 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 1938 1939 PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformKeyboardEvent::RawKeyDown, systemKeyDown); 1940 bool handled = frame->eventHandler()->keyEvent(keyEvent); 1941 1942 // These events cannot be canceled, and we have no default handling for them. 1943 // FIXME: match IE list more closely, see <http://msdn2.microsoft.com/en-us/library/ms536938.aspx>. 1944 if (systemKeyDown && virtualKeyCode != VK_RETURN) 1945 return false; 1946 1947 if (handled) { 1948 // FIXME: remove WM_UNICHAR, too 1949 MSG msg; 1950 // WM_SYSCHAR events should not be removed, because access keys are implemented in WebCore in WM_SYSCHAR handler. 1951 if (!systemKeyDown) 1952 ::PeekMessage(&msg, m_viewWindow, WM_CHAR, WM_CHAR, PM_REMOVE); 1953 return true; 1954 } 1955 1956 // We need to handle back/forward using either Ctrl+Left/Right Arrow keys. 1957 // FIXME: This logic should probably be in EventHandler::defaultArrowEventHandler(). 1958 // FIXME: Should check that other modifiers aren't pressed. 1959 if (virtualKeyCode == VK_RIGHT && keyEvent.ctrlKey()) 1960 return m_page->goForward(); 1961 if (virtualKeyCode == VK_LEFT && keyEvent.ctrlKey()) 1962 return m_page->goBack(); 1963 1964 // Need to scroll the page if the arrow keys, pgup/dn, or home/end are hit. 1965 ScrollDirection direction; 1966 ScrollGranularity granularity; 1967 switch (virtualKeyCode) { 1968 case VK_LEFT: 1969 granularity = ScrollByLine; 1970 direction = ScrollLeft; 1971 break; 1972 case VK_RIGHT: 1973 granularity = ScrollByLine; 1974 direction = ScrollRight; 1975 break; 1976 case VK_UP: 1977 granularity = ScrollByLine; 1978 direction = ScrollUp; 1979 break; 1980 case VK_DOWN: 1981 granularity = ScrollByLine; 1982 direction = ScrollDown; 1983 break; 1984 case VK_HOME: 1985 granularity = ScrollByDocument; 1986 direction = ScrollUp; 1987 break; 1988 case VK_END: 1989 granularity = ScrollByDocument; 1990 direction = ScrollDown; 1991 break; 1992 case VK_PRIOR: 1993 granularity = ScrollByPage; 1994 direction = ScrollUp; 1995 break; 1996 case VK_NEXT: 1997 granularity = ScrollByPage; 1998 direction = ScrollDown; 1999 break; 2000 default: 2001 return false; 2002 } 2003 2004 return frame->eventHandler()->scrollRecursively(direction, granularity); 2005 } 2006 2007 bool WebView::keyPress(WPARAM charCode, LPARAM keyData, bool systemKeyDown) 2008 { 2009 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 2010 2011 PlatformKeyboardEvent keyEvent(m_viewWindow, charCode, keyData, PlatformKeyboardEvent::Char, systemKeyDown); 2012 // IE does not dispatch keypress event for WM_SYSCHAR. 2013 if (systemKeyDown) 2014 return frame->eventHandler()->handleAccessKey(keyEvent); 2015 return frame->eventHandler()->keyEvent(keyEvent); 2016 } 2017 2018 void WebView::setIsBeingDestroyed() 2019 { 2020 m_isBeingDestroyed = true; 2021 2022 // Remove our this pointer from the window so we won't try to handle any more window messages. 2023 // See <http://webkit.org/b/55054>. 2024 ::SetWindowLongPtrW(m_viewWindow, 0, 0); 2025 } 2026 2027 bool WebView::registerWebViewWindowClass() 2028 { 2029 static bool haveRegisteredWindowClass = false; 2030 if (haveRegisteredWindowClass) 2031 return true; 2032 2033 haveRegisteredWindowClass = true; 2034 2035 WNDCLASSEX wcex; 2036 2037 wcex.cbSize = sizeof(WNDCLASSEX); 2038 2039 wcex.style = CS_DBLCLKS; 2040 wcex.lpfnWndProc = WebViewWndProc; 2041 wcex.cbClsExtra = 0; 2042 wcex.cbWndExtra = 4; // 4 bytes for the IWebView pointer 2043 wcex.hInstance = gInstance; 2044 wcex.hIcon = 0; 2045 wcex.hCursor = ::LoadCursor(0, IDC_ARROW); 2046 wcex.hbrBackground = 0; 2047 wcex.lpszMenuName = 0; 2048 wcex.lpszClassName = kWebViewWindowClassName; 2049 wcex.hIconSm = 0; 2050 2051 return !!RegisterClassEx(&wcex); 2052 } 2053 2054 static HWND findTopLevelParent(HWND window) 2055 { 2056 if (!window) 2057 return 0; 2058 2059 HWND current = window; 2060 for (HWND parent = GetParent(current); current; current = parent, parent = GetParent(parent)) 2061 if (!parent || !(GetWindowLongPtr(current, GWL_STYLE) & (WS_POPUP | WS_CHILD))) 2062 return current; 2063 ASSERT_NOT_REACHED(); 2064 return 0; 2065 } 2066 2067 LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 2068 { 2069 LRESULT lResult = 0; 2070 LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0); 2071 WebView* webView = reinterpret_cast<WebView*>(longPtr); 2072 WebFrame* mainFrameImpl = webView ? webView->topLevelFrame() : 0; 2073 if (!mainFrameImpl) 2074 return DefWindowProc(hWnd, message, wParam, lParam); 2075 2076 // We shouldn't be trying to handle any window messages after WM_DESTROY. 2077 // See <http://webkit.org/b/55054>. 2078 ASSERT(!webView->isBeingDestroyed()); 2079 2080 // hold a ref, since the WebView could go away in an event handler. 2081 COMPtr<WebView> protector(webView); 2082 ASSERT(webView); 2083 2084 // Windows Media Player has a modal message loop that will deliver messages 2085 // to us at inappropriate times and we will crash if we handle them when 2086 // they are delivered. We repost paint messages so that we eventually get 2087 // a chance to paint once the modal loop has exited, but other messages 2088 // aren't safe to repost, so we just drop them. 2089 if (PluginView::isCallingPlugin()) { 2090 if (message == WM_PAINT) 2091 PostMessage(hWnd, message, wParam, lParam); 2092 return 0; 2093 } 2094 2095 bool handled = true; 2096 2097 switch (message) { 2098 case WM_PAINT: { 2099 webView->paint(0, 0); 2100 break; 2101 } 2102 case WM_PRINTCLIENT: 2103 webView->paint((HDC)wParam, lParam); 2104 break; 2105 case WM_DESTROY: 2106 webView->setIsBeingDestroyed(); 2107 webView->close(); 2108 break; 2109 case WM_GESTURENOTIFY: 2110 handled = webView->gestureNotify(wParam, lParam); 2111 break; 2112 case WM_GESTURE: 2113 handled = webView->gesture(wParam, lParam); 2114 break; 2115 case WM_MOUSEMOVE: 2116 case WM_LBUTTONDOWN: 2117 case WM_MBUTTONDOWN: 2118 case WM_RBUTTONDOWN: 2119 case WM_LBUTTONDBLCLK: 2120 case WM_MBUTTONDBLCLK: 2121 case WM_RBUTTONDBLCLK: 2122 case WM_LBUTTONUP: 2123 case WM_MBUTTONUP: 2124 case WM_RBUTTONUP: 2125 case WM_MOUSELEAVE: 2126 case WM_CANCELMODE: 2127 if (Frame* coreFrame = core(mainFrameImpl)) 2128 if (coreFrame->view()->didFirstLayout()) 2129 handled = webView->handleMouseEvent(message, wParam, lParam); 2130 break; 2131 case WM_MOUSEWHEEL: 2132 case WM_VISTA_MOUSEHWHEEL: 2133 if (Frame* coreFrame = core(mainFrameImpl)) 2134 if (coreFrame->view()->didFirstLayout()) 2135 handled = webView->mouseWheel(wParam, lParam, message == WM_VISTA_MOUSEHWHEEL); 2136 break; 2137 case WM_SYSKEYDOWN: 2138 handled = webView->keyDown(wParam, lParam, true); 2139 break; 2140 case WM_KEYDOWN: 2141 handled = webView->keyDown(wParam, lParam); 2142 break; 2143 case WM_SYSKEYUP: 2144 handled = webView->keyUp(wParam, lParam, true); 2145 break; 2146 case WM_KEYUP: 2147 handled = webView->keyUp(wParam, lParam); 2148 break; 2149 case WM_SYSCHAR: 2150 handled = webView->keyPress(wParam, lParam, true); 2151 break; 2152 case WM_CHAR: 2153 handled = webView->keyPress(wParam, lParam); 2154 break; 2155 // FIXME: We need to check WM_UNICHAR to support supplementary characters (that don't fit in 16 bits). 2156 case WM_SIZE: 2157 if (lParam != 0) 2158 webView->sizeChanged(IntSize(LOWORD(lParam), HIWORD(lParam))); 2159 break; 2160 case WM_SHOWWINDOW: 2161 lResult = DefWindowProc(hWnd, message, wParam, lParam); 2162 if (wParam == 0) { 2163 // The window is being hidden (e.g., because we switched tabs). 2164 // Null out our backing store. 2165 webView->deleteBackingStore(); 2166 } 2167 break; 2168 case WM_SETFOCUS: { 2169 COMPtr<IWebUIDelegate> uiDelegate; 2170 COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate; 2171 if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate 2172 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate) 2173 uiDelegatePrivate->webViewReceivedFocus(webView); 2174 2175 FocusController* focusController = webView->page()->focusController(); 2176 if (Frame* frame = focusController->focusedFrame()) { 2177 // Send focus events unless the previously focused window is a 2178 // child of ours (for example a plugin). 2179 if (!IsChild(hWnd, reinterpret_cast<HWND>(wParam))) 2180 focusController->setFocused(true); 2181 } else 2182 focusController->setFocused(true); 2183 break; 2184 } 2185 case WM_KILLFOCUS: { 2186 COMPtr<IWebUIDelegate> uiDelegate; 2187 COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate; 2188 HWND newFocusWnd = reinterpret_cast<HWND>(wParam); 2189 if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate 2190 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate) 2191 uiDelegatePrivate->webViewLostFocus(webView, (OLE_HANDLE)(ULONG64)newFocusWnd); 2192 2193 FocusController* focusController = webView->page()->focusController(); 2194 Frame* frame = focusController->focusedOrMainFrame(); 2195 webView->resetIME(frame); 2196 // Send blur events unless we're losing focus to a child of ours. 2197 if (!IsChild(hWnd, newFocusWnd)) 2198 focusController->setFocused(false); 2199 2200 // If we are pan-scrolling when we lose focus, stop the pan scrolling. 2201 frame->eventHandler()->stopAutoscrollTimer(); 2202 2203 break; 2204 } 2205 case WM_WINDOWPOSCHANGED: 2206 if (reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW) 2207 webView->updateActiveStateSoon(); 2208 handled = false; 2209 break; 2210 case WM_CUT: 2211 webView->cut(0); 2212 break; 2213 case WM_COPY: 2214 webView->copy(0); 2215 break; 2216 case WM_PASTE: 2217 webView->paste(0); 2218 break; 2219 case WM_CLEAR: 2220 webView->delete_(0); 2221 break; 2222 case WM_COMMAND: 2223 if (HIWORD(wParam)) 2224 handled = webView->execCommand(wParam, lParam); 2225 else // If the high word of wParam is 0, the message is from a menu 2226 webView->performContextMenuAction(wParam, lParam, false); 2227 break; 2228 case WM_MENUCOMMAND: 2229 webView->performContextMenuAction(wParam, lParam, true); 2230 break; 2231 case WM_CONTEXTMENU: 2232 handled = webView->handleContextMenuEvent(wParam, lParam); 2233 break; 2234 case WM_INITMENUPOPUP: 2235 handled = webView->onInitMenuPopup(wParam, lParam); 2236 break; 2237 case WM_MEASUREITEM: 2238 handled = webView->onMeasureItem(wParam, lParam); 2239 break; 2240 case WM_DRAWITEM: 2241 handled = webView->onDrawItem(wParam, lParam); 2242 break; 2243 case WM_UNINITMENUPOPUP: 2244 handled = webView->onUninitMenuPopup(wParam, lParam); 2245 break; 2246 case WM_XP_THEMECHANGED: 2247 if (Frame* coreFrame = core(mainFrameImpl)) { 2248 webView->deleteBackingStore(); 2249 coreFrame->page()->theme()->themeChanged(); 2250 ScrollbarTheme::nativeTheme()->themeChanged(); 2251 RECT windowRect; 2252 ::GetClientRect(hWnd, &windowRect); 2253 ::InvalidateRect(hWnd, &windowRect, false); 2254 #if USE(ACCELERATED_COMPOSITING) 2255 if (webView->isAcceleratedCompositing()) 2256 webView->m_backingLayer->setNeedsDisplay(); 2257 #endif 2258 } 2259 break; 2260 case WM_MOUSEACTIVATE: 2261 webView->setMouseActivated(true); 2262 handled = false; 2263 break; 2264 case WM_GETDLGCODE: { 2265 COMPtr<IWebUIDelegate> uiDelegate; 2266 COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate; 2267 LONG_PTR dlgCode = 0; 2268 UINT keyCode = 0; 2269 if (lParam) { 2270 LPMSG lpMsg = (LPMSG)lParam; 2271 if (lpMsg->message == WM_KEYDOWN) 2272 keyCode = (UINT) lpMsg->wParam; 2273 } 2274 if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate 2275 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate 2276 && SUCCEEDED(uiDelegatePrivate->webViewGetDlgCode(webView, keyCode, &dlgCode))) 2277 return dlgCode; 2278 handled = false; 2279 break; 2280 } 2281 case WM_GETOBJECT: 2282 handled = webView->onGetObject(wParam, lParam, lResult); 2283 break; 2284 case WM_IME_STARTCOMPOSITION: 2285 handled = webView->onIMEStartComposition(); 2286 break; 2287 case WM_IME_REQUEST: 2288 lResult = webView->onIMERequest(wParam, lParam); 2289 break; 2290 case WM_IME_COMPOSITION: 2291 handled = webView->onIMEComposition(lParam); 2292 break; 2293 case WM_IME_ENDCOMPOSITION: 2294 handled = webView->onIMEEndComposition(); 2295 break; 2296 case WM_IME_CHAR: 2297 handled = webView->onIMEChar(wParam, lParam); 2298 break; 2299 case WM_IME_NOTIFY: 2300 handled = webView->onIMENotify(wParam, lParam, &lResult); 2301 break; 2302 case WM_IME_SELECT: 2303 handled = webView->onIMESelect(wParam, lParam); 2304 break; 2305 case WM_IME_SETCONTEXT: 2306 handled = webView->onIMESetContext(wParam, lParam); 2307 break; 2308 case WM_TIMER: 2309 switch (wParam) { 2310 case UpdateActiveStateTimer: 2311 KillTimer(hWnd, UpdateActiveStateTimer); 2312 webView->updateActiveState(); 2313 break; 2314 case DeleteBackingStoreTimer: 2315 webView->deleteBackingStore(); 2316 break; 2317 } 2318 break; 2319 case WM_SETCURSOR: 2320 handled = ::SetCursor(webView->m_lastSetCursor); 2321 break; 2322 case WM_VSCROLL: 2323 handled = webView->verticalScroll(wParam, lParam); 2324 break; 2325 case WM_HSCROLL: 2326 handled = webView->horizontalScroll(wParam, lParam); 2327 break; 2328 default: 2329 handled = false; 2330 break; 2331 } 2332 2333 if (!handled) 2334 lResult = DefWindowProc(hWnd, message, wParam, lParam); 2335 2336 // Let the client know whether we consider this message handled. 2337 return (message == WM_KEYDOWN || message == WM_SYSKEYDOWN || message == WM_KEYUP || message == WM_SYSKEYUP) ? !handled : lResult; 2338 } 2339 2340 bool WebView::developerExtrasEnabled() const 2341 { 2342 if (m_preferences->developerExtrasDisabledByOverride()) 2343 return false; 2344 2345 #ifdef NDEBUG 2346 BOOL enabled; 2347 return SUCCEEDED(m_preferences->developerExtrasEnabled(&enabled)) && enabled; 2348 #else 2349 return true; 2350 #endif 2351 } 2352 2353 static String webKitVersionString() 2354 { 2355 LPWSTR buildNumberStringPtr; 2356 if (!::LoadStringW(gInstance, BUILD_NUMBER, reinterpret_cast<LPWSTR>(&buildNumberStringPtr), 0) || !buildNumberStringPtr) 2357 return "534+"; 2358 2359 return buildNumberStringPtr; 2360 } 2361 2362 const String& WebView::userAgentForKURL(const KURL&) 2363 { 2364 if (m_userAgentOverridden) 2365 return m_userAgentCustom; 2366 2367 if (!m_userAgentStandard.length()) 2368 m_userAgentStandard = WebView::standardUserAgentWithApplicationName(m_applicationName); 2369 return m_userAgentStandard; 2370 } 2371 2372 // IUnknown ------------------------------------------------------------------- 2373 2374 HRESULT STDMETHODCALLTYPE WebView::QueryInterface(REFIID riid, void** ppvObject) 2375 { 2376 *ppvObject = 0; 2377 if (IsEqualGUID(riid, CLSID_WebView)) 2378 *ppvObject = this; 2379 else if (IsEqualGUID(riid, IID_IUnknown)) 2380 *ppvObject = static_cast<IWebView*>(this); 2381 else if (IsEqualGUID(riid, IID_IWebView)) 2382 *ppvObject = static_cast<IWebView*>(this); 2383 else if (IsEqualGUID(riid, IID_IWebViewPrivate)) 2384 *ppvObject = static_cast<IWebViewPrivate*>(this); 2385 else if (IsEqualGUID(riid, IID_IWebIBActions)) 2386 *ppvObject = static_cast<IWebIBActions*>(this); 2387 else if (IsEqualGUID(riid, IID_IWebViewCSS)) 2388 *ppvObject = static_cast<IWebViewCSS*>(this); 2389 else if (IsEqualGUID(riid, IID_IWebViewEditing)) 2390 *ppvObject = static_cast<IWebViewEditing*>(this); 2391 else if (IsEqualGUID(riid, IID_IWebViewUndoableEditing)) 2392 *ppvObject = static_cast<IWebViewUndoableEditing*>(this); 2393 else if (IsEqualGUID(riid, IID_IWebViewEditingActions)) 2394 *ppvObject = static_cast<IWebViewEditingActions*>(this); 2395 else if (IsEqualGUID(riid, IID_IWebNotificationObserver)) 2396 *ppvObject = static_cast<IWebNotificationObserver*>(this); 2397 else if (IsEqualGUID(riid, IID_IDropTarget)) 2398 *ppvObject = static_cast<IDropTarget*>(this); 2399 else 2400 return E_NOINTERFACE; 2401 2402 AddRef(); 2403 return S_OK; 2404 } 2405 2406 ULONG STDMETHODCALLTYPE WebView::AddRef(void) 2407 { 2408 ASSERT(!m_deletionHasBegun); 2409 return ++m_refCount; 2410 } 2411 2412 ULONG STDMETHODCALLTYPE WebView::Release(void) 2413 { 2414 ASSERT(!m_deletionHasBegun); 2415 2416 if (m_refCount == 1) { 2417 // Call close() now so that clients don't have to. (It's harmless to call close() multiple 2418 // times.) We do this here instead of in our destructor because close() can cause AddRef() 2419 // and Release() to be called, and if that happened in our destructor we would be destroyed 2420 // more than once. 2421 close(); 2422 } 2423 2424 ULONG newRef = --m_refCount; 2425 if (!newRef) { 2426 #if !ASSERT_DISABLED 2427 m_deletionHasBegun = true; 2428 #endif 2429 delete(this); 2430 } 2431 2432 return newRef; 2433 } 2434 2435 // IWebView -------------------------------------------------------------------- 2436 2437 HRESULT STDMETHODCALLTYPE WebView::canShowMIMEType( 2438 /* [in] */ BSTR mimeType, 2439 /* [retval][out] */ BOOL* canShow) 2440 { 2441 String mimeTypeStr(mimeType, SysStringLen(mimeType)); 2442 2443 if (!canShow) 2444 return E_POINTER; 2445 2446 *canShow = MIMETypeRegistry::isSupportedImageMIMEType(mimeTypeStr) || 2447 MIMETypeRegistry::isSupportedNonImageMIMEType(mimeTypeStr) || 2448 (m_page && m_page->pluginData() && m_page->pluginData()->supportsMimeType(mimeTypeStr)) || 2449 shouldUseEmbeddedView(mimeTypeStr); 2450 2451 return S_OK; 2452 } 2453 2454 HRESULT STDMETHODCALLTYPE WebView::canShowMIMETypeAsHTML( 2455 /* [in] */ BSTR /*mimeType*/, 2456 /* [retval][out] */ BOOL* canShow) 2457 { 2458 // FIXME 2459 *canShow = TRUE; 2460 return S_OK; 2461 } 2462 2463 HRESULT STDMETHODCALLTYPE WebView::MIMETypesShownAsHTML( 2464 /* [retval][out] */ IEnumVARIANT** /*enumVariant*/) 2465 { 2466 ASSERT_NOT_REACHED(); 2467 return E_NOTIMPL; 2468 } 2469 2470 HRESULT STDMETHODCALLTYPE WebView::setMIMETypesShownAsHTML( 2471 /* [size_is][in] */ BSTR* /*mimeTypes*/, 2472 /* [in] */ int /*cMimeTypes*/) 2473 { 2474 ASSERT_NOT_REACHED(); 2475 return E_NOTIMPL; 2476 } 2477 2478 HRESULT STDMETHODCALLTYPE WebView::URLFromPasteboard( 2479 /* [in] */ IDataObject* /*pasteboard*/, 2480 /* [retval][out] */ BSTR* /*url*/) 2481 { 2482 ASSERT_NOT_REACHED(); 2483 return E_NOTIMPL; 2484 } 2485 2486 HRESULT STDMETHODCALLTYPE WebView::URLTitleFromPasteboard( 2487 /* [in] */ IDataObject* /*pasteboard*/, 2488 /* [retval][out] */ BSTR* /*urlTitle*/) 2489 { 2490 ASSERT_NOT_REACHED(); 2491 return E_NOTIMPL; 2492 } 2493 2494 static void WebKitSetApplicationCachePathIfNecessary() 2495 { 2496 static bool initialized = false; 2497 if (initialized) 2498 return; 2499 2500 String path = localUserSpecificStorageDirectory(); 2501 if (!path.isNull()) 2502 cacheStorage().setCacheDirectory(path); 2503 2504 initialized = true; 2505 } 2506 2507 bool WebView::shouldInitializeTrackPointHack() 2508 { 2509 static bool shouldCreateScrollbars; 2510 static bool hasRunTrackPointCheck; 2511 2512 if (hasRunTrackPointCheck) 2513 return shouldCreateScrollbars; 2514 2515 hasRunTrackPointCheck = true; 2516 const WCHAR trackPointKeys[][50] = { L"Software\\Lenovo\\TrackPoint", 2517 L"Software\\Lenovo\\UltraNav", 2518 L"Software\\Alps\\Apoint\\TrackPoint", 2519 L"Software\\Synaptics\\SynTPEnh\\UltraNavUSB", 2520 L"Software\\Synaptics\\SynTPEnh\\UltraNavPS2" }; 2521 2522 for (int i = 0; i < 5; ++i) { 2523 HKEY trackPointKey; 2524 int readKeyResult = ::RegOpenKeyExW(HKEY_CURRENT_USER, trackPointKeys[i], 0, KEY_READ, &trackPointKey); 2525 ::RegCloseKey(trackPointKey); 2526 if (readKeyResult == ERROR_SUCCESS) { 2527 shouldCreateScrollbars = true; 2528 return shouldCreateScrollbars; 2529 } 2530 } 2531 2532 return shouldCreateScrollbars; 2533 } 2534 2535 HRESULT STDMETHODCALLTYPE WebView::initWithFrame( 2536 /* [in] */ RECT frame, 2537 /* [in] */ BSTR frameName, 2538 /* [in] */ BSTR groupName) 2539 { 2540 HRESULT hr = S_OK; 2541 2542 if (m_viewWindow) 2543 return E_FAIL; 2544 2545 registerWebViewWindowClass(); 2546 2547 m_viewWindow = CreateWindowEx(0, kWebViewWindowClassName, 0, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 2548 frame.left, frame.top, frame.right - frame.left, frame.bottom - frame.top, m_hostWindow ? m_hostWindow : HWND_MESSAGE, 0, gInstance, 0); 2549 ASSERT(::IsWindow(m_viewWindow)); 2550 2551 if (shouldInitializeTrackPointHack()) { 2552 // If we detected a registry key belonging to a TrackPoint driver, then create fake trackpoint 2553 // scrollbars, so the WebView will receive WM_VSCROLL and WM_HSCROLL messages. We create one 2554 // vertical scrollbar and one horizontal to allow for receiving both types of messages. 2555 ::CreateWindowW(L"SCROLLBAR", L"FAKETRACKPOINTHSCROLLBAR", WS_CHILD | WS_VISIBLE | SBS_HORZ, 0, 0, 0, 0, m_viewWindow, 0, gInstance, 0); 2556 ::CreateWindowW(L"SCROLLBAR", L"FAKETRACKPOINTVSCROLLBAR", WS_CHILD | WS_VISIBLE | SBS_VERT, 0, 0, 0, 0, m_viewWindow, 0, gInstance, 0); 2557 } 2558 2559 hr = registerDragDrop(); 2560 if (FAILED(hr)) 2561 return hr; 2562 2563 WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences(); 2564 sharedPreferences->willAddToWebView(); 2565 m_preferences = sharedPreferences; 2566 2567 static bool didOneTimeInitialization; 2568 if (!didOneTimeInitialization) { 2569 InitializeLoggingChannelsIfNecessary(); 2570 #if ENABLE(DATABASE) 2571 WebKitInitializeWebDatabasesIfNecessary(); 2572 #endif 2573 WebKitSetApplicationCachePathIfNecessary(); 2574 WebPlatformStrategies::initialize(); 2575 Settings::setDefaultMinDOMTimerInterval(0.004); 2576 2577 didOneTimeInitialization = true; 2578 } 2579 2580 #if USE(SAFARI_THEME) 2581 BOOL shouldPaintNativeControls; 2582 if (SUCCEEDED(m_preferences->shouldPaintNativeControls(&shouldPaintNativeControls))) 2583 Settings::setShouldPaintNativeControls(shouldPaintNativeControls); 2584 #endif 2585 2586 BOOL useHighResolutionTimer; 2587 if (SUCCEEDED(m_preferences->shouldUseHighResolutionTimers(&useHighResolutionTimer))) 2588 Settings::setShouldUseHighResolutionTimers(useHighResolutionTimer); 2589 2590 Page::PageClients pageClients; 2591 pageClients.chromeClient = new WebChromeClient(this); 2592 pageClients.contextMenuClient = new WebContextMenuClient(this); 2593 pageClients.editorClient = new WebEditorClient(this); 2594 pageClients.dragClient = new WebDragClient(this); 2595 pageClients.inspectorClient = new WebInspectorClient(this); 2596 pageClients.pluginHalterClient = new WebPluginHalterClient(this); 2597 #if ENABLE(CLIENT_BASED_GEOLOCATION) 2598 pageClients.geolocationClient = new WebGeolocationClient(this); 2599 #endif 2600 m_page = new Page(pageClients); 2601 2602 BSTR localStoragePath; 2603 if (SUCCEEDED(m_preferences->localStorageDatabasePath(&localStoragePath))) { 2604 m_page->settings()->setLocalStorageDatabasePath(String(localStoragePath, SysStringLen(localStoragePath))); 2605 SysFreeString(localStoragePath); 2606 } 2607 2608 if (m_uiDelegate) { 2609 BSTR path; 2610 if (SUCCEEDED(m_uiDelegate->ftpDirectoryTemplatePath(this, &path))) { 2611 m_page->settings()->setFTPDirectoryTemplatePath(String(path, SysStringLen(path))); 2612 SysFreeString(path); 2613 } 2614 } 2615 2616 WebFrame* webFrame = WebFrame::createInstance(); 2617 RefPtr<Frame> coreFrame = webFrame->init(this, m_page, 0); 2618 m_mainFrame = webFrame; 2619 webFrame->Release(); // The WebFrame is owned by the Frame, so release our reference to it. 2620 2621 coreFrame->tree()->setName(String(frameName, SysStringLen(frameName))); 2622 coreFrame->init(); 2623 setGroupName(groupName); 2624 2625 addToAllWebViewsSet(); 2626 2627 #pragma warning(suppress: 4244) 2628 SetWindowLongPtr(m_viewWindow, 0, (LONG_PTR)this); 2629 ShowWindow(m_viewWindow, SW_SHOW); 2630 2631 initializeToolTipWindow(); 2632 windowAncestryDidChange(); 2633 2634 IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal(); 2635 notifyCenter->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get())); 2636 m_preferences->postPreferencesChangesNotification(); 2637 2638 setSmartInsertDeleteEnabled(TRUE); 2639 return hr; 2640 } 2641 2642 static bool initCommonControls() 2643 { 2644 static bool haveInitialized = false; 2645 if (haveInitialized) 2646 return true; 2647 2648 INITCOMMONCONTROLSEX init; 2649 init.dwSize = sizeof(init); 2650 init.dwICC = ICC_TREEVIEW_CLASSES; 2651 haveInitialized = !!::InitCommonControlsEx(&init); 2652 return haveInitialized; 2653 } 2654 2655 void WebView::initializeToolTipWindow() 2656 { 2657 if (!initCommonControls()) 2658 return; 2659 2660 m_toolTipHwnd = CreateWindowEx(WS_EX_TRANSPARENT, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, 2661 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 2662 m_viewWindow, 0, 0, 0); 2663 if (!m_toolTipHwnd) 2664 return; 2665 2666 TOOLINFO info = {0}; 2667 info.cbSize = sizeof(info); 2668 info.uFlags = TTF_IDISHWND | TTF_SUBCLASS ; 2669 info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow); 2670 2671 ::SendMessage(m_toolTipHwnd, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info)); 2672 ::SendMessage(m_toolTipHwnd, TTM_SETMAXTIPWIDTH, 0, maxToolTipWidth); 2673 2674 ::SetWindowPos(m_toolTipHwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 2675 } 2676 2677 void WebView::setToolTip(const String& toolTip) 2678 { 2679 if (!m_toolTipHwnd) 2680 return; 2681 2682 if (toolTip == m_toolTip) 2683 return; 2684 2685 m_toolTip = toolTip; 2686 2687 if (!m_toolTip.isEmpty()) { 2688 TOOLINFO info = {0}; 2689 info.cbSize = sizeof(info); 2690 info.uFlags = TTF_IDISHWND; 2691 info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow); 2692 info.lpszText = const_cast<UChar*>(m_toolTip.charactersWithNullTermination()); 2693 ::SendMessage(m_toolTipHwnd, TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info)); 2694 } 2695 2696 ::SendMessage(m_toolTipHwnd, TTM_ACTIVATE, !m_toolTip.isEmpty(), 0); 2697 } 2698 2699 HRESULT WebView::notifyDidAddIcon(IWebNotification* notification) 2700 { 2701 COMPtr<IPropertyBag> propertyBag; 2702 HRESULT hr = notification->userInfo(&propertyBag); 2703 if (FAILED(hr)) 2704 return hr; 2705 if (!propertyBag) 2706 return E_FAIL; 2707 2708 COMPtr<CFDictionaryPropertyBag> dictionaryPropertyBag; 2709 hr = propertyBag->QueryInterface(&dictionaryPropertyBag); 2710 if (FAILED(hr)) 2711 return hr; 2712 2713 CFDictionaryRef dictionary = dictionaryPropertyBag->dictionary(); 2714 if (!dictionary) 2715 return E_FAIL; 2716 2717 CFTypeRef value = CFDictionaryGetValue(dictionary, WebIconDatabase::iconDatabaseNotificationUserInfoURLKey()); 2718 if (!value) 2719 return E_FAIL; 2720 if (CFGetTypeID(value) != CFStringGetTypeID()) 2721 return E_FAIL; 2722 2723 String mainFrameURL; 2724 if (m_mainFrame) 2725 mainFrameURL = m_mainFrame->url().string(); 2726 2727 if (!mainFrameURL.isEmpty() && mainFrameURL == String((CFStringRef)value)) 2728 dispatchDidReceiveIconFromWebFrame(m_mainFrame); 2729 2730 return hr; 2731 } 2732 2733 void WebView::registerForIconNotification(bool listen) 2734 { 2735 IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal(); 2736 if (listen) 2737 nc->addObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0); 2738 else 2739 nc->removeObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0); 2740 } 2741 2742 void WebView::dispatchDidReceiveIconFromWebFrame(WebFrame* frame) 2743 { 2744 registerForIconNotification(false); 2745 2746 if (m_frameLoadDelegate) 2747 // FIXME: <rdar://problem/5491010> - Pass in the right HBITMAP. 2748 m_frameLoadDelegate->didReceiveIcon(this, 0, frame); 2749 } 2750 2751 HRESULT STDMETHODCALLTYPE WebView::setUIDelegate( 2752 /* [in] */ IWebUIDelegate* d) 2753 { 2754 m_uiDelegate = d; 2755 2756 if (m_uiDelegatePrivate) 2757 m_uiDelegatePrivate = 0; 2758 2759 if (d) { 2760 if (FAILED(d->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&m_uiDelegatePrivate))) 2761 m_uiDelegatePrivate = 0; 2762 } 2763 2764 return S_OK; 2765 } 2766 2767 HRESULT STDMETHODCALLTYPE WebView::uiDelegate( 2768 /* [out][retval] */ IWebUIDelegate** d) 2769 { 2770 if (!m_uiDelegate) 2771 return E_FAIL; 2772 2773 return m_uiDelegate.copyRefTo(d); 2774 } 2775 2776 HRESULT STDMETHODCALLTYPE WebView::setResourceLoadDelegate( 2777 /* [in] */ IWebResourceLoadDelegate* d) 2778 { 2779 m_resourceLoadDelegate = d; 2780 return S_OK; 2781 } 2782 2783 HRESULT STDMETHODCALLTYPE WebView::resourceLoadDelegate( 2784 /* [out][retval] */ IWebResourceLoadDelegate** d) 2785 { 2786 if (!m_resourceLoadDelegate) 2787 return E_FAIL; 2788 2789 return m_resourceLoadDelegate.copyRefTo(d); 2790 } 2791 2792 HRESULT STDMETHODCALLTYPE WebView::setDownloadDelegate( 2793 /* [in] */ IWebDownloadDelegate* d) 2794 { 2795 m_downloadDelegate = d; 2796 return S_OK; 2797 } 2798 2799 HRESULT STDMETHODCALLTYPE WebView::downloadDelegate( 2800 /* [out][retval] */ IWebDownloadDelegate** d) 2801 { 2802 if (!m_downloadDelegate) 2803 return E_FAIL; 2804 2805 return m_downloadDelegate.copyRefTo(d); 2806 } 2807 2808 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegate( 2809 /* [in] */ IWebFrameLoadDelegate* d) 2810 { 2811 m_frameLoadDelegate = d; 2812 return S_OK; 2813 } 2814 2815 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegate( 2816 /* [out][retval] */ IWebFrameLoadDelegate** d) 2817 { 2818 if (!m_frameLoadDelegate) 2819 return E_FAIL; 2820 2821 return m_frameLoadDelegate.copyRefTo(d); 2822 } 2823 2824 HRESULT STDMETHODCALLTYPE WebView::setPolicyDelegate( 2825 /* [in] */ IWebPolicyDelegate* d) 2826 { 2827 m_policyDelegate = d; 2828 return S_OK; 2829 } 2830 2831 HRESULT STDMETHODCALLTYPE WebView::policyDelegate( 2832 /* [out][retval] */ IWebPolicyDelegate** d) 2833 { 2834 if (!m_policyDelegate) 2835 return E_FAIL; 2836 return m_policyDelegate.copyRefTo(d); 2837 } 2838 2839 HRESULT STDMETHODCALLTYPE WebView::mainFrame( 2840 /* [out][retval] */ IWebFrame** frame) 2841 { 2842 if (!frame) { 2843 ASSERT_NOT_REACHED(); 2844 return E_POINTER; 2845 } 2846 2847 *frame = m_mainFrame; 2848 if (!m_mainFrame) 2849 return E_FAIL; 2850 2851 m_mainFrame->AddRef(); 2852 return S_OK; 2853 } 2854 2855 HRESULT STDMETHODCALLTYPE WebView::focusedFrame( 2856 /* [out][retval] */ IWebFrame** frame) 2857 { 2858 if (!frame) { 2859 ASSERT_NOT_REACHED(); 2860 return E_POINTER; 2861 } 2862 2863 *frame = 0; 2864 Frame* f = m_page->focusController()->focusedFrame(); 2865 if (!f) 2866 return E_FAIL; 2867 2868 WebFrame* webFrame = kit(f); 2869 if (!webFrame) 2870 return E_FAIL; 2871 2872 return webFrame->QueryInterface(IID_IWebFrame, (void**) frame); 2873 } 2874 2875 HRESULT STDMETHODCALLTYPE WebView::backForwardList( 2876 /* [out][retval] */ IWebBackForwardList** list) 2877 { 2878 if (!m_useBackForwardList) 2879 return E_FAIL; 2880 2881 *list = WebBackForwardList::createInstance(static_cast<WebCore::BackForwardListImpl*>(m_page->backForwardList())); 2882 2883 return S_OK; 2884 } 2885 2886 HRESULT STDMETHODCALLTYPE WebView::setMaintainsBackForwardList( 2887 /* [in] */ BOOL flag) 2888 { 2889 m_useBackForwardList = !!flag; 2890 return S_OK; 2891 } 2892 2893 HRESULT STDMETHODCALLTYPE WebView::goBack( 2894 /* [retval][out] */ BOOL* succeeded) 2895 { 2896 *succeeded = m_page->goBack(); 2897 return S_OK; 2898 } 2899 2900 HRESULT STDMETHODCALLTYPE WebView::goForward( 2901 /* [retval][out] */ BOOL* succeeded) 2902 { 2903 *succeeded = m_page->goForward(); 2904 return S_OK; 2905 } 2906 2907 HRESULT STDMETHODCALLTYPE WebView::goToBackForwardItem( 2908 /* [in] */ IWebHistoryItem* item, 2909 /* [retval][out] */ BOOL* succeeded) 2910 { 2911 *succeeded = FALSE; 2912 2913 COMPtr<WebHistoryItem> webHistoryItem; 2914 HRESULT hr = item->QueryInterface(&webHistoryItem); 2915 if (FAILED(hr)) 2916 return hr; 2917 2918 m_page->goToItem(webHistoryItem->historyItem(), FrameLoadTypeIndexedBackForward); 2919 *succeeded = TRUE; 2920 2921 return S_OK; 2922 } 2923 2924 HRESULT STDMETHODCALLTYPE WebView::setTextSizeMultiplier( 2925 /* [in] */ float multiplier) 2926 { 2927 if (!m_mainFrame) 2928 return E_FAIL; 2929 setZoomMultiplier(multiplier, true); 2930 return S_OK; 2931 } 2932 2933 HRESULT STDMETHODCALLTYPE WebView::setPageSizeMultiplier( 2934 /* [in] */ float multiplier) 2935 { 2936 if (!m_mainFrame) 2937 return E_FAIL; 2938 setZoomMultiplier(multiplier, false); 2939 return S_OK; 2940 } 2941 2942 void WebView::setZoomMultiplier(float multiplier, bool isTextOnly) 2943 { 2944 m_zoomMultiplier = multiplier; 2945 m_zoomsTextOnly = isTextOnly; 2946 2947 if (Frame* coreFrame = core(m_mainFrame)) { 2948 if (m_zoomsTextOnly) 2949 coreFrame->setPageAndTextZoomFactors(1, multiplier); 2950 else 2951 coreFrame->setPageAndTextZoomFactors(multiplier, 1); 2952 } 2953 } 2954 2955 HRESULT STDMETHODCALLTYPE WebView::textSizeMultiplier( 2956 /* [retval][out] */ float* multiplier) 2957 { 2958 *multiplier = zoomMultiplier(true); 2959 return S_OK; 2960 } 2961 2962 HRESULT STDMETHODCALLTYPE WebView::pageSizeMultiplier( 2963 /* [retval][out] */ float* multiplier) 2964 { 2965 *multiplier = zoomMultiplier(false); 2966 return S_OK; 2967 } 2968 2969 float WebView::zoomMultiplier(bool isTextOnly) 2970 { 2971 if (isTextOnly != m_zoomsTextOnly) 2972 return 1.0f; 2973 return m_zoomMultiplier; 2974 } 2975 2976 HRESULT STDMETHODCALLTYPE WebView::setApplicationNameForUserAgent( 2977 /* [in] */ BSTR applicationName) 2978 { 2979 m_applicationName = String(applicationName, SysStringLen(applicationName)); 2980 m_userAgentStandard = String(); 2981 return S_OK; 2982 } 2983 2984 HRESULT STDMETHODCALLTYPE WebView::applicationNameForUserAgent( 2985 /* [retval][out] */ BSTR* applicationName) 2986 { 2987 *applicationName = SysAllocStringLen(m_applicationName.characters(), m_applicationName.length()); 2988 if (!*applicationName && m_applicationName.length()) 2989 return E_OUTOFMEMORY; 2990 return S_OK; 2991 } 2992 2993 HRESULT STDMETHODCALLTYPE WebView::setCustomUserAgent( 2994 /* [in] */ BSTR userAgentString) 2995 { 2996 m_userAgentOverridden = userAgentString; 2997 m_userAgentCustom = String(userAgentString, SysStringLen(userAgentString)); 2998 return S_OK; 2999 } 3000 3001 HRESULT STDMETHODCALLTYPE WebView::customUserAgent( 3002 /* [retval][out] */ BSTR* userAgentString) 3003 { 3004 *userAgentString = 0; 3005 if (!m_userAgentOverridden) 3006 return S_OK; 3007 *userAgentString = SysAllocStringLen(m_userAgentCustom.characters(), m_userAgentCustom.length()); 3008 if (!*userAgentString && m_userAgentCustom.length()) 3009 return E_OUTOFMEMORY; 3010 return S_OK; 3011 } 3012 3013 HRESULT STDMETHODCALLTYPE WebView::userAgentForURL( 3014 /* [in] */ BSTR url, 3015 /* [retval][out] */ BSTR* userAgent) 3016 { 3017 String userAgentString = userAgentForKURL(MarshallingHelpers::BSTRToKURL(url)); 3018 *userAgent = SysAllocStringLen(userAgentString.characters(), userAgentString.length()); 3019 if (!*userAgent && userAgentString.length()) 3020 return E_OUTOFMEMORY; 3021 return S_OK; 3022 } 3023 3024 HRESULT STDMETHODCALLTYPE WebView::supportsTextEncoding( 3025 /* [retval][out] */ BOOL* supports) 3026 { 3027 *supports = TRUE; 3028 return S_OK; 3029 } 3030 3031 HRESULT STDMETHODCALLTYPE WebView::setCustomTextEncodingName( 3032 /* [in] */ BSTR encodingName) 3033 { 3034 if (!m_mainFrame) 3035 return E_FAIL; 3036 3037 HRESULT hr; 3038 BSTR oldEncoding; 3039 hr = customTextEncodingName(&oldEncoding); 3040 if (FAILED(hr)) 3041 return hr; 3042 3043 if (oldEncoding != encodingName && (!oldEncoding || !encodingName || wcscmp(oldEncoding, encodingName))) { 3044 if (Frame* coreFrame = core(m_mainFrame)) 3045 coreFrame->loader()->reloadWithOverrideEncoding(String(encodingName, SysStringLen(encodingName))); 3046 } 3047 3048 return S_OK; 3049 } 3050 3051 HRESULT STDMETHODCALLTYPE WebView::customTextEncodingName( 3052 /* [retval][out] */ BSTR* encodingName) 3053 { 3054 HRESULT hr = S_OK; 3055 COMPtr<IWebDataSource> dataSource; 3056 COMPtr<WebDataSource> dataSourceImpl; 3057 *encodingName = 0; 3058 3059 if (!m_mainFrame) 3060 return E_FAIL; 3061 3062 if (FAILED(m_mainFrame->provisionalDataSource(&dataSource)) || !dataSource) { 3063 hr = m_mainFrame->dataSource(&dataSource); 3064 if (FAILED(hr) || !dataSource) 3065 return hr; 3066 } 3067 3068 hr = dataSource->QueryInterface(IID_WebDataSource, (void**)&dataSourceImpl); 3069 if (FAILED(hr)) 3070 return hr; 3071 3072 BString str = dataSourceImpl->documentLoader()->overrideEncoding(); 3073 if (FAILED(hr)) 3074 return hr; 3075 3076 if (!*encodingName) 3077 *encodingName = SysAllocStringLen(m_overrideEncoding.characters(), m_overrideEncoding.length()); 3078 3079 if (!*encodingName && m_overrideEncoding.length()) 3080 return E_OUTOFMEMORY; 3081 3082 return S_OK; 3083 } 3084 3085 HRESULT STDMETHODCALLTYPE WebView::setMediaStyle( 3086 /* [in] */ BSTR /*media*/) 3087 { 3088 ASSERT_NOT_REACHED(); 3089 return E_NOTIMPL; 3090 } 3091 3092 HRESULT STDMETHODCALLTYPE WebView::mediaStyle( 3093 /* [retval][out] */ BSTR* /*media*/) 3094 { 3095 ASSERT_NOT_REACHED(); 3096 return E_NOTIMPL; 3097 } 3098 3099 HRESULT STDMETHODCALLTYPE WebView::stringByEvaluatingJavaScriptFromString( 3100 /* [in] */ BSTR script, // assumes input does not have "JavaScript" at the begining. 3101 /* [retval][out] */ BSTR* result) 3102 { 3103 if (!result) { 3104 ASSERT_NOT_REACHED(); 3105 return E_POINTER; 3106 } 3107 3108 *result = 0; 3109 3110 Frame* coreFrame = core(m_mainFrame); 3111 if (!coreFrame) 3112 return E_FAIL; 3113 3114 JSC::JSValue scriptExecutionResult = coreFrame->script()->executeScript(WTF::String(script), true).jsValue(); 3115 if (!scriptExecutionResult) 3116 return E_FAIL; 3117 else if (scriptExecutionResult.isString()) { 3118 JSLock lock(JSC::SilenceAssertionsOnly); 3119 JSC::ExecState* exec = coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec(); 3120 *result = BString(ustringToString(scriptExecutionResult.getString(exec))); 3121 } 3122 3123 return S_OK; 3124 } 3125 3126 HRESULT STDMETHODCALLTYPE WebView::windowScriptObject( 3127 /* [retval][out] */ IWebScriptObject** /*webScriptObject*/) 3128 { 3129 ASSERT_NOT_REACHED(); 3130 return E_NOTIMPL; 3131 } 3132 3133 HRESULT STDMETHODCALLTYPE WebView::setPreferences( 3134 /* [in] */ IWebPreferences* prefs) 3135 { 3136 if (!prefs) 3137 prefs = WebPreferences::sharedStandardPreferences(); 3138 3139 if (m_preferences == prefs) 3140 return S_OK; 3141 3142 COMPtr<WebPreferences> webPrefs(Query, prefs); 3143 if (!webPrefs) 3144 return E_NOINTERFACE; 3145 webPrefs->willAddToWebView(); 3146 3147 COMPtr<WebPreferences> oldPrefs = m_preferences; 3148 3149 IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal(); 3150 nc->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get())); 3151 3152 BSTR identifier = 0; 3153 oldPrefs->identifier(&identifier); 3154 oldPrefs->didRemoveFromWebView(); 3155 oldPrefs = 0; // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences 3156 3157 m_preferences = webPrefs; 3158 3159 if (identifier) { 3160 WebPreferences::removeReferenceForIdentifier(identifier); 3161 SysFreeString(identifier); 3162 } 3163 3164 nc->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get())); 3165 3166 m_preferences->postPreferencesChangesNotification(); 3167 3168 return S_OK; 3169 } 3170 3171 HRESULT STDMETHODCALLTYPE WebView::preferences( 3172 /* [retval][out] */ IWebPreferences** prefs) 3173 { 3174 if (!prefs) 3175 return E_POINTER; 3176 *prefs = m_preferences.get(); 3177 if (m_preferences) 3178 m_preferences->AddRef(); 3179 return S_OK; 3180 } 3181 3182 HRESULT STDMETHODCALLTYPE WebView::setPreferencesIdentifier( 3183 /* [in] */ BSTR /*anIdentifier*/) 3184 { 3185 ASSERT_NOT_REACHED(); 3186 return E_NOTIMPL; 3187 } 3188 3189 HRESULT STDMETHODCALLTYPE WebView::preferencesIdentifier( 3190 /* [retval][out] */ BSTR* /*anIdentifier*/) 3191 { 3192 ASSERT_NOT_REACHED(); 3193 return E_NOTIMPL; 3194 } 3195 3196 static void systemParameterChanged(WPARAM parameter) 3197 { 3198 #if USE(CG) 3199 if (parameter == SPI_SETFONTSMOOTHING || parameter == SPI_SETFONTSMOOTHINGTYPE || parameter == SPI_SETFONTSMOOTHINGCONTRAST || parameter == SPI_SETFONTSMOOTHINGORIENTATION) 3200 wkSystemFontSmoothingChanged(); 3201 #endif 3202 } 3203 3204 void WebView::windowReceivedMessage(HWND, UINT message, WPARAM wParam, LPARAM) 3205 { 3206 switch (message) { 3207 case WM_NCACTIVATE: 3208 updateActiveStateSoon(); 3209 if (!wParam) 3210 deleteBackingStoreSoon(); 3211 break; 3212 case WM_SETTINGCHANGE: 3213 systemParameterChanged(wParam); 3214 break; 3215 } 3216 } 3217 3218 void WebView::updateActiveStateSoon() const 3219 { 3220 // This function is called while processing the WM_NCACTIVATE message. 3221 // While processing WM_NCACTIVATE when we are being deactivated, GetActiveWindow() will 3222 // still return our window. If we were to call updateActiveState() in that case, we would 3223 // wrongly think that we are still the active window. To work around this, we update our 3224 // active state after a 0-delay timer fires, at which point GetActiveWindow() will return 3225 // the newly-activated window. 3226 3227 SetTimer(m_viewWindow, UpdateActiveStateTimer, 0, 0); 3228 } 3229 3230 void WebView::deleteBackingStoreSoon() 3231 { 3232 if (pendingDeleteBackingStoreSet.size() > 2) { 3233 Vector<WebView*> views; 3234 HashSet<WebView*>::iterator end = pendingDeleteBackingStoreSet.end(); 3235 for (HashSet<WebView*>::iterator it = pendingDeleteBackingStoreSet.begin(); it != end; ++it) 3236 views.append(*it); 3237 for (int i = 0; i < views.size(); ++i) 3238 views[i]->deleteBackingStore(); 3239 ASSERT(pendingDeleteBackingStoreSet.isEmpty()); 3240 } 3241 3242 pendingDeleteBackingStoreSet.add(this); 3243 m_deleteBackingStoreTimerActive = true; 3244 SetTimer(m_viewWindow, DeleteBackingStoreTimer, delayBeforeDeletingBackingStoreMsec, 0); 3245 } 3246 3247 void WebView::cancelDeleteBackingStoreSoon() 3248 { 3249 if (!m_deleteBackingStoreTimerActive) 3250 return; 3251 pendingDeleteBackingStoreSet.remove(this); 3252 m_deleteBackingStoreTimerActive = false; 3253 KillTimer(m_viewWindow, DeleteBackingStoreTimer); 3254 } 3255 3256 HRESULT STDMETHODCALLTYPE WebView::setHostWindow( 3257 /* [in] */ OLE_HANDLE oleWindow) 3258 { 3259 HWND window = (HWND)(ULONG64)oleWindow; 3260 if (m_viewWindow) { 3261 if (window) 3262 SetParent(m_viewWindow, window); 3263 else if (!isBeingDestroyed()) { 3264 // Turn the WebView into a message-only window so it will no longer be a child of the 3265 // old host window and will be hidden from screen. We only do this when 3266 // isBeingDestroyed() is false because doing this while handling WM_DESTROY can leave 3267 // m_viewWindow in a weird state (see <http://webkit.org/b/29337>). 3268 SetParent(m_viewWindow, HWND_MESSAGE); 3269 } 3270 } 3271 3272 m_hostWindow = window; 3273 3274 windowAncestryDidChange(); 3275 3276 return S_OK; 3277 } 3278 3279 HRESULT STDMETHODCALLTYPE WebView::hostWindow( 3280 /* [retval][out] */ OLE_HANDLE* window) 3281 { 3282 *window = (OLE_HANDLE)(ULONG64)m_hostWindow; 3283 return S_OK; 3284 } 3285 3286 3287 static Frame *incrementFrame(Frame *curr, bool forward, bool wrapFlag) 3288 { 3289 return forward 3290 ? curr->tree()->traverseNextWithWrap(wrapFlag) 3291 : curr->tree()->traversePreviousWithWrap(wrapFlag); 3292 } 3293 3294 HRESULT STDMETHODCALLTYPE WebView::searchFor( 3295 /* [in] */ BSTR str, 3296 /* [in] */ BOOL forward, 3297 /* [in] */ BOOL caseFlag, 3298 /* [in] */ BOOL wrapFlag, 3299 /* [retval][out] */ BOOL* found) 3300 { 3301 if (!found) 3302 return E_INVALIDARG; 3303 3304 if (!m_page || !m_page->mainFrame()) 3305 return E_UNEXPECTED; 3306 3307 if (!str || !SysStringLen(str)) 3308 return E_INVALIDARG; 3309 3310 *found = m_page->findString(String(str, SysStringLen(str)), caseFlag ? TextCaseSensitive : TextCaseInsensitive, forward ? FindDirectionForward : FindDirectionBackward, wrapFlag); 3311 return S_OK; 3312 } 3313 3314 bool WebView::active() 3315 { 3316 HWND activeWindow = GetActiveWindow(); 3317 return (activeWindow && m_topLevelParent == findTopLevelParent(activeWindow)); 3318 } 3319 3320 void WebView::updateActiveState() 3321 { 3322 m_page->focusController()->setActive(active()); 3323 } 3324 3325 HRESULT STDMETHODCALLTYPE WebView::updateFocusedAndActiveState() 3326 { 3327 updateActiveState(); 3328 3329 bool active = m_page->focusController()->isActive(); 3330 Frame* mainFrame = m_page->mainFrame(); 3331 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame(); 3332 mainFrame->selection()->setFocused(active && mainFrame == focusedFrame); 3333 3334 return S_OK; 3335 } 3336 3337 HRESULT STDMETHODCALLTYPE WebView::executeCoreCommandByName(BSTR bName, BSTR bValue) 3338 { 3339 String name(bName, SysStringLen(bName)); 3340 String value(bValue, SysStringLen(bValue)); 3341 3342 m_page->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value); 3343 3344 return S_OK; 3345 } 3346 3347 HRESULT STDMETHODCALLTYPE WebView::clearMainFrameName() 3348 { 3349 m_page->mainFrame()->tree()->clearName(); 3350 3351 return S_OK; 3352 } 3353 3354 HRESULT STDMETHODCALLTYPE WebView::markAllMatchesForText( 3355 BSTR str, BOOL caseSensitive, BOOL highlight, UINT limit, UINT* matches) 3356 { 3357 if (!matches) 3358 return E_INVALIDARG; 3359 3360 if (!m_page || !m_page->mainFrame()) 3361 return E_UNEXPECTED; 3362 3363 if (!str || !SysStringLen(str)) 3364 return E_INVALIDARG; 3365 3366 *matches = m_page->markAllMatchesForText(String(str, SysStringLen(str)), caseSensitive ? TextCaseSensitive : TextCaseInsensitive, highlight, limit); 3367 return S_OK; 3368 } 3369 3370 HRESULT STDMETHODCALLTYPE WebView::unmarkAllTextMatches() 3371 { 3372 if (!m_page || !m_page->mainFrame()) 3373 return E_UNEXPECTED; 3374 3375 m_page->unmarkAllTextMatches(); 3376 return S_OK; 3377 } 3378 3379 HRESULT STDMETHODCALLTYPE WebView::rectsForTextMatches( 3380 IEnumTextMatches** pmatches) 3381 { 3382 Vector<IntRect> allRects; 3383 WebCore::Frame* frame = m_page->mainFrame(); 3384 do { 3385 if (Document* document = frame->document()) { 3386 IntRect visibleRect = frame->view()->visibleContentRect(); 3387 Vector<IntRect> frameRects = document->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch); 3388 IntPoint frameOffset(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height()); 3389 frameOffset = frame->view()->convertToContainingWindow(frameOffset); 3390 3391 Vector<IntRect>::iterator end = frameRects.end(); 3392 for (Vector<IntRect>::iterator it = frameRects.begin(); it < end; it++) { 3393 it->intersect(visibleRect); 3394 it->move(frameOffset.x(), frameOffset.y()); 3395 allRects.append(*it); 3396 } 3397 } 3398 frame = incrementFrame(frame, true, false); 3399 } while (frame); 3400 3401 return createMatchEnumerator(&allRects, pmatches); 3402 } 3403 3404 HRESULT STDMETHODCALLTYPE WebView::generateSelectionImage(BOOL forceWhiteText, OLE_HANDLE* hBitmap) 3405 { 3406 *hBitmap = 0; 3407 3408 WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame(); 3409 3410 if (frame) { 3411 HBITMAP bitmap = imageFromSelection(frame, forceWhiteText ? TRUE : FALSE); 3412 *hBitmap = (OLE_HANDLE)(ULONG64)bitmap; 3413 } 3414 3415 return S_OK; 3416 } 3417 3418 HRESULT STDMETHODCALLTYPE WebView::selectionRect(RECT* rc) 3419 { 3420 WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame(); 3421 3422 if (frame) { 3423 IntRect ir = enclosingIntRect(frame->selection()->bounds()); 3424 ir = frame->view()->convertToContainingWindow(ir); 3425 ir.move(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height()); 3426 rc->left = ir.x(); 3427 rc->top = ir.y(); 3428 rc->bottom = rc->top + ir.height(); 3429 rc->right = rc->left + ir.width(); 3430 } 3431 3432 return S_OK; 3433 } 3434 3435 HRESULT STDMETHODCALLTYPE WebView::registerViewClass( 3436 /* [in] */ IWebDocumentView* /*view*/, 3437 /* [in] */ IWebDocumentRepresentation* /*representation*/, 3438 /* [in] */ BSTR /*forMIMEType*/) 3439 { 3440 ASSERT_NOT_REACHED(); 3441 return E_NOTIMPL; 3442 } 3443 3444 HRESULT STDMETHODCALLTYPE WebView::setGroupName( 3445 /* [in] */ BSTR groupName) 3446 { 3447 if (!m_page) 3448 return S_OK; 3449 m_page->setGroupName(String(groupName, SysStringLen(groupName))); 3450 return S_OK; 3451 } 3452 3453 HRESULT STDMETHODCALLTYPE WebView::groupName( 3454 /* [retval][out] */ BSTR* groupName) 3455 { 3456 *groupName = 0; 3457 if (!m_page) 3458 return S_OK; 3459 String groupNameString = m_page->groupName(); 3460 *groupName = SysAllocStringLen(groupNameString.characters(), groupNameString.length()); 3461 if (!*groupName && groupNameString.length()) 3462 return E_OUTOFMEMORY; 3463 return S_OK; 3464 } 3465 3466 HRESULT STDMETHODCALLTYPE WebView::estimatedProgress( 3467 /* [retval][out] */ double* estimatedProgress) 3468 { 3469 *estimatedProgress = m_page->progress()->estimatedProgress(); 3470 return S_OK; 3471 } 3472 3473 HRESULT STDMETHODCALLTYPE WebView::isLoading( 3474 /* [retval][out] */ BOOL* isLoading) 3475 { 3476 COMPtr<IWebDataSource> dataSource; 3477 COMPtr<IWebDataSource> provisionalDataSource; 3478 3479 if (!isLoading) 3480 return E_POINTER; 3481 3482 *isLoading = FALSE; 3483 3484 if (!m_mainFrame) 3485 return E_FAIL; 3486 3487 if (SUCCEEDED(m_mainFrame->dataSource(&dataSource))) 3488 dataSource->isLoading(isLoading); 3489 3490 if (*isLoading) 3491 return S_OK; 3492 3493 if (SUCCEEDED(m_mainFrame->provisionalDataSource(&provisionalDataSource))) 3494 provisionalDataSource->isLoading(isLoading); 3495 return S_OK; 3496 } 3497 3498 HRESULT STDMETHODCALLTYPE WebView::elementAtPoint( 3499 /* [in] */ LPPOINT point, 3500 /* [retval][out] */ IPropertyBag** elementDictionary) 3501 { 3502 if (!elementDictionary) { 3503 ASSERT_NOT_REACHED(); 3504 return E_POINTER; 3505 } 3506 3507 *elementDictionary = 0; 3508 3509 Frame* frame = core(m_mainFrame); 3510 if (!frame) 3511 return E_FAIL; 3512 3513 IntPoint webCorePoint = IntPoint(point->x, point->y); 3514 HitTestResult result = HitTestResult(webCorePoint); 3515 if (frame->contentRenderer()) 3516 result = frame->eventHandler()->hitTestResultAtPoint(webCorePoint, false); 3517 *elementDictionary = WebElementPropertyBag::createInstance(result); 3518 return S_OK; 3519 } 3520 3521 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForSelection( 3522 /* [retval][out] */ IEnumVARIANT** /*enumVariant*/) 3523 { 3524 ASSERT_NOT_REACHED(); 3525 return E_NOTIMPL; 3526 } 3527 3528 HRESULT STDMETHODCALLTYPE WebView::writeSelectionWithPasteboardTypes( 3529 /* [size_is][in] */ BSTR* /*types*/, 3530 /* [in] */ int /*cTypes*/, 3531 /* [in] */ IDataObject* /*pasteboard*/) 3532 { 3533 ASSERT_NOT_REACHED(); 3534 return E_NOTIMPL; 3535 } 3536 3537 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForElement( 3538 /* [in] */ IPropertyBag* /*elementDictionary*/, 3539 /* [retval][out] */ IEnumVARIANT** /*enumVariant*/) 3540 { 3541 ASSERT_NOT_REACHED(); 3542 return E_NOTIMPL; 3543 } 3544 3545 HRESULT STDMETHODCALLTYPE WebView::writeElement( 3546 /* [in] */ IPropertyBag* /*elementDictionary*/, 3547 /* [size_is][in] */ BSTR* /*withPasteboardTypes*/, 3548 /* [in] */ int /*cWithPasteboardTypes*/, 3549 /* [in] */ IDataObject* /*pasteboard*/) 3550 { 3551 ASSERT_NOT_REACHED(); 3552 return E_NOTIMPL; 3553 } 3554 3555 HRESULT STDMETHODCALLTYPE WebView::selectedText( 3556 /* [out, retval] */ BSTR* text) 3557 { 3558 if (!text) { 3559 ASSERT_NOT_REACHED(); 3560 return E_POINTER; 3561 } 3562 3563 *text = 0; 3564 3565 Frame* focusedFrame = (m_page && m_page->focusController()) ? m_page->focusController()->focusedOrMainFrame() : 0; 3566 if (!focusedFrame) 3567 return E_FAIL; 3568 3569 String frameSelectedText = focusedFrame->editor()->selectedText(); 3570 *text = SysAllocStringLen(frameSelectedText.characters(), frameSelectedText.length()); 3571 if (!*text && frameSelectedText.length()) 3572 return E_OUTOFMEMORY; 3573 return S_OK; 3574 } 3575 3576 HRESULT STDMETHODCALLTYPE WebView::centerSelectionInVisibleArea( 3577 /* [in] */ IUnknown* /* sender */) 3578 { 3579 Frame* coreFrame = core(m_mainFrame); 3580 if (!coreFrame) 3581 return E_FAIL; 3582 3583 coreFrame->selection()->revealSelection(ScrollAlignment::alignCenterAlways); 3584 return S_OK; 3585 } 3586 3587 3588 HRESULT STDMETHODCALLTYPE WebView::moveDragCaretToPoint( 3589 /* [in] */ LPPOINT /*point*/) 3590 { 3591 ASSERT_NOT_REACHED(); 3592 return E_NOTIMPL; 3593 } 3594 3595 HRESULT STDMETHODCALLTYPE WebView::removeDragCaret( void) 3596 { 3597 ASSERT_NOT_REACHED(); 3598 return E_NOTIMPL; 3599 } 3600 3601 HRESULT STDMETHODCALLTYPE WebView::setDrawsBackground( 3602 /* [in] */ BOOL /*drawsBackground*/) 3603 { 3604 ASSERT_NOT_REACHED(); 3605 return E_NOTIMPL; 3606 } 3607 3608 HRESULT STDMETHODCALLTYPE WebView::drawsBackground( 3609 /* [retval][out] */ BOOL* /*drawsBackground*/) 3610 { 3611 ASSERT_NOT_REACHED(); 3612 return E_NOTIMPL; 3613 } 3614 3615 HRESULT STDMETHODCALLTYPE WebView::setMainFrameURL( 3616 /* [in] */ BSTR /*urlString*/) 3617 { 3618 ASSERT_NOT_REACHED(); 3619 return E_NOTIMPL; 3620 } 3621 3622 HRESULT STDMETHODCALLTYPE WebView::mainFrameURL( 3623 /* [retval][out] */ BSTR* urlString) 3624 { 3625 if (!urlString) 3626 return E_POINTER; 3627 3628 if (!m_mainFrame) 3629 return E_FAIL; 3630 3631 COMPtr<IWebDataSource> dataSource; 3632 3633 if (FAILED(m_mainFrame->provisionalDataSource(&dataSource))) { 3634 if (FAILED(m_mainFrame->dataSource(&dataSource))) 3635 return E_FAIL; 3636 } 3637 3638 if (!dataSource) { 3639 *urlString = 0; 3640 return S_OK; 3641 } 3642 3643 COMPtr<IWebMutableURLRequest> request; 3644 if (FAILED(dataSource->request(&request)) || !request) 3645 return E_FAIL; 3646 3647 if (FAILED(request->URL(urlString))) 3648 return E_FAIL; 3649 3650 return S_OK; 3651 } 3652 3653 HRESULT STDMETHODCALLTYPE WebView::mainFrameDocument( 3654 /* [retval][out] */ IDOMDocument** document) 3655 { 3656 if (document) 3657 *document = 0; 3658 if (!m_mainFrame) 3659 return E_FAIL; 3660 return m_mainFrame->DOMDocument(document); 3661 } 3662 3663 HRESULT STDMETHODCALLTYPE WebView::mainFrameTitle( 3664 /* [retval][out] */ BSTR* /*title*/) 3665 { 3666 ASSERT_NOT_REACHED(); 3667 return E_NOTIMPL; 3668 } 3669 3670 HRESULT STDMETHODCALLTYPE WebView::mainFrameIcon( 3671 /* [retval][out] */ OLE_HANDLE* /*hBitmap*/) 3672 { 3673 ASSERT_NOT_REACHED(); 3674 return E_NOTIMPL; 3675 } 3676 3677 HRESULT STDMETHODCALLTYPE WebView::registerURLSchemeAsLocal( 3678 /* [in] */ BSTR scheme) 3679 { 3680 if (!scheme) 3681 return E_POINTER; 3682 3683 SchemeRegistry::registerURLSchemeAsLocal(String(scheme, ::SysStringLen(scheme))); 3684 3685 return S_OK; 3686 } 3687 3688 // IWebIBActions --------------------------------------------------------------- 3689 3690 HRESULT STDMETHODCALLTYPE WebView::takeStringURLFrom( 3691 /* [in] */ IUnknown* /*sender*/) 3692 { 3693 ASSERT_NOT_REACHED(); 3694 return E_NOTIMPL; 3695 } 3696 3697 HRESULT STDMETHODCALLTYPE WebView::stopLoading( 3698 /* [in] */ IUnknown* /*sender*/) 3699 { 3700 if (!m_mainFrame) 3701 return E_FAIL; 3702 3703 return m_mainFrame->stopLoading(); 3704 } 3705 3706 HRESULT STDMETHODCALLTYPE WebView::reload( 3707 /* [in] */ IUnknown* /*sender*/) 3708 { 3709 if (!m_mainFrame) 3710 return E_FAIL; 3711 3712 return m_mainFrame->reload(); 3713 } 3714 3715 HRESULT STDMETHODCALLTYPE WebView::canGoBack( 3716 /* [in] */ IUnknown* /*sender*/, 3717 /* [retval][out] */ BOOL* result) 3718 { 3719 *result = !!(m_page->backForwardList()->backItem() && !m_page->defersLoading()); 3720 return S_OK; 3721 } 3722 3723 HRESULT STDMETHODCALLTYPE WebView::goBack( 3724 /* [in] */ IUnknown* /*sender*/) 3725 { 3726 ASSERT_NOT_REACHED(); 3727 return E_NOTIMPL; 3728 } 3729 3730 HRESULT STDMETHODCALLTYPE WebView::canGoForward( 3731 /* [in] */ IUnknown* /*sender*/, 3732 /* [retval][out] */ BOOL* result) 3733 { 3734 *result = !!(m_page->backForwardList()->forwardItem() && !m_page->defersLoading()); 3735 return S_OK; 3736 } 3737 3738 HRESULT STDMETHODCALLTYPE WebView::goForward( 3739 /* [in] */ IUnknown* /*sender*/) 3740 { 3741 ASSERT_NOT_REACHED(); 3742 return E_NOTIMPL; 3743 } 3744 3745 // FIXME: This code should move into WebCore so it can be shared by all the WebKits. 3746 #define MinimumZoomMultiplier 0.5f 3747 #define MaximumZoomMultiplier 3.0f 3748 #define ZoomMultiplierRatio 1.2f 3749 3750 HRESULT STDMETHODCALLTYPE WebView::canMakeTextLarger( 3751 /* [in] */ IUnknown* /*sender*/, 3752 /* [retval][out] */ BOOL* result) 3753 { 3754 bool canGrowMore = canZoomIn(m_zoomsTextOnly); 3755 *result = canGrowMore ? TRUE : FALSE; 3756 return S_OK; 3757 } 3758 3759 HRESULT STDMETHODCALLTYPE WebView::canZoomPageIn( 3760 /* [in] */ IUnknown* /*sender*/, 3761 /* [retval][out] */ BOOL* result) 3762 { 3763 bool canGrowMore = canZoomIn(false); 3764 *result = canGrowMore ? TRUE : FALSE; 3765 return S_OK; 3766 } 3767 3768 bool WebView::canZoomIn(bool isTextOnly) 3769 { 3770 return zoomMultiplier(isTextOnly) * ZoomMultiplierRatio < MaximumZoomMultiplier; 3771 } 3772 3773 HRESULT STDMETHODCALLTYPE WebView::makeTextLarger( 3774 /* [in] */ IUnknown* /*sender*/) 3775 { 3776 return zoomIn(m_zoomsTextOnly); 3777 } 3778 3779 HRESULT STDMETHODCALLTYPE WebView::zoomPageIn( 3780 /* [in] */ IUnknown* /*sender*/) 3781 { 3782 return zoomIn(false); 3783 } 3784 3785 HRESULT WebView::zoomIn(bool isTextOnly) 3786 { 3787 if (!canZoomIn(isTextOnly)) 3788 return E_FAIL; 3789 setZoomMultiplier(zoomMultiplier(isTextOnly) * ZoomMultiplierRatio, isTextOnly); 3790 return S_OK; 3791 } 3792 3793 HRESULT STDMETHODCALLTYPE WebView::canMakeTextSmaller( 3794 /* [in] */ IUnknown* /*sender*/, 3795 /* [retval][out] */ BOOL* result) 3796 { 3797 bool canShrinkMore = canZoomOut(m_zoomsTextOnly); 3798 *result = canShrinkMore ? TRUE : FALSE; 3799 return S_OK; 3800 } 3801 3802 HRESULT STDMETHODCALLTYPE WebView::canZoomPageOut( 3803 /* [in] */ IUnknown* /*sender*/, 3804 /* [retval][out] */ BOOL* result) 3805 { 3806 bool canShrinkMore = canZoomOut(false); 3807 *result = canShrinkMore ? TRUE : FALSE; 3808 return S_OK; 3809 } 3810 3811 bool WebView::canZoomOut(bool isTextOnly) 3812 { 3813 return zoomMultiplier(isTextOnly) / ZoomMultiplierRatio > MinimumZoomMultiplier; 3814 } 3815 3816 HRESULT STDMETHODCALLTYPE WebView::makeTextSmaller( 3817 /* [in] */ IUnknown* /*sender*/) 3818 { 3819 return zoomOut(m_zoomsTextOnly); 3820 } 3821 3822 HRESULT STDMETHODCALLTYPE WebView::zoomPageOut( 3823 /* [in] */ IUnknown* /*sender*/) 3824 { 3825 return zoomOut(false); 3826 } 3827 3828 HRESULT WebView::zoomOut(bool isTextOnly) 3829 { 3830 if (!canZoomOut(isTextOnly)) 3831 return E_FAIL; 3832 setZoomMultiplier(zoomMultiplier(isTextOnly) / ZoomMultiplierRatio, isTextOnly); 3833 return S_OK; 3834 } 3835 3836 HRESULT STDMETHODCALLTYPE WebView::canMakeTextStandardSize( 3837 /* [in] */ IUnknown* /*sender*/, 3838 /* [retval][out] */ BOOL* result) 3839 { 3840 // Since we always reset text zoom and page zoom together, this should continue to return an answer about text zoom even if its not enabled. 3841 bool notAlreadyStandard = canResetZoom(true); 3842 *result = notAlreadyStandard ? TRUE : FALSE; 3843 return S_OK; 3844 } 3845 3846 HRESULT STDMETHODCALLTYPE WebView::canResetPageZoom( 3847 /* [in] */ IUnknown* /*sender*/, 3848 /* [retval][out] */ BOOL* result) 3849 { 3850 bool notAlreadyStandard = canResetZoom(false); 3851 *result = notAlreadyStandard ? TRUE : FALSE; 3852 return S_OK; 3853 } 3854 3855 bool WebView::canResetZoom(bool isTextOnly) 3856 { 3857 return zoomMultiplier(isTextOnly) != 1.0f; 3858 } 3859 3860 HRESULT STDMETHODCALLTYPE WebView::makeTextStandardSize( 3861 /* [in] */ IUnknown* /*sender*/) 3862 { 3863 return resetZoom(true); 3864 } 3865 3866 HRESULT STDMETHODCALLTYPE WebView::resetPageZoom( 3867 /* [in] */ IUnknown* /*sender*/) 3868 { 3869 return resetZoom(false); 3870 } 3871 3872 HRESULT WebView::resetZoom(bool isTextOnly) 3873 { 3874 if (!canResetZoom(isTextOnly)) 3875 return E_FAIL; 3876 setZoomMultiplier(1.0f, isTextOnly); 3877 return S_OK; 3878 } 3879 3880 HRESULT STDMETHODCALLTYPE WebView::toggleContinuousSpellChecking( 3881 /* [in] */ IUnknown* /*sender*/) 3882 { 3883 HRESULT hr; 3884 BOOL enabled; 3885 if (FAILED(hr = isContinuousSpellCheckingEnabled(&enabled))) 3886 return hr; 3887 return setContinuousSpellCheckingEnabled(enabled ? FALSE : TRUE); 3888 } 3889 3890 HRESULT STDMETHODCALLTYPE WebView::toggleSmartInsertDelete( 3891 /* [in] */ IUnknown* /*sender*/) 3892 { 3893 BOOL enabled = FALSE; 3894 HRESULT hr = smartInsertDeleteEnabled(&enabled); 3895 if (FAILED(hr)) 3896 return hr; 3897 3898 return setSmartInsertDeleteEnabled(enabled ? FALSE : TRUE); 3899 } 3900 3901 HRESULT STDMETHODCALLTYPE WebView::toggleGrammarChecking( 3902 /* [in] */ IUnknown* /*sender*/) 3903 { 3904 BOOL enabled; 3905 HRESULT hr = isGrammarCheckingEnabled(&enabled); 3906 if (FAILED(hr)) 3907 return hr; 3908 3909 return setGrammarCheckingEnabled(enabled ? FALSE : TRUE); 3910 } 3911 3912 HRESULT STDMETHODCALLTYPE WebView::reloadFromOrigin( 3913 /* [in] */ IUnknown* /*sender*/) 3914 { 3915 if (!m_mainFrame) 3916 return E_FAIL; 3917 3918 return m_mainFrame->reloadFromOrigin(); 3919 } 3920 3921 // IWebViewCSS ----------------------------------------------------------------- 3922 3923 HRESULT STDMETHODCALLTYPE WebView::computedStyleForElement( 3924 /* [in] */ IDOMElement* /*element*/, 3925 /* [in] */ BSTR /*pseudoElement*/, 3926 /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/) 3927 { 3928 ASSERT_NOT_REACHED(); 3929 return E_NOTIMPL; 3930 } 3931 3932 // IWebViewEditing ------------------------------------------------------------- 3933 3934 HRESULT STDMETHODCALLTYPE WebView::editableDOMRangeForPoint( 3935 /* [in] */ LPPOINT /*point*/, 3936 /* [retval][out] */ IDOMRange** /*range*/) 3937 { 3938 ASSERT_NOT_REACHED(); 3939 return E_NOTIMPL; 3940 } 3941 3942 HRESULT STDMETHODCALLTYPE WebView::setSelectedDOMRange( 3943 /* [in] */ IDOMRange* /*range*/, 3944 /* [in] */ WebSelectionAffinity /*affinity*/) 3945 { 3946 ASSERT_NOT_REACHED(); 3947 return E_NOTIMPL; 3948 } 3949 3950 HRESULT STDMETHODCALLTYPE WebView::selectedDOMRange( 3951 /* [retval][out] */ IDOMRange** /*range*/) 3952 { 3953 ASSERT_NOT_REACHED(); 3954 return E_NOTIMPL; 3955 } 3956 3957 HRESULT STDMETHODCALLTYPE WebView::selectionAffinity( 3958 /* [retval][out][retval][out] */ WebSelectionAffinity* /*affinity*/) 3959 { 3960 ASSERT_NOT_REACHED(); 3961 return E_NOTIMPL; 3962 } 3963 3964 HRESULT STDMETHODCALLTYPE WebView::setEditable( 3965 /* [in] */ BOOL /*flag*/) 3966 { 3967 ASSERT_NOT_REACHED(); 3968 return E_NOTIMPL; 3969 } 3970 3971 HRESULT STDMETHODCALLTYPE WebView::isEditable( 3972 /* [retval][out] */ BOOL* /*isEditable*/) 3973 { 3974 ASSERT_NOT_REACHED(); 3975 return E_NOTIMPL; 3976 } 3977 3978 HRESULT STDMETHODCALLTYPE WebView::setTypingStyle( 3979 /* [in] */ IDOMCSSStyleDeclaration* /*style*/) 3980 { 3981 ASSERT_NOT_REACHED(); 3982 return E_NOTIMPL; 3983 } 3984 3985 HRESULT STDMETHODCALLTYPE WebView::typingStyle( 3986 /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/) 3987 { 3988 ASSERT_NOT_REACHED(); 3989 return E_NOTIMPL; 3990 } 3991 3992 HRESULT STDMETHODCALLTYPE WebView::setSmartInsertDeleteEnabled( 3993 /* [in] */ BOOL flag) 3994 { 3995 m_smartInsertDeleteEnabled = !!flag; 3996 if (m_smartInsertDeleteEnabled) 3997 setSelectTrailingWhitespaceEnabled(false); 3998 return S_OK; 3999 } 4000 4001 HRESULT STDMETHODCALLTYPE WebView::smartInsertDeleteEnabled( 4002 /* [retval][out] */ BOOL* enabled) 4003 { 4004 *enabled = m_smartInsertDeleteEnabled ? TRUE : FALSE; 4005 return S_OK; 4006 } 4007 4008 HRESULT STDMETHODCALLTYPE WebView::setSelectTrailingWhitespaceEnabled( 4009 /* [in] */ BOOL flag) 4010 { 4011 m_selectTrailingWhitespaceEnabled = !!flag; 4012 if (m_selectTrailingWhitespaceEnabled) 4013 setSmartInsertDeleteEnabled(false); 4014 return S_OK; 4015 } 4016 4017 HRESULT STDMETHODCALLTYPE WebView::isSelectTrailingWhitespaceEnabled( 4018 /* [retval][out] */ BOOL* enabled) 4019 { 4020 *enabled = m_selectTrailingWhitespaceEnabled ? TRUE : FALSE; 4021 return S_OK; 4022 } 4023 4024 HRESULT STDMETHODCALLTYPE WebView::setContinuousSpellCheckingEnabled( 4025 /* [in] */ BOOL flag) 4026 { 4027 if (continuousSpellCheckingEnabled != !!flag) { 4028 continuousSpellCheckingEnabled = !!flag; 4029 COMPtr<IWebPreferences> prefs; 4030 if (SUCCEEDED(preferences(&prefs))) 4031 prefs->setContinuousSpellCheckingEnabled(flag); 4032 } 4033 4034 BOOL spellCheckingEnabled; 4035 if (SUCCEEDED(isContinuousSpellCheckingEnabled(&spellCheckingEnabled)) && spellCheckingEnabled) 4036 preflightSpellChecker(); 4037 else 4038 m_mainFrame->unmarkAllMisspellings(); 4039 4040 return S_OK; 4041 } 4042 4043 HRESULT STDMETHODCALLTYPE WebView::isContinuousSpellCheckingEnabled( 4044 /* [retval][out] */ BOOL* enabled) 4045 { 4046 *enabled = (continuousSpellCheckingEnabled && continuousCheckingAllowed()) ? TRUE : FALSE; 4047 return S_OK; 4048 } 4049 4050 HRESULT STDMETHODCALLTYPE WebView::spellCheckerDocumentTag( 4051 /* [retval][out] */ int* tag) 4052 { 4053 // we just use this as a flag to indicate that we've spell checked the document 4054 // and need to close the spell checker out when the view closes. 4055 *tag = 0; 4056 m_hasSpellCheckerDocumentTag = true; 4057 return S_OK; 4058 } 4059 4060 static COMPtr<IWebEditingDelegate> spellingDelegateForTimer; 4061 4062 static void preflightSpellCheckerNow() 4063 { 4064 spellingDelegateForTimer->preflightChosenSpellServer(); 4065 spellingDelegateForTimer = 0; 4066 } 4067 4068 static void CALLBACK preflightSpellCheckerTimerCallback(HWND, UINT, UINT_PTR id, DWORD) 4069 { 4070 ::KillTimer(0, id); 4071 preflightSpellCheckerNow(); 4072 } 4073 4074 void WebView::preflightSpellChecker() 4075 { 4076 // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch. 4077 if (!m_editingDelegate) 4078 return; 4079 4080 BOOL exists; 4081 spellingDelegateForTimer = m_editingDelegate; 4082 if (SUCCEEDED(m_editingDelegate->sharedSpellCheckerExists(&exists)) && exists) 4083 preflightSpellCheckerNow(); 4084 else 4085 ::SetTimer(0, 0, 2000, preflightSpellCheckerTimerCallback); 4086 } 4087 4088 bool WebView::continuousCheckingAllowed() 4089 { 4090 static bool allowContinuousSpellChecking = true; 4091 static bool readAllowContinuousSpellCheckingDefault = false; 4092 if (!readAllowContinuousSpellCheckingDefault) { 4093 COMPtr<IWebPreferences> prefs; 4094 if (SUCCEEDED(preferences(&prefs))) { 4095 BOOL allowed; 4096 prefs->allowContinuousSpellChecking(&allowed); 4097 allowContinuousSpellChecking = !!allowed; 4098 } 4099 readAllowContinuousSpellCheckingDefault = true; 4100 } 4101 return allowContinuousSpellChecking; 4102 } 4103 4104 HRESULT STDMETHODCALLTYPE WebView::undoManager( 4105 /* [retval][out] */ IWebUndoManager** /*manager*/) 4106 { 4107 ASSERT_NOT_REACHED(); 4108 return E_NOTIMPL; 4109 } 4110 4111 HRESULT STDMETHODCALLTYPE WebView::setEditingDelegate( 4112 /* [in] */ IWebEditingDelegate* d) 4113 { 4114 m_editingDelegate = d; 4115 return S_OK; 4116 } 4117 4118 HRESULT STDMETHODCALLTYPE WebView::editingDelegate( 4119 /* [retval][out] */ IWebEditingDelegate** d) 4120 { 4121 if (!d) { 4122 ASSERT_NOT_REACHED(); 4123 return E_POINTER; 4124 } 4125 4126 *d = m_editingDelegate.get(); 4127 if (!*d) 4128 return E_FAIL; 4129 4130 (*d)->AddRef(); 4131 return S_OK; 4132 } 4133 4134 HRESULT STDMETHODCALLTYPE WebView::styleDeclarationWithText( 4135 /* [in] */ BSTR /*text*/, 4136 /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/) 4137 { 4138 ASSERT_NOT_REACHED(); 4139 return E_NOTIMPL; 4140 } 4141 4142 HRESULT STDMETHODCALLTYPE WebView::hasSelectedRange( 4143 /* [retval][out] */ BOOL* hasSelectedRange) 4144 { 4145 *hasSelectedRange = m_page->mainFrame()->selection()->isRange(); 4146 return S_OK; 4147 } 4148 4149 HRESULT STDMETHODCALLTYPE WebView::cutEnabled( 4150 /* [retval][out] */ BOOL* enabled) 4151 { 4152 Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor(); 4153 *enabled = editor->canCut() || editor->canDHTMLCut(); 4154 return S_OK; 4155 } 4156 4157 HRESULT STDMETHODCALLTYPE WebView::copyEnabled( 4158 /* [retval][out] */ BOOL* enabled) 4159 { 4160 Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor(); 4161 *enabled = editor->canCopy() || editor->canDHTMLCopy(); 4162 return S_OK; 4163 } 4164 4165 HRESULT STDMETHODCALLTYPE WebView::pasteEnabled( 4166 /* [retval][out] */ BOOL* enabled) 4167 { 4168 Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor(); 4169 *enabled = editor->canPaste() || editor->canDHTMLPaste(); 4170 return S_OK; 4171 } 4172 4173 HRESULT STDMETHODCALLTYPE WebView::deleteEnabled( 4174 /* [retval][out] */ BOOL* enabled) 4175 { 4176 *enabled = m_page->focusController()->focusedOrMainFrame()->editor()->canDelete(); 4177 return S_OK; 4178 } 4179 4180 HRESULT STDMETHODCALLTYPE WebView::editingEnabled( 4181 /* [retval][out] */ BOOL* enabled) 4182 { 4183 *enabled = m_page->focusController()->focusedOrMainFrame()->editor()->canEdit(); 4184 return S_OK; 4185 } 4186 4187 HRESULT STDMETHODCALLTYPE WebView::isGrammarCheckingEnabled( 4188 /* [retval][out] */ BOOL* enabled) 4189 { 4190 *enabled = grammarCheckingEnabled ? TRUE : FALSE; 4191 return S_OK; 4192 } 4193 4194 HRESULT STDMETHODCALLTYPE WebView::setGrammarCheckingEnabled( 4195 BOOL enabled) 4196 { 4197 if (!m_editingDelegate) { 4198 LOG_ERROR("No NSSpellChecker"); 4199 return E_FAIL; 4200 } 4201 4202 if (grammarCheckingEnabled == !!enabled) 4203 return S_OK; 4204 4205 grammarCheckingEnabled = !!enabled; 4206 COMPtr<IWebPreferences> prefs; 4207 if (SUCCEEDED(preferences(&prefs))) 4208 prefs->setGrammarCheckingEnabled(enabled); 4209 4210 m_editingDelegate->updateGrammar(); 4211 4212 // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here 4213 // because grammar checking only occurs on code paths that already preflight spell checking appropriately. 4214 4215 BOOL grammarEnabled; 4216 if (SUCCEEDED(isGrammarCheckingEnabled(&grammarEnabled)) && !grammarEnabled) 4217 m_mainFrame->unmarkAllBadGrammar(); 4218 4219 return S_OK; 4220 } 4221 4222 // IWebViewUndoableEditing ----------------------------------------------------- 4223 4224 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithNode( 4225 /* [in] */ IDOMNode* /*node*/) 4226 { 4227 ASSERT_NOT_REACHED(); 4228 return E_NOTIMPL; 4229 } 4230 4231 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithText( 4232 /* [in] */ BSTR text) 4233 { 4234 String textString(text, ::SysStringLen(text)); 4235 Position start = m_page->mainFrame()->selection()->selection().start(); 4236 m_page->focusController()->focusedOrMainFrame()->editor()->insertText(textString, 0); 4237 m_page->mainFrame()->selection()->setBase(start); 4238 return S_OK; 4239 } 4240 4241 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithMarkupString( 4242 /* [in] */ BSTR /*markupString*/) 4243 { 4244 ASSERT_NOT_REACHED(); 4245 return E_NOTIMPL; 4246 } 4247 4248 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithArchive( 4249 /* [in] */ IWebArchive* /*archive*/) 4250 { 4251 ASSERT_NOT_REACHED(); 4252 return E_NOTIMPL; 4253 } 4254 4255 HRESULT STDMETHODCALLTYPE WebView::deleteSelection( void) 4256 { 4257 Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor(); 4258 editor->deleteSelectionWithSmartDelete(editor->canSmartCopyOrDelete()); 4259 return S_OK; 4260 } 4261 4262 HRESULT STDMETHODCALLTYPE WebView::clearSelection( void) 4263 { 4264 m_page->focusController()->focusedOrMainFrame()->selection()->clear(); 4265 return S_OK; 4266 } 4267 4268 HRESULT STDMETHODCALLTYPE WebView::applyStyle( 4269 /* [in] */ IDOMCSSStyleDeclaration* /*style*/) 4270 { 4271 ASSERT_NOT_REACHED(); 4272 return E_NOTIMPL; 4273 } 4274 4275 // IWebViewEditingActions ------------------------------------------------------ 4276 4277 HRESULT STDMETHODCALLTYPE WebView::copy( 4278 /* [in] */ IUnknown* /*sender*/) 4279 { 4280 m_page->focusController()->focusedOrMainFrame()->editor()->command("Copy").execute(); 4281 return S_OK; 4282 } 4283 4284 HRESULT STDMETHODCALLTYPE WebView::cut( 4285 /* [in] */ IUnknown* /*sender*/) 4286 { 4287 m_page->focusController()->focusedOrMainFrame()->editor()->command("Cut").execute(); 4288 return S_OK; 4289 } 4290 4291 HRESULT STDMETHODCALLTYPE WebView::paste( 4292 /* [in] */ IUnknown* /*sender*/) 4293 { 4294 m_page->focusController()->focusedOrMainFrame()->editor()->command("Paste").execute(); 4295 return S_OK; 4296 } 4297 4298 HRESULT STDMETHODCALLTYPE WebView::copyURL( 4299 /* [in] */ BSTR url) 4300 { 4301 m_page->focusController()->focusedOrMainFrame()->editor()->copyURL(MarshallingHelpers::BSTRToKURL(url), ""); 4302 return S_OK; 4303 } 4304 4305 4306 HRESULT STDMETHODCALLTYPE WebView::copyFont( 4307 /* [in] */ IUnknown* /*sender*/) 4308 { 4309 ASSERT_NOT_REACHED(); 4310 return E_NOTIMPL; 4311 } 4312 4313 HRESULT STDMETHODCALLTYPE WebView::pasteFont( 4314 /* [in] */ IUnknown* /*sender*/) 4315 { 4316 ASSERT_NOT_REACHED(); 4317 return E_NOTIMPL; 4318 } 4319 4320 HRESULT STDMETHODCALLTYPE WebView::delete_( 4321 /* [in] */ IUnknown* /*sender*/) 4322 { 4323 m_page->focusController()->focusedOrMainFrame()->editor()->command("Delete").execute(); 4324 return S_OK; 4325 } 4326 4327 HRESULT STDMETHODCALLTYPE WebView::pasteAsPlainText( 4328 /* [in] */ IUnknown* /*sender*/) 4329 { 4330 ASSERT_NOT_REACHED(); 4331 return E_NOTIMPL; 4332 } 4333 4334 HRESULT STDMETHODCALLTYPE WebView::pasteAsRichText( 4335 /* [in] */ IUnknown* /*sender*/) 4336 { 4337 ASSERT_NOT_REACHED(); 4338 return E_NOTIMPL; 4339 } 4340 4341 HRESULT STDMETHODCALLTYPE WebView::changeFont( 4342 /* [in] */ IUnknown* /*sender*/) 4343 { 4344 ASSERT_NOT_REACHED(); 4345 return E_NOTIMPL; 4346 } 4347 4348 HRESULT STDMETHODCALLTYPE WebView::changeAttributes( 4349 /* [in] */ IUnknown* /*sender*/) 4350 { 4351 ASSERT_NOT_REACHED(); 4352 return E_NOTIMPL; 4353 } 4354 4355 HRESULT STDMETHODCALLTYPE WebView::changeDocumentBackgroundColor( 4356 /* [in] */ IUnknown* /*sender*/) 4357 { 4358 ASSERT_NOT_REACHED(); 4359 return E_NOTIMPL; 4360 } 4361 4362 HRESULT STDMETHODCALLTYPE WebView::changeColor( 4363 /* [in] */ IUnknown* /*sender*/) 4364 { 4365 ASSERT_NOT_REACHED(); 4366 return E_NOTIMPL; 4367 } 4368 4369 HRESULT STDMETHODCALLTYPE WebView::alignCenter( 4370 /* [in] */ IUnknown* /*sender*/) 4371 { 4372 ASSERT_NOT_REACHED(); 4373 return E_NOTIMPL; 4374 } 4375 4376 HRESULT STDMETHODCALLTYPE WebView::alignJustified( 4377 /* [in] */ IUnknown* /*sender*/) 4378 { 4379 ASSERT_NOT_REACHED(); 4380 return E_NOTIMPL; 4381 } 4382 4383 HRESULT STDMETHODCALLTYPE WebView::alignLeft( 4384 /* [in] */ IUnknown* /*sender*/) 4385 { 4386 ASSERT_NOT_REACHED(); 4387 return E_NOTIMPL; 4388 } 4389 4390 HRESULT STDMETHODCALLTYPE WebView::alignRight( 4391 /* [in] */ IUnknown* /*sender*/) 4392 { 4393 ASSERT_NOT_REACHED(); 4394 return E_NOTIMPL; 4395 } 4396 4397 HRESULT STDMETHODCALLTYPE WebView::checkSpelling( 4398 /* [in] */ IUnknown* /*sender*/) 4399 { 4400 if (!m_editingDelegate) { 4401 LOG_ERROR("No NSSpellChecker"); 4402 return E_FAIL; 4403 } 4404 4405 core(m_mainFrame)->editor()->advanceToNextMisspelling(); 4406 return S_OK; 4407 } 4408 4409 HRESULT STDMETHODCALLTYPE WebView::showGuessPanel( 4410 /* [in] */ IUnknown* /*sender*/) 4411 { 4412 if (!m_editingDelegate) { 4413 LOG_ERROR("No NSSpellChecker"); 4414 return E_FAIL; 4415 } 4416 4417 // Post-Tiger, this menu item is a show/hide toggle, to match AppKit. Leave Tiger behavior alone 4418 // to match rest of OS X. 4419 BOOL showing; 4420 if (SUCCEEDED(m_editingDelegate->spellingUIIsShowing(&showing)) && showing) { 4421 m_editingDelegate->showSpellingUI(FALSE); 4422 } 4423 4424 core(m_mainFrame)->editor()->advanceToNextMisspelling(true); 4425 m_editingDelegate->showSpellingUI(TRUE); 4426 return S_OK; 4427 } 4428 4429 HRESULT STDMETHODCALLTYPE WebView::performFindPanelAction( 4430 /* [in] */ IUnknown* /*sender*/) 4431 { 4432 ASSERT_NOT_REACHED(); 4433 return E_NOTIMPL; 4434 } 4435 4436 HRESULT STDMETHODCALLTYPE WebView::startSpeaking( 4437 /* [in] */ IUnknown* /*sender*/) 4438 { 4439 ASSERT_NOT_REACHED(); 4440 return E_NOTIMPL; 4441 } 4442 4443 HRESULT STDMETHODCALLTYPE WebView::stopSpeaking( 4444 /* [in] */ IUnknown* /*sender*/) 4445 { 4446 ASSERT_NOT_REACHED(); 4447 return E_NOTIMPL; 4448 } 4449 4450 // IWebNotificationObserver ----------------------------------------------------------------- 4451 4452 HRESULT STDMETHODCALLTYPE WebView::onNotify( 4453 /* [in] */ IWebNotification* notification) 4454 { 4455 BSTR nameBSTR; 4456 HRESULT hr = notification->name(&nameBSTR); 4457 if (FAILED(hr)) 4458 return hr; 4459 4460 BString name; 4461 name.adoptBSTR(nameBSTR); 4462 4463 if (!wcscmp(name, WebIconDatabase::iconDatabaseDidAddIconNotification())) 4464 return notifyDidAddIcon(notification); 4465 4466 if (!wcscmp(name, WebPreferences::webPreferencesChangedNotification())) 4467 return notifyPreferencesChanged(notification); 4468 4469 return hr; 4470 } 4471 4472 HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification) 4473 { 4474 HRESULT hr; 4475 4476 COMPtr<IUnknown> unkPrefs; 4477 hr = notification->getObject(&unkPrefs); 4478 if (FAILED(hr)) 4479 return hr; 4480 4481 COMPtr<IWebPreferences> preferences(Query, unkPrefs); 4482 if (!preferences) 4483 return E_NOINTERFACE; 4484 4485 ASSERT(preferences == m_preferences); 4486 4487 BSTR str; 4488 int size; 4489 BOOL enabled; 4490 4491 Settings* settings = m_page->settings(); 4492 4493 hr = preferences->cursiveFontFamily(&str); 4494 if (FAILED(hr)) 4495 return hr; 4496 settings->setCursiveFontFamily(AtomicString(str, SysStringLen(str))); 4497 SysFreeString(str); 4498 4499 hr = preferences->defaultFixedFontSize(&size); 4500 if (FAILED(hr)) 4501 return hr; 4502 settings->setDefaultFixedFontSize(size); 4503 4504 hr = preferences->defaultFontSize(&size); 4505 if (FAILED(hr)) 4506 return hr; 4507 settings->setDefaultFontSize(size); 4508 4509 hr = preferences->defaultTextEncodingName(&str); 4510 if (FAILED(hr)) 4511 return hr; 4512 settings->setDefaultTextEncodingName(String(str, SysStringLen(str))); 4513 SysFreeString(str); 4514 4515 hr = preferences->fantasyFontFamily(&str); 4516 if (FAILED(hr)) 4517 return hr; 4518 settings->setFantasyFontFamily(AtomicString(str, SysStringLen(str))); 4519 SysFreeString(str); 4520 4521 hr = preferences->fixedFontFamily(&str); 4522 if (FAILED(hr)) 4523 return hr; 4524 settings->setFixedFontFamily(AtomicString(str, SysStringLen(str))); 4525 SysFreeString(str); 4526 4527 hr = preferences->isJavaEnabled(&enabled); 4528 if (FAILED(hr)) 4529 return hr; 4530 settings->setJavaEnabled(!!enabled); 4531 4532 hr = preferences->isJavaScriptEnabled(&enabled); 4533 if (FAILED(hr)) 4534 return hr; 4535 settings->setJavaScriptEnabled(!!enabled); 4536 4537 hr = preferences->javaScriptCanOpenWindowsAutomatically(&enabled); 4538 if (FAILED(hr)) 4539 return hr; 4540 settings->setJavaScriptCanOpenWindowsAutomatically(!!enabled); 4541 4542 hr = preferences->minimumFontSize(&size); 4543 if (FAILED(hr)) 4544 return hr; 4545 settings->setMinimumFontSize(size); 4546 4547 hr = preferences->minimumLogicalFontSize(&size); 4548 if (FAILED(hr)) 4549 return hr; 4550 settings->setMinimumLogicalFontSize(size); 4551 4552 hr = preferences->arePlugInsEnabled(&enabled); 4553 if (FAILED(hr)) 4554 return hr; 4555 settings->setPluginsEnabled(!!enabled); 4556 4557 hr = preferences->privateBrowsingEnabled(&enabled); 4558 if (FAILED(hr)) 4559 return hr; 4560 settings->setPrivateBrowsingEnabled(!!enabled); 4561 4562 hr = preferences->sansSerifFontFamily(&str); 4563 if (FAILED(hr)) 4564 return hr; 4565 settings->setSansSerifFontFamily(AtomicString(str, SysStringLen(str))); 4566 SysFreeString(str); 4567 4568 hr = preferences->serifFontFamily(&str); 4569 if (FAILED(hr)) 4570 return hr; 4571 settings->setSerifFontFamily(AtomicString(str, SysStringLen(str))); 4572 SysFreeString(str); 4573 4574 hr = preferences->standardFontFamily(&str); 4575 if (FAILED(hr)) 4576 return hr; 4577 settings->setStandardFontFamily(AtomicString(str, SysStringLen(str))); 4578 SysFreeString(str); 4579 4580 hr = preferences->loadsImagesAutomatically(&enabled); 4581 if (FAILED(hr)) 4582 return hr; 4583 settings->setLoadsImagesAutomatically(!!enabled); 4584 4585 hr = preferences->userStyleSheetEnabled(&enabled); 4586 if (FAILED(hr)) 4587 return hr; 4588 if (enabled) { 4589 hr = preferences->userStyleSheetLocation(&str); 4590 if (FAILED(hr)) 4591 return hr; 4592 4593 RetainPtr<CFStringRef> urlString(AdoptCF, String(str, SysStringLen(str)).createCFString()); 4594 RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithString(kCFAllocatorDefault, urlString.get(), 0)); 4595 4596 // Check if the passed in string is a path and convert it to a URL. 4597 // FIXME: This is a workaround for nightly builds until we can get Safari to pass 4598 // in an URL here. See <rdar://problem/5478378> 4599 if (!url) { 4600 DWORD len = SysStringLen(str) + 1; 4601 4602 int result = WideCharToMultiByte(CP_UTF8, 0, str, len, 0, 0, 0, 0); 4603 Vector<UInt8> utf8Path(result); 4604 if (!WideCharToMultiByte(CP_UTF8, 0, str, len, (LPSTR)utf8Path.data(), result, 0, 0)) 4605 return E_FAIL; 4606 4607 url.adoptCF(CFURLCreateFromFileSystemRepresentation(0, utf8Path.data(), result - 1, false)); 4608 } 4609 4610 settings->setUserStyleSheetLocation(url.get()); 4611 SysFreeString(str); 4612 } else { 4613 settings->setUserStyleSheetLocation(KURL()); 4614 } 4615 4616 hr = preferences->shouldPrintBackgrounds(&enabled); 4617 if (FAILED(hr)) 4618 return hr; 4619 settings->setShouldPrintBackgrounds(!!enabled); 4620 4621 hr = preferences->textAreasAreResizable(&enabled); 4622 if (FAILED(hr)) 4623 return hr; 4624 settings->setTextAreasAreResizable(!!enabled); 4625 4626 WebKitEditableLinkBehavior behavior; 4627 hr = preferences->editableLinkBehavior(&behavior); 4628 if (FAILED(hr)) 4629 return hr; 4630 settings->setEditableLinkBehavior((EditableLinkBehavior)behavior); 4631 4632 WebKitEditingBehavior editingBehavior; 4633 hr = preferences->editingBehavior(&editingBehavior); 4634 if (FAILED(hr)) 4635 return hr; 4636 settings->setEditingBehaviorType((EditingBehaviorType)editingBehavior); 4637 4638 hr = preferences->usesPageCache(&enabled); 4639 if (FAILED(hr)) 4640 return hr; 4641 settings->setUsesPageCache(!!enabled); 4642 4643 hr = preferences->isDOMPasteAllowed(&enabled); 4644 if (FAILED(hr)) 4645 return hr; 4646 settings->setDOMPasteAllowed(!!enabled); 4647 4648 hr = preferences->shouldPaintCustomScrollbars(&enabled); 4649 if (FAILED(hr)) 4650 return hr; 4651 settings->setShouldPaintCustomScrollbars(!!enabled); 4652 4653 hr = preferences->zoomsTextOnly(&enabled); 4654 if (FAILED(hr)) 4655 return hr; 4656 4657 if (m_zoomsTextOnly != !!enabled) 4658 setZoomMultiplier(m_zoomMultiplier, enabled); 4659 4660 settings->setShowsURLsInToolTips(false); 4661 settings->setForceFTPDirectoryListings(true); 4662 settings->setDeveloperExtrasEnabled(developerExtrasEnabled()); 4663 settings->setNeedsSiteSpecificQuirks(s_allowSiteSpecificHacks); 4664 4665 FontSmoothingType smoothingType; 4666 hr = preferences->fontSmoothing(&smoothingType); 4667 if (FAILED(hr)) 4668 return hr; 4669 settings->setFontRenderingMode(smoothingType != FontSmoothingTypeWindows ? NormalRenderingMode : AlternateRenderingMode); 4670 4671 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences); 4672 if (prefsPrivate) { 4673 hr = prefsPrivate->authorAndUserStylesEnabled(&enabled); 4674 if (FAILED(hr)) 4675 return hr; 4676 settings->setAuthorAndUserStylesEnabled(enabled); 4677 } 4678 4679 hr = prefsPrivate->inApplicationChromeMode(&enabled); 4680 if (FAILED(hr)) 4681 return hr; 4682 settings->setApplicationChromeMode(enabled); 4683 4684 hr = prefsPrivate->offlineWebApplicationCacheEnabled(&enabled); 4685 if (FAILED(hr)) 4686 return hr; 4687 settings->setOfflineWebApplicationCacheEnabled(enabled); 4688 4689 #if ENABLE(DATABASE) 4690 hr = prefsPrivate->databasesEnabled(&enabled); 4691 if (FAILED(hr)) 4692 return hr; 4693 AbstractDatabase::setIsAvailable(enabled); 4694 #endif 4695 4696 hr = prefsPrivate->localStorageEnabled(&enabled); 4697 if (FAILED(hr)) 4698 return hr; 4699 settings->setLocalStorageEnabled(enabled); 4700 4701 hr = prefsPrivate->experimentalNotificationsEnabled(&enabled); 4702 if (FAILED(hr)) 4703 return hr; 4704 settings->setExperimentalNotificationsEnabled(enabled); 4705 4706 hr = prefsPrivate->isWebSecurityEnabled(&enabled); 4707 if (FAILED(hr)) 4708 return hr; 4709 settings->setWebSecurityEnabled(!!enabled); 4710 4711 hr = prefsPrivate->allowUniversalAccessFromFileURLs(&enabled); 4712 if (FAILED(hr)) 4713 return hr; 4714 settings->setAllowUniversalAccessFromFileURLs(!!enabled); 4715 4716 hr = prefsPrivate->allowFileAccessFromFileURLs(&enabled); 4717 if (FAILED(hr)) 4718 return hr; 4719 settings->setAllowFileAccessFromFileURLs(!!enabled); 4720 4721 hr = prefsPrivate->javaScriptCanAccessClipboard(&enabled); 4722 if (FAILED(hr)) 4723 return hr; 4724 settings->setJavaScriptCanAccessClipboard(!!enabled); 4725 4726 hr = prefsPrivate->isXSSAuditorEnabled(&enabled); 4727 if (FAILED(hr)) 4728 return hr; 4729 settings->setXSSAuditorEnabled(!!enabled); 4730 4731 #if USE(SAFARI_THEME) 4732 hr = prefsPrivate->shouldPaintNativeControls(&enabled); 4733 if (FAILED(hr)) 4734 return hr; 4735 settings->setShouldPaintNativeControls(!!enabled); 4736 #endif 4737 4738 hr = prefsPrivate->shouldUseHighResolutionTimers(&enabled); 4739 if (FAILED(hr)) 4740 return hr; 4741 settings->setShouldUseHighResolutionTimers(enabled); 4742 4743 UINT runTime; 4744 hr = prefsPrivate->pluginAllowedRunTime(&runTime); 4745 if (FAILED(hr)) 4746 return hr; 4747 settings->setPluginAllowedRunTime(runTime); 4748 4749 hr = prefsPrivate->isFrameFlatteningEnabled(&enabled); 4750 if (FAILED(hr)) 4751 return hr; 4752 settings->setFrameFlatteningEnabled(enabled); 4753 4754 #if USE(ACCELERATED_COMPOSITING) 4755 hr = prefsPrivate->acceleratedCompositingEnabled(&enabled); 4756 if (FAILED(hr)) 4757 return hr; 4758 settings->setAcceleratedCompositingEnabled(enabled); 4759 #endif 4760 4761 hr = prefsPrivate->showDebugBorders(&enabled); 4762 if (FAILED(hr)) 4763 return hr; 4764 settings->setShowDebugBorders(enabled); 4765 4766 hr = prefsPrivate->showRepaintCounter(&enabled); 4767 if (FAILED(hr)) 4768 return hr; 4769 settings->setShowRepaintCounter(enabled); 4770 4771 #if ENABLE(WEB_AUDIO) 4772 settings->setWebAudioEnabled(true); 4773 #endif // ENABLE(WEB_AUDIO) 4774 4775 #if ENABLE(WEBGL) 4776 settings->setWebGLEnabled(true); 4777 #endif // ENABLE(WEBGL) 4778 4779 hr = prefsPrivate->isDNSPrefetchingEnabled(&enabled); 4780 if (FAILED(hr)) 4781 return hr; 4782 settings->setDNSPrefetchingEnabled(enabled); 4783 4784 hr = prefsPrivate->memoryInfoEnabled(&enabled); 4785 if (FAILED(hr)) 4786 return hr; 4787 settings->setMemoryInfoEnabled(enabled); 4788 4789 hr = prefsPrivate->hyperlinkAuditingEnabled(&enabled); 4790 if (FAILED(hr)) 4791 return hr; 4792 settings->setHyperlinkAuditingEnabled(enabled); 4793 4794 hr = prefsPrivate->loadsSiteIconsIgnoringImageLoadingPreference(&enabled); 4795 if (FAILED(hr)) 4796 return hr; 4797 settings->setLoadsSiteIconsIgnoringImageLoadingSetting(!!enabled); 4798 4799 if (!m_closeWindowTimer) 4800 m_mainFrame->invalidate(); // FIXME 4801 4802 hr = updateSharedSettingsFromPreferencesIfNeeded(preferences.get()); 4803 if (FAILED(hr)) 4804 return hr; 4805 4806 return S_OK; 4807 } 4808 4809 HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences* preferences) 4810 { 4811 if (preferences != WebPreferences::sharedStandardPreferences()) 4812 return S_OK; 4813 4814 WebKitCookieStorageAcceptPolicy acceptPolicy; 4815 HRESULT hr = preferences->cookieStorageAcceptPolicy(&acceptPolicy); 4816 if (FAILED(hr)) 4817 return hr; 4818 4819 #if USE(CFNETWORK) 4820 // Set cookie storage accept policy 4821 if (CFHTTPCookieStorageRef cookieStorage = currentCookieStorage()) 4822 CFHTTPCookieStorageSetCookieAcceptPolicy(cookieStorage, acceptPolicy); 4823 #endif 4824 4825 return S_OK; 4826 } 4827 4828 // IWebViewPrivate ------------------------------------------------------------ 4829 4830 HRESULT STDMETHODCALLTYPE WebView::MIMETypeForExtension( 4831 /* [in] */ BSTR extension, 4832 /* [retval][out] */ BSTR* mimeType) 4833 { 4834 if (!mimeType) 4835 return E_POINTER; 4836 4837 String extensionStr(extension, SysStringLen(extension)); 4838 4839 *mimeType = BString(MIMETypeRegistry::getMIMETypeForExtension(extensionStr)).release(); 4840 4841 return S_OK; 4842 } 4843 4844 HRESULT STDMETHODCALLTYPE WebView::setCustomDropTarget( 4845 /* [in] */ IDropTarget* dt) 4846 { 4847 ASSERT(::IsWindow(m_viewWindow)); 4848 if (!dt) 4849 return E_POINTER; 4850 m_hasCustomDropTarget = true; 4851 revokeDragDrop(); 4852 return ::RegisterDragDrop(m_viewWindow,dt); 4853 } 4854 4855 HRESULT STDMETHODCALLTYPE WebView::removeCustomDropTarget() 4856 { 4857 if (!m_hasCustomDropTarget) 4858 return S_OK; 4859 m_hasCustomDropTarget = false; 4860 revokeDragDrop(); 4861 return registerDragDrop(); 4862 } 4863 4864 HRESULT STDMETHODCALLTYPE WebView::setInViewSourceMode( 4865 /* [in] */ BOOL flag) 4866 { 4867 if (!m_mainFrame) 4868 return E_FAIL; 4869 4870 return m_mainFrame->setInViewSourceMode(flag); 4871 } 4872 4873 HRESULT STDMETHODCALLTYPE WebView::inViewSourceMode( 4874 /* [retval][out] */ BOOL* flag) 4875 { 4876 if (!m_mainFrame) 4877 return E_FAIL; 4878 4879 return m_mainFrame->inViewSourceMode(flag); 4880 } 4881 4882 HRESULT STDMETHODCALLTYPE WebView::viewWindow( 4883 /* [retval][out] */ OLE_HANDLE *window) 4884 { 4885 *window = (OLE_HANDLE)(ULONG64)m_viewWindow; 4886 return S_OK; 4887 } 4888 4889 HRESULT STDMETHODCALLTYPE WebView::setFormDelegate( 4890 /* [in] */ IWebFormDelegate *formDelegate) 4891 { 4892 m_formDelegate = formDelegate; 4893 return S_OK; 4894 } 4895 4896 HRESULT STDMETHODCALLTYPE WebView::formDelegate( 4897 /* [retval][out] */ IWebFormDelegate **formDelegate) 4898 { 4899 if (!m_formDelegate) 4900 return E_FAIL; 4901 4902 return m_formDelegate.copyRefTo(formDelegate); 4903 } 4904 4905 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegatePrivate( 4906 /* [in] */ IWebFrameLoadDelegatePrivate* d) 4907 { 4908 m_frameLoadDelegatePrivate = d; 4909 return S_OK; 4910 } 4911 4912 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegatePrivate( 4913 /* [out][retval] */ IWebFrameLoadDelegatePrivate** d) 4914 { 4915 if (!m_frameLoadDelegatePrivate) 4916 return E_FAIL; 4917 4918 return m_frameLoadDelegatePrivate.copyRefTo(d); 4919 } 4920 4921 HRESULT STDMETHODCALLTYPE WebView::scrollOffset( 4922 /* [retval][out] */ LPPOINT offset) 4923 { 4924 if (!offset) 4925 return E_POINTER; 4926 IntSize offsetIntSize = m_page->mainFrame()->view()->scrollOffset(); 4927 offset->x = offsetIntSize.width(); 4928 offset->y = offsetIntSize.height(); 4929 return S_OK; 4930 } 4931 4932 HRESULT STDMETHODCALLTYPE WebView::scrollBy( 4933 /* [in] */ LPPOINT offset) 4934 { 4935 if (!offset) 4936 return E_POINTER; 4937 m_page->mainFrame()->view()->scrollBy(IntSize(offset->x, offset->y)); 4938 return S_OK; 4939 } 4940 4941 HRESULT STDMETHODCALLTYPE WebView::visibleContentRect( 4942 /* [retval][out] */ LPRECT rect) 4943 { 4944 if (!rect) 4945 return E_POINTER; 4946 FloatRect visibleContent = m_page->mainFrame()->view()->visibleContentRect(); 4947 rect->left = (LONG) visibleContent.x(); 4948 rect->top = (LONG) visibleContent.y(); 4949 rect->right = (LONG) visibleContent.maxX(); 4950 rect->bottom = (LONG) visibleContent.maxY(); 4951 return S_OK; 4952 } 4953 4954 static DWORD dragOperationToDragCursor(DragOperation op) { 4955 DWORD res = DROPEFFECT_NONE; 4956 if (op & DragOperationCopy) 4957 res = DROPEFFECT_COPY; 4958 else if (op & DragOperationLink) 4959 res = DROPEFFECT_LINK; 4960 else if (op & DragOperationMove) 4961 res = DROPEFFECT_MOVE; 4962 else if (op & DragOperationGeneric) 4963 res = DROPEFFECT_MOVE; //This appears to be the Firefox behaviour 4964 return res; 4965 } 4966 4967 DragOperation WebView::keyStateToDragOperation(DWORD grfKeyState) const 4968 { 4969 if (!m_page) 4970 return DragOperationNone; 4971 4972 // Conforms to Microsoft's key combinations as documented for 4973 // IDropTarget::DragOver. Note, grfKeyState is the current 4974 // state of the keyboard modifier keys on the keyboard. See: 4975 // <http://msdn.microsoft.com/en-us/library/ms680129(VS.85).aspx>. 4976 DragOperation operation = m_page->dragController()->sourceDragOperation(); 4977 4978 if ((grfKeyState & (MK_CONTROL | MK_SHIFT)) == (MK_CONTROL | MK_SHIFT)) 4979 operation = DragOperationLink; 4980 else if ((grfKeyState & MK_CONTROL) == MK_CONTROL) 4981 operation = DragOperationCopy; 4982 else if ((grfKeyState & MK_SHIFT) == MK_SHIFT) 4983 operation = DragOperationGeneric; 4984 4985 return operation; 4986 } 4987 4988 HRESULT STDMETHODCALLTYPE WebView::DragEnter( 4989 IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) 4990 { 4991 m_dragData = 0; 4992 4993 if (m_dropTargetHelper) 4994 m_dropTargetHelper->DragEnter(m_viewWindow, pDataObject, (POINT*)&pt, *pdwEffect); 4995 4996 POINTL localpt = pt; 4997 ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt); 4998 DragData data(pDataObject, IntPoint(localpt.x, localpt.y), 4999 IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState)); 5000 *pdwEffect = dragOperationToDragCursor(m_page->dragController()->dragEntered(&data)); 5001 5002 m_lastDropEffect = *pdwEffect; 5003 m_dragData = pDataObject; 5004 5005 return S_OK; 5006 } 5007 5008 HRESULT STDMETHODCALLTYPE WebView::DragOver( 5009 DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) 5010 { 5011 if (m_dropTargetHelper) 5012 m_dropTargetHelper->DragOver((POINT*)&pt, *pdwEffect); 5013 5014 if (m_dragData) { 5015 POINTL localpt = pt; 5016 ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt); 5017 DragData data(m_dragData.get(), IntPoint(localpt.x, localpt.y), 5018 IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState)); 5019 *pdwEffect = dragOperationToDragCursor(m_page->dragController()->dragUpdated(&data)); 5020 } else 5021 *pdwEffect = DROPEFFECT_NONE; 5022 5023 m_lastDropEffect = *pdwEffect; 5024 return S_OK; 5025 } 5026 5027 HRESULT STDMETHODCALLTYPE WebView::DragLeave() 5028 { 5029 if (m_dropTargetHelper) 5030 m_dropTargetHelper->DragLeave(); 5031 5032 if (m_dragData) { 5033 DragData data(m_dragData.get(), IntPoint(), IntPoint(), 5034 DragOperationNone); 5035 m_page->dragController()->dragExited(&data); 5036 m_dragData = 0; 5037 } 5038 return S_OK; 5039 } 5040 5041 HRESULT STDMETHODCALLTYPE WebView::Drop( 5042 IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) 5043 { 5044 if (m_dropTargetHelper) 5045 m_dropTargetHelper->Drop(pDataObject, (POINT*)&pt, *pdwEffect); 5046 5047 m_dragData = 0; 5048 *pdwEffect = m_lastDropEffect; 5049 POINTL localpt = pt; 5050 ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt); 5051 DragData data(pDataObject, IntPoint(localpt.x, localpt.y), 5052 IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState)); 5053 m_page->dragController()->performDrag(&data); 5054 return S_OK; 5055 } 5056 5057 HRESULT STDMETHODCALLTYPE WebView::canHandleRequest( 5058 IWebURLRequest *request, 5059 BOOL *result) 5060 { 5061 COMPtr<WebMutableURLRequest> requestImpl; 5062 5063 HRESULT hr = request->QueryInterface(&requestImpl); 5064 if (FAILED(hr)) 5065 return hr; 5066 5067 *result = !!canHandleRequest(requestImpl->resourceRequest()); 5068 return S_OK; 5069 } 5070 5071 HRESULT STDMETHODCALLTYPE WebView::standardUserAgentWithApplicationName( 5072 BSTR applicationName, 5073 BSTR* groupName) 5074 { 5075 if (!groupName) { 5076 ASSERT_NOT_REACHED(); 5077 return E_POINTER; 5078 } 5079 5080 *groupName; 5081 5082 if (!applicationName) { 5083 ASSERT_NOT_REACHED(); 5084 return E_POINTER; 5085 } 5086 5087 BString applicationNameBString(applicationName); 5088 *groupName = BString(standardUserAgentWithApplicationName(String(applicationNameBString, SysStringLen(applicationNameBString)))).release(); 5089 return S_OK; 5090 } 5091 5092 HRESULT STDMETHODCALLTYPE WebView::clearFocusNode() 5093 { 5094 if (m_page && m_page->focusController()) 5095 m_page->focusController()->setFocusedNode(0, 0); 5096 return S_OK; 5097 } 5098 5099 HRESULT STDMETHODCALLTYPE WebView::setInitialFocus( 5100 /* [in] */ BOOL forward) 5101 { 5102 if (m_page && m_page->focusController()) { 5103 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 5104 frame->document()->setFocusedNode(0); 5105 m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0); 5106 } 5107 return S_OK; 5108 } 5109 5110 HRESULT STDMETHODCALLTYPE WebView::setTabKeyCyclesThroughElements( 5111 /* [in] */ BOOL cycles) 5112 { 5113 if (m_page) 5114 m_page->setTabKeyCyclesThroughElements(!!cycles); 5115 5116 return S_OK; 5117 } 5118 5119 HRESULT STDMETHODCALLTYPE WebView::tabKeyCyclesThroughElements( 5120 /* [retval][out] */ BOOL* result) 5121 { 5122 if (!result) { 5123 ASSERT_NOT_REACHED(); 5124 return E_POINTER; 5125 } 5126 5127 *result = m_page && m_page->tabKeyCyclesThroughElements() ? TRUE : FALSE; 5128 return S_OK; 5129 } 5130 5131 HRESULT STDMETHODCALLTYPE WebView::setAllowSiteSpecificHacks( 5132 /* [in] */ BOOL allow) 5133 { 5134 s_allowSiteSpecificHacks = !!allow; 5135 // FIXME: This sets a global so it needs to call notifyPreferencesChanged 5136 // on all WebView objects (not just itself). 5137 return S_OK; 5138 } 5139 5140 HRESULT STDMETHODCALLTYPE WebView::addAdditionalPluginDirectory( 5141 /* [in] */ BSTR directory) 5142 { 5143 PluginDatabase::installedPlugins()->addExtraPluginDirectory(String(directory, SysStringLen(directory))); 5144 return S_OK; 5145 } 5146 5147 HRESULT STDMETHODCALLTYPE WebView::loadBackForwardListFromOtherView( 5148 /* [in] */ IWebView* otherView) 5149 { 5150 if (!m_page) 5151 return E_FAIL; 5152 5153 // It turns out the right combination of behavior is done with the back/forward load 5154 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items 5155 // in the back forward list, and go to the current one. 5156 BackForwardList* backForwardList = m_page->backForwardList(); 5157 ASSERT(!backForwardList->currentItem()); // destination list should be empty 5158 5159 COMPtr<WebView> otherWebView; 5160 if (FAILED(otherView->QueryInterface(&otherWebView))) 5161 return E_FAIL; 5162 BackForwardList* otherBackForwardList = otherWebView->m_page->backForwardList(); 5163 if (!otherBackForwardList->currentItem()) 5164 return S_OK; // empty back forward list, bail 5165 5166 HistoryItem* newItemToGoTo = 0; 5167 5168 int lastItemIndex = otherBackForwardList->forwardListCount(); 5169 for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) { 5170 if (!i) { 5171 // If this item is showing , save away its current scroll and form state, 5172 // since that might have changed since loading and it is normally not saved 5173 // until we leave that page. 5174 otherWebView->m_page->mainFrame()->loader()->history()->saveDocumentAndScrollState(); 5175 } 5176 RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy(); 5177 if (!i) 5178 newItemToGoTo = newItem.get(); 5179 backForwardList->addItem(newItem.release()); 5180 } 5181 5182 ASSERT(newItemToGoTo); 5183 m_page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward); 5184 return S_OK; 5185 } 5186 5187 HRESULT STDMETHODCALLTYPE WebView::clearUndoRedoOperations() 5188 { 5189 if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) 5190 frame->editor()->clearUndoRedoOperations(); 5191 return S_OK; 5192 } 5193 5194 HRESULT STDMETHODCALLTYPE WebView::shouldClose( 5195 /* [retval][out] */ BOOL* result) 5196 { 5197 if (!result) { 5198 ASSERT_NOT_REACHED(); 5199 return E_POINTER; 5200 } 5201 5202 *result = TRUE; 5203 if (Frame* frame = m_page->mainFrame()) 5204 *result = frame->loader()->shouldClose(); 5205 return S_OK; 5206 } 5207 5208 HRESULT WebView::registerDragDrop() 5209 { 5210 ASSERT(::IsWindow(m_viewWindow)); 5211 return ::RegisterDragDrop(m_viewWindow, this); 5212 } 5213 5214 HRESULT WebView::revokeDragDrop() 5215 { 5216 if (!m_viewWindow) 5217 return S_OK; 5218 5219 return ::RevokeDragDrop(m_viewWindow); 5220 } 5221 5222 HRESULT WebView::setProhibitsMainFrameScrolling(BOOL b) 5223 { 5224 if (!m_page) 5225 return E_FAIL; 5226 5227 m_page->mainFrame()->view()->setProhibitsScrolling(b); 5228 return S_OK; 5229 } 5230 5231 HRESULT WebView::setShouldApplyMacFontAscentHack(BOOL b) 5232 { 5233 SimpleFontData::setShouldApplyMacAscentHack(b); 5234 return S_OK; 5235 } 5236 5237 class IMMDict { 5238 typedef HIMC (CALLBACK *getContextPtr)(HWND); 5239 typedef BOOL (CALLBACK *releaseContextPtr)(HWND, HIMC); 5240 typedef LONG (CALLBACK *getCompositionStringPtr)(HIMC, DWORD, LPVOID, DWORD); 5241 typedef BOOL (CALLBACK *setCandidateWindowPtr)(HIMC, LPCANDIDATEFORM); 5242 typedef BOOL (CALLBACK *setOpenStatusPtr)(HIMC, BOOL); 5243 typedef BOOL (CALLBACK *notifyIMEPtr)(HIMC, DWORD, DWORD, DWORD); 5244 typedef BOOL (CALLBACK *associateContextExPtr)(HWND, HIMC, DWORD); 5245 5246 public: 5247 getContextPtr getContext; 5248 releaseContextPtr releaseContext; 5249 getCompositionStringPtr getCompositionString; 5250 setCandidateWindowPtr setCandidateWindow; 5251 setOpenStatusPtr setOpenStatus; 5252 notifyIMEPtr notifyIME; 5253 associateContextExPtr associateContextEx; 5254 5255 static const IMMDict& dict(); 5256 private: 5257 IMMDict(); 5258 HMODULE m_instance; 5259 }; 5260 5261 const IMMDict& IMMDict::dict() 5262 { 5263 static IMMDict instance; 5264 return instance; 5265 } 5266 5267 IMMDict::IMMDict() 5268 { 5269 m_instance = ::LoadLibraryW(L"IMM32.DLL"); 5270 getContext = reinterpret_cast<getContextPtr>(::GetProcAddress(m_instance, "ImmGetContext")); 5271 ASSERT(getContext); 5272 releaseContext = reinterpret_cast<releaseContextPtr>(::GetProcAddress(m_instance, "ImmReleaseContext")); 5273 ASSERT(releaseContext); 5274 getCompositionString = reinterpret_cast<getCompositionStringPtr>(::GetProcAddress(m_instance, "ImmGetCompositionStringW")); 5275 ASSERT(getCompositionString); 5276 setCandidateWindow = reinterpret_cast<setCandidateWindowPtr>(::GetProcAddress(m_instance, "ImmSetCandidateWindow")); 5277 ASSERT(setCandidateWindow); 5278 setOpenStatus = reinterpret_cast<setOpenStatusPtr>(::GetProcAddress(m_instance, "ImmSetOpenStatus")); 5279 ASSERT(setOpenStatus); 5280 notifyIME = reinterpret_cast<notifyIMEPtr>(::GetProcAddress(m_instance, "ImmNotifyIME")); 5281 ASSERT(notifyIME); 5282 associateContextEx = reinterpret_cast<associateContextExPtr>(::GetProcAddress(m_instance, "ImmAssociateContextEx")); 5283 ASSERT(associateContextEx); 5284 } 5285 5286 HIMC WebView::getIMMContext() 5287 { 5288 HIMC context = IMMDict::dict().getContext(m_viewWindow); 5289 return context; 5290 } 5291 5292 void WebView::releaseIMMContext(HIMC hIMC) 5293 { 5294 if (!hIMC) 5295 return; 5296 IMMDict::dict().releaseContext(m_viewWindow, hIMC); 5297 } 5298 5299 void WebView::prepareCandidateWindow(Frame* targetFrame, HIMC hInputContext) 5300 { 5301 IntRect caret; 5302 if (RefPtr<Range> range = targetFrame->selection()->selection().toNormalizedRange()) { 5303 ExceptionCode ec = 0; 5304 RefPtr<Range> tempRange = range->cloneRange(ec); 5305 caret = targetFrame->editor()->firstRectForRange(tempRange.get()); 5306 } 5307 caret = targetFrame->view()->contentsToWindow(caret); 5308 CANDIDATEFORM form; 5309 form.dwIndex = 0; 5310 form.dwStyle = CFS_EXCLUDE; 5311 form.ptCurrentPos.x = caret.x(); 5312 form.ptCurrentPos.y = caret.y() + caret.height(); 5313 form.rcArea.top = caret.y(); 5314 form.rcArea.bottom = caret.maxY(); 5315 form.rcArea.left = caret.x(); 5316 form.rcArea.right = caret.maxX(); 5317 IMMDict::dict().setCandidateWindow(hInputContext, &form); 5318 } 5319 5320 void WebView::resetIME(Frame* targetFrame) 5321 { 5322 if (targetFrame) 5323 targetFrame->editor()->confirmCompositionWithoutDisturbingSelection(); 5324 5325 if (HIMC hInputContext = getIMMContext()) { 5326 IMMDict::dict().notifyIME(hInputContext, NI_COMPOSITIONSTR, CPS_CANCEL, 0); 5327 releaseIMMContext(hInputContext); 5328 } 5329 } 5330 5331 void WebView::updateSelectionForIME() 5332 { 5333 Frame* targetFrame = m_page->focusController()->focusedOrMainFrame(); 5334 if (!targetFrame || !targetFrame->editor()->hasComposition()) 5335 return; 5336 5337 if (targetFrame->editor()->ignoreCompositionSelectionChange()) 5338 return; 5339 5340 unsigned start; 5341 unsigned end; 5342 if (!targetFrame->editor()->getCompositionSelection(start, end)) 5343 resetIME(targetFrame); 5344 } 5345 5346 void WebView::setInputMethodState(bool enabled) 5347 { 5348 IMMDict::dict().associateContextEx(m_viewWindow, 0, enabled ? IACE_DEFAULT : 0); 5349 } 5350 5351 void WebView::selectionChanged() 5352 { 5353 updateSelectionForIME(); 5354 } 5355 5356 bool WebView::onIMEStartComposition() 5357 { 5358 LOG(TextInput, "onIMEStartComposition"); 5359 m_inIMEComposition++; 5360 Frame* targetFrame = m_page->focusController()->focusedOrMainFrame(); 5361 if (!targetFrame) 5362 return true; 5363 5364 HIMC hInputContext = getIMMContext(); 5365 prepareCandidateWindow(targetFrame, hInputContext); 5366 releaseIMMContext(hInputContext); 5367 return true; 5368 } 5369 5370 static bool getCompositionString(HIMC hInputContext, DWORD type, String& result) 5371 { 5372 int compositionLength = IMMDict::dict().getCompositionString(hInputContext, type, 0, 0); 5373 if (compositionLength <= 0) 5374 return false; 5375 Vector<UChar> compositionBuffer(compositionLength / 2); 5376 compositionLength = IMMDict::dict().getCompositionString(hInputContext, type, (LPVOID)compositionBuffer.data(), compositionLength); 5377 result = String(compositionBuffer.data(), compositionLength / 2); 5378 ASSERT(!compositionLength || compositionBuffer[0]); 5379 ASSERT(!compositionLength || compositionBuffer[compositionLength / 2 - 1]); 5380 return true; 5381 } 5382 5383 static void compositionToUnderlines(const Vector<DWORD>& clauses, const Vector<BYTE>& attributes, Vector<CompositionUnderline>& underlines) 5384 { 5385 if (clauses.isEmpty()) { 5386 underlines.clear(); 5387 return; 5388 } 5389 5390 const size_t numBoundaries = clauses.size() - 1; 5391 underlines.resize(numBoundaries); 5392 for (unsigned i = 0; i < numBoundaries; i++) { 5393 underlines[i].startOffset = clauses[i]; 5394 underlines[i].endOffset = clauses[i + 1]; 5395 BYTE attribute = attributes[clauses[i]]; 5396 underlines[i].thick = attribute == ATTR_TARGET_CONVERTED || attribute == ATTR_TARGET_NOTCONVERTED; 5397 underlines[i].color = Color(0,0,0); 5398 } 5399 } 5400 5401 #if !LOG_DISABLED 5402 #define APPEND_ARGUMENT_NAME(name) \ 5403 if (lparam & name) { \ 5404 if (needsComma) \ 5405 result += ", "; \ 5406 result += #name; \ 5407 needsComma = true; \ 5408 } 5409 5410 static String imeCompositionArgumentNames(LPARAM lparam) 5411 { 5412 String result; 5413 bool needsComma = false; 5414 if (lparam & GCS_COMPATTR) { 5415 result = "GCS_COMPATTR"; 5416 needsComma = true; 5417 } 5418 APPEND_ARGUMENT_NAME(GCS_COMPCLAUSE); 5419 APPEND_ARGUMENT_NAME(GCS_COMPREADSTR); 5420 APPEND_ARGUMENT_NAME(GCS_COMPREADATTR); 5421 APPEND_ARGUMENT_NAME(GCS_COMPREADCLAUSE); 5422 APPEND_ARGUMENT_NAME(GCS_COMPSTR); 5423 APPEND_ARGUMENT_NAME(GCS_CURSORPOS); 5424 APPEND_ARGUMENT_NAME(GCS_DELTASTART); 5425 APPEND_ARGUMENT_NAME(GCS_RESULTCLAUSE); 5426 APPEND_ARGUMENT_NAME(GCS_RESULTREADCLAUSE); 5427 APPEND_ARGUMENT_NAME(GCS_RESULTREADSTR); 5428 APPEND_ARGUMENT_NAME(GCS_RESULTSTR); 5429 APPEND_ARGUMENT_NAME(CS_INSERTCHAR); 5430 APPEND_ARGUMENT_NAME(CS_NOMOVECARET); 5431 5432 return result; 5433 } 5434 5435 static String imeNotificationName(WPARAM wparam) 5436 { 5437 switch (wparam) { 5438 case IMN_CHANGECANDIDATE: 5439 return "IMN_CHANGECANDIDATE"; 5440 case IMN_CLOSECANDIDATE: 5441 return "IMN_CLOSECANDIDATE"; 5442 case IMN_CLOSESTATUSWINDOW: 5443 return "IMN_CLOSESTATUSWINDOW"; 5444 case IMN_GUIDELINE: 5445 return "IMN_GUIDELINE"; 5446 case IMN_OPENCANDIDATE: 5447 return "IMN_OPENCANDIDATE"; 5448 case IMN_OPENSTATUSWINDOW: 5449 return "IMN_OPENSTATUSWINDOW"; 5450 case IMN_SETCANDIDATEPOS: 5451 return "IMN_SETCANDIDATEPOS"; 5452 case IMN_SETCOMPOSITIONFONT: 5453 return "IMN_SETCOMPOSITIONFONT"; 5454 case IMN_SETCOMPOSITIONWINDOW: 5455 return "IMN_SETCOMPOSITIONWINDOW"; 5456 case IMN_SETCONVERSIONMODE: 5457 return "IMN_SETCONVERSIONMODE"; 5458 case IMN_SETOPENSTATUS: 5459 return "IMN_SETOPENSTATUS"; 5460 case IMN_SETSENTENCEMODE: 5461 return "IMN_SETSENTENCEMODE"; 5462 case IMN_SETSTATUSWINDOWPOS: 5463 return "IMN_SETSTATUSWINDOWPOS"; 5464 default: 5465 return "Unknown (" + String::number(wparam) + ")"; 5466 } 5467 } 5468 5469 static String imeRequestName(WPARAM wparam) 5470 { 5471 switch (wparam) { 5472 case IMR_CANDIDATEWINDOW: 5473 return "IMR_CANDIDATEWINDOW"; 5474 case IMR_COMPOSITIONFONT: 5475 return "IMR_COMPOSITIONFONT"; 5476 case IMR_COMPOSITIONWINDOW: 5477 return "IMR_COMPOSITIONWINDOW"; 5478 case IMR_CONFIRMRECONVERTSTRING: 5479 return "IMR_CONFIRMRECONVERTSTRING"; 5480 case IMR_DOCUMENTFEED: 5481 return "IMR_DOCUMENTFEED"; 5482 case IMR_QUERYCHARPOSITION: 5483 return "IMR_QUERYCHARPOSITION"; 5484 case IMR_RECONVERTSTRING: 5485 return "IMR_RECONVERTSTRING"; 5486 default: 5487 return "Unknown (" + String::number(wparam) + ")"; 5488 } 5489 } 5490 #endif 5491 5492 bool WebView::onIMEComposition(LPARAM lparam) 5493 { 5494 LOG(TextInput, "onIMEComposition %s", imeCompositionArgumentNames(lparam).latin1().data()); 5495 HIMC hInputContext = getIMMContext(); 5496 if (!hInputContext) 5497 return true; 5498 5499 Frame* targetFrame = m_page->focusController()->focusedOrMainFrame(); 5500 if (!targetFrame || !targetFrame->editor()->canEdit()) 5501 return true; 5502 5503 prepareCandidateWindow(targetFrame, hInputContext); 5504 5505 if (lparam & GCS_RESULTSTR || !lparam) { 5506 String compositionString; 5507 if (!getCompositionString(hInputContext, GCS_RESULTSTR, compositionString) && lparam) 5508 return true; 5509 5510 targetFrame->editor()->confirmComposition(compositionString); 5511 } else { 5512 String compositionString; 5513 if (!getCompositionString(hInputContext, GCS_COMPSTR, compositionString)) 5514 return true; 5515 5516 // Composition string attributes 5517 int numAttributes = IMMDict::dict().getCompositionString(hInputContext, GCS_COMPATTR, 0, 0); 5518 Vector<BYTE> attributes(numAttributes); 5519 IMMDict::dict().getCompositionString(hInputContext, GCS_COMPATTR, attributes.data(), numAttributes); 5520 5521 // Get clauses 5522 int numClauses = IMMDict::dict().getCompositionString(hInputContext, GCS_COMPCLAUSE, 0, 0); 5523 Vector<DWORD> clauses(numClauses / sizeof(DWORD)); 5524 IMMDict::dict().getCompositionString(hInputContext, GCS_COMPCLAUSE, clauses.data(), numClauses); 5525 5526 Vector<CompositionUnderline> underlines; 5527 compositionToUnderlines(clauses, attributes, underlines); 5528 5529 int cursorPosition = LOWORD(IMMDict::dict().getCompositionString(hInputContext, GCS_CURSORPOS, 0, 0)); 5530 5531 targetFrame->editor()->setComposition(compositionString, underlines, cursorPosition, 0); 5532 } 5533 5534 return true; 5535 } 5536 5537 bool WebView::onIMEEndComposition() 5538 { 5539 LOG(TextInput, "onIMEEndComposition"); 5540 // If the composition hasn't been confirmed yet, it needs to be cancelled. 5541 // This happens after deleting the last character from inline input hole. 5542 Frame* targetFrame = m_page->focusController()->focusedOrMainFrame(); 5543 if (targetFrame && targetFrame->editor()->hasComposition()) 5544 targetFrame->editor()->confirmComposition(String()); 5545 5546 if (m_inIMEComposition) 5547 m_inIMEComposition--; 5548 5549 return true; 5550 } 5551 5552 bool WebView::onIMEChar(WPARAM wparam, LPARAM lparam) 5553 { 5554 UNUSED_PARAM(wparam); 5555 UNUSED_PARAM(lparam); 5556 LOG(TextInput, "onIMEChar U+%04X %08X", wparam, lparam); 5557 return true; 5558 } 5559 5560 bool WebView::onIMENotify(WPARAM wparam, LPARAM, LRESULT*) 5561 { 5562 UNUSED_PARAM(wparam); 5563 LOG(TextInput, "onIMENotify %s", imeNotificationName(wparam).latin1().data()); 5564 return false; 5565 } 5566 5567 LRESULT WebView::onIMERequestCharPosition(Frame* targetFrame, IMECHARPOSITION* charPos) 5568 { 5569 if (charPos->dwCharPos && !targetFrame->editor()->hasComposition()) 5570 return 0; 5571 IntRect caret; 5572 if (RefPtr<Range> range = targetFrame->editor()->hasComposition() ? targetFrame->editor()->compositionRange() : targetFrame->selection()->selection().toNormalizedRange()) { 5573 ExceptionCode ec = 0; 5574 RefPtr<Range> tempRange = range->cloneRange(ec); 5575 tempRange->setStart(tempRange->startContainer(ec), tempRange->startOffset(ec) + charPos->dwCharPos, ec); 5576 caret = targetFrame->editor()->firstRectForRange(tempRange.get()); 5577 } 5578 caret = targetFrame->view()->contentsToWindow(caret); 5579 charPos->pt.x = caret.x(); 5580 charPos->pt.y = caret.y(); 5581 ::ClientToScreen(m_viewWindow, &charPos->pt); 5582 charPos->cLineHeight = caret.height(); 5583 ::GetWindowRect(m_viewWindow, &charPos->rcDocument); 5584 return true; 5585 } 5586 5587 LRESULT WebView::onIMERequestReconvertString(Frame* targetFrame, RECONVERTSTRING* reconvertString) 5588 { 5589 RefPtr<Range> selectedRange = targetFrame->selection()->toNormalizedRange(); 5590 String text = selectedRange->text(); 5591 if (!reconvertString) 5592 return sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar); 5593 5594 unsigned totalSize = sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar); 5595 if (totalSize > reconvertString->dwSize) 5596 return 0; 5597 reconvertString->dwCompStrLen = text.length(); 5598 reconvertString->dwStrLen = text.length(); 5599 reconvertString->dwTargetStrLen = text.length(); 5600 reconvertString->dwStrOffset = sizeof(RECONVERTSTRING); 5601 memcpy(reconvertString + 1, text.characters(), text.length() * sizeof(UChar)); 5602 return totalSize; 5603 } 5604 5605 LRESULT WebView::onIMERequest(WPARAM request, LPARAM data) 5606 { 5607 LOG(TextInput, "onIMERequest %s", imeRequestName(request).latin1().data()); 5608 Frame* targetFrame = m_page->focusController()->focusedOrMainFrame(); 5609 if (!targetFrame || !targetFrame->editor()->canEdit()) 5610 return 0; 5611 5612 switch (request) { 5613 case IMR_RECONVERTSTRING: 5614 return onIMERequestReconvertString(targetFrame, (RECONVERTSTRING*)data); 5615 5616 case IMR_QUERYCHARPOSITION: 5617 return onIMERequestCharPosition(targetFrame, (IMECHARPOSITION*)data); 5618 } 5619 return 0; 5620 } 5621 5622 bool WebView::onIMESelect(WPARAM wparam, LPARAM lparam) 5623 { 5624 UNUSED_PARAM(wparam); 5625 UNUSED_PARAM(lparam); 5626 LOG(TextInput, "onIMESelect locale %ld %s", lparam, wparam ? "select" : "deselect"); 5627 return false; 5628 } 5629 5630 bool WebView::onIMESetContext(WPARAM wparam, LPARAM) 5631 { 5632 LOG(TextInput, "onIMESetContext %s", wparam ? "active" : "inactive"); 5633 return false; 5634 } 5635 5636 HRESULT STDMETHODCALLTYPE WebView::inspector(IWebInspector** inspector) 5637 { 5638 if (!m_webInspector) 5639 m_webInspector.adoptRef(WebInspector::createInstance(this)); 5640 5641 return m_webInspector.copyRefTo(inspector); 5642 } 5643 5644 HRESULT STDMETHODCALLTYPE WebView::windowAncestryDidChange() 5645 { 5646 HWND newParent; 5647 if (m_viewWindow) 5648 newParent = findTopLevelParent(m_hostWindow); 5649 else { 5650 // There's no point in tracking active state changes of our parent window if we don't have 5651 // a window ourselves. 5652 newParent = 0; 5653 } 5654 5655 if (newParent == m_topLevelParent) 5656 return S_OK; 5657 5658 if (m_topLevelParent) 5659 WindowMessageBroadcaster::removeListener(m_topLevelParent, this); 5660 5661 m_topLevelParent = newParent; 5662 5663 if (m_topLevelParent) 5664 WindowMessageBroadcaster::addListener(m_topLevelParent, this); 5665 5666 updateActiveState(); 5667 5668 return S_OK; 5669 } 5670 5671 HRESULT STDMETHODCALLTYPE WebView::paintDocumentRectToContext( 5672 /* [in] */ RECT rect, 5673 /* [in] */ OLE_HANDLE deviceContext) 5674 { 5675 if (!deviceContext) 5676 return E_POINTER; 5677 5678 if (!m_mainFrame) 5679 return E_FAIL; 5680 5681 return m_mainFrame->paintDocumentRectToContext(rect, deviceContext); 5682 } 5683 5684 HRESULT STDMETHODCALLTYPE WebView::paintScrollViewRectToContextAtPoint( 5685 /* [in] */ RECT rect, 5686 /* [in] */ POINT pt, 5687 /* [in] */ OLE_HANDLE deviceContext) 5688 { 5689 if (!deviceContext) 5690 return E_POINTER; 5691 5692 if (!m_mainFrame) 5693 return E_FAIL; 5694 5695 return m_mainFrame->paintScrollViewRectToContextAtPoint(rect, pt, deviceContext); 5696 } 5697 5698 HRESULT STDMETHODCALLTYPE WebView::reportException( 5699 /* [in] */ JSContextRef context, 5700 /* [in] */ JSValueRef exception) 5701 { 5702 if (!context || !exception) 5703 return E_FAIL; 5704 5705 JSLock lock(JSC::SilenceAssertionsOnly); 5706 JSC::ExecState* execState = toJS(context); 5707 5708 // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a WebView. 5709 if (!toJSDOMWindow(execState->lexicalGlobalObject())) 5710 return E_FAIL; 5711 5712 WebCore::reportException(execState, toJS(execState, exception)); 5713 return S_OK; 5714 } 5715 5716 HRESULT STDMETHODCALLTYPE WebView::elementFromJS( 5717 /* [in] */ JSContextRef context, 5718 /* [in] */ JSValueRef nodeObject, 5719 /* [retval][out] */ IDOMElement **element) 5720 { 5721 if (!element) 5722 return E_POINTER; 5723 5724 *element = 0; 5725 5726 if (!context) 5727 return E_FAIL; 5728 5729 if (!nodeObject) 5730 return E_FAIL; 5731 5732 JSLock lock(JSC::SilenceAssertionsOnly); 5733 Element* elt = toElement(toJS(toJS(context), nodeObject)); 5734 if (!elt) 5735 return E_FAIL; 5736 5737 *element = DOMElement::createInstance(elt); 5738 return S_OK; 5739 } 5740 5741 HRESULT STDMETHODCALLTYPE WebView::setCustomHTMLTokenizerTimeDelay( 5742 /* [in] */ double timeDelay) 5743 { 5744 if (!m_page) 5745 return E_FAIL; 5746 5747 m_page->setCustomHTMLTokenizerTimeDelay(timeDelay); 5748 return S_OK; 5749 } 5750 5751 HRESULT STDMETHODCALLTYPE WebView::setCustomHTMLTokenizerChunkSize( 5752 /* [in] */ int chunkSize) 5753 { 5754 if (!m_page) 5755 return E_FAIL; 5756 5757 m_page->setCustomHTMLTokenizerChunkSize(chunkSize); 5758 return S_OK; 5759 } 5760 5761 HRESULT STDMETHODCALLTYPE WebView::backingStore( 5762 /* [out, retval] */ OLE_HANDLE* hBitmap) 5763 { 5764 if (!hBitmap) 5765 return E_POINTER; 5766 if (!m_backingStoreBitmap) 5767 return E_FAIL; 5768 *hBitmap = reinterpret_cast<OLE_HANDLE>(m_backingStoreBitmap->handle()); 5769 return S_OK; 5770 } 5771 5772 HRESULT STDMETHODCALLTYPE WebView::setTransparent(BOOL transparent) 5773 { 5774 if (m_transparent == !!transparent) 5775 return S_OK; 5776 5777 m_transparent = transparent; 5778 m_mainFrame->updateBackground(); 5779 return S_OK; 5780 } 5781 5782 HRESULT STDMETHODCALLTYPE WebView::transparent(BOOL* transparent) 5783 { 5784 if (!transparent) 5785 return E_POINTER; 5786 5787 *transparent = this->transparent() ? TRUE : FALSE; 5788 return S_OK; 5789 } 5790 5791 HRESULT STDMETHODCALLTYPE WebView::setCookieEnabled(BOOL enable) 5792 { 5793 if (!m_page) 5794 return E_FAIL; 5795 5796 m_page->setCookieEnabled(enable); 5797 return S_OK; 5798 } 5799 5800 HRESULT STDMETHODCALLTYPE WebView::cookieEnabled(BOOL* enabled) 5801 { 5802 if (!enabled) 5803 return E_POINTER; 5804 5805 if (!m_page) 5806 return E_FAIL; 5807 5808 *enabled = m_page->cookieEnabled(); 5809 return S_OK; 5810 } 5811 5812 HRESULT STDMETHODCALLTYPE WebView::setMediaVolume(float volume) 5813 { 5814 if (!m_page) 5815 return E_FAIL; 5816 5817 m_page->setMediaVolume(volume); 5818 return S_OK; 5819 } 5820 5821 HRESULT STDMETHODCALLTYPE WebView::mediaVolume(float* volume) 5822 { 5823 if (!volume) 5824 return E_POINTER; 5825 5826 if (!m_page) 5827 return E_FAIL; 5828 5829 *volume = m_page->mediaVolume(); 5830 return S_OK; 5831 } 5832 5833 HRESULT STDMETHODCALLTYPE WebView::setDefersCallbacks(BOOL defersCallbacks) 5834 { 5835 if (!m_page) 5836 return E_FAIL; 5837 5838 m_page->setDefersLoading(defersCallbacks); 5839 return S_OK; 5840 } 5841 5842 HRESULT STDMETHODCALLTYPE WebView::defersCallbacks(BOOL* defersCallbacks) 5843 { 5844 if (!defersCallbacks) 5845 return E_POINTER; 5846 5847 if (!m_page) 5848 return E_FAIL; 5849 5850 *defersCallbacks = m_page->defersLoading(); 5851 return S_OK; 5852 } 5853 5854 HRESULT STDMETHODCALLTYPE WebView::globalHistoryItem(IWebHistoryItem** item) 5855 { 5856 if (!item) 5857 return E_POINTER; 5858 5859 if (!m_page) 5860 return E_FAIL; 5861 5862 if (!m_globalHistoryItem) { 5863 *item = 0; 5864 return S_OK; 5865 } 5866 5867 *item = WebHistoryItem::createInstance(m_globalHistoryItem); 5868 return S_OK; 5869 } 5870 5871 HRESULT STDMETHODCALLTYPE WebView::setAlwaysUsesComplexTextCodePath(BOOL complex) 5872 { 5873 WebCoreSetAlwaysUsesComplexTextCodePath(complex); 5874 5875 return S_OK; 5876 } 5877 5878 HRESULT STDMETHODCALLTYPE WebView::alwaysUsesComplexTextCodePath(BOOL* complex) 5879 { 5880 if (!complex) 5881 return E_POINTER; 5882 5883 *complex = WebCoreAlwaysUsesComplexTextCodePath(); 5884 return S_OK; 5885 } 5886 5887 HRESULT STDMETHODCALLTYPE WebView::registerEmbeddedViewMIMEType(BSTR mimeType) 5888 { 5889 if (!mimeType) 5890 return E_POINTER; 5891 5892 if (!m_embeddedViewMIMETypes) 5893 m_embeddedViewMIMETypes.set(new HashSet<String>); 5894 5895 m_embeddedViewMIMETypes->add(String(mimeType, ::SysStringLen(mimeType))); 5896 return S_OK; 5897 } 5898 5899 bool WebView::shouldUseEmbeddedView(const WTF::String& mimeType) const 5900 { 5901 if (!m_embeddedViewMIMETypes) 5902 return false; 5903 5904 return m_embeddedViewMIMETypes->contains(mimeType); 5905 } 5906 5907 bool WebView::onGetObject(WPARAM wParam, LPARAM lParam, LRESULT& lResult) const 5908 { 5909 lResult = 0; 5910 5911 if (lParam != OBJID_CLIENT) 5912 return false; 5913 5914 AXObjectCache::enableAccessibility(); 5915 5916 // Get the accessible object for the top-level frame. 5917 WebFrame* mainFrameImpl = topLevelFrame(); 5918 if (!mainFrameImpl) 5919 return false; 5920 5921 COMPtr<IAccessible> accessible = mainFrameImpl->accessible(); 5922 if (!accessible) 5923 return false; 5924 5925 if (!accessibilityLib) { 5926 if (!(accessibilityLib = ::LoadLibraryW(L"oleacc.dll"))) 5927 return false; 5928 } 5929 5930 static LPFNLRESULTFROMOBJECT procPtr = reinterpret_cast<LPFNLRESULTFROMOBJECT>(::GetProcAddress(accessibilityLib, "LresultFromObject")); 5931 if (!procPtr) 5932 return false; 5933 5934 // LresultFromObject returns a reference to the accessible object, stored 5935 // in an LRESULT. If this call is not successful, Windows will handle the 5936 // request through DefWindowProc. 5937 return SUCCEEDED(lResult = procPtr(__uuidof(IAccessible), wParam, accessible.get())); 5938 } 5939 5940 STDMETHODIMP WebView::AccessibleObjectFromWindow(HWND hwnd, DWORD objectID, REFIID riid, void** ppObject) 5941 { 5942 ASSERT(accessibilityLib); 5943 static LPFNACCESSIBLEOBJECTFROMWINDOW procPtr = reinterpret_cast<LPFNACCESSIBLEOBJECTFROMWINDOW>(::GetProcAddress(accessibilityLib, "AccessibleObjectFromWindow")); 5944 if (!procPtr) 5945 return E_FAIL; 5946 return procPtr(hwnd, objectID, riid, ppObject); 5947 } 5948 5949 HRESULT WebView::setMemoryCacheDelegateCallsEnabled(BOOL enabled) 5950 { 5951 m_page->setMemoryCacheClientCallsEnabled(enabled); 5952 return S_OK; 5953 } 5954 5955 HRESULT WebView::setJavaScriptURLsAreAllowed(BOOL areAllowed) 5956 { 5957 m_page->setJavaScriptURLsAreAllowed(areAllowed); 5958 return S_OK; 5959 } 5960 5961 HRESULT WebView::setCanStartPlugins(BOOL canStartPlugins) 5962 { 5963 m_page->setCanStartMedia(canStartPlugins); 5964 return S_OK; 5965 } 5966 5967 static String toString(BSTR bstr) 5968 { 5969 return String(bstr, SysStringLen(bstr)); 5970 } 5971 5972 static KURL toKURL(BSTR bstr) 5973 { 5974 return KURL(KURL(), toString(bstr)); 5975 } 5976 5977 void WebView::enterFullscreenForNode(Node* node) 5978 { 5979 if (!node->hasTagName(HTMLNames::videoTag)) 5980 return; 5981 5982 #if ENABLE(VIDEO) 5983 HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node); 5984 5985 if (m_fullscreenController) { 5986 if (m_fullscreenController->mediaElement() == videoElement) { 5987 // The backend may just warn us that the underlaying plaftormMovie() 5988 // has changed. Just force an update. 5989 m_fullscreenController->setMediaElement(videoElement); 5990 return; // No more to do. 5991 } 5992 5993 // First exit Fullscreen for the old mediaElement. 5994 m_fullscreenController->mediaElement()->exitFullscreen(); 5995 // This previous call has to trigger exitFullscreen, 5996 // which has to clear m_fullscreenController. 5997 ASSERT(!m_fullscreenController); 5998 } 5999 6000 m_fullscreenController = new FullscreenVideoController; 6001 m_fullscreenController->setMediaElement(videoElement); 6002 m_fullscreenController->enterFullscreen(); 6003 #endif 6004 } 6005 6006 void WebView::exitFullscreen() 6007 { 6008 #if ENABLE(VIDEO) 6009 if (m_fullscreenController) 6010 m_fullscreenController->exitFullscreen(); 6011 m_fullscreenController = 0; 6012 #endif 6013 } 6014 6015 static PassOwnPtr<Vector<String> > toStringVector(unsigned patternsCount, BSTR* patterns) 6016 { 6017 // Convert the patterns into a Vector. 6018 if (patternsCount == 0) 6019 return 0; 6020 Vector<String>* patternsVector = new Vector<String>; 6021 for (unsigned i = 0; i < patternsCount; ++i) 6022 patternsVector->append(toString(patterns[i])); 6023 return patternsVector; 6024 } 6025 6026 HRESULT WebView::addUserScriptToGroup(BSTR groupName, IWebScriptWorld* iWorld, BSTR source, BSTR url, 6027 unsigned whitelistCount, BSTR* whitelist, 6028 unsigned blacklistCount, BSTR* blacklist, 6029 WebUserScriptInjectionTime injectionTime) 6030 { 6031 COMPtr<WebScriptWorld> world(Query, iWorld); 6032 if (!world) 6033 return E_POINTER; 6034 6035 String group = toString(groupName); 6036 if (group.isEmpty()) 6037 return E_INVALIDARG; 6038 6039 PageGroup* pageGroup = PageGroup::pageGroup(group); 6040 ASSERT(pageGroup); 6041 if (!pageGroup) 6042 return E_FAIL; 6043 6044 pageGroup->addUserScriptToWorld(world->world(), toString(source), toKURL(url), 6045 toStringVector(whitelistCount, whitelist), toStringVector(blacklistCount, blacklist), 6046 injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd, 6047 InjectInAllFrames); 6048 6049 return S_OK; 6050 } 6051 6052 HRESULT WebView::addUserStyleSheetToGroup(BSTR groupName, IWebScriptWorld* iWorld, BSTR source, BSTR url, 6053 unsigned whitelistCount, BSTR* whitelist, 6054 unsigned blacklistCount, BSTR* blacklist) 6055 { 6056 COMPtr<WebScriptWorld> world(Query, iWorld); 6057 if (!world) 6058 return E_POINTER; 6059 6060 String group = toString(groupName); 6061 if (group.isEmpty()) 6062 return E_INVALIDARG; 6063 6064 PageGroup* pageGroup = PageGroup::pageGroup(group); 6065 ASSERT(pageGroup); 6066 if (!pageGroup) 6067 return E_FAIL; 6068 6069 pageGroup->addUserStyleSheetToWorld(world->world(), toString(source), toKURL(url), 6070 toStringVector(whitelistCount, whitelist), toStringVector(blacklistCount, blacklist), 6071 InjectInAllFrames); 6072 6073 return S_OK; 6074 } 6075 6076 HRESULT WebView::removeUserScriptFromGroup(BSTR groupName, IWebScriptWorld* iWorld, BSTR url) 6077 { 6078 COMPtr<WebScriptWorld> world(Query, iWorld); 6079 if (!world) 6080 return E_POINTER; 6081 6082 String group = toString(groupName); 6083 if (group.isEmpty()) 6084 return E_INVALIDARG; 6085 6086 PageGroup* pageGroup = PageGroup::pageGroup(group); 6087 ASSERT(pageGroup); 6088 if (!pageGroup) 6089 return E_FAIL; 6090 6091 pageGroup->removeUserScriptFromWorld(world->world(), toKURL(url)); 6092 6093 return S_OK; 6094 } 6095 6096 HRESULT WebView::removeUserStyleSheetFromGroup(BSTR groupName, IWebScriptWorld* iWorld, BSTR url) 6097 { 6098 COMPtr<WebScriptWorld> world(Query, iWorld); 6099 if (!world) 6100 return E_POINTER; 6101 6102 String group = toString(groupName); 6103 if (group.isEmpty()) 6104 return E_INVALIDARG; 6105 6106 PageGroup* pageGroup = PageGroup::pageGroup(group); 6107 ASSERT(pageGroup); 6108 if (!pageGroup) 6109 return E_FAIL; 6110 6111 pageGroup->removeUserStyleSheetFromWorld(world->world(), toKURL(url)); 6112 6113 return S_OK; 6114 } 6115 6116 HRESULT WebView::removeUserScriptsFromGroup(BSTR groupName, IWebScriptWorld* iWorld) 6117 { 6118 COMPtr<WebScriptWorld> world(Query, iWorld); 6119 if (!world) 6120 return E_POINTER; 6121 6122 String group = toString(groupName); 6123 if (group.isEmpty()) 6124 return E_INVALIDARG; 6125 6126 PageGroup* pageGroup = PageGroup::pageGroup(group); 6127 ASSERT(pageGroup); 6128 if (!pageGroup) 6129 return E_FAIL; 6130 6131 pageGroup->removeUserScriptsFromWorld(world->world()); 6132 return S_OK; 6133 } 6134 6135 HRESULT WebView::removeUserStyleSheetsFromGroup(BSTR groupName, IWebScriptWorld* iWorld) 6136 { 6137 COMPtr<WebScriptWorld> world(Query, iWorld); 6138 if (!world) 6139 return E_POINTER; 6140 6141 String group = toString(groupName); 6142 if (group.isEmpty()) 6143 return E_INVALIDARG; 6144 6145 PageGroup* pageGroup = PageGroup::pageGroup(group); 6146 ASSERT(pageGroup); 6147 if (!pageGroup) 6148 return E_FAIL; 6149 6150 pageGroup->removeUserStyleSheetsFromWorld(world->world()); 6151 return S_OK; 6152 } 6153 6154 HRESULT WebView::removeAllUserContentFromGroup(BSTR groupName) 6155 { 6156 String group = toString(groupName); 6157 if (group.isEmpty()) 6158 return E_INVALIDARG; 6159 6160 PageGroup* pageGroup = PageGroup::pageGroup(group); 6161 ASSERT(pageGroup); 6162 if (!pageGroup) 6163 return E_FAIL; 6164 6165 pageGroup->removeAllUserContent(); 6166 return S_OK; 6167 } 6168 6169 HRESULT WebView::invalidateBackingStore(const RECT* rect) 6170 { 6171 if (!IsWindow(m_viewWindow)) 6172 return S_OK; 6173 6174 RECT clientRect; 6175 if (!GetClientRect(m_viewWindow, &clientRect)) 6176 return E_FAIL; 6177 6178 RECT rectToInvalidate; 6179 if (!rect) 6180 rectToInvalidate = clientRect; 6181 else if (!IntersectRect(&rectToInvalidate, &clientRect, rect)) 6182 return S_OK; 6183 6184 repaint(rectToInvalidate, true); 6185 return S_OK; 6186 } 6187 6188 HRESULT WebView::addOriginAccessWhitelistEntry(BSTR sourceOrigin, BSTR destinationProtocol, BSTR destinationHost, BOOL allowDestinationSubdomains) 6189 { 6190 SecurityOrigin::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(String(sourceOrigin, SysStringLen(sourceOrigin))), String(destinationProtocol, SysStringLen(destinationProtocol)), String(destinationHost, SysStringLen(destinationHost)), allowDestinationSubdomains); 6191 return S_OK; 6192 } 6193 6194 HRESULT WebView::removeOriginAccessWhitelistEntry(BSTR sourceOrigin, BSTR destinationProtocol, BSTR destinationHost, BOOL allowDestinationSubdomains) 6195 { 6196 SecurityOrigin::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(String(sourceOrigin, SysStringLen(sourceOrigin))), String(destinationProtocol, SysStringLen(destinationProtocol)), String(destinationHost, SysStringLen(destinationHost)), allowDestinationSubdomains); 6197 return S_OK; 6198 } 6199 6200 HRESULT WebView::resetOriginAccessWhitelists() 6201 { 6202 SecurityOrigin::resetOriginAccessWhitelists(); 6203 return S_OK; 6204 } 6205 6206 HRESULT WebView::setHistoryDelegate(IWebHistoryDelegate* historyDelegate) 6207 { 6208 m_historyDelegate = historyDelegate; 6209 return S_OK; 6210 } 6211 6212 HRESULT WebView::historyDelegate(IWebHistoryDelegate** historyDelegate) 6213 { 6214 if (!historyDelegate) 6215 return E_POINTER; 6216 6217 return m_historyDelegate.copyRefTo(historyDelegate); 6218 } 6219 6220 HRESULT WebView::addVisitedLinks(BSTR* visitedURLs, unsigned visitedURLCount) 6221 { 6222 PageGroup& group = core(this)->group(); 6223 6224 for (unsigned i = 0; i < visitedURLCount; ++i) { 6225 BSTR url = visitedURLs[i]; 6226 unsigned length = SysStringLen(url); 6227 group.addVisitedLink(url, length); 6228 } 6229 6230 return S_OK; 6231 } 6232 6233 void WebView::downloadURL(const KURL& url) 6234 { 6235 // It's the delegate's job to ref the WebDownload to keep it alive - otherwise it will be 6236 // destroyed when this function returns. 6237 COMPtr<WebDownload> download(AdoptCOM, WebDownload::createInstance(url, m_downloadDelegate.get())); 6238 download->start(); 6239 } 6240 6241 #if USE(ACCELERATED_COMPOSITING) 6242 void WebView::setRootChildLayer(GraphicsLayer* layer) 6243 { 6244 setAcceleratedCompositing(layer ? true : false); 6245 if (!m_backingLayer) 6246 return; 6247 m_backingLayer->addChild(layer); 6248 } 6249 6250 void WebView::flushPendingGraphicsLayerChangesSoon() 6251 { 6252 if (!m_layerTreeHost) 6253 return; 6254 m_layerTreeHost->flushPendingGraphicsLayerChangesSoon(); 6255 } 6256 6257 void WebView::setAcceleratedCompositing(bool accelerated) 6258 { 6259 if (m_isAcceleratedCompositing == accelerated || !CACFLayerTreeHost::acceleratedCompositingAvailable()) 6260 return; 6261 6262 if (accelerated) { 6263 m_layerTreeHost = CACFLayerTreeHost::create(); 6264 if (m_layerTreeHost) { 6265 m_isAcceleratedCompositing = true; 6266 6267 m_layerTreeHost->setClient(this); 6268 ASSERT(m_viewWindow); 6269 m_layerTreeHost->setWindow(m_viewWindow); 6270 6271 // FIXME: We could perhaps get better performance by never allowing this layer to 6272 // become tiled (or choosing a higher-than-normal tiling threshold). 6273 // <http://webkit.org/b/52603> 6274 m_backingLayer = GraphicsLayer::create(this); 6275 m_backingLayer->setDrawsContent(true); 6276 m_backingLayer->setContentsOpaque(true); 6277 RECT clientRect; 6278 ::GetClientRect(m_viewWindow, &clientRect); 6279 m_backingLayer->setSize(IntRect(clientRect).size()); 6280 m_backingLayer->setNeedsDisplay(); 6281 6282 m_layerTreeHost->setRootChildLayer(PlatformCALayer::platformCALayer(m_backingLayer->platformLayer())); 6283 6284 // We aren't going to be using our backing store while we're in accelerated compositing 6285 // mode. But don't delete it immediately, in case we switch out of accelerated 6286 // compositing mode soon (e.g., if we're only compositing for a :hover animation). 6287 deleteBackingStoreSoon(); 6288 } 6289 } else { 6290 ASSERT(m_layerTreeHost); 6291 m_layerTreeHost->setClient(0); 6292 m_layerTreeHost->setWindow(0); 6293 m_layerTreeHost = 0; 6294 m_backingLayer = 0; 6295 m_isAcceleratedCompositing = false; 6296 } 6297 } 6298 #endif 6299 6300 HRESULT STDMETHODCALLTYPE WebView::setPluginHalterDelegate(IWebPluginHalterDelegate* d) 6301 { 6302 m_pluginHalterDelegate = d; 6303 return S_OK; 6304 } 6305 6306 HRESULT STDMETHODCALLTYPE WebView::pluginHalterDelegate(IWebPluginHalterDelegate** d) 6307 { 6308 if (!d) 6309 return E_POINTER; 6310 6311 if (!m_pluginHalterDelegate) 6312 return E_FAIL; 6313 6314 return m_pluginHalterDelegate.copyRefTo(d); 6315 } 6316 6317 static PluginView* pluginViewForNode(IDOMNode* domNode) 6318 { 6319 COMPtr<DOMNode> webKitDOMNode(Query, domNode); 6320 if (!webKitDOMNode) 6321 return 0; 6322 6323 Node* node = webKitDOMNode->node(); 6324 if (!node) 6325 return 0; 6326 6327 RenderObject* renderer = node->renderer(); 6328 if (!renderer || !renderer->isWidget()) 6329 return 0; 6330 6331 Widget* widget = toRenderWidget(renderer)->widget(); 6332 if (!widget || !widget->isPluginView()) 6333 return 0; 6334 6335 return static_cast<PluginView*>(widget); 6336 } 6337 6338 HRESULT WebView::isNodeHaltedPlugin(IDOMNode* domNode, BOOL* result) 6339 { 6340 if (!domNode || !result) 6341 return E_POINTER; 6342 6343 *result = FALSE; 6344 6345 PluginView* view = pluginViewForNode(domNode); 6346 if (!view) 6347 return E_FAIL; 6348 6349 *result = view->isHalted(); 6350 return S_OK; 6351 } 6352 6353 HRESULT WebView::restartHaltedPluginForNode(IDOMNode* domNode) 6354 { 6355 if (!domNode) 6356 return E_POINTER; 6357 6358 PluginView* view = pluginViewForNode(domNode); 6359 if (!view) 6360 return E_FAIL; 6361 6362 view->restart(); 6363 return S_OK; 6364 } 6365 6366 HRESULT WebView::hasPluginForNodeBeenHalted(IDOMNode* domNode, BOOL* result) 6367 { 6368 if (!domNode || !result) 6369 return E_POINTER; 6370 6371 *result = FALSE; 6372 6373 PluginView* view = pluginViewForNode(domNode); 6374 if (!view) 6375 return E_FAIL; 6376 6377 *result = view->hasBeenHalted(); 6378 return S_OK; 6379 } 6380 6381 HRESULT WebView::setGeolocationProvider(IWebGeolocationProvider* locationProvider) 6382 { 6383 m_geolocationProvider = locationProvider; 6384 return S_OK; 6385 } 6386 6387 HRESULT WebView::geolocationProvider(IWebGeolocationProvider** locationProvider) 6388 { 6389 if (!locationProvider) 6390 return E_POINTER; 6391 6392 if (!m_geolocationProvider) 6393 return E_FAIL; 6394 6395 return m_geolocationProvider.copyRefTo(locationProvider); 6396 } 6397 6398 HRESULT WebView::geolocationDidChangePosition(IWebGeolocationPosition* position) 6399 { 6400 #if ENABLE(CLIENT_BASED_GEOLOCATION) 6401 if (!m_page) 6402 return E_FAIL; 6403 m_page->geolocationController()->positionChanged(core(position)); 6404 return S_OK; 6405 #else 6406 return E_NOTIMPL; 6407 #endif 6408 } 6409 6410 HRESULT WebView::geolocationDidFailWithError(IWebError* error) 6411 { 6412 #if ENABLE(CLIENT_BASED_GEOLOCATION) 6413 if (!m_page) 6414 return E_FAIL; 6415 if (!error) 6416 return E_POINTER; 6417 6418 BSTR descriptionBSTR; 6419 if (FAILED(error->localizedDescription(&descriptionBSTR))) 6420 return E_FAIL; 6421 String descriptionString(descriptionBSTR, SysStringLen(descriptionBSTR)); 6422 SysFreeString(descriptionBSTR); 6423 6424 RefPtr<GeolocationError> geolocationError = GeolocationError::create(GeolocationError::PositionUnavailable, descriptionString); 6425 m_page->geolocationController()->errorOccurred(geolocationError.get()); 6426 return S_OK; 6427 #else 6428 return E_NOTIMPL; 6429 #endif 6430 } 6431 6432 HRESULT WebView::setDomainRelaxationForbiddenForURLScheme(BOOL forbidden, BSTR scheme) 6433 { 6434 SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(forbidden, String(scheme, SysStringLen(scheme))); 6435 return S_OK; 6436 } 6437 6438 HRESULT WebView::registerURLSchemeAsSecure(BSTR scheme) 6439 { 6440 SchemeRegistry::registerURLSchemeAsSecure(toString(scheme)); 6441 return S_OK; 6442 } 6443 6444 HRESULT WebView::nextDisplayIsSynchronous() 6445 { 6446 m_nextDisplayIsSynchronous = true; 6447 return S_OK; 6448 } 6449 6450 #if USE(ACCELERATED_COMPOSITING) 6451 void WebView::notifyAnimationStarted(const GraphicsLayer*, double) 6452 { 6453 // We never set any animations on our backing layer. 6454 ASSERT_NOT_REACHED(); 6455 } 6456 6457 void WebView::notifySyncRequired(const GraphicsLayer*) 6458 { 6459 flushPendingGraphicsLayerChangesSoon(); 6460 } 6461 6462 void WebView::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& inClip) 6463 { 6464 Frame* frame = core(m_mainFrame); 6465 if (!frame) 6466 return; 6467 6468 context.save(); 6469 context.clip(inClip); 6470 frame->view()->paint(&context, inClip); 6471 context.restore(); 6472 } 6473 6474 bool WebView::showDebugBorders() const 6475 { 6476 return m_page->settings()->showDebugBorders(); 6477 } 6478 6479 bool WebView::showRepaintCounter() const 6480 { 6481 return m_page->settings()->showRepaintCounter(); 6482 } 6483 6484 void WebView::flushPendingGraphicsLayerChanges() 6485 { 6486 Frame* coreFrame = core(m_mainFrame); 6487 if (!coreFrame) 6488 return; 6489 FrameView* view = coreFrame->view(); 6490 if (!view) 6491 return; 6492 if (!m_backingLayer) 6493 return; 6494 6495 view->updateLayoutAndStyleIfNeededRecursive(); 6496 6497 // Updating layout might have taken us out of compositing mode. 6498 if (m_backingLayer) 6499 m_backingLayer->syncCompositingStateForThisLayerOnly(); 6500 6501 view->syncCompositingStateIncludingSubframes(); 6502 } 6503 6504 #endif 6505 6506 class EnumTextMatches : public IEnumTextMatches 6507 { 6508 long m_ref; 6509 UINT m_index; 6510 Vector<IntRect> m_rects; 6511 public: 6512 EnumTextMatches(Vector<IntRect>* rects) : m_index(0), m_ref(1) 6513 { 6514 m_rects = *rects; 6515 } 6516 6517 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv) 6518 { 6519 if (IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IEnumTextMatches)) { 6520 *ppv = this; 6521 AddRef(); 6522 } 6523 6524 return *ppv?S_OK:E_NOINTERFACE; 6525 } 6526 6527 virtual ULONG STDMETHODCALLTYPE AddRef() 6528 { 6529 return m_ref++; 6530 } 6531 6532 virtual ULONG STDMETHODCALLTYPE Release() 6533 { 6534 if (m_ref == 1) { 6535 delete this; 6536 return 0; 6537 } 6538 else 6539 return m_ref--; 6540 } 6541 6542 virtual HRESULT STDMETHODCALLTYPE Next(ULONG, RECT* rect, ULONG* pceltFetched) 6543 { 6544 if (m_index < m_rects.size()) { 6545 if (pceltFetched) 6546 *pceltFetched = 1; 6547 *rect = m_rects[m_index]; 6548 m_index++; 6549 return S_OK; 6550 } 6551 6552 if (pceltFetched) 6553 *pceltFetched = 0; 6554 6555 return S_FALSE; 6556 } 6557 virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt) 6558 { 6559 m_index += celt; 6560 return S_OK; 6561 } 6562 virtual HRESULT STDMETHODCALLTYPE Reset(void) 6563 { 6564 m_index = 0; 6565 return S_OK; 6566 } 6567 virtual HRESULT STDMETHODCALLTYPE Clone(IEnumTextMatches**) 6568 { 6569 return E_NOTIMPL; 6570 } 6571 }; 6572 6573 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches) 6574 { 6575 *matches = new EnumTextMatches(rects); 6576 return (*matches)?S_OK:E_OUTOFMEMORY; 6577 } 6578 6579 Page* core(IWebView* iWebView) 6580 { 6581 Page* page = 0; 6582 6583 COMPtr<WebView> webView; 6584 if (SUCCEEDED(iWebView->QueryInterface(&webView)) && webView) 6585 page = webView->page(); 6586 6587 return page; 6588 } 6589 6590 HRESULT WebView::defaultMinimumTimerInterval(double* interval) 6591 { 6592 if (!interval) 6593 return E_POINTER; 6594 *interval = Settings::defaultMinDOMTimerInterval(); 6595 return S_OK; 6596 } 6597 6598 HRESULT WebView::setMinimumTimerInterval(double interval) 6599 { 6600 page()->settings()->setMinDOMTimerInterval(interval); 6601 return S_OK; 6602 } 6603 6604 void WebView::setGlobalHistoryItem(HistoryItem* historyItem) 6605 { 6606 m_globalHistoryItem = historyItem; 6607 } 6608