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