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