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