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