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