Remove CUSTOM_ELEMENTS build flag
[WebKit-https.git] / Source / WebKit / win / WebView.cpp
1 /*
2  * Copyright (C) 2006-2016 Apple, Inc.  All rights reserved.
3  * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
4  * Copyright (C) 2011 Brent Fulgham. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
26  */
27
28 #include "WebView.h"
29
30 #include "BackForwardList.h"
31 #include "COMVariantSetter.h"
32 #include "DOMCoreClasses.h"
33 #include "FullscreenVideoController.h"
34 #include "MarshallingHelpers.h"
35 #include "PluginDatabase.h"
36 #include "PluginView.h"
37 #include "SocketProvider.h"
38 #include "SoftLinking.h"
39 #include "SubframeLoader.h"
40 #include "TextIterator.h"
41 #include "WebApplicationCache.h"
42 #include "WebBackForwardList.h"
43 #include "WebChromeClient.h"
44 #include "WebContextMenuClient.h"
45 #include "WebCoreTextRenderer.h"
46 #include "WebDatabaseManager.h"
47 #include "WebDatabaseProvider.h"
48 #include "WebDocumentLoader.h"
49 #include "WebDownload.h"
50 #include "WebDragClient.h"
51 #include "WebEditorClient.h"
52 #include "WebElementPropertyBag.h"
53 #include "WebFrame.h"
54 #include "WebFrameLoaderClient.h"
55 #include "WebFrameNetworkingContext.h"
56 #include "WebGeolocationClient.h"
57 #include "WebGeolocationPosition.h"
58 #include "WebIconDatabase.h"
59 #include "WebInspector.h"
60 #include "WebInspectorClient.h"
61 #include "WebKit.h"
62 #include "WebKitDLL.h"
63 #include "WebKitLogging.h"
64 #include "WebKitStatisticsPrivate.h"
65 #include "WebKitSystemBits.h"
66 #include "WebKitVersion.h"
67 #include "WebMutableURLRequest.h"
68 #include "WebNotificationCenter.h"
69 #include "WebPlatformStrategies.h"
70 #include "WebPluginInfoProvider.h"
71 #include "WebPreferences.h"
72 #include "WebResourceLoadScheduler.h"
73 #include "WebScriptWorld.h"
74 #include "WebStorageNamespaceProvider.h"
75 #include "WebViewGroup.h"
76 #include "WebVisitedLinkStore.h"
77 #include "resource.h"
78 #include <JavaScriptCore/APICast.h>
79 #include <JavaScriptCore/Exception.h>
80 #include <JavaScriptCore/InitializeThreading.h>
81 #include <JavaScriptCore/JSCJSValue.h>
82 #include <JavaScriptCore/JSLock.h>
83 #include <WebCore/AXObjectCache.h>
84 #include <WebCore/ApplicationCacheStorage.h>
85 #include <WebCore/BString.h>
86 #include <WebCore/BackForwardController.h>
87 #include <WebCore/BitmapInfo.h>
88 #include <WebCore/Chrome.h>
89 #include <WebCore/ContextMenu.h>
90 #include <WebCore/ContextMenuController.h>
91 #include <WebCore/Cursor.h>
92 #include <WebCore/DatabaseManager.h>
93 #include <WebCore/Document.h>
94 #include <WebCore/DocumentMarkerController.h>
95 #include <WebCore/DragController.h>
96 #include <WebCore/DragData.h>
97 #include <WebCore/Editor.h>
98 #include <WebCore/EventHandler.h>
99 #include <WebCore/EventNames.h>
100 #include <WebCore/FileSystem.h>
101 #include <WebCore/FloatQuad.h>
102 #include <WebCore/FocusController.h>
103 #include <WebCore/Font.h>
104 #include <WebCore/FrameLoader.h>
105 #include <WebCore/FrameSelection.h>
106 #include <WebCore/FrameTree.h>
107 #include <WebCore/FrameView.h>
108 #include <WebCore/FrameWin.h>
109 #include <WebCore/FullScreenController.h>
110 #include <WebCore/GDIObjectCounter.h>
111 #include <WebCore/GDIUtilities.h>
112 #include <WebCore/GeolocationController.h>
113 #include <WebCore/GeolocationError.h>
114 #include <WebCore/GraphicsContext.h>
115 #include <WebCore/HTMLNames.h>
116 #include <WebCore/HTMLVideoElement.h>
117 #include <WebCore/HWndDC.h>
118 #include <WebCore/HistoryController.h>
119 #include <WebCore/HistoryItem.h>
120 #include <WebCore/HitTestRequest.h>
121 #include <WebCore/HitTestResult.h>
122 #include <WebCore/IntRect.h>
123 #include <WebCore/JSElement.h>
124 #include <WebCore/KeyboardEvent.h>
125 #include <WebCore/LogInitialization.h>
126 #include <WebCore/Logging.h>
127 #include <WebCore/MIMETypeRegistry.h>
128 #include <WebCore/MainFrame.h>
129 #include <WebCore/MemoryCache.h>
130 #include <WebCore/MemoryPressureHandler.h>
131 #include <WebCore/NotImplemented.h>
132 #include <WebCore/Page.h>
133 #include <WebCore/PageCache.h>
134 #include <WebCore/PageConfiguration.h>
135 #include <WebCore/PageGroup.h>
136 #include <WebCore/PathUtilities.h>
137 #include <WebCore/PlatformKeyboardEvent.h>
138 #include <WebCore/PlatformMouseEvent.h>
139 #include <WebCore/PlatformWheelEvent.h>
140 #include <WebCore/PluginData.h>
141 #include <WebCore/PopupMenu.h>
142 #include <WebCore/PopupMenuWin.h>
143 #include <WebCore/ProgressTracker.h>
144 #include <WebCore/RenderLayer.h>
145 #include <WebCore/RenderTheme.h>
146 #include <WebCore/RenderTreeAsText.h>
147 #include <WebCore/RenderView.h>
148 #include <WebCore/RenderWidget.h>
149 #include <WebCore/ResourceHandle.h>
150 #include <WebCore/ResourceHandleClient.h>
151 #include <WebCore/ResourceRequest.h>
152 #include <WebCore/RuntimeEnabledFeatures.h>
153 #include <WebCore/SchemeRegistry.h>
154 #include <WebCore/ScriptController.h>
155 #include <WebCore/Scrollbar.h>
156 #include <WebCore/ScrollbarTheme.h>
157 #include <WebCore/SecurityOrigin.h>
158 #include <WebCore/SecurityPolicy.h>
159 #include <WebCore/Settings.h>
160 #include <WebCore/SystemInfo.h>
161 #include <WebCore/UserContentController.h>
162 #include <WebCore/UserScript.h>
163 #include <WebCore/UserStyleSheet.h>
164 #include <WebCore/WindowMessageBroadcaster.h>
165 #include <WebCore/WindowsTouch.h>
166 #include <bindings/ScriptValue.h>
167 #include <comdef.h>
168 #include <d2d1.h>
169 #include <wtf/MainThread.h>
170 #include <wtf/RAMSize.h>
171 #include <wtf/UniqueRef.h>
172
173 #if USE(CG)
174 #include <CoreGraphics/CGContext.h>
175 #endif
176
177 #if USE(CF)
178 #include <CoreFoundation/CoreFoundation.h>
179 #endif
180
181 #if USE(CFURLCONNECTION)
182 #include <CFNetwork/CFURLCachePriv.h>
183 #include <CFNetwork/CFURLProtocolPriv.h>
184 #include <WebKitSystemInterface/WebKitSystemInterface.h>
185 #elif USE(CURL)
186 #include <WebCore/CurlCacheManager.h>
187 #endif
188
189 #if USE(CA)
190 #include <WebCore/CACFLayerTreeHost.h>
191 #include <WebCore/PlatformCALayer.h>
192 #elif USE(TEXTURE_MAPPER_GL)
193 #include "AcceleratedCompositingContext.h"
194 #endif
195
196 #if ENABLE(FULLSCREEN_API)
197 #include <WebCore/FullScreenController.h>
198 #endif
199
200 #include <ShlObj.h>
201 #include <comutil.h>
202 #include <dimm.h>
203 #include <oleacc.h>
204 #include <wchar.h>
205 #include <windowsx.h>
206 #include <winuser.h>
207 #include <wtf/HashSet.h>
208 #include <wtf/text/CString.h>
209 #include <wtf/text/StringConcatenate.h>
210 #include <wtf/win/GDIObject.h>
211
212 #define WEBKIT_DRAWING 4
213
214 // Soft link functions for gestures and panning feedback
215 SOFT_LINK_LIBRARY(USER32);
216 SOFT_LINK_OPTIONAL(USER32, GetGestureInfo, BOOL, WINAPI, (HGESTUREINFO, PGESTUREINFO));
217 SOFT_LINK_OPTIONAL(USER32, SetGestureConfig, BOOL, WINAPI, (HWND, DWORD, UINT, PGESTURECONFIG, UINT));
218 SOFT_LINK_OPTIONAL(USER32, CloseGestureInfoHandle, BOOL, WINAPI, (HGESTUREINFO));
219 SOFT_LINK_LIBRARY(Uxtheme);
220 SOFT_LINK_OPTIONAL(Uxtheme, BeginPanningFeedback, BOOL, WINAPI, (HWND));
221 SOFT_LINK_OPTIONAL(Uxtheme, EndPanningFeedback, BOOL, WINAPI, (HWND, BOOL));
222 SOFT_LINK_OPTIONAL(Uxtheme, UpdatePanningFeedback, BOOL, WINAPI, (HWND, LONG, LONG, BOOL));
223
224 using namespace WebCore;
225 using namespace std;
226 using JSC::JSLock;
227
228 static HMODULE accessibilityLib;
229 static HashSet<WebView*>& pendingDeleteBackingStoreSet()
230 {
231     static NeverDestroyed<HashSet<WebView*>> pendingDeleteBackingStoreSet;
232     return pendingDeleteBackingStoreSet;
233 }
234
235 static CFStringRef WebKitLocalCacheDefaultsKey = CFSTR("WebKitLocalCache");
236
237 static String webKitVersionString();
238
239 WebView* kit(Page* page)
240 {
241     if (!page)
242         return 0;
243     
244     if (page->chrome().client().isEmptyChromeClient())
245         return 0;
246     
247     return static_cast<WebChromeClient&>(page->chrome().client()).webView();
248 }
249
250 static inline AtomicString toAtomicString(BSTR bstr)
251 {
252     return AtomicString(bstr, SysStringLen(bstr));
253 }
254
255 static inline String toString(BSTR bstr)
256 {
257     return String(bstr, SysStringLen(bstr));
258 }
259
260 static inline String toString(BString &bstr)
261 {
262     return String(bstr, SysStringLen(bstr));
263 }
264
265 static inline URL toURL(BSTR bstr)
266 {
267     return URL(URL(), toString(bstr));
268 }
269
270 static String localStorageDatabasePath(WebPreferences* preferences)
271 {
272     BString localStorageDatabasePath;
273     if (FAILED(preferences->localStorageDatabasePath(&localStorageDatabasePath)))
274         return String();
275
276     return toString(localStorageDatabasePath);
277 }
278
279 class PreferencesChangedOrRemovedObserver : public IWebNotificationObserver {
280 public:
281     static PreferencesChangedOrRemovedObserver* sharedInstance();
282
283 private:
284     PreferencesChangedOrRemovedObserver() {}
285     ~PreferencesChangedOrRemovedObserver() {}
286
287     virtual HRESULT STDMETHODCALLTYPE QueryInterface(_In_ REFIID, _Outptr_ void**) { return E_FAIL; }
288     virtual ULONG STDMETHODCALLTYPE AddRef() { return 0; }
289     virtual ULONG STDMETHODCALLTYPE Release() { return 0; }
290
291 public:
292     // IWebNotificationObserver
293     virtual HRESULT STDMETHODCALLTYPE onNotify( 
294         /* [in] */ IWebNotification* notification);
295
296 private:
297     HRESULT notifyPreferencesChanged(WebCacheModel);
298     HRESULT notifyPreferencesRemoved(WebCacheModel);
299 };
300
301 PreferencesChangedOrRemovedObserver* PreferencesChangedOrRemovedObserver::sharedInstance()
302 {
303     static PreferencesChangedOrRemovedObserver* shared = new PreferencesChangedOrRemovedObserver;
304     return shared;
305 }
306
307 HRESULT PreferencesChangedOrRemovedObserver::onNotify(IWebNotification* notification)
308 {
309     HRESULT hr = S_OK;
310
311     COMPtr<IUnknown> unkPrefs;
312     hr = notification->getObject(&unkPrefs);
313     if (FAILED(hr))
314         return hr;
315
316     COMPtr<IWebPreferences> preferences(Query, unkPrefs);
317     if (!preferences)
318         return E_NOINTERFACE;
319
320     WebCacheModel cacheModel;
321     hr = preferences->cacheModel(&cacheModel);
322     if (FAILED(hr))
323         return hr;
324
325     BString name;
326     hr = notification->name(&name);
327     if (FAILED(hr))
328         return hr;
329
330     if (wcscmp(name, WebPreferences::webPreferencesChangedNotification()) == 0)
331         return notifyPreferencesChanged(cacheModel);
332
333     if (wcscmp(name, WebPreferences::webPreferencesRemovedNotification()) == 0)
334         return notifyPreferencesRemoved(cacheModel);
335
336     ASSERT_NOT_REACHED();
337     return E_FAIL;
338 }
339
340 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesChanged(WebCacheModel cacheModel)
341 {
342     HRESULT hr = S_OK;
343
344     if (!WebView::didSetCacheModel() || cacheModel > WebView::cacheModel())
345         WebView::setCacheModel(cacheModel);
346     else if (cacheModel < WebView::cacheModel()) {
347         WebCacheModel sharedPreferencesCacheModel;
348         hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel);
349         if (FAILED(hr))
350             return hr;
351         WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance()));
352     }
353
354     return hr;
355 }
356
357 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesRemoved(WebCacheModel cacheModel)
358 {
359     HRESULT hr = S_OK;
360
361     if (cacheModel == WebView::cacheModel()) {
362         WebCacheModel sharedPreferencesCacheModel;
363         hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel);
364         if (FAILED(hr))
365             return hr;
366         WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance()));
367     }
368
369     return hr;
370 }
371
372
373 const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass";
374
375 const int WM_XP_THEMECHANGED = 0x031A;
376 const int WM_VISTA_MOUSEHWHEEL = 0x020E;
377 #ifndef WM_DPICHANGED
378 const int WM_DPICHANGED = 0x02E0;
379 #endif
380
381 static const int maxToolTipWidth = 250;
382
383 static const int delayBeforeDeletingBackingStoreMsec = 5000;
384
385 static ATOM registerWebView();
386
387 static void initializeStaticObservers();
388
389 static HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences*);
390
391 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches);
392
393 static bool continuousSpellCheckingEnabled;
394 static bool grammarCheckingEnabled;
395
396 static bool s_didSetCacheModel;
397 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
398
399 enum {
400     UpdateActiveStateTimer = 1,
401     DeleteBackingStoreTimer = 2,
402 };
403
404 // WebView ----------------------------------------------------------------
405
406 bool WebView::s_allowSiteSpecificHacks = false;
407
408 WebView::WebView()
409 {
410     JSC::initializeThreading();
411     WTF::initializeMainThread();
412     RunLoop::initializeMainRunLoop();
413
414     m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
415
416     CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper,(void**)&m_dropTargetHelper);
417
418     initializeStaticObservers();
419
420     WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences();
421     BOOL enabled = FALSE;
422     if (SUCCEEDED(sharedPreferences->continuousSpellCheckingEnabled(&enabled)))
423         continuousSpellCheckingEnabled = !!enabled;
424     if (SUCCEEDED(sharedPreferences->grammarCheckingEnabled(&enabled)))
425         grammarCheckingEnabled = !!enabled;
426
427     m_webViewGroup = WebViewGroup::getOrCreate(String(), localStorageDatabasePath(sharedPreferences));
428     m_webViewGroup->addWebView(this);
429
430     WebViewCount++;
431     gClassCount++;
432     gClassNameCount().add("WebView");
433 }
434
435 WebView::~WebView()
436 {
437     deleteBackingStore();
438
439     // the tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD
440     if (::IsWindow(m_toolTipHwnd))
441         ::DestroyWindow(m_toolTipHwnd);
442
443     ASSERT(!m_page);
444     ASSERT(!m_preferences);
445     ASSERT(!m_viewWindow);
446
447 #if USE(CA)
448     ASSERT(!m_layerTreeHost);
449 #endif
450
451     m_webViewGroup->removeWebView(this);
452
453     WebViewCount--;
454     gClassCount--;
455     gClassNameCount().remove("WebView");
456 }
457
458 WebView* WebView::createInstance()
459 {
460     WebView* instance = new WebView();
461     instance->AddRef();
462     return instance;
463 }
464
465 void initializeStaticObservers()
466 {
467     static bool initialized = false;
468     if (initialized)
469         return;
470     initialized = true;
471
472     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
473     notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesChangedNotification(), 0);
474     notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesRemovedNotification(), 0);
475 }
476
477 static HashSet<WebView*>& allWebViewsSet()
478 {
479     static HashSet<WebView*> allWebViewsSet;
480     return allWebViewsSet;
481 }
482
483 void WebView::addToAllWebViewsSet()
484 {
485     allWebViewsSet().add(this);
486 }
487
488 void WebView::removeFromAllWebViewsSet()
489 {
490     allWebViewsSet().remove(this);
491 }
492
493 void WebView::setCacheModel(WebCacheModel cacheModel)
494 {
495     if (s_didSetCacheModel && cacheModel == s_cacheModel)
496         return;
497
498     String cacheDirectory;
499
500 #if USE(CFURLCONNECTION)
501     RetainPtr<CFURLCacheRef> cfurlCache = adoptCF(CFURLCacheCopySharedURLCache());
502     RetainPtr<CFStringRef> cfurlCacheDirectory = adoptCF(wkCopyFoundationCacheDirectory(0));
503     if (!cfurlCacheDirectory) {
504         RetainPtr<CFPropertyListRef> preference = adoptCF(CFPreferencesCopyAppValue(WebKitLocalCacheDefaultsKey, WebPreferences::applicationId()));
505         if (preference && (CFStringGetTypeID() == CFGetTypeID(preference.get())))
506             cfurlCacheDirectory = adoptCF(static_cast<CFStringRef>(preference.leakRef()));
507         else
508             cfurlCacheDirectory = WebCore::localUserSpecificStorageDirectory().createCFString();
509     }
510     cacheDirectory = String(cfurlCacheDirectory.get());
511     CFIndex cacheMemoryCapacity = 0;
512     CFIndex cacheDiskCapacity = 0;
513 #elif USE(CURL)
514     cacheDirectory = CurlCacheManager::getInstance().cacheDirectory();
515     long cacheMemoryCapacity = 0;
516     long cacheDiskCapacity = 0;
517 #endif
518
519     unsigned long long memSize = ramSize() / 1024 / 1024;
520
521     // As a fudge factor, use 1000 instead of 1024, in case the reported byte 
522     // count doesn't align exactly to a megabyte boundary.
523     unsigned long long diskFreeSize = WebVolumeFreeSize(cacheDirectory) / 1024 / 1000;
524
525     unsigned cacheTotalCapacity = 0;
526     unsigned cacheMinDeadCapacity = 0;
527     unsigned cacheMaxDeadCapacity = 0;
528     auto deadDecodedDataDeletionInterval = std::chrono::seconds { 0 };
529
530     unsigned pageCacheSize = 0;
531
532
533     switch (cacheModel) {
534     case WebCacheModelDocumentViewer: {
535         // Page cache capacity (in pages)
536         pageCacheSize = 0;
537
538         // Object cache capacities (in bytes)
539         if (memSize >= 2048)
540             cacheTotalCapacity = 96 * 1024 * 1024;
541         else if (memSize >= 1536)
542             cacheTotalCapacity = 64 * 1024 * 1024;
543         else if (memSize >= 1024)
544             cacheTotalCapacity = 32 * 1024 * 1024;
545         else if (memSize >= 512)
546             cacheTotalCapacity = 16 * 1024 * 1024; 
547
548         cacheMinDeadCapacity = 0;
549         cacheMaxDeadCapacity = 0;
550
551         // Memory cache capacity (in bytes)
552         cacheMemoryCapacity = 0;
553
554 #if USE(CFURLCONNECTION)
555         // Foundation disk cache capacity (in bytes)
556         cacheDiskCapacity = CFURLCacheDiskCapacity(cfurlCache.get());
557 #endif
558         break;
559     }
560     case WebCacheModelDocumentBrowser: {
561         // Page cache capacity (in pages)
562         if (memSize >= 1024)
563             pageCacheSize = 3;
564         else if (memSize >= 512)
565             pageCacheSize = 2;
566         else if (memSize >= 256)
567             pageCacheSize = 1;
568         else
569             pageCacheSize = 0;
570
571         // Object cache capacities (in bytes)
572         if (memSize >= 2048)
573             cacheTotalCapacity = 96 * 1024 * 1024;
574         else if (memSize >= 1536)
575             cacheTotalCapacity = 64 * 1024 * 1024;
576         else if (memSize >= 1024)
577             cacheTotalCapacity = 32 * 1024 * 1024;
578         else if (memSize >= 512)
579             cacheTotalCapacity = 16 * 1024 * 1024; 
580
581         cacheMinDeadCapacity = cacheTotalCapacity / 8;
582         cacheMaxDeadCapacity = cacheTotalCapacity / 4;
583
584         // Memory cache capacity (in bytes)
585         if (memSize >= 2048)
586             cacheMemoryCapacity = 4 * 1024 * 1024;
587         else if (memSize >= 1024)
588             cacheMemoryCapacity = 2 * 1024 * 1024;
589         else if (memSize >= 512)
590             cacheMemoryCapacity = 1 * 1024 * 1024;
591         else
592             cacheMemoryCapacity =      512 * 1024; 
593
594         // Disk cache capacity (in bytes)
595         if (diskFreeSize >= 16384)
596             cacheDiskCapacity = 50 * 1024 * 1024;
597         else if (diskFreeSize >= 8192)
598             cacheDiskCapacity = 40 * 1024 * 1024;
599         else if (diskFreeSize >= 4096)
600             cacheDiskCapacity = 30 * 1024 * 1024;
601         else
602             cacheDiskCapacity = 20 * 1024 * 1024;
603
604         break;
605     }
606     case WebCacheModelPrimaryWebBrowser: {
607         // Page cache capacity (in pages)
608         // (Research indicates that value / page drops substantially after 3 pages.)
609         if (memSize >= 2048)
610             pageCacheSize = 5;
611         else if (memSize >= 1024)
612             pageCacheSize = 4;
613         else if (memSize >= 512)
614             pageCacheSize = 3;
615         else if (memSize >= 256)
616             pageCacheSize = 2;
617         else
618             pageCacheSize = 1;
619
620         // Object cache capacities (in bytes)
621         // (Testing indicates that value / MB depends heavily on content and
622         // browsing pattern. Even growth above 128MB can have substantial 
623         // value / MB for some content / browsing patterns.)
624         if (memSize >= 2048)
625             cacheTotalCapacity = 128 * 1024 * 1024;
626         else if (memSize >= 1536)
627             cacheTotalCapacity = 96 * 1024 * 1024;
628         else if (memSize >= 1024)
629             cacheTotalCapacity = 64 * 1024 * 1024;
630         else if (memSize >= 512)
631             cacheTotalCapacity = 32 * 1024 * 1024; 
632
633         cacheMinDeadCapacity = cacheTotalCapacity / 4;
634         cacheMaxDeadCapacity = cacheTotalCapacity / 2;
635
636         // This code is here to avoid a PLT regression. We can remove it if we
637         // can prove that the overall system gain would justify the regression.
638         cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity);
639
640         deadDecodedDataDeletionInterval = std::chrono::seconds { 60 };
641
642         // Memory cache capacity (in bytes)
643         // (These values are small because WebCore does most caching itself.)
644         if (memSize >= 1024)
645             cacheMemoryCapacity = 4 * 1024 * 1024;
646         else if (memSize >= 512)
647             cacheMemoryCapacity = 2 * 1024 * 1024;
648         else if (memSize >= 256)
649             cacheMemoryCapacity = 1 * 1024 * 1024;
650         else
651             cacheMemoryCapacity =      512 * 1024; 
652
653         // Disk cache capacity (in bytes)
654         if (diskFreeSize >= 16384)
655             cacheDiskCapacity = 175 * 1024 * 1024;
656         else if (diskFreeSize >= 8192)
657             cacheDiskCapacity = 150 * 1024 * 1024;
658         else if (diskFreeSize >= 4096)
659             cacheDiskCapacity = 125 * 1024 * 1024;
660         else if (diskFreeSize >= 2048)
661             cacheDiskCapacity = 100 * 1024 * 1024;
662         else if (diskFreeSize >= 1024)
663             cacheDiskCapacity = 75 * 1024 * 1024;
664         else
665             cacheDiskCapacity = 50 * 1024 * 1024;
666
667         break;
668     }
669     default:
670         ASSERT_NOT_REACHED();
671     }
672
673     auto& memoryCache = MemoryCache::singleton();
674     memoryCache.setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
675     memoryCache.setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
676     PageCache::singleton().setMaxSize(pageCacheSize);
677
678 #if USE(CFURLCONNECTION)
679     // Don't shrink a big disk cache, since that would cause churn.
680     cacheDiskCapacity = max(cacheDiskCapacity, CFURLCacheDiskCapacity(cfurlCache.get()));
681
682     CFURLCacheSetMemoryCapacity(cfurlCache.get(), cacheMemoryCapacity);
683     CFURLCacheSetDiskCapacity(cfurlCache.get(), cacheDiskCapacity);
684 #elif USE(CURL)
685     CurlCacheManager::getInstance().setStorageSizeLimit(cacheDiskCapacity);
686 #endif
687
688     s_didSetCacheModel = true;
689     s_cacheModel = cacheModel;
690     return;
691 }
692
693 WebCacheModel WebView::cacheModel()
694 {
695     return s_cacheModel;
696 }
697
698 bool WebView::didSetCacheModel()
699 {
700     return s_didSetCacheModel;
701 }
702
703 WebCacheModel WebView::maxCacheModelInAnyInstance()
704 {
705     WebCacheModel cacheModel = WebCacheModelDocumentViewer;
706
707     HashSet<WebView*>::iterator end = allWebViewsSet().end();
708     for (HashSet<WebView*>::iterator it = allWebViewsSet().begin(); it != end; ++it) {
709         COMPtr<IWebPreferences> pref;
710         if (FAILED((*it)->preferences(&pref)))
711             continue;
712         WebCacheModel prefCacheModel = WebCacheModelDocumentViewer;
713         if (FAILED(pref->cacheModel(&prefCacheModel)))
714             continue;
715
716         cacheModel = max(cacheModel, prefCacheModel);
717     }
718
719     return cacheModel;
720 }
721
722 HRESULT WebView::close()
723 {
724     if (m_didClose)
725         return S_OK;
726
727     m_didClose = true;
728
729     setAcceleratedCompositing(false);
730
731     WebNotificationCenter::defaultCenterInternal()->postNotificationName(_bstr_t(WebViewWillCloseNotification).GetBSTR(), static_cast<IWebView*>(this), 0);
732
733     if (m_uiDelegatePrivate)
734         m_uiDelegatePrivate->webViewClosing(this);
735
736     removeFromAllWebViewsSet();
737
738     if (m_page)
739         m_page->mainFrame().loader().detachFromParent();
740
741     if (m_mouseOutTracker) {
742         m_mouseOutTracker->dwFlags = TME_CANCEL;
743         ::TrackMouseEvent(m_mouseOutTracker.get());
744         m_mouseOutTracker.reset();
745     }
746     
747     revokeDragDrop();
748
749     if (m_viewWindow) {
750         // We can't check IsWindow(m_viewWindow) here, because that will return true even while
751         // we're already handling WM_DESTROY. So we check !isBeingDestroyed() instead.
752         if (!isBeingDestroyed())
753             DestroyWindow(m_viewWindow);
754         // Either we just destroyed m_viewWindow, or it's in the process of being destroyed. Either
755         // way, we clear it out to make sure we don't try to use it later.
756         m_viewWindow = 0;
757     }
758
759     setHostWindow(0);
760
761     setAccessibilityDelegate(0);
762     setDownloadDelegate(0);
763     setEditingDelegate(0);
764     setFrameLoadDelegate(0);
765     setFrameLoadDelegatePrivate(0);
766     setHistoryDelegate(0);
767     setPolicyDelegate(0);
768     setResourceLoadDelegate(0);
769     setUIDelegate(0);
770     setFormDelegate(0);
771
772     m_inspectorClient = nullptr;
773     if (m_webInspector)
774         m_webInspector->inspectedWebViewClosed();
775
776     delete m_page;
777     m_page = nullptr;
778
779     m_mainFrame = nullptr;
780
781     registerForIconNotification(false);
782     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
783     notifyCenter->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
784
785     if (COMPtr<WebPreferences> preferences = m_preferences) {
786         BString identifier;
787         preferences->identifier(&identifier);
788
789         m_preferences = 0;
790         preferences->didRemoveFromWebView();
791         // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
792         preferences = 0;
793         if (identifier)
794             WebPreferences::removeReferenceForIdentifier(identifier);
795     }
796
797     deleteBackingStore();
798     return S_OK;
799 }
800
801 void WebView::repaint(const WebCore::IntRect& logicalWindowRect, bool contentChanged, bool immediate, bool repaintContentOnly)
802 {
803     FloatRect windowRectFloat(logicalWindowRect);
804     windowRectFloat.scale(deviceScaleFactor());
805     IntRect windowRect(enclosingIntRect(windowRectFloat));
806
807     if (isAcceleratedCompositing()) {
808         // The contentChanged, immediate, and repaintContentOnly parameters are all based on a non-
809         // compositing painting/scrolling model.
810         addToDirtyRegion(logicalWindowRect);
811         return;
812     }
813
814     if (!repaintContentOnly) {
815         RECT rect = windowRect;
816         ::InvalidateRect(m_viewWindow, &rect, false);
817     }
818     if (contentChanged)
819         addToDirtyRegion(windowRect);
820     if (immediate) {
821         if (repaintContentOnly)
822             updateBackingStore(core(topLevelFrame())->view());
823         else
824             ::UpdateWindow(m_viewWindow);
825     }
826     m_needsDisplay = true;
827 }
828
829 void WebView::deleteBackingStore()
830 {
831     pendingDeleteBackingStoreSet().remove(this);
832
833     if (m_deleteBackingStoreTimerActive) {
834         KillTimer(m_viewWindow, DeleteBackingStoreTimer);
835         m_deleteBackingStoreTimerActive = false;
836     }
837     m_backingStoreBitmap = nullptr;
838 #if USE(DIRECT2D)
839     m_backingStoreD2DBitmap = nullptr;
840     m_backingStoreGdiInterop = nullptr;
841     m_backingStoreRenderTarget = nullptr;
842 #endif
843     m_backingStoreDirtyRegion = nullptr;
844     m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
845 }
846
847 bool WebView::ensureBackingStore()
848 {
849     RECT windowRect;
850     ::GetClientRect(m_viewWindow, &windowRect);
851     LONG width = windowRect.right - windowRect.left;
852     LONG height = windowRect.bottom - windowRect.top;
853     if (width > 0 && height > 0 && (width != m_backingStoreSize.cx || height != m_backingStoreSize.cy)) {
854         deleteBackingStore();
855
856 #if USE(DIRECT2D)
857         auto bitmapSize = D2D1::SizeF(width, height);
858         auto pixelSize = D2D1::SizeU(width, height);
859
860         if (!m_renderTarget) {
861             // Create a Direct2D render target.
862             auto renderTargetProperties = D2D1::RenderTargetProperties();
863             renderTargetProperties.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
864             auto hwndRenderTargetProperties = D2D1::HwndRenderTargetProperties(m_viewWindow, pixelSize);
865             HRESULT hr = GraphicsContext::systemFactory()->CreateHwndRenderTarget(&renderTargetProperties, &hwndRenderTargetProperties, &m_renderTarget);
866             if (!SUCCEEDED(hr))
867                 return false;
868         }
869
870         COMPtr<ID2D1SolidColorBrush> brush;
871         m_renderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::BlueViolet), &brush);
872
873         m_renderTarget->BeginDraw();
874         m_renderTarget->FillRoundedRectangle(D2D1::RoundedRect(D2D1::RectF(100.0f, 100.0f, 300.0f, 200.0f), 20.0f, 20.0f), brush.get());
875         m_renderTarget->EndDraw();
876 #endif
877         m_backingStoreSize.cx = width;
878         m_backingStoreSize.cy = height;
879         BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(m_backingStoreSize));
880
881         void* pixels = NULL;
882         m_backingStoreBitmap = SharedGDIObject<HBITMAP>::create(adoptGDIObject(::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0)));
883
884 #if USE(DIRECT2D)
885         HRESULT hr = m_renderTarget->CreateCompatibleRenderTarget(&bitmapSize, &pixelSize, nullptr, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_GDI_COMPATIBLE, &m_backingStoreRenderTarget);
886         RELEASE_ASSERT(SUCCEEDED(hr));
887
888         hr = m_backingStoreRenderTarget->GetBitmap(&m_backingStoreD2DBitmap);
889         RELEASE_ASSERT(SUCCEEDED(hr));
890
891         hr = m_backingStoreRenderTarget->QueryInterface(__uuidof(ID2D1GdiInteropRenderTarget), (void**)&m_backingStoreGdiInterop);
892         RELEASE_ASSERT(SUCCEEDED(hr));
893
894         COMPtr<ID2D1SolidColorBrush> brush2;
895         m_backingStoreRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::SeaGreen), &brush2);
896         m_backingStoreRenderTarget->BeginDraw();
897         m_renderTarget->FillRoundedRectangle(D2D1::RoundedRect(D2D1::RectF(100.0f, 100.0f, 300.0f, 200.0f), 20.0f, 20.0f), brush2.get());
898         m_renderTarget->EndDraw();
899 #endif
900         return true;
901     }
902
903     return false;
904 }
905
906 void WebView::addToDirtyRegion(const IntRect& dirtyRect)
907 {
908     m_needsDisplay = true;
909
910     // FIXME: We want an assert here saying that the dirtyRect is inside the clienRect,
911     // but it was being hit during our layout tests, and is being investigated in
912     // http://webkit.org/b/29350.
913
914     if (isAcceleratedCompositing()) {
915 #if USE(CA)
916         m_backingLayer->setNeedsDisplayInRect(dirtyRect);
917 #elif USE(TEXTURE_MAPPER_GL)
918         m_acceleratedCompositingContext->setNonCompositedContentsNeedDisplay(dirtyRect);
919 #endif
920         return;
921     }
922
923     auto newRegion = adoptGDIObject(::CreateRectRgn(dirtyRect.x(), dirtyRect.y(),
924         dirtyRect.maxX(), dirtyRect.maxY()));
925     addToDirtyRegion(WTFMove(newRegion));
926 }
927
928 void WebView::addToDirtyRegion(GDIObject<HRGN> newRegion)
929 {
930     m_needsDisplay = true;
931
932     ASSERT(!isAcceleratedCompositing());
933
934     LOCAL_GDI_COUNTER(0, __FUNCTION__);
935
936     if (m_backingStoreDirtyRegion) {
937         auto combinedRegion = adoptGDIObject(::CreateRectRgn(0, 0, 0, 0));
938         ::CombineRgn(combinedRegion.get(), m_backingStoreDirtyRegion->get(), newRegion.get(), RGN_OR);
939         m_backingStoreDirtyRegion = SharedGDIObject<HRGN>::create(WTFMove(combinedRegion));
940     } else
941         m_backingStoreDirtyRegion = SharedGDIObject<HRGN>::create(WTFMove(newRegion));
942
943     if (m_uiDelegatePrivate)
944         m_uiDelegatePrivate->webViewDidInvalidate(this);
945 }
946
947 void WebView::scrollBackingStore(FrameView* frameView, int logicalDx, int logicalDy, const IntRect& logicalScrollViewRect, const IntRect& logicalClipRect)
948 {
949     m_needsDisplay = true;
950
951     // Dimensions passed to us from WebCore are in logical units. We must convert to pixels:
952     float scaleFactor = deviceScaleFactor();
953     int dx = clampTo<int>(scaleFactor * logicalDx);
954     int dy = clampTo<int>(scaleFactor * logicalDy);
955     FloatRect scrollViewRectFloat(logicalScrollViewRect);
956     scrollViewRectFloat.scale(scaleFactor);
957     IntRect scrollViewRect(enclosingIntRect(scrollViewRectFloat));
958     FloatRect clipRect(logicalClipRect);
959     clipRect.scale(scaleFactor);
960
961 #if USE(DIRECT2D)
962     RECT scrollRectWin(scrollViewRect);
963     RECT clipRectWin(enclosingIntRect(clipRect));
964     RECT updateRect;
965     ::ScrollWindowEx(m_viewWindow, dx, dy, &scrollRectWin, &clipRectWin, nullptr, &updateRect, 0);
966     ::InvalidateRect(m_viewWindow, &updateRect, FALSE);
967
968     if (m_uiDelegatePrivate)
969         m_uiDelegatePrivate->webViewScrolled(this);
970 #else
971     if (isAcceleratedCompositing()) {
972         // FIXME: We should be doing something smarter here, like moving tiles around and painting
973         // any newly-exposed tiles. <http://webkit.org/b/52714>
974 #if USE(CA)
975         m_backingLayer->setNeedsDisplayInRect(scrollViewRect);
976 #elif USE(TEXTURE_MAPPER_GL)
977         m_acceleratedCompositingContext->scrollNonCompositedContents(scrollViewRect, IntSize(dx, dy));
978 #endif
979         return;
980     }
981
982     LOCAL_GDI_COUNTER(0, __FUNCTION__);
983
984     // If there's no backing store we don't need to update it
985     if (!m_backingStoreBitmap) {
986         if (m_uiDelegatePrivate)
987             m_uiDelegatePrivate->webViewScrolled(this);
988
989         return;
990     }
991
992     // Make a region to hold the invalidated scroll area.
993     auto updateRegion = adoptGDIObject(::CreateRectRgn(0, 0, 0, 0));
994
995     // Collect our device context info and select the bitmap to scroll.
996     HWndDC windowDC(m_viewWindow);
997     auto bitmapDC = adoptGDIObject(::CreateCompatibleDC(windowDC));
998     HGDIOBJ oldBitmap = ::SelectObject(bitmapDC.get(), m_backingStoreBitmap->get());
999     if (!oldBitmap) {
1000         // The ::SelectObject call will fail if m_backingStoreBitmap is already selected into a device context.
1001         // This happens when this method is called indirectly from WebView::updateBackingStore during normal WM_PAINT handling.
1002         // There is no point continuing, since we would just be scrolling a 1x1 bitmap which is selected into the device context by default.
1003         // We can just scroll by repainting the scroll rectangle.
1004         RECT scrollRect(scrollViewRect);
1005         ::InvalidateRect(m_viewWindow, &scrollRect, FALSE);
1006         return;
1007     }
1008
1009     // Scroll the bitmap.
1010     RECT scrollRectWin(scrollViewRect);
1011     RECT clipRectWin(enclosingIntRect(clipRect));
1012     ::ScrollDC(bitmapDC.get(), dx, dy, &scrollRectWin, &clipRectWin, updateRegion.get(), 0);
1013     RECT regionBox;
1014     ::GetRgnBox(updateRegion.get(), &regionBox);
1015
1016     // Flush.
1017     GdiFlush();
1018
1019     // Add the dirty region to the backing store's dirty region.
1020     addToDirtyRegion(WTFMove(updateRegion));
1021
1022     if (m_uiDelegatePrivate)
1023         m_uiDelegatePrivate->webViewScrolled(this);
1024
1025     // Update the backing store.
1026     updateBackingStore(frameView, bitmapDC.get(), false);
1027
1028     // Clean up.
1029     ::SelectObject(bitmapDC.get(), oldBitmap);
1030 #endif // USE(DIRECT2D)
1031 }
1032
1033 void WebView::sizeChanged(const IntSize& newSize)
1034 {
1035     m_needsDisplay = true;
1036
1037     deleteBackingStore();
1038
1039     if (Frame* coreFrame = core(topLevelFrame())) {
1040         IntSize logicalSize = newSize;
1041         logicalSize.scale(1.0f / deviceScaleFactor());
1042         coreFrame->view()->resize(logicalSize);
1043     }
1044
1045 #if USE(CA)
1046     if (m_layerTreeHost)
1047         m_layerTreeHost->resize();
1048
1049     if (m_backingLayer) {
1050         m_backingLayer->setSize(newSize);
1051         m_backingLayer->setNeedsDisplay();
1052     }
1053 #elif USE(TEXTURE_MAPPER_GL)
1054     if (m_acceleratedCompositingContext)
1055         m_acceleratedCompositingContext->resizeRootLayer(newSize);
1056 #endif
1057
1058 #if USE(DIRECT2D)
1059     if (m_renderTarget) {
1060         m_renderTarget->Resize(newSize);
1061         return;
1062     }
1063
1064     // Create a Direct2D render target.
1065     auto renderTargetProperties = D2D1::RenderTargetProperties();
1066     renderTargetProperties.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
1067     auto hwndRenderTargetProperties = D2D1::HwndRenderTargetProperties(m_viewWindow, newSize, D2D1_PRESENT_OPTIONS_IMMEDIATELY);
1068     HRESULT hr = GraphicsContext::systemFactory()->CreateHwndRenderTarget(&renderTargetProperties, &hwndRenderTargetProperties, &m_renderTarget);
1069     ASSERT(SUCCEEDED(hr));
1070 #endif
1071 }
1072
1073 bool WebView::dpiChanged(float, const WebCore::IntSize& newSize)
1074 {
1075     if (!IsProcessDPIAware())
1076         return false;
1077
1078     sizeChanged(newSize);
1079
1080     return true;
1081 }
1082
1083 // This emulates the Mac smarts for painting rects intelligently.  This is very
1084 // important for us, since we double buffer based off dirty rects.
1085 static void getUpdateRects(HRGN region, const IntRect& dirtyRect, Vector<IntRect>& rects)
1086 {
1087     ASSERT_ARG(region, region);
1088
1089     const int cRectThreshold = 10;
1090     const float cWastedSpaceThreshold = 0.75f;
1091
1092     rects.clear();
1093
1094     DWORD regionDataSize = GetRegionData(region, sizeof(RGNDATA), NULL);
1095     if (!regionDataSize) {
1096         rects.append(dirtyRect);
1097         return;
1098     }
1099
1100     Vector<unsigned char> buffer(regionDataSize);
1101     RGNDATA* regionData = reinterpret_cast<RGNDATA*>(buffer.data());
1102     GetRegionData(region, regionDataSize, regionData);
1103     if (regionData->rdh.nCount > cRectThreshold) {
1104         rects.append(dirtyRect);
1105         return;
1106     }
1107
1108     double singlePixels = 0.0;
1109     unsigned i;
1110     RECT* rect;
1111     for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++)
1112         singlePixels += (rect->right - rect->left) * (rect->bottom - rect->top);
1113
1114     double unionPixels = dirtyRect.width() * dirtyRect.height();
1115     double wastedSpace = 1.0 - (singlePixels / unionPixels);
1116     if (wastedSpace <= cWastedSpaceThreshold) {
1117         rects.append(dirtyRect);
1118         return;
1119     }
1120
1121     for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++)
1122         rects.append(*rect);
1123 }
1124
1125 void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStoreCompletelyDirty, WindowsToPaint windowsToPaint)
1126 {
1127     ASSERT(!isAcceleratedCompositing());
1128
1129     LOCAL_GDI_COUNTER(0, __FUNCTION__);
1130
1131 #if USE(DIRECT2D)
1132     if (!m_backingStoreGdiInterop) {
1133         HRESULT hr = m_backingStoreRenderTarget->QueryInterface(__uuidof(ID2D1GdiInteropRenderTarget), (void**)&m_backingStoreGdiInterop);
1134         RELEASE_ASSERT(SUCCEEDED(hr));
1135     }
1136 #endif
1137
1138     GDIObject<HDC> bitmapDCObject;
1139
1140     HDC bitmapDC = dc;
1141     HGDIOBJ oldBitmap = 0;
1142     if (!dc) {
1143         HWndDC windowDC(m_viewWindow);
1144         bitmapDCObject = adoptGDIObject(::CreateCompatibleDC(windowDC));
1145         bitmapDC = bitmapDCObject.get();
1146         oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->get());
1147 #if USE(DIRECT2D)
1148         HRESULT hr = m_backingStoreGdiInterop->GetDC(D2D1_DC_INITIALIZE_MODE_COPY, &bitmapDC);
1149         RELEASE_ASSERT(SUCCEEDED(hr));
1150 #endif
1151     }
1152
1153     if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
1154         // Do a layout first so that everything we render to the backing store is always current.
1155         if (Frame* coreFrame = core(m_mainFrame))
1156             if (FrameView* view = coreFrame->view())
1157                 view->updateLayoutAndStyleIfNeededRecursive();
1158
1159         Vector<IntRect> paintRects;
1160         if (!backingStoreCompletelyDirty && m_backingStoreDirtyRegion) {
1161             RECT regionBox;
1162             ::GetRgnBox(m_backingStoreDirtyRegion->get(), &regionBox);
1163             getUpdateRects(m_backingStoreDirtyRegion->get(), regionBox, paintRects);
1164         } else {
1165             RECT clientRect;
1166             ::GetClientRect(m_viewWindow, &clientRect);
1167             paintRects.append(clientRect);
1168         }
1169
1170         for (unsigned i = 0; i < paintRects.size(); ++i)
1171             paintIntoBackingStore(frameView, bitmapDC, paintRects[i], windowsToPaint);
1172
1173         if (m_uiDelegatePrivate)
1174             m_uiDelegatePrivate->webViewPainted(this);
1175
1176         m_backingStoreDirtyRegion = nullptr;
1177     }
1178
1179     if (!dc) {
1180         ::SelectObject(bitmapDC, oldBitmap);
1181 #if USE(DIRECT2D)
1182         m_backingStoreGdiInterop->ReleaseDC(nullptr);
1183 #endif
1184     }
1185
1186     GdiFlush();
1187
1188     m_needsDisplay = true;
1189 }
1190
1191 void WebView::performLayeredWindowUpdate()
1192 {
1193     // The backing store may have been destroyed if the window rect was set to zero height or zero width.
1194     if (!m_backingStoreBitmap)
1195         return;
1196
1197     HWndDC hdcScreen(m_viewWindow);
1198     auto hdcMem = adoptGDIObject(::CreateCompatibleDC(hdcScreen));
1199     HBITMAP hbmOld = static_cast<HBITMAP>(::SelectObject(hdcMem.get(), m_backingStoreBitmap->get()));
1200
1201     BITMAP bmpInfo;
1202     ::GetObject(m_backingStoreBitmap->get(), sizeof(bmpInfo), &bmpInfo);
1203     SIZE windowSize = { bmpInfo.bmWidth, bmpInfo.bmHeight };
1204
1205     BLENDFUNCTION blendFunction;
1206     blendFunction.BlendOp = AC_SRC_OVER;
1207     blendFunction.BlendFlags = 0;
1208     blendFunction.SourceConstantAlpha = 0xFF;
1209     blendFunction.AlphaFormat = AC_SRC_ALPHA;
1210
1211     POINT layerPos = { 0, 0 };
1212     ::UpdateLayeredWindow(m_viewWindow, hdcScreen, 0, &windowSize, hdcMem.get(), &layerPos, 0, &blendFunction, ULW_ALPHA);
1213
1214     ::SelectObject(hdcMem.get(), hbmOld);
1215
1216     m_needsDisplay = false;
1217 }
1218
1219 void WebView::paintWithDirect2D()
1220 {
1221 #if USE(DIRECT2D)
1222     Frame* coreFrame = core(m_mainFrame);
1223     if (!coreFrame)
1224         return;
1225     FrameView* frameView = coreFrame->view();
1226     frameView->updateLayoutAndStyleIfNeededRecursive();
1227
1228     if (!m_renderTarget) {
1229         // Create a Direct2D render target.
1230         auto renderTargetProperties = D2D1::RenderTargetProperties();
1231         renderTargetProperties.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
1232
1233         RECT rect;
1234         ::GetClientRect(m_viewWindow, &rect);
1235
1236         IntRect clientRect(rect);
1237
1238         auto pixelSize = D2D1::SizeU(clientRect.width(), clientRect.height());
1239
1240         auto hwndRenderTargetProperties = D2D1::HwndRenderTargetProperties(m_viewWindow, pixelSize, D2D1_PRESENT_OPTIONS_IMMEDIATELY);
1241         HRESULT hr = GraphicsContext::systemFactory()->CreateHwndRenderTarget(&renderTargetProperties, &hwndRenderTargetProperties, &m_renderTarget);
1242         if (!SUCCEEDED(hr))
1243             return;
1244     }
1245
1246     RECT clientRect = {};
1247     GraphicsContext gc(m_renderTarget.get());
1248
1249     {
1250         m_renderTarget->SetTags(WEBKIT_DRAWING, __LINE__);
1251         m_renderTarget->Clear();
1252
1253         // Direct2D honors the scale factor natively.
1254         float scaleFactor = 1.0f;
1255         float inverseScaleFactor = 1.0f / scaleFactor;
1256
1257         GetClientRect(m_viewWindow, &clientRect);
1258
1259         IntRect dirtyRectPixels(0, 0, clientRect.right, clientRect.bottom);
1260         FloatRect logicalDirtyRectFloat = dirtyRectPixels;
1261         logicalDirtyRectFloat.scale(inverseScaleFactor);
1262         IntRect logicalDirtyRect(enclosingIntRect(logicalDirtyRectFloat));
1263
1264         if (frameView && frameView->frame().contentRenderer()) {
1265             gc.save();
1266             gc.scale(FloatSize(scaleFactor, scaleFactor));
1267             gc.clip(logicalDirtyRect);
1268             frameView->paint(gc, logicalDirtyRect);
1269             gc.restore();
1270             if (m_shouldInvertColors)
1271                 gc.fillRect(logicalDirtyRect, Color::white, CompositeDifference);
1272         }
1273     }
1274
1275     ::ValidateRect(m_viewWindow, &clientRect);
1276 #else
1277     ASSERT_NOT_REACHED();
1278 #endif
1279 }
1280
1281 void WebView::paint(HDC dc, LPARAM options)
1282 {
1283     LOCAL_GDI_COUNTER(0, __FUNCTION__);
1284
1285     if (paintCompositedContentToHDC(dc)) {
1286         ::ValidateRect(m_viewWindow, nullptr);
1287         return;
1288     }
1289
1290     Frame* coreFrame = core(m_mainFrame);
1291     if (!coreFrame)
1292         return;
1293     FrameView* frameView = coreFrame->view();
1294
1295     RECT rcPaint;
1296     HDC hdc;
1297     GDIObject<HRGN> region;
1298     int regionType = NULLREGION;
1299     PAINTSTRUCT ps;
1300     WindowsToPaint windowsToPaint;
1301     if (!dc) {
1302         region = adoptGDIObject(::CreateRectRgn(0, 0, 0, 0));
1303         regionType = GetUpdateRgn(m_viewWindow, region.get(), false);
1304         hdc = BeginPaint(m_viewWindow, &ps);
1305         rcPaint = ps.rcPaint;
1306         // We're painting to the screen, and our child windows can handle
1307         // painting themselves to the screen.
1308         windowsToPaint = PaintWebViewOnly;
1309     } else {
1310         hdc = dc;
1311         ::GetClientRect(m_viewWindow, &rcPaint);
1312         if (options & PRF_ERASEBKGND)
1313             ::FillRect(hdc, &rcPaint, (HBRUSH)GetStockObject(WHITE_BRUSH));
1314         // Since we aren't painting to the screen, we want to paint all our
1315         // children into the HDC.
1316         windowsToPaint = PaintWebViewAndChildren;
1317     }
1318
1319     bool backingStoreCompletelyDirty = ensureBackingStore();
1320     if (!m_backingStoreBitmap) {
1321         if (!dc)
1322             EndPaint(m_viewWindow, &ps);
1323         return;
1324     }
1325
1326     m_paintCount++;
1327
1328     auto bitmapDC = adoptGDIObject(::CreateCompatibleDC(hdc));
1329     HGDIOBJ oldBitmap = ::SelectObject(bitmapDC.get(), m_backingStoreBitmap->get());
1330
1331     // Update our backing store if needed.
1332     updateBackingStore(frameView, bitmapDC.get(), backingStoreCompletelyDirty, windowsToPaint);
1333
1334     // Now we blit the updated backing store
1335     IntRect windowDirtyRect = rcPaint;
1336     
1337     // Apply the same heuristic for this update region too.
1338     Vector<IntRect> blitRects;
1339     if (region && regionType == COMPLEXREGION)
1340         getUpdateRects(region.get(), windowDirtyRect, blitRects);
1341     else
1342         blitRects.append(windowDirtyRect);
1343
1344     for (unsigned i = 0; i < blitRects.size(); ++i)
1345         paintIntoWindow(bitmapDC.get(), hdc, blitRects[i]);
1346
1347     ::SelectObject(bitmapDC.get(), oldBitmap);
1348
1349     if (!dc) {
1350         EndPaint(m_viewWindow, &ps);
1351 #if USE(DIRECT2D)
1352         HRESULT hr = m_backingStoreRenderTarget->EndDraw();
1353         // FIXME: Recognize and recover from error state:
1354         RELEASE_ASSERT(SUCCEEDED(hr));
1355 #endif
1356     }
1357
1358 #if USE(DIRECT2D)
1359     m_backingStoreGdiInterop->ReleaseDC(nullptr);
1360 #endif
1361
1362     m_paintCount--;
1363
1364     if (active())
1365         cancelDeleteBackingStoreSoon();
1366     else
1367         deleteBackingStoreSoon();
1368 }
1369
1370 void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, const IntRect& dirtyRectPixels, WindowsToPaint windowsToPaint)
1371 {
1372     // FIXME: This function should never be called in accelerated compositing mode, and we should
1373     // assert as such. But currently it *is* sometimes called, so we can't assert yet. See
1374     // <http://webkit.org/b/58539>.
1375
1376     LOCAL_GDI_COUNTER(0, __FUNCTION__);
1377
1378     // FIXME: We want an assert here saying that the dirtyRect is inside the clienRect,
1379     // but it was being hit during our layout tests, and is being investigated in
1380     // http://webkit.org/b/29350.
1381
1382     RECT rect = dirtyRectPixels;
1383
1384 #if FLASH_BACKING_STORE_REDRAW
1385     {
1386         HWndDC dc(m_viewWindow);
1387         auto yellowBrush = adoptGDIObject(::CreateSolidBrush(RGB(255, 255, 0)));
1388         FillRect(dc, &rect, yellowBrush.get());
1389         GdiFlush();
1390         Sleep(50);
1391         paintIntoWindow(bitmapDC, dc, dirtyRectPixels);
1392     }
1393 #endif
1394
1395     float scaleFactor = deviceScaleFactor();
1396     float inverseScaleFactor = 1.0f / scaleFactor;
1397
1398     FloatRect logicalDirtyRectFloat = dirtyRectPixels;
1399     logicalDirtyRectFloat.scale(inverseScaleFactor);    
1400     IntRect logicalDirtyRect(enclosingIntRect(logicalDirtyRectFloat));
1401
1402 #if USE(DIRECT2D)
1403     m_backingStoreRenderTarget = nullptr;
1404 #endif
1405
1406     GraphicsContext gc(bitmapDC, m_transparent);
1407     gc.setShouldIncludeChildWindows(windowsToPaint == PaintWebViewAndChildren);
1408     gc.save();
1409     if (m_transparent)
1410         gc.clearRect(logicalDirtyRect);
1411     else
1412         FillRect(bitmapDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
1413
1414     COMPtr<IWebUIDelegatePrivate2> uiPrivate(Query, m_uiDelegate);
1415     if (uiPrivate)
1416         uiPrivate->drawBackground(this, bitmapDC, &rect);
1417
1418     if (frameView && frameView->frame().contentRenderer()) {
1419         gc.save();
1420         gc.scale(FloatSize(scaleFactor, scaleFactor));
1421         gc.clip(logicalDirtyRect);
1422         frameView->paint(gc, logicalDirtyRect);
1423         gc.restore();
1424         if (m_shouldInvertColors)
1425             gc.fillRect(logicalDirtyRect, Color::white, CompositeDifference);
1426     }
1427     gc.restore();
1428 }
1429
1430 void WebView::paintIntoWindow(HDC bitmapDC, HDC windowDC, const IntRect& dirtyRectPixels)
1431 {
1432     // FIXME: This function should never be called in accelerated compositing mode, and we should
1433     // assert as such. But currently it *is* sometimes called, so we can't assert yet. See
1434     // <http://webkit.org/b/58539>.
1435
1436     LOCAL_GDI_COUNTER(0, __FUNCTION__);
1437 #if FLASH_WINDOW_REDRAW
1438     auto greenBrush = adoptGDIObject(::CreateSolidBrush(RGB(0, 255, 0)));
1439     RECT rect = dirtyRectPixels;
1440     FillRect(windowDC, &rect, greenBrush.get());
1441     GdiFlush();
1442     Sleep(50);
1443 #endif
1444
1445     // Blit the dirty rect from the backing store into the same position
1446     // in the destination DC.
1447     BitBlt(windowDC, dirtyRectPixels.x(), dirtyRectPixels.y(), dirtyRectPixels.width(), dirtyRectPixels.height(), bitmapDC,
1448         dirtyRectPixels.x(), dirtyRectPixels.y(), SRCCOPY);
1449
1450     m_needsDisplay = false;
1451 }
1452
1453 void WebView::frameRect(RECT* rect)
1454 {
1455     ::GetWindowRect(m_viewWindow, rect);
1456 }
1457
1458 class WindowCloseTimer final : public WebCore::SuspendableTimer {
1459 public:
1460     static WindowCloseTimer* create(WebView*);
1461
1462 private:
1463     WindowCloseTimer(ScriptExecutionContext&, WebView*);
1464
1465     // ActiveDOMObject API.
1466     void contextDestroyed() override;
1467     const char* activeDOMObjectName() const override { return "WindowCloseTimer"; }
1468
1469     // SuspendableTimer API.
1470     void fired() override;
1471
1472     WebView* m_webView;
1473 };
1474
1475 WindowCloseTimer* WindowCloseTimer::create(WebView* webView)
1476 {
1477     ASSERT_ARG(webView, webView);
1478     Frame* frame = core(webView->topLevelFrame());
1479     ASSERT(frame);
1480     if (!frame)
1481         return nullptr;
1482
1483     Document* document = frame->document();
1484     ASSERT(document);
1485     if (!document)
1486         return nullptr;
1487
1488     auto closeTimer = new WindowCloseTimer(*document, webView);
1489     closeTimer->suspendIfNeeded();
1490     return closeTimer;
1491 }
1492
1493 WindowCloseTimer::WindowCloseTimer(ScriptExecutionContext& context, WebView* webView)
1494     : SuspendableTimer(context)
1495     , m_webView(webView)
1496 {
1497     ASSERT_ARG(webView, webView);
1498 }
1499
1500 void WindowCloseTimer::contextDestroyed()
1501 {
1502     SuspendableTimer::contextDestroyed();
1503     delete this;
1504 }
1505
1506 void WindowCloseTimer::fired()
1507 {
1508     m_webView->closeWindowTimerFired();
1509 }
1510
1511 void WebView::closeWindowSoon()
1512 {
1513     if (m_closeWindowTimer)
1514         return;
1515
1516     m_closeWindowTimer = WindowCloseTimer::create(this);
1517     if (!m_closeWindowTimer)
1518         return;
1519     m_closeWindowTimer->startOneShot(0);
1520
1521     AddRef();
1522 }
1523
1524 void WebView::closeWindowTimerFired()
1525 {
1526     closeWindow();
1527     Release();
1528 }
1529
1530 void WebView::closeWindow()
1531 {
1532     if (m_hasSpellCheckerDocumentTag) {
1533         if (m_editingDelegate)
1534             m_editingDelegate->closeSpellDocument(this);
1535         m_hasSpellCheckerDocumentTag = false;
1536     }
1537
1538     COMPtr<IWebUIDelegate> ui;
1539     if (SUCCEEDED(uiDelegate(&ui)))
1540         ui->webViewClose(this);
1541 }
1542
1543 bool WebView::canHandleRequest(const WebCore::ResourceRequest& request)
1544 {
1545 #if USE(CFURLCONNECTION)
1546     // On the Mac there's an about URL protocol implementation but Windows CFNetwork doesn't have that.
1547     if (request.url().protocolIs("about"))
1548         return true;
1549
1550     return CFURLProtocolCanHandleRequest(request.cfURLRequest(UpdateHTTPBody));
1551 #else
1552     return true;
1553 #endif
1554 }
1555
1556 String WebView::standardUserAgentWithApplicationName(const String& applicationName)
1557 {
1558     DEPRECATED_DEFINE_STATIC_LOCAL(String, osVersion, (windowsVersionForUAString()));
1559     DEPRECATED_DEFINE_STATIC_LOCAL(String, webKitVersion, (webKitVersionString()));
1560
1561     return makeString("Mozilla/5.0 (", osVersion, ") AppleWebKit/", webKitVersion, " (KHTML, like Gecko)", applicationName.isEmpty() ? "" : " ", applicationName);
1562 }
1563
1564 Page* WebView::page()
1565 {
1566     return m_page;
1567 }
1568
1569 static HMENU createContextMenuFromItems(const Vector<ContextMenuItem>& items)
1570 {
1571     HMENU menu = ::CreatePopupMenu();
1572
1573     for (auto& item : items) {
1574         UINT flags = 0;
1575
1576         flags |= item.enabled() ? MF_ENABLED : MF_DISABLED;
1577         flags |= item.checked() ? MF_CHECKED : MF_UNCHECKED;
1578
1579         switch (item.type()) {
1580         case ActionType:
1581         case CheckableActionType:
1582             ::AppendMenu(menu, flags | MF_STRING, item.action(), item.title().charactersWithNullTermination().data());
1583             break;
1584         case SeparatorType:
1585             ::AppendMenu(menu, flags | MF_SEPARATOR, item.action(), nullptr);
1586             break;
1587         case SubmenuType:
1588             ::AppendMenu(menu, flags | MF_POPUP, (UINT_PTR)createContextMenuFromItems(item.subMenuItems()), item.title().charactersWithNullTermination().data());
1589             break;
1590         }
1591     }
1592
1593     return menu;
1594 }
1595
1596 HMENU WebView::createContextMenu()
1597 {
1598     auto& contextMenuController = m_page->contextMenuController();
1599
1600     ContextMenu* coreMenu = contextMenuController.contextMenu();
1601     if (!coreMenu)
1602         return nullptr;
1603
1604     HMENU contextMenu = createContextMenuFromItems(coreMenu->items());
1605
1606     COMPtr<IWebUIDelegate> uiDelegate;
1607     if (SUCCEEDED(this->uiDelegate(&uiDelegate))) {
1608         ASSERT(uiDelegate);
1609
1610         COMPtr<WebElementPropertyBag> propertyBag;
1611         propertyBag.adoptRef(WebElementPropertyBag::createInstance(contextMenuController.hitTestResult()));
1612
1613         HMENU newMenu = nullptr;
1614         if (SUCCEEDED(uiDelegate->contextMenuItemsForElement(this, propertyBag.get(), contextMenu, &newMenu))) {
1615             // Make sure to delete the old menu if the delegate returned a new menu.
1616             if (newMenu != contextMenu) {
1617                 ::DestroyMenu(contextMenu);
1618                 contextMenu = newMenu;
1619             }
1620         }
1621     }
1622
1623     return contextMenu;
1624 }
1625
1626 bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam)
1627 {
1628     // Translate the screen coordinates into window coordinates
1629     POINT coords = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1630     if (coords.x == -1 || coords.y == -1) {
1631         // The contextMenuController() holds onto the last context menu that was popped up on the
1632         // page until a new one is created. We need to clear this menu before propagating the event
1633         // through the DOM so that we can detect if we create a new menu for this event, since we
1634         // won't create a new menu if the DOM swallows the event and the defaultEventHandler does
1635         // not run.
1636         m_page->contextMenuController().clearContextMenu();
1637
1638         Frame& focusedFrame = m_page->focusController().focusedOrMainFrame();
1639         return focusedFrame.eventHandler().sendContextMenuEventForKey();
1640
1641     } else {
1642         if (!::ScreenToClient(m_viewWindow, &coords))
1643             return false;
1644     }
1645
1646     lParam = MAKELPARAM(coords.x, coords.y);
1647
1648     // Convert coordinates to logical pixels
1649     float scaleFactor = deviceScaleFactor();
1650     float inverseScaleFactor = 1.0f / scaleFactor;
1651     IntPoint logicalCoords(coords);
1652     logicalCoords.scale(inverseScaleFactor, inverseScaleFactor);
1653
1654     m_page->contextMenuController().clearContextMenu();
1655
1656     IntPoint documentPoint(m_page->mainFrame().view()->windowToContents(logicalCoords));
1657     HitTestResult result = m_page->mainFrame().eventHandler().hitTestResultAtPoint(documentPoint);
1658     Frame* targetFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document().frame() : &m_page->focusController().focusedOrMainFrame();
1659
1660     targetFrame->view()->setCursor(pointerCursor());
1661     PlatformMouseEvent mouseEvent(m_viewWindow, WM_RBUTTONUP, wParam, lParam);
1662     bool handledEvent = targetFrame->eventHandler().sendContextMenuEvent(mouseEvent);
1663     if (!handledEvent)
1664         return false;
1665
1666     ContextMenuController& contextMenuController = m_page->contextMenuController();
1667
1668     // Show the menu
1669     ContextMenu* coreMenu = contextMenuController.contextMenu();
1670     if (!coreMenu)
1671         return false;
1672
1673     Frame* frame = contextMenuController.hitTestResult().innerNodeFrame();
1674     if (!frame)
1675         return false;
1676
1677     FrameView* view = frame->view();
1678     if (!view)
1679         return false;
1680
1681     IntPoint logicalPoint = view->contentsToWindow(contextMenuController.hitTestResult().roundedPointInInnerNodeFrame());
1682     logicalPoint.scale(scaleFactor, scaleFactor);
1683
1684     // Translate the point to screen coordinates
1685     POINT point = logicalPoint;
1686     if (!::ClientToScreen(m_viewWindow, &point))
1687         return false;
1688
1689     if (m_currentContextMenu)
1690         ::DestroyMenu(m_currentContextMenu);
1691     m_currentContextMenu = createContextMenu();
1692
1693     MENUINFO menuInfo;
1694     menuInfo.cbSize = sizeof(menuInfo);
1695     menuInfo.fMask = MIM_STYLE;
1696     menuInfo.dwStyle = MNS_NOTIFYBYPOS;
1697     ::SetMenuInfo(m_currentContextMenu, &menuInfo);
1698
1699     BOOL hasCustomMenus = false;
1700     if (m_uiDelegate)
1701         m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1702
1703     if (hasCustomMenus)
1704         m_uiDelegate->trackCustomPopupMenu((IWebView*)this, m_currentContextMenu, &point);
1705     else {
1706         // Surprisingly, TPM_RIGHTBUTTON means that items are selectable with either the right OR left mouse button
1707         UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL | TPM_LEFTALIGN | TPM_HORPOSANIMATION;
1708         ::TrackPopupMenuEx(m_currentContextMenu, flags, point.x, point.y, m_viewWindow, 0);
1709     }
1710
1711     return true;
1712 }
1713
1714 bool WebView::onMeasureItem(WPARAM /*wParam*/, LPARAM lParam)
1715 {
1716     if (!m_uiDelegate)
1717         return false;
1718
1719     BOOL hasCustomMenus = false;
1720     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1721     if (!hasCustomMenus)
1722         return false;
1723
1724     m_uiDelegate->measureCustomMenuItem((IWebView*)this, (void*)lParam);
1725     return true;
1726 }
1727
1728 bool WebView::onDrawItem(WPARAM /*wParam*/, LPARAM lParam)
1729 {
1730     if (!m_uiDelegate)
1731         return false;
1732
1733     BOOL hasCustomMenus = false;
1734     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1735     if (!hasCustomMenus)
1736         return false;
1737
1738     m_uiDelegate->drawCustomMenuItem((IWebView*)this, (void*)lParam);
1739     return true;
1740 }
1741
1742 bool WebView::onInitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
1743 {
1744     if (!m_uiDelegate)
1745         return false;
1746
1747     HMENU menu = (HMENU)wParam;
1748     if (!menu)
1749         return false;
1750
1751     BOOL hasCustomMenus = false;
1752     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1753     if (!hasCustomMenus)
1754         return false;
1755
1756     m_uiDelegate->addCustomMenuDrawingData((IWebView*)this, menu);
1757     return true;
1758 }
1759
1760 bool WebView::onUninitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
1761 {
1762     if (!m_uiDelegate)
1763         return false;
1764
1765     HMENU menu = (HMENU)wParam;
1766     if (!menu)
1767         return false;
1768
1769     BOOL hasCustomMenus = false;
1770     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1771     if (!hasCustomMenus)
1772         return false;
1773
1774     m_uiDelegate->cleanUpCustomMenuDrawingData((IWebView*)this, menu);
1775     return true;
1776 }
1777
1778 void WebView::onMenuCommand(WPARAM wParam, LPARAM lParam)
1779 {
1780     HMENU hMenu = reinterpret_cast<HMENU>(lParam);
1781     unsigned index = static_cast<unsigned>(wParam);
1782
1783     MENUITEMINFO menuItemInfo = { 0 };
1784     menuItemInfo.cbSize = sizeof(menuItemInfo);
1785     menuItemInfo.fMask = MIIM_STRING;
1786     ::GetMenuItemInfo(hMenu, index, true, &menuItemInfo);
1787
1788     auto buffer = std::make_unique<WCHAR[]>(menuItemInfo.cch + 1);
1789     menuItemInfo.dwTypeData = buffer.get();
1790     menuItemInfo.cch++;
1791     menuItemInfo.fMask |= MIIM_ID;
1792
1793     ::GetMenuItemInfo(hMenu, index, true, &menuItemInfo);
1794
1795     ::DestroyMenu(m_currentContextMenu);
1796     m_currentContextMenu = nullptr;
1797
1798     String title(buffer.get(), menuItemInfo.cch);
1799     ContextMenuAction action = static_cast<ContextMenuAction>(menuItemInfo.wID);
1800
1801     if (action >= ContextMenuItemBaseApplicationTag) {
1802         if (m_uiDelegate) {
1803             COMPtr<WebElementPropertyBag> propertyBag;
1804             propertyBag.adoptRef(WebElementPropertyBag::createInstance(m_page->contextMenuController().hitTestResult()));
1805
1806             m_uiDelegate->contextMenuItemSelected(this, &menuItemInfo, propertyBag.get());
1807         }
1808         return;
1809     }
1810
1811     m_page->contextMenuController().contextMenuItemSelected(action, title);
1812 }
1813
1814 bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam)
1815 {
1816     static LONG globalClickCount;
1817     static IntPoint globalPrevPoint;
1818     static MouseButton globalPrevButton;
1819     static LONG globalPrevMouseDownTime;
1820
1821     if (message == WM_CANCELMODE) {
1822         m_page->mainFrame().eventHandler().lostMouseCapture();
1823         return true;
1824     }
1825
1826     // Create our event.
1827     // On WM_MOUSELEAVE we need to create a mouseout event, so we force the position
1828     // of the event to be at (MINSHORT, MINSHORT).
1829     LPARAM position = (message == WM_MOUSELEAVE) ? ((MINSHORT << 16) | MINSHORT) : lParam;
1830     PlatformMouseEvent mouseEvent(m_viewWindow, message, wParam, position, m_mouseActivated);
1831
1832     setMouseActivated(false);
1833
1834     bool insideThreshold = abs(globalPrevPoint.x() - mouseEvent.position().x()) < ::GetSystemMetrics(SM_CXDOUBLECLK) &&
1835                            abs(globalPrevPoint.y() - mouseEvent.position().y()) < ::GetSystemMetrics(SM_CYDOUBLECLK);
1836     LONG messageTime = ::GetMessageTime();
1837
1838     bool handled = false;
1839
1840     if (message == WM_LBUTTONDOWN || message == WM_MBUTTONDOWN || message == WM_RBUTTONDOWN) {
1841         // FIXME: I'm not sure if this is the "right" way to do this
1842         // but without this call, we never become focused since we don't allow
1843         // the default handling of mouse events.
1844         SetFocus(m_viewWindow);
1845
1846         // Always start capturing events when the mouse goes down in our HWND.
1847         ::SetCapture(m_viewWindow);
1848
1849         if (((messageTime - globalPrevMouseDownTime) < (LONG)::GetDoubleClickTime()) && 
1850             insideThreshold &&
1851             mouseEvent.button() == globalPrevButton)
1852             globalClickCount++;
1853         else
1854             // Reset the click count.
1855             globalClickCount = 1;
1856         globalPrevMouseDownTime = messageTime;
1857         globalPrevButton = mouseEvent.button();
1858         globalPrevPoint = mouseEvent.position();
1859         
1860         mouseEvent.setClickCount(globalClickCount);
1861         handled = m_page->mainFrame().eventHandler().handleMousePressEvent(mouseEvent);
1862     } else if (message == WM_LBUTTONDBLCLK || message == WM_MBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) {
1863         globalClickCount++;
1864         mouseEvent.setClickCount(globalClickCount);
1865         handled = m_page->mainFrame().eventHandler().handleMousePressEvent(mouseEvent);
1866     } else if (message == WM_LBUTTONUP || message == WM_MBUTTONUP || message == WM_RBUTTONUP) {
1867         // Record the global position and the button of the up.
1868         globalPrevButton = mouseEvent.button();
1869         globalPrevPoint = mouseEvent.position();
1870         mouseEvent.setClickCount(globalClickCount);
1871         m_page->mainFrame().eventHandler().handleMouseReleaseEvent(mouseEvent);
1872         ::ReleaseCapture();
1873     } else if (message == WM_MOUSELEAVE && m_mouseOutTracker) {
1874         // Once WM_MOUSELEAVE is fired windows clears this tracker
1875         // so there is no need to disable it ourselves.
1876         m_mouseOutTracker.reset();
1877         m_page->mainFrame().eventHandler().mouseMoved(mouseEvent);
1878         handled = true;
1879     } else if (message == WM_MOUSEMOVE) {
1880         if (!insideThreshold)
1881             globalClickCount = 0;
1882         mouseEvent.setClickCount(globalClickCount);
1883         handled = m_page->mainFrame().eventHandler().mouseMoved(mouseEvent);
1884         if (!m_mouseOutTracker) {
1885             m_mouseOutTracker = std::make_unique<TRACKMOUSEEVENT>();
1886             m_mouseOutTracker->cbSize = sizeof(TRACKMOUSEEVENT);
1887             m_mouseOutTracker->dwFlags = TME_LEAVE;
1888             m_mouseOutTracker->hwndTrack = m_viewWindow;
1889             ::TrackMouseEvent(m_mouseOutTracker.get());
1890         }
1891     }
1892     return handled;
1893 }
1894
1895 bool WebView::gestureNotify(WPARAM wParam, LPARAM lParam)
1896 {
1897     GESTURENOTIFYSTRUCT* gn = reinterpret_cast<GESTURENOTIFYSTRUCT*>(lParam);
1898
1899     Frame* coreFrame = core(m_mainFrame);
1900     if (!coreFrame)
1901         return false;
1902
1903     ScrollView* view = coreFrame->view();
1904     if (!view)
1905         return false;
1906
1907     // If we don't have this function, we shouldn't be receiving this message
1908     ASSERT(SetGestureConfigPtr());
1909
1910     bool hitScrollbar = false;
1911     POINT gestureBeginPoint = {gn->ptsLocation.x, gn->ptsLocation.y};
1912
1913     float scaleFactor = deviceScaleFactor();
1914     float inverseScaleFactor = 1.0f / scaleFactor;
1915     IntPoint logicalGestureBeginPoint(gestureBeginPoint);
1916     logicalGestureBeginPoint.scale(inverseScaleFactor, inverseScaleFactor);
1917
1918     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowUserAgentShadowContent);
1919     for (Frame* childFrame = &m_page->mainFrame(); childFrame; childFrame = EventHandler::subframeForTargetNode(m_gestureTargetNode.get())) {
1920         FrameView* frameView = childFrame->view();
1921         if (!frameView)
1922             break;
1923         RenderView* renderView = childFrame->document()->renderView();
1924         if (!renderView)
1925             break;
1926         RenderLayer* layer = renderView->layer();
1927         if (!layer)
1928             break;
1929
1930         HitTestResult result(frameView->screenToContents(logicalGestureBeginPoint));
1931         layer->hitTest(request, result);
1932         m_gestureTargetNode = result.innerNode();
1933
1934         if (!hitScrollbar)
1935             hitScrollbar = result.scrollbar();
1936     }
1937
1938     if (!hitScrollbar) {
1939         // The hit testing above won't detect if we've hit the main frame's vertical scrollbar. Check that manually now.
1940         RECT webViewRect;
1941         GetWindowRect(m_viewWindow, &webViewRect);
1942         hitScrollbar = (view->verticalScrollbar() && (gestureBeginPoint.x > (webViewRect.right - view->verticalScrollbar()->theme().scrollbarThickness()))) 
1943             || (view->horizontalScrollbar() && (gestureBeginPoint.y > (webViewRect.bottom - view->horizontalScrollbar()->theme().scrollbarThickness())));  
1944     }
1945
1946     bool canBeScrolled = false;
1947     if (m_gestureTargetNode) {
1948         for (RenderObject* renderer = m_gestureTargetNode->renderer(); renderer; renderer = renderer->parent()) {
1949             if (is<RenderBox>(*renderer) && downcast<RenderBox>(*renderer).canBeScrolledAndHasScrollableArea()) {
1950                 canBeScrolled = true;
1951                 break;
1952             }
1953         }
1954     } else {
1955         // We've hit the main document but not any of the document's content
1956         if (core(m_mainFrame)->view()->isScrollable())
1957             canBeScrolled = true;
1958     }
1959
1960     // We always allow two-fingered panning with inertia and a gutter (which limits movement to one
1961     // direction in most cases).
1962     DWORD dwPanWant = GC_PAN | GC_PAN_WITH_INERTIA | GC_PAN_WITH_GUTTER;
1963     DWORD dwPanBlock = 0;
1964
1965     if (hitScrollbar || !canBeScrolled) {
1966         // The part of the page under the gesture can't be scrolled, or the gesture is on a scrollbar.
1967         // Disallow single-fingered panning in this case so we'll fall back to the default
1968         // behavior (which allows the scrollbar thumb to be dragged, text selections to be made, etc.).
1969         dwPanBlock = GC_PAN_WITH_SINGLE_FINGER_VERTICALLY | GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
1970     } else {
1971         // The part of the page the gesture is under can be scrolled, and we're not under a scrollbar.
1972         // Allow single-fingered vertical panning in this case, so the user will be able to pan the page
1973         // with one or two fingers.
1974         dwPanWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
1975
1976         // Disable single-fingered horizontal panning only if the target node is text.
1977         if (m_gestureTargetNode && m_gestureTargetNode->isTextNode())
1978             dwPanBlock = GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
1979         else
1980             dwPanWant |= GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
1981     }
1982
1983     GESTURECONFIG gc = { GID_PAN, dwPanWant, dwPanBlock };
1984     return SetGestureConfigPtr()(m_viewWindow, 0, 1, &gc, sizeof(GESTURECONFIG));
1985 }
1986
1987 bool WebView::gesture(WPARAM wParam, LPARAM lParam) 
1988 {
1989     // We want to bail out if we don't have either of these functions
1990     if (!GetGestureInfoPtr() || !CloseGestureInfoHandlePtr())
1991         return false;
1992
1993     HGESTUREINFO gestureHandle = reinterpret_cast<HGESTUREINFO>(lParam);
1994     
1995     GESTUREINFO gi = {0};
1996     gi.cbSize = sizeof(GESTUREINFO);
1997
1998     if (!GetGestureInfoPtr()(gestureHandle, reinterpret_cast<PGESTUREINFO>(&gi)))
1999         return false;
2000
2001     switch (gi.dwID) {
2002     case GID_BEGIN:
2003         m_lastPanX = gi.ptsLocation.x;
2004         m_lastPanY = gi.ptsLocation.y;
2005
2006         break;
2007     case GID_END:
2008         m_gestureTargetNode = nullptr;
2009         break;
2010     case GID_PAN: {
2011         if (gi.dwFlags & GF_BEGIN) {
2012             m_lastPanX = gi.ptsLocation.x;
2013             m_lastPanY = gi.ptsLocation.y;
2014         }
2015         // Where are the fingers currently?
2016         long currentX = gi.ptsLocation.x;
2017         long currentY = gi.ptsLocation.y;
2018         // How far did we pan in each direction?
2019         long deltaX = currentX - m_lastPanX;
2020         long deltaY = currentY - m_lastPanY;
2021         // Calculate the overpan for window bounce
2022         m_yOverpan -= m_lastPanY - currentY;
2023         m_xOverpan -= m_lastPanX - currentX;
2024         // Update our class variables with updated values
2025         m_lastPanX = currentX;
2026         m_lastPanY = currentY;
2027
2028         Frame* coreFrame = core(m_mainFrame);
2029         if (!coreFrame) {
2030             CloseGestureInfoHandlePtr()(gestureHandle);
2031             return false;
2032         }
2033
2034         ScrollableArea* scrolledArea = 0;
2035         float scaleFactor = deviceScaleFactor();
2036         IntSize logicalScrollDelta(-deltaX * scaleFactor, -deltaY * scaleFactor);
2037
2038         RenderLayer* scrollableLayer = nullptr;
2039         if (m_gestureTargetNode && m_gestureTargetNode->renderer() && m_gestureTargetNode->renderer()->enclosingLayer())
2040             scrollableLayer = m_gestureTargetNode->renderer()->enclosingLayer()->enclosingScrollableLayer();
2041
2042         if (!scrollableLayer) {
2043             // We might directly hit the document without hitting any nodes
2044             coreFrame->view()->scrollBy(logicalScrollDelta);
2045             scrolledArea = coreFrame->view();
2046         } else
2047             scrollableLayer->scrollByRecursively(logicalScrollDelta, WebCore::RenderLayer::ScrollOffsetClamped, &scrolledArea);
2048
2049         if (!(UpdatePanningFeedbackPtr() && BeginPanningFeedbackPtr() && EndPanningFeedbackPtr())) {
2050             CloseGestureInfoHandlePtr()(gestureHandle);
2051             return true;
2052         }
2053
2054         // Handle overpanning
2055         if (gi.dwFlags & GF_BEGIN) {
2056             BeginPanningFeedbackPtr()(m_viewWindow);
2057             m_yOverpan = 0;
2058             m_xOverpan = 0;
2059         } else if (gi.dwFlags & GF_END) {
2060             EndPanningFeedbackPtr()(m_viewWindow, true);
2061             m_yOverpan = 0;
2062             m_xOverpan = 0;
2063         }
2064
2065         if (!scrolledArea) {
2066             CloseGestureInfoHandlePtr()(gestureHandle);
2067             return true;
2068         }
2069
2070         Scrollbar* vertScrollbar = scrolledArea->verticalScrollbar();
2071
2072         int ypan = 0;
2073         int xpan = 0;
2074
2075         if (vertScrollbar && (!vertScrollbar->currentPos() || vertScrollbar->currentPos() >= vertScrollbar->maximum()))
2076             ypan = m_yOverpan;
2077
2078         Scrollbar* horiScrollbar = scrolledArea->horizontalScrollbar();
2079
2080         if (horiScrollbar && (!horiScrollbar->currentPos() || horiScrollbar->currentPos() >= horiScrollbar->maximum()))
2081             xpan = m_xOverpan;
2082
2083         UpdatePanningFeedbackPtr()(m_viewWindow, xpan, ypan, gi.dwFlags & GF_INERTIA);
2084
2085         CloseGestureInfoHandlePtr()(gestureHandle);
2086         return true;
2087     }
2088     default:
2089         break;
2090     }
2091
2092     // If we get to this point, the gesture has not been handled. We forward
2093     // the call to DefWindowProc by returning false, and we don't need to 
2094     // to call CloseGestureInfoHandle. 
2095     // http://msdn.microsoft.com/en-us/library/dd353228(VS.85).aspx
2096     return false;
2097 }
2098
2099 bool WebView::mouseWheel(WPARAM wParam, LPARAM lParam, bool isMouseHWheel)
2100 {
2101     // Ctrl+Mouse wheel doesn't ever go into WebCore.  It is used to
2102     // zoom instead (Mac zooms the whole Desktop, but Windows browsers trigger their
2103     // own local zoom modes for Ctrl+wheel).
2104     if (wParam & MK_CONTROL) {
2105         short delta = short(HIWORD(wParam));
2106         if (delta < 0)
2107             makeTextSmaller(0);
2108         else
2109             makeTextLarger(0);
2110         return true;
2111     }
2112     
2113     // 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.
2114     HWND focusedWindow = GetFocus();
2115     if (focusedWindow && focusedWindow != m_viewWindow) {
2116         // 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).
2117         WCHAR className[256];
2118
2119         // Make sure truncation won't affect the comparison.
2120         ASSERT(WTF_ARRAY_LENGTH(className) > wcslen(PopupMenuWin::popupClassName()));
2121
2122         if (GetClassNameW(focusedWindow, className, WTF_ARRAY_LENGTH(className)) && !wcscmp(className, PopupMenuWin::popupClassName())) {
2123             // We don't let the WebView scroll here for two reasons - 1) To match Firefox behavior, 2) If we do scroll, we lose the
2124             // focus ring around the select menu.
2125             SetFocus(m_viewWindow);
2126             return true;
2127         }
2128     }
2129
2130     PlatformWheelEvent wheelEvent(m_viewWindow, wParam, lParam, isMouseHWheel);
2131     Frame* coreFrame = core(m_mainFrame);
2132     if (!coreFrame)
2133         return false;
2134
2135     return coreFrame->eventHandler().handleWheelEvent(wheelEvent);
2136 }
2137
2138 bool WebView::verticalScroll(WPARAM wParam, LPARAM /*lParam*/)
2139 {
2140     ScrollDirection direction;
2141     ScrollGranularity granularity;
2142     switch (LOWORD(wParam)) {
2143     case SB_LINEDOWN:
2144         granularity = ScrollByLine;
2145         direction = ScrollDown;
2146         break;
2147     case SB_LINEUP:
2148         granularity = ScrollByLine;
2149         direction = ScrollUp;
2150         break;
2151     case SB_PAGEDOWN:
2152         granularity = ScrollByDocument;
2153         direction = ScrollDown;
2154         break;
2155     case SB_PAGEUP:
2156         granularity = ScrollByDocument;
2157         direction = ScrollUp;
2158         break;
2159     default:
2160         return false;
2161         break;
2162     }
2163     
2164     Frame& frame = m_page->focusController().focusedOrMainFrame();
2165     return frame.eventHandler().scrollRecursively(direction, granularity);
2166 }
2167
2168 bool WebView::horizontalScroll(WPARAM wParam, LPARAM /*lParam*/)
2169 {
2170     ScrollDirection direction;
2171     ScrollGranularity granularity;
2172     switch (LOWORD(wParam)) {
2173     case SB_LINELEFT:
2174         granularity = ScrollByLine;
2175         direction = ScrollLeft;
2176         break;
2177     case SB_LINERIGHT:
2178         granularity = ScrollByLine;
2179         direction = ScrollRight;
2180         break;
2181     case SB_PAGELEFT:
2182         granularity = ScrollByDocument;
2183         direction = ScrollLeft;
2184         break;
2185     case SB_PAGERIGHT:
2186         granularity = ScrollByDocument;
2187         direction = ScrollRight;
2188         break;
2189     default:
2190         return false;
2191     }
2192
2193     Frame& frame = m_page->focusController().focusedOrMainFrame();
2194     return frame.eventHandler().scrollRecursively(direction, granularity);
2195 }
2196
2197
2198 bool WebView::execCommand(WPARAM wParam, LPARAM /*lParam*/)
2199 {
2200     Frame& frame = m_page->focusController().focusedOrMainFrame();
2201     switch (LOWORD(wParam)) {
2202         case SelectAll:
2203             return frame.editor().command("SelectAll").execute();
2204         case Undo:
2205             return frame.editor().command("Undo").execute();
2206         case Redo:
2207             return frame.editor().command("Redo").execute();
2208     }
2209     return false;
2210 }
2211
2212 bool WebView::keyUp(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
2213 {
2214     PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformEvent::KeyUp, systemKeyDown);
2215
2216     Frame& frame = m_page->focusController().focusedOrMainFrame();
2217     m_currentCharacterCode = 0;
2218
2219     return frame.eventHandler().keyEvent(keyEvent);
2220 }
2221
2222 static const unsigned CtrlKey = 1 << 0;
2223 static const unsigned AltKey = 1 << 1;
2224 static const unsigned ShiftKey = 1 << 2;
2225
2226
2227 struct KeyDownEntry {
2228     unsigned virtualKey;
2229     unsigned modifiers;
2230     const char* name;
2231 };
2232
2233 struct KeyPressEntry {
2234     unsigned charCode;
2235     unsigned modifiers;
2236     const char* name;
2237 };
2238
2239 static const KeyDownEntry keyDownEntries[] = {
2240     { VK_LEFT,   0,                  "MoveLeft"                                    },
2241     { VK_LEFT,   ShiftKey,           "MoveLeftAndModifySelection"                  },
2242     { VK_LEFT,   CtrlKey,            "MoveWordLeft"                                },
2243     { VK_LEFT,   CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection"              },
2244     { VK_RIGHT,  0,                  "MoveRight"                                   },
2245     { VK_RIGHT,  ShiftKey,           "MoveRightAndModifySelection"                 },
2246     { VK_RIGHT,  CtrlKey,            "MoveWordRight"                               },
2247     { VK_RIGHT,  CtrlKey | ShiftKey, "MoveWordRightAndModifySelection"             },
2248     { VK_UP,     0,                  "MoveUp"                                      },
2249     { VK_UP,     ShiftKey,           "MoveUpAndModifySelection"                    },
2250     { VK_PRIOR,  ShiftKey,           "MovePageUpAndModifySelection"                },
2251     { VK_DOWN,   0,                  "MoveDown"                                    },
2252     { VK_DOWN,   ShiftKey,           "MoveDownAndModifySelection"                  },
2253     { VK_NEXT,   ShiftKey,           "MovePageDownAndModifySelection"              },
2254     { VK_PRIOR,  0,                  "MovePageUp"                                  },
2255     { VK_NEXT,   0,                  "MovePageDown"                                },
2256     { VK_HOME,   0,                  "MoveToBeginningOfLine"                       },
2257     { VK_HOME,   ShiftKey,           "MoveToBeginningOfLineAndModifySelection"     },
2258     { VK_HOME,   CtrlKey,            "MoveToBeginningOfDocument"                   },
2259     { VK_HOME,   CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
2260
2261     { VK_END,    0,                  "MoveToEndOfLine"                             },
2262     { VK_END,    ShiftKey,           "MoveToEndOfLineAndModifySelection"           },
2263     { VK_END,    CtrlKey,            "MoveToEndOfDocument"                         },
2264     { VK_END,    CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection"       },
2265
2266     { VK_BACK,   0,                  "DeleteBackward"                              },
2267     { VK_BACK,   ShiftKey,           "DeleteBackward"                              },
2268     { VK_DELETE, 0,                  "DeleteForward"                               },
2269     { VK_BACK,   CtrlKey,            "DeleteWordBackward"                          },
2270     { VK_DELETE, CtrlKey,            "DeleteWordForward"                           },
2271     
2272     { 'B',       CtrlKey,            "ToggleBold"                                  },
2273     { 'I',       CtrlKey,            "ToggleItalic"                                },
2274
2275     { VK_ESCAPE, 0,                  "Cancel"                                      },
2276     { VK_OEM_PERIOD, CtrlKey,        "Cancel"                                      },
2277     { VK_TAB,    0,                  "InsertTab"                                   },
2278     { VK_TAB,    ShiftKey,           "InsertBacktab"                               },
2279     { VK_RETURN, 0,                  "InsertNewline"                               },
2280     { VK_RETURN, CtrlKey,            "InsertNewline"                               },
2281     { VK_RETURN, AltKey,             "InsertNewline"                               },
2282     { VK_RETURN, ShiftKey,           "InsertNewline"                               },
2283     { VK_RETURN, AltKey | ShiftKey,  "InsertNewline"                               },
2284
2285     // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled
2286     // in the application or in WebKit. We chose WebKit.
2287     { 'C',       CtrlKey,            "Copy"                                        },
2288     { 'V',       CtrlKey,            "Paste"                                       },
2289     { 'X',       CtrlKey,            "Cut"                                         },
2290     { 'A',       CtrlKey,            "SelectAll"                                   },
2291     { VK_INSERT, CtrlKey,            "Copy"                                        },
2292     { VK_DELETE, ShiftKey,           "Cut"                                         },
2293     { VK_INSERT, ShiftKey,           "Paste"                                       },
2294     { 'Z',       CtrlKey,            "Undo"                                        },
2295     { 'Z',       CtrlKey | ShiftKey, "Redo"                                        },
2296 };
2297
2298 static const KeyPressEntry keyPressEntries[] = {
2299     { '\t',   0,                  "InsertTab"                                   },
2300     { '\t',   ShiftKey,           "InsertBacktab"                               },
2301     { '\r',   0,                  "InsertNewline"                               },
2302     { '\r',   CtrlKey,            "InsertNewline"                               },
2303     { '\r',   AltKey,             "InsertNewline"                               },
2304     { '\r',   ShiftKey,           "InsertNewline"                               },
2305     { '\r',   AltKey | ShiftKey,  "InsertNewline"                               },
2306 };
2307
2308 const char* WebView::interpretKeyEvent(const KeyboardEvent* evt)
2309 {
2310     ASSERT(evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
2311
2312     static HashMap<int, const char*>* keyDownCommandsMap = 0;
2313     static HashMap<int, const char*>* keyPressCommandsMap = 0;
2314
2315     if (!keyDownCommandsMap) {
2316         keyDownCommandsMap = new HashMap<int, const char*>;
2317         keyPressCommandsMap = new HashMap<int, const char*>;
2318
2319         for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyDownEntries); ++i)
2320             keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
2321
2322         for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyPressEntries); ++i)
2323             keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
2324     }
2325
2326     unsigned modifiers = 0;
2327     if (evt->shiftKey())
2328         modifiers |= ShiftKey;
2329     if (evt->altKey())
2330         modifiers |= AltKey;
2331     if (evt->ctrlKey())
2332         modifiers |= CtrlKey;
2333
2334     if (evt->type() == eventNames().keydownEvent) {
2335         int mapKey = modifiers << 16 | evt->keyCode();
2336         return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
2337     }
2338
2339     int mapKey = modifiers << 16 | evt->charCode();
2340     return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
2341 }
2342
2343 bool WebView::handleEditingKeyboardEvent(KeyboardEvent* evt)
2344 {
2345     Node* node = evt->target()->toNode();
2346     ASSERT(node);
2347     Frame* frame = node->document().frame();
2348     ASSERT(frame);
2349
2350     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
2351     if (!keyEvent || keyEvent->isSystemKey())  // do not treat this as text input if it's a system key event
2352         return false;
2353
2354     Editor::Command command = frame->editor().command(interpretKeyEvent(evt));
2355
2356     if (keyEvent->type() == PlatformEvent::RawKeyDown) {
2357         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
2358         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
2359         // (e.g. Tab that inserts a Tab character, or Enter).
2360         return !command.isTextInsertion() && command.execute(evt);
2361     }
2362
2363      if (command.execute(evt))
2364         return true;
2365
2366     // Don't insert null or control characters as they can result in unexpected behaviour
2367     if (evt->charCode() < ' ')
2368         return false;
2369
2370     return frame->editor().insertText(evt->keyEvent()->text(), evt);
2371 }
2372
2373 bool WebView::keyDown(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
2374 {
2375 #if ENABLE(FULLSCREEN_API)
2376     // Trap the ESC key when in full screen mode.
2377     if (virtualKeyCode == VK_ESCAPE && isFullScreen()) {
2378         m_fullscreenController->exitFullScreen();
2379         return false;
2380     }
2381 #endif
2382     Frame& frame = m_page->focusController().focusedOrMainFrame();
2383
2384     PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformEvent::RawKeyDown, systemKeyDown);
2385     bool handled = frame.eventHandler().keyEvent(keyEvent);
2386
2387     // These events cannot be canceled, and we have no default handling for them.
2388     // FIXME: match IE list more closely, see <http://msdn2.microsoft.com/en-us/library/ms536938.aspx>.
2389     if (systemKeyDown && virtualKeyCode != VK_RETURN)
2390         return false;
2391
2392     if (handled) {
2393         // FIXME: remove WM_UNICHAR, too
2394         MSG msg;
2395         // WM_SYSCHAR events should not be removed, because access keys are implemented in WebCore in WM_SYSCHAR handler.
2396         if (!systemKeyDown)
2397             ::PeekMessage(&msg, m_viewWindow, WM_CHAR, WM_CHAR, PM_REMOVE);
2398         return true;
2399     }
2400
2401     // We need to handle back/forward using either Ctrl+Left/Right Arrow keys.
2402     // FIXME: This logic should probably be in EventHandler::defaultArrowEventHandler().
2403     // FIXME: Should check that other modifiers aren't pressed.
2404     if (virtualKeyCode == VK_RIGHT && keyEvent.ctrlKey())
2405         return m_page->backForward().goForward();
2406     if (virtualKeyCode == VK_LEFT && keyEvent.ctrlKey())
2407         return m_page->backForward().goBack();
2408
2409     // Need to scroll the page if the arrow keys, pgup/dn, or home/end are hit.
2410     ScrollDirection direction;
2411     ScrollGranularity granularity;
2412     switch (virtualKeyCode) {
2413         case VK_LEFT:
2414             granularity = ScrollByLine;
2415             direction = ScrollLeft;
2416             break;
2417         case VK_RIGHT:
2418             granularity = ScrollByLine;
2419             direction = ScrollRight;
2420             break;
2421         case VK_UP:
2422             granularity = ScrollByLine;
2423             direction = ScrollUp;
2424             break;
2425         case VK_DOWN:
2426             granularity = ScrollByLine;
2427             direction = ScrollDown;
2428             break;
2429         case VK_HOME:
2430             granularity = ScrollByDocument;
2431             direction = ScrollUp;
2432             break;
2433         case VK_END:
2434             granularity = ScrollByDocument;
2435             direction = ScrollDown;
2436             break;
2437         case VK_PRIOR:
2438             granularity = ScrollByPage;
2439             direction = ScrollUp;
2440             break;
2441         case VK_NEXT:
2442             granularity = ScrollByPage;
2443             direction = ScrollDown;
2444             break;
2445         default:
2446             return false;
2447     }
2448
2449     return frame.eventHandler().scrollRecursively(direction, granularity);
2450 }
2451
2452 bool WebView::keyPress(WPARAM charCode, LPARAM keyData, bool systemKeyDown)
2453 {
2454     Frame& frame = m_page->focusController().focusedOrMainFrame();
2455
2456     PlatformKeyboardEvent keyEvent(m_viewWindow, charCode, keyData, PlatformEvent::Char, systemKeyDown);
2457     // IE does not dispatch keypress event for WM_SYSCHAR.
2458     if (systemKeyDown)
2459         return frame.eventHandler().handleAccessKey(keyEvent);
2460     return frame.eventHandler().keyEvent(keyEvent);
2461 }
2462
2463 void WebView::setIsBeingDestroyed()
2464 {
2465     m_isBeingDestroyed = true;
2466
2467     // Remove our this pointer from the window so we won't try to handle any more window messages.
2468     // See <http://webkit.org/b/55054>.
2469     ::SetWindowLongPtrW(m_viewWindow, 0, 0);
2470 }
2471
2472 void WebView::setShouldInvertColors(bool shouldInvertColors)
2473 {
2474     if (m_shouldInvertColors == shouldInvertColors)
2475         return;
2476
2477     m_shouldInvertColors = shouldInvertColors;
2478
2479 #if USE(CA)
2480     if (m_layerTreeHost)
2481         m_layerTreeHost->setShouldInvertColors(shouldInvertColors);
2482 #endif
2483
2484     RECT windowRect = {0};
2485     frameRect(&windowRect);
2486
2487     // repaint expects logical pixels, so rescale here.
2488     IntRect logicalRect(windowRect);
2489     logicalRect.scale(1.0f / deviceScaleFactor());
2490     repaint(logicalRect, true, true);
2491 }
2492
2493 bool WebView::registerWebViewWindowClass()
2494 {
2495     static bool haveRegisteredWindowClass = false;
2496     if (haveRegisteredWindowClass)
2497         return true;
2498
2499     haveRegisteredWindowClass = true;
2500
2501     WNDCLASSEX wcex;
2502
2503     wcex.cbSize = sizeof(WNDCLASSEX);
2504
2505     wcex.style          = CS_DBLCLKS;
2506     wcex.lpfnWndProc    = WebViewWndProc;
2507     wcex.cbClsExtra     = 0;
2508     wcex.cbWndExtra     = sizeof(WebView*);
2509     wcex.hInstance      = gInstance;
2510     wcex.hIcon          = 0;
2511     wcex.hCursor        = ::LoadCursor(0, IDC_ARROW);
2512     wcex.hbrBackground  = 0;
2513     wcex.lpszMenuName   = 0;
2514     wcex.lpszClassName  = kWebViewWindowClassName;
2515     wcex.hIconSm        = 0;
2516
2517     return !!RegisterClassEx(&wcex);
2518 }
2519
2520 static HWND findTopLevelParent(HWND window)
2521 {
2522     if (!window)
2523         return 0;
2524
2525     HWND current = window;
2526     for (HWND parent = GetParent(current); current; current = parent, parent = GetParent(parent))
2527         if (!parent || !(GetWindowLongPtr(current, GWL_STYLE) & (WS_POPUP | WS_CHILD)))
2528             return current;
2529     ASSERT_NOT_REACHED();
2530     return 0;
2531 }
2532
2533 LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
2534 {
2535     LRESULT lResult = 0;
2536     LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0);
2537     WebView* webView = reinterpret_cast<WebView*>(longPtr);
2538     WebFrame* mainFrameImpl = webView ? webView->topLevelFrame() : 0;
2539     if (!mainFrameImpl)
2540         return DefWindowProc(hWnd, message, wParam, lParam);
2541
2542     // We shouldn't be trying to handle any window messages after WM_DESTROY.
2543     // See <http://webkit.org/b/55054>.
2544     ASSERT(!webView->isBeingDestroyed());
2545
2546     // hold a ref, since the WebView could go away in an event handler.
2547     COMPtr<WebView> protector(webView);
2548     ASSERT(webView);
2549
2550     // Windows Media Player has a modal message loop that will deliver messages
2551     // to us at inappropriate times and we will crash if we handle them when:
2552     // they are delivered. We repost paint messages so that we eventually get
2553     // a chance to paint once the modal loop has exited, but other messages
2554     // aren't safe to repost, so we just drop them.
2555     if (PluginView::isCallingPlugin()) {
2556         if (message == WM_PAINT)
2557             PostMessage(hWnd, message, wParam, lParam);
2558         return 0;
2559     }
2560
2561     bool handled = true;
2562
2563     switch (message) {
2564         case WM_PAINT: {
2565 #if USE(DIRECT2D)
2566             webView->paintWithDirect2D();
2567 #else
2568             webView->paint(0, 0);
2569 #endif
2570             if (webView->usesLayeredWindow())
2571                 webView->performLayeredWindowUpdate();
2572             break;
2573         }
2574         case WM_ERASEBKGND:
2575             // Don't perform a background erase.
2576             handled = true;
2577             lResult = 1;
2578             break;
2579         case WM_PRINTCLIENT:
2580             webView->paint((HDC)wParam, lParam);
2581             break;
2582         case WM_DESTROY:
2583             webView->setIsBeingDestroyed();
2584             webView->close();
2585             break;
2586         case WM_GESTURENOTIFY:
2587             handled = webView->gestureNotify(wParam, lParam);
2588             break;
2589         case WM_GESTURE:
2590             handled = webView->gesture(wParam, lParam);
2591             break;
2592         case WM_MOUSEMOVE:
2593         case WM_LBUTTONDOWN:
2594         case WM_MBUTTONDOWN:
2595         case WM_RBUTTONDOWN:
2596         case WM_LBUTTONDBLCLK:
2597         case WM_MBUTTONDBLCLK:
2598         case WM_RBUTTONDBLCLK:
2599         case WM_LBUTTONUP:
2600         case WM_MBUTTONUP:
2601         case WM_RBUTTONUP:
2602         case WM_MOUSELEAVE:
2603         case WM_CANCELMODE:
2604             if (Frame* coreFrame = core(mainFrameImpl))
2605                 if (coreFrame->view()->didFirstLayout())
2606                     handled = webView->handleMouseEvent(message, wParam, lParam);
2607             break;
2608         case WM_MOUSEWHEEL:
2609         case WM_VISTA_MOUSEHWHEEL:
2610             if (Frame* coreFrame = core(mainFrameImpl))
2611                 if (coreFrame->view()->didFirstLayout())
2612                     handled = webView->mouseWheel(wParam, lParam, message == WM_VISTA_MOUSEHWHEEL);
2613             break;
2614         case WM_SYSKEYDOWN:
2615             handled = webView->keyDown(wParam, lParam, true);
2616             break;
2617         case WM_KEYDOWN:
2618             handled = webView->keyDown(wParam, lParam);
2619             break;
2620         case WM_SYSKEYUP:
2621             handled = webView->keyUp(wParam, lParam, true);
2622             break;
2623         case WM_KEYUP:
2624             handled = webView->keyUp(wParam, lParam);
2625             break;
2626         case WM_SYSCHAR:
2627             handled = webView->keyPress(wParam, lParam, true);
2628             break;
2629         case WM_CHAR:
2630             handled = webView->keyPress(wParam, lParam);
2631             break;
2632         // FIXME: We need to check WM_UNICHAR to support supplementary characters (that don't fit in 16 bits).
2633         case WM_SIZE:
2634             if (lParam != 0)
2635                 webView->sizeChanged(IntSize(LOWORD(lParam), HIWORD(lParam)));
2636             break;
2637         case WM_DPICHANGED:
2638             webView->dpiChanged(LOWORD(wParam), IntSize(LOWORD(lParam), HIWORD(lParam)));
2639             break;
2640         case WM_SHOWWINDOW:
2641             lResult = DefWindowProc(hWnd, message, wParam, lParam);
2642             if (wParam == 0) {
2643                 // The window is being hidden (e.g., because we switched tabs).
2644                 // Null out our backing store.
2645                 webView->deleteBackingStore();
2646             }
2647             break;
2648         case WM_SETFOCUS: {
2649             COMPtr<IWebUIDelegate> uiDelegate;
2650             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
2651             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate
2652                 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
2653                 uiDelegatePrivate->webViewReceivedFocus(webView);
2654
2655             FocusController& focusController = webView->page()->focusController();
2656             if (Frame* frame = focusController.focusedFrame()) {
2657                 // Send focus events unless the previously focused window is a
2658                 // child of ours (for example a plugin).
2659                 if (!IsChild(hWnd, reinterpret_cast<HWND>(wParam)))
2660                     focusController.setFocused(true);
2661             } else
2662                 focusController.setFocused(true);
2663             break;
2664         }
2665         case WM_KILLFOCUS: {
2666             COMPtr<IWebUIDelegate> uiDelegate;
2667             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
2668             HWND newFocusWnd = reinterpret_cast<HWND>(wParam);
2669             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate
2670                 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
2671                 uiDelegatePrivate->webViewLostFocus(webView, newFocusWnd);
2672
2673             FocusController& focusController = webView->page()->focusController();
2674             Frame& frame = focusController.focusedOrMainFrame();
2675             webView->resetIME(&frame);
2676             // Send blur events unless we're losing focus to a child of ours.
2677             if (!IsChild(hWnd, newFocusWnd))
2678                 focusController.setFocused(false);
2679
2680             // If we are pan-scrolling when we lose focus, stop the pan scrolling.
2681             frame.eventHandler().stopAutoscrollTimer();
2682
2683             break;
2684         }
2685         case WM_WINDOWPOSCHANGED:
2686             if (reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW)
2687                 webView->updateActiveStateSoon();
2688             handled = false;
2689             break;
2690         case WM_CUT:
2691             webView->cut(0);
2692             break;
2693         case WM_COPY:
2694             webView->copy(0);
2695             break;
2696         case WM_PASTE:
2697             webView->paste(0);
2698             break;
2699         case WM_CLEAR:
2700             webView->delete_(0);
2701             break;
2702         case WM_COMMAND:
2703             if (HIWORD(wParam))
2704                 handled = webView->execCommand(wParam, lParam);
2705             break;
2706         case WM_MENUCOMMAND:
2707             webView->onMenuCommand(wParam, lParam);
2708             break;
2709         case WM_CONTEXTMENU:
2710             handled = webView->handleContextMenuEvent(wParam, lParam);
2711             break;
2712         case WM_INITMENUPOPUP:
2713             handled = webView->onInitMenuPopup(wParam, lParam);
2714             break;
2715         case WM_MEASUREITEM:
2716             handled = webView->onMeasureItem(wParam, lParam);
2717             break;
2718         case WM_DRAWITEM:
2719             handled = webView->onDrawItem(wParam, lParam);
2720             break;
2721         case WM_UNINITMENUPOPUP:
2722             handled = webView->onUninitMenuPopup(wParam, lParam);
2723             break;
2724         case WM_XP_THEMECHANGED:
2725             if (Frame* coreFrame = core(mainFrameImpl)) {
2726                 webView->deleteBackingStore();
2727                 coreFrame->page()->theme().themeChanged();
2728                 ScrollbarTheme::theme().themeChanged();
2729                 RECT windowRect;
2730                 ::GetClientRect(hWnd, &windowRect);
2731                 ::InvalidateRect(hWnd, &windowRect, false);
2732 #if USE(CA)
2733                 if (webView->isAcceleratedCompositing())
2734                     webView->m_backingLayer->setNeedsDisplay();
2735 #endif
2736            }
2737             break;
2738         case WM_MOUSEACTIVATE:
2739             webView->setMouseActivated(true);
2740             handled = false;
2741             break;
2742         case WM_GETDLGCODE: {
2743             COMPtr<IWebUIDelegate> uiDelegate;
2744             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
2745             LONG_PTR dlgCode = 0;
2746             UINT keyCode = 0;
2747             if (lParam) {
2748                 LPMSG lpMsg = (LPMSG)lParam;
2749                 if (lpMsg->message == WM_KEYDOWN)
2750                     keyCode = (UINT) lpMsg->wParam;
2751             }
2752             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate
2753                 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate
2754                 && SUCCEEDED(uiDelegatePrivate->webViewGetDlgCode(webView, keyCode, &dlgCode)))
2755                 return dlgCode;
2756             handled = false;
2757             break;
2758         }
2759         case WM_GETOBJECT:
2760             handled = webView->onGetObject(wParam, lParam, lResult);
2761             break;
2762         case WM_IME_STARTCOMPOSITION:
2763             handled = webView->onIMEStartComposition();
2764             break;
2765         case WM_IME_REQUEST:
2766             lResult = webView->onIMERequest(wParam, lParam);
2767             break;
2768         case WM_IME_COMPOSITION:
2769             handled = webView->onIMEComposition(lParam);
2770             break;
2771         case WM_IME_ENDCOMPOSITION:
2772             handled = webView->onIMEEndComposition();
2773             break;
2774         case WM_IME_CHAR:
2775             handled = webView->onIMEChar(wParam, lParam);
2776             break;
2777         case WM_IME_NOTIFY:
2778             handled = webView->onIMENotify(wParam, lParam, &lResult);
2779             break;
2780         case WM_IME_SELECT:
2781             handled = webView->onIMESelect(wParam, lParam);
2782             break;
2783         case WM_IME_SETCONTEXT:
2784             handled = webView->onIMESetContext(wParam, lParam);
2785             break;
2786         case WM_TIMER:
2787             switch (wParam) {
2788                 case UpdateActiveStateTimer:
2789                     KillTimer(hWnd, UpdateActiveStateTimer);
2790                     webView->updateActiveState();
2791                     break;
2792                 case DeleteBackingStoreTimer:
2793                     webView->deleteBackingStore();
2794                     break;
2795             }
2796             break;
2797         case WM_SETCURSOR:
2798             handled = ::SetCursor(webView->m_lastSetCursor);
2799             break;
2800         case WM_VSCROLL:
2801             handled = webView->verticalScroll(wParam, lParam);
2802             break;
2803         case WM_HSCROLL:
2804             handled = webView->horizontalScroll(wParam, lParam);
2805             break;
2806         default:
2807             handled = false;
2808             break;
2809     }
2810
2811     webView->updateWindowIfNeeded(hWnd, message);
2812
2813     if (!handled)
2814         lResult = DefWindowProc(hWnd, message, wParam, lParam);
2815     
2816     // Let the client know whether we consider this message handled.
2817     return (message == WM_KEYDOWN || message == WM_SYSKEYDOWN || message == WM_KEYUP || message == WM_SYSKEYUP) ? !handled : lResult;
2818 }
2819
2820 void WebView::updateWindowIfNeeded(HWND hWnd, UINT message)
2821 {
2822     if (!needsDisplay())
2823         return;
2824
2825     // Care should be taken when updating the window from the window procedure.
2826     // Updating the window in response to e.g. WM_PARENTNOTIFY may cause reentrancy problems,
2827     // because WM_PARENTNOTIFY is sent synchronously to the parent window when e.g. DestroyWindow() is called.
2828
2829     switch (message) {
2830     case WM_PAINT:
2831     case WM_PARENTNOTIFY:
2832         return;
2833     }
2834
2835     ::UpdateWindow(hWnd);
2836 }
2837
2838 bool WebView::developerExtrasEnabled() const
2839 {
2840     if (m_preferences->developerExtrasDisabledByOverride())
2841         return false;
2842
2843 #ifdef NDEBUG
2844     BOOL enabled;
2845     return SUCCEEDED(m_preferences->developerExtrasEnabled(&enabled)) && enabled;
2846 #else
2847     return true;
2848 #endif
2849 }
2850
2851 static String webKitVersionString()
2852 {
2853 #if !USE(CAIRO)
2854     LPWSTR buildNumberStringPtr;
2855     if (::LoadStringW(gInstance, BUILD_NUMBER, reinterpret_cast<LPWSTR>(&buildNumberStringPtr), 0) && buildNumberStringPtr)
2856         return buildNumberStringPtr;
2857 #endif
2858     return String::format("%d.%d", WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION);
2859 }
2860
2861 const String& WebView::userAgentForKURL(const URL&)
2862 {
2863     if (m_userAgentOverridden)
2864         return m_userAgentCustom;
2865
2866     if (!m_userAgentStandard.length())
2867         m_userAgentStandard = WebView::standardUserAgentWithApplicationName(m_applicationName);
2868     return m_userAgentStandard;
2869 }
2870
2871 // IUnknown -------------------------------------------------------------------
2872
2873 HRESULT WebView::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
2874 {
2875     if (!ppvObject)
2876         return E_POINTER;
2877     *ppvObject = nullptr;
2878     if (IsEqualGUID(riid, CLSID_WebView))
2879         *ppvObject = this;
2880     else if (IsEqualGUID(riid, IID_IUnknown))
2881         *ppvObject = static_cast<IWebView*>(this);
2882     else if (IsEqualGUID(riid, IID_IWebView))
2883         *ppvObject = static_cast<IWebView*>(this);
2884     else if (IsEqualGUID(riid, IID_IWebViewPrivate))
2885         *ppvObject = static_cast<IWebViewPrivate*>(this);
2886     else if (IsEqualGUID(riid, IID_IWebViewPrivate2))
2887         *ppvObject = static_cast<IWebViewPrivate2*>(this);
2888     else if (IsEqualGUID(riid, IID_IWebViewPrivate3))
2889         *ppvObject = static_cast<IWebViewPrivate3*>(this);
2890     else if (IsEqualGUID(riid, IID_IWebIBActions))
2891         *ppvObject = static_cast<IWebIBActions*>(this);
2892     else if (IsEqualGUID(riid, IID_IWebViewCSS))
2893         *ppvObject = static_cast<IWebViewCSS*>(this);
2894     else if (IsEqualGUID(riid, IID_IWebViewEditing))
2895         *ppvObject = static_cast<IWebViewEditing*>(this);
2896     else if (IsEqualGUID(riid, IID_IWebViewUndoableEditing))
2897         *ppvObject = static_cast<IWebViewUndoableEditing*>(this);
2898     else if (IsEqualGUID(riid, IID_IWebViewEditingActions))
2899         *ppvObject = static_cast<IWebViewEditingActions*>(this);
2900     else if (IsEqualGUID(riid, IID_IWebNotificationObserver))
2901         *ppvObject = static_cast<IWebNotificationObserver*>(this);
2902     else if (IsEqualGUID(riid, IID_IDropTarget))
2903         *ppvObject = static_cast<IDropTarget*>(this);
2904     else
2905         return E_NOINTERFACE;
2906
2907     AddRef();
2908     return S_OK;
2909 }
2910
2911 ULONG WebView::AddRef()
2912 {
2913     ASSERT(!m_deletionHasBegun);
2914     return ++m_refCount;
2915 }
2916
2917 ULONG WebView::Release()
2918 {
2919     ASSERT(!m_deletionHasBegun);
2920
2921     if (m_refCount == 1) {
2922         // Call close() now so that clients don't have to. (It's harmless to call close() multiple
2923         // times.) We do this here instead of in our destructor because close() can cause AddRef()
2924         // and Release() to be called, and if that happened in our destructor we would be destroyed
2925         // more than once.
2926         close();
2927     }
2928
2929     ULONG newRef = --m_refCount;
2930     if (!newRef) {
2931 #if !ASSERT_DISABLED
2932         m_deletionHasBegun = true;
2933 #endif
2934         delete(this);
2935     }
2936
2937     return newRef;
2938 }
2939
2940 // IWebView --------------------------------------------------------------------
2941
2942 HRESULT WebView::canShowMIMEType(_In_ BSTR mimeType, _Out_ BOOL* canShow)
2943 {
2944     if (!canShow)
2945         return E_POINTER;
2946
2947     *canShow = canShowMIMEType(toString(mimeType));
2948
2949     return S_OK;
2950 }
2951
2952 bool WebView::canShowMIMEType(const String& mimeType)
2953 {
2954     Frame* coreFrame = core(m_mainFrame);
2955     bool allowPlugins = coreFrame && coreFrame->loader().subframeLoader().allowPlugins();
2956
2957     bool canShow = MIMETypeRegistry::isSupportedImageMIMEType(mimeType)
2958         || MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)
2959         || MIMETypeRegistry::isSupportedMediaMIMEType(mimeType);
2960
2961     if (!canShow && m_page) {
2962         canShow = (m_page->pluginData().supportsWebVisibleMimeType(mimeType, PluginData::AllPlugins) && allowPlugins)
2963             || m_page->pluginData().supportsWebVisibleMimeType(mimeType, PluginData::OnlyApplicationPlugins);
2964     }
2965
2966     if (!canShow)
2967         canShow = shouldUseEmbeddedView(mimeType);
2968
2969     return canShow;
2970 }
2971
2972 HRESULT WebView::canShowMIMETypeAsHTML(_In_ BSTR mimeType, _Out_ BOOL* canShow)
2973 {
2974     if (!canShow)
2975         return E_POINTER;
2976
2977     *canShow = canShowMIMETypeAsHTML(toString(mimeType));
2978
2979     return S_OK;
2980 }
2981
2982 bool WebView::canShowMIMETypeAsHTML(const String& /*mimeType*/)
2983 {
2984     // FIXME
2985     notImplemented();
2986     return true;
2987 }
2988
2989 HRESULT WebView::MIMETypesShownAsHTML(_COM_Outptr_opt_ IEnumVARIANT** enumVariant)
2990 {
2991     ASSERT_NOT_REACHED();
2992     if (!enumVariant)
2993         return E_POINTER;
2994     *enumVariant = nullptr;
2995     return E_NOTIMPL;
2996 }
2997
2998 HRESULT WebView::setMIMETypesShownAsHTML(__inout_ecount_full(cMimeTypes) BSTR* mimeTypes, int cMimeTypes)
2999 {
3000     ASSERT_NOT_REACHED();
3001     return E_NOTIMPL;
3002 }
3003
3004 HRESULT WebView::URLFromPasteboard(_In_opt_ IDataObject* /*pasteboard*/, _Deref_opt_out_ BSTR* /*url*/)
3005 {
3006     ASSERT_NOT_REACHED();
3007     return E_NOTIMPL;
3008 }
3009
3010 HRESULT WebView::URLTitleFromPasteboard(_In_opt_ IDataObject* /*pasteboard*/, _Deref_opt_out_ BSTR* /*urlTitle*/)
3011 {
3012     ASSERT_NOT_REACHED();
3013     return E_NOTIMPL;
3014 }
3015
3016 bool WebView::shouldInitializeTrackPointHack()
3017 {
3018     static bool shouldCreateScrollbars;
3019     static bool hasRunTrackPointCheck;
3020
3021     if (hasRunTrackPointCheck)
3022         return shouldCreateScrollbars;
3023
3024     hasRunTrackPointCheck = true;
3025     const WCHAR trackPointKeys[][50] = { L"Software\\Lenovo\\TrackPoint",
3026         L"Software\\Lenovo\\UltraNav",
3027         L"Software\\Alps\\Apoint\\TrackPoint",
3028         L"Software\\Synaptics\\SynTPEnh\\UltraNavUSB",
3029         L"Software\\Synaptics\\SynTPEnh\\UltraNavPS2" };
3030
3031     for (int i = 0; i < 5; ++i) {
3032         HKEY trackPointKey = nullptr;
3033         LSTATUS readKeyResult = ::RegOpenKeyExW(HKEY_CURRENT_USER, trackPointKeys[i], 0, KEY_READ, &trackPointKey);
3034         ::RegCloseKey(trackPointKey);
3035         if (readKeyResult == ERROR_SUCCESS) {
3036             shouldCreateScrollbars = true;
3037             return shouldCreateScrollbars;
3038         }
3039     }
3040
3041     return shouldCreateScrollbars;
3042 }
3043
3044 HRESULT WebView::initWithFrame(RECT frame, _In_ BSTR frameName, _In_ BSTR groupName)
3045 {
3046     HRESULT hr = S_OK;
3047
3048     if (m_viewWindow)
3049         return E_UNEXPECTED;
3050
3051     registerWebViewWindowClass();
3052
3053     m_viewWindow = CreateWindowEx(0, kWebViewWindowClassName, 0, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
3054         frame.left, frame.top, frame.right - frame.left, frame.bottom - frame.top, m_hostWindow ? m_hostWindow : HWND_MESSAGE, 0, gInstance, 0);
3055     ASSERT(::IsWindow(m_viewWindow));
3056
3057     if (shouldInitializeTrackPointHack()) {
3058         // If we detected a registry key belonging to a TrackPoint driver, then create fake trackpoint
3059         // scrollbars, so the WebView will receive WM_VSCROLL and WM_HSCROLL messages. We create one
3060         // vertical scrollbar and one horizontal to allow for receiving both types of messages.
3061         ::CreateWindowW(L"SCROLLBAR", L"FAKETRACKPOINTHSCROLLBAR", WS_CHILD | WS_VISIBLE | SBS_HORZ, 0, 0, 0, 0, m_viewWindow, 0, gInstance, 0);
3062         ::CreateWindowW(L"SCROLLBAR", L"FAKETRACKPOINTVSCROLLBAR", WS_CHILD | WS_VISIBLE | SBS_VERT, 0, 0, 0, 0, m_viewWindow, 0, gInstance, 0);
3063     }
3064
3065     hr = registerDragDrop();
3066     if (FAILED(hr))
3067         return hr;
3068
3069     WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences();
3070     sharedPreferences->willAddToWebView();
3071     m_preferences = sharedPreferences;
3072
3073     static bool didOneTimeInitialization;
3074     if (!didOneTimeInitialization) {
3075 #if !LOG_DISABLED || !RELEASE_LOG_DISABLED
3076         initializeLogChannelsIfNecessary();
3077 #endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED
3078
3079         // Initialize our platform strategies first before invoking the rest
3080         // of the initialization code which may depend on the strategies.
3081         WebPlatformStrategies::initialize();
3082
3083         WebKitInitializeWebDatabasesIfNecessary();
3084
3085         MemoryPressureHandler::singleton().install();
3086
3087         didOneTimeInitialization = true;
3088      }
3089
3090     BOOL useHighResolutionTimer;
3091     if (SUCCEEDED(m_preferences->shouldUseHighResolutionTimers(&useHighResolutionTimer)))
3092         Settings::setShouldUseHighResolutionTimers(useHighResolutionTimer);
3093
3094     m_inspectorClient = new WebInspectorClient(this);
3095
3096     PageConfiguration configuration(makeUniqueRef<WebEditorClient>(this), SocketProvider::create());
3097     configuration.backForwardClient = BackForwardList::create();
3098     configuration.chromeClient = new WebChromeClient(this);
3099     configuration.contextMenuClient = new WebContextMenuClient(this);
3100     configuration.dragClient = new WebDragClient(this);
3101     configuration.inspectorClient = m_inspectorClient;
3102     configuration.loaderClientForMainFrame = new WebFrameLoaderClient;
3103     configuration.applicationCacheStorage = &WebApplicationCache::storage();
3104     configuration.databaseProvider = &WebDatabaseProvider::singleton();
3105     configuration.storageNamespaceProvider = &m_webViewGroup->storageNamespaceProvider();
3106     configuration.progressTrackerClient = static_cast<WebFrameLoaderClient*>(configuration.loaderClientForMainFrame);
3107     configuration.userContentProvider = &m_webViewGroup->userContentController();
3108     configuration.visitedLinkStore = &m_webViewGroup->visitedLinkStore();
3109     configuration.pluginInfoProvider = &WebPluginInfoProvider::singleton();
3110
3111     m_page = new Page(WTFMove(configuration));
3112     provideGeolocationTo(m_page, new WebGeolocationClient(this));
3113
3114     unsigned layoutMilestones = DidFirstLayout | DidFirstVisuallyNonEmptyLayout;
3115     m_page->addLayoutMilestones(static_cast<LayoutMilestones>(layoutMilestones));
3116
3117
3118     if (m_uiDelegate) {
3119         BString path;
3120         if (SUCCEEDED(m_uiDelegate->ftpDirectoryTemplatePath(this, &path)))
3121             m_page->settings().setFTPDirectoryTemplatePath(toString(path));
3122     }
3123
3124     WebFrame* webFrame = WebFrame::createInstance();
3125     webFrame->initWithWebView(this, m_page);
3126     static_cast<WebFrameLoaderClient&>(m_page->mainFrame().loader().client()).setWebFrame(webFrame);
3127     m_mainFrame = webFrame;
3128     webFrame->Release(); // The WebFrame is owned by the Frame, so release our reference to it.
3129
3130     m_page->mainFrame().tree().setName(toString(frameName));
3131     m_page->mainFrame().init();
3132     setGroupName(groupName);
3133
3134     addToAllWebViewsSet();
3135
3136     #pragma warning(suppress: 4244)
3137     SetWindowLongPtr(m_viewWindow, 0, (LONG_PTR)this);
3138     ShowWindow(m_viewWindow, SW_SHOW);
3139
3140     initializeToolTipWindow();
3141     windowAncestryDidChange();
3142
3143     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
3144     notifyCenter->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3145     m_preferences->postPreferencesChangesNotification();
3146
3147     m_page->setDeviceScaleFactor(deviceScaleFactor());
3148
3149     setSmartInsertDeleteEnabled(TRUE);
3150
3151     return hr;
3152 }
3153
3154 static bool initCommonControls()
3155 {
3156     static bool haveInitialized = false;
3157     if (haveInitialized)
3158         return true;
3159
3160     INITCOMMONCONTROLSEX init;
3161     init.dwSize = sizeof(init);
3162     init.dwICC = ICC_TREEVIEW_CLASSES;
3163     haveInitialized = !!::InitCommonControlsEx(&init);
3164     return haveInitialized;
3165 }
3166
3167 void WebView::initializeToolTipWindow()
3168 {
3169     if (!initCommonControls())
3170         return;
3171
3172     m_toolTipHwnd = CreateWindowEx(WS_EX_TRANSPARENT, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
3173                                    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
3174                                    m_viewWindow, 0, 0, 0);
3175     if (!m_toolTipHwnd)
3176         return;
3177
3178     TOOLINFO info = {0};
3179     info.cbSize = sizeof(info);
3180     info.uFlags = TTF_IDISHWND | TTF_SUBCLASS ;
3181     info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
3182
3183     ::SendMessage(m_toolTipHwnd, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info));
3184     ::SendMessage(m_toolTipHwnd, TTM_SETMAXTIPWIDTH, 0, clampTo<int>(maxToolTipWidth * deviceScaleFactor()));
3185
3186     ::SetWindowPos(m_toolTipHwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
3187 }
3188
3189 void WebView::setToolTip(const String& toolTip)
3190 {
3191     if (!m_toolTipHwnd)
3192         return;
3193
3194     if (toolTip == m_toolTip)
3195         return;
3196
3197     m_toolTip = toolTip;
3198
3199     if (!m_toolTip.isEmpty()) {
3200         TOOLINFO info = {0};
3201         info.cbSize = sizeof(info);
3202         info.uFlags = TTF_IDISHWND;
3203         info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
3204         Vector<UChar> toolTipCharacters = m_toolTip.charactersWithNullTermination(); // Retain buffer long enough to make the SendMessage call
3205         info.lpszText = const_cast<UChar*>(toolTipCharacters.data());
3206         ::SendMessage(m_toolTipHwnd, TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info));
3207     }
3208
3209     ::SendMessage(m_toolTipHwnd, TTM_ACTIVATE, !m_toolTip.isEmpty(), 0);
3210 }
3211
3212 HRESULT WebView::notifyDidAddIcon(IWebNotification* notification)
3213 {
3214     COMPtr<IPropertyBag> propertyBag;
3215     HRESULT hr = notification->userInfo(&propertyBag);
3216     if (FAILED(hr))
3217         return hr;
3218     if (!propertyBag)
3219         return E_FAIL;
3220
3221     COMVariant iconUserInfoURL;
3222     hr = propertyBag->Read(WebIconDatabase::iconDatabaseNotificationUserInfoURLKey(), &iconUserInfoURL, nullptr);
3223     if (FAILED(hr))
3224         return hr;
3225
3226     if (iconUserInfoURL.variantType() != VT_BSTR)
3227         return E_FAIL;
3228
3229     String mainFrameURL;
3230     if (m_mainFrame)
3231         mainFrameURL = m_mainFrame->url().string();
3232
3233     if (!mainFrameURL.isEmpty() && mainFrameURL == toString(V_BSTR(&iconUserInfoURL)))
3234         dispatchDidReceiveIconFromWebFrame(m_mainFrame);
3235
3236     return hr;
3237 }
3238
3239 void WebView::registerForIconNotification(bool listen)
3240 {
3241     IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
3242     if (listen)
3243         nc->addObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
3244     else
3245         nc->removeObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
3246 }
3247
3248 void WebView::dispatchDidReceiveIconFromWebFrame(WebFrame* frame)
3249 {
3250     registerForIconNotification(false);
3251
3252     if (m_frameLoadDelegate) {
3253         String str = frame->url().string();
3254
3255         IntSize sz(16, 16);
3256
3257         BitmapInfo bmInfo = BitmapInfo::create(sz);
3258
3259         HBITMAP hBitmap = nullptr;
3260
3261         Image* icon = iconDatabase().synchronousIconForPageURL(str, sz);
3262
3263         if (icon && icon->width()) {
3264             HWndDC dc(0);
3265             hBitmap = CreateDIBSection(dc, &bmInfo, DIB_RGB_COLORS, 0, 0, 0);
3266             icon->getHBITMAPOfSize(hBitmap, &sz);
3267         }
3268
3269         HRESULT hr = m_frameLoadDelegate->didReceiveIcon(this, hBitmap, frame);
3270         if ((hr == E_NOTIMPL) && hBitmap)
3271             DeleteObject(hBitmap);
3272     }
3273 }
3274
3275 HRESULT WebView::setAccessibilityDelegate(_In_opt_ IAccessibilityDelegate* d)
3276 {
3277     m_accessibilityDelegate = d;
3278     return S_OK;
3279 }
3280
3281 HRESULT WebView::accessibilityDelegate(_COM_Outptr_opt_ IAccessibilityDelegate** d)
3282 {
3283     if (!d)
3284         return E_POINTER;
3285     *d = nullptr;
3286     if (!m_accessibilityDelegate)
3287         return E_POINTER;
3288
3289     return m_accessibilityDelegate.copyRefTo(d);
3290 }
3291
3292 HRESULT WebView::setUIDelegate(_In_opt_ IWebUIDelegate* d)
3293 {
3294     m_uiDelegate = d;
3295
3296     if (m_uiDelegatePrivate)
3297         m_uiDelegatePrivate = 0;
3298
3299     if (d) {
3300         if (FAILED(d->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&m_uiDelegatePrivate)))
3301             m_uiDelegatePrivate = 0;
3302     }
3303
3304     return S_OK;
3305 }
3306
3307 HRESULT WebView::uiDelegate(_COM_Outptr_opt_ IWebUIDelegate** d)
3308 {
3309     if (!d)
3310         return E_POINTER;
3311     *d = nullptr;
3312     if (!m_uiDelegate)
3313         return E_FAIL;
3314
3315     return m_uiDelegate.copyRefTo(d);
3316 }
3317
3318 HRESULT WebView::setResourceLoadDelegate(_In_opt_ IWebResourceLoadDelegate* d)
3319 {
3320     m_resourceLoadDelegate = d;
3321     return S_OK;
3322 }
3323
3324 HRESULT WebView::resourceLoadDelegate(_COM_Outptr_opt_ IWebResourceLoadDelegate** d)
3325 {
3326     if (!d)
3327         return E_POINTER;
3328     *d = nullptr;
3329     if (!m_resourceLoadDelegate)
3330         return E_FAIL;
3331
3332     return m_resourceLoadDelegate.copyRefTo(d);
3333 }
3334
3335 HRESULT WebView::setDownloadDelegate(_In_opt_ IWebDownloadDelegate* d)
3336 {
3337     m_downloadDelegate = d;
3338     return S_OK;
3339 }
3340
3341 HRESULT WebView::downloadDelegate(_COM_Outptr_opt_ IWebDownloadDelegate** d)
3342 {
3343     if (!d)
3344         return E_POINTER;
3345     *d = nullptr;
3346     if (!m_downloadDelegate)
3347         return E_FAIL;
3348
3349     return m_downloadDelegate.copyRefTo(d);
3350 }
3351
3352 HRESULT WebView::setFrameLoadDelegate(_In_opt_ IWebFrameLoadDelegate* d)
3353 {
3354     m_frameLoadDelegate = d;
3355     return S_OK;
3356 }
3357
3358 HRESULT WebView::frameLoadDelegate(_COM_Outptr_opt_ IWebFrameLoadDelegate** d)
3359 {
3360     if (!d)
3361         return E_POINTER;
3362     *d = nullptr;
3363     if (!m_frameLoadDelegate)
3364         return E_FAIL;
3365
3366     return m_frameLoadDelegate.copyRefTo(d);
3367 }
3368
3369 HRESULT WebView::setPolicyDelegate(_In_opt_ IWebPolicyDelegate* d)
3370 {
3371     m_policyDelegate = d;
3372     return S_OK;
3373 }
3374
3375 HRESULT WebView::policyDelegate(_COM_Outptr_opt_ IWebPolicyDelegate** d)
3376 {
3377     if (!d)
3378         return E_POINTER;
3379     *d = nullptr;
3380     if (!m_policyDelegate)
3381         return E_FAIL;
3382
3383     return m_policyDelegate.copyRefTo(d);
3384 }
3385
3386 HRESULT WebView::mainFrame(_COM_Outptr_opt_ IWebFrame** frame)
3387 {
3388     if (!frame) {
3389         ASSERT_NOT_REACHED();
3390         return E_POINTER;
3391     }
3392
3393     *frame = m_mainFrame;
3394     if (!m_mainFrame)
3395         return E_UNEXPECTED;
3396
3397     m_mainFrame->AddRef();
3398     return S_OK;
3399 }
3400
3401 HRESULT WebView::focusedFrame(_COM_Outptr_opt_ IWebFrame** frame)
3402 {
3403     if (!frame) {
3404         ASSERT_NOT_REACHED();
3405         return E_POINTER;
3406     }
3407
3408     *frame = nullptr;
3409     Frame* f = m_page->focusController().focusedFrame();
3410     if (!f)
3411         return E_FAIL;
3412
3413     WebFrame* webFrame = kit(f);
3414     if (!webFrame)
3415         return E_UNEXPECTED;
3416
3417     return webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
3418 }
3419
3420 HRESULT WebView::backForwardList(_COM_Outptr_opt_ IWebBackForwardList** list)
3421 {
3422     if (!list) {
3423         ASSERT_NOT_REACHED();
3424         return E_POINTER;
3425     }
3426     *list = nullptr;
3427     if (!m_useBackForwardList)
3428         return E_FAIL;
3429  
3430     *list = WebBackForwardList::createInstance(static_cast<BackForwardList*>(m_page->backForward().client()));
3431
3432     return S_OK;
3433 }
3434
3435 HRESULT WebView::setMaintainsBackForwardList(BOOL flag)
3436 {
3437     m_useBackForwardList = !!flag;
3438     return S_OK;
3439 }
3440
3441 HRESULT WebView::goBack(_Out_ BOOL* succeeded)
3442 {
3443     if (!succeeded)
3444         return E_POINTER;
3445
3446     *succeeded = m_page->backForward().goBack();
3447     return S_OK;
3448 }
3449
3450 HRESULT WebView::goForward(_Out_ BOOL* succeeded)
3451 {
3452     if (!succeeded)
3453         return E_POINTER;
3454
3455     *succeeded = m_page->backForward().goForward();
3456     return S_OK;
3457 }
3458
3459 HRESULT WebView::goToBackForwardItem(_In_opt_ IWebHistoryItem* item, _Out_ BOOL* succeeded)
3460 {
3461     if (!item)
3462         return E_FAIL;
3463
3464     if (!succeeded)
3465         return E_POINTER;
3466
3467     *succeeded = FALSE;
3468
3469     COMPtr<WebHistoryItem> webHistoryItem;
3470     HRESULT hr = item->QueryInterface(&webHistoryItem);
3471     if (FAILED(hr))
3472         return hr;
3473
3474     m_page->goToItem(*webHistoryItem->historyItem(), FrameLoadType::IndexedBackForward);
3475     *succeeded = TRUE;
3476
3477     return S_OK;
3478 }
3479
3480 HRESULT WebView::setTextSizeMultiplier(float multiplier)
3481 {
3482     if (!m_mainFrame)
3483         return E_UNEXPECTED;
3484     setZoomMultiplier(multiplier, true);
3485     return S_OK;
3486 }
3487
3488 HRESULT WebView::setPageSizeMultiplier(float multiplier)
3489 {
3490     if (!m_mainFrame)
3491         return E_UNEXPECTED;
3492     setZoomMultiplier(multiplier, false);
3493     return S_OK;
3494 }
3495
3496 void WebView::setZoomMultiplier(float multiplier, bool isTextOnly)
3497 {
3498     m_zoomMultiplier = multiplier;
3499     m_zoomsTextOnly = isTextOnly;
3500
3501     if (Frame* coreFrame = core(m_mainFrame)) {
3502         if (m_zoomsTextOnly)
3503             coreFrame->setPageAndTextZoomFactors(1, multiplier);
3504         else
3505             coreFrame->setPageAndTextZoomFactors(multiplier, 1);
3506     }
3507 }
3508
3509 HRESULT WebView::textSizeMultiplier(_Out_ float* multiplier)
3510 {
3511     if (!multiplier)
3512         return E_POINTER;
3513
3514     *multiplier = zoomMultiplier(true);
3515     return S_OK;
3516 }
3517
3518 HRESULT WebView::pageSizeMultiplier(_Out_ float* multiplier)
3519 {
3520     if (!multiplier)
3521         return E_POINTER;
3522
3523     *multiplier = zoomMultiplier(false);
3524     return S_OK;
3525 }
3526
3527 float WebView::zoomMultiplier(bool isTextOnly)
3528 {
3529     if (isTextOnly != m_zoomsTextOnly)
3530         return 1.0f;
3531     return m_zoomMultiplier;
3532 }
3533
3534 HRESULT WebView::setApplicationNameForUserAgent(_In_ BSTR applicationName)
3535 {
3536     m_applicationName = toString(applicationName);
3537     m_userAgentStandard = String();
3538     return S_OK;
3539 }
3540
3541 HRESULT WebView::applicationNameForUserAgent(_Deref_opt_out_ BSTR* applicationName)
3542 {
3543     if (!applicationName)
3544         return E_POINTER;
3545
3546     *applicationName = BString(m_applicationName).release();
3547     if (!*applicationName && m_applicationName.length())
3548         return E_OUTOFMEMORY;
3549     return S_OK;
3550 }
3551
3552 HRESULT WebView::setCustomUserAgent(_In_ BSTR userAgentString)
3553 {
3554     m_userAgentOverridden = userAgentString;
3555     m_userAgentCustom = toString(userAgentString);
3556     return S_OK;
3557 }
3558
3559 HRESULT WebView::customUserAgent(_Deref_opt_out_ BSTR* userAgentString)
3560 {
3561     if (!userAgentString)
3562         return E_POINTER;
3563
3564     *userAgentString = nullptr;
3565     if (!m_userAgentOverridden)
3566         return S_OK;
3567     *userAgentString = BString(m_userAgentCustom).release();
3568     if (!*userAgentString && m_userAgentCustom.length())
3569         return E_OUTOFMEMORY;
3570     return S_OK;
3571 }
3572
3573 HRESULT WebView::userAgentForURL(_In_ BSTR url, _Deref_opt_out_ BSTR* userAgent)
3574 {
3575     if (!userAgent)
3576         return E_POINTER;
3577
3578     String userAgentString = userAgentForKURL(MarshallingHelpers::BSTRToKURL(url));
3579     *userAgent = BString(userAgentString).release();
3580     if (!*userAgent && userAgentString.length())
3581         return E_OUTOFMEMORY;
3582     return S_OK;
3583 }
3584
3585 HRESULT WebView::supportsTextEncoding(_Out_ BOOL* supports)
3586 {
3587     if (!supports)
3588         return E_POINTER;
3589
3590     *supports = TRUE;
3591     return S_OK;
3592 }
3593
3594 HRESULT WebView::setCustomTextEncodingName(_In_ BSTR encodingName)
3595 {
3596     if (!m_mainFrame)
3597         return E_UNEXPECTED;
3598
3599     HRESULT hr;
3600     BString oldEncoding;
3601     hr = customTextEncodingName(&oldEncoding);
3602     if (FAILED(hr))
3603         return hr;
3604
3605     if (oldEncoding != encodingName && (!oldEncoding || !encodingName || wcscmp(oldEncoding, encodingName))) {
3606         if (Frame* coreFrame = core(m_mainFrame))
3607             coreFrame->loader().reloadWithOverrideEncoding(toString(encodingName));
3608     }
3609
3610     return S_OK;
3611 }
3612
3613 HRESULT WebView::customTextEncodingName(_Deref_opt_out_ BSTR* encodingName)
3614 {
3615     if (!encodingName)
3616         return E_POINTER;
3617
3618     HRESULT hr = S_OK;
3619     COMPtr<IWebDataSource> dataSource;
3620     COMPtr<WebDataSource> dataSourceImpl;
3621     *encodingName = nullptr;
3622
3623     if (!m_mainFrame)
3624         return E_UNEXPECTED;
3625
3626     if (FAILED(m_mainFrame->provisionalDataSource(&dataSource)) || !dataSource) {
3627         hr = m_mainFrame->dataSource(&dataSource);
3628         if (FAILED(hr) || !dataSource)
3629             return hr;
3630     }
3631
3632     hr = dataSource->QueryInterface(IID_WebDataSource, (void**)&dataSourceImpl);
3633     if (FAILED(hr))
3634         return hr;
3635
3636     BString str = dataSourceImpl->documentLoader()->overrideEncoding();
3637     if (FAILED(hr))
3638         return hr;
3639
3640     if (!*encodingName)
3641         *encodingName = BString(m_overrideEncoding).release();
3642
3643     if (!*encodingName && m_overrideEncoding.length())
3644         return E_OUTOFMEMORY;
3645
3646     return S_OK;
3647 }
3648
3649 HRESULT WebView::setMediaStyle(_In_ BSTR /*media*/)
3650 {
3651     ASSERT_NOT_REACHED();
3652     return E_NOTIMPL;
3653 }
3654
3655 HRESULT WebView::mediaStyle(_Deref_opt_out_ BSTR* /*media*/)
3656 {
3657     ASSERT_NOT_REACHED();
3658     return E_NOTIMPL;
3659 }
3660
3661 HRESULT WebView::stringByEvaluatingJavaScriptFromString(_In_ BSTR script, // assumes input does not have "JavaScript" at the begining.
3662     _Deref_opt_out_ BSTR* result)
3663 {
3664     if (!result) {
3665         ASSERT_NOT_REACHED();
3666         return E_POINTER;
3667     }
3668
3669     *result = nullptr;
3670
3671     Frame* coreFrame = core(m_mainFrame);
3672     if (!coreFrame)
3673         return E_UNEXPECTED;
3674
3675     auto scriptExecutionResult = coreFrame->script().executeScript(WTF::String(script), true);
3676     if (!scriptExecutionResult)
3677         return E_FAIL;
3678     else if (scriptExecutionResult.isString()) {
3679         JSC::ExecState* exec = coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec();
3680         JSC::JSLockHolder lock(exec);
3681         *result = BString(scriptExecutionResult.getString(exec));
3682     }
3683
3684     return S_OK;
3685 }
3686
3687 HRESULT WebView::windowScriptObject(_COM_Outptr_opt_ IWebScriptObject** webScriptObject)
3688 {
3689     ASSERT_NOT_REACHED();
3690     if (!webScriptObject)
3691         return E_POINTER;
3692     *webScriptObject = nullptr;
3693     return E_NOTIMPL;
3694 }
3695
3696 HRESULT WebView::setPreferences(_In_opt_ IWebPreferences* prefs)
3697 {
3698     if (!prefs)
3699         prefs = WebPreferences::sharedStandardPreferences();
3700
3701     if (m_preferences == prefs)
3702         return S_OK;
3703
3704     COMPtr<WebPreferences> webPrefs(Query, prefs);
3705     if (!webPrefs)
3706         return E_NOINTERFACE;
3707     webPrefs->willAddToWebView();
3708
3709     COMPtr<WebPreferences> oldPrefs = m_preferences;
3710
3711     IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
3712     nc->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3713
3714     BString identifier;
3715     oldPrefs->identifier(&identifier);
3716     oldPrefs->didRemoveFromWebView();
3717     oldPrefs = 0; // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
3718
3719     m_preferences = webPrefs;
3720
3721     if (identifier)
3722         WebPreferences::removeReferenceForIdentifier(identifier);
3723
3724     nc->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3725
3726     m_preferences->postPreferencesChangesNotification();
3727
3728     return S_OK;
3729 }
3730
3731 HRESULT WebView::preferences(_COM_Outptr_opt_ IWebPreferences** prefs)
3732 {
3733     if (!prefs)
3734         return E_POINTER;
3735     *prefs = m_preferences.get();
3736     if (m_preferences)
3737         m_preferences->AddRef();
3738     return S_OK;
3739 }
3740
3741 HRESULT WebView::setPreferencesIdentifier(_In_ BSTR /*anIdentifier*/)
3742 {
3743     ASSERT_NOT_REACHED();
3744     return E_NOTIMPL;
3745 }
3746
3747 HRESULT WebView::preferencesIdentifier(_Deref_opt_out_ BSTR* /*anIdentifier*/)
3748 {
3749     ASSERT_NOT_REACHED();
3750     return E_NOTIMPL;
3751 }
3752
3753 static void systemParameterChanged(WPARAM parameter)
3754 {
3755 #if USE(CG)
3756     if (parameter == SPI_SETFONTSMOOTHING || parameter == SPI_SETFONTSMOOTHINGTYPE || parameter == SPI_SETFONTSMOOTHINGCONTRAST || parameter == SPI_SETFONTSMOOTHINGORIENTATION)
3757         wkSystemFontSmoothingChanged();
3758 #endif
3759 }
3760
3761 void WebView::windowReceivedMessage(HWND, UINT message, WPARAM wParam, LPARAM)
3762 {
3763     switch (message) {
3764     case WM_NCACTIVATE:
3765         updateActiveStateSoon();
3766         if (!wParam)
3767             deleteBackingStoreSoon();
3768         break;
3769     case WM_SETTINGCHANGE:
3770         systemParameterChanged(wParam);
3771         break;
3772     }
3773 }
3774
3775 void WebView::updateActiveStateSoon() const
3776 {
3777     // This function is called while processing the WM_NCACTIVATE message.
3778     // While processing WM_NCACTIVATE when we are being deactivated, GetActiveWindow() will
3779     // still return our window. If we were to call updateActiveState() in that case, we would
3780     // wrongly think that we are still the active window. To work around this, we update our
3781     // active state after a 0-delay timer fires, at which point GetActiveWindow() will return
3782     // the newly-activated window.
3783
3784     SetTimer(m_viewWindow, UpdateActiveStateTimer, 0, 0);
3785 }
3786
3787 void WebView::deleteBackingStoreSoon()
3788 {
3789     if (pendingDeleteBackingStoreSet().size() > 2) {
3790         Vector<WebView*> views;
3791         HashSet<WebView*>::iterator end = pendingDeleteBackingStoreSet().end();
3792         for (HashSet<WebView*>::iterator it = pendingDeleteBackingStoreSet().begin(); it != end; ++it)
3793             views.append(*it);
3794         for (int i = 0; i < views.size(); ++i)
3795             views[i]->deleteBackingStore();
3796         ASSERT(pendingDeleteBackingStoreSet().isEmpty());
3797     }
3798
3799     pendingDeleteBackingStoreSet().add(this);
3800     m_deleteBackingStoreTimerActive = true;
3801     SetTimer(m_viewWindow, DeleteBackingStoreTimer, delayBeforeDeletingBackingStoreMsec, 0);
3802 }
3803
3804 void WebView::cancelDeleteBackingStoreSoon()
3805 {
3806     if (!m_deleteBackingStoreTimerActive)
3807         return;
3808     pendingDeleteBackingStoreSet().remove(this);
3809     m_deleteBackingStoreTimerActive = false;
3810     KillTimer(m_viewWindow, DeleteBackingStoreTimer);
3811 }
3812
3813 HRESULT WebView::setHostWindow(_In_ HWND window)
3814 {
3815     if (m_viewWindow) {
3816         if (window)
3817             SetParent(m_viewWindow, window);
3818         else if (!isBeingDestroyed()) {
3819             // Turn the WebView into a message-only window so it will no longer be a child of the
3820             // old host window and will be hidden from screen. We only do this when
3821             // isBeingDestroyed() is false because doing this while handling WM_DESTROY can leave
3822             // m_viewWindow in a weird state (see <http://webkit.org/b/29337>).
3823             SetParent(m_viewWindow, HWND_MESSAGE);
3824         }
3825     }
3826
3827     m_hostWindow = window;
3828
3829     windowAncestryDidChange();
3830
3831     if (m_page)
3832         m_page->setDeviceScaleFactor(deviceScaleFactor());
3833
3834     return S_OK;
3835 }
3836
3837 HRESULT WebView::hostWindow(_Deref_opt_out_ HWND* window)
3838 {
3839     if (!window)
3840         return E_POINTER;
3841
3842     *window = m_hostWindow;
3843     return S_OK;
3844 }
3845
3846
3847 static Frame *incrementFrame(Frame *curr, bool forward, bool wrapFlag)
3848 {
3849     return forward
3850         ? curr->tree().traverseNextWithWrap(wrapFlag)
3851         : curr->tree().traversePreviousWithWrap(wrapFlag);
3852 }
3853
3854 HRESULT WebView::searchFor(_In_ BSTR str, BOOL forward, BOOL caseFlag, BOOL wrapFlag, _Out_ BOOL* found)
3855 {
3856     if (!found)
3857         return E_INVALIDARG;
3858     
3859     if (!m_page)
3860         return E_FAIL;
3861
3862     if (!str || !SysStringLen(str))
3863         return E_INVALIDARG;
3864
3865     FindOptions options = (caseFlag ? 0 : CaseInsensitive) | (forward ? 0 : Backwards) | (wrapFlag ? WrapAround : 0);
3866     *found = m_page->findString(toString(str), options);
3867     return S_OK;
3868 }
3869
3870 bool WebView::active()
3871 {
3872     HWND activeWindow = GetActiveWindow();
3873     if (usesLayeredWindow() && activeWindow == m_viewWindow)
3874         return true;
3875
3876     return (activeWindow && m_topLevelParent == findTopLevelParent(activeWindow));
3877 }
3878
3879 void WebView::updateActiveState()
3880 {
3881     if (m_page)
3882         m_page->focusController().setActive(active());
3883 }
3884
3885 HRESULT WebView::updateFocusedAndActiveState()
3886 {
3887     updateActiveState();
3888
3889     bool active = m_page->focusController().isActive();
3890     Frame& mainFrame = m_page->mainFrame();
3891     Frame& focusedFrame = m_page->focusController().focusedOrMainFrame();
3892     mainFrame.selection().setFocused(active && &mainFrame == &focusedFrame);
3893
3894     return S_OK;
3895 }
3896
3897 HRESULT WebView::executeCoreCommandByName(_In_ BSTR name, _In_ BSTR value)
3898 {
3899     if (!m_page)
3900         return E_FAIL;
3901
3902     m_page->focusController().focusedOrMainFrame().editor().command(toString(name)).execute(toString(value));
3903
3904     return S_OK;
3905 }
3906
3907 HRESULT WebView::clearMainFrameName()
3908 {
3909     if (!m_page)
3910         return E_FAIL;
3911
3912     m_page->mainFrame().tree().clearName();
3913
3914     return S_OK;
3915 }
3916
3917 HRESULT WebView::markAllMatchesForText(_In_ BSTR str, BOOL caseSensitive, BOOL highlight, UINT limit, _Out_ UINT* matches)
3918 {
3919     if (!matches)
3920         return E_INVALIDARG;
3921
3922     if (!m_page)
3923         return E_FAIL;
3924
3925     if (!str || !SysStringLen(str))
3926         return E_INVALIDARG;
3927
3928     *matches = m_page->markAllMatchesForText(toString(str), caseSensitive ? TextCaseSensitive : TextCaseInsensitive, highlight, limit);
3929     return S_OK;
3930 }
3931
3932 HRESULT WebView::unmarkAllTextMatches()
3933 {
3934     if (!m_page)
3935         return E_FAIL;
3936
3937     m_page->unmarkAllTextMatches();
3938     return S_OK;
3939 }
3940
3941 HRESULT WebView::rectsForTextMatches(_COM_Outptr_opt_ IEnumTextMatches** pmatches)
3942 {
3943     if (!pmatches)
3944         return E_POINTER;
3945     *pmatches = nullptr;
3946     if (!m_page)
3947         return E_FAIL;
3948
3949     Vector<IntRect> allRects;
3950     WebCore::Frame* frame = &m_page->mainFrame();
3951     do {
3952         if (Document* document = frame->document()) {
3953             IntRect visibleRect = frame->view()->visibleContentRect();
3954             Vector<FloatRect> frameRects = document->markers().renderedRectsForMarkers(DocumentMarker::TextMatch);
3955             IntPoint frameOffset = -frame->view()->scrollPosition();
3956             frameOffset = frame->view()->convertToContainingWindow(frameOffset);
3957
3958             Vector<FloatRect>::iterator end = frameRects.end();
3959             for (Vector<FloatRect>::iterator it = frameRects.begin(); it < end; it++) {
3960                 it->intersect(visibleRect);
3961                 it->move(frameOffset.x(), frameOffset.y());
3962                 allRects.append(enclosingIntRect(*it));
3963             }
3964         }
3965         frame = incrementFrame(frame, true, false);
3966     } while (frame);
3967
3968     return createMatchEnumerator(&allRects, pmatches);
3969 }
3970
3971 HRESULT WebView::generateSelectionImage(BOOL forceWhiteText, _Deref_opt_out_ HBITMAP* hBitmap)
3972 {
3973     if (!hBitmap)
3974         return E_POINTER;
3975
3976     if (!m_page)
3977         return E_FAIL;
3978
3979     *hBitmap = nullptr;
3980
3981     WebCore::Frame& frame = m_page->focusController().focusedOrMainFrame();
3982
3983     auto bitmap = imageFromSelection(&frame, forceWhiteText ? TRUE : FALSE);
3984     *hBitmap = bitmap.leak();
3985
3986     return S_OK;
3987 }
3988
3989 HRESULT WebView::selectionRect(_Inout_ RECT* rc)
3990 {
3991     if (!rc)
3992         return E_POINTER;
3993
3994     if (!m_page)
3995         return E_FAIL;
3996
3997     WebCore::Frame& frame = m_page->focusController().focusedOrMainFrame();
3998
3999     IntRect ir = enclosingIntRect(frame.selection().selectionBounds());
4000     ir = frame.view()->convertToContainingWindow(ir);
4001     ir.moveBy(-frame.view()->scrollPosition());
4002
4003     float scaleFactor = deviceScaleFactor();
4004     rc->left = ir.x() * scaleFactor;
4005     rc->top = ir.y() * scaleFactor;
4006     rc->bottom = rc->top + ir.height() * scaleFactor;
4007     rc->right = rc->left + ir.width() * scaleFactor;
4008
4009     return S_OK;
4010 }
4011
4012 HRESULT WebView::registerViewClass(_In_opt_ IWebDocumentView*, _In_opt_ IWebDocumentRepresentation*, _In_ BSTR /*forMIMEType*/)
4013 {
4014     ASSERT_NOT_REACHED();
4015     return E_NOTIMPL;
4016 }
4017
4018 HRESULT WebView::setGroupName(_In_ BSTR groupName)
4019 {
4020     if (m_webViewGroup)
4021         m_webViewGroup->removeWebView(this);
4022
4023     m_webViewGroup = WebViewGroup::getOrCreate(groupName, localStorageDatabasePath(m_preferences.get()));
4024     m_webViewGroup->addWebView(this);
4025
4026     if (!m_page)
4027         return S_OK;
4028
4029     m_page->setUserContentProvider(m_webViewGroup->userContentController());
4030     m_page->setVisitedLinkStore(m_webViewGroup->visitedLinkStore());
4031     m_page->setGroupName(toString(groupName));
4032     return S_OK;
4033 }
4034     
4035 HRESULT WebView::groupName(_Deref_opt_out_ BSTR* groupName)
4036 {
4037     if (!groupName)
4038         return E_POINTER;
4039
4040     *groupName = nullptr;
4041     if (!m_page)
4042         return S_OK;
4043     String groupNameString = m_page->groupName();
4044     *groupName = BString(groupNameString).release();
4045     if (!*groupName && groupNameString.length())
4046         return E_OUTOFMEMORY;
4047     return S_OK;
4048 }
4049     
4050 HRESULT WebView::estimatedProgress(_Out_ double* estimatedProgress)
4051 {
4052     if (!estimatedProgress)
4053         return E_POINTER;
4054     *estimatedProgress = m_page->progress().estimatedProgress();
4055     return S_OK;
4056 }
4057     
4058 HRESULT WebView::isLoading(_Out_ BOOL* isLoading)
4059 {
4060     COMPtr<IWebDataSource> dataSource;
4061     COMPtr<IWebDataSource> provisionalDataSource;
4062
4063     if (!isLoading)
4064         return E_POINTER;
4065
4066     *isLoading = FALSE;
4067
4068     if (!m_mainFrame)
4069         return E_UNEXPECTED;
4070
4071     if (SUCCEEDED(m_mainFrame->dataSource(&dataSource)))
4072         dataSource->isLoading(isLoading);
4073
4074     if (*isLoading)
4075         return S_OK;
4076
4077     if (SUCCEEDED(m_mainFrame->provisionalDataSource(&provisionalDataSource)))
4078         provisionalDataSource->isLoading(isLoading);
4079     return S_OK;
4080 }
4081     
4082 HRESULT WebView::elementAtPoint(_In_ LPPOINT point, _COM_Outptr_opt_ IPropertyBag** elementDictionary)
4083 {
4084     if (!elementDictionary || !point) {
4085         ASSERT_NOT_REACHED();
4086         return E_POINTER;
4087     }
4088
4089     *elementDictionary = nullptr;
4090
4091     Frame* frame = core(m_mainFrame);
4092     if (!frame)
4093         return E_UNEXPECTED;
4094
4095     IntPoint webCorePoint = IntPoint(point->x, point->y);
4096     float inverseScaleFactor = 1.0f / deviceScaleFactor();
4097     webCorePoint.scale(inverseScaleFactor, inverseScaleFactor);
4098     HitTestResult result = HitTestResult(webCorePoint);
4099     if (frame->contentRenderer())
4100         result = frame->eventHandler().hitTestResultAtPoint(webCorePoint);
4101     *elementDictionary = WebElementPropertyBag::createInstance(result);
4102     return S_OK;
4103 }
4104     
4105 HRESULT WebView::pasteboardTypesForSelection(_COM_Outptr_opt_ IEnumVARIANT** enumVariant)
4106 {
4107     ASSERT_NOT_REACHED();
4108     if (!enumVariant)
4109         return E_POINTER;
4110     *enumVariant = nullptr;
4111     return E_NOTIMPL;
4112 }
4113     
4114 HRESULT WebView::writeSelectionWithPasteboardTypes(__inout_ecount_full(cTypes) BSTR* types, int cTypes, _In_opt_ IDataObject* /*pasteboard*/)
4115 {
4116     ASSERT_NOT_REACHED();
4117     return E_NOTIMPL;
4118 }
4119     
4120 HRESULT WebView::pasteboardTypesForElement(_In_opt_ IPropertyBag* /*elementDictionary*/, _COM_Outptr_opt_ IEnumVARIANT** enumVariant)
4121 {
4122     ASSERT_NOT_REACHED();
4123     if (!enumVariant)
4124         return E_POINTER;
4125     *enumVariant = nullptr;
4126     return E_NOTIMPL;
4127 }
4128     
4129 HRESULT WebView::writeElement(_In_opt_ IPropertyBag* /*elementDictionary*/, __inout_ecount_full(cWithPasteboardTypes) BSTR* withPasteboardTypes, int cWithPasteboardTypes, _In_opt_ IDataObject* /*pasteboard*/)
4130 {
4131     ASSERT_NOT_REACHED();
4132     return E_NOTIMPL;
4133 }
4134     
4135 HRESULT WebView::selectedText(_Deref_opt_out_ BSTR* text)
4136 {
4137     if (!text) {
4138         ASSERT_NOT_REACHED();
4139         return E_POINTER;
4140     }
4141
4142     *text = nullptr;
4143
4144     Frame* focusedFrame = m_page ? &m_page->focusController().focusedOrMainFrame() : 0;
4145     if (!focusedFrame)
4146         return E_FAIL;
4147
4148     String frameSelectedText = focusedFrame->editor().selectedText();
4149     *text = BString(frameSelectedText).release();
4150     if (!*text && frameSelectedText.length())
4151         return E_OUTOFMEMORY;
4152     return S_OK;
4153 }
4154
4155 HRESULT WebView::centerSelectionInVisibleArea(_In_opt_ IUnknown* /* sender */)
4156 {
4157     Frame* coreFrame = core(m_mainFrame);
4158     if (!coreFrame)
4159         return E_UNEXPECTED;
4160
4161     coreFrame->selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignCenterAlways);
4162     return S_OK;
4163 }
4164
4165
4166 HRESULT WebView::moveDragCaretToPoint(_In_ LPPOINT /*point*/)
4167 {
4168     ASSERT_NOT_REACHED();
4169     return E_NOTIMPL;
4170 }
4171     
4172 HRESULT WebView::removeDragCaret()
4173 {
4174     ASSERT_NOT_REACHED();
4175     return E_NOTIMPL;
4176 }
4177     
4178 HRESULT WebView::setDrawsBackground(BOOL /*drawsBackground*/)
4179 {
4180     ASSERT_NOT_REACHED();
4181     return E_NOTIMPL;
4182 }
4183     
4184 HRESULT WebView::drawsBackground(_Out_ BOOL* /*drawsBackground*/)
4185 {
4186     ASSERT_NOT_REACHED();
4187     return E_NOTIMPL;
4188 }
4189     
4190 HRESULT WebView::setMainFrameURL(_In_ BSTR /*urlString*/)
4191 {
4192     ASSERT_NOT_REACHED();
4193     return E_NOTIMPL;
4194 }
4195     
4196 HRESULT WebView::mainFrameURL(_Deref_opt_out_ BSTR* urlString)
4197 {
4198     if (!urlString)
4199         return E_POINTER;
4200
4201     if (!m_mainFrame)
4202         return E_UNEXPECTED;
4203
4204     COMPtr<IWebDataSource> dataSource;
4205
4206     if (FAILED(m_mainFrame->provisionalDataSource(&dataSource))) {
4207         if (FAILED(m_mainFrame->dataSource(&dataSource)))
4208             return E_FAIL;
4209     }
4210
4211     if (!dataSource) {
4212         *urlString = nullptr;
4213         return S_OK;
4214     }
4215     
4216     COMPtr<IWebMutableURLRequest> request;
4217     if (FAILED(dataSource->request(&request)) || !request)
4218         return E_FAIL;
4219
4220     if (FAILED(request->URL(urlString)))
4221         return E_FAIL;
4222
4223     return S_OK;
4224 }
4225     
4226 HRESULT WebView::mainFrameDocument(_COM_Outptr_opt_ IDOMDocument** document)
4227 {
4228     if (!document)
4229         return E_POINTER;
4230
4231     *document = nullptr;
4232
4233     if (!m_mainFrame)
4234         return E_UNEXPECTED;
4235     return m_mainFrame->DOMDocument(document);
4236 }
4237     
4238 HRESULT WebView::mainFrameTitle(_Deref_opt_out_ BSTR* /*title*/)
4239 {
4240     ASSERT_NOT_REACHED();
4241     return E_NOTIMPL;
4242 }
4243     
4244 HRESULT WebView::mainFrameIcon(_Deref_opt_out_ HBITMAP* /*hBitmap*/)
4245 {
4246     ASSERT_NOT_REACHED();
4247     return E_NOTIMPL;
4248 }
4249
4250 HRESULT WebView::registerURLSchemeAsLocal(_In_ BSTR scheme)
4251 {
4252     if (!scheme)
4253         return E_POINTER;
4254
4255     SchemeRegistry::registerURLSchemeAsLocal(toString(scheme));
4256
4257     return S_OK;
4258 }
4259
4260 // IWebIBActions ---------------------------------------------------------------
4261
4262 HRESULT WebView::takeStringURLFrom(_In_opt_ IUnknown* /*sender*/)
4263 {
4264     ASSERT_NOT_REACHED();
4265     return E_NOTIMPL;
4266 }
4267     
4268 HRESULT WebView::stopLoading(_In_opt_ IUnknown* /*sender*/)
4269 {
4270     if (!m_mainFrame)
4271         return E_UNEXPECTED;
4272
4273     return m_mainFrame->stopLoading();
4274 }
4275     
4276 HRESULT WebView::reload(_In_opt_ IUnknown* /*sender*/)
4277 {
4278     if (!m_mainFrame)
4279         return E_UNEXPECTED;
4280
4281     return m_mainFrame->reload();
4282 }