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