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