2 * Copyright (C) 2006-2014 Apple, Inc. All rights reserved.
3 * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
4 * Copyright (C) 2011 Brent Fulgham. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "BackForwardController.h"
31 #include "COMVariantSetter.h"
32 #include "DOMCoreClasses.h"
33 #include "FullscreenVideoController.h"
34 #include "MarshallingHelpers.h"
35 #include "SoftLinking.h"
36 #include "SubframeLoader.h"
37 #include "TextIterator.h"
38 #include "WebBackForwardList.h"
39 #include "WebChromeClient.h"
40 #include "WebContextMenuClient.h"
41 #include "WebCoreTextRenderer.h"
42 #include "WebDatabaseManager.h"
43 #include "WebDocumentLoader.h"
44 #include "WebDownload.h"
45 #include "WebDragClient.h"
46 #include "WebEditorClient.h"
47 #include "WebElementPropertyBag.h"
49 #include "WebFrameLoaderClient.h"
50 #include "WebFrameNetworkingContext.h"
51 #include "WebGeolocationClient.h"
52 #include "WebGeolocationPosition.h"
53 #include "WebIconDatabase.h"
54 #include "WebInspector.h"
55 #include "WebInspectorClient.h"
57 #include "WebKitDLL.h"
58 #include "WebKitLogging.h"
59 #include "WebKitStatisticsPrivate.h"
60 #include "WebKitSystemBits.h"
61 #include "WebKitVersion.h"
62 #include "WebMutableURLRequest.h"
63 #include "WebNotificationCenter.h"
64 #include "WebPlatformStrategies.h"
65 #include "WebPreferences.h"
66 #include "WebScriptWorld.h"
67 #include "WebVisitedLinkStore.h"
69 #include <JavaScriptCore/APICast.h>
70 #include <JavaScriptCore/InitializeThreading.h>
71 #include <JavaScriptCore/JSCJSValue.h>
72 #include <JavaScriptCore/JSLock.h>
73 #include <WebCore/AXObjectCache.h>
74 #include <WebCore/ApplicationCacheStorage.h>
75 #include <WebCore/BString.h>
76 #include <WebCore/BackForwardController.h>
77 #include <WebCore/BackForwardList.h>
78 #include <WebCore/BitmapInfo.h>
79 #include <WebCore/Chrome.h>
80 #include <WebCore/ContextMenu.h>
81 #include <WebCore/ContextMenuController.h>
82 #include <WebCore/Cursor.h>
83 #include <WebCore/DatabaseManager.h>
84 #include <WebCore/Document.h>
85 #include <WebCore/DocumentMarkerController.h>
86 #include <WebCore/DragController.h>
87 #include <WebCore/DragData.h>
88 #include <WebCore/Editor.h>
89 #include <WebCore/EventHandler.h>
90 #include <WebCore/EventNames.h>
91 #include <WebCore/FileSystem.h>
92 #include <WebCore/FloatQuad.h>
93 #include <WebCore/FocusController.h>
94 #include <WebCore/FrameLoader.h>
95 #include <WebCore/FrameSelection.h>
96 #include <WebCore/FrameTree.h>
97 #include <WebCore/FrameView.h>
98 #include <WebCore/FrameWin.h>
99 #include <WebCore/FullScreenController.h>
100 #include <WebCore/GDIObjectCounter.h>
101 #include <WebCore/GeolocationController.h>
102 #include <WebCore/GeolocationError.h>
103 #include <WebCore/GraphicsContext.h>
104 #include <WebCore/HTMLNames.h>
105 #include <WebCore/HTMLVideoElement.h>
106 #include <WebCore/HWndDC.h>
107 #include <WebCore/HistoryController.h>
108 #include <WebCore/HistoryItem.h>
109 #include <WebCore/HitTestRequest.h>
110 #include <WebCore/HitTestResult.h>
111 #include <WebCore/IntRect.h>
112 #include <WebCore/JSElement.h>
113 #include <WebCore/KeyboardEvent.h>
114 #include <WebCore/Logging.h>
115 #include <WebCore/MIMETypeRegistry.h>
116 #include <WebCore/MainFrame.h>
117 #include <WebCore/MemoryCache.h>
118 #include <WebCore/NotImplemented.h>
119 #include <WebCore/Page.h>
120 #include <WebCore/PageCache.h>
121 #include <WebCore/PageConfiguration.h>
122 #include <WebCore/PageGroup.h>
123 #include <WebCore/PlatformKeyboardEvent.h>
124 #include <WebCore/PlatformMouseEvent.h>
125 #include <WebCore/PlatformWheelEvent.h>
126 #include <WebCore/PluginData.h>
127 #include <WebCore/PluginDatabase.h>
128 #include <WebCore/PluginView.h>
129 #include <WebCore/PopupMenu.h>
130 #include <WebCore/PopupMenuWin.h>
131 #include <WebCore/ProgressTracker.h>
132 #include <WebCore/RenderLayer.h>
133 #include <WebCore/RenderTheme.h>
134 #include <WebCore/RenderTreeAsText.h>
135 #include <WebCore/RenderView.h>
136 #include <WebCore/RenderWidget.h>
137 #include <WebCore/ResourceHandle.h>
138 #include <WebCore/ResourceHandleClient.h>
139 #include <WebCore/ResourceRequest.h>
140 #include <WebCore/RuntimeEnabledFeatures.h>
141 #include <WebCore/SchemeRegistry.h>
142 #include <WebCore/ScriptController.h>
143 #include <WebCore/Scrollbar.h>
144 #include <WebCore/ScrollbarTheme.h>
145 #include <WebCore/SecurityOrigin.h>
146 #include <WebCore/SecurityPolicy.h>
147 #include <WebCore/Settings.h>
148 #include <WebCore/SimpleFontData.h>
149 #include <WebCore/SystemInfo.h>
150 #include <WebCore/WindowMessageBroadcaster.h>
151 #include <WebCore/WindowsTouch.h>
152 #include <bindings/ScriptValue.h>
153 #include <wtf/MainThread.h>
156 #include <CoreGraphics/CGContext.h>
160 #include <CoreFoundation/CoreFoundation.h>
164 #include <CFNetwork/CFURLCachePriv.h>
165 #include <CFNetwork/CFURLProtocolPriv.h>
166 #include <WebKitSystemInterface/WebKitSystemInterface.h>
168 #include <WebCore/CurlCacheManager.h>
172 #include <WebCore/CACFLayerTreeHost.h>
173 #include <WebCore/PlatformCALayer.h>
174 #elif USE(TEXTURE_MAPPER_GL)
175 #include "AcceleratedCompositingContext.h"
178 #if ENABLE(FULLSCREEN_API)
179 #include <WebCore/FullScreenController.h>
187 #include <windowsx.h>
188 #include <wtf/HashSet.h>
189 #include <wtf/text/CString.h>
190 #include <wtf/text/StringConcatenate.h>
191 #include <wtf/win/GDIObject.h>
193 // Soft link functions for gestures and panning feedback
194 SOFT_LINK_LIBRARY(USER32);
195 SOFT_LINK_OPTIONAL(USER32, GetGestureInfo, BOOL, WINAPI, (HGESTUREINFO, PGESTUREINFO));
196 SOFT_LINK_OPTIONAL(USER32, SetGestureConfig, BOOL, WINAPI, (HWND, DWORD, UINT, PGESTURECONFIG, UINT));
197 SOFT_LINK_OPTIONAL(USER32, CloseGestureInfoHandle, BOOL, WINAPI, (HGESTUREINFO));
198 SOFT_LINK_LIBRARY(Uxtheme);
199 SOFT_LINK_OPTIONAL(Uxtheme, BeginPanningFeedback, BOOL, WINAPI, (HWND));
200 SOFT_LINK_OPTIONAL(Uxtheme, EndPanningFeedback, BOOL, WINAPI, (HWND, BOOL));
201 SOFT_LINK_OPTIONAL(Uxtheme, UpdatePanningFeedback, BOOL, WINAPI, (HWND, LONG, LONG, BOOL));
203 using namespace WebCore;
207 static HMODULE accessibilityLib;
208 static HashSet<WebView*>& pendingDeleteBackingStoreSet()
210 static NeverDestroyed<HashSet<WebView*>> pendingDeleteBackingStoreSet;
211 return pendingDeleteBackingStoreSet;
214 static CFStringRef WebKitLocalCacheDefaultsKey = CFSTR("WebKitLocalCache");
216 static String webKitVersionString();
218 WebView* kit(Page* page)
223 if (page->chrome().client().isEmptyChromeClient())
226 return static_cast<WebChromeClient&>(page->chrome().client()).webView();
229 static inline AtomicString toAtomicString(BSTR bstr)
231 return AtomicString(bstr, SysStringLen(bstr));
234 static inline String toString(BSTR bstr)
236 return String(bstr, SysStringLen(bstr));
239 static inline String toString(BString &bstr)
241 return String(bstr, SysStringLen(bstr));
244 static inline URL toURL(BSTR bstr)
246 return URL(URL(), toString(bstr));
249 class PreferencesChangedOrRemovedObserver : public IWebNotificationObserver {
251 static PreferencesChangedOrRemovedObserver* sharedInstance();
254 PreferencesChangedOrRemovedObserver() {}
255 ~PreferencesChangedOrRemovedObserver() {}
257 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) { return E_FAIL; }
258 virtual ULONG STDMETHODCALLTYPE AddRef(void) { return 0; }
259 virtual ULONG STDMETHODCALLTYPE Release(void) { return 0; }
262 // IWebNotificationObserver
263 virtual HRESULT STDMETHODCALLTYPE onNotify(
264 /* [in] */ IWebNotification* notification);
267 HRESULT notifyPreferencesChanged(WebCacheModel);
268 HRESULT notifyPreferencesRemoved(WebCacheModel);
271 PreferencesChangedOrRemovedObserver* PreferencesChangedOrRemovedObserver::sharedInstance()
273 static PreferencesChangedOrRemovedObserver* shared = new PreferencesChangedOrRemovedObserver;
277 HRESULT PreferencesChangedOrRemovedObserver::onNotify(IWebNotification* notification)
281 COMPtr<IUnknown> unkPrefs;
282 hr = notification->getObject(&unkPrefs);
286 COMPtr<IWebPreferences> preferences(Query, unkPrefs);
288 return E_NOINTERFACE;
290 WebCacheModel cacheModel;
291 hr = preferences->cacheModel(&cacheModel);
296 hr = notification->name(&name);
300 if (wcscmp(name, WebPreferences::webPreferencesChangedNotification()) == 0)
301 return notifyPreferencesChanged(cacheModel);
303 if (wcscmp(name, WebPreferences::webPreferencesRemovedNotification()) == 0)
304 return notifyPreferencesRemoved(cacheModel);
306 ASSERT_NOT_REACHED();
310 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesChanged(WebCacheModel cacheModel)
314 if (!WebView::didSetCacheModel() || cacheModel > WebView::cacheModel())
315 WebView::setCacheModel(cacheModel);
316 else if (cacheModel < WebView::cacheModel()) {
317 WebCacheModel sharedPreferencesCacheModel;
318 hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel);
321 WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance()));
327 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesRemoved(WebCacheModel cacheModel)
331 if (cacheModel == WebView::cacheModel()) {
332 WebCacheModel sharedPreferencesCacheModel;
333 hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel);
336 WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance()));
343 const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass";
345 const int WM_XP_THEMECHANGED = 0x031A;
346 const int WM_VISTA_MOUSEHWHEEL = 0x020E;
348 static const int maxToolTipWidth = 250;
350 static const int delayBeforeDeletingBackingStoreMsec = 5000;
352 static ATOM registerWebView();
354 static void initializeStaticObservers();
356 static HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences*);
358 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches);
360 static bool continuousSpellCheckingEnabled;
361 static bool grammarCheckingEnabled;
363 static bool s_didSetCacheModel;
364 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
367 UpdateActiveStateTimer = 1,
368 DeleteBackingStoreTimer = 2,
371 // WebView ----------------------------------------------------------------
373 bool WebView::s_allowSiteSpecificHacks = false;
377 , m_shouldInvertColors(false)
379 , m_deletionHasBegun(false)
385 #if ENABLE(INSPECTOR)
386 , m_inspectorClient(0)
387 #endif // ENABLE(INSPECTOR)
388 , m_hasCustomDropTarget(false)
389 , m_useBackForwardList(true)
390 , m_userAgentOverridden(false)
391 , m_zoomMultiplier(1.0f)
392 , m_zoomsTextOnly(false)
393 , m_mouseActivated(false)
395 , m_currentCharacterCode(0)
396 , m_isBeingDestroyed(false)
398 , m_hasSpellCheckerDocumentTag(false)
400 , m_inIMEComposition(0)
402 , m_closeWindowTimer(0)
403 , m_topLevelParent(0)
404 , m_deleteBackingStoreTimerActive(false)
405 , m_transparent(false)
410 , m_isAcceleratedCompositing(false)
411 , m_nextDisplayIsSynchronous(false)
413 , m_usesLayeredWindow(false)
414 , m_needsDisplay(false)
415 #if USE(TEXTURE_MAPPER_GL)
416 , m_acceleratedCompositingContext(nullptr)
419 JSC::initializeThreading();
420 WTF::initializeMainThread();
422 m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
424 CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper,(void**)&m_dropTargetHelper);
426 initializeStaticObservers();
428 WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences();
430 if (SUCCEEDED(sharedPreferences->continuousSpellCheckingEnabled(&enabled)))
431 continuousSpellCheckingEnabled = !!enabled;
432 if (SUCCEEDED(sharedPreferences->grammarCheckingEnabled(&enabled)))
433 grammarCheckingEnabled = !!enabled;
437 gClassNameCount().add("WebView");
442 deleteBackingStore();
444 // the tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD
445 if (::IsWindow(m_toolTipHwnd))
446 ::DestroyWindow(m_toolTipHwnd);
449 ASSERT(!m_preferences);
450 ASSERT(!m_viewWindow);
453 ASSERT(!m_layerTreeHost);
458 gClassNameCount().remove("WebView");
461 WebView* WebView::createInstance()
463 WebView* instance = new WebView();
468 void initializeStaticObservers()
470 static bool initialized;
475 IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
476 notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesChangedNotification(), 0);
477 notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesRemovedNotification(), 0);
480 static HashSet<WebView*>& allWebViewsSet()
482 static HashSet<WebView*> allWebViewsSet;
483 return allWebViewsSet;
486 void WebView::addToAllWebViewsSet()
488 allWebViewsSet().add(this);
491 void WebView::removeFromAllWebViewsSet()
493 allWebViewsSet().remove(this);
496 void WebView::setCacheModel(WebCacheModel cacheModel)
498 if (s_didSetCacheModel && cacheModel == s_cacheModel)
501 String cacheDirectory;
504 RetainPtr<CFURLCacheRef> cfurlCache = adoptCF(CFURLCacheCopySharedURLCache());
505 RetainPtr<CFStringRef> cfurlCacheDirectory = adoptCF(wkCopyFoundationCacheDirectory(0));
506 if (!cfurlCacheDirectory) {
507 RetainPtr<CFPropertyListRef> preference = adoptCF(CFPreferencesCopyAppValue(WebKitLocalCacheDefaultsKey, kCFPreferencesCurrentApplication));
508 if (preference && (CFStringGetTypeID() == CFGetTypeID(preference.get())))
509 cfurlCacheDirectory = adoptCF(static_cast<CFStringRef>(preference.leakRef()));
511 cfurlCacheDirectory = WebCore::localUserSpecificStorageDirectory().createCFString();
513 cacheDirectory = String(cfurlCacheDirectory);
514 CFIndex cacheMemoryCapacity = 0;
515 CFIndex cacheDiskCapacity = 0;
517 cacheDirectory = CurlCacheManager::getInstance().cacheDirectory();
518 long cacheMemoryCapacity = 0;
519 long cacheDiskCapacity = 0;
522 // As a fudge factor, use 1000 instead of 1024, in case the reported byte
523 // count doesn't align exactly to a megabyte boundary.
524 unsigned long long memSize = WebMemorySize() / 1024 / 1000;
525 unsigned long long diskFreeSize = WebVolumeFreeSize(cacheDirectory) / 1024 / 1000;
527 unsigned cacheTotalCapacity = 0;
528 unsigned cacheMinDeadCapacity = 0;
529 unsigned cacheMaxDeadCapacity = 0;
530 auto deadDecodedDataDeletionInterval = std::chrono::seconds { 0 };
532 unsigned pageCacheCapacity = 0;
535 switch (cacheModel) {
536 case WebCacheModelDocumentViewer: {
537 // Page cache capacity (in pages)
538 pageCacheCapacity = 0;
540 // Object cache capacities (in bytes)
542 cacheTotalCapacity = 96 * 1024 * 1024;
543 else if (memSize >= 1536)
544 cacheTotalCapacity = 64 * 1024 * 1024;
545 else if (memSize >= 1024)
546 cacheTotalCapacity = 32 * 1024 * 1024;
547 else if (memSize >= 512)
548 cacheTotalCapacity = 16 * 1024 * 1024;
550 cacheMinDeadCapacity = 0;
551 cacheMaxDeadCapacity = 0;
553 // Memory cache capacity (in bytes)
554 cacheMemoryCapacity = 0;
557 // Foundation disk cache capacity (in bytes)
558 cacheDiskCapacity = CFURLCacheDiskCapacity(cfurlCache.get());
562 case WebCacheModelDocumentBrowser: {
563 // Page cache capacity (in pages)
565 pageCacheCapacity = 3;
566 else if (memSize >= 512)
567 pageCacheCapacity = 2;
568 else if (memSize >= 256)
569 pageCacheCapacity = 1;
571 pageCacheCapacity = 0;
573 // Object cache capacities (in bytes)
575 cacheTotalCapacity = 96 * 1024 * 1024;
576 else if (memSize >= 1536)
577 cacheTotalCapacity = 64 * 1024 * 1024;
578 else if (memSize >= 1024)
579 cacheTotalCapacity = 32 * 1024 * 1024;
580 else if (memSize >= 512)
581 cacheTotalCapacity = 16 * 1024 * 1024;
583 cacheMinDeadCapacity = cacheTotalCapacity / 8;
584 cacheMaxDeadCapacity = cacheTotalCapacity / 4;
586 // Memory cache capacity (in bytes)
588 cacheMemoryCapacity = 4 * 1024 * 1024;
589 else if (memSize >= 1024)
590 cacheMemoryCapacity = 2 * 1024 * 1024;
591 else if (memSize >= 512)
592 cacheMemoryCapacity = 1 * 1024 * 1024;
594 cacheMemoryCapacity = 512 * 1024;
596 // Disk cache capacity (in bytes)
597 if (diskFreeSize >= 16384)
598 cacheDiskCapacity = 50 * 1024 * 1024;
599 else if (diskFreeSize >= 8192)
600 cacheDiskCapacity = 40 * 1024 * 1024;
601 else if (diskFreeSize >= 4096)
602 cacheDiskCapacity = 30 * 1024 * 1024;
604 cacheDiskCapacity = 20 * 1024 * 1024;
608 case WebCacheModelPrimaryWebBrowser: {
609 // Page cache capacity (in pages)
610 // (Research indicates that value / page drops substantially after 3 pages.)
612 pageCacheCapacity = 5;
613 else if (memSize >= 1024)
614 pageCacheCapacity = 4;
615 else if (memSize >= 512)
616 pageCacheCapacity = 3;
617 else if (memSize >= 256)
618 pageCacheCapacity = 2;
620 pageCacheCapacity = 1;
622 // Object cache capacities (in bytes)
623 // (Testing indicates that value / MB depends heavily on content and
624 // browsing pattern. Even growth above 128MB can have substantial
625 // value / MB for some content / browsing patterns.)
627 cacheTotalCapacity = 128 * 1024 * 1024;
628 else if (memSize >= 1536)
629 cacheTotalCapacity = 96 * 1024 * 1024;
630 else if (memSize >= 1024)
631 cacheTotalCapacity = 64 * 1024 * 1024;
632 else if (memSize >= 512)
633 cacheTotalCapacity = 32 * 1024 * 1024;
635 cacheMinDeadCapacity = cacheTotalCapacity / 4;
636 cacheMaxDeadCapacity = cacheTotalCapacity / 2;
638 // This code is here to avoid a PLT regression. We can remove it if we
639 // can prove that the overall system gain would justify the regression.
640 cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity);
642 deadDecodedDataDeletionInterval = std::chrono::seconds { 60 };
644 // Memory cache capacity (in bytes)
645 // (These values are small because WebCore does most caching itself.)
647 cacheMemoryCapacity = 4 * 1024 * 1024;
648 else if (memSize >= 512)
649 cacheMemoryCapacity = 2 * 1024 * 1024;
650 else if (memSize >= 256)
651 cacheMemoryCapacity = 1 * 1024 * 1024;
653 cacheMemoryCapacity = 512 * 1024;
655 // Disk cache capacity (in bytes)
656 if (diskFreeSize >= 16384)
657 cacheDiskCapacity = 175 * 1024 * 1024;
658 else if (diskFreeSize >= 8192)
659 cacheDiskCapacity = 150 * 1024 * 1024;
660 else if (diskFreeSize >= 4096)
661 cacheDiskCapacity = 125 * 1024 * 1024;
662 else if (diskFreeSize >= 2048)
663 cacheDiskCapacity = 100 * 1024 * 1024;
664 else if (diskFreeSize >= 1024)
665 cacheDiskCapacity = 75 * 1024 * 1024;
667 cacheDiskCapacity = 50 * 1024 * 1024;
672 ASSERT_NOT_REACHED();
675 memoryCache().setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
676 memoryCache().setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
677 pageCache()->setCapacity(pageCacheCapacity);
680 // Don't shrink a big disk cache, since that would cause churn.
681 cacheDiskCapacity = max(cacheDiskCapacity, CFURLCacheDiskCapacity(cfurlCache.get()));
683 CFURLCacheSetMemoryCapacity(cfurlCache.get(), cacheMemoryCapacity);
684 CFURLCacheSetDiskCapacity(cfurlCache.get(), cacheDiskCapacity);
686 CurlCacheManager::getInstance().setStorageSizeLimit(cacheDiskCapacity);
689 s_didSetCacheModel = true;
690 s_cacheModel = cacheModel;
694 WebCacheModel WebView::cacheModel()
699 bool WebView::didSetCacheModel()
701 return s_didSetCacheModel;
704 WebCacheModel WebView::maxCacheModelInAnyInstance()
706 WebCacheModel cacheModel = WebCacheModelDocumentViewer;
708 HashSet<WebView*>::iterator end = allWebViewsSet().end();
709 for (HashSet<WebView*>::iterator it = allWebViewsSet().begin(); it != end; ++it) {
710 COMPtr<IWebPreferences> pref;
711 if (FAILED((*it)->preferences(&pref)))
713 WebCacheModel prefCacheModel = WebCacheModelDocumentViewer;
714 if (FAILED(pref->cacheModel(&prefCacheModel)))
717 cacheModel = max(cacheModel, prefCacheModel);
723 HRESULT STDMETHODCALLTYPE WebView::close()
730 setAcceleratedCompositing(false);
732 WebNotificationCenter::defaultCenterInternal()->postNotificationName(_bstr_t(WebViewWillCloseNotification).GetBSTR(), static_cast<IWebView*>(this), 0);
734 if (m_uiDelegatePrivate)
735 m_uiDelegatePrivate->webViewClosing(this);
737 removeFromAllWebViewsSet();
740 m_page->mainFrame().loader().detachFromParent();
742 if (m_mouseOutTracker) {
743 m_mouseOutTracker->dwFlags = TME_CANCEL;
744 ::TrackMouseEvent(m_mouseOutTracker.get());
745 m_mouseOutTracker.reset();
751 // We can't check IsWindow(m_viewWindow) here, because that will return true even while
752 // we're already handling WM_DESTROY. So we check !isBeingDestroyed() instead.
753 if (!isBeingDestroyed())
754 DestroyWindow(m_viewWindow);
755 // Either we just destroyed m_viewWindow, or it's in the process of being destroyed. Either
756 // way, we clear it out to make sure we don't try to use it later.
762 setAccessibilityDelegate(0);
763 setDownloadDelegate(0);
764 setEditingDelegate(0);
765 setFrameLoadDelegate(0);
766 setFrameLoadDelegatePrivate(0);
767 setHistoryDelegate(0);
768 setPolicyDelegate(0);
769 setResourceLoadDelegate(0);
773 #if ENABLE(INSPECTOR)
774 m_inspectorClient = 0;
776 m_webInspector->webViewClosed();
777 #endif // ENABLE(INSPECTOR)
782 registerForIconNotification(false);
783 IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
784 notifyCenter->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
786 if (COMPtr<WebPreferences> preferences = m_preferences) {
788 preferences->identifier(&identifier);
791 preferences->didRemoveFromWebView();
792 // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
795 WebPreferences::removeReferenceForIdentifier(identifier);
798 deleteBackingStore();
802 void WebView::repaint(const WebCore::IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly)
804 if (isAcceleratedCompositing()) {
805 // The contentChanged, immediate, and repaintContentOnly parameters are all based on a non-
806 // compositing painting/scrolling model.
807 addToDirtyRegion(windowRect);
811 if (!repaintContentOnly) {
812 RECT rect = windowRect;
813 ::InvalidateRect(m_viewWindow, &rect, false);
816 addToDirtyRegion(windowRect);
818 if (repaintContentOnly)
819 updateBackingStore(core(topLevelFrame())->view());
821 ::UpdateWindow(m_viewWindow);
823 m_needsDisplay = true;
826 void WebView::deleteBackingStore()
828 pendingDeleteBackingStoreSet().remove(this);
830 if (m_deleteBackingStoreTimerActive) {
831 KillTimer(m_viewWindow, DeleteBackingStoreTimer);
832 m_deleteBackingStoreTimerActive = false;
834 m_backingStoreBitmap.clear();
835 m_backingStoreDirtyRegion.clear();
836 m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
839 bool WebView::ensureBackingStore()
842 ::GetClientRect(m_viewWindow, &windowRect);
843 LONG width = windowRect.right - windowRect.left;
844 LONG height = windowRect.bottom - windowRect.top;
845 if (width > 0 && height > 0 && (width != m_backingStoreSize.cx || height != m_backingStoreSize.cy)) {
846 deleteBackingStore();
848 m_backingStoreSize.cx = width;
849 m_backingStoreSize.cy = height;
850 BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(m_backingStoreSize));
853 m_backingStoreBitmap = SharedGDIObject<HBITMAP>::create(adoptGDIObject(::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0)));
860 void WebView::addToDirtyRegion(const IntRect& dirtyRect)
862 m_needsDisplay = true;
864 // FIXME: We want an assert here saying that the dirtyRect is inside the clienRect,
865 // but it was being hit during our layout tests, and is being investigated in
866 // http://webkit.org/b/29350.
868 if (isAcceleratedCompositing()) {
870 m_backingLayer->setNeedsDisplayInRect(dirtyRect);
871 #elif USE(TEXTURE_MAPPER_GL)
872 m_acceleratedCompositingContext->setNonCompositedContentsNeedDisplay(dirtyRect);
877 auto newRegion = adoptGDIObject(::CreateRectRgn(dirtyRect.x(), dirtyRect.y(),
878 dirtyRect.maxX(), dirtyRect.maxY()));
879 addToDirtyRegion(WTF::move(newRegion));
882 void WebView::addToDirtyRegion(GDIObject<HRGN> newRegion)
884 m_needsDisplay = true;
886 ASSERT(!isAcceleratedCompositing());
888 LOCAL_GDI_COUNTER(0, __FUNCTION__);
890 if (m_backingStoreDirtyRegion) {
891 auto combinedRegion = adoptGDIObject(::CreateRectRgn(0, 0, 0, 0));
892 ::CombineRgn(combinedRegion.get(), m_backingStoreDirtyRegion->get(), newRegion.get(), RGN_OR);
893 m_backingStoreDirtyRegion = SharedGDIObject<HRGN>::create(WTF::move(combinedRegion));
895 m_backingStoreDirtyRegion = SharedGDIObject<HRGN>::create(WTF::move(newRegion));
897 if (m_uiDelegatePrivate)
898 m_uiDelegatePrivate->webViewDidInvalidate(this);
901 void WebView::scrollBackingStore(FrameView* frameView, int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect)
903 m_needsDisplay = true;
905 if (isAcceleratedCompositing()) {
906 // FIXME: We should be doing something smarter here, like moving tiles around and painting
907 // any newly-exposed tiles. <http://webkit.org/b/52714>
909 m_backingLayer->setNeedsDisplayInRect(scrollViewRect);
910 #elif USE(TEXTURE_MAPPER_GL)
911 m_acceleratedCompositingContext->scrollNonCompositedContents(scrollViewRect, IntSize(dx, dy));
916 LOCAL_GDI_COUNTER(0, __FUNCTION__);
918 // If there's no backing store we don't need to update it
919 if (!m_backingStoreBitmap) {
920 if (m_uiDelegatePrivate)
921 m_uiDelegatePrivate->webViewScrolled(this);
926 // Make a region to hold the invalidated scroll area.
927 auto updateRegion = adoptGDIObject(::CreateRectRgn(0, 0, 0, 0));
929 // Collect our device context info and select the bitmap to scroll.
930 HWndDC windowDC(m_viewWindow);
931 auto bitmapDC = adoptGDIObject(::CreateCompatibleDC(windowDC));
932 HGDIOBJ oldBitmap = ::SelectObject(bitmapDC.get(), m_backingStoreBitmap->get());
934 // Scroll the bitmap.
935 RECT scrollRectWin(scrollViewRect);
936 RECT clipRectWin(clipRect);
937 ::ScrollDC(bitmapDC.get(), dx, dy, &scrollRectWin, &clipRectWin, updateRegion.get(), 0);
939 ::GetRgnBox(updateRegion.get(), ®ionBox);
944 // Add the dirty region to the backing store's dirty region.
945 addToDirtyRegion(WTF::move(updateRegion));
947 if (m_uiDelegatePrivate)
948 m_uiDelegatePrivate->webViewScrolled(this);
950 // Update the backing store.
951 updateBackingStore(frameView, bitmapDC.get(), false);
954 ::SelectObject(bitmapDC.get(), oldBitmap);
957 void WebView::sizeChanged(const IntSize& newSize)
959 m_needsDisplay = true;
961 deleteBackingStore();
963 if (Frame* coreFrame = core(topLevelFrame()))
964 coreFrame->view()->resize(newSize);
968 m_layerTreeHost->resize();
970 if (m_backingLayer) {
971 m_backingLayer->setSize(newSize);
972 m_backingLayer->setNeedsDisplay();
974 #elif USE(TEXTURE_MAPPER_GL)
975 if (m_acceleratedCompositingContext)
976 m_acceleratedCompositingContext->resizeRootLayer(newSize);
980 // This emulates the Mac smarts for painting rects intelligently. This is very
981 // important for us, since we double buffer based off dirty rects.
982 static void getUpdateRects(HRGN region, const IntRect& dirtyRect, Vector<IntRect>& rects)
984 ASSERT_ARG(region, region);
986 const int cRectThreshold = 10;
987 const float cWastedSpaceThreshold = 0.75f;
991 DWORD regionDataSize = GetRegionData(region, sizeof(RGNDATA), NULL);
992 if (!regionDataSize) {
993 rects.append(dirtyRect);
997 Vector<unsigned char> buffer(regionDataSize);
998 RGNDATA* regionData = reinterpret_cast<RGNDATA*>(buffer.data());
999 GetRegionData(region, regionDataSize, regionData);
1000 if (regionData->rdh.nCount > cRectThreshold) {
1001 rects.append(dirtyRect);
1005 double singlePixels = 0.0;
1008 for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++)
1009 singlePixels += (rect->right - rect->left) * (rect->bottom - rect->top);
1011 double unionPixels = dirtyRect.width() * dirtyRect.height();
1012 double wastedSpace = 1.0 - (singlePixels / unionPixels);
1013 if (wastedSpace <= cWastedSpaceThreshold) {
1014 rects.append(dirtyRect);
1018 for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++)
1019 rects.append(*rect);
1022 void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStoreCompletelyDirty, WindowsToPaint windowsToPaint)
1024 ASSERT(!isAcceleratedCompositing());
1026 LOCAL_GDI_COUNTER(0, __FUNCTION__);
1028 GDIObject<HDC> bitmapDCObject;
1031 HGDIOBJ oldBitmap = 0;
1033 HWndDC windowDC(m_viewWindow);
1034 bitmapDCObject = adoptGDIObject(::CreateCompatibleDC(windowDC));
1035 bitmapDC = bitmapDCObject.get();
1036 oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->get());
1039 if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
1040 // Do a layout first so that everything we render to the backing store is always current.
1041 if (Frame* coreFrame = core(m_mainFrame))
1042 if (FrameView* view = coreFrame->view())
1043 view->updateLayoutAndStyleIfNeededRecursive();
1045 Vector<IntRect> paintRects;
1046 if (!backingStoreCompletelyDirty && m_backingStoreDirtyRegion) {
1048 ::GetRgnBox(m_backingStoreDirtyRegion->get(), ®ionBox);
1049 getUpdateRects(m_backingStoreDirtyRegion->get(), regionBox, paintRects);
1052 ::GetClientRect(m_viewWindow, &clientRect);
1053 paintRects.append(clientRect);
1056 for (unsigned i = 0; i < paintRects.size(); ++i)
1057 paintIntoBackingStore(frameView, bitmapDC, paintRects[i], windowsToPaint);
1059 if (m_uiDelegatePrivate)
1060 m_uiDelegatePrivate->webViewPainted(this);
1062 m_backingStoreDirtyRegion.clear();
1066 ::SelectObject(bitmapDC, oldBitmap);
1070 m_needsDisplay = true;
1073 void WebView::performLayeredWindowUpdate()
1075 // The backing store may have been destroyed if the window rect was set to zero height or zero width.
1076 if (!m_backingStoreBitmap)
1079 HWndDC hdcScreen(m_viewWindow);
1080 auto hdcMem = adoptGDIObject(::CreateCompatibleDC(hdcScreen));
1081 HBITMAP hbmOld = static_cast<HBITMAP>(::SelectObject(hdcMem.get(), m_backingStoreBitmap->get()));
1084 ::GetObject(m_backingStoreBitmap->get(), sizeof(bmpInfo), &bmpInfo);
1085 SIZE windowSize = { bmpInfo.bmWidth, bmpInfo.bmHeight };
1087 BLENDFUNCTION blendFunction;
1088 blendFunction.BlendOp = AC_SRC_OVER;
1089 blendFunction.BlendFlags = 0;
1090 blendFunction.SourceConstantAlpha = 0xFF;
1091 blendFunction.AlphaFormat = AC_SRC_ALPHA;
1093 POINT layerPos = { 0, 0 };
1094 ::UpdateLayeredWindow(m_viewWindow, hdcScreen, 0, &windowSize, hdcMem.get(), &layerPos, 0, &blendFunction, ULW_ALPHA);
1096 ::SelectObject(hdcMem.get(), hbmOld);
1098 m_needsDisplay = false;
1101 void WebView::paint(HDC dc, LPARAM options)
1103 LOCAL_GDI_COUNTER(0, __FUNCTION__);
1105 if (isAcceleratedCompositing() && !usesLayeredWindow()) {
1107 m_layerTreeHost->flushPendingLayerChangesNow();
1108 #elif USE(TEXTURE_MAPPER_GL)
1109 m_acceleratedCompositingContext->flushAndRenderLayers();
1111 // Flushing might have taken us out of compositing mode.
1112 if (isAcceleratedCompositing()) {
1114 // FIXME: We need to paint into dc (if provided). <http://webkit.org/b/52578>
1115 m_layerTreeHost->paint();
1117 ::ValidateRect(m_viewWindow, 0);
1122 Frame* coreFrame = core(m_mainFrame);
1125 FrameView* frameView = coreFrame->view();
1129 GDIObject<HRGN> region;
1130 int regionType = NULLREGION;
1132 WindowsToPaint windowsToPaint;
1134 region = adoptGDIObject(::CreateRectRgn(0, 0, 0, 0));
1135 regionType = GetUpdateRgn(m_viewWindow, region.get(), false);
1136 hdc = BeginPaint(m_viewWindow, &ps);
1137 rcPaint = ps.rcPaint;
1138 // We're painting to the screen, and our child windows can handle
1139 // painting themselves to the screen.
1140 windowsToPaint = PaintWebViewOnly;
1143 ::GetClientRect(m_viewWindow, &rcPaint);
1144 if (options & PRF_ERASEBKGND)
1145 ::FillRect(hdc, &rcPaint, (HBRUSH)GetStockObject(WHITE_BRUSH));
1146 // Since we aren't painting to the screen, we want to paint all our
1147 // children into the HDC.
1148 windowsToPaint = PaintWebViewAndChildren;
1151 bool backingStoreCompletelyDirty = ensureBackingStore();
1152 if (!m_backingStoreBitmap) {
1154 EndPaint(m_viewWindow, &ps);
1160 auto bitmapDC = adoptGDIObject(::CreateCompatibleDC(hdc));
1161 HGDIOBJ oldBitmap = ::SelectObject(bitmapDC.get(), m_backingStoreBitmap->get());
1163 // Update our backing store if needed.
1164 updateBackingStore(frameView, bitmapDC.get(), backingStoreCompletelyDirty, windowsToPaint);
1166 // Now we blit the updated backing store
1167 IntRect windowDirtyRect = rcPaint;
1169 // Apply the same heuristic for this update region too.
1170 Vector<IntRect> blitRects;
1171 if (region && regionType == COMPLEXREGION)
1172 getUpdateRects(region.get(), windowDirtyRect, blitRects);
1174 blitRects.append(windowDirtyRect);
1176 for (unsigned i = 0; i < blitRects.size(); ++i)
1177 paintIntoWindow(bitmapDC.get(), hdc, blitRects[i]);
1179 ::SelectObject(bitmapDC.get(), oldBitmap);
1182 EndPaint(m_viewWindow, &ps);
1187 cancelDeleteBackingStoreSoon();
1189 deleteBackingStoreSoon();
1192 void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, const IntRect& dirtyRect, WindowsToPaint windowsToPaint)
1194 // FIXME: This function should never be called in accelerated compositing mode, and we should
1195 // assert as such. But currently it *is* sometimes called, so we can't assert yet. See
1196 // <http://webkit.org/b/58539>.
1198 LOCAL_GDI_COUNTER(0, __FUNCTION__);
1200 // FIXME: We want an assert here saying that the dirtyRect is inside the clienRect,
1201 // but it was being hit during our layout tests, and is being investigated in
1202 // http://webkit.org/b/29350.
1204 RECT rect = dirtyRect;
1206 #if FLASH_BACKING_STORE_REDRAW
1208 HWndDC dc(m_viewWindow);
1209 auto yellowBrush = adoptGDIObject(::CreateSolidBrush(RGB(255, 255, 0)));
1210 FillRect(dc, &rect, yellowBrush.get());
1213 paintIntoWindow(bitmapDC, dc, dirtyRect);
1217 GraphicsContext gc(bitmapDC, m_transparent);
1218 gc.setShouldIncludeChildWindows(windowsToPaint == PaintWebViewAndChildren);
1221 gc.clearRect(dirtyRect);
1223 FillRect(bitmapDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
1225 COMPtr<IWebUIDelegatePrivate2> uiPrivate(Query, m_uiDelegate);
1227 uiPrivate->drawBackground(this, bitmapDC, &rect);
1229 if (frameView && frameView->frame().contentRenderer()) {
1231 frameView->paint(&gc, dirtyRect);
1232 if (m_shouldInvertColors)
1233 gc.fillRect(dirtyRect, Color::white, ColorSpaceDeviceRGB, CompositeDifference);
1238 void WebView::paintIntoWindow(HDC bitmapDC, HDC windowDC, const IntRect& dirtyRect)
1240 // FIXME: This function should never be called in accelerated compositing mode, and we should
1241 // assert as such. But currently it *is* sometimes called, so we can't assert yet. See
1242 // <http://webkit.org/b/58539>.
1244 LOCAL_GDI_COUNTER(0, __FUNCTION__);
1245 #if FLASH_WINDOW_REDRAW
1246 auto greenBrush = adoptGDIObject(::CreateSolidBrush(RGB(0, 255, 0)));
1247 RECT rect = dirtyRect;
1248 FillRect(windowDC, &rect, greenBrush.get());
1253 // Blit the dirty rect from the backing store into the same position
1254 // in the destination DC.
1255 BitBlt(windowDC, dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), bitmapDC,
1256 dirtyRect.x(), dirtyRect.y(), SRCCOPY);
1258 m_needsDisplay = false;
1261 void WebView::frameRect(RECT* rect)
1263 ::GetWindowRect(m_viewWindow, rect);
1266 class WindowCloseTimer : public WebCore::SuspendableTimer {
1268 static WindowCloseTimer* create(WebView*);
1271 WindowCloseTimer(ScriptExecutionContext&, WebView*);
1272 virtual void contextDestroyed();
1273 virtual void fired();
1278 WindowCloseTimer* WindowCloseTimer::create(WebView* webView)
1280 ASSERT_ARG(webView, webView);
1281 Frame* frame = core(webView->topLevelFrame());
1286 Document* document = frame->document();
1291 return new WindowCloseTimer(*document, webView);
1294 WindowCloseTimer::WindowCloseTimer(ScriptExecutionContext& context, WebView* webView)
1295 : SuspendableTimer(context)
1296 , m_webView(webView)
1298 ASSERT_ARG(webView, webView);
1301 void WindowCloseTimer::contextDestroyed()
1303 SuspendableTimer::contextDestroyed();
1307 void WindowCloseTimer::fired()
1309 m_webView->closeWindowTimerFired();
1312 void WebView::closeWindowSoon()
1314 if (m_closeWindowTimer)
1317 m_closeWindowTimer = WindowCloseTimer::create(this);
1318 if (!m_closeWindowTimer)
1320 m_closeWindowTimer->startOneShot(0);
1325 void WebView::closeWindowTimerFired()
1331 void WebView::closeWindow()
1333 if (m_hasSpellCheckerDocumentTag) {
1334 if (m_editingDelegate)
1335 m_editingDelegate->closeSpellDocument(this);
1336 m_hasSpellCheckerDocumentTag = false;
1339 COMPtr<IWebUIDelegate> ui;
1340 if (SUCCEEDED(uiDelegate(&ui)))
1341 ui->webViewClose(this);
1344 bool WebView::canHandleRequest(const WebCore::ResourceRequest& request)
1346 // On the mac there's an about url protocol implementation but CFNetwork doesn't have that.
1347 if (equalIgnoringCase(String(request.url().protocol()), "about"))
1351 if (CFURLProtocolCanHandleRequest(request.cfURLRequest(UpdateHTTPBody)))
1354 // FIXME: Mac WebKit calls _representationExistsForURLScheme here
1361 String WebView::standardUserAgentWithApplicationName(const String& applicationName)
1363 DEPRECATED_DEFINE_STATIC_LOCAL(String, osVersion, (windowsVersionForUAString()));
1364 DEPRECATED_DEFINE_STATIC_LOCAL(String, webKitVersion, (webKitVersionString()));
1366 return makeString("Mozilla/5.0 (", osVersion, ") AppleWebKit/", webKitVersion, " (KHTML, like Gecko)", applicationName.isEmpty() ? "" : " ", applicationName);
1369 Page* WebView::page()
1374 bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam)
1376 // Translate the screen coordinates into window coordinates
1377 POINT coords = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1378 if (coords.x == -1 || coords.y == -1) {
1379 // The contextMenuController() holds onto the last context menu that was popped up on the
1380 // page until a new one is created. We need to clear this menu before propagating the event
1381 // through the DOM so that we can detect if we create a new menu for this event, since we
1382 // won't create a new menu if the DOM swallows the event and the defaultEventHandler does
1384 m_page->contextMenuController().clearContextMenu();
1386 Frame& focusedFrame = m_page->focusController().focusedOrMainFrame();
1387 return focusedFrame.eventHandler().sendContextMenuEventForKey();
1390 if (!::ScreenToClient(m_viewWindow, &coords))
1394 lParam = MAKELPARAM(coords.x, coords.y);
1396 m_page->contextMenuController().clearContextMenu();
1398 IntPoint documentPoint(m_page->mainFrame().view()->windowToContents(coords));
1399 HitTestResult result = m_page->mainFrame().eventHandler().hitTestResultAtPoint(documentPoint);
1400 Frame* targetFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document().frame() : &m_page->focusController().focusedOrMainFrame();
1402 targetFrame->view()->setCursor(pointerCursor());
1403 PlatformMouseEvent mouseEvent(m_viewWindow, WM_RBUTTONUP, wParam, lParam);
1404 bool handledEvent = targetFrame->eventHandler().sendContextMenuEvent(mouseEvent);
1408 ContextMenuController& contextMenuController = m_page->contextMenuController();
1411 ContextMenu* coreMenu = contextMenuController.contextMenu();
1415 Frame* frame = contextMenuController.hitTestResult().innerNodeFrame();
1419 FrameView* view = frame->view();
1423 POINT point(view->contentsToWindow(contextMenuController.hitTestResult().roundedPointInInnerNodeFrame()));
1425 // Translate the point to screen coordinates
1426 if (!::ClientToScreen(m_viewWindow, &point))
1429 BOOL hasCustomMenus = false;
1431 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1434 m_uiDelegate->trackCustomPopupMenu((IWebView*)this, coreMenu->platformContextMenu(), &point);
1436 // Surprisingly, TPM_RIGHTBUTTON means that items are selectable with either the right OR left mouse button
1437 UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL
1438 | TPM_LEFTALIGN | TPM_HORPOSANIMATION;
1439 ::TrackPopupMenuEx(coreMenu->platformContextMenu(), flags, point.x, point.y, m_viewWindow, 0);
1445 bool WebView::onMeasureItem(WPARAM /*wParam*/, LPARAM lParam)
1450 BOOL hasCustomMenus = false;
1451 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1452 if (!hasCustomMenus)
1455 m_uiDelegate->measureCustomMenuItem((IWebView*)this, (void*)lParam);
1459 bool WebView::onDrawItem(WPARAM /*wParam*/, LPARAM lParam)
1464 BOOL hasCustomMenus = false;
1465 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1466 if (!hasCustomMenus)
1469 m_uiDelegate->drawCustomMenuItem((IWebView*)this, (void*)lParam);
1473 bool WebView::onInitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
1478 HMENU menu = (HMENU)wParam;
1482 BOOL hasCustomMenus = false;
1483 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1484 if (!hasCustomMenus)
1487 m_uiDelegate->addCustomMenuDrawingData((IWebView*)this, menu);
1491 bool WebView::onUninitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
1496 HMENU menu = (HMENU)wParam;
1500 BOOL hasCustomMenus = false;
1501 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1502 if (!hasCustomMenus)
1505 m_uiDelegate->cleanUpCustomMenuDrawingData((IWebView*)this, menu);
1509 void WebView::performContextMenuAction(WPARAM wParam, LPARAM lParam, bool byPosition)
1511 ContextMenu* menu = m_page->contextMenuController().contextMenu();
1514 ContextMenuItem* item = byPosition ? menu->itemAtIndex((unsigned)wParam) : menu->itemWithAction((ContextMenuAction)wParam);
1517 m_page->contextMenuController().contextMenuItemSelected(item);
1520 bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam)
1522 static LONG globalClickCount;
1523 static IntPoint globalPrevPoint;
1524 static MouseButton globalPrevButton;
1525 static LONG globalPrevMouseDownTime;
1527 if (message == WM_CANCELMODE) {
1528 m_page->mainFrame().eventHandler().lostMouseCapture();
1532 // Create our event.
1533 // On WM_MOUSELEAVE we need to create a mouseout event, so we force the position
1534 // of the event to be at (MINSHORT, MINSHORT).
1535 LPARAM position = (message == WM_MOUSELEAVE) ? ((MINSHORT << 16) | MINSHORT) : lParam;
1536 PlatformMouseEvent mouseEvent(m_viewWindow, message, wParam, position, m_mouseActivated);
1538 setMouseActivated(false);
1540 bool insideThreshold = abs(globalPrevPoint.x() - mouseEvent.position().x()) < ::GetSystemMetrics(SM_CXDOUBLECLK) &&
1541 abs(globalPrevPoint.y() - mouseEvent.position().y()) < ::GetSystemMetrics(SM_CYDOUBLECLK);
1542 LONG messageTime = ::GetMessageTime();
1544 bool handled = false;
1546 if (message == WM_LBUTTONDOWN || message == WM_MBUTTONDOWN || message == WM_RBUTTONDOWN) {
1547 // FIXME: I'm not sure if this is the "right" way to do this
1548 // but without this call, we never become focused since we don't allow
1549 // the default handling of mouse events.
1550 SetFocus(m_viewWindow);
1552 // Always start capturing events when the mouse goes down in our HWND.
1553 ::SetCapture(m_viewWindow);
1555 if (((messageTime - globalPrevMouseDownTime) < (LONG)::GetDoubleClickTime()) &&
1557 mouseEvent.button() == globalPrevButton)
1560 // Reset the click count.
1561 globalClickCount = 1;
1562 globalPrevMouseDownTime = messageTime;
1563 globalPrevButton = mouseEvent.button();
1564 globalPrevPoint = mouseEvent.position();
1566 mouseEvent.setClickCount(globalClickCount);
1567 handled = m_page->mainFrame().eventHandler().handleMousePressEvent(mouseEvent);
1568 } else if (message == WM_LBUTTONDBLCLK || message == WM_MBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) {
1570 mouseEvent.setClickCount(globalClickCount);
1571 handled = m_page->mainFrame().eventHandler().handleMousePressEvent(mouseEvent);
1572 } else if (message == WM_LBUTTONUP || message == WM_MBUTTONUP || message == WM_RBUTTONUP) {
1573 // Record the global position and the button of the up.
1574 globalPrevButton = mouseEvent.button();
1575 globalPrevPoint = mouseEvent.position();
1576 mouseEvent.setClickCount(globalClickCount);
1577 m_page->mainFrame().eventHandler().handleMouseReleaseEvent(mouseEvent);
1579 } else if (message == WM_MOUSELEAVE && m_mouseOutTracker) {
1580 // Once WM_MOUSELEAVE is fired windows clears this tracker
1581 // so there is no need to disable it ourselves.
1582 m_mouseOutTracker.reset();
1583 m_page->mainFrame().eventHandler().mouseMoved(mouseEvent);
1585 } else if (message == WM_MOUSEMOVE) {
1586 if (!insideThreshold)
1587 globalClickCount = 0;
1588 mouseEvent.setClickCount(globalClickCount);
1589 handled = m_page->mainFrame().eventHandler().mouseMoved(mouseEvent);
1590 if (!m_mouseOutTracker) {
1591 m_mouseOutTracker = std::make_unique<TRACKMOUSEEVENT>();
1592 m_mouseOutTracker->cbSize = sizeof(TRACKMOUSEEVENT);
1593 m_mouseOutTracker->dwFlags = TME_LEAVE;
1594 m_mouseOutTracker->hwndTrack = m_viewWindow;
1595 ::TrackMouseEvent(m_mouseOutTracker.get());
1601 bool WebView::gestureNotify(WPARAM wParam, LPARAM lParam)
1603 GESTURENOTIFYSTRUCT* gn = reinterpret_cast<GESTURENOTIFYSTRUCT*>(lParam);
1605 Frame* coreFrame = core(m_mainFrame);
1609 ScrollView* view = coreFrame->view();
1613 // If we don't have this function, we shouldn't be receiving this message
1614 ASSERT(SetGestureConfigPtr());
1616 bool hitScrollbar = false;
1617 POINT gestureBeginPoint = {gn->ptsLocation.x, gn->ptsLocation.y};
1618 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent);
1619 for (Frame* childFrame = &m_page->mainFrame(); childFrame; childFrame = EventHandler::subframeForTargetNode(m_gestureTargetNode.get())) {
1620 FrameView* frameView = childFrame->view();
1623 RenderView* renderView = childFrame->document()->renderView();
1626 RenderLayer* layer = renderView->layer();
1630 HitTestResult result(frameView->screenToContents(gestureBeginPoint));
1631 layer->hitTest(request, result);
1632 m_gestureTargetNode = result.innerNode();
1635 hitScrollbar = result.scrollbar();
1638 if (!hitScrollbar) {
1639 // The hit testing above won't detect if we've hit the main frame's vertical scrollbar. Check that manually now.
1641 GetWindowRect(m_viewWindow, &webViewRect);
1642 hitScrollbar = (view->verticalScrollbar() && (gestureBeginPoint.x > (webViewRect.right - view->verticalScrollbar()->theme()->scrollbarThickness())))
1643 || (view->horizontalScrollbar() && (gestureBeginPoint.y > (webViewRect.bottom - view->horizontalScrollbar()->theme()->scrollbarThickness())));
1646 bool canBeScrolled = false;
1647 if (m_gestureTargetNode) {
1648 for (RenderObject* renderer = m_gestureTargetNode->renderer(); renderer; renderer = renderer->parent()) {
1649 if (is<RenderBox>(*renderer) && downcast<RenderBox>(*renderer).canBeScrolledAndHasScrollableArea()) {
1650 canBeScrolled = true;
1655 // We've hit the main document but not any of the document's content
1656 if (core(m_mainFrame)->view()->isScrollable())
1657 canBeScrolled = true;
1660 // We always allow two-fingered panning with inertia and a gutter (which limits movement to one
1661 // direction in most cases).
1662 DWORD dwPanWant = GC_PAN | GC_PAN_WITH_INERTIA | GC_PAN_WITH_GUTTER;
1663 DWORD dwPanBlock = 0;
1665 if (hitScrollbar || !canBeScrolled) {
1666 // The part of the page under the gesture can't be scrolled, or the gesture is on a scrollbar.
1667 // Disallow single-fingered panning in this case so we'll fall back to the default
1668 // behavior (which allows the scrollbar thumb to be dragged, text selections to be made, etc.).
1669 dwPanBlock = GC_PAN_WITH_SINGLE_FINGER_VERTICALLY | GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
1671 // The part of the page the gesture is under can be scrolled, and we're not under a scrollbar.
1672 // Allow single-fingered vertical panning in this case, so the user will be able to pan the page
1673 // with one or two fingers.
1674 dwPanWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
1676 // Disable single-fingered horizontal panning only if the target node is text.
1677 if (m_gestureTargetNode && m_gestureTargetNode->isTextNode())
1678 dwPanBlock = GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
1680 dwPanWant |= GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
1683 GESTURECONFIG gc = { GID_PAN, dwPanWant, dwPanBlock };
1684 return SetGestureConfigPtr()(m_viewWindow, 0, 1, &gc, sizeof(GESTURECONFIG));
1687 bool WebView::gesture(WPARAM wParam, LPARAM lParam)
1689 // We want to bail out if we don't have either of these functions
1690 if (!GetGestureInfoPtr() || !CloseGestureInfoHandlePtr())
1693 HGESTUREINFO gestureHandle = reinterpret_cast<HGESTUREINFO>(lParam);
1695 GESTUREINFO gi = {0};
1696 gi.cbSize = sizeof(GESTUREINFO);
1698 if (!GetGestureInfoPtr()(gestureHandle, reinterpret_cast<PGESTUREINFO>(&gi)))
1703 m_lastPanX = gi.ptsLocation.x;
1704 m_lastPanY = gi.ptsLocation.y;
1708 m_gestureTargetNode = 0;
1711 if (gi.dwFlags & GF_BEGIN) {
1712 m_lastPanX = gi.ptsLocation.x;
1713 m_lastPanY = gi.ptsLocation.y;
1715 // Where are the fingers currently?
1716 long currentX = gi.ptsLocation.x;
1717 long currentY = gi.ptsLocation.y;
1718 // How far did we pan in each direction?
1719 long deltaX = currentX - m_lastPanX;
1720 long deltaY = currentY - m_lastPanY;
1721 // Calculate the overpan for window bounce
1722 m_yOverpan -= m_lastPanY - currentY;
1723 m_xOverpan -= m_lastPanX - currentX;
1724 // Update our class variables with updated values
1725 m_lastPanX = currentX;
1726 m_lastPanY = currentY;
1728 Frame* coreFrame = core(m_mainFrame);
1730 CloseGestureInfoHandlePtr()(gestureHandle);
1734 ScrollableArea* scrolledArea = 0;
1736 if (!m_gestureTargetNode || !m_gestureTargetNode->renderer()) {
1737 // We might directly hit the document without hitting any nodes
1738 coreFrame->view()->scrollBy(IntSize(-deltaX, -deltaY));
1739 scrolledArea = coreFrame->view();
1741 m_gestureTargetNode->renderer()->enclosingLayer()->enclosingScrollableLayer()->scrollByRecursively(IntSize(-deltaX, -deltaY), WebCore::RenderLayer::ScrollOffsetClamped, &scrolledArea);
1743 if (!(UpdatePanningFeedbackPtr() && BeginPanningFeedbackPtr() && EndPanningFeedbackPtr())) {
1744 CloseGestureInfoHandlePtr()(gestureHandle);
1748 // Handle overpanning
1749 if (gi.dwFlags & GF_BEGIN) {
1750 BeginPanningFeedbackPtr()(m_viewWindow);
1753 } else if (gi.dwFlags & GF_END) {
1754 EndPanningFeedbackPtr()(m_viewWindow, true);
1759 if (!scrolledArea) {
1760 CloseGestureInfoHandlePtr()(gestureHandle);
1764 Scrollbar* vertScrollbar = scrolledArea->verticalScrollbar();
1769 if (vertScrollbar && (!vertScrollbar->currentPos() || vertScrollbar->currentPos() >= vertScrollbar->maximum()))
1772 Scrollbar* horiScrollbar = scrolledArea->horizontalScrollbar();
1774 if (horiScrollbar && (!horiScrollbar->currentPos() || horiScrollbar->currentPos() >= horiScrollbar->maximum()))
1777 UpdatePanningFeedbackPtr()(m_viewWindow, xpan, ypan, gi.dwFlags & GF_INERTIA);
1779 CloseGestureInfoHandlePtr()(gestureHandle);
1786 // If we get to this point, the gesture has not been handled. We forward
1787 // the call to DefWindowProc by returning false, and we don't need to
1788 // to call CloseGestureInfoHandle.
1789 // http://msdn.microsoft.com/en-us/library/dd353228(VS.85).aspx
1793 bool WebView::mouseWheel(WPARAM wParam, LPARAM lParam, bool isMouseHWheel)
1795 // Ctrl+Mouse wheel doesn't ever go into WebCore. It is used to
1796 // zoom instead (Mac zooms the whole Desktop, but Windows browsers trigger their
1797 // own local zoom modes for Ctrl+wheel).
1798 if (wParam & MK_CONTROL) {
1799 short delta = short(HIWORD(wParam));
1807 // 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.
1808 HWND focusedWindow = GetFocus();
1809 if (focusedWindow && focusedWindow != m_viewWindow) {
1810 // 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).
1811 WCHAR className[256];
1813 // Make sure truncation won't affect the comparison.
1814 ASSERT(WTF_ARRAY_LENGTH(className) > wcslen(PopupMenuWin::popupClassName()));
1816 if (GetClassNameW(focusedWindow, className, WTF_ARRAY_LENGTH(className)) && !wcscmp(className, PopupMenuWin::popupClassName())) {
1817 // We don't let the WebView scroll here for two reasons - 1) To match Firefox behavior, 2) If we do scroll, we lose the
1818 // focus ring around the select menu.
1819 SetFocus(m_viewWindow);
1824 PlatformWheelEvent wheelEvent(m_viewWindow, wParam, lParam, isMouseHWheel);
1825 Frame* coreFrame = core(m_mainFrame);
1829 return coreFrame->eventHandler().handleWheelEvent(wheelEvent);
1832 bool WebView::verticalScroll(WPARAM wParam, LPARAM /*lParam*/)
1834 ScrollDirection direction;
1835 ScrollGranularity granularity;
1836 switch (LOWORD(wParam)) {
1838 granularity = ScrollByLine;
1839 direction = ScrollDown;
1842 granularity = ScrollByLine;
1843 direction = ScrollUp;
1846 granularity = ScrollByDocument;
1847 direction = ScrollDown;
1850 granularity = ScrollByDocument;
1851 direction = ScrollUp;
1858 Frame& frame = m_page->focusController().focusedOrMainFrame();
1859 return frame.eventHandler().scrollRecursively(direction, granularity);
1862 bool WebView::horizontalScroll(WPARAM wParam, LPARAM /*lParam*/)
1864 ScrollDirection direction;
1865 ScrollGranularity granularity;
1866 switch (LOWORD(wParam)) {
1868 granularity = ScrollByLine;
1869 direction = ScrollLeft;
1872 granularity = ScrollByLine;
1873 direction = ScrollRight;
1876 granularity = ScrollByDocument;
1877 direction = ScrollLeft;
1880 granularity = ScrollByDocument;
1881 direction = ScrollRight;
1887 Frame& frame = m_page->focusController().focusedOrMainFrame();
1888 return frame.eventHandler().scrollRecursively(direction, granularity);
1892 bool WebView::execCommand(WPARAM wParam, LPARAM /*lParam*/)
1894 Frame& frame = m_page->focusController().focusedOrMainFrame();
1895 switch (LOWORD(wParam)) {
1897 return frame.editor().command("SelectAll").execute();
1899 return frame.editor().command("Undo").execute();
1901 return frame.editor().command("Redo").execute();
1906 bool WebView::keyUp(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
1908 PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformEvent::KeyUp, systemKeyDown);
1910 Frame& frame = m_page->focusController().focusedOrMainFrame();
1911 m_currentCharacterCode = 0;
1913 return frame.eventHandler().keyEvent(keyEvent);
1916 static const unsigned CtrlKey = 1 << 0;
1917 static const unsigned AltKey = 1 << 1;
1918 static const unsigned ShiftKey = 1 << 2;
1921 struct KeyDownEntry {
1922 unsigned virtualKey;
1927 struct KeyPressEntry {
1933 static const KeyDownEntry keyDownEntries[] = {
1934 { VK_LEFT, 0, "MoveLeft" },
1935 { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" },
1936 { VK_LEFT, CtrlKey, "MoveWordLeft" },
1937 { VK_LEFT, CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection" },
1938 { VK_RIGHT, 0, "MoveRight" },
1939 { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" },
1940 { VK_RIGHT, CtrlKey, "MoveWordRight" },
1941 { VK_RIGHT, CtrlKey | ShiftKey, "MoveWordRightAndModifySelection" },
1942 { VK_UP, 0, "MoveUp" },
1943 { VK_UP, ShiftKey, "MoveUpAndModifySelection" },
1944 { VK_PRIOR, ShiftKey, "MovePageUpAndModifySelection" },
1945 { VK_DOWN, 0, "MoveDown" },
1946 { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" },
1947 { VK_NEXT, ShiftKey, "MovePageDownAndModifySelection" },
1948 { VK_PRIOR, 0, "MovePageUp" },
1949 { VK_NEXT, 0, "MovePageDown" },
1950 { VK_HOME, 0, "MoveToBeginningOfLine" },
1951 { VK_HOME, ShiftKey, "MoveToBeginningOfLineAndModifySelection" },
1952 { VK_HOME, CtrlKey, "MoveToBeginningOfDocument" },
1953 { VK_HOME, CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
1955 { VK_END, 0, "MoveToEndOfLine" },
1956 { VK_END, ShiftKey, "MoveToEndOfLineAndModifySelection" },
1957 { VK_END, CtrlKey, "MoveToEndOfDocument" },
1958 { VK_END, CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection" },
1960 { VK_BACK, 0, "DeleteBackward" },
1961 { VK_BACK, ShiftKey, "DeleteBackward" },
1962 { VK_DELETE, 0, "DeleteForward" },
1963 { VK_BACK, CtrlKey, "DeleteWordBackward" },
1964 { VK_DELETE, CtrlKey, "DeleteWordForward" },
1966 { 'B', CtrlKey, "ToggleBold" },
1967 { 'I', CtrlKey, "ToggleItalic" },
1969 { VK_ESCAPE, 0, "Cancel" },
1970 { VK_OEM_PERIOD, CtrlKey, "Cancel" },
1971 { VK_TAB, 0, "InsertTab" },
1972 { VK_TAB, ShiftKey, "InsertBacktab" },
1973 { VK_RETURN, 0, "InsertNewline" },
1974 { VK_RETURN, CtrlKey, "InsertNewline" },
1975 { VK_RETURN, AltKey, "InsertNewline" },
1976 { VK_RETURN, ShiftKey, "InsertNewline" },
1977 { VK_RETURN, AltKey | ShiftKey, "InsertNewline" },
1979 // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled
1980 // in the application or in WebKit. We chose WebKit.
1981 { 'C', CtrlKey, "Copy" },
1982 { 'V', CtrlKey, "Paste" },
1983 { 'X', CtrlKey, "Cut" },
1984 { 'A', CtrlKey, "SelectAll" },
1985 { VK_INSERT, CtrlKey, "Copy" },
1986 { VK_DELETE, ShiftKey, "Cut" },
1987 { VK_INSERT, ShiftKey, "Paste" },
1988 { 'Z', CtrlKey, "Undo" },
1989 { 'Z', CtrlKey | ShiftKey, "Redo" },
1992 static const KeyPressEntry keyPressEntries[] = {
1993 { '\t', 0, "InsertTab" },
1994 { '\t', ShiftKey, "InsertBacktab" },
1995 { '\r', 0, "InsertNewline" },
1996 { '\r', CtrlKey, "InsertNewline" },
1997 { '\r', AltKey, "InsertNewline" },
1998 { '\r', ShiftKey, "InsertNewline" },
1999 { '\r', AltKey | ShiftKey, "InsertNewline" },
2002 const char* WebView::interpretKeyEvent(const KeyboardEvent* evt)
2004 ASSERT(evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
2006 static HashMap<int, const char*>* keyDownCommandsMap = 0;
2007 static HashMap<int, const char*>* keyPressCommandsMap = 0;
2009 if (!keyDownCommandsMap) {
2010 keyDownCommandsMap = new HashMap<int, const char*>;
2011 keyPressCommandsMap = new HashMap<int, const char*>;
2013 for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyDownEntries); ++i)
2014 keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
2016 for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyPressEntries); ++i)
2017 keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
2020 unsigned modifiers = 0;
2021 if (evt->shiftKey())
2022 modifiers |= ShiftKey;
2024 modifiers |= AltKey;
2026 modifiers |= CtrlKey;
2028 if (evt->type() == eventNames().keydownEvent) {
2029 int mapKey = modifiers << 16 | evt->keyCode();
2030 return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
2033 int mapKey = modifiers << 16 | evt->charCode();
2034 return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
2037 bool WebView::handleEditingKeyboardEvent(KeyboardEvent* evt)
2039 Node* node = evt->target()->toNode();
2041 Frame* frame = node->document().frame();
2044 const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
2045 if (!keyEvent || keyEvent->isSystemKey()) // do not treat this as text input if it's a system key event
2048 Editor::Command command = frame->editor().command(interpretKeyEvent(evt));
2050 if (keyEvent->type() == PlatformEvent::RawKeyDown) {
2051 // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
2052 // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
2053 // (e.g. Tab that inserts a Tab character, or Enter).
2054 return !command.isTextInsertion() && command.execute(evt);
2057 if (command.execute(evt))
2060 // Don't insert null or control characters as they can result in unexpected behaviour
2061 if (evt->charCode() < ' ')
2064 return frame->editor().insertText(evt->keyEvent()->text(), evt);
2067 bool WebView::keyDown(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
2069 #if ENABLE(FULLSCREEN_API)
2070 // Trap the ESC key when in full screen mode.
2071 if (virtualKeyCode == VK_ESCAPE && isFullScreen()) {
2072 m_fullscreenController->exitFullScreen();
2076 Frame& frame = m_page->focusController().focusedOrMainFrame();
2078 PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformEvent::RawKeyDown, systemKeyDown);
2079 bool handled = frame.eventHandler().keyEvent(keyEvent);
2081 // These events cannot be canceled, and we have no default handling for them.
2082 // FIXME: match IE list more closely, see <http://msdn2.microsoft.com/en-us/library/ms536938.aspx>.
2083 if (systemKeyDown && virtualKeyCode != VK_RETURN)
2087 // FIXME: remove WM_UNICHAR, too
2089 // WM_SYSCHAR events should not be removed, because access keys are implemented in WebCore in WM_SYSCHAR handler.
2091 ::PeekMessage(&msg, m_viewWindow, WM_CHAR, WM_CHAR, PM_REMOVE);
2095 // We need to handle back/forward using either Ctrl+Left/Right Arrow keys.
2096 // FIXME: This logic should probably be in EventHandler::defaultArrowEventHandler().
2097 // FIXME: Should check that other modifiers aren't pressed.
2098 if (virtualKeyCode == VK_RIGHT && keyEvent.ctrlKey())
2099 return m_page->backForward().goForward();
2100 if (virtualKeyCode == VK_LEFT && keyEvent.ctrlKey())
2101 return m_page->backForward().goBack();
2103 // Need to scroll the page if the arrow keys, pgup/dn, or home/end are hit.
2104 ScrollDirection direction;
2105 ScrollGranularity granularity;
2106 switch (virtualKeyCode) {
2108 granularity = ScrollByLine;
2109 direction = ScrollLeft;
2112 granularity = ScrollByLine;
2113 direction = ScrollRight;
2116 granularity = ScrollByLine;
2117 direction = ScrollUp;
2120 granularity = ScrollByLine;
2121 direction = ScrollDown;
2124 granularity = ScrollByDocument;
2125 direction = ScrollUp;
2128 granularity = ScrollByDocument;
2129 direction = ScrollDown;
2132 granularity = ScrollByPage;
2133 direction = ScrollUp;
2136 granularity = ScrollByPage;
2137 direction = ScrollDown;
2143 return frame.eventHandler().scrollRecursively(direction, granularity);
2146 bool WebView::keyPress(WPARAM charCode, LPARAM keyData, bool systemKeyDown)
2148 Frame& frame = m_page->focusController().focusedOrMainFrame();
2150 PlatformKeyboardEvent keyEvent(m_viewWindow, charCode, keyData, PlatformEvent::Char, systemKeyDown);
2151 // IE does not dispatch keypress event for WM_SYSCHAR.
2153 return frame.eventHandler().handleAccessKey(keyEvent);
2154 return frame.eventHandler().keyEvent(keyEvent);
2157 void WebView::setIsBeingDestroyed()
2159 m_isBeingDestroyed = true;
2161 // Remove our this pointer from the window so we won't try to handle any more window messages.
2162 // See <http://webkit.org/b/55054>.
2163 ::SetWindowLongPtrW(m_viewWindow, 0, 0);
2166 void WebView::setShouldInvertColors(bool shouldInvertColors)
2168 if (m_shouldInvertColors == shouldInvertColors)
2171 m_shouldInvertColors = shouldInvertColors;
2174 if (m_layerTreeHost)
2175 m_layerTreeHost->setShouldInvertColors(shouldInvertColors);
2178 RECT windowRect = {0};
2179 frameRect(&windowRect);
2180 repaint(windowRect, true, true);
2183 bool WebView::registerWebViewWindowClass()
2185 static bool haveRegisteredWindowClass = false;
2186 if (haveRegisteredWindowClass)
2189 haveRegisteredWindowClass = true;
2193 wcex.cbSize = sizeof(WNDCLASSEX);
2195 wcex.style = CS_DBLCLKS;
2196 wcex.lpfnWndProc = WebViewWndProc;
2197 wcex.cbClsExtra = 0;
2198 wcex.cbWndExtra = sizeof(WebView*);
2199 wcex.hInstance = gInstance;
2201 wcex.hCursor = ::LoadCursor(0, IDC_ARROW);
2202 wcex.hbrBackground = 0;
2203 wcex.lpszMenuName = 0;
2204 wcex.lpszClassName = kWebViewWindowClassName;
2207 return !!RegisterClassEx(&wcex);
2210 static HWND findTopLevelParent(HWND window)
2215 HWND current = window;
2216 for (HWND parent = GetParent(current); current; current = parent, parent = GetParent(parent))
2217 if (!parent || !(GetWindowLongPtr(current, GWL_STYLE) & (WS_POPUP | WS_CHILD)))
2219 ASSERT_NOT_REACHED();
2223 LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
2225 LRESULT lResult = 0;
2226 LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0);
2227 WebView* webView = reinterpret_cast<WebView*>(longPtr);
2228 WebFrame* mainFrameImpl = webView ? webView->topLevelFrame() : 0;
2230 return DefWindowProc(hWnd, message, wParam, lParam);
2232 // We shouldn't be trying to handle any window messages after WM_DESTROY.
2233 // See <http://webkit.org/b/55054>.
2234 ASSERT(!webView->isBeingDestroyed());
2236 // hold a ref, since the WebView could go away in an event handler.
2237 COMPtr<WebView> protector(webView);
2240 // Windows Media Player has a modal message loop that will deliver messages
2241 // to us at inappropriate times and we will crash if we handle them when
2242 // they are delivered. We repost paint messages so that we eventually get
2243 // a chance to paint once the modal loop has exited, but other messages
2244 // aren't safe to repost, so we just drop them.
2245 if (PluginView::isCallingPlugin()) {
2246 if (message == WM_PAINT)
2247 PostMessage(hWnd, message, wParam, lParam);
2251 bool handled = true;
2255 webView->paint(0, 0);
2256 if (webView->usesLayeredWindow())
2257 webView->performLayeredWindowUpdate();
2261 // Don't perform a background erase.
2265 case WM_PRINTCLIENT:
2266 webView->paint((HDC)wParam, lParam);
2269 webView->setIsBeingDestroyed();
2272 case WM_GESTURENOTIFY:
2273 handled = webView->gestureNotify(wParam, lParam);
2276 handled = webView->gesture(wParam, lParam);
2279 case WM_LBUTTONDOWN:
2280 case WM_MBUTTONDOWN:
2281 case WM_RBUTTONDOWN:
2282 case WM_LBUTTONDBLCLK:
2283 case WM_MBUTTONDBLCLK:
2284 case WM_RBUTTONDBLCLK:
2290 if (Frame* coreFrame = core(mainFrameImpl))
2291 if (coreFrame->view()->didFirstLayout())
2292 handled = webView->handleMouseEvent(message, wParam, lParam);
2295 case WM_VISTA_MOUSEHWHEEL:
2296 if (Frame* coreFrame = core(mainFrameImpl))
2297 if (coreFrame->view()->didFirstLayout())
2298 handled = webView->mouseWheel(wParam, lParam, message == WM_VISTA_MOUSEHWHEEL);
2301 handled = webView->keyDown(wParam, lParam, true);
2304 handled = webView->keyDown(wParam, lParam);
2307 handled = webView->keyUp(wParam, lParam, true);
2310 handled = webView->keyUp(wParam, lParam);
2313 handled = webView->keyPress(wParam, lParam, true);
2316 handled = webView->keyPress(wParam, lParam);
2318 // FIXME: We need to check WM_UNICHAR to support supplementary characters (that don't fit in 16 bits).
2321 webView->sizeChanged(IntSize(LOWORD(lParam), HIWORD(lParam)));
2324 lResult = DefWindowProc(hWnd, message, wParam, lParam);
2326 // The window is being hidden (e.g., because we switched tabs).
2327 // Null out our backing store.
2328 webView->deleteBackingStore();
2332 COMPtr<IWebUIDelegate> uiDelegate;
2333 COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
2334 if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate
2335 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
2336 uiDelegatePrivate->webViewReceivedFocus(webView);
2338 FocusController& focusController = webView->page()->focusController();
2339 if (Frame* frame = focusController.focusedFrame()) {
2340 // Send focus events unless the previously focused window is a
2341 // child of ours (for example a plugin).
2342 if (!IsChild(hWnd, reinterpret_cast<HWND>(wParam)))
2343 focusController.setFocused(true);
2345 focusController.setFocused(true);
2348 case WM_KILLFOCUS: {
2349 COMPtr<IWebUIDelegate> uiDelegate;
2350 COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
2351 HWND newFocusWnd = reinterpret_cast<HWND>(wParam);
2352 if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate
2353 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
2354 uiDelegatePrivate->webViewLostFocus(webView, newFocusWnd);
2356 FocusController& focusController = webView->page()->focusController();
2357 Frame& frame = focusController.focusedOrMainFrame();
2358 webView->resetIME(&frame);
2359 // Send blur events unless we're losing focus to a child of ours.
2360 if (!IsChild(hWnd, newFocusWnd))
2361 focusController.setFocused(false);
2363 // If we are pan-scrolling when we lose focus, stop the pan scrolling.
2364 frame.eventHandler().stopAutoscrollTimer();
2368 case WM_WINDOWPOSCHANGED:
2369 if (reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW)
2370 webView->updateActiveStateSoon();
2383 webView->delete_(0);
2387 handled = webView->execCommand(wParam, lParam);
2388 else // If the high word of wParam is 0, the message is from a menu
2389 webView->performContextMenuAction(wParam, lParam, false);
2391 case WM_MENUCOMMAND:
2392 webView->performContextMenuAction(wParam, lParam, true);
2394 case WM_CONTEXTMENU:
2395 handled = webView->handleContextMenuEvent(wParam, lParam);
2397 case WM_INITMENUPOPUP:
2398 handled = webView->onInitMenuPopup(wParam, lParam);
2400 case WM_MEASUREITEM:
2401 handled = webView->onMeasureItem(wParam, lParam);
2404 handled = webView->onDrawItem(wParam, lParam);
2406 case WM_UNINITMENUPOPUP:
2407 handled = webView->onUninitMenuPopup(wParam, lParam);
2409 case WM_XP_THEMECHANGED:
2410 if (Frame* coreFrame = core(mainFrameImpl)) {
2411 webView->deleteBackingStore();
2412 coreFrame->page()->theme().themeChanged();
2413 ScrollbarTheme::theme()->themeChanged();
2415 ::GetClientRect(hWnd, &windowRect);
2416 ::InvalidateRect(hWnd, &windowRect, false);
2418 if (webView->isAcceleratedCompositing())
2419 webView->m_backingLayer->setNeedsDisplay();
2423 case WM_MOUSEACTIVATE:
2424 webView->setMouseActivated(true);
2427 case WM_GETDLGCODE: {
2428 COMPtr<IWebUIDelegate> uiDelegate;
2429 COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
2430 LONG_PTR dlgCode = 0;
2433 LPMSG lpMsg = (LPMSG)lParam;
2434 if (lpMsg->message == WM_KEYDOWN)
2435 keyCode = (UINT) lpMsg->wParam;
2437 if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate
2438 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate
2439 && SUCCEEDED(uiDelegatePrivate->webViewGetDlgCode(webView, keyCode, &dlgCode)))
2445 handled = webView->onGetObject(wParam, lParam, lResult);
2447 case WM_IME_STARTCOMPOSITION:
2448 handled = webView->onIMEStartComposition();
2450 case WM_IME_REQUEST:
2451 lResult = webView->onIMERequest(wParam, lParam);
2453 case WM_IME_COMPOSITION:
2454 handled = webView->onIMEComposition(lParam);
2456 case WM_IME_ENDCOMPOSITION:
2457 handled = webView->onIMEEndComposition();
2460 handled = webView->onIMEChar(wParam, lParam);
2463 handled = webView->onIMENotify(wParam, lParam, &lResult);
2466 handled = webView->onIMESelect(wParam, lParam);
2468 case WM_IME_SETCONTEXT:
2469 handled = webView->onIMESetContext(wParam, lParam);
2473 case UpdateActiveStateTimer:
2474 KillTimer(hWnd, UpdateActiveStateTimer);
2475 webView->updateActiveState();
2477 case DeleteBackingStoreTimer:
2478 webView->deleteBackingStore();
2483 handled = ::SetCursor(webView->m_lastSetCursor);
2486 handled = webView->verticalScroll(wParam, lParam);
2489 handled = webView->horizontalScroll(wParam, lParam);
2496 if (webView->needsDisplay() && message != WM_PAINT)
2497 ::UpdateWindow(hWnd);
2500 lResult = DefWindowProc(hWnd, message, wParam, lParam);
2502 // Let the client know whether we consider this message handled.
2503 return (message == WM_KEYDOWN || message == WM_SYSKEYDOWN || message == WM_KEYUP || message == WM_SYSKEYUP) ? !handled : lResult;
2506 bool WebView::developerExtrasEnabled() const
2508 if (m_preferences->developerExtrasDisabledByOverride())
2513 return SUCCEEDED(m_preferences->developerExtrasEnabled(&enabled)) && enabled;
2519 static String webKitVersionString()
2522 LPWSTR buildNumberStringPtr;
2523 if (::LoadStringW(gInstance, BUILD_NUMBER, reinterpret_cast<LPWSTR>(&buildNumberStringPtr), 0) && buildNumberStringPtr)
2524 return buildNumberStringPtr;
2526 return String::format("%d.%d", WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION);
2529 const String& WebView::userAgentForKURL(const URL&)
2531 if (m_userAgentOverridden)
2532 return m_userAgentCustom;
2534 if (!m_userAgentStandard.length())
2535 m_userAgentStandard = WebView::standardUserAgentWithApplicationName(m_applicationName);
2536 return m_userAgentStandard;
2539 // IUnknown -------------------------------------------------------------------
2541 HRESULT STDMETHODCALLTYPE WebView::QueryInterface(REFIID riid, void** ppvObject)
2544 if (IsEqualGUID(riid, CLSID_WebView))
2546 else if (IsEqualGUID(riid, IID_IUnknown))
2547 *ppvObject = static_cast<IWebView*>(this);
2548 else if (IsEqualGUID(riid, IID_IWebView))
2549 *ppvObject = static_cast<IWebView*>(this);
2550 else if (IsEqualGUID(riid, IID_IWebViewPrivate))
2551 *ppvObject = static_cast<IWebViewPrivate*>(this);
2552 else if (IsEqualGUID(riid, IID_IWebIBActions))
2553 *ppvObject = static_cast<IWebIBActions*>(this);
2554 else if (IsEqualGUID(riid, IID_IWebViewCSS))
2555 *ppvObject = static_cast<IWebViewCSS*>(this);
2556 else if (IsEqualGUID(riid, IID_IWebViewEditing))
2557 *ppvObject = static_cast<IWebViewEditing*>(this);
2558 else if (IsEqualGUID(riid, IID_IWebViewUndoableEditing))
2559 *ppvObject = static_cast<IWebViewUndoableEditing*>(this);
2560 else if (IsEqualGUID(riid, IID_IWebViewEditingActions))
2561 *ppvObject = static_cast<IWebViewEditingActions*>(this);
2562 else if (IsEqualGUID(riid, IID_IWebNotificationObserver))
2563 *ppvObject = static_cast<IWebNotificationObserver*>(this);
2564 else if (IsEqualGUID(riid, IID_IDropTarget))
2565 *ppvObject = static_cast<IDropTarget*>(this);
2567 return E_NOINTERFACE;
2573 ULONG STDMETHODCALLTYPE WebView::AddRef(void)
2575 ASSERT(!m_deletionHasBegun);
2576 return ++m_refCount;
2579 ULONG STDMETHODCALLTYPE WebView::Release(void)
2581 ASSERT(!m_deletionHasBegun);
2583 if (m_refCount == 1) {
2584 // Call close() now so that clients don't have to. (It's harmless to call close() multiple
2585 // times.) We do this here instead of in our destructor because close() can cause AddRef()
2586 // and Release() to be called, and if that happened in our destructor we would be destroyed
2591 ULONG newRef = --m_refCount;
2593 #if !ASSERT_DISABLED
2594 m_deletionHasBegun = true;
2602 // IWebView --------------------------------------------------------------------
2604 HRESULT WebView::canShowMIMEType(/* [in] */ BSTR mimeType, /* [retval][out] */ BOOL* canShow)
2609 *canShow = canShowMIMEType(toString(mimeType));
2614 bool WebView::canShowMIMEType(const String& mimeType)
2616 Frame* coreFrame = core(m_mainFrame);
2617 bool allowPlugins = coreFrame && coreFrame->loader().subframeLoader().allowPlugins(NotAboutToInstantiatePlugin);
2619 bool canShow = MIMETypeRegistry::isSupportedImageMIMEType(mimeType)
2620 || MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)
2621 || MIMETypeRegistry::isSupportedMediaMIMEType(mimeType);
2623 if (!canShow && m_page) {
2624 canShow = (m_page->pluginData().supportsMimeType(mimeType, PluginData::AllPlugins) && allowPlugins)
2625 || m_page->pluginData().supportsMimeType(mimeType, PluginData::OnlyApplicationPlugins);
2629 canShow = shouldUseEmbeddedView(mimeType);
2634 HRESULT WebView::canShowMIMETypeAsHTML(/* [in] */ BSTR mimeType, /* [retval][out] */ BOOL* canShow)
2639 *canShow = canShowMIMETypeAsHTML(toString(mimeType));
2644 bool WebView::canShowMIMETypeAsHTML(const String& /*mimeType*/)
2651 HRESULT STDMETHODCALLTYPE WebView::MIMETypesShownAsHTML(
2652 /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
2654 ASSERT_NOT_REACHED();
2658 HRESULT STDMETHODCALLTYPE WebView::setMIMETypesShownAsHTML(
2659 /* [size_is][in] */ BSTR* /*mimeTypes*/,
2660 /* [in] */ int /*cMimeTypes*/)
2662 ASSERT_NOT_REACHED();
2666 HRESULT STDMETHODCALLTYPE WebView::URLFromPasteboard(
2667 /* [in] */ IDataObject* /*pasteboard*/,
2668 /* [retval][out] */ BSTR* /*url*/)
2670 ASSERT_NOT_REACHED();
2674 HRESULT STDMETHODCALLTYPE WebView::URLTitleFromPasteboard(
2675 /* [in] */ IDataObject* /*pasteboard*/,
2676 /* [retval][out] */ BSTR* /*urlTitle*/)
2678 ASSERT_NOT_REACHED();
2682 static void WebKitSetApplicationCachePathIfNecessary()
2684 static bool initialized = false;
2688 String path = localUserSpecificStorageDirectory();
2691 RetainPtr<CFPropertyListRef> cacheDirectoryPreference = adoptCF(CFPreferencesCopyAppValue(WebKitLocalCacheDefaultsKey, kCFPreferencesCurrentApplication));
2692 if (cacheDirectoryPreference && (CFStringGetTypeID() == CFGetTypeID(cacheDirectoryPreference.get())))
2693 path = static_cast<CFStringRef>(cacheDirectoryPreference.get());
2697 cacheStorage().setCacheDirectory(path);
2702 bool WebView::shouldInitializeTrackPointHack()
2704 static bool shouldCreateScrollbars;
2705 static bool hasRunTrackPointCheck;
2707 if (hasRunTrackPointCheck)
2708 return shouldCreateScrollbars;
2710 hasRunTrackPointCheck = true;
2711 const WCHAR trackPointKeys[][50] = { L"Software\\Lenovo\\TrackPoint",
2712 L"Software\\Lenovo\\UltraNav",
2713 L"Software\\Alps\\Apoint\\TrackPoint",
2714 L"Software\\Synaptics\\SynTPEnh\\UltraNavUSB",
2715 L"Software\\Synaptics\\SynTPEnh\\UltraNavPS2" };
2717 for (int i = 0; i < 5; ++i) {
2718 HKEY trackPointKey = nullptr;
2719 LSTATUS readKeyResult = ::RegOpenKeyExW(HKEY_CURRENT_USER, trackPointKeys[i], 0, KEY_READ, &trackPointKey);
2720 ::RegCloseKey(trackPointKey);
2721 if (readKeyResult == ERROR_SUCCESS) {
2722 shouldCreateScrollbars = true;
2723 return shouldCreateScrollbars;
2727 return shouldCreateScrollbars;
2730 HRESULT STDMETHODCALLTYPE WebView::initWithFrame(
2731 /* [in] */ RECT frame,
2732 /* [in] */ BSTR frameName,
2733 /* [in] */ BSTR groupName)
2740 registerWebViewWindowClass();
2742 m_viewWindow = CreateWindowEx(0, kWebViewWindowClassName, 0, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
2743 frame.left, frame.top, frame.right - frame.left, frame.bottom - frame.top, m_hostWindow ? m_hostWindow : HWND_MESSAGE, 0, gInstance, 0);
2744 ASSERT(::IsWindow(m_viewWindow));
2746 if (shouldInitializeTrackPointHack()) {
2747 // If we detected a registry key belonging to a TrackPoint driver, then create fake trackpoint
2748 // scrollbars, so the WebView will receive WM_VSCROLL and WM_HSCROLL messages. We create one
2749 // vertical scrollbar and one horizontal to allow for receiving both types of messages.
2750 ::CreateWindowW(L"SCROLLBAR", L"FAKETRACKPOINTHSCROLLBAR", WS_CHILD | WS_VISIBLE | SBS_HORZ, 0, 0, 0, 0, m_viewWindow, 0, gInstance, 0);
2751 ::CreateWindowW(L"SCROLLBAR", L"FAKETRACKPOINTVSCROLLBAR", WS_CHILD | WS_VISIBLE | SBS_VERT, 0, 0, 0, 0, m_viewWindow, 0, gInstance, 0);
2754 hr = registerDragDrop();
2758 WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences();
2759 sharedPreferences->willAddToWebView();
2760 m_preferences = sharedPreferences;
2762 static bool didOneTimeInitialization;
2763 if (!didOneTimeInitialization) {
2765 initializeLoggingChannelsIfNecessary();
2766 #endif // !LOG_DISABLED
2768 // Initialize our platform strategies first before invoking the rest
2769 // of the initialization code which may depend on the strategies.
2770 WebPlatformStrategies::initialize();
2772 #if ENABLE(SQL_DATABASE)
2773 WebKitInitializeWebDatabasesIfNecessary();
2775 WebKitSetApplicationCachePathIfNecessary();
2776 Settings::setDefaultMinDOMTimerInterval(0.004);
2778 didOneTimeInitialization = true;
2781 #if USE(SAFARI_THEME)
2782 BOOL shouldPaintNativeControls;
2783 if (SUCCEEDED(m_preferences->shouldPaintNativeControls(&shouldPaintNativeControls)))
2784 Settings::setShouldPaintNativeControls(shouldPaintNativeControls);
2787 BOOL useHighResolutionTimer;
2788 if (SUCCEEDED(m_preferences->shouldUseHighResolutionTimers(&useHighResolutionTimer)))
2789 Settings::setShouldUseHighResolutionTimers(useHighResolutionTimer);
2791 #if ENABLE(INSPECTOR)
2792 m_inspectorClient = new WebInspectorClient(this);
2793 #endif // ENABLE(INSPECTOR)
2795 PageConfiguration configuration;
2796 configuration.chromeClient = new WebChromeClient(this);
2797 configuration.contextMenuClient = new WebContextMenuClient(this);
2798 configuration.editorClient = new WebEditorClient(this);
2799 configuration.dragClient = new WebDragClient(this);
2800 #if ENABLE(INSPECTOR)
2801 configuration.inspectorClient = m_inspectorClient;
2802 #endif // ENABLE(INSPECTOR)
2803 configuration.loaderClientForMainFrame = new WebFrameLoaderClient;
2804 configuration.progressTrackerClient = static_cast<WebFrameLoaderClient*>(configuration.loaderClientForMainFrame);
2805 configuration.visitedLinkStore = &WebVisitedLinkStore::shared();
2807 m_page = new Page(configuration);
2808 provideGeolocationTo(m_page, new WebGeolocationClient(this));
2810 unsigned layoutMilestones = DidFirstLayout | DidFirstVisuallyNonEmptyLayout;
2811 m_page->addLayoutMilestones(static_cast<LayoutMilestones>(layoutMilestones));
2813 BString localStoragePath;
2814 if (SUCCEEDED(m_preferences->localStorageDatabasePath(&localStoragePath)))
2815 m_page->settings().setLocalStorageDatabasePath(toString(localStoragePath));
2819 if (SUCCEEDED(m_uiDelegate->ftpDirectoryTemplatePath(this, &path)))
2820 m_page->settings().setFTPDirectoryTemplatePath(toString(path));
2823 WebFrame* webFrame = WebFrame::createInstance();
2824 webFrame->initWithWebView(this, m_page);
2825 static_cast<WebFrameLoaderClient&>(m_page->mainFrame().loader().client()).setWebFrame(webFrame);
2826 m_mainFrame = webFrame;
2827 webFrame->Release(); // The WebFrame is owned by the Frame, so release our reference to it.
2829 m_page->mainFrame().tree().setName(toString(frameName));
2830 m_page->mainFrame().init();
2831 setGroupName(groupName);
2833 addToAllWebViewsSet();
2835 #pragma warning(suppress: 4244)
2836 SetWindowLongPtr(m_viewWindow, 0, (LONG_PTR)this);
2837 ShowWindow(m_viewWindow, SW_SHOW);
2839 initializeToolTipWindow();
2840 windowAncestryDidChange();
2842 IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
2843 notifyCenter->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
2844 m_preferences->postPreferencesChangesNotification();
2846 setSmartInsertDeleteEnabled(TRUE);
2850 static bool initCommonControls()
2852 static bool haveInitialized = false;
2853 if (haveInitialized)
2856 INITCOMMONCONTROLSEX init;
2857 init.dwSize = sizeof(init);
2858 init.dwICC = ICC_TREEVIEW_CLASSES;
2859 haveInitialized = !!::InitCommonControlsEx(&init);
2860 return haveInitialized;
2863 void WebView::initializeToolTipWindow()
2865 if (!initCommonControls())
2868 m_toolTipHwnd = CreateWindowEx(WS_EX_TRANSPARENT, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
2869 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2870 m_viewWindow, 0, 0, 0);
2874 TOOLINFO info = {0};
2875 info.cbSize = sizeof(info);
2876 info.uFlags = TTF_IDISHWND | TTF_SUBCLASS ;
2877 info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
2879 ::SendMessage(m_toolTipHwnd, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info));
2880 ::SendMessage(m_toolTipHwnd, TTM_SETMAXTIPWIDTH, 0, maxToolTipWidth);
2882 ::SetWindowPos(m_toolTipHwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
2885 void WebView::setToolTip(const String& toolTip)
2890 if (toolTip == m_toolTip)
2893 m_toolTip = toolTip;
2895 if (!m_toolTip.isEmpty()) {
2896 TOOLINFO info = {0};
2897 info.cbSize = sizeof(info);
2898 info.uFlags = TTF_IDISHWND;
2899 info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
2900 Vector<UChar> toolTipCharacters = m_toolTip.charactersWithNullTermination(); // Retain buffer long enough to make the SendMessage call
2901 info.lpszText = const_cast<UChar*>(toolTipCharacters.data());
2902 ::SendMessage(m_toolTipHwnd, TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info));
2905 ::SendMessage(m_toolTipHwnd, TTM_ACTIVATE, !m_toolTip.isEmpty(), 0);
2908 HRESULT WebView::notifyDidAddIcon(IWebNotification* notification)
2910 COMPtr<IPropertyBag> propertyBag;
2911 HRESULT hr = notification->userInfo(&propertyBag);
2917 COMVariant iconUserInfoURL;
2918 hr = propertyBag->Read(WebIconDatabase::iconDatabaseNotificationUserInfoURLKey(), &iconUserInfoURL, 0);
2922 if (iconUserInfoURL.variantType() != VT_BSTR)
2925 String mainFrameURL;
2927 mainFrameURL = m_mainFrame->url().string();
2929 if (!mainFrameURL.isEmpty() && mainFrameURL == toString(V_BSTR(&iconUserInfoURL)))
2930 dispatchDidReceiveIconFromWebFrame(m_mainFrame);
2935 void WebView::registerForIconNotification(bool listen)
2937 IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
2939 nc->addObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
2941 nc->removeObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
2944 void WebView::dispatchDidReceiveIconFromWebFrame(WebFrame* frame)
2946 registerForIconNotification(false);
2948 if (m_frameLoadDelegate) {
2949 String str = frame->url().string();
2953 BitmapInfo bmInfo = BitmapInfo::create(sz);
2955 HBITMAP hBitmap = nullptr;
2957 Image* icon = iconDatabase().synchronousIconForPageURL(str, sz);
2959 if (icon && icon->width()) {
2961 hBitmap = CreateDIBSection(dc, &bmInfo, DIB_RGB_COLORS, 0, 0, 0);
2962 icon->getHBITMAPOfSize(hBitmap, &sz);
2965 HRESULT hr = m_frameLoadDelegate->didReceiveIcon(this, hBitmap, frame);
2966 if ((hr == E_NOTIMPL) && hBitmap)
2967 DeleteObject(hBitmap);
2971 HRESULT WebView::setAccessibilityDelegate(
2972 /* [in] */ IAccessibilityDelegate* d)
2974 m_accessibilityDelegate = d;
2978 HRESULT WebView::accessibilityDelegate(
2979 /* [out][retval] */ IAccessibilityDelegate** d)
2981 if (!m_accessibilityDelegate)
2984 return m_accessibilityDelegate.copyRefTo(d);
2987 HRESULT STDMETHODCALLTYPE WebView::setUIDelegate(
2988 /* [in] */ IWebUIDelegate* d)
2992 if (m_uiDelegatePrivate)
2993 m_uiDelegatePrivate = 0;
2996 if (FAILED(d->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&m_uiDelegatePrivate)))
2997 m_uiDelegatePrivate = 0;
3003 HRESULT STDMETHODCALLTYPE WebView::uiDelegate(
3004 /* [out][retval] */ IWebUIDelegate** d)
3009 return m_uiDelegate.copyRefTo(d);
3012 HRESULT STDMETHODCALLTYPE WebView::setResourceLoadDelegate(
3013 /* [in] */ IWebResourceLoadDelegate* d)
3015 m_resourceLoadDelegate = d;
3019 HRESULT STDMETHODCALLTYPE WebView::resourceLoadDelegate(
3020 /* [out][retval] */ IWebResourceLoadDelegate** d)
3022 if (!m_resourceLoadDelegate)
3025 return m_resourceLoadDelegate.copyRefTo(d);
3028 HRESULT STDMETHODCALLTYPE WebView::setDownloadDelegate(
3029 /* [in] */ IWebDownloadDelegate* d)
3031 m_downloadDelegate = d;
3035 HRESULT STDMETHODCALLTYPE WebView::downloadDelegate(
3036 /* [out][retval] */ IWebDownloadDelegate** d)
3038 if (!m_downloadDelegate)
3041 return m_downloadDelegate.copyRefTo(d);
3044 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegate(
3045 /* [in] */ IWebFrameLoadDelegate* d)
3047 m_frameLoadDelegate = d;
3051 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegate(
3052 /* [out][retval] */ IWebFrameLoadDelegate** d)
3054 if (!m_frameLoadDelegate)
3057 return m_frameLoadDelegate.copyRefTo(d);
3060 HRESULT STDMETHODCALLTYPE WebView::setPolicyDelegate(
3061 /* [in] */ IWebPolicyDelegate* d)
3063 m_policyDelegate = d;
3067 HRESULT STDMETHODCALLTYPE WebView::policyDelegate(
3068 /* [out][retval] */ IWebPolicyDelegate** d)
3070 if (!m_policyDelegate)
3072 return m_policyDelegate.copyRefTo(d);
3075 HRESULT STDMETHODCALLTYPE WebView::mainFrame(
3076 /* [out][retval] */ IWebFrame** frame)
3079 ASSERT_NOT_REACHED();
3083 *frame = m_mainFrame;
3087 m_mainFrame->AddRef();
3091 HRESULT STDMETHODCALLTYPE WebView::focusedFrame(
3092 /* [out][retval] */ IWebFrame** frame)
3095 ASSERT_NOT_REACHED();
3100 Frame* f = m_page->focusController().focusedFrame();
3104 WebFrame* webFrame = kit(f);
3108 return webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
3111 HRESULT STDMETHODCALLTYPE WebView::backForwardList(
3112 /* [out][retval] */ IWebBackForwardList** list)
3114 if (!m_useBackForwardList)
3117 *list = WebBackForwardList::createInstance(static_cast<WebCore::BackForwardList*>(m_page->backForward().client()));
3122 HRESULT STDMETHODCALLTYPE WebView::setMaintainsBackForwardList(
3123 /* [in] */ BOOL flag)
3125 m_useBackForwardList = !!flag;
3129 HRESULT STDMETHODCALLTYPE WebView::goBack(
3130 /* [retval][out] */ BOOL* succeeded)
3132 *succeeded = m_page->backForward().goBack();
3136 HRESULT STDMETHODCALLTYPE WebView::goForward(
3137 /* [retval][out] */ BOOL* succeeded)
3139 *succeeded = m_page->backForward().goForward();
3143 HRESULT STDMETHODCALLTYPE WebView::goToBackForwardItem(
3144 /* [in] */ IWebHistoryItem* item,
3145 /* [retval][out] */ BOOL* succeeded)
3149 COMPtr<WebHistoryItem> webHistoryItem;
3150 HRESULT hr = item->QueryInterface(&webHistoryItem);
3154 m_page->goToItem(webHistoryItem->historyItem(), FrameLoadType::IndexedBackForward);
3160 HRESULT STDMETHODCALLTYPE WebView::setTextSizeMultiplier(
3161 /* [in] */ float multiplier)
3165 setZoomMultiplier(multiplier, true);
3169 HRESULT STDMETHODCALLTYPE WebView::setPageSizeMultiplier(
3170 /* [in] */ float multiplier)
3174 setZoomMultiplier(multiplier, false);
3178 void WebView::setZoomMultiplier(float multiplier, bool isTextOnly)
3180 m_zoomMultiplier = multiplier;
3181 m_zoomsTextOnly = isTextOnly;
3183 if (Frame* coreFrame = core(m_mainFrame)) {
3184 if (m_zoomsTextOnly)
3185 coreFrame->setPageAndTextZoomFactors(1, multiplier);
3187 coreFrame->setPageAndTextZoomFactors(multiplier, 1);
3191 HRESULT STDMETHODCALLTYPE WebView::textSizeMultiplier(
3192 /* [retval][out] */ float* multiplier)
3194 *multiplier = zoomMultiplier(true);
3198 HRESULT STDMETHODCALLTYPE WebView::pageSizeMultiplier(
3199 /* [retval][out] */ float* multiplier)
3201 *multiplier = zoomMultiplier(false);
3205 float WebView::zoomMultiplier(bool isTextOnly)
3207 if (isTextOnly != m_zoomsTextOnly)
3209 return m_zoomMultiplier;
3212 HRESULT STDMETHODCALLTYPE WebView::setApplicationNameForUserAgent(
3213 /* [in] */ BSTR applicationName)
3215 m_applicationName = toString(applicationName);
3216 m_userAgentStandard = String();
3220 HRESULT STDMETHODCALLTYPE WebView::applicationNameForUserAgent(
3221 /* [retval][out] */ BSTR* applicationName)
3223 *applicationName = BString(m_applicationName).release();
3224 if (!*applicationName && m_applicationName.length())
3225 return E_OUTOFMEMORY;
3229 HRESULT STDMETHODCALLTYPE WebView::setCustomUserAgent(
3230 /* [in] */ BSTR userAgentString)
3232 m_userAgentOverridden = userAgentString;
3233 m_userAgentCustom = toString(userAgentString);
3237 HRESULT STDMETHODCALLTYPE WebView::customUserAgent(
3238 /* [retval][out] */ BSTR* userAgentString)
3240 *userAgentString = 0;
3241 if (!m_userAgentOverridden)
3243 *userAgentString = BString(m_userAgentCustom).release();
3244 if (!*userAgentString && m_userAgentCustom.length())
3245 return E_OUTOFMEMORY;
3249 HRESULT STDMETHODCALLTYPE WebView::userAgentForURL(
3250 /* [in] */ BSTR url,
3251 /* [retval][out] */ BSTR* userAgent)
3253 String userAgentString = userAgentForKURL(MarshallingHelpers::BSTRToKURL(url));
3254 *userAgent = BString(userAgentString).release();
3255 if (!*userAgent && userAgentString.length())
3256 return E_OUTOFMEMORY;
3260 HRESULT STDMETHODCALLTYPE WebView::supportsTextEncoding(
3261 /* [retval][out] */ BOOL* supports)
3267 HRESULT STDMETHODCALLTYPE WebView::setCustomTextEncodingName(
3268 /* [in] */ BSTR encodingName)
3274 BString oldEncoding;
3275 hr = customTextEncodingName(&oldEncoding);
3279 if (oldEncoding != encodingName && (!oldEncoding || !encodingName || wcscmp(oldEncoding, encodingName))) {
3280 if (Frame* coreFrame = core(m_mainFrame))
3281 coreFrame->loader().reloadWithOverrideEncoding(toString(encodingName));
3287 HRESULT STDMETHODCALLTYPE WebView::customTextEncodingName(
3288 /* [retval][out] */ BSTR* encodingName)
3291 COMPtr<IWebDataSource> dataSource;
3292 COMPtr<WebDataSource> dataSourceImpl;
3298 if (FAILED(m_mainFrame->provisionalDataSource(&dataSource)) || !dataSource) {
3299 hr = m_mainFrame->dataSource(&dataSource);
3300 if (FAILED(hr) || !dataSource)
3304 hr = dataSource->QueryInterface(IID_WebDataSource, (void**)&dataSourceImpl);
3308 BString str = dataSourceImpl->documentLoader()->overrideEncoding();
3313 *encodingName = BString(m_overrideEncoding).release();
3315 if (!*encodingName && m_overrideEncoding.length())
3316 return E_OUTOFMEMORY;
3321 HRESULT STDMETHODCALLTYPE WebView::setMediaStyle(
3322 /* [in] */ BSTR /*media*/)
3324 ASSERT_NOT_REACHED();
3328 HRESULT STDMETHODCALLTYPE WebView::mediaStyle(
3329 /* [retval][out] */ BSTR* /*media*/)
3331 ASSERT_NOT_REACHED();
3335 HRESULT STDMETHODCALLTYPE WebView::stringByEvaluatingJavaScriptFromString(
3336 /* [in] */ BSTR script, // assumes input does not have "JavaScript" at the begining.
3337 /* [retval][out] */ BSTR* result)
3340 ASSERT_NOT_REACHED();
3346 Frame* coreFrame = core(m_mainFrame);
3350 JSC::JSValue scriptExecutionResult = coreFrame->script().executeScript(WTF::String(script), true).jsValue();
3351 if (!scriptExecutionResult)
3353 else if (scriptExecutionResult.isString()) {
3354 JSC::ExecState* exec = coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec();
3355 JSC::JSLockHolder lock(exec);
3356 *result = BString(scriptExecutionResult.getString(exec));
3362 HRESULT STDMETHODCALLTYPE WebView::windowScriptObject(
3363 /* [retval][out] */ IWebScriptObject** /*webScriptObject*/)
3365 ASSERT_NOT_REACHED();
3369 HRESULT STDMETHODCALLTYPE WebView::setPreferences(
3370 /* [in] */ IWebPreferences* prefs)
3373 prefs = WebPreferences::sharedStandardPreferences();
3375 if (m_preferences == prefs)
3378 COMPtr<WebPreferences> webPrefs(Query, prefs);
3380 return E_NOINTERFACE;
3381 webPrefs->willAddToWebView();
3383 COMPtr<WebPreferences> oldPrefs = m_preferences;
3385 IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
3386 nc->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3389 oldPrefs->identifier(&identifier);
3390 oldPrefs->didRemoveFromWebView();
3391 oldPrefs = 0; // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
3393 m_preferences = webPrefs;
3396 WebPreferences::removeReferenceForIdentifier(identifier);
3398 nc->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3400 m_preferences->postPreferencesChangesNotification();
3405 HRESULT STDMETHODCALLTYPE WebView::preferences(
3406 /* [retval][out] */ IWebPreferences** prefs)
3410 *prefs = m_preferences.get();
3412 m_preferences->AddRef();
3416 HRESULT STDMETHODCALLTYPE WebView::setPreferencesIdentifier(
3417 /* [in] */ BSTR /*anIdentifier*/)
3419 ASSERT_NOT_REACHED();
3423 HRESULT STDMETHODCALLTYPE WebView::preferencesIdentifier(
3424 /* [retval][out] */ BSTR* /*anIdentifier*/)
3426 ASSERT_NOT_REACHED();
3430 static void systemParameterChanged(WPARAM parameter)
3433 if (parameter == SPI_SETFONTSMOOTHING || parameter == SPI_SETFONTSMOOTHINGTYPE || parameter == SPI_SETFONTSMOOTHINGCONTRAST || parameter == SPI_SETFONTSMOOTHINGORIENTATION)
3434 wkSystemFontSmoothingChanged();
3438 void WebView::windowReceivedMessage(HWND, UINT message, WPARAM wParam, LPARAM)
3442 updateActiveStateSoon();
3444 deleteBackingStoreSoon();
3446 case WM_SETTINGCHANGE:
3447 systemParameterChanged(wParam);
3452 void WebView::updateActiveStateSoon() const
3454 // This function is called while processing the WM_NCACTIVATE message.
3455 // While processing WM_NCACTIVATE when we are being deactivated, GetActiveWindow() will
3456 // still return our window. If we were to call updateActiveState() in that case, we would
3457 // wrongly think that we are still the active window. To work around this, we update our
3458 // active state after a 0-delay timer fires, at which point GetActiveWindow() will return
3459 // the newly-activated window.
3461 SetTimer(m_viewWindow, UpdateActiveStateTimer, 0, 0);
3464 void WebView::deleteBackingStoreSoon()
3466 if (pendingDeleteBackingStoreSet().size() > 2) {
3467 Vector<WebView*> views;
3468 HashSet<WebView*>::iterator end = pendingDeleteBackingStoreSet().end();
3469 for (HashSet<WebView*>::iterator it = pendingDeleteBackingStoreSet().begin(); it != end; ++it)
3471 for (int i = 0; i < views.size(); ++i)
3472 views[i]->deleteBackingStore();
3473 ASSERT(pendingDeleteBackingStoreSet().isEmpty());
3476 pendingDeleteBackingStoreSet().add(this);
3477 m_deleteBackingStoreTimerActive = true;
3478 SetTimer(m_viewWindow, DeleteBackingStoreTimer, delayBeforeDeletingBackingStoreMsec, 0);
3481 void WebView::cancelDeleteBackingStoreSoon()
3483 if (!m_deleteBackingStoreTimerActive)
3485 pendingDeleteBackingStoreSet().remove(this);
3486 m_deleteBackingStoreTimerActive = false;
3487 KillTimer(m_viewWindow, DeleteBackingStoreTimer);
3490 HRESULT WebView::setHostWindow(/* [in] */ HWND window)
3494 SetParent(m_viewWindow, window);
3495 else if (!isBeingDestroyed()) {
3496 // Turn the WebView into a message-only window so it will no longer be a child of the
3497 // old host window and will be hidden from screen. We only do this when
3498 // isBeingDestroyed() is false because doing this while handling WM_DESTROY can leave
3499 // m_viewWindow in a weird state (see <http://webkit.org/b/29337>).
3500 SetParent(m_viewWindow, HWND_MESSAGE);
3504 m_hostWindow = window;
3506 windowAncestryDidChange();
3511 HRESULT WebView::hostWindow(/* [retval][out] */ HWND* window)
3513 *window = m_hostWindow;
3518 static Frame *incrementFrame(Frame *curr, bool forward, bool wrapFlag)
3521 ? curr->tree().traverseNextWithWrap(wrapFlag)
3522 : curr->tree().traversePreviousWithWrap(wrapFlag);
3525 HRESULT STDMETHODCALLTYPE WebView::searchFor(
3526 /* [in] */ BSTR str,
3527 /* [in] */ BOOL forward,
3528 /* [in] */ BOOL caseFlag,
3529 /* [in] */ BOOL wrapFlag,
3530 /* [retval][out] */ BOOL* found)
3533 return E_INVALIDARG;
3536 return E_UNEXPECTED;
3538 if (!str || !SysStringLen(str))
3539 return E_INVALIDARG;
3541 FindOptions options = (caseFlag ? 0 : CaseInsensitive) | (forward ? 0 : Backwards) | (wrapFlag ? WrapAround : 0);
3542 *found = m_page->findString(toString(str), options);
3546 bool WebView::active()
3548 HWND activeWindow = GetActiveWindow();
3549 if (usesLayeredWindow() && activeWindow == m_viewWindow)
3552 return (activeWindow && m_topLevelParent == findTopLevelParent(activeWindow));
3555 void WebView::updateActiveState()
3557 m_page->focusController().setActive(active());
3560 HRESULT STDMETHODCALLTYPE WebView::updateFocusedAndActiveState()
3562 updateActiveState();
3564 bool active = m_page->focusController().isActive();
3565 Frame& mainFrame = m_page->mainFrame();
3566 Frame& focusedFrame = m_page->focusController().focusedOrMainFrame();
3567 mainFrame.selection().setFocused(active && &mainFrame == &focusedFrame);
3572 HRESULT STDMETHODCALLTYPE WebView::executeCoreCommandByName(BSTR name, BSTR value)
3574 m_page->focusController().focusedOrMainFrame().editor().command(toString(name)).execute(toString(value));
3579 HRESULT STDMETHODCALLTYPE WebView::clearMainFrameName()
3581 m_page->mainFrame().tree().clearName();
3586 HRESULT STDMETHODCALLTYPE WebView::markAllMatchesForText(
3587 BSTR str, BOOL caseSensitive, BOOL highlight, UINT limit, UINT* matches)
3590 return E_INVALIDARG;
3593 return E_UNEXPECTED;
3595 if (!str || !SysStringLen(str))
3596 return E_INVALIDARG;
3598 *matches = m_page->markAllMatchesForText(toString(str), caseSensitive ? TextCaseSensitive : TextCaseInsensitive, highlight, limit);
3602 HRESULT STDMETHODCALLTYPE WebView::unmarkAllTextMatches()
3605 return E_UNEXPECTED;
3607 m_page->unmarkAllTextMatches();
3611 HRESULT STDMETHODCALLTYPE WebView::rectsForTextMatches(
3612 IEnumTextMatches** pmatches)
3614 Vector<IntRect> allRects;
3615 WebCore::Frame* frame = &m_page->mainFrame();
3617 if (Document* document = frame->document()) {
3618 IntRect visibleRect = frame->view()->visibleContentRect();