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