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