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