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