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