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