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