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