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