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