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