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