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