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