Remove PassRefPtr from "page" directory of WebCore, also deploy references
[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/MemoryRelease.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         auto& memoryPressureHandler = MemoryPressureHandler::singleton();
3088         memoryPressureHandler.setLowMemoryHandler([] (Critical critical, Synchronous synchronous) {
3089             WebCore::releaseMemory(critical, synchronous);
3090         });
3091         memoryPressureHandler.install();
3092
3093         didOneTimeInitialization = true;
3094      }
3095
3096     BOOL useHighResolutionTimer;
3097     if (SUCCEEDED(m_preferences->shouldUseHighResolutionTimers(&useHighResolutionTimer)))
3098         Settings::setShouldUseHighResolutionTimers(useHighResolutionTimer);
3099
3100     m_inspectorClient = new WebInspectorClient(this);
3101
3102     PageConfiguration configuration(makeUniqueRef<WebEditorClient>(this), SocketProvider::create());
3103     configuration.backForwardClient = BackForwardList::create();
3104     configuration.chromeClient = new WebChromeClient(this);
3105     configuration.contextMenuClient = new WebContextMenuClient(this);
3106     configuration.dragClient = new WebDragClient(this);
3107     configuration.inspectorClient = m_inspectorClient;
3108     configuration.loaderClientForMainFrame = new WebFrameLoaderClient;
3109     configuration.applicationCacheStorage = &WebApplicationCache::storage();
3110     configuration.databaseProvider = &WebDatabaseProvider::singleton();
3111     configuration.storageNamespaceProvider = &m_webViewGroup->storageNamespaceProvider();
3112     configuration.progressTrackerClient = static_cast<WebFrameLoaderClient*>(configuration.loaderClientForMainFrame);
3113     configuration.userContentProvider = &m_webViewGroup->userContentController();
3114     configuration.visitedLinkStore = &m_webViewGroup->visitedLinkStore();
3115     configuration.pluginInfoProvider = &WebPluginInfoProvider::singleton();
3116
3117     m_page = new Page(WTFMove(configuration));
3118     provideGeolocationTo(m_page, new WebGeolocationClient(this));
3119
3120     unsigned layoutMilestones = DidFirstLayout | DidFirstVisuallyNonEmptyLayout;
3121     m_page->addLayoutMilestones(static_cast<LayoutMilestones>(layoutMilestones));
3122
3123
3124     if (m_uiDelegate) {
3125         BString path;
3126         if (SUCCEEDED(m_uiDelegate->ftpDirectoryTemplatePath(this, &path)))
3127             m_page->settings().setFTPDirectoryTemplatePath(toString(path));
3128     }
3129
3130     WebFrame* webFrame = WebFrame::createInstance();
3131     webFrame->initWithWebView(this, m_page);
3132     static_cast<WebFrameLoaderClient&>(m_page->mainFrame().loader().client()).setWebFrame(webFrame);
3133     m_mainFrame = webFrame;
3134     webFrame->Release(); // The WebFrame is owned by the Frame, so release our reference to it.
3135
3136     m_page->mainFrame().tree().setName(toString(frameName));
3137     m_page->mainFrame().init();
3138     setGroupName(groupName);
3139
3140     addToAllWebViewsSet();
3141
3142     #pragma warning(suppress: 4244)
3143     SetWindowLongPtr(m_viewWindow, 0, (LONG_PTR)this);
3144     ShowWindow(m_viewWindow, SW_SHOW);
3145
3146     initializeToolTipWindow();
3147     windowAncestryDidChange();
3148
3149     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
3150     notifyCenter->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3151     m_preferences->postPreferencesChangesNotification();
3152
3153     m_page->setDeviceScaleFactor(deviceScaleFactor());
3154
3155     setSmartInsertDeleteEnabled(TRUE);
3156
3157     return hr;
3158 }
3159
3160 static bool initCommonControls()
3161 {
3162     static bool haveInitialized = false;
3163     if (haveInitialized)
3164         return true;
3165
3166     INITCOMMONCONTROLSEX init;
3167     init.dwSize = sizeof(init);
3168     init.dwICC = ICC_TREEVIEW_CLASSES;
3169     haveInitialized = !!::InitCommonControlsEx(&init);
3170     return haveInitialized;
3171 }
3172
3173 void WebView::initializeToolTipWindow()
3174 {
3175     if (!initCommonControls())
3176         return;
3177
3178     m_toolTipHwnd = CreateWindowEx(WS_EX_TRANSPARENT, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
3179                                    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
3180                                    m_viewWindow, 0, 0, 0);
3181     if (!m_toolTipHwnd)
3182         return;
3183
3184     TOOLINFO info = {0};
3185     info.cbSize = sizeof(info);
3186     info.uFlags = TTF_IDISHWND | TTF_SUBCLASS ;
3187     info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
3188
3189     ::SendMessage(m_toolTipHwnd, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info));
3190     ::SendMessage(m_toolTipHwnd, TTM_SETMAXTIPWIDTH, 0, clampTo<int>(maxToolTipWidth * deviceScaleFactor()));
3191
3192     ::SetWindowPos(m_toolTipHwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
3193 }
3194
3195 void WebView::setToolTip(const String& toolTip)
3196 {
3197     if (!m_toolTipHwnd)
3198         return;
3199
3200     if (toolTip == m_toolTip)
3201         return;
3202
3203     m_toolTip = toolTip;
3204
3205     if (!m_toolTip.isEmpty()) {
3206         TOOLINFO info = {0};
3207         info.cbSize = sizeof(info);
3208         info.uFlags = TTF_IDISHWND;
3209         info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
3210         Vector<UChar> toolTipCharacters = m_toolTip.charactersWithNullTermination(); // Retain buffer long enough to make the SendMessage call
3211         info.lpszText = const_cast<UChar*>(toolTipCharacters.data());
3212         ::SendMessage(m_toolTipHwnd, TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info));
3213     }
3214
3215     ::SendMessage(m_toolTipHwnd, TTM_ACTIVATE, !m_toolTip.isEmpty(), 0);
3216 }
3217
3218 HRESULT WebView::notifyDidAddIcon(IWebNotification* notification)
3219 {
3220     COMPtr<IPropertyBag> propertyBag;
3221     HRESULT hr = notification->userInfo(&propertyBag);
3222     if (FAILED(hr))
3223         return hr;
3224     if (!propertyBag)
3225         return E_FAIL;
3226
3227     COMVariant iconUserInfoURL;
3228     hr = propertyBag->Read(WebIconDatabase::iconDatabaseNotificationUserInfoURLKey(), &iconUserInfoURL, nullptr);
3229     if (FAILED(hr))
3230         return hr;
3231
3232     if (iconUserInfoURL.variantType() != VT_BSTR)
3233         return E_FAIL;
3234
3235     String mainFrameURL;
3236     if (m_mainFrame)
3237         mainFrameURL = m_mainFrame->url().string();
3238
3239     if (!mainFrameURL.isEmpty() && mainFrameURL == toString(V_BSTR(&iconUserInfoURL)))
3240         dispatchDidReceiveIconFromWebFrame(m_mainFrame);
3241
3242     return hr;
3243 }
3244
3245 void WebView::registerForIconNotification(bool listen)
3246 {
3247     IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
3248     if (listen)
3249         nc->addObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
3250     else
3251         nc->removeObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
3252 }
3253
3254 void WebView::dispatchDidReceiveIconFromWebFrame(WebFrame* frame)
3255 {
3256     registerForIconNotification(false);
3257
3258     if (m_frameLoadDelegate) {
3259         String str = frame->url().string();
3260
3261         IntSize sz(16, 16);
3262
3263         BitmapInfo bmInfo = BitmapInfo::create(sz);
3264
3265         HBITMAP hBitmap = nullptr;
3266
3267         Image* icon = iconDatabase().synchronousIconForPageURL(str, sz);
3268
3269         if (icon && icon->width()) {
3270             HWndDC dc(0);
3271             hBitmap = CreateDIBSection(dc, &bmInfo, DIB_RGB_COLORS, 0, 0, 0);
3272             icon->getHBITMAPOfSize(hBitmap, &sz);
3273         }
3274
3275         HRESULT hr = m_frameLoadDelegate->didReceiveIcon(this, hBitmap, frame);
3276         if ((hr == E_NOTIMPL) && hBitmap)
3277             DeleteObject(hBitmap);
3278     }
3279 }
3280
3281 HRESULT WebView::setAccessibilityDelegate(_In_opt_ IAccessibilityDelegate* d)
3282 {
3283     m_accessibilityDelegate = d;
3284     return S_OK;
3285 }
3286
3287 HRESULT WebView::accessibilityDelegate(_COM_Outptr_opt_ IAccessibilityDelegate** d)
3288 {
3289     if (!d)
3290         return E_POINTER;
3291     *d = nullptr;
3292     if (!m_accessibilityDelegate)
3293         return E_POINTER;
3294
3295     return m_accessibilityDelegate.copyRefTo(d);
3296 }
3297
3298 HRESULT WebView::setUIDelegate(_In_opt_ IWebUIDelegate* d)
3299 {
3300     m_uiDelegate = d;
3301
3302     if (m_uiDelegatePrivate)
3303         m_uiDelegatePrivate = 0;
3304
3305     if (d) {
3306         if (FAILED(d->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&m_uiDelegatePrivate)))
3307             m_uiDelegatePrivate = 0;
3308     }
3309
3310     return S_OK;
3311 }
3312
3313 HRESULT WebView::uiDelegate(_COM_Outptr_opt_ IWebUIDelegate** d)
3314 {
3315     if (!d)
3316         return E_POINTER;
3317     *d = nullptr;
3318     if (!m_uiDelegate)
3319         return E_FAIL;
3320
3321     return m_uiDelegate.copyRefTo(d);
3322 }
3323
3324 HRESULT WebView::setResourceLoadDelegate(_In_opt_ IWebResourceLoadDelegate* d)
3325 {
3326     m_resourceLoadDelegate = d;
3327     return S_OK;
3328 }
3329
3330 HRESULT WebView::resourceLoadDelegate(_COM_Outptr_opt_ IWebResourceLoadDelegate** d)
3331 {
3332     if (!d)
3333         return E_POINTER;
3334     *d = nullptr;
3335     if (!m_resourceLoadDelegate)
3336         return E_FAIL;
3337
3338     return m_resourceLoadDelegate.copyRefTo(d);
3339 }
3340
3341 HRESULT WebView::setDownloadDelegate(_In_opt_ IWebDownloadDelegate* d)
3342 {
3343     m_downloadDelegate = d;
3344     return S_OK;
3345 }
3346
3347 HRESULT WebView::downloadDelegate(_COM_Outptr_opt_ IWebDownloadDelegate** d)
3348 {
3349     if (!d)
3350         return E_POINTER;
3351     *d = nullptr;
3352     if (!m_downloadDelegate)
3353         return E_FAIL;
3354
3355     return m_downloadDelegate.copyRefTo(d);
3356 }
3357
3358 HRESULT WebView::setFrameLoadDelegate(_In_opt_ IWebFrameLoadDelegate* d)
3359 {
3360     m_frameLoadDelegate = d;
3361     return S_OK;
3362 }
3363
3364 HRESULT WebView::frameLoadDelegate(_COM_Outptr_opt_ IWebFrameLoadDelegate** d)
3365 {
3366     if (!d)
3367         return E_POINTER;
3368     *d = nullptr;
3369     if (!m_frameLoadDelegate)
3370         return E_FAIL;
3371
3372     return m_frameLoadDelegate.copyRefTo(d);
3373 }
3374
3375 HRESULT WebView::setPolicyDelegate(_In_opt_ IWebPolicyDelegate* d)
3376 {
3377     m_policyDelegate = d;
3378     return S_OK;
3379 }
3380
3381 HRESULT WebView::policyDelegate(_COM_Outptr_opt_ IWebPolicyDelegate** d)
3382 {
3383     if (!d)
3384         return E_POINTER;
3385     *d = nullptr;
3386     if (!m_policyDelegate)
3387         return E_FAIL;
3388
3389     return m_policyDelegate.copyRefTo(d);
3390 }
3391
3392 HRESULT WebView::mainFrame(_COM_Outptr_opt_ IWebFrame** frame)
3393 {
3394     if (!frame) {
3395         ASSERT_NOT_REACHED();
3396         return E_POINTER;
3397     }
3398
3399     *frame = m_mainFrame;
3400     if (!m_mainFrame)
3401         return E_UNEXPECTED;
3402
3403     m_mainFrame->AddRef();
3404     return S_OK;
3405 }
3406
3407 HRESULT WebView::focusedFrame(_COM_Outptr_opt_ IWebFrame** frame)
3408 {
3409     if (!frame) {
3410         ASSERT_NOT_REACHED();
3411         return E_POINTER;
3412     }
3413
3414     *frame = nullptr;
3415     Frame* f = m_page->focusController().focusedFrame();
3416     if (!f)
3417         return E_FAIL;
3418
3419     WebFrame* webFrame = kit(f);
3420     if (!webFrame)
3421         return E_UNEXPECTED;
3422
3423     return webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
3424 }
3425
3426 HRESULT WebView::backForwardList(_COM_Outptr_opt_ IWebBackForwardList** list)
3427 {
3428     if (!list) {
3429         ASSERT_NOT_REACHED();
3430         return E_POINTER;
3431     }
3432     *list = nullptr;
3433     if (!m_useBackForwardList)
3434         return E_FAIL;
3435  
3436     *list = WebBackForwardList::createInstance(static_cast<BackForwardList*>(m_page->backForward().client()));
3437
3438     return S_OK;
3439 }
3440
3441 HRESULT WebView::setMaintainsBackForwardList(BOOL flag)
3442 {
3443     m_useBackForwardList = !!flag;
3444     return S_OK;
3445 }
3446
3447 HRESULT WebView::goBack(_Out_ BOOL* succeeded)
3448 {
3449     if (!succeeded)
3450         return E_POINTER;
3451
3452     *succeeded = m_page->backForward().goBack();
3453     return S_OK;
3454 }
3455
3456 HRESULT WebView::goForward(_Out_ BOOL* succeeded)
3457 {
3458     if (!succeeded)
3459         return E_POINTER;
3460
3461     *succeeded = m_page->backForward().goForward();
3462     return S_OK;
3463 }
3464
3465 HRESULT WebView::goToBackForwardItem(_In_opt_ IWebHistoryItem* item, _Out_ BOOL* succeeded)
3466 {
3467     if (!item)
3468         return E_FAIL;
3469
3470     if (!succeeded)
3471         return E_POINTER;
3472
3473     *succeeded = FALSE;
3474
3475     COMPtr<WebHistoryItem> webHistoryItem;
3476     HRESULT hr = item->QueryInterface(&webHistoryItem);
3477     if (FAILED(hr))
3478         return hr;
3479
3480     m_page->goToItem(*webHistoryItem->historyItem(), FrameLoadType::IndexedBackForward);
3481     *succeeded = TRUE;
3482
3483     return S_OK;
3484 }
3485
3486 HRESULT WebView::setTextSizeMultiplier(float multiplier)
3487 {
3488     if (!m_mainFrame)
3489         return E_UNEXPECTED;
3490     setZoomMultiplier(multiplier, true);
3491     return S_OK;
3492 }
3493
3494 HRESULT WebView::setPageSizeMultiplier(float multiplier)
3495 {
3496     if (!m_mainFrame)
3497         return E_UNEXPECTED;
3498     setZoomMultiplier(multiplier, false);
3499     return S_OK;
3500 }
3501
3502 void WebView::setZoomMultiplier(float multiplier, bool isTextOnly)
3503 {
3504     m_zoomMultiplier = multiplier;
3505     m_zoomsTextOnly = isTextOnly;
3506
3507     if (Frame* coreFrame = core(m_mainFrame)) {
3508         if (m_zoomsTextOnly)
3509             coreFrame->setPageAndTextZoomFactors(1, multiplier);
3510         else
3511             coreFrame->setPageAndTextZoomFactors(multiplier, 1);
3512     }
3513 }
3514
3515 HRESULT WebView::textSizeMultiplier(_Out_ float* multiplier)
3516 {
3517     if (!multiplier)
3518         return E_POINTER;
3519
3520     *multiplier = zoomMultiplier(true);
3521     return S_OK;
3522 }
3523
3524 HRESULT WebView::pageSizeMultiplier(_Out_ float* multiplier)
3525 {
3526     if (!multiplier)
3527         return E_POINTER;
3528
3529     *multiplier = zoomMultiplier(false);
3530     return S_OK;
3531 }
3532
3533 float WebView::zoomMultiplier(bool isTextOnly)
3534 {
3535     if (isTextOnly != m_zoomsTextOnly)
3536         return 1.0f;
3537     return m_zoomMultiplier;
3538 }
3539
3540 HRESULT WebView::setApplicationNameForUserAgent(_In_ BSTR applicationName)
3541 {
3542     m_applicationName = toString(applicationName);
3543     m_userAgentStandard = String();
3544     return S_OK;
3545 }
3546
3547 HRESULT WebView::applicationNameForUserAgent(_Deref_opt_out_ BSTR* applicationName)
3548 {
3549     if (!applicationName)
3550         return E_POINTER;
3551
3552     *applicationName = BString(m_applicationName).release();
3553     if (!*applicationName && m_applicationName.length())
3554         return E_OUTOFMEMORY;
3555     return S_OK;
3556 }
3557
3558 HRESULT WebView::setCustomUserAgent(_In_ BSTR userAgentString)
3559 {
3560     m_userAgentOverridden = userAgentString;
3561     m_userAgentCustom = toString(userAgentString);
3562     return S_OK;
3563 }
3564
3565 HRESULT WebView::customUserAgent(_Deref_opt_out_ BSTR* userAgentString)
3566 {
3567     if (!userAgentString)
3568         return E_POINTER;
3569
3570     *userAgentString = nullptr;
3571     if (!m_userAgentOverridden)
3572         return S_OK;
3573     *userAgentString = BString(m_userAgentCustom).release();
3574     if (!*userAgentString && m_userAgentCustom.length())
3575         return E_OUTOFMEMORY;
3576     return S_OK;
3577 }
3578
3579 HRESULT WebView::userAgentForURL(_In_ BSTR url, _Deref_opt_out_ BSTR* userAgent)
3580 {
3581     if (!userAgent)
3582         return E_POINTER;
3583
3584     String userAgentString = userAgentForKURL(MarshallingHelpers::BSTRToKURL(url));
3585     *userAgent = BString(userAgentString).release();
3586     if (!*userAgent && userAgentString.length())
3587         return E_OUTOFMEMORY;
3588     return S_OK;
3589 }
3590
3591 HRESULT WebView::supportsTextEncoding(_Out_ BOOL* supports)
3592 {
3593     if (!supports)
3594         return E_POINTER;
3595
3596     *supports = TRUE;
3597     return S_OK;
3598 }
3599
3600 HRESULT WebView::setCustomTextEncodingName(_In_ BSTR encodingName)
3601 {
3602     if (!m_mainFrame)
3603         return E_UNEXPECTED;
3604
3605     HRESULT hr;
3606     BString oldEncoding;
3607     hr = customTextEncodingName(&oldEncoding);
3608     if (FAILED(hr))
3609         return hr;
3610
3611     if (oldEncoding != encodingName && (!oldEncoding || !encodingName || wcscmp(oldEncoding, encodingName))) {
3612         if (Frame* coreFrame = core(m_mainFrame))
3613             coreFrame->loader().reloadWithOverrideEncoding(toString(encodingName));
3614     }
3615
3616     return S_OK;
3617 }
3618
3619 HRESULT WebView::customTextEncodingName(_Deref_opt_out_ BSTR* encodingName)
3620 {
3621     if (!encodingName)
3622         return E_POINTER;
3623
3624     HRESULT hr = S_OK;
3625     COMPtr<IWebDataSource> dataSource;
3626     COMPtr<WebDataSource> dataSourceImpl;
3627     *encodingName = nullptr;
3628
3629     if (!m_mainFrame)
3630         return E_UNEXPECTED;
3631
3632     if (FAILED(m_mainFrame->provisionalDataSource(&dataSource)) || !dataSource) {
3633         hr = m_mainFrame->dataSource(&dataSource);
3634         if (FAILED(hr) || !dataSource)
3635             return hr;
3636     }
3637
3638     hr = dataSource->QueryInterface(IID_WebDataSource, (void**)&dataSourceImpl);
3639     if (FAILED(hr))
3640         return hr;
3641
3642     BString str = dataSourceImpl->documentLoader()->overrideEncoding();
3643     if (FAILED(hr))
3644         return hr;
3645
3646     if (!*encodingName)
3647         *encodingName = BString(m_overrideEncoding).release();
3648
3649     if (!*encodingName && m_overrideEncoding.length())
3650         return E_OUTOFMEMORY;
3651
3652     return S_OK;
3653 }
3654
3655 HRESULT WebView::setMediaStyle(_In_ BSTR /*media*/)
3656 {
3657     ASSERT_NOT_REACHED();
3658     return E_NOTIMPL;
3659 }
3660
3661 HRESULT WebView::mediaStyle(_Deref_opt_out_ BSTR* /*media*/)
3662 {
3663     ASSERT_NOT_REACHED();
3664     return E_NOTIMPL;
3665 }
3666
3667 HRESULT WebView::stringByEvaluatingJavaScriptFromString(_In_ BSTR script, // assumes input does not have "JavaScript" at the begining.
3668     _Deref_opt_out_ BSTR* result)
3669 {
3670     if (!result) {
3671         ASSERT_NOT_REACHED();
3672         return E_POINTER;
3673     }
3674
3675     *result = nullptr;
3676
3677     Frame* coreFrame = core(m_mainFrame);
3678     if (!coreFrame)
3679         return E_UNEXPECTED;
3680
3681     auto scriptExecutionResult = coreFrame->script().executeScript(WTF::String(script), true);
3682     if (!scriptExecutionResult)
3683         return E_FAIL;
3684     else if (scriptExecutionResult.isString()) {
3685         JSC::ExecState* exec = coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec();
3686         JSC::JSLockHolder lock(exec);
3687         *result = BString(scriptExecutionResult.getString(exec));
3688     }
3689
3690     return S_OK;
3691 }
3692
3693 HRESULT WebView::windowScriptObject(_COM_Outptr_opt_ IWebScriptObject** webScriptObject)
3694 {
3695     ASSERT_NOT_REACHED();
3696     if (!webScriptObject)
3697         return E_POINTER;
3698     *webScriptObject = nullptr;
3699     return E_NOTIMPL;
3700 }
3701
3702 HRESULT WebView::setPreferences(_In_opt_ IWebPreferences* prefs)
3703 {
3704     if (!prefs)
3705         prefs = WebPreferences::sharedStandardPreferences();
3706
3707     if (m_preferences == prefs)
3708         return S_OK;
3709
3710     COMPtr<WebPreferences> webPrefs(Query, prefs);
3711     if (!webPrefs)
3712         return E_NOINTERFACE;
3713     webPrefs->willAddToWebView();
3714
3715     COMPtr<WebPreferences> oldPrefs = m_preferences;
3716
3717     IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
3718     nc->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3719
3720     BString identifier;
3721     oldPrefs->identifier(&identifier);
3722     oldPrefs->didRemoveFromWebView();
3723     oldPrefs = 0; // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
3724
3725     m_preferences = webPrefs;
3726
3727     if (identifier)
3728         WebPreferences::removeReferenceForIdentifier(identifier);
3729
3730     nc->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3731
3732     m_preferences->postPreferencesChangesNotification();
3733
3734     return S_OK;
3735 }
3736
3737 HRESULT WebView::preferences(_COM_Outptr_opt_ IWebPreferences** prefs)
3738 {
3739     if (!prefs)
3740         return E_POINTER;
3741     *prefs = m_preferences.get();
3742     if (m_preferences)
3743         m_preferences->AddRef();
3744     return S_OK;
3745 }
3746
3747 HRESULT WebView::setPreferencesIdentifier(_In_ BSTR /*anIdentifier*/)
3748 {
3749     ASSERT_NOT_REACHED();
3750     return E_NOTIMPL;
3751 }
3752
3753 HRESULT WebView::preferencesIdentifier(_Deref_opt_out_ BSTR* /*anIdentifier*/)
3754 {
3755     ASSERT_NOT_REACHED();
3756     return E_NOTIMPL;
3757 }
3758
3759 static void systemParameterChanged(WPARAM parameter)
3760 {
3761 #if USE(CG)
3762     if (parameter == SPI_SETFONTSMOOTHING || parameter == SPI_SETFONTSMOOTHINGTYPE || parameter == SPI_SETFONTSMOOTHINGCONTRAST || parameter == SPI_SETFONTSMOOTHINGORIENTATION)
3763         wkSystemFontSmoothingChanged();
3764 #endif
3765 }
3766
3767 void WebView::windowReceivedMessage(HWND, UINT message, WPARAM wParam, LPARAM)
3768 {
3769     switch (message) {
3770     case WM_NCACTIVATE:
3771         updateActiveStateSoon();
3772         if (!wParam)
3773             deleteBackingStoreSoon();
3774         break;
3775     case WM_SETTINGCHANGE:
3776         systemParameterChanged(wParam);
3777         break;
3778     }
3779 }
3780
3781 void WebView::updateActiveStateSoon() const
3782 {
3783     // This function is called while processing the WM_NCACTIVATE message.
3784     // While processing WM_NCACTIVATE when we are being deactivated, GetActiveWindow() will
3785     // still return our window. If we were to call updateActiveState() in that case, we would
3786     // wrongly think that we are still the active window. To work around this, we update our
3787     // active state after a 0-delay timer fires, at which point GetActiveWindow() will return
3788     // the newly-activated window.
3789
3790     SetTimer(m_viewWindow, UpdateActiveStateTimer, 0, 0);
3791 }
3792
3793 void WebView::deleteBackingStoreSoon()
3794 {
3795     if (pendingDeleteBackingStoreSet().size() > 2) {
3796         Vector<WebView*> views;
3797         HashSet<WebView*>::iterator end = pendingDeleteBackingStoreSet().end();
3798         for (HashSet<WebView*>::iterator it = pendingDeleteBackingStoreSet().begin(); it != end; ++it)
3799             views.append(*it);
3800         for (int i = 0; i < views.size(); ++i)
3801             views[i]->deleteBackingStore();
3802         ASSERT(pendingDeleteBackingStoreSet().isEmpty());
3803     }
3804
3805     pendingDeleteBackingStoreSet().add(this);
3806     m_deleteBackingStoreTimerActive = true;
3807     SetTimer(m_viewWindow, DeleteBackingStoreTimer, delayBeforeDeletingBackingStoreMsec, 0);
3808 }
3809
3810 void WebView::cancelDeleteBackingStoreSoon()
3811 {
3812     if (!m_deleteBackingStoreTimerActive)
3813         return;
3814     pendingDeleteBackingStoreSet().remove(this);
3815     m_deleteBackingStoreTimerActive = false;
3816     KillTimer(m_viewWindow, DeleteBackingStoreTimer);
3817 }
3818
3819 HRESULT WebView::setHostWindow(_In_ HWND window)
3820 {
3821     if (m_viewWindow) {
3822         if (window)
3823             SetParent(m_viewWindow, window);
3824         else if (!isBeingDestroyed()) {
3825             // Turn the WebView into a message-only window so it will no longer be a child of the
3826             // old host window and will be hidden from screen. We only do this when
3827             // isBeingDestroyed() is false because doing this while handling WM_DESTROY can leave
3828             // m_viewWindow in a weird state (see <http://webkit.org/b/29337>).
3829             SetParent(m_viewWindow, HWND_MESSAGE);
3830         }
3831     }
3832
3833     m_hostWindow = window;
3834
3835     windowAncestryDidChange();
3836
3837     if (m_page)
3838         m_page->setDeviceScaleFactor(deviceScaleFactor());
3839
3840     return S_OK;
3841 }
3842
3843 HRESULT WebView::hostWindow(_Deref_opt_out_ HWND* window)
3844 {
3845     if (!window)
3846         return E_POINTER;
3847
3848     *window = m_hostWindow;
3849     return S_OK;
3850 }
3851
3852
3853 static Frame *incrementFrame(Frame *curr, bool forward, bool wrapFlag)
3854 {
3855     return forward
3856         ? curr->tree().traverseNextWithWrap(wrapFlag)
3857         : curr->tree().traversePreviousWithWrap(wrapFlag);
3858 }
3859
3860 HRESULT WebView::searchFor(_In_ BSTR str, BOOL forward, BOOL caseFlag, BOOL wrapFlag, _Out_ BOOL* found)
3861 {
3862     if (!found)
3863         return E_INVALIDARG;
3864     
3865     if (!m_page)
3866         return E_FAIL;
3867
3868     if (!str || !SysStringLen(str))
3869         return E_INVALIDARG;
3870
3871     FindOptions options = (caseFlag ? 0 : CaseInsensitive) | (forward ? 0 : Backwards) | (wrapFlag ? WrapAround : 0);
3872     *found = m_page->findString(toString(str), options);
3873     return S_OK;
3874 }
3875
3876 bool WebView::active()
3877 {
3878     HWND activeWindow = GetActiveWindow();
3879     if (usesLayeredWindow() && activeWindow == m_viewWindow)
3880         return true;
3881
3882     return (activeWindow && m_topLevelParent == findTopLevelParent(activeWindow));
3883 }
3884
3885 void WebView::updateActiveState()
3886 {
3887     if (m_page)
3888         m_page->focusController().setActive(active());
3889 }
3890
3891 HRESULT WebView::updateFocusedAndActiveState()
3892 {
3893     updateActiveState();
3894
3895     bool active = m_page->focusController().isActive();
3896     Frame& mainFrame = m_page->mainFrame();
3897     Frame& focusedFrame = m_page->focusController().focusedOrMainFrame();
3898     mainFrame.selection().setFocused(active && &mainFrame == &focusedFrame);
3899
3900     return S_OK;
3901 }
3902
3903 HRESULT WebView::executeCoreCommandByName(_In_ BSTR name, _In_ BSTR value)
3904 {
3905     if (!m_page)
3906         return E_FAIL;
3907
3908     m_page->focusController().focusedOrMainFrame().editor().command(toString(name)).execute(toString(value));
3909
3910     return S_OK;
3911 }
3912
3913 HRESULT WebView::clearMainFrameName()
3914 {
3915     if (!m_page)
3916         return E_FAIL;
3917
3918     m_page->mainFrame().tree().clearName();
3919
3920     return S_OK;
3921 }
3922
3923 HRESULT WebView::markAllMatchesForText(_In_ BSTR str, BOOL caseSensitive, BOOL highlight, UINT limit, _Out_ UINT* matches)
3924 {
3925     if (!matches)
3926         return E_INVALIDARG;
3927
3928     if (!m_page)
3929         return E_FAIL;
3930
3931     if (!str || !SysStringLen(str))
3932         return E_INVALIDARG;
3933
3934     *matches = m_page->markAllMatchesForText(toString(str), caseSensitive ? TextCaseSensitive : TextCaseInsensitive, highlight, limit);
3935     return S_OK;
3936 }
3937
3938 HRESULT WebView::unmarkAllTextMatches()
3939 {
3940     if (!m_page)
3941         return E_FAIL;
3942
3943     m_page->unmarkAllTextMatches();
3944     return S_OK;
3945 }
3946
3947 HRESULT WebView::rectsForTextMatches(_COM_Outptr_opt_ IEnumTextMatches** pmatches)
3948 {
3949     if (!pmatches)
3950         return E_POINTER;
3951     *pmatches = nullptr;
3952     if (!m_page)
3953         return E_FAIL;
3954
3955     Vector<IntRect> allRects;
3956     WebCore::Frame* frame = &m_page->mainFrame();
3957     do {
3958         if (Document* document = frame->document()) {
3959             IntRect visibleRect = frame->view()->visibleContentRect();
3960             Vector<FloatRect> frameRects = document->markers().renderedRectsForMarkers(DocumentMarker::TextMatch);
3961             IntPoint frameOffset = -frame->view()->scrollPosition();
3962             frameOffset = frame->view()->convertToContainingWindow(frameOffset);
3963
3964             Vector<FloatRect>::iterator end = frameRects.end();
3965             for (Vector<FloatRect>::iterator it = frameRects.begin(); it < end; it++) {
3966                 it->intersect(visibleRect);
3967                 it->move(frameOffset.x(), frameOffset.y());
3968                 allRects.append(enclosingIntRect(*it));
3969             }
3970         }
3971         frame = incrementFrame(frame, true, false);
3972     } while (frame);
3973
3974     return createMatchEnumerator(&allRects, pmatches);
3975 }
3976
3977 HRESULT WebView::generateSelectionImage(BOOL forceWhiteText, _Deref_opt_out_ HBITMAP* hBitmap)
3978 {
3979     if (!hBitmap)
3980         return E_POINTER;
3981
3982     if (!m_page)
3983         return E_FAIL;
3984
3985     *hBitmap = nullptr;
3986
3987     WebCore::Frame& frame = m_page->focusController().focusedOrMainFrame();
3988
3989     auto bitmap = imageFromSelection(&frame, forceWhiteText ? TRUE : FALSE);
3990     *hBitmap = bitmap.leak();
3991
3992     return S_OK;
3993 }
3994
3995 HRESULT WebView::selectionRect(_Inout_ RECT* rc)
3996 {
3997     if (!rc)
3998         return E_POINTER;
3999
4000     if (!m_page)
4001         return E_FAIL;
4002
4003     WebCore::Frame& frame = m_page->focusController().focusedOrMainFrame();
4004
4005     IntRect ir = enclosingIntRect(frame.selection().selectionBounds());
4006     ir = frame.view()->convertToContainingWindow(ir);
4007     ir.moveBy(-frame.view()->scrollPosition());
4008
4009     float scaleFactor = deviceScaleFactor();
4010     rc->left = ir.x() * scaleFactor;
4011     rc->top = ir.y() * scaleFactor;
4012     rc->bottom = rc->top + ir.height() * scaleFactor;
4013     rc->right = rc->left + ir.width() * scaleFactor;
4014
4015     return S_OK;
4016 }
4017
4018 HRESULT WebView::registerViewClass(_In_opt_ IWebDocumentView*, _In_opt_ IWebDocumentRepresentation*, _In_ BSTR /*forMIMEType*/)
4019 {
4020     ASSERT_NOT_REACHED();
4021     return E_NOTIMPL;
4022 }
4023
4024 HRESULT WebView::setGroupName(_In_ BSTR groupName)
4025 {
4026     if (m_webViewGroup)
4027         m_webViewGroup->removeWebView(this);
4028
4029     m_webViewGroup = WebViewGroup::getOrCreate(groupName, localStorageDatabasePath(m_preferences.get()));
4030     m_webViewGroup->addWebView(this);
4031
4032     if (!m_page)
4033         return S_OK;
4034
4035     m_page->setUserContentProvider(m_webViewGroup->userContentController());
4036     m_page->setVisitedLinkStore(m_webViewGroup->visitedLinkStore());
4037     m_page->setGroupName(toString(groupName));
4038     return S_OK;
4039 }
4040     
4041 HRESULT WebView::groupName(_Deref_opt_out_ BSTR* groupName)
4042 {
4043     if (!groupName)
4044         return E_POINTER;
4045
4046     *groupName = nullptr;
4047     if (!m_page)
4048         return S_OK;
4049     String groupNameString = m_page->groupName();
4050     *groupName = BString(groupNameString).release();
4051     if (!*groupName && groupNameString.length())
4052         return E_OUTOFMEMORY;
4053     return S_OK;
4054 }
4055     
4056 HRESULT WebView::estimatedProgress(_Out_ double* estimatedProgress)
4057 {
4058     if (!estimatedProgress)
4059         return E_POINTER;
4060     *estimatedProgress = m_page->progress().estimatedProgress();
4061     return S_OK;
4062 }
4063     
4064 HRESULT WebView::isLoading(_Out_ BOOL* isLoading)
4065 {
4066     COMPtr<IWebDataSource> dataSource;
4067     COMPtr<IWebDataSource> provisionalDataSource;
4068
4069     if (!isLoading)
4070         return E_POINTER;
4071
4072     *isLoading = FALSE;
4073
4074     if (!m_mainFrame)
4075         return E_UNEXPECTED;
4076
4077     if (SUCCEEDED(m_mainFrame->dataSource(&dataSource)))
4078         dataSource->isLoading(isLoading);
4079
4080     if (*isLoading)
4081         return S_OK;
4082
4083     if (SUCCEEDED(m_mainFrame->provisionalDataSource(&provisionalDataSource)))
4084         provisionalDataSource->isLoading(isLoading);
4085     return S_OK;
4086 }
4087     
4088 HRESULT WebView::elementAtPoint(_In_ LPPOINT point, _COM_Outptr_opt_ IPropertyBag** elementDictionary)
4089 {
4090     if (!elementDictionary || !point) {
4091         ASSERT_NOT_REACHED();
4092         return E_POINTER;
4093     }
4094
4095     *elementDictionary = nullptr;
4096
4097     Frame* frame = core(m_mainFrame);
4098     if (!frame)
4099         return E_UNEXPECTED;
4100
4101     IntPoint webCorePoint = IntPoint(point->x, point->y);
4102     float inverseScaleFactor = 1.0f / deviceScaleFactor();
4103     webCorePoint.scale(inverseScaleFactor, inverseScaleFactor);
4104     HitTestResult result = HitTestResult(webCorePoint);
4105     if (frame->contentRenderer())
4106         result = frame->eventHandler().hitTestResultAtPoint(webCorePoint);
4107     *elementDictionary = WebElementPropertyBag::createInstance(result);
4108     return S_OK;
4109 }
4110     
4111 HRESULT WebView::pasteboardTypesForSelection(_COM_Outptr_opt_ IEnumVARIANT** enumVariant)
4112 {
4113     ASSERT_NOT_REACHED();
4114     if (!enumVariant)
4115         return E_POINTER;
4116     *enumVariant = nullptr;
4117     return E_NOTIMPL;
4118 }
4119     
4120 HRESULT WebView::writeSelectionWithPasteboardTypes(__inout_ecount_full(cTypes) BSTR* types, int cTypes, _In_opt_ IDataObject* /*pasteboard*/)
4121 {
4122     ASSERT_NOT_REACHED();
4123     return E_NOTIMPL;
4124 }
4125     
4126 HRESULT WebView::pasteboardTypesForElement(_In_opt_ IPropertyBag* /*elementDictionary*/, _COM_Outptr_opt_ IEnumVARIANT** enumVariant)
4127 {
4128     ASSERT_NOT_REACHED();
4129     if (!enumVariant)
4130         return E_POINTER;
4131     *enumVariant = nullptr;
4132     return E_NOTIMPL;
4133 }
4134     
4135 HRESULT WebView::writeElement(_In_opt_ IPropertyBag* /*elementDictionary*/, __inout_ecount_full(cWithPasteboardTypes) BSTR* withPasteboardTypes, int cWithPasteboardTypes, _In_opt_ IDataObject* /*pasteboard*/)
4136 {
4137     ASSERT_NOT_REACHED();
4138     return E_NOTIMPL;
4139 }
4140     
4141 HRESULT WebView::selectedText(_Deref_opt_out_ BSTR* text)
4142 {
4143     if (!text) {
4144         ASSERT_NOT_REACHED();
4145         return E_POINTER;
4146     }
4147
4148     *text = nullptr;
4149
4150     Frame* focusedFrame = m_page ? &m_page->focusController().focusedOrMainFrame() : 0;
4151     if (!focusedFrame)
4152         return E_FAIL;
4153
4154     String frameSelectedText = focusedFrame->editor().selectedText();
4155     *text = BString(frameSelectedText).release();
4156     if (!*text && frameSelectedText.length())
4157         return E_OUTOFMEMORY;
4158     return S_OK;
4159 }
4160
4161 HRESULT WebView::centerSelectionInVisibleArea(_In_opt_ IUnknown* /* sender */)
4162 {
4163     Frame* coreFrame = core(m_mainFrame);
4164     if (!coreFrame)
4165         return E_UNEXPECTED;
4166
4167     coreFrame->selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignCenterAlways);
4168     return S_OK;
4169 }
4170
4171
4172 HRESULT WebView::moveDragCaretToPoint(_In_ LPPOINT /*point*/)
4173 {
4174     ASSERT_NOT_REACHED();
4175     return E_NOTIMPL;
4176 }
4177     
4178 HRESULT WebView::removeDragCaret()
4179 {
4180     ASSERT_NOT_REACHED();
4181     return E_NOTIMPL;
4182 }
4183     
4184 HRESULT WebView::setDrawsBackground(BOOL /*drawsBackground*/)
4185 {
4186     ASSERT_NOT_REACHED();
4187     return E_NOTIMPL;
4188 }
4189     
4190 HRESULT WebView::drawsBackground(_Out_ BOOL* /*drawsBackground*/)
4191 {
4192     ASSERT_NOT_REACHED();
4193     return E_NOTIMPL;
4194 }
4195     
4196 HRESULT WebView::setMainFrameURL(_In_ BSTR /*urlString*/)
4197 {
4198     ASSERT_NOT_REACHED();
4199     return E_NOTIMPL;
4200 }
4201     
4202 HRESULT WebView::mainFrameURL(_Deref_opt_out_ BSTR* urlString)
4203 {
4204     if (!urlString)
4205         return E_POINTER;
4206
4207     if (!m_mainFrame)
4208         return E_UNEXPECTED;
4209
4210     COMPtr<IWebDataSource> dataSource;
4211
4212     if (FAILED(m_mainFrame->provisionalDataSource(&dataSource))) {
4213         if (FAILED(m_mainFrame->dataSource(&dataSource)))
4214             return E_FAIL;
4215     }
4216
4217     if (!dataSource) {
4218         *urlString = nullptr;
4219         return S_OK;
4220     }
4221     
4222     COMPtr<IWebMutableURLRequest> request;
4223     if (FAILED(dataSource->request(&request)) || !request)
4224         return E_FAIL;
4225
4226     if (FAILED(request->URL(urlString)))
4227         return E_FAIL;
4228
4229     return S_OK;
4230 }
4231     
4232 HRESULT WebView::mainFrameDocument(_COM_Outptr_opt_ IDOMDocument** document)
4233 {
4234     if (!document)
4235         return E_POINTER;
4236
4237     *document = nullptr;
4238
4239     if (!m_mainFrame)
4240         return E_UNEXPECTED;
4241     return m_mainFrame->DOMDocument(document);
4242 }
4243     
4244 HRESULT WebView::mainFrameTitle(_Deref_opt_out_ BSTR* /*title*/)
4245 {
4246     ASSERT_NOT_REACHED();
4247     return E_NOTIMPL;
4248 }
4249     
4250 HRESULT WebView::mainFrameIcon(_Deref_opt_out_ HBITMAP* /*hBitmap*/)
4251 {
4252     ASSERT_NOT_REACHED();
4253     return E_NOTIMPL;
4254 }
4255
4256 HRESULT WebView::registerURLSchemeAsLocal(_In_ BSTR scheme)
4257 {
4258     if (!scheme)
4259         return E_POINTER;
4260
4261     SchemeRegistry::registerURLSchemeAsLocal(toString(scheme));
4262
4263     return S_OK;
4264 }
4265
4266 // IWebIBActions ---------------------------------------------------------------
4267
4268 HRESULT WebView::takeStringURLFrom(_In_opt_ IUnknown* /*sender*/)
4269 {
4270     ASSERT_NOT_REACHED();
4271     return E_NOTIMPL;
4272 }
4273     
4274 HRESULT WebView::stopLoading(_In_opt_ IUnknown* /*sender*/)
4275 {
4276     if (!m_mainFrame)
4277         return E_UNEXPECTED;
4278
4279     return m_mainFrame->stopLoading();