Unreviewed, rolling out r177037.
[WebKit-https.git] / Source / WebKit / win / WebView.cpp
1 /*
2  * Copyright (C) 2006-2014 Apple, Inc.  All rights reserved.
3  * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
4  * Copyright (C) 2011 Brent Fulgham. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
26  */
27
28 #include "WebView.h"
29
30 #include "BackForwardController.h"
31 #include "COMVariantSetter.h"
32 #include "DOMCoreClasses.h"
33 #include "FullscreenVideoController.h"
34 #include "MarshallingHelpers.h"
35 #include "SoftLinking.h"
36 #include "SubframeLoader.h"
37 #include "TextIterator.h"
38 #include "WebBackForwardList.h"
39 #include "WebChromeClient.h"
40 #include "WebContextMenuClient.h"
41 #include "WebCoreTextRenderer.h"
42 #include "WebDatabaseManager.h"
43 #include "WebDocumentLoader.h"
44 #include "WebDownload.h"
45 #include "WebDragClient.h"
46 #include "WebEditorClient.h"
47 #include "WebElementPropertyBag.h"
48 #include "WebFrame.h"
49 #include "WebFrameLoaderClient.h"
50 #include "WebFrameNetworkingContext.h"
51 #include "WebGeolocationClient.h"
52 #include "WebGeolocationPosition.h"
53 #include "WebIconDatabase.h"
54 #include "WebInspector.h"
55 #include "WebInspectorClient.h"
56 #include "WebKit.h"
57 #include "WebKitDLL.h"
58 #include "WebKitLogging.h"
59 #include "WebKitStatisticsPrivate.h"
60 #include "WebKitSystemBits.h"
61 #include "WebKitVersion.h"
62 #include "WebMutableURLRequest.h"
63 #include "WebNotificationCenter.h"
64 #include "WebPlatformStrategies.h"
65 #include "WebPreferences.h"
66 #include "WebScriptWorld.h"
67 #include "WebVisitedLinkStore.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/PageConfiguration.h>
122 #include <WebCore/PageGroup.h>
123 #include <WebCore/PlatformKeyboardEvent.h>
124 #include <WebCore/PlatformMouseEvent.h>
125 #include <WebCore/PlatformWheelEvent.h>
126 #include <WebCore/PluginData.h>
127 #include <WebCore/PluginDatabase.h>
128 #include <WebCore/PluginView.h>
129 #include <WebCore/PopupMenu.h>
130 #include <WebCore/PopupMenuWin.h>
131 #include <WebCore/ProgressTracker.h>
132 #include <WebCore/RenderLayer.h>
133 #include <WebCore/RenderTheme.h>
134 #include <WebCore/RenderTreeAsText.h>
135 #include <WebCore/RenderView.h>
136 #include <WebCore/RenderWidget.h>
137 #include <WebCore/ResourceHandle.h>
138 #include <WebCore/ResourceHandleClient.h>
139 #include <WebCore/ResourceRequest.h>
140 #include <WebCore/RuntimeEnabledFeatures.h>
141 #include <WebCore/SchemeRegistry.h>
142 #include <WebCore/ScriptController.h>
143 #include <WebCore/Scrollbar.h>
144 #include <WebCore/ScrollbarTheme.h>
145 #include <WebCore/SecurityOrigin.h>
146 #include <WebCore/SecurityPolicy.h>
147 #include <WebCore/Settings.h>
148 #include <WebCore/SimpleFontData.h>
149 #include <WebCore/SystemInfo.h>
150 #include <WebCore/WindowMessageBroadcaster.h>
151 #include <WebCore/WindowsTouch.h>
152 #include <bindings/ScriptValue.h>
153 #include <wtf/MainThread.h>
154
155 #if USE(CG)
156 #include <CoreGraphics/CGContext.h>
157 #endif
158
159 #if USE(CF)
160 #include <CoreFoundation/CoreFoundation.h>
161 #endif
162
163 #if USE(CFNETWORK)
164 #include <CFNetwork/CFURLCachePriv.h>
165 #include <CFNetwork/CFURLProtocolPriv.h>
166 #include <WebKitSystemInterface/WebKitSystemInterface.h>
167 #elif USE(CURL)
168 #include <WebCore/CurlCacheManager.h>
169 #endif
170
171 #if USE(CA)
172 #include <WebCore/CACFLayerTreeHost.h>
173 #include <WebCore/PlatformCALayer.h>
174 #elif USE(TEXTURE_MAPPER_GL)
175 #include "AcceleratedCompositingContext.h"
176 #endif
177
178 #if ENABLE(FULLSCREEN_API)
179 #include <WebCore/FullScreenController.h>
180 #endif
181
182 #include <ShlObj.h>
183 #include <comutil.h>
184 #include <dimm.h>
185 #include <oleacc.h>
186 #include <wchar.h>
187 #include <windowsx.h>
188 #include <wtf/HashSet.h>
189 #include <wtf/text/CString.h>
190 #include <wtf/text/StringConcatenate.h>
191 #include <wtf/win/GDIObject.h>
192
193 // Soft link functions for gestures and panning feedback
194 SOFT_LINK_LIBRARY(USER32);
195 SOFT_LINK_OPTIONAL(USER32, GetGestureInfo, BOOL, WINAPI, (HGESTUREINFO, PGESTUREINFO));
196 SOFT_LINK_OPTIONAL(USER32, SetGestureConfig, BOOL, WINAPI, (HWND, DWORD, UINT, PGESTURECONFIG, UINT));
197 SOFT_LINK_OPTIONAL(USER32, CloseGestureInfoHandle, BOOL, WINAPI, (HGESTUREINFO));
198 SOFT_LINK_LIBRARY(Uxtheme);
199 SOFT_LINK_OPTIONAL(Uxtheme, BeginPanningFeedback, BOOL, WINAPI, (HWND));
200 SOFT_LINK_OPTIONAL(Uxtheme, EndPanningFeedback, BOOL, WINAPI, (HWND, BOOL));
201 SOFT_LINK_OPTIONAL(Uxtheme, UpdatePanningFeedback, BOOL, WINAPI, (HWND, LONG, LONG, BOOL));
202
203 using namespace WebCore;
204 using namespace std;
205 using JSC::JSLock;
206
207 static HMODULE accessibilityLib;
208 static HashSet<WebView*>& pendingDeleteBackingStoreSet()
209 {
210     static NeverDestroyed<HashSet<WebView*>> pendingDeleteBackingStoreSet;
211     return pendingDeleteBackingStoreSet;
212 }
213
214 static CFStringRef WebKitLocalCacheDefaultsKey = CFSTR("WebKitLocalCache");
215
216 static String webKitVersionString();
217
218 WebView* kit(Page* page)
219 {
220     if (!page)
221         return 0;
222     
223     if (page->chrome().client().isEmptyChromeClient())
224         return 0;
225     
226     return static_cast<WebChromeClient&>(page->chrome().client()).webView();
227 }
228
229 static inline AtomicString toAtomicString(BSTR bstr)
230 {
231     return AtomicString(bstr, SysStringLen(bstr));
232 }
233
234 static inline String toString(BSTR bstr)
235 {
236     return String(bstr, SysStringLen(bstr));
237 }
238
239 static inline String toString(BString &bstr)
240 {
241     return String(bstr, SysStringLen(bstr));
242 }
243
244 static inline URL toURL(BSTR bstr)
245 {
246     return URL(URL(), toString(bstr));
247 }
248
249 class PreferencesChangedOrRemovedObserver : public IWebNotificationObserver {
250 public:
251     static PreferencesChangedOrRemovedObserver* sharedInstance();
252
253 private:
254     PreferencesChangedOrRemovedObserver() {}
255     ~PreferencesChangedOrRemovedObserver() {}
256
257     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) { return E_FAIL; }
258     virtual ULONG STDMETHODCALLTYPE AddRef(void) { return 0; }
259     virtual ULONG STDMETHODCALLTYPE Release(void) { return 0; }
260
261 public:
262     // IWebNotificationObserver
263     virtual HRESULT STDMETHODCALLTYPE onNotify( 
264         /* [in] */ IWebNotification* notification);
265
266 private:
267     HRESULT notifyPreferencesChanged(WebCacheModel);
268     HRESULT notifyPreferencesRemoved(WebCacheModel);
269 };
270
271 PreferencesChangedOrRemovedObserver* PreferencesChangedOrRemovedObserver::sharedInstance()
272 {
273     static PreferencesChangedOrRemovedObserver* shared = new PreferencesChangedOrRemovedObserver;
274     return shared;
275 }
276
277 HRESULT PreferencesChangedOrRemovedObserver::onNotify(IWebNotification* notification)
278 {
279     HRESULT hr = S_OK;
280
281     COMPtr<IUnknown> unkPrefs;
282     hr = notification->getObject(&unkPrefs);
283     if (FAILED(hr))
284         return hr;
285
286     COMPtr<IWebPreferences> preferences(Query, unkPrefs);
287     if (!preferences)
288         return E_NOINTERFACE;
289
290     WebCacheModel cacheModel;
291     hr = preferences->cacheModel(&cacheModel);
292     if (FAILED(hr))
293         return hr;
294
295     BString name;
296     hr = notification->name(&name);
297     if (FAILED(hr))
298         return hr;
299
300     if (wcscmp(name, WebPreferences::webPreferencesChangedNotification()) == 0)
301         return notifyPreferencesChanged(cacheModel);
302
303     if (wcscmp(name, WebPreferences::webPreferencesRemovedNotification()) == 0)
304         return notifyPreferencesRemoved(cacheModel);
305
306     ASSERT_NOT_REACHED();
307     return E_FAIL;
308 }
309
310 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesChanged(WebCacheModel cacheModel)
311 {
312     HRESULT hr = S_OK;
313
314     if (!WebView::didSetCacheModel() || cacheModel > WebView::cacheModel())
315         WebView::setCacheModel(cacheModel);
316     else if (cacheModel < WebView::cacheModel()) {
317         WebCacheModel sharedPreferencesCacheModel;
318         hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel);
319         if (FAILED(hr))
320             return hr;
321         WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance()));
322     }
323
324     return hr;
325 }
326
327 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesRemoved(WebCacheModel cacheModel)
328 {
329     HRESULT hr = S_OK;
330
331     if (cacheModel == WebView::cacheModel()) {
332         WebCacheModel sharedPreferencesCacheModel;
333         hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel);
334         if (FAILED(hr))
335             return hr;
336         WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance()));
337     }
338
339     return hr;
340 }
341
342
343 const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass";
344
345 const int WM_XP_THEMECHANGED = 0x031A;
346 const int WM_VISTA_MOUSEHWHEEL = 0x020E;
347
348 static const int maxToolTipWidth = 250;
349
350 static const int delayBeforeDeletingBackingStoreMsec = 5000;
351
352 static ATOM registerWebView();
353
354 static void initializeStaticObservers();
355
356 static HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences*);
357
358 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches);
359
360 static bool continuousSpellCheckingEnabled;
361 static bool grammarCheckingEnabled;
362
363 static bool s_didSetCacheModel;
364 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
365
366 enum {
367     UpdateActiveStateTimer = 1,
368     DeleteBackingStoreTimer = 2,
369 };
370
371 // WebView ----------------------------------------------------------------
372
373 bool WebView::s_allowSiteSpecificHacks = false;
374
375 WebView::WebView()
376     : m_refCount(0)
377     , m_shouldInvertColors(false)
378 #if !ASSERT_DISABLED
379     , m_deletionHasBegun(false)
380 #endif
381     , m_hostWindow(0)
382     , m_viewWindow(0)
383     , m_mainFrame(0)
384     , m_page(0)
385 #if ENABLE(INSPECTOR)
386     , m_inspectorClient(0)
387 #endif // ENABLE(INSPECTOR)
388     , m_hasCustomDropTarget(false)
389     , m_useBackForwardList(true)
390     , m_userAgentOverridden(false)
391     , m_zoomMultiplier(1.0f)
392     , m_zoomsTextOnly(false)
393     , m_mouseActivated(false)
394     , m_dragData(0)
395     , m_currentCharacterCode(0)
396     , m_isBeingDestroyed(false)
397     , m_paintCount(0)
398     , m_hasSpellCheckerDocumentTag(false)
399     , m_didClose(false)
400     , m_inIMEComposition(0)
401     , m_toolTipHwnd(0)
402     , m_closeWindowTimer(0)
403     , m_topLevelParent(0)
404     , m_deleteBackingStoreTimerActive(false)
405     , m_transparent(false)
406     , m_lastPanX(0)
407     , m_lastPanY(0)
408     , m_xOverpan(0)
409     , m_yOverpan(0)
410     , m_isAcceleratedCompositing(false)
411     , m_nextDisplayIsSynchronous(false)
412     , m_lastSetCursor(0)
413     , m_usesLayeredWindow(false)
414     , m_needsDisplay(false)
415 #if USE(TEXTURE_MAPPER_GL)
416     , m_acceleratedCompositingContext(nullptr)
417 #endif
418 {
419     JSC::initializeThreading();
420     WTF::initializeMainThread();
421
422     m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
423
424     CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper,(void**)&m_dropTargetHelper);
425
426     initializeStaticObservers();
427
428     WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences();
429     BOOL enabled;
430     if (SUCCEEDED(sharedPreferences->continuousSpellCheckingEnabled(&enabled)))
431         continuousSpellCheckingEnabled = !!enabled;
432     if (SUCCEEDED(sharedPreferences->grammarCheckingEnabled(&enabled)))
433         grammarCheckingEnabled = !!enabled;
434
435     WebViewCount++;
436     gClassCount++;
437     gClassNameCount().add("WebView");
438 }
439
440 WebView::~WebView()
441 {
442     deleteBackingStore();
443
444     // the tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD
445     if (::IsWindow(m_toolTipHwnd))
446         ::DestroyWindow(m_toolTipHwnd);
447
448     ASSERT(!m_page);
449     ASSERT(!m_preferences);
450     ASSERT(!m_viewWindow);
451
452 #if USE(CA)
453     ASSERT(!m_layerTreeHost);
454 #endif
455
456     WebViewCount--;
457     gClassCount--;
458     gClassNameCount().remove("WebView");
459 }
460
461 WebView* WebView::createInstance()
462 {
463     WebView* instance = new WebView();
464     instance->AddRef();
465     return instance;
466 }
467
468 void initializeStaticObservers()
469 {
470     static bool initialized;
471     if (initialized)
472         return;
473     initialized = true;
474
475     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
476     notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesChangedNotification(), 0);
477     notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesRemovedNotification(), 0);
478 }
479
480 static HashSet<WebView*>& allWebViewsSet()
481 {
482     static HashSet<WebView*> allWebViewsSet;
483     return allWebViewsSet;
484 }
485
486 void WebView::addToAllWebViewsSet()
487 {
488     allWebViewsSet().add(this);
489 }
490
491 void WebView::removeFromAllWebViewsSet()
492 {
493     allWebViewsSet().remove(this);
494 }
495
496 void WebView::setCacheModel(WebCacheModel cacheModel)
497 {
498     if (s_didSetCacheModel && cacheModel == s_cacheModel)
499         return;
500
501     String cacheDirectory;
502
503 #if USE(CFNETWORK)
504     RetainPtr<CFURLCacheRef> cfurlCache = adoptCF(CFURLCacheCopySharedURLCache());
505     RetainPtr<CFStringRef> cfurlCacheDirectory = adoptCF(wkCopyFoundationCacheDirectory(0));
506     if (!cfurlCacheDirectory) {
507         RetainPtr<CFPropertyListRef> preference = adoptCF(CFPreferencesCopyAppValue(WebKitLocalCacheDefaultsKey, kCFPreferencesCurrentApplication));
508         if (preference && (CFStringGetTypeID() == CFGetTypeID(preference.get())))
509             cfurlCacheDirectory = adoptCF(static_cast<CFStringRef>(preference.leakRef()));
510         else
511             cfurlCacheDirectory = WebCore::localUserSpecificStorageDirectory().createCFString();
512     }
513     cacheDirectory = String(cfurlCacheDirectory);
514     CFIndex cacheMemoryCapacity = 0;
515     CFIndex cacheDiskCapacity = 0;
516 #elif USE(CURL)
517     cacheDirectory = CurlCacheManager::getInstance().cacheDirectory();
518     long cacheMemoryCapacity = 0;
519     long cacheDiskCapacity = 0;
520 #endif
521
522     // As a fudge factor, use 1000 instead of 1024, in case the reported byte 
523     // count doesn't align exactly to a megabyte boundary.
524     unsigned long long memSize = WebMemorySize() / 1024 / 1000;
525     unsigned long long diskFreeSize = WebVolumeFreeSize(cacheDirectory) / 1024 / 1000;
526
527     unsigned cacheTotalCapacity = 0;
528     unsigned cacheMinDeadCapacity = 0;
529     unsigned cacheMaxDeadCapacity = 0;
530     auto deadDecodedDataDeletionInterval = std::chrono::seconds { 0 };
531
532     unsigned pageCacheCapacity = 0;
533
534
535     switch (cacheModel) {
536     case WebCacheModelDocumentViewer: {
537         // Page cache capacity (in pages)
538         pageCacheCapacity = 0;
539
540         // Object cache capacities (in bytes)
541         if (memSize >= 2048)
542             cacheTotalCapacity = 96 * 1024 * 1024;
543         else if (memSize >= 1536)
544             cacheTotalCapacity = 64 * 1024 * 1024;
545         else if (memSize >= 1024)
546             cacheTotalCapacity = 32 * 1024 * 1024;
547         else if (memSize >= 512)
548             cacheTotalCapacity = 16 * 1024 * 1024; 
549
550         cacheMinDeadCapacity = 0;
551         cacheMaxDeadCapacity = 0;
552
553         // Memory cache capacity (in bytes)
554         cacheMemoryCapacity = 0;
555
556 #if USE(CFNETWORK)
557         // Foundation disk cache capacity (in bytes)
558         cacheDiskCapacity = CFURLCacheDiskCapacity(cfurlCache.get());
559 #endif
560         break;
561     }
562     case WebCacheModelDocumentBrowser: {
563         // Page cache capacity (in pages)
564         if (memSize >= 1024)
565             pageCacheCapacity = 3;
566         else if (memSize >= 512)
567             pageCacheCapacity = 2;
568         else if (memSize >= 256)
569             pageCacheCapacity = 1;
570         else
571             pageCacheCapacity = 0;
572
573         // Object cache capacities (in bytes)
574         if (memSize >= 2048)
575             cacheTotalCapacity = 96 * 1024 * 1024;
576         else if (memSize >= 1536)
577             cacheTotalCapacity = 64 * 1024 * 1024;
578         else if (memSize >= 1024)
579             cacheTotalCapacity = 32 * 1024 * 1024;
580         else if (memSize >= 512)
581             cacheTotalCapacity = 16 * 1024 * 1024; 
582
583         cacheMinDeadCapacity = cacheTotalCapacity / 8;
584         cacheMaxDeadCapacity = cacheTotalCapacity / 4;
585
586         // Memory cache capacity (in bytes)
587         if (memSize >= 2048)
588             cacheMemoryCapacity = 4 * 1024 * 1024;
589         else if (memSize >= 1024)
590             cacheMemoryCapacity = 2 * 1024 * 1024;
591         else if (memSize >= 512)
592             cacheMemoryCapacity = 1 * 1024 * 1024;
593         else
594             cacheMemoryCapacity =      512 * 1024; 
595
596         // Disk cache capacity (in bytes)
597         if (diskFreeSize >= 16384)
598             cacheDiskCapacity = 50 * 1024 * 1024;
599         else if (diskFreeSize >= 8192)
600             cacheDiskCapacity = 40 * 1024 * 1024;
601         else if (diskFreeSize >= 4096)
602             cacheDiskCapacity = 30 * 1024 * 1024;
603         else
604             cacheDiskCapacity = 20 * 1024 * 1024;
605
606         break;
607     }
608     case WebCacheModelPrimaryWebBrowser: {
609         // Page cache capacity (in pages)
610         // (Research indicates that value / page drops substantially after 3 pages.)
611         if (memSize >= 2048)
612             pageCacheCapacity = 5;
613         else if (memSize >= 1024)
614             pageCacheCapacity = 4;
615         else if (memSize >= 512)
616             pageCacheCapacity = 3;
617         else if (memSize >= 256)
618             pageCacheCapacity = 2;
619         else
620             pageCacheCapacity = 1;
621
622         // Object cache capacities (in bytes)
623         // (Testing indicates that value / MB depends heavily on content and
624         // browsing pattern. Even growth above 128MB can have substantial 
625         // value / MB for some content / browsing patterns.)
626         if (memSize >= 2048)
627             cacheTotalCapacity = 128 * 1024 * 1024;
628         else if (memSize >= 1536)
629             cacheTotalCapacity = 96 * 1024 * 1024;
630         else if (memSize >= 1024)
631             cacheTotalCapacity = 64 * 1024 * 1024;
632         else if (memSize >= 512)
633             cacheTotalCapacity = 32 * 1024 * 1024; 
634
635         cacheMinDeadCapacity = cacheTotalCapacity / 4;
636         cacheMaxDeadCapacity = cacheTotalCapacity / 2;
637
638         // This code is here to avoid a PLT regression. We can remove it if we
639         // can prove that the overall system gain would justify the regression.
640         cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity);
641
642         deadDecodedDataDeletionInterval = std::chrono::seconds { 60 };
643
644         // Memory cache capacity (in bytes)
645         // (These values are small because WebCore does most caching itself.)
646         if (memSize >= 1024)
647             cacheMemoryCapacity = 4 * 1024 * 1024;
648         else if (memSize >= 512)
649             cacheMemoryCapacity = 2 * 1024 * 1024;
650         else if (memSize >= 256)
651             cacheMemoryCapacity = 1 * 1024 * 1024;
652         else
653             cacheMemoryCapacity =      512 * 1024; 
654
655         // Disk cache capacity (in bytes)
656         if (diskFreeSize >= 16384)
657             cacheDiskCapacity = 175 * 1024 * 1024;
658         else if (diskFreeSize >= 8192)
659             cacheDiskCapacity = 150 * 1024 * 1024;
660         else if (diskFreeSize >= 4096)
661             cacheDiskCapacity = 125 * 1024 * 1024;
662         else if (diskFreeSize >= 2048)
663             cacheDiskCapacity = 100 * 1024 * 1024;
664         else if (diskFreeSize >= 1024)
665             cacheDiskCapacity = 75 * 1024 * 1024;
666         else
667             cacheDiskCapacity = 50 * 1024 * 1024;
668
669         break;
670     }
671     default:
672         ASSERT_NOT_REACHED();
673     }
674
675     memoryCache().setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
676     memoryCache().setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
677     pageCache()->setCapacity(pageCacheCapacity);
678
679 #if USE(CFNETWORK)
680     // Don't shrink a big disk cache, since that would cause churn.
681     cacheDiskCapacity = max(cacheDiskCapacity, CFURLCacheDiskCapacity(cfurlCache.get()));
682
683     CFURLCacheSetMemoryCapacity(cfurlCache.get(), cacheMemoryCapacity);
684     CFURLCacheSetDiskCapacity(cfurlCache.get(), cacheDiskCapacity);
685 #elif USE(CURL)
686     CurlCacheManager::getInstance().setStorageSizeLimit(cacheDiskCapacity);
687 #endif
688
689     s_didSetCacheModel = true;
690     s_cacheModel = cacheModel;
691     return;
692 }
693
694 WebCacheModel WebView::cacheModel()
695 {
696     return s_cacheModel;
697 }
698
699 bool WebView::didSetCacheModel()
700 {
701     return s_didSetCacheModel;
702 }
703
704 WebCacheModel WebView::maxCacheModelInAnyInstance()
705 {
706     WebCacheModel cacheModel = WebCacheModelDocumentViewer;
707
708     HashSet<WebView*>::iterator end = allWebViewsSet().end();
709     for (HashSet<WebView*>::iterator it = allWebViewsSet().begin(); it != end; ++it) {
710         COMPtr<IWebPreferences> pref;
711         if (FAILED((*it)->preferences(&pref)))
712             continue;
713         WebCacheModel prefCacheModel = WebCacheModelDocumentViewer;
714         if (FAILED(pref->cacheModel(&prefCacheModel)))
715             continue;
716
717         cacheModel = max(cacheModel, prefCacheModel);
718     }
719
720     return cacheModel;
721 }
722
723 HRESULT STDMETHODCALLTYPE WebView::close()
724 {
725     if (m_didClose)
726         return S_OK;
727
728     m_didClose = true;
729
730     setAcceleratedCompositing(false);
731
732     WebNotificationCenter::defaultCenterInternal()->postNotificationName(_bstr_t(WebViewWillCloseNotification).GetBSTR(), static_cast<IWebView*>(this), 0);
733
734     if (m_uiDelegatePrivate)
735         m_uiDelegatePrivate->webViewClosing(this);
736
737     removeFromAllWebViewsSet();
738
739     if (m_page)
740         m_page->mainFrame().loader().detachFromParent();
741
742     if (m_mouseOutTracker) {
743         m_mouseOutTracker->dwFlags = TME_CANCEL;
744         ::TrackMouseEvent(m_mouseOutTracker.get());
745         m_mouseOutTracker.reset();
746     }
747     
748     revokeDragDrop();
749
750     if (m_viewWindow) {
751         // We can't check IsWindow(m_viewWindow) here, because that will return true even while
752         // we're already handling WM_DESTROY. So we check !isBeingDestroyed() instead.
753         if (!isBeingDestroyed())
754             DestroyWindow(m_viewWindow);
755         // Either we just destroyed m_viewWindow, or it's in the process of being destroyed. Either
756         // way, we clear it out to make sure we don't try to use it later.
757         m_viewWindow = 0;
758     }
759
760     setHostWindow(0);
761
762     setAccessibilityDelegate(0);
763     setDownloadDelegate(0);
764     setEditingDelegate(0);
765     setFrameLoadDelegate(0);
766     setFrameLoadDelegatePrivate(0);
767     setHistoryDelegate(0);
768     setPolicyDelegate(0);
769     setResourceLoadDelegate(0);
770     setUIDelegate(0);
771     setFormDelegate(0);
772
773 #if ENABLE(INSPECTOR)
774     m_inspectorClient = 0;
775     if (m_webInspector)
776         m_webInspector->webViewClosed();
777 #endif // ENABLE(INSPECTOR)
778
779     delete m_page;
780     m_page = 0;
781
782     registerForIconNotification(false);
783     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
784     notifyCenter->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
785
786     if (COMPtr<WebPreferences> preferences = m_preferences) {
787         BString identifier;
788         preferences->identifier(&identifier);
789
790         m_preferences = 0;
791         preferences->didRemoveFromWebView();
792         // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
793         preferences = 0;
794         if (identifier)
795             WebPreferences::removeReferenceForIdentifier(identifier);
796     }
797
798     deleteBackingStore();
799     return S_OK;
800 }
801
802 void WebView::repaint(const WebCore::IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly)
803 {
804     if (isAcceleratedCompositing()) {
805         // The contentChanged, immediate, and repaintContentOnly parameters are all based on a non-
806         // compositing painting/scrolling model.
807         addToDirtyRegion(windowRect);
808         return;
809     }
810
811     if (!repaintContentOnly) {
812         RECT rect = windowRect;
813         ::InvalidateRect(m_viewWindow, &rect, false);
814     }
815     if (contentChanged)
816         addToDirtyRegion(windowRect);
817     if (immediate) {
818         if (repaintContentOnly)
819             updateBackingStore(core(topLevelFrame())->view());
820         else
821             ::UpdateWindow(m_viewWindow);
822     }
823     m_needsDisplay = true;
824 }
825
826 void WebView::deleteBackingStore()
827 {
828     pendingDeleteBackingStoreSet().remove(this);
829
830     if (m_deleteBackingStoreTimerActive) {
831         KillTimer(m_viewWindow, DeleteBackingStoreTimer);
832         m_deleteBackingStoreTimerActive = false;
833     }
834     m_backingStoreBitmap.clear();
835     m_backingStoreDirtyRegion.clear();
836     m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
837 }
838
839 bool WebView::ensureBackingStore()
840 {
841     RECT windowRect;
842     ::GetClientRect(m_viewWindow, &windowRect);
843     LONG width = windowRect.right - windowRect.left;
844     LONG height = windowRect.bottom - windowRect.top;
845     if (width > 0 && height > 0 && (width != m_backingStoreSize.cx || height != m_backingStoreSize.cy)) {
846         deleteBackingStore();
847
848         m_backingStoreSize.cx = width;
849         m_backingStoreSize.cy = height;
850         BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(m_backingStoreSize));
851
852         void* pixels = NULL;
853         m_backingStoreBitmap = SharedGDIObject<HBITMAP>::create(adoptGDIObject(::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0)));
854         return true;
855     }
856
857     return false;
858 }
859
860 void WebView::addToDirtyRegion(const IntRect& dirtyRect)
861 {
862     m_needsDisplay = true;
863
864     // FIXME: We want an assert here saying that the dirtyRect is inside the clienRect,
865     // but it was being hit during our layout tests, and is being investigated in
866     // http://webkit.org/b/29350.
867
868     if (isAcceleratedCompositing()) {
869 #if USE(CA)
870         m_backingLayer->setNeedsDisplayInRect(dirtyRect);
871 #elif USE(TEXTURE_MAPPER_GL)
872         m_acceleratedCompositingContext->setNonCompositedContentsNeedDisplay(dirtyRect);
873 #endif
874         return;
875     }
876
877     auto newRegion = adoptGDIObject(::CreateRectRgn(dirtyRect.x(), dirtyRect.y(),
878         dirtyRect.maxX(), dirtyRect.maxY()));
879     addToDirtyRegion(WTF::move(newRegion));
880 }
881
882 void WebView::addToDirtyRegion(GDIObject<HRGN> newRegion)
883 {
884     m_needsDisplay = true;
885
886     ASSERT(!isAcceleratedCompositing());
887
888     LOCAL_GDI_COUNTER(0, __FUNCTION__);
889
890     if (m_backingStoreDirtyRegion) {
891         auto combinedRegion = adoptGDIObject(::CreateRectRgn(0, 0, 0, 0));
892         ::CombineRgn(combinedRegion.get(), m_backingStoreDirtyRegion->get(), newRegion.get(), RGN_OR);
893         m_backingStoreDirtyRegion = SharedGDIObject<HRGN>::create(WTF::move(combinedRegion));
894     } else
895         m_backingStoreDirtyRegion = SharedGDIObject<HRGN>::create(WTF::move(newRegion));
896
897     if (m_uiDelegatePrivate)
898         m_uiDelegatePrivate->webViewDidInvalidate(this);
899 }
900
901 void WebView::scrollBackingStore(FrameView* frameView, int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect)
902 {
903     m_needsDisplay = true;
904
905     if (isAcceleratedCompositing()) {
906         // FIXME: We should be doing something smarter here, like moving tiles around and painting
907         // any newly-exposed tiles. <http://webkit.org/b/52714>
908 #if USE(CA)
909         m_backingLayer->setNeedsDisplayInRect(scrollViewRect);
910 #elif USE(TEXTURE_MAPPER_GL)
911         m_acceleratedCompositingContext->scrollNonCompositedContents(scrollViewRect, IntSize(dx, dy));
912 #endif
913         return;
914     }
915
916     LOCAL_GDI_COUNTER(0, __FUNCTION__);
917
918     // If there's no backing store we don't need to update it
919     if (!m_backingStoreBitmap) {
920         if (m_uiDelegatePrivate)
921             m_uiDelegatePrivate->webViewScrolled(this);
922
923         return;
924     }
925
926     // Make a region to hold the invalidated scroll area.
927     auto updateRegion = adoptGDIObject(::CreateRectRgn(0, 0, 0, 0));
928
929     // Collect our device context info and select the bitmap to scroll.
930     HWndDC windowDC(m_viewWindow);
931     auto bitmapDC = adoptGDIObject(::CreateCompatibleDC(windowDC));
932     HGDIOBJ oldBitmap = ::SelectObject(bitmapDC.get(), m_backingStoreBitmap->get());
933     
934     // Scroll the bitmap.
935     RECT scrollRectWin(scrollViewRect);
936     RECT clipRectWin(clipRect);
937     ::ScrollDC(bitmapDC.get(), dx, dy, &scrollRectWin, &clipRectWin, updateRegion.get(), 0);
938     RECT regionBox;
939     ::GetRgnBox(updateRegion.get(), &regionBox);
940
941     // Flush.
942     GdiFlush();
943
944     // Add the dirty region to the backing store's dirty region.
945     addToDirtyRegion(WTF::move(updateRegion));
946
947     if (m_uiDelegatePrivate)
948         m_uiDelegatePrivate->webViewScrolled(this);
949
950     // Update the backing store.
951     updateBackingStore(frameView, bitmapDC.get(), false);
952
953     // Clean up.
954     ::SelectObject(bitmapDC.get(), oldBitmap);
955 }
956
957 void WebView::sizeChanged(const IntSize& newSize)
958 {
959     m_needsDisplay = true;
960
961     deleteBackingStore();
962
963     if (Frame* coreFrame = core(topLevelFrame()))
964         coreFrame->view()->resize(newSize);
965
966 #if USE(CA)
967     if (m_layerTreeHost)
968         m_layerTreeHost->resize();
969
970     if (m_backingLayer) {
971         m_backingLayer->setSize(newSize);
972         m_backingLayer->setNeedsDisplay();
973     }
974 #elif USE(TEXTURE_MAPPER_GL)
975     if (m_acceleratedCompositingContext)
976         m_acceleratedCompositingContext->resizeRootLayer(newSize);
977 #endif
978 }
979
980 // This emulates the Mac smarts for painting rects intelligently.  This is very
981 // important for us, since we double buffer based off dirty rects.
982 static void getUpdateRects(HRGN region, const IntRect& dirtyRect, Vector<IntRect>& rects)
983 {
984     ASSERT_ARG(region, region);
985
986     const int cRectThreshold = 10;
987     const float cWastedSpaceThreshold = 0.75f;
988
989     rects.clear();
990
991     DWORD regionDataSize = GetRegionData(region, sizeof(RGNDATA), NULL);
992     if (!regionDataSize) {
993         rects.append(dirtyRect);
994         return;
995     }
996
997     Vector<unsigned char> buffer(regionDataSize);
998     RGNDATA* regionData = reinterpret_cast<RGNDATA*>(buffer.data());
999     GetRegionData(region, regionDataSize, regionData);
1000     if (regionData->rdh.nCount > cRectThreshold) {
1001         rects.append(dirtyRect);
1002         return;
1003     }
1004
1005     double singlePixels = 0.0;
1006     unsigned i;
1007     RECT* rect;
1008     for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++)
1009         singlePixels += (rect->right - rect->left) * (rect->bottom - rect->top);
1010
1011     double unionPixels = dirtyRect.width() * dirtyRect.height();
1012     double wastedSpace = 1.0 - (singlePixels / unionPixels);
1013     if (wastedSpace <= cWastedSpaceThreshold) {
1014         rects.append(dirtyRect);
1015         return;
1016     }
1017
1018     for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++)
1019         rects.append(*rect);
1020 }
1021
1022 void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStoreCompletelyDirty, WindowsToPaint windowsToPaint)
1023 {
1024     ASSERT(!isAcceleratedCompositing());
1025
1026     LOCAL_GDI_COUNTER(0, __FUNCTION__);
1027
1028     GDIObject<HDC> bitmapDCObject;
1029
1030     HDC bitmapDC = dc;
1031     HGDIOBJ oldBitmap = 0;
1032     if (!dc) {
1033         HWndDC windowDC(m_viewWindow);
1034         bitmapDCObject = adoptGDIObject(::CreateCompatibleDC(windowDC));
1035         bitmapDC = bitmapDCObject.get();
1036         oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->get());
1037     }
1038
1039     if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
1040         // Do a layout first so that everything we render to the backing store is always current.
1041         if (Frame* coreFrame = core(m_mainFrame))
1042             if (FrameView* view = coreFrame->view())
1043                 view->updateLayoutAndStyleIfNeededRecursive();
1044
1045         Vector<IntRect> paintRects;
1046         if (!backingStoreCompletelyDirty && m_backingStoreDirtyRegion) {
1047             RECT regionBox;
1048             ::GetRgnBox(m_backingStoreDirtyRegion->get(), &regionBox);
1049             getUpdateRects(m_backingStoreDirtyRegion->get(), regionBox, paintRects);
1050         } else {
1051             RECT clientRect;
1052             ::GetClientRect(m_viewWindow, &clientRect);
1053             paintRects.append(clientRect);
1054         }
1055
1056         for (unsigned i = 0; i < paintRects.size(); ++i)
1057             paintIntoBackingStore(frameView, bitmapDC, paintRects[i], windowsToPaint);
1058
1059         if (m_uiDelegatePrivate)
1060             m_uiDelegatePrivate->webViewPainted(this);
1061
1062         m_backingStoreDirtyRegion.clear();
1063     }
1064
1065     if (!dc)
1066         ::SelectObject(bitmapDC, oldBitmap);
1067
1068     GdiFlush();
1069
1070     m_needsDisplay = true;
1071 }
1072
1073 void WebView::performLayeredWindowUpdate()
1074 {
1075     // The backing store may have been destroyed if the window rect was set to zero height or zero width.
1076     if (!m_backingStoreBitmap)
1077         return;
1078
1079     HWndDC hdcScreen(m_viewWindow);
1080     auto hdcMem = adoptGDIObject(::CreateCompatibleDC(hdcScreen));
1081     HBITMAP hbmOld = static_cast<HBITMAP>(::SelectObject(hdcMem.get(), m_backingStoreBitmap->get()));
1082
1083     BITMAP bmpInfo;
1084     ::GetObject(m_backingStoreBitmap->get(), sizeof(bmpInfo), &bmpInfo);
1085     SIZE windowSize = { bmpInfo.bmWidth, bmpInfo.bmHeight };
1086
1087     BLENDFUNCTION blendFunction;
1088     blendFunction.BlendOp = AC_SRC_OVER;
1089     blendFunction.BlendFlags = 0;
1090     blendFunction.SourceConstantAlpha = 0xFF;
1091     blendFunction.AlphaFormat = AC_SRC_ALPHA;
1092
1093     POINT layerPos = { 0, 0 };
1094     ::UpdateLayeredWindow(m_viewWindow, hdcScreen, 0, &windowSize, hdcMem.get(), &layerPos, 0, &blendFunction, ULW_ALPHA);
1095
1096     ::SelectObject(hdcMem.get(), hbmOld);
1097
1098     m_needsDisplay = false;
1099 }
1100
1101 void WebView::paint(HDC dc, LPARAM options)
1102 {
1103     LOCAL_GDI_COUNTER(0, __FUNCTION__);
1104
1105     if (isAcceleratedCompositing() && !usesLayeredWindow()) {
1106 #if USE(CA)
1107         m_layerTreeHost->flushPendingLayerChangesNow();
1108 #elif USE(TEXTURE_MAPPER_GL)
1109         m_acceleratedCompositingContext->flushAndRenderLayers();
1110 #endif
1111         // Flushing might have taken us out of compositing mode.
1112         if (isAcceleratedCompositing()) {
1113 #if USE(CA)
1114             // FIXME: We need to paint into dc (if provided). <http://webkit.org/b/52578>
1115             m_layerTreeHost->paint();
1116 #endif
1117             ::ValidateRect(m_viewWindow, 0);
1118             return;
1119         }
1120     }
1121
1122     Frame* coreFrame = core(m_mainFrame);
1123     if (!coreFrame)
1124         return;
1125     FrameView* frameView = coreFrame->view();
1126
1127     RECT rcPaint;
1128     HDC hdc;
1129     GDIObject<HRGN> region;
1130     int regionType = NULLREGION;
1131     PAINTSTRUCT ps;
1132     WindowsToPaint windowsToPaint;
1133     if (!dc) {
1134         region = adoptGDIObject(::CreateRectRgn(0, 0, 0, 0));
1135         regionType = GetUpdateRgn(m_viewWindow, region.get(), false);
1136         hdc = BeginPaint(m_viewWindow, &ps);
1137         rcPaint = ps.rcPaint;
1138         // We're painting to the screen, and our child windows can handle
1139         // painting themselves to the screen.
1140         windowsToPaint = PaintWebViewOnly;
1141     } else {
1142         hdc = dc;
1143         ::GetClientRect(m_viewWindow, &rcPaint);
1144         if (options & PRF_ERASEBKGND)
1145             ::FillRect(hdc, &rcPaint, (HBRUSH)GetStockObject(WHITE_BRUSH));
1146         // Since we aren't painting to the screen, we want to paint all our
1147         // children into the HDC.
1148         windowsToPaint = PaintWebViewAndChildren;
1149     }
1150
1151     bool backingStoreCompletelyDirty = ensureBackingStore();
1152     if (!m_backingStoreBitmap) {
1153         if (!dc)
1154             EndPaint(m_viewWindow, &ps);
1155         return;
1156     }
1157
1158     m_paintCount++;
1159
1160     auto bitmapDC = adoptGDIObject(::CreateCompatibleDC(hdc));
1161     HGDIOBJ oldBitmap = ::SelectObject(bitmapDC.get(), m_backingStoreBitmap->get());
1162
1163     // Update our backing store if needed.
1164     updateBackingStore(frameView, bitmapDC.get(), backingStoreCompletelyDirty, windowsToPaint);
1165
1166     // Now we blit the updated backing store
1167     IntRect windowDirtyRect = rcPaint;
1168     
1169     // Apply the same heuristic for this update region too.
1170     Vector<IntRect> blitRects;
1171     if (region && regionType == COMPLEXREGION)
1172         getUpdateRects(region.get(), windowDirtyRect, blitRects);
1173     else
1174         blitRects.append(windowDirtyRect);
1175
1176     for (unsigned i = 0; i < blitRects.size(); ++i)
1177         paintIntoWindow(bitmapDC.get(), hdc, blitRects[i]);
1178
1179     ::SelectObject(bitmapDC.get(), oldBitmap);
1180
1181     if (!dc)
1182         EndPaint(m_viewWindow, &ps);
1183
1184     m_paintCount--;
1185
1186     if (active())
1187         cancelDeleteBackingStoreSoon();
1188     else
1189         deleteBackingStoreSoon();
1190 }
1191
1192 void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, const IntRect& dirtyRect, WindowsToPaint windowsToPaint)
1193 {
1194     // FIXME: This function should never be called in accelerated compositing mode, and we should
1195     // assert as such. But currently it *is* sometimes called, so we can't assert yet. See
1196     // <http://webkit.org/b/58539>.
1197
1198     LOCAL_GDI_COUNTER(0, __FUNCTION__);
1199
1200     // FIXME: We want an assert here saying that the dirtyRect is inside the clienRect,
1201     // but it was being hit during our layout tests, and is being investigated in
1202     // http://webkit.org/b/29350.
1203
1204     RECT rect = dirtyRect;
1205
1206 #if FLASH_BACKING_STORE_REDRAW
1207     {
1208         HWndDC dc(m_viewWindow);
1209         auto yellowBrush = adoptGDIObject(::CreateSolidBrush(RGB(255, 255, 0)));
1210         FillRect(dc, &rect, yellowBrush.get());
1211         GdiFlush();
1212         Sleep(50);
1213         paintIntoWindow(bitmapDC, dc, dirtyRect);
1214     }
1215 #endif
1216
1217     GraphicsContext gc(bitmapDC, m_transparent);
1218     gc.setShouldIncludeChildWindows(windowsToPaint == PaintWebViewAndChildren);
1219     gc.save();
1220     if (m_transparent)
1221         gc.clearRect(dirtyRect);
1222     else
1223         FillRect(bitmapDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
1224
1225     COMPtr<IWebUIDelegatePrivate2> uiPrivate(Query, m_uiDelegate);
1226     if (uiPrivate)
1227         uiPrivate->drawBackground(this, bitmapDC, &rect);
1228
1229     if (frameView && frameView->frame().contentRenderer()) {
1230         gc.clip(dirtyRect);
1231         frameView->paint(&gc, dirtyRect);
1232         if (m_shouldInvertColors)
1233             gc.fillRect(dirtyRect, Color::white, ColorSpaceDeviceRGB, CompositeDifference);
1234     }
1235     gc.restore();
1236 }
1237
1238 void WebView::paintIntoWindow(HDC bitmapDC, HDC windowDC, const IntRect& dirtyRect)
1239 {
1240     // FIXME: This function should never be called in accelerated compositing mode, and we should
1241     // assert as such. But currently it *is* sometimes called, so we can't assert yet. See
1242     // <http://webkit.org/b/58539>.
1243
1244     LOCAL_GDI_COUNTER(0, __FUNCTION__);
1245 #if FLASH_WINDOW_REDRAW
1246     auto greenBrush = adoptGDIObject(::CreateSolidBrush(RGB(0, 255, 0)));
1247     RECT rect = dirtyRect;
1248     FillRect(windowDC, &rect, greenBrush.get());
1249     GdiFlush();
1250     Sleep(50);
1251 #endif
1252
1253     // Blit the dirty rect from the backing store into the same position
1254     // in the destination DC.
1255     BitBlt(windowDC, dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), bitmapDC,
1256            dirtyRect.x(), dirtyRect.y(), SRCCOPY);
1257
1258     m_needsDisplay = false;
1259 }
1260
1261 void WebView::frameRect(RECT* rect)
1262 {
1263     ::GetWindowRect(m_viewWindow, rect);
1264 }
1265
1266 class WindowCloseTimer : public WebCore::SuspendableTimer {
1267 public:
1268     static WindowCloseTimer* create(WebView*);
1269
1270 private:
1271     WindowCloseTimer(ScriptExecutionContext&, WebView*);
1272     virtual void contextDestroyed();
1273     virtual void fired();
1274
1275     WebView* m_webView;
1276 };
1277
1278 WindowCloseTimer* WindowCloseTimer::create(WebView* webView)
1279 {
1280     ASSERT_ARG(webView, webView);
1281     Frame* frame = core(webView->topLevelFrame());
1282     ASSERT(frame);
1283     if (!frame)
1284         return nullptr;
1285
1286     Document* document = frame->document();
1287     ASSERT(document);
1288     if (!document)
1289         return nullptr;
1290
1291     return new WindowCloseTimer(*document, webView);
1292 }
1293
1294 WindowCloseTimer::WindowCloseTimer(ScriptExecutionContext& context, WebView* webView)
1295     : SuspendableTimer(context)
1296     , m_webView(webView)
1297 {
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     PageConfiguration configuration;
2796     configuration.chromeClient = new WebChromeClient(this);
2797     configuration.contextMenuClient = new WebContextMenuClient(this);
2798     configuration.editorClient = new WebEditorClient(this);
2799     configuration.dragClient = new WebDragClient(this);
2800 #if ENABLE(INSPECTOR)
2801     configuration.inspectorClient = m_inspectorClient;
2802 #endif // ENABLE(INSPECTOR)
2803     configuration.loaderClientForMainFrame = new WebFrameLoaderClient;
2804     configuration.progressTrackerClient = static_cast<WebFrameLoaderClient*>(configuration.loaderClientForMainFrame);
2805     configuration.visitedLinkStore = &WebVisitedLinkStore::shared();
2806
2807     m_page = new Page(configuration);
2808     provideGeolocationTo(m_page, new WebGeolocationClient(this));
2809
2810     unsigned layoutMilestones = DidFirstLayout | DidFirstVisuallyNonEmptyLayout;
2811     m_page->addLayoutMilestones(static_cast<LayoutMilestones>(layoutMilestones));
2812
2813     BString localStoragePath;
2814     if (SUCCEEDED(m_preferences->localStorageDatabasePath(&localStoragePath)))
2815         m_page->settings().setLocalStorageDatabasePath(toString(localStoragePath));
2816
2817     if (m_uiDelegate) {
2818         BString path;
2819         if (SUCCEEDED(m_uiDelegate->ftpDirectoryTemplatePath(this, &path)))
2820             m_page->settings().setFTPDirectoryTemplatePath(toString(path));
2821     }
2822
2823     WebFrame* webFrame = WebFrame::createInstance();
2824     webFrame->initWithWebView(this, m_page);
2825     static_cast<WebFrameLoaderClient&>(m_page->mainFrame().loader().client()).setWebFrame(webFrame);
2826     m_mainFrame = webFrame;
2827     webFrame->Release(); // The WebFrame is owned by the Frame, so release our reference to it.
2828
2829     m_page->mainFrame().tree().setName(toString(frameName));
2830     m_page->mainFrame().init();
2831     setGroupName(groupName);
2832
2833     addToAllWebViewsSet();
2834
2835     #pragma warning(suppress: 4244)
2836     SetWindowLongPtr(m_viewWindow, 0, (LONG_PTR)this);
2837     ShowWindow(m_viewWindow, SW_SHOW);
2838
2839     initializeToolTipWindow();
2840     windowAncestryDidChange();
2841
2842     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
2843     notifyCenter->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
2844     m_preferences->postPreferencesChangesNotification();
2845
2846     setSmartInsertDeleteEnabled(TRUE);
2847     return hr;
2848 }
2849
2850 static bool initCommonControls()
2851 {
2852     static bool haveInitialized = false;
2853     if (haveInitialized)
2854         return true;
2855
2856     INITCOMMONCONTROLSEX init;
2857     init.dwSize = sizeof(init);
2858     init.dwICC = ICC_TREEVIEW_CLASSES;
2859     haveInitialized = !!::InitCommonControlsEx(&init);
2860     return haveInitialized;
2861 }
2862
2863 void WebView::initializeToolTipWindow()
2864 {
2865     if (!initCommonControls())
2866         return;
2867
2868     m_toolTipHwnd = CreateWindowEx(WS_EX_TRANSPARENT, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
2869                                    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2870                                    m_viewWindow, 0, 0, 0);
2871     if (!m_toolTipHwnd)
2872         return;
2873
2874     TOOLINFO info = {0};
2875     info.cbSize = sizeof(info);
2876     info.uFlags = TTF_IDISHWND | TTF_SUBCLASS ;
2877     info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
2878
2879     ::SendMessage(m_toolTipHwnd, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info));
2880     ::SendMessage(m_toolTipHwnd, TTM_SETMAXTIPWIDTH, 0, maxToolTipWidth);
2881
2882     ::SetWindowPos(m_toolTipHwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
2883 }
2884
2885 void WebView::setToolTip(const String& toolTip)
2886 {
2887     if (!m_toolTipHwnd)
2888         return;
2889
2890     if (toolTip == m_toolTip)
2891         return;
2892
2893     m_toolTip = toolTip;
2894
2895     if (!m_toolTip.isEmpty()) {
2896         TOOLINFO info = {0};
2897         info.cbSize = sizeof(info);
2898         info.uFlags = TTF_IDISHWND;
2899         info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
2900         Vector<UChar> toolTipCharacters = m_toolTip.charactersWithNullTermination(); // Retain buffer long enough to make the SendMessage call
2901         info.lpszText = const_cast<UChar*>(toolTipCharacters.data());
2902         ::SendMessage(m_toolTipHwnd, TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info));
2903     }
2904
2905     ::SendMessage(m_toolTipHwnd, TTM_ACTIVATE, !m_toolTip.isEmpty(), 0);
2906 }
2907
2908 HRESULT WebView::notifyDidAddIcon(IWebNotification* notification)
2909 {
2910     COMPtr<IPropertyBag> propertyBag;
2911     HRESULT hr = notification->userInfo(&propertyBag);
2912     if (FAILED(hr))
2913         return hr;
2914     if (!propertyBag)
2915         return E_FAIL;
2916
2917     COMVariant iconUserInfoURL;
2918     hr = propertyBag->Read(WebIconDatabase::iconDatabaseNotificationUserInfoURLKey(), &iconUserInfoURL, 0);
2919     if (FAILED(hr))
2920         return hr;
2921
2922     if (iconUserInfoURL.variantType() != VT_BSTR)
2923         return E_FAIL;
2924
2925     String mainFrameURL;
2926     if (m_mainFrame)
2927         mainFrameURL = m_mainFrame->url().string();
2928
2929     if (!mainFrameURL.isEmpty() && mainFrameURL == toString(V_BSTR(&iconUserInfoURL)))
2930         dispatchDidReceiveIconFromWebFrame(m_mainFrame);
2931
2932     return hr;
2933 }
2934
2935 void WebView::registerForIconNotification(bool listen)
2936 {
2937     IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
2938     if (listen)
2939         nc->addObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
2940     else
2941         nc->removeObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
2942 }
2943
2944 void WebView::dispatchDidReceiveIconFromWebFrame(WebFrame* frame)
2945 {
2946     registerForIconNotification(false);
2947
2948     if (m_frameLoadDelegate) {
2949         String str = frame->url().string();
2950
2951         IntSize sz(16, 16);
2952
2953         BitmapInfo bmInfo = BitmapInfo::create(sz);
2954
2955         HBITMAP hBitmap = nullptr;
2956
2957         Image* icon = iconDatabase().synchronousIconForPageURL(str, sz);
2958
2959         if (icon && icon->width()) {
2960             HWndDC dc(0);
2961             hBitmap = CreateDIBSection(dc, &bmInfo, DIB_RGB_COLORS, 0, 0, 0);
2962             icon->getHBITMAPOfSize(hBitmap, &sz);
2963         }
2964
2965         HRESULT hr = m_frameLoadDelegate->didReceiveIcon(this, hBitmap, frame);
2966         if ((hr == E_NOTIMPL) && hBitmap)
2967             DeleteObject(hBitmap);
2968     }
2969 }
2970
2971 HRESULT WebView::setAccessibilityDelegate(
2972     /* [in] */ IAccessibilityDelegate* d)
2973 {
2974     m_accessibilityDelegate = d;
2975     return S_OK;
2976 }
2977
2978 HRESULT WebView::accessibilityDelegate(
2979     /* [out][retval] */ IAccessibilityDelegate** d)
2980 {
2981     if (!m_accessibilityDelegate)
2982         return E_POINTER;
2983
2984     return m_accessibilityDelegate.copyRefTo(d);
2985 }
2986
2987 HRESULT STDMETHODCALLTYPE WebView::setUIDelegate( 
2988     /* [in] */ IWebUIDelegate* d)
2989 {
2990     m_uiDelegate = d;
2991
2992     if (m_uiDelegatePrivate)
2993         m_uiDelegatePrivate = 0;
2994
2995     if (d) {
2996         if (FAILED(d->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&m_uiDelegatePrivate)))
2997             m_uiDelegatePrivate = 0;
2998     }
2999
3000     return S_OK;
3001 }
3002
3003 HRESULT STDMETHODCALLTYPE WebView::uiDelegate( 
3004     /* [out][retval] */ IWebUIDelegate** d)
3005 {
3006     if (!m_uiDelegate)
3007         return E_FAIL;
3008
3009     return m_uiDelegate.copyRefTo(d);
3010 }
3011
3012 HRESULT STDMETHODCALLTYPE WebView::setResourceLoadDelegate( 
3013     /* [in] */ IWebResourceLoadDelegate* d)
3014 {
3015     m_resourceLoadDelegate = d;
3016     return S_OK;
3017 }
3018
3019 HRESULT STDMETHODCALLTYPE WebView::resourceLoadDelegate( 
3020     /* [out][retval] */ IWebResourceLoadDelegate** d)
3021 {
3022     if (!m_resourceLoadDelegate)
3023         return E_FAIL;
3024
3025     return m_resourceLoadDelegate.copyRefTo(d);
3026 }
3027
3028 HRESULT STDMETHODCALLTYPE WebView::setDownloadDelegate( 
3029     /* [in] */ IWebDownloadDelegate* d)
3030 {
3031     m_downloadDelegate = d;
3032     return S_OK;
3033 }
3034
3035 HRESULT STDMETHODCALLTYPE WebView::downloadDelegate( 
3036     /* [out][retval] */ IWebDownloadDelegate** d)
3037 {
3038     if (!m_downloadDelegate)
3039         return E_FAIL;
3040
3041     return m_downloadDelegate.copyRefTo(d);
3042 }
3043
3044 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegate( 
3045     /* [in] */ IWebFrameLoadDelegate* d)
3046 {
3047     m_frameLoadDelegate = d;
3048     return S_OK;
3049 }
3050
3051 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegate( 
3052     /* [out][retval] */ IWebFrameLoadDelegate** d)
3053 {
3054     if (!m_frameLoadDelegate)
3055         return E_FAIL;
3056
3057     return m_frameLoadDelegate.copyRefTo(d);
3058 }
3059
3060 HRESULT STDMETHODCALLTYPE WebView::setPolicyDelegate( 
3061     /* [in] */ IWebPolicyDelegate* d)
3062 {
3063     m_policyDelegate = d;
3064     return S_OK;
3065 }
3066
3067 HRESULT STDMETHODCALLTYPE WebView::policyDelegate( 
3068     /* [out][retval] */ IWebPolicyDelegate** d)
3069 {
3070     if (!m_policyDelegate)
3071         return E_FAIL;
3072     return m_policyDelegate.copyRefTo(d);
3073 }
3074
3075 HRESULT STDMETHODCALLTYPE WebView::mainFrame( 
3076     /* [out][retval] */ IWebFrame** frame)
3077 {
3078     if (!frame) {
3079         ASSERT_NOT_REACHED();
3080         return E_POINTER;
3081     }
3082
3083     *frame = m_mainFrame;
3084     if (!m_mainFrame)
3085         return E_FAIL;
3086
3087     m_mainFrame->AddRef();
3088     return S_OK;
3089 }
3090
3091 HRESULT STDMETHODCALLTYPE WebView::focusedFrame( 
3092     /* [out][retval] */ IWebFrame** frame)
3093 {
3094     if (!frame) {
3095         ASSERT_NOT_REACHED();
3096         return E_POINTER;
3097     }
3098
3099     *frame = 0;
3100     Frame* f = m_page->focusController().focusedFrame();
3101     if (!f)
3102         return E_FAIL;
3103
3104     WebFrame* webFrame = kit(f);
3105     if (!webFrame)
3106         return E_FAIL;
3107
3108     return webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
3109 }
3110
3111 HRESULT STDMETHODCALLTYPE WebView::backForwardList( 
3112     /* [out][retval] */ IWebBackForwardList** list)
3113 {
3114     if (!m_useBackForwardList)
3115         return E_FAIL;
3116  
3117     *list = WebBackForwardList::createInstance(static_cast<WebCore::BackForwardList*>(m_page->backForward().client()));
3118
3119     return S_OK;
3120 }
3121
3122 HRESULT STDMETHODCALLTYPE WebView::setMaintainsBackForwardList( 
3123     /* [in] */ BOOL flag)
3124 {
3125     m_useBackForwardList = !!flag;
3126     return S_OK;
3127 }
3128
3129 HRESULT STDMETHODCALLTYPE WebView::goBack( 
3130     /* [retval][out] */ BOOL* succeeded)
3131 {
3132     *succeeded = m_page->backForward().goBack();
3133     return S_OK;
3134 }
3135
3136 HRESULT STDMETHODCALLTYPE WebView::goForward( 
3137     /* [retval][out] */ BOOL* succeeded)
3138 {
3139     *succeeded = m_page->backForward().goForward();
3140     return S_OK;
3141 }
3142
3143 HRESULT STDMETHODCALLTYPE WebView::goToBackForwardItem( 
3144     /* [in] */ IWebHistoryItem* item,
3145     /* [retval][out] */ BOOL* succeeded)
3146 {
3147     *succeeded = FALSE;
3148
3149     COMPtr<WebHistoryItem> webHistoryItem;
3150     HRESULT hr = item->QueryInterface(&webHistoryItem);
3151     if (FAILED(hr))
3152         return hr;
3153
3154     m_page->goToItem(webHistoryItem->historyItem(), FrameLoadType::IndexedBackForward);
3155     *succeeded = TRUE;
3156
3157     return S_OK;
3158 }
3159
3160 HRESULT STDMETHODCALLTYPE WebView::setTextSizeMultiplier( 
3161     /* [in] */ float multiplier)
3162 {
3163     if (!m_mainFrame)
3164         return E_FAIL;
3165     setZoomMultiplier(multiplier, true);
3166     return S_OK;
3167 }
3168
3169 HRESULT STDMETHODCALLTYPE WebView::setPageSizeMultiplier( 
3170     /* [in] */ float multiplier)
3171 {
3172     if (!m_mainFrame)
3173         return E_FAIL;
3174     setZoomMultiplier(multiplier, false);
3175     return S_OK;
3176 }
3177
3178 void WebView::setZoomMultiplier(float multiplier, bool isTextOnly)
3179 {
3180     m_zoomMultiplier = multiplier;
3181     m_zoomsTextOnly = isTextOnly;
3182
3183     if (Frame* coreFrame = core(m_mainFrame)) {
3184         if (m_zoomsTextOnly)
3185             coreFrame->setPageAndTextZoomFactors(1, multiplier);
3186         else
3187             coreFrame->setPageAndTextZoomFactors(multiplier, 1);
3188     }
3189 }
3190
3191 HRESULT STDMETHODCALLTYPE WebView::textSizeMultiplier( 
3192     /* [retval][out] */ float* multiplier)
3193 {
3194     *multiplier = zoomMultiplier(true);
3195     return S_OK;
3196 }
3197
3198 HRESULT STDMETHODCALLTYPE WebView::pageSizeMultiplier( 
3199     /* [retval][out] */ float* multiplier)
3200 {
3201     *multiplier = zoomMultiplier(false);
3202     return S_OK;
3203 }
3204
3205 float WebView::zoomMultiplier(bool isTextOnly)
3206 {
3207     if (isTextOnly != m_zoomsTextOnly)
3208         return 1.0f;
3209     return m_zoomMultiplier;
3210 }
3211
3212 HRESULT STDMETHODCALLTYPE WebView::setApplicationNameForUserAgent( 
3213     /* [in] */ BSTR applicationName)
3214 {
3215     m_applicationName = toString(applicationName);
3216     m_userAgentStandard = String();
3217     return S_OK;
3218 }
3219
3220 HRESULT STDMETHODCALLTYPE WebView::applicationNameForUserAgent( 
3221     /* [retval][out] */ BSTR* applicationName)
3222 {
3223     *applicationName = BString(m_applicationName).release();
3224     if (!*applicationName && m_applicationName.length())
3225         return E_OUTOFMEMORY;
3226     return S_OK;
3227 }
3228
3229 HRESULT STDMETHODCALLTYPE WebView::setCustomUserAgent( 
3230     /* [in] */ BSTR userAgentString)
3231 {
3232     m_userAgentOverridden = userAgentString;
3233     m_userAgentCustom = toString(userAgentString);
3234     return S_OK;
3235 }
3236
3237 HRESULT STDMETHODCALLTYPE WebView::customUserAgent( 
3238     /* [retval][out] */ BSTR* userAgentString)
3239 {
3240     *userAgentString = 0;
3241     if (!m_userAgentOverridden)
3242         return S_OK;
3243     *userAgentString = BString(m_userAgentCustom).release();
3244     if (!*userAgentString && m_userAgentCustom.length())
3245         return E_OUTOFMEMORY;
3246     return S_OK;
3247 }
3248
3249 HRESULT STDMETHODCALLTYPE WebView::userAgentForURL( 
3250     /* [in] */ BSTR url,
3251     /* [retval][out] */ BSTR* userAgent)
3252 {
3253     String userAgentString = userAgentForKURL(MarshallingHelpers::BSTRToKURL(url));
3254     *userAgent = BString(userAgentString).release();
3255     if (!*userAgent && userAgentString.length())
3256         return E_OUTOFMEMORY;
3257     return S_OK;
3258 }
3259
3260 HRESULT STDMETHODCALLTYPE WebView::supportsTextEncoding( 
3261     /* [retval][out] */ BOOL* supports)
3262 {
3263     *supports = TRUE;
3264     return S_OK;
3265 }
3266
3267 HRESULT STDMETHODCALLTYPE WebView::setCustomTextEncodingName( 
3268     /* [in] */ BSTR encodingName)
3269 {
3270     if (!m_mainFrame)
3271         return E_FAIL;
3272
3273     HRESULT hr;
3274     BString oldEncoding;
3275     hr = customTextEncodingName(&oldEncoding);
3276     if (FAILED(hr))
3277         return hr;
3278
3279     if (oldEncoding != encodingName && (!oldEncoding || !encodingName || wcscmp(oldEncoding, encodingName))) {
3280         if (Frame* coreFrame = core(m_mainFrame))
3281             coreFrame->loader().reloadWithOverrideEncoding(toString(encodingName));
3282     }
3283
3284     return S_OK;
3285 }
3286
3287 HRESULT STDMETHODCALLTYPE WebView::customTextEncodingName( 
3288     /* [retval][out] */ BSTR* encodingName)
3289 {
3290     HRESULT hr = S_OK;
3291     COMPtr<IWebDataSource> dataSource;
3292     COMPtr<WebDataSource> dataSourceImpl;
3293     *encodingName = 0;
3294
3295     if (!m_mainFrame)
3296         return E_FAIL;
3297
3298     if (FAILED(m_mainFrame->provisionalDataSource(&dataSource)) || !dataSource) {
3299         hr = m_mainFrame->dataSource(&dataSource);
3300         if (FAILED(hr) || !dataSource)
3301             return hr;
3302     }
3303
3304     hr = dataSource->QueryInterface(IID_WebDataSource, (void**)&dataSourceImpl);
3305     if (FAILED(hr))
3306         return hr;
3307
3308     BString str = dataSourceImpl->documentLoader()->overrideEncoding();
3309     if (FAILED(hr))
3310         return hr;
3311
3312     if (!*encodingName)
3313         *encodingName = BString(m_overrideEncoding).release();
3314
3315     if (!*encodingName && m_overrideEncoding.length())
3316         return E_OUTOFMEMORY;
3317
3318     return S_OK;
3319 }
3320
3321 HRESULT STDMETHODCALLTYPE WebView::setMediaStyle( 
3322     /* [in] */ BSTR /*media*/)
3323 {
3324     ASSERT_NOT_REACHED();
3325     return E_NOTIMPL;
3326 }
3327
3328 HRESULT STDMETHODCALLTYPE WebView::mediaStyle( 
3329     /* [retval][out] */ BSTR* /*media*/)
3330 {
3331     ASSERT_NOT_REACHED();
3332     return E_NOTIMPL;
3333 }
3334
3335 HRESULT STDMETHODCALLTYPE WebView::stringByEvaluatingJavaScriptFromString( 
3336     /* [in] */ BSTR script, // assumes input does not have "JavaScript" at the begining.
3337     /* [retval][out] */ BSTR* result)
3338 {
3339     if (!result) {
3340         ASSERT_NOT_REACHED();
3341         return E_POINTER;
3342     }
3343
3344     *result = 0;
3345
3346     Frame* coreFrame = core(m_mainFrame);
3347     if (!coreFrame)
3348         return E_FAIL;
3349
3350     JSC::JSValue scriptExecutionResult = coreFrame->script().executeScript(WTF::String(script), true).jsValue();
3351     if (!scriptExecutionResult)
3352         return E_FAIL;
3353     else if (scriptExecutionResult.isString()) {
3354         JSC::ExecState* exec = coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec();
3355         JSC::JSLockHolder lock(exec);
3356         *result = BString(scriptExecutionResult.getString(exec));
3357     }
3358
3359     return S_OK;
3360 }
3361
3362 HRESULT STDMETHODCALLTYPE WebView::windowScriptObject( 
3363     /* [retval][out] */ IWebScriptObject** /*webScriptObject*/)
3364 {
3365     ASSERT_NOT_REACHED();
3366     return E_NOTIMPL;
3367 }
3368
3369 HRESULT STDMETHODCALLTYPE WebView::setPreferences( 
3370     /* [in] */ IWebPreferences* prefs)
3371 {
3372     if (!prefs)
3373         prefs = WebPreferences::sharedStandardPreferences();
3374
3375     if (m_preferences == prefs)
3376         return S_OK;
3377
3378     COMPtr<WebPreferences> webPrefs(Query, prefs);
3379     if (!webPrefs)
3380         return E_NOINTERFACE;
3381     webPrefs->willAddToWebView();
3382
3383     COMPtr<WebPreferences> oldPrefs = m_preferences;
3384
3385     IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
3386     nc->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3387
3388     BString identifier;
3389     oldPrefs->identifier(&identifier);
3390     oldPrefs->didRemoveFromWebView();
3391     oldPrefs = 0; // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
3392
3393     m_preferences = webPrefs;
3394
3395     if (identifier)
3396         WebPreferences::removeReferenceForIdentifier(identifier);
3397
3398     nc->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3399
3400     m_preferences->postPreferencesChangesNotification();
3401
3402     return S_OK;
3403 }
3404
3405 HRESULT STDMETHODCALLTYPE WebView::preferences( 
3406     /* [retval][out] */ IWebPreferences** prefs)
3407 {
3408     if (!prefs)
3409         return E_POINTER;
3410     *prefs = m_preferences.get();
3411     if (m_preferences)
3412         m_preferences->AddRef();
3413     return S_OK;
3414 }
3415
3416 HRESULT STDMETHODCALLTYPE WebView::setPreferencesIdentifier( 
3417     /* [in] */ BSTR /*anIdentifier*/)
3418 {
3419     ASSERT_NOT_REACHED();
3420     return E_NOTIMPL;
3421 }
3422
3423 HRESULT STDMETHODCALLTYPE WebView::preferencesIdentifier( 
3424     /* [retval][out] */ BSTR* /*anIdentifier*/)
3425 {
3426     ASSERT_NOT_REACHED();
3427     return E_NOTIMPL;
3428 }
3429
3430 static void systemParameterChanged(WPARAM parameter)
3431 {
3432 #if USE(CG)
3433     if (parameter == SPI_SETFONTSMOOTHING || parameter == SPI_SETFONTSMOOTHINGTYPE || parameter == SPI_SETFONTSMOOTHINGCONTRAST || parameter == SPI_SETFONTSMOOTHINGORIENTATION)
3434         wkSystemFontSmoothingChanged();
3435 #endif
3436 }
3437
3438 void WebView::windowReceivedMessage(HWND, UINT message, WPARAM wParam, LPARAM)
3439 {
3440     switch (message) {
3441     case WM_NCACTIVATE:
3442         updateActiveStateSoon();
3443         if (!wParam)
3444             deleteBackingStoreSoon();
3445         break;
3446     case WM_SETTINGCHANGE:
3447         systemParameterChanged(wParam);
3448         break;
3449     }
3450 }
3451
3452 void WebView::updateActiveStateSoon() const
3453 {
3454     // This function is called while processing the WM_NCACTIVATE message.
3455     // While processing WM_NCACTIVATE when we are being deactivated, GetActiveWindow() will
3456     // still return our window. If we were to call updateActiveState() in that case, we would
3457     // wrongly think that we are still the active window. To work around this, we update our
3458     // active state after a 0-delay timer fires, at which point GetActiveWindow() will return
3459     // the newly-activated window.
3460
3461     SetTimer(m_viewWindow, UpdateActiveStateTimer, 0, 0);
3462 }
3463
3464 void WebView::deleteBackingStoreSoon()
3465 {
3466     if (pendingDeleteBackingStoreSet().size() > 2) {
3467         Vector<WebView*> views;
3468         HashSet<WebView*>::iterator end = pendingDeleteBackingStoreSet().end();
3469         for (HashSet<WebView*>::iterator it = pendingDeleteBackingStoreSet().begin(); it != end; ++it)
3470             views.append(*it);
3471         for (int i = 0; i < views.size(); ++i)
3472             views[i]->deleteBackingStore();
3473         ASSERT(pendingDeleteBackingStoreSet().isEmpty());
3474     }
3475
3476     pendingDeleteBackingStoreSet().add(this);
3477     m_deleteBackingStoreTimerActive = true;
3478     SetTimer(m_viewWindow, DeleteBackingStoreTimer, delayBeforeDeletingBackingStoreMsec, 0);
3479 }
3480
3481 void WebView::cancelDeleteBackingStoreSoon()
3482 {
3483     if (!m_deleteBackingStoreTimerActive)
3484         return;
3485     pendingDeleteBackingStoreSet().remove(this);
3486     m_deleteBackingStoreTimerActive = false;
3487     KillTimer(m_viewWindow, DeleteBackingStoreTimer);
3488 }
3489
3490 HRESULT WebView::setHostWindow(/* [in] */ HWND window)
3491 {
3492     if (m_viewWindow) {
3493         if (window)
3494             SetParent(m_viewWindow, window);
3495         else if (!isBeingDestroyed()) {
3496             // Turn the WebView into a message-only window so it will no longer be a child of the
3497             // old host window and will be hidden from screen. We only do this when
3498             // isBeingDestroyed() is false because doing this while handling WM_DESTROY can leave
3499             // m_viewWindow in a weird state (see <http://webkit.org/b/29337>).
3500             SetParent(m_viewWindow, HWND_MESSAGE);
3501         }
3502     }
3503
3504     m_hostWindow = window;
3505
3506     windowAncestryDidChange();
3507
3508     return S_OK;
3509 }
3510
3511 HRESULT WebView::hostWindow(/* [retval][out] */ HWND* window)
3512 {
3513     *window = m_hostWindow;
3514     return S_OK;
3515 }
3516
3517
3518 static Frame *incrementFrame(Frame *curr, bool forward, bool wrapFlag)
3519 {
3520     return forward
3521         ? curr->tree().traverseNextWithWrap(wrapFlag)
3522         : curr->tree().traversePreviousWithWrap(wrapFlag);
3523 }
3524
3525 HRESULT STDMETHODCALLTYPE WebView::searchFor( 
3526     /* [in] */ BSTR str,
3527     /* [in] */ BOOL forward,
3528     /* [in] */ BOOL caseFlag,
3529     /* [in] */ BOOL wrapFlag,
3530     /* [retval][out] */ BOOL* found)
3531 {
3532     if (!found)
3533         return E_INVALIDARG;
3534     
3535     if (!m_page)
3536         return E_UNEXPECTED;
3537
3538     if (!str || !SysStringLen(str))
3539         return E_INVALIDARG;
3540
3541     FindOptions options = (caseFlag ? 0 : CaseInsensitive) | (forward ? 0 : Backwards) | (wrapFlag ? WrapAround : 0);
3542     *found = m_page->findString(toString(str), options);
3543     return S_OK;
3544 }
3545
3546 bool WebView::active()
3547 {
3548     HWND activeWindow = GetActiveWindow();
3549     if (usesLayeredWindow() && activeWindow == m_viewWindow)
3550         return true;
3551
3552     return (activeWindow && m_topLevelParent == findTopLevelParent(activeWindow));
3553 }
3554
3555 void WebView::updateActiveState()
3556 {
3557     m_page->focusController().setActive(active());
3558 }
3559
3560 HRESULT STDMETHODCALLTYPE WebView::updateFocusedAndActiveState()
3561 {
3562     updateActiveState();
3563
3564     bool active = m_page->focusController().isActive();
3565     Frame& mainFrame = m_page->mainFrame();
3566     Frame& focusedFrame = m_page->focusController().focusedOrMainFrame();
3567     mainFrame.selection().setFocused(active && &mainFrame == &focusedFrame);
3568
3569     return S_OK;
3570 }
3571
3572 HRESULT STDMETHODCALLTYPE WebView::executeCoreCommandByName(BSTR name, BSTR value)
3573 {
3574     m_page->focusController().focusedOrMainFrame().editor().command(toString(name)).execute(toString(value));
3575
3576     return S_OK;
3577 }
3578
3579 HRESULT STDMETHODCALLTYPE WebView::clearMainFrameName()
3580 {
3581     m_page->mainFrame().tree().clearName();
3582
3583     return S_OK;
3584 }
3585
3586 HRESULT STDMETHODCALLTYPE WebView::markAllMatchesForText(
3587     BSTR str, BOOL caseSensitive, BOOL highlight, UINT limit, UINT* matches)
3588 {
3589     if (!matches)
3590         return E_INVALIDARG;
3591
3592     if (!m_page)
3593         return E_UNEXPECTED;
3594
3595     if (!str || !SysStringLen(str))
3596         return E_INVALIDARG;
3597
3598     *matches = m_page->markAllMatchesForText(toString(str), caseSensitive ? TextCaseSensitive : TextCaseInsensitive, highlight, limit);
3599     return S_OK;
3600 }
3601
3602 HRESULT STDMETHODCALLTYPE WebView::unmarkAllTextMatches()
3603 {
3604     if (!m_page)
3605         return E_UNEXPECTED;
3606
3607     m_page->unmarkAllTextMatches();
3608     return S_OK;
3609 }
3610
3611 HRESULT STDMETHODCALLTYPE WebView::rectsForTextMatches(
3612     IEnumTextMatches** pmatches)
3613 {
3614     Vector<IntRect> allRects;
3615     WebCore::Frame* frame = &m_page->mainFrame();
3616     do {
3617         if (Document* document = frame->document()) {
3618             IntRect visibleRect = frame->view()->visibleContentRect();
3619             Vector<IntRect> frameRects = document->markers().renderedRectsForMarkers(DocumentMarker::TextMatch);
3620             IntPoint frameOffset(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height());
3621             frameOffset = frame->view()->convertToContainingWindow(frameOffset);
3622
3623             Vector<IntRect>::iterator end = frameRects.end();
3624             for (Vector<IntRect>::iterator it = frameRects.begin(); it < end; it++) {
3625                 it->intersect(visibleRect);
3626                 it->move(frameOffset.x(), frameOffset.y());
3627                 allRects.append(*it);
3628             }
3629         }
3630         frame = incrementFrame(frame, true, false);
3631     } while (frame);
3632
3633     return createMatchEnumerator(&allRects, pmatches);
3634 }
3635
3636 HRESULT STDMETHODCALLTYPE WebView::generateSelectionImage(BOOL forceWhiteText, HBITMAP* hBitmap)
3637 {
3638     *hBitmap = 0;
3639
3640     WebCore::Frame& frame = m_page->focusController().focusedOrMainFrame();
3641
3642     auto bitmap = imageFromSelection(&frame, forceWhiteText ? TRUE : FALSE);
3643     *hBitmap = bitmap.leak();
3644
3645     return S_OK;
3646 }
3647
3648 HRESULT STDMETHODCALLTYPE WebView::selectionRect(RECT* rc)
3649 {
3650     WebCore::Frame& frame = m_page->focusController().focusedOrMainFrame();
3651
3652     IntRect ir = enclosingIntRect(frame.selection().selectionBounds());
3653     ir = frame.view()->convertToContainingWindow(ir);
3654     ir.move(-frame.view()->scrollOffset().width(), -frame.view()->scrollOffset().height());
3655     rc->left = ir.x();
3656     rc->top = ir.y();
3657     rc->bottom = rc->top + ir.height();
3658     rc->right = rc->left + ir.width();
3659
3660     return S_OK;
3661 }
3662
3663 HRESULT STDMETHODCALLTYPE WebView::registerViewClass( 
3664     /* [in] */ IWebDocumentView* /*view*/,
3665     /* [in] */ IWebDocumentRepresentation* /*representation*/,
3666     /* [in] */ BSTR /*forMIMEType*/)
3667 {
3668     ASSERT_NOT_REACHED();
3669     return E_NOTIMPL;
3670 }
3671
3672 HRESULT STDMETHODCALLTYPE WebView::setGroupName( 
3673         /* [in] */ BSTR groupName)
3674 {
3675     if (!m_page)
3676         return S_OK;
3677     m_page->setGroupName(toString(groupName));
3678     return S_OK;
3679 }
3680     
3681 HRESULT STDMETHODCALLTYPE WebView::groupName( 
3682         /* [retval][out] */ BSTR* groupName)
3683 {
3684     *groupName = 0;
3685     if (!m_page)
3686         return S_OK;
3687     String groupNameString = m_page->groupName();
3688     *groupName = BString(groupNameString).release();
3689     if (!*groupName && groupNameString.length())
3690         return E_OUTOFMEMORY;
3691     return S_OK;
3692 }
3693     
3694 HRESULT STDMETHODCALLTYPE WebView::estimatedProgress( 
3695         /* [retval][out] */ double* estimatedProgress)
3696 {
3697     *estimatedProgress = m_page->progress().estimatedProgress();
3698     return S_OK;
3699 }
3700     
3701 HRESULT STDMETHODCALLTYPE WebView::isLoading( 
3702         /* [retval][out] */ BOOL* isLoading)
3703 {
3704     COMPtr<IWebDataSource> dataSource;
3705     COMPtr<IWebDataSource> provisionalDataSource;
3706
3707     if (!isLoading)
3708         return E_POINTER;
3709
3710     *isLoading = FALSE;
3711
3712     if (!m_mainFrame)
3713         return E_FAIL;
3714
3715     if (SUCCEEDED(m_mainFrame->dataSource(&dataSource)))
3716         dataSource->isLoading(isLoading);
3717
3718     if (*isLoading)
3719         return S_OK;
3720
3721     if (SUCCEEDED(m_mainFrame->provisionalDataSource(&provisionalDataSource)))
3722         provisionalDataSource->isLoading(isLoading);
3723     return S_OK;
3724 }
3725     
3726 HRESULT STDMETHODCALLTYPE WebView::elementAtPoint( 
3727         /* [in] */ LPPOINT point,
3728         /* [retval][out] */ IPropertyBag** elementDictionary)
3729 {
3730     if (!elementDictionary) {
3731         ASSERT_NOT_REACHED();
3732         return E_POINTER;
3733     }
3734
3735     *elementDictionary = 0;
3736
3737     Frame* frame = core(m_mainFrame);
3738     if (!frame)
3739         return E_FAIL;
3740
3741     IntPoint webCorePoint = IntPoint(point->x, point->y);
3742     HitTestResult result = HitTestResult(webCorePoint);
3743     if (frame->contentRenderer())
3744         result = frame->eventHandler().hitTestResultAtPoint(webCorePoint);
3745     *elementDictionary = WebElementPropertyBag::createInstance(result);
3746     return S_OK;
3747 }
3748     
3749 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForSelection( 
3750     /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
3751 {
3752     ASSERT_NOT_REACHED();
3753     return E_NOTIMPL;
3754 }
3755     
3756 HRESULT STDMETHODCALLTYPE WebView::writeSelectionWithPasteboardTypes( 
3757         /* [size_is][in] */ BSTR* /*types*/,
3758         /* [in] */ int /*cTypes*/,
3759         /* [in] */ IDataObject* /*pasteboard*/)
3760 {
3761     ASSERT_NOT_REACHED();
3762     return E_NOTIMPL;
3763 }
3764     
3765 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForElement( 
3766     /* [in] */ IPropertyBag* /*elementDictionary*/,
3767     /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
3768 {
3769     ASSERT_NOT_REACHED();
3770     return E_NOTIMPL;
3771 }
3772     
3773 HRESULT STDMETHODCALLTYPE WebView::writeElement( 
3774         /* [in] */ IPropertyBag* /*elementDictionary*/,
3775         /* [size_is][in] */ BSTR* /*withPasteboardTypes*/,
3776         /* [in] */ int /*cWithPasteboardTypes*/,
3777         /* [in] */ IDataObject* /*pasteboard*/)
3778 {
3779     ASSERT_NOT_REACHED();
3780     return E_NOTIMPL;
3781 }
3782     
3783 HRESULT STDMETHODCALLTYPE WebView::selectedText(
3784         /* [out, retval] */ BSTR* text)
3785 {
3786     if (!text) {
3787         ASSERT_NOT_REACHED();
3788         return E_POINTER;
3789     }
3790
3791     *text = 0;
3792
3793     Frame* focusedFrame = m_page ? &m_page->focusController().focusedOrMainFrame() : 0;
3794     if (!focusedFrame)
3795         return E_FAIL;
3796
3797     String frameSelectedText = focusedFrame->editor().selectedText();
3798     *text = BString(frameSelectedText).release();
3799     if (!*text && frameSelectedText.length())
3800         return E_OUTOFMEMORY;
3801     return S_OK;
3802 }
3803
3804 HRESULT STDMETHODCALLTYPE WebView::centerSelectionInVisibleArea(
3805         /* [in] */ IUnknown* /* sender */)
3806 {
3807     Frame* coreFrame = core(m_mainFrame);
3808     if (!coreFrame)
3809         return E_FAIL;
3810
3811     coreFrame->selection().revealSelection(ScrollAlignment::alignCenterAlways);
3812     return S_OK;
3813 }
3814
3815
3816 HRESULT STDMETHODCALLTYPE WebView::moveDragCaretToPoint( 
3817         /* [in] */ LPPOINT /*point*/)
3818 {
3819     ASSERT_NOT_REACHED();
3820     return E_NOTIMPL;
3821 }
3822     
3823 HRESULT STDMETHODCALLTYPE WebView::removeDragCaret( void)
3824 {
3825     ASSERT_NOT_REACHED();
3826     return E_NOTIMPL;
3827 }
3828     
3829 HRESULT STDMETHODCALLTYPE WebView::setDrawsBackground( 
3830         /* [in] */ BOOL /*drawsBackground*/)
3831 {
3832     ASSERT_NOT_REACHED();
3833     return E_NOTIMPL;
3834 }
3835     
3836 HRESULT STDMETHODCALLTYPE WebView::drawsBackground( 
3837         /* [retval][out] */ BOOL* /*drawsBackground*/)
3838 {
3839     ASSERT_NOT_REACHED();
3840     return E_NOTIMPL;
3841 }
3842     
3843 HRESULT STDMETHODCALLTYPE WebView::setMainFrameURL( 
3844         /* [in] */ BSTR /*urlString*/)
3845 {
3846     ASSERT_NOT_REACHED();
3847     return E_NOTIMPL;
3848 }
3849     
3850 HRESULT STDMETHODCALLTYPE WebView::mainFrameURL( 
3851         /* [retval][out] */ BSTR* urlString)
3852 {
3853     if (!urlString)
3854         return E_POINTER;
3855
3856     if (!m_mainFrame)
3857         return E_FAIL;
3858
3859     COMPtr<IWebDataSource> dataSource;
3860
3861     if (FAILED(m_mainFrame->provisionalDataSource(&dataSource))) {
3862         if (FAILED(m_mainFrame->dataSource(&dataSource)))
3863             return E_FAIL;
3864     }
3865
3866     if (!dataSource) {
3867         *urlString = 0;
3868         return S_OK;
3869     }
3870     
3871     COMPtr<IWebMutableURLRequest> request;
3872     if (FAILED(dataSource->request(&request)) || !request)
3873         return E_FAIL;
3874
3875     if (FAILED(request->URL(urlString)))
3876         return E_FAIL;
3877
3878     return S_OK;
3879 }
3880     
3881 HRESULT STDMETHODCALLTYPE WebView::mainFrameDocument( 
3882         /* [retval][out] */ IDOMDocument** document)
3883 {
3884     if (document)
3885         *document = 0;
3886     if (!m_mainFrame)
3887         return E_FAIL;
3888     return m_mainFrame->DOMDocument(document);
3889 }
3890     
3891 HRESULT STDMETHODCALLTYPE WebView::mainFrameTitle( 
3892         /* [retval][out] */ BSTR* /*title*/)
3893 {
3894     ASSERT_NOT_REACHED();
3895     return E_NOTIMPL;
3896 }
3897     
3898 HRESULT WebView::mainFrameIcon(/* [retval][out] */ HBITMAP* /*hBitmap*/)
3899 {
3900     ASSERT_NOT_REACHED();
3901     return E_NOTIMPL;
3902 }
3903
3904 HRESULT STDMETHODCALLTYPE WebView::registerURLSchemeAsLocal( 
3905         /* [in] */ BSTR scheme)
3906 {
3907     if (!scheme)
3908         return E_POINTER;
3909
3910     SchemeRegistry::registerURLSchemeAsLocal(toString(scheme));
3911
3912     return S_OK;
3913 }
3914
3915 // IWebIBActions ---------------------------------------------------------------
3916
3917 HRESULT STDMETHODCALLTYPE WebView::takeStringURLFrom( 
3918         /* [in] */ IUnknown* /*sender*/)
3919 {
3920     ASSERT_NOT_REACHED();
3921     return E_NOTIMPL;
3922 }
3923     
3924 HRESULT STDMETHODCALLTYPE WebView::stopLoading( 
3925         /* [in] */ IUnknown* /*sender*/)
3926 {
3927     if (!m_mainFrame)
3928         return E_FAIL;
3929
3930     return m_mainFrame->stopLoading();
3931 }
3932     
3933 HRESULT STDMETHODCALLTYPE WebView::reload( 
3934         /* [in] */ IUnknown* /*sender*/)
3935 {
3936     if (!m_mainFrame)
3937         return E_FAIL;
3938
3939     return m_mainFrame->reload();
3940 }
3941     
3942 HRESULT STDMETHODCALLTYPE WebView::canGoBack( 
3943         /* [in] */ IUnknown* /*sender*/,
3944         /* [retval][out] */ BOOL* result)
3945 {
3946     *result = !!(m_page->backForward().client()->backItem() && !m_page->defersLoading());
3947     return S_OK;
3948 }
3949     
3950 HRESULT STDMETHODCALLTYPE WebView::goBack( 
3951         /* [in] */ IUnknown* /*sender*/)
3952 {
3953     ASSERT_NOT_REACHED();
3954     return E_NOTIMPL;
3955 }
3956     
3957 HRESULT STDMETHODCALLTYPE WebView::canGoForward( 
3958         /* [in] */ IUnknown* /*sender*/,
3959         /* [retval][out] */ BOOL* result)
3960 {
3961     *result = !!(m_page->backForward().client()->forwardItem() && !m_page->defersLoading());
3962     return S_OK;
3963 }
3964     
3965 HRESULT STDMETHODCALLTYPE WebView::goForward( 
3966         /* [in] */ IUnknown* /*sender*/)
3967 {
3968     ASSERT_NOT_REACHED();
3969     return E_NOTIMPL;
3970 }
3971
3972 // FIXME: This code should move into WebCore so it can be shared by all the WebKits.
3973 #define MinimumZoomMultiplier   0.5f
3974 #define MaximumZoomMultiplier   3.0f
3975 #define ZoomMultiplierRatio     1.2f
3976
3977 HRESULT STDMETHODCALLTYPE WebView::canMakeTextLarger( 
3978         /* [in] */ IUnknown* /*sender*/,
3979         /* [retval][out] */ BOOL* result)
3980 {
3981     bool canGrowMore = canZoomIn(m_zoomsTextOnly);
3982     *result = canGrowMore ? TRUE : FALSE;
3983     return S_OK;
3984 }
3985
3986 HRESULT STDMETHODCALLTYPE WebView::canZoomPageIn( 
3987         /* [in] */ IUnknown* /*sender*/,
3988         /* [retval][out] */ BOOL* result)
3989 {
3990     bool canGrowMore = canZoomIn(false);
3991     *result = canGrowMore ? TRUE : FALSE;
3992     return S_OK;
3993 }
3994
3995 bool WebView::canZoomIn(bool isTextOnly)
3996 {
3997     return zoomMultiplier(isTextOnly) * ZoomMultiplierRatio < MaximumZoomMultiplier;
3998 }
3999     
4000 HRESULT STDMETHODCALLTYPE WebView::makeTextLarger( 
4001         /* [in] */ IUnknown* /*sender*/)
4002 {
4003     return zoomIn(m_zoomsTextOnly);
4004 }
4005
4006 HRESULT STDMETHODCALLTYPE WebView::zoomPageIn( 
4007         /* [in] */ IUnknown* /*sender*/)
4008 {
4009     return zoomIn(false);
4010 }
4011
4012 HRESULT WebView::zoomIn(bool isTextOnly)
4013 {
4014     if (!canZoomIn(isTextOnly))
4015         return E_FAIL;
4016     setZoomMultiplier(zoomMultiplier(isTextOnly) * ZoomMultiplierRatio, isTextOnly);
4017     return S_OK;
4018 }
4019
4020 HRESULT STDMETHODCALLTYPE WebView::canMakeTextSmaller( 
4021         /* [in] */ IUnknown* /*sender*/,
4022         /* [retval][out] */ BOOL* result)
4023 {
4024     bool canShrinkMore = canZoomOut(m_zoomsTextOnly);
4025     *result = canShrinkMore ? TRUE : FALSE;
4026     return S_OK;
4027 }
4028
4029 HRESULT STDMETHODCALLTYPE WebView::canZoomPageOut( 
4030         /* [in] */ IUnknown* /*sender*/,
4031         /* [retval][out] */ BOOL* result)
4032 {
4033     bool canShrinkMore = canZoomOut(false);
4034     *result = canShrinkMore ? TRUE : FALSE;
4035     return S_OK;
4036 }
4037
4038 bool WebView::canZoomOut(bool isTextOnly)
4039 {
4040     return zoomMultiplier(isTextOnly) / ZoomMultiplierRatio > MinimumZoomMultiplier;
4041 }
4042
4043 HRESULT STDMETHODCALLTYPE WebView::makeTextSmaller( 
4044         /* [in] */ IUnknown* /*sender*/)
4045 {
4046     return zoomOut(m_zoomsTextOnly);
4047 }
4048
4049 HRESULT STDMETHODCALLTYPE WebView::zoomPageOut( 
4050         /* [in] */ IUnknown* /*sender*/)
4051 {
4052     return zoomOut(false);
4053 }
4054
4055 HRESULT WebView::zoomOut(bool isTextOnly)
4056 {
4057     if (!canZoomOut(isTextOnly))
4058         return E_FAIL;
4059     setZoomMultiplier(zoomMultiplier(isTextOnly) / ZoomMultiplierRatio, isTextOnly);
4060     return S_OK;
4061 }
4062
4063 HRESULT STDMETHODCALLTYPE WebView::canMakeTextStandardSize( 
4064     /* [in] */ IUnknown* /*sender*/,
4065     /* [retval][out] */ BOOL* result)
4066 {
4067     // 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.
4068     bool notAlreadyStandard = canResetZoom(true);
4069     *result = notAlreadyStandard ? TRUE : FALSE;
4070     return S_OK;
4071 }
4072
4073 HRESULT STDMETHODCALLTYPE WebView::canResetPageZoom( 
4074     /* [in] */ IUnknown* /*sender*/,
4075     /* [retval][out] */ BOOL* result)
4076 {
4077     bool notAlreadyStandard = canResetZoom(false);
4078     *result = notAlreadyStandard ? TRUE : FALSE;
4079     return S_OK;
4080 }
4081
4082 bool WebView::canResetZoom(bool isTextOnly)
4083 {
4084     return zoomMultiplier(isTextOnly) != 1.0f;
4085 }
4086
4087 HRESULT STDMETHODCALLTYPE WebView::makeTextStandardSize( 
4088     /* [in] */ IUnknown* /*sender*/)
4089 {
4090     return resetZoom(true);
4091 }
4092
4093 HRESULT STDMETHODCALLTYPE WebView::resetPageZoom( 
4094     /* [in] */ IUnknown* /*sender*/)
4095 {
4096     return resetZoom(false);
4097 }
4098
4099 HRESULT WebView::resetZoom(bool isTextOnly)
4100 {
4101     if (!canResetZoom(isTextOnly))
4102         return E_FAIL;
4103     setZoomMultiplier(1.0f, isTextOnly);
4104     return S_OK;
4105 }
4106
4107 HRESULT STDMETHODCALLTYPE WebView::toggleContinuousSpellChecking( 
4108     /* [in] */ IUnknown* /*sender*/)
4109 {
4110     HRESULT hr;
4111     BOOL enabled;
4112     if (FAILED(hr = isContinuousSpellCheckingEnabled(&enabled)))
4113         return hr;
4114     return setContinuousSpellCheckingEnabled(enabled ? FALSE : TRUE);
4115 }
4116
4117 HRESULT STDMETHODCALLTYPE WebView::toggleSmartInsertDelete( 
4118     /* [in] */ IUnknown* /*sender*/)
4119 {
4120     BOOL enabled = FALSE;
4121     HRESULT hr = smartInsertDeleteEnabled(&enabled);
4122     if (FAILED(hr))
4123         return hr;
4124
4125     return setSmartInsertDeleteEnabled(enabled ? FALSE : TRUE);
4126 }
4127
4128 HRESULT STDMETHODCALLTYPE WebView::toggleGrammarChecking( 
4129     /* [in] */ IUnknown* /*sender*/)
4130 {
4131     BOOL enabled;
4132     HRESULT hr = isGrammarCheckingEnabled(&enabled);
4133     if (FAILED(hr))
4134         return hr;
4135
4136     return setGrammarCheckingEnabled(enabled ? FALSE : TRUE);
4137 }
4138
4139 HRESULT STDMETHODCALLTYPE WebView::reloadFromOrigin( 
4140         /* [in] */ IUnknown* /*sender*/)
4141 {
4142     if (!m_mainFrame)
4143         return E_FAIL;
4144
4145     return m_mainFrame->reloadFromOrigin();
4146 }
4147
4148 // IWebViewCSS -----------------------------------------------------------------
4149
4150 HRESULT STDMETHODCALLTYPE WebView::computedStyleForElement( 
4151         /* [in] */ IDOMElement* /*element*/,
4152         /* [in] */ BSTR /*pseudoElement*/,
4153         /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
4154 {
4155     ASSERT_NOT_REACHED();
4156     return E_NOTIMPL;
4157 }
4158
4159 // IWebViewEditing -------------------------------------------------------------
4160
4161 HRESULT STDMETHODCALLTYPE WebView::editableDOMRangeForPoint( 
4162         /* [in] */ LPPOINT /*point*/,
4163         /* [retval][out] */ IDOMRange** /*range*/)
4164 {
4165     ASSERT_NOT_REACHED();
4166     return E_NOTIMPL;
4167 }
4168     
4169 HRESULT STDMETHODCALLTYPE WebView::setSelectedDOMRange( 
4170         /* [in] */ IDOMRange* /*range*/,
4171         /* [in] */ WebSelectionAffinity /*affinity*/)
4172 {
4173     ASSERT_NOT_REACHED();
4174     return E_NOTIMPL;
4175 }
4176     
4177 HRESULT STDMETHODCALLTYPE WebView::selectedDOMRange( 
4178         /* [retval][out] */ IDOMRange** /*range*/)
4179 {
4180     ASSERT_NOT_REACHED();
4181     return E_NOTIMPL;
4182 }
4183     
4184 HRESULT STDMETHODCALLTYPE WebView::selectionAffinity( 
4185         /* [retval][out][retval][out] */ WebSelectionAffinity* /*affinity*/)
4186 {
4187     ASSERT_NOT_REACHED();
4188     return E_NOTIMPL;
4189 }
4190     
4191 HRESULT STDMETHODCALLTYPE WebView::setEditable( 
4192         /* [in] */ BOOL /*flag*/)
4193 {
4194     ASSERT_NOT_REACHED();
4195     return E_NOTIMPL;
4196 }
4197     
4198 HRESULT STDMETHODCALLTYPE WebView::isEditable( 
4199         /* [retval][out] */ BOOL* /*isEditable*/)
4200 {
4201     ASSERT_NOT_REACHED();
4202     return E_NOTIMPL;
4203 }
4204     
4205 HRESULT STDMETHODCALLTYPE WebView::setTypingStyle( 
4206         /* [in] */ IDOMCSSStyleDeclaration* /*style*/)
4207 {
4208     ASSERT_NOT_REACHED();
4209     return E_NOTIMPL;
4210 }
4211     
4212 HRESULT STDMETHODCALLTYPE WebView::typingStyle( 
4213         /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
4214 {
4215     ASSERT_NOT_REACHED();
4216     return E_NOTIMPL;
4217 }
4218     
4219 HRESULT STDMETHODCALLTYPE WebView::setSmartInsertDeleteEnabled( 
4220         /* [in] */ BOOL flag)
4221 {
4222     if (m_page->settings().smartInsertDeleteEnabled() != !!flag) {
4223         m_page->settings().setSmartInsertDeleteEnabled(!!flag);
4224         setSelectTrailingWhitespaceEnabled(!flag);
4225     }
4226     return S_OK;
4227 }
4228     
4229 HRESULT STDMETHODCALLTYPE WebView::smartInsertDeleteEnabled( 
4230         /* [retval][out] */ BOOL* enabled)
4231 {
4232     *enabled = m_page->settings().smartInsertDeleteEnabled() ? TRUE : FALSE;
4233     return S_OK;
4234 }
4235  
4236 HRESULT STDMETHODCALLTYPE WebView::setSelectTrailingWhitespaceEnabled( 
4237         /* [in] */ BOOL flag)
4238 {
4239     if (m_page->settings().selectTrailingWhitespaceEnabled() != !!flag) {
4240         m_page->settings().setSelectTrailingWhitespaceEnabled(!!flag);
4241         setSmartInsertDeleteEnabled(!flag);
4242     }
4243     return S_OK;
4244 }
4245     
4246 HRESULT STDMETHODCALLTYPE WebView::isSelectTrailingWhitespaceEnabled( 
4247         /* [retval][out] */ BOOL* enabled)
4248 {
4249     *enabled = m_page->settings().selectTrailingWhitespaceEnabled() ? TRUE : FALSE;
4250     return S_OK;
4251 }
4252
4253 HRESULT STDMETHODCALLTYPE WebView::setContinuousSpellCheckingEnabled( 
4254         /* [in] */ BOOL flag)
4255 {
4256     if (continuousSpellCheckingEnabled != !!flag) {
4257         continuousSpellCheckingEnabled = !!flag;
4258         COMPtr<IWebPreferences> prefs;
4259         if (SUCCEEDED(preferences(&prefs)))
4260             prefs->setContinuousSpellCheckingEnabled(flag);
4261     }
4262     
4263     BOOL spellCheckingEnabled;
4264     if (SUCCEEDED(isContinuousSpellCheckingEnabled(&spellCheckingEnabled)) && spellCheckingEnabled)
4265         preflightSpellChecker();
4266     else
4267         m_mainFrame->unmarkAllMisspellings();
4268
4269     return S_OK;
4270 }
4271     
4272 HRESULT STDMETHODCALLTYPE WebView::isContinuousSpellCheckingEnabled( 
4273         /* [retval][out] */ BOOL* enabled)
4274 {
4275     *enabled = (continuousSpellCheckingEnabled && continuousCheckingAllowed()) ? TRUE : FALSE;
4276     return S_OK;
4277 }
4278     
4279 HRESULT STDMETHODCALLTYPE WebView::spellCheckerDocumentTag( 
4280         /* [retval][out] */ int* tag)
4281 {
4282     // we just use this as a flag to indicate that we've spell checked the document
4283     // and need to close the spell checker out when the view closes.
4284     *tag = 0;
4285     m_hasSpellCheckerDocumentTag = true;
4286     return S_OK;
4287 }
4288
4289 static COMPtr<IWebEditingDelegate> spellingDelegateForTimer;
4290
4291 static void preflightSpellCheckerNow()
4292 {
4293     spellingDelegateForTimer->preflightChosenSpellServer();
4294     spellingDelegateForTimer = 0;
4295 }
4296
4297 static void CALLBACK preflightSpellCheckerTimerCallback(HWND, UINT, UINT_PTR id, DWORD)
4298 {
4299     ::KillTimer(0, id);
4300     preflightSpellCheckerNow();