[Release] Webkit2-efl-123997_0.11.86
[framework/web/webkit-efl.git] / Source / WebKit / win / WebView.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple, Inc.  All rights reserved.
3  * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
4  * Copyright (C) 2011 Brent Fulgham. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
26  */
27
28 #include "config.h"
29 #include "WebView.h"
30
31 #include "CFDictionaryPropertyBag.h"
32 #include "DOMCoreClasses.h"
33 #include "FullscreenVideoController.h"
34 #include "MarshallingHelpers.h"
35 #include "SoftLinking.h"
36 #include "TextIterator.h"
37 #include "WebBackForwardList.h"
38 #include "WebChromeClient.h"
39 #include "WebContextMenuClient.h"
40 #include "WebCoreTextRenderer.h"
41 #include "WebDatabaseManager.h"
42 #include "WebDocumentLoader.h"
43 #include "WebDownload.h"
44 #include "WebDragClient.h"
45 #include "WebEditorClient.h"
46 #include "WebElementPropertyBag.h"
47 #include "WebFrame.h"
48 #include "WebGeolocationClient.h"
49 #include "WebGeolocationPosition.h"
50 #include "WebIconDatabase.h"
51 #include "WebInspector.h"
52 #include "WebInspectorClient.h"
53 #include "WebKit.h"
54 #include "WebKitDLL.h"
55 #include "WebKitLogging.h"
56 #include "WebKitStatisticsPrivate.h"
57 #include "WebKitSystemBits.h"
58 #include "WebMutableURLRequest.h"
59 #include "WebNotificationCenter.h"
60 #include "WebPlatformStrategies.h"
61 #include "WebPreferences.h"
62 #include "WebScriptWorld.h"
63 #include "resource.h"
64 #include <JavaScriptCore/APICast.h>
65 #include <JavaScriptCore/InitializeThreading.h>
66 #include <JavaScriptCore/JSLock.h>
67 #include <JavaScriptCore/JSValue.h>
68 #include <WebCore/AXObjectCache.h>
69 #include <WebCore/AbstractDatabase.h>
70 #include <WebCore/ApplicationCacheStorage.h>
71 #include <WebCore/BString.h>
72 #include <WebCore/BackForwardListImpl.h>
73 #include <WebCore/BitmapInfo.h>
74 #include <WebCore/Chrome.h>
75 #include <WebCore/ContextMenu.h>
76 #include <WebCore/ContextMenuController.h>
77 #include <WebCore/Cursor.h>
78 #include <WebCore/Document.h>
79 #include <WebCore/DocumentMarkerController.h>
80 #include <WebCore/DragController.h>
81 #include <WebCore/DragData.h>
82 #include <WebCore/DragSession.h>
83 #include <WebCore/Editor.h>
84 #include <WebCore/EventHandler.h>
85 #include <WebCore/EventNames.h>
86 #include <WebCore/FileSystem.h>
87 #include <WebCore/FloatQuad.h>
88 #include <WebCore/FocusController.h>
89 #include <WebCore/Frame.h>
90 #include <WebCore/FrameLoader.h>
91 #include <WebCore/FrameSelection.h>
92 #include <WebCore/FrameTree.h>
93 #include <WebCore/FrameView.h>
94 #include <WebCore/FrameWin.h>
95 #include <WebCore/GDIObjectCounter.h>
96 #include <WebCore/GeolocationController.h>
97 #include <WebCore/GeolocationError.h>
98 #include <WebCore/GraphicsContext.h>
99 #include <WebCore/HTMLMediaElement.h>
100 #include <WebCore/HTMLNames.h>
101 #include <WebCore/HWndDC.h>
102 #include <WebCore/HistoryItem.h>
103 #include <WebCore/HitTestRequest.h>
104 #include <WebCore/HitTestResult.h>
105 #include <WebCore/IntRect.h>
106 #include <WebCore/JSElement.h>
107 #include <WebCore/KeyboardEvent.h>
108 #include <WebCore/Logging.h>
109 #include <WebCore/MIMETypeRegistry.h>
110 #include <WebCore/MemoryCache.h>
111 #include <WebCore/Page.h>
112 #include <WebCore/PageCache.h>
113 #include <WebCore/PageGroup.h>
114 #include <WebCore/PlatformKeyboardEvent.h>
115 #include <WebCore/PlatformMouseEvent.h>
116 #include <WebCore/PlatformWheelEvent.h>
117 #include <WebCore/PluginData.h>
118 #include <WebCore/PluginDatabase.h>
119 #include <WebCore/PluginView.h>
120 #include <WebCore/PopupMenu.h>
121 #include <WebCore/PopupMenuWin.h>
122 #include <WebCore/ProgressTracker.h>
123 #include <WebCore/RenderLayer.h>
124 #include <WebCore/RenderTheme.h>
125 #include <WebCore/RenderTreeAsText.h>
126 #include <WebCore/RenderView.h>
127 #include <WebCore/RenderWidget.h>
128 #include <WebCore/ResourceHandle.h>
129 #include <WebCore/ResourceHandleClient.h>
130 #include <WebCore/ResourceRequest.h>
131 #include <WebCore/SchemeRegistry.h>
132 #include <WebCore/ScriptValue.h>
133 #include <WebCore/Scrollbar.h>
134 #include <WebCore/ScrollbarTheme.h>
135 #include <WebCore/SecurityOrigin.h>
136 #include <WebCore/SecurityPolicy.h>
137 #include <WebCore/Settings.h>
138 #include <WebCore/SimpleFontData.h>
139 #include <WebCore/SystemInfo.h>
140 #include <WebCore/WindowMessageBroadcaster.h>
141 #include <WebCore/WindowsTouch.h>
142 #include <wtf/MainThread.h>
143
144 #if USE(CG)
145 #include <CoreGraphics/CGContext.h>
146 #endif
147
148 #if USE(CF)
149 #include <CoreFoundation/CoreFoundation.h>
150 #endif
151
152 #if USE(CFNETWORK)
153 #include <CFNetwork/CFURLCachePriv.h>
154 #include <CFNetwork/CFURLProtocolPriv.h>
155 #include <WebCore/CookieStorageCFNet.h>
156 #include <WebKitSystemInterface/WebKitSystemInterface.h> 
157 #endif
158
159 #if USE(ACCELERATED_COMPOSITING)
160 #include <WebCore/CACFLayerTreeHost.h>
161 #include <WebCore/PlatformCALayer.h>
162 #endif
163
164 #if ENABLE(FULLSCREEN_API)
165 #include <WebCore/FullScreenController.h>
166 #endif
167
168 #include <ShlObj.h>
169 #include <comutil.h>
170 #include <dimm.h>
171 #include <oleacc.h>
172 #include <wchar.h>
173 #include <windowsx.h>
174 #include <wtf/HashSet.h>
175 #include <wtf/text/CString.h>
176 #include <wtf/text/StringConcatenate.h>
177
178 // Soft link functions for gestures and panning feedback
179 SOFT_LINK_LIBRARY(USER32);
180 SOFT_LINK_OPTIONAL(USER32, GetGestureInfo, BOOL, WINAPI, (HGESTUREINFO, PGESTUREINFO));
181 SOFT_LINK_OPTIONAL(USER32, SetGestureConfig, BOOL, WINAPI, (HWND, DWORD, UINT, PGESTURECONFIG, UINT));
182 SOFT_LINK_OPTIONAL(USER32, CloseGestureInfoHandle, BOOL, WINAPI, (HGESTUREINFO));
183 SOFT_LINK_LIBRARY(Uxtheme);
184 SOFT_LINK_OPTIONAL(Uxtheme, BeginPanningFeedback, BOOL, WINAPI, (HWND));
185 SOFT_LINK_OPTIONAL(Uxtheme, EndPanningFeedback, BOOL, WINAPI, (HWND, BOOL));
186 SOFT_LINK_OPTIONAL(Uxtheme, UpdatePanningFeedback, BOOL, WINAPI, (HWND, LONG, LONG, BOOL));
187
188 using namespace WebCore;
189 using namespace std;
190 using JSC::JSLock;
191
192 static HMODULE accessibilityLib;
193 static HashSet<WebView*> pendingDeleteBackingStoreSet;
194
195 static String webKitVersionString();
196
197 WebView* kit(Page* page)
198 {
199     return page ? static_cast<WebView*>(static_cast<WebChromeClient*>(page->chrome()->client())->webView()) : 0;
200 }
201
202 class PreferencesChangedOrRemovedObserver : public IWebNotificationObserver {
203 public:
204     static PreferencesChangedOrRemovedObserver* sharedInstance();
205
206 private:
207     PreferencesChangedOrRemovedObserver() {}
208     ~PreferencesChangedOrRemovedObserver() {}
209
210     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) { return E_FAIL; }
211     virtual ULONG STDMETHODCALLTYPE AddRef(void) { return 0; }
212     virtual ULONG STDMETHODCALLTYPE Release(void) { return 0; }
213
214 public:
215     // IWebNotificationObserver
216     virtual HRESULT STDMETHODCALLTYPE onNotify( 
217         /* [in] */ IWebNotification* notification);
218
219 private:
220     HRESULT notifyPreferencesChanged(WebCacheModel);
221     HRESULT notifyPreferencesRemoved(WebCacheModel);
222 };
223
224 PreferencesChangedOrRemovedObserver* PreferencesChangedOrRemovedObserver::sharedInstance()
225 {
226     static PreferencesChangedOrRemovedObserver* shared = new PreferencesChangedOrRemovedObserver;
227     return shared;
228 }
229
230 HRESULT PreferencesChangedOrRemovedObserver::onNotify(IWebNotification* notification)
231 {
232     HRESULT hr = S_OK;
233
234     COMPtr<IUnknown> unkPrefs;
235     hr = notification->getObject(&unkPrefs);
236     if (FAILED(hr))
237         return hr;
238
239     COMPtr<IWebPreferences> preferences(Query, unkPrefs);
240     if (!preferences)
241         return E_NOINTERFACE;
242
243     WebCacheModel cacheModel;
244     hr = preferences->cacheModel(&cacheModel);
245     if (FAILED(hr))
246         return hr;
247
248     BSTR nameBSTR;
249     hr = notification->name(&nameBSTR);
250     if (FAILED(hr))
251         return hr;
252     BString name;
253     name.adoptBSTR(nameBSTR);
254
255     if (wcscmp(name, WebPreferences::webPreferencesChangedNotification()) == 0)
256         return notifyPreferencesChanged(cacheModel);
257
258     if (wcscmp(name, WebPreferences::webPreferencesRemovedNotification()) == 0)
259         return notifyPreferencesRemoved(cacheModel);
260
261     ASSERT_NOT_REACHED();
262     return E_FAIL;
263 }
264
265 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesChanged(WebCacheModel cacheModel)
266 {
267     HRESULT hr = S_OK;
268
269     if (!WebView::didSetCacheModel() || cacheModel > WebView::cacheModel())
270         WebView::setCacheModel(cacheModel);
271     else if (cacheModel < WebView::cacheModel()) {
272         WebCacheModel sharedPreferencesCacheModel;
273         hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel);
274         if (FAILED(hr))
275             return hr;
276         WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance()));
277     }
278
279     return hr;
280 }
281
282 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesRemoved(WebCacheModel cacheModel)
283 {
284     HRESULT hr = S_OK;
285
286     if (cacheModel == WebView::cacheModel()) {
287         WebCacheModel sharedPreferencesCacheModel;
288         hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel);
289         if (FAILED(hr))
290             return hr;
291         WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance()));
292     }
293
294     return hr;
295 }
296
297
298 const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass";
299
300 const int WM_XP_THEMECHANGED = 0x031A;
301 const int WM_VISTA_MOUSEHWHEEL = 0x020E;
302
303 static const int maxToolTipWidth = 250;
304
305 static const int delayBeforeDeletingBackingStoreMsec = 5000;
306
307 static ATOM registerWebView();
308
309 static void initializeStaticObservers();
310
311 static HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences*);
312
313 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches);
314
315 static bool continuousSpellCheckingEnabled;
316 static bool grammarCheckingEnabled;
317
318 static bool s_didSetCacheModel;
319 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
320
321 enum {
322     UpdateActiveStateTimer = 1,
323     DeleteBackingStoreTimer = 2,
324 };
325
326 // WebView ----------------------------------------------------------------
327
328 bool WebView::s_allowSiteSpecificHacks = false;
329
330 WebView::WebView()
331     : m_refCount(0)
332     , m_shouldInvertColors(false)
333 #if !ASSERT_DISABLED
334     , m_deletionHasBegun(false)
335 #endif
336     , m_hostWindow(0)
337     , m_viewWindow(0)
338     , m_mainFrame(0)
339     , m_page(0)
340 #if ENABLE(INSPECTOR)
341     , m_inspectorClient(0)
342 #endif // ENABLE(INSPECTOR)
343     , m_hasCustomDropTarget(false)
344     , m_useBackForwardList(true)
345     , m_userAgentOverridden(false)
346     , m_zoomMultiplier(1.0f)
347     , m_zoomsTextOnly(false)
348     , m_mouseActivated(false)
349     , m_dragData(0)
350     , m_currentCharacterCode(0)
351     , m_isBeingDestroyed(false)
352     , m_paintCount(0)
353     , m_hasSpellCheckerDocumentTag(false)
354     , m_smartInsertDeleteEnabled(false)
355     , m_didClose(false)
356     , m_inIMEComposition(0)
357     , m_toolTipHwnd(0)
358     , m_closeWindowTimer(0)
359     , m_topLevelParent(0)
360     , m_deleteBackingStoreTimerActive(false)
361     , m_transparent(false)
362     , m_selectTrailingWhitespaceEnabled(false)
363     , m_lastPanX(0)
364     , m_lastPanY(0)
365     , m_xOverpan(0)
366     , m_yOverpan(0)
367 #if USE(ACCELERATED_COMPOSITING)
368     , m_isAcceleratedCompositing(false)
369 #endif
370     , m_nextDisplayIsSynchronous(false)
371     , m_lastSetCursor(0)
372     , m_usesLayeredWindow(false)
373 {
374     JSC::initializeThreading();
375     WTF::initializeMainThread();
376
377     m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
378
379     CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper,(void**)&m_dropTargetHelper);
380
381     initializeStaticObservers();
382
383     WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences();
384     BOOL enabled;
385     if (SUCCEEDED(sharedPreferences->continuousSpellCheckingEnabled(&enabled)))
386         continuousSpellCheckingEnabled = !!enabled;
387     if (SUCCEEDED(sharedPreferences->grammarCheckingEnabled(&enabled)))
388         grammarCheckingEnabled = !!enabled;
389
390     WebViewCount++;
391     gClassCount++;
392     gClassNameCount.add("WebView");
393 }
394
395 WebView::~WebView()
396 {
397     deleteBackingStore();
398
399     // the tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD
400     if (::IsWindow(m_toolTipHwnd))
401         ::DestroyWindow(m_toolTipHwnd);
402
403     ASSERT(!m_page);
404     ASSERT(!m_preferences);
405     ASSERT(!m_viewWindow);
406
407 #if USE(ACCELERATED_COMPOSITING)
408     ASSERT(!m_layerTreeHost);
409     ASSERT(!m_backingLayer);
410 #endif
411
412     WebViewCount--;
413     gClassCount--;
414     gClassNameCount.remove("WebView");
415 }
416
417 WebView* WebView::createInstance()
418 {
419     WebView* instance = new WebView();
420     instance->AddRef();
421     return instance;
422 }
423
424 void initializeStaticObservers()
425 {
426     static bool initialized;
427     if (initialized)
428         return;
429     initialized = true;
430
431     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
432     notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesChangedNotification(), 0);
433     notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesRemovedNotification(), 0);
434 }
435
436 static HashSet<WebView*>& allWebViewsSet()
437 {
438     static HashSet<WebView*> allWebViewsSet;
439     return allWebViewsSet;
440 }
441
442 void WebView::addToAllWebViewsSet()
443 {
444     allWebViewsSet().add(this);
445 }
446
447 void WebView::removeFromAllWebViewsSet()
448 {
449     allWebViewsSet().remove(this);
450 }
451
452 void WebView::setCacheModel(WebCacheModel cacheModel)
453 {
454 #if USE(CFNETWORK)
455     if (s_didSetCacheModel && cacheModel == s_cacheModel)
456         return;
457
458     RetainPtr<CFURLCacheRef> cfurlCache(AdoptCF, CFURLCacheCopySharedURLCache());
459     RetainPtr<CFStringRef> cfurlCacheDirectory(AdoptCF, wkCopyFoundationCacheDirectory(0));
460     if (!cfurlCacheDirectory)
461         cfurlCacheDirectory.adoptCF(WebCore::localUserSpecificStorageDirectory().createCFString());
462
463     // As a fudge factor, use 1000 instead of 1024, in case the reported byte 
464     // count doesn't align exactly to a megabyte boundary.
465     unsigned long long memSize = WebMemorySize() / 1024 / 1000;
466     unsigned long long diskFreeSize = WebVolumeFreeSize(cfurlCacheDirectory.get()) / 1024 / 1000;
467
468     unsigned cacheTotalCapacity = 0;
469     unsigned cacheMinDeadCapacity = 0;
470     unsigned cacheMaxDeadCapacity = 0;
471     double deadDecodedDataDeletionInterval = 0;
472
473     unsigned pageCacheCapacity = 0;
474
475     CFIndex cfurlCacheMemoryCapacity = 0;
476     CFIndex cfurlCacheDiskCapacity = 0;
477
478     switch (cacheModel) {
479     case WebCacheModelDocumentViewer: {
480         // Page cache capacity (in pages)
481         pageCacheCapacity = 0;
482
483         // Object cache capacities (in bytes)
484         if (memSize >= 2048)
485             cacheTotalCapacity = 96 * 1024 * 1024;
486         else if (memSize >= 1536)
487             cacheTotalCapacity = 64 * 1024 * 1024;
488         else if (memSize >= 1024)
489             cacheTotalCapacity = 32 * 1024 * 1024;
490         else if (memSize >= 512)
491             cacheTotalCapacity = 16 * 1024 * 1024; 
492
493         cacheMinDeadCapacity = 0;
494         cacheMaxDeadCapacity = 0;
495
496         // Foundation memory cache capacity (in bytes)
497         cfurlCacheMemoryCapacity = 0;
498
499         // Foundation disk cache capacity (in bytes)
500         cfurlCacheDiskCapacity = CFURLCacheDiskCapacity(cfurlCache.get());
501
502         break;
503     }
504     case WebCacheModelDocumentBrowser: {
505         // Page cache capacity (in pages)
506         if (memSize >= 1024)
507             pageCacheCapacity = 3;
508         else if (memSize >= 512)
509             pageCacheCapacity = 2;
510         else if (memSize >= 256)
511             pageCacheCapacity = 1;
512         else
513             pageCacheCapacity = 0;
514
515         // Object cache capacities (in bytes)
516         if (memSize >= 2048)
517             cacheTotalCapacity = 96 * 1024 * 1024;
518         else if (memSize >= 1536)
519             cacheTotalCapacity = 64 * 1024 * 1024;
520         else if (memSize >= 1024)
521             cacheTotalCapacity = 32 * 1024 * 1024;
522         else if (memSize >= 512)
523             cacheTotalCapacity = 16 * 1024 * 1024; 
524
525         cacheMinDeadCapacity = cacheTotalCapacity / 8;
526         cacheMaxDeadCapacity = cacheTotalCapacity / 4;
527
528         // Foundation memory cache capacity (in bytes)
529         if (memSize >= 2048)
530             cfurlCacheMemoryCapacity = 4 * 1024 * 1024;
531         else if (memSize >= 1024)
532             cfurlCacheMemoryCapacity = 2 * 1024 * 1024;
533         else if (memSize >= 512)
534             cfurlCacheMemoryCapacity = 1 * 1024 * 1024;
535         else
536             cfurlCacheMemoryCapacity =      512 * 1024; 
537
538         // Foundation disk cache capacity (in bytes)
539         if (diskFreeSize >= 16384)
540             cfurlCacheDiskCapacity = 50 * 1024 * 1024;
541         else if (diskFreeSize >= 8192)
542             cfurlCacheDiskCapacity = 40 * 1024 * 1024;
543         else if (diskFreeSize >= 4096)
544             cfurlCacheDiskCapacity = 30 * 1024 * 1024;
545         else
546             cfurlCacheDiskCapacity = 20 * 1024 * 1024;
547
548         break;
549     }
550     case WebCacheModelPrimaryWebBrowser: {
551         // Page cache capacity (in pages)
552         // (Research indicates that value / page drops substantially after 3 pages.)
553         if (memSize >= 2048)
554             pageCacheCapacity = 5;
555         else if (memSize >= 1024)
556             pageCacheCapacity = 4;
557         else if (memSize >= 512)
558             pageCacheCapacity = 3;
559         else if (memSize >= 256)
560             pageCacheCapacity = 2;
561         else
562             pageCacheCapacity = 1;
563
564         // Object cache capacities (in bytes)
565         // (Testing indicates that value / MB depends heavily on content and
566         // browsing pattern. Even growth above 128MB can have substantial 
567         // value / MB for some content / browsing patterns.)
568         if (memSize >= 2048)
569             cacheTotalCapacity = 128 * 1024 * 1024;
570         else if (memSize >= 1536)
571             cacheTotalCapacity = 96 * 1024 * 1024;
572         else if (memSize >= 1024)
573             cacheTotalCapacity = 64 * 1024 * 1024;
574         else if (memSize >= 512)
575             cacheTotalCapacity = 32 * 1024 * 1024; 
576
577         cacheMinDeadCapacity = cacheTotalCapacity / 4;
578         cacheMaxDeadCapacity = cacheTotalCapacity / 2;
579
580         // This code is here to avoid a PLT regression. We can remove it if we
581         // can prove that the overall system gain would justify the regression.
582         cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity);
583
584         deadDecodedDataDeletionInterval = 60;
585
586         // Foundation memory cache capacity (in bytes)
587         // (These values are small because WebCore does most caching itself.)
588         if (memSize >= 1024)
589             cfurlCacheMemoryCapacity = 4 * 1024 * 1024;
590         else if (memSize >= 512)
591             cfurlCacheMemoryCapacity = 2 * 1024 * 1024;
592         else if (memSize >= 256)
593             cfurlCacheMemoryCapacity = 1 * 1024 * 1024;
594         else
595             cfurlCacheMemoryCapacity =      512 * 1024; 
596
597         // Foundation disk cache capacity (in bytes)
598         if (diskFreeSize >= 16384)
599             cfurlCacheDiskCapacity = 175 * 1024 * 1024;
600         else if (diskFreeSize >= 8192)
601             cfurlCacheDiskCapacity = 150 * 1024 * 1024;
602         else if (diskFreeSize >= 4096)
603             cfurlCacheDiskCapacity = 125 * 1024 * 1024;
604         else if (diskFreeSize >= 2048)
605             cfurlCacheDiskCapacity = 100 * 1024 * 1024;
606         else if (diskFreeSize >= 1024)
607             cfurlCacheDiskCapacity = 75 * 1024 * 1024;
608         else
609             cfurlCacheDiskCapacity = 50 * 1024 * 1024;
610
611         break;
612     }
613     default:
614         ASSERT_NOT_REACHED();
615     }
616
617     // Don't shrink a big disk cache, since that would cause churn.
618     cfurlCacheDiskCapacity = max(cfurlCacheDiskCapacity, CFURLCacheDiskCapacity(cfurlCache.get()));
619
620     memoryCache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
621     memoryCache()->setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
622     pageCache()->setCapacity(pageCacheCapacity);
623
624     CFURLCacheSetMemoryCapacity(cfurlCache.get(), cfurlCacheMemoryCapacity);
625     CFURLCacheSetDiskCapacity(cfurlCache.get(), cfurlCacheDiskCapacity);
626
627     s_didSetCacheModel = true;
628     s_cacheModel = cacheModel;
629     return;
630 #endif
631 }
632
633 WebCacheModel WebView::cacheModel()
634 {
635     return s_cacheModel;
636 }
637
638 bool WebView::didSetCacheModel()
639 {
640     return s_didSetCacheModel;
641 }
642
643 WebCacheModel WebView::maxCacheModelInAnyInstance()
644 {
645     WebCacheModel cacheModel = WebCacheModelDocumentViewer;
646
647     HashSet<WebView*>::iterator end = allWebViewsSet().end();
648     for (HashSet<WebView*>::iterator it = allWebViewsSet().begin(); it != end; ++it) {
649         COMPtr<IWebPreferences> pref;
650         if (FAILED((*it)->preferences(&pref)))
651             continue;
652         WebCacheModel prefCacheModel = WebCacheModelDocumentViewer;
653         if (FAILED(pref->cacheModel(&prefCacheModel)))
654             continue;
655
656         cacheModel = max(cacheModel, prefCacheModel);
657     }
658
659     return cacheModel;
660 }
661
662 HRESULT STDMETHODCALLTYPE WebView::close()
663 {
664     if (m_didClose)
665         return S_OK;
666
667     m_didClose = true;
668
669 #if USE(ACCELERATED_COMPOSITING)
670     setAcceleratedCompositing(false);
671 #endif
672
673     WebNotificationCenter::defaultCenterInternal()->postNotificationName(_bstr_t(WebViewWillCloseNotification).GetBSTR(), static_cast<IWebView*>(this), 0);
674
675     if (m_uiDelegatePrivate)
676         m_uiDelegatePrivate->webViewClosing(this);
677
678     removeFromAllWebViewsSet();
679
680     if (m_page) {
681         if (Frame* frame = m_page->mainFrame())
682             frame->loader()->detachFromParent();
683     }
684
685     if (m_mouseOutTracker) {
686         m_mouseOutTracker->dwFlags = TME_CANCEL;
687         ::TrackMouseEvent(m_mouseOutTracker.get());
688         m_mouseOutTracker.clear();
689     }
690     
691     revokeDragDrop();
692
693     if (m_viewWindow) {
694         // We can't check IsWindow(m_viewWindow) here, because that will return true even while
695         // we're already handling WM_DESTROY. So we check !isBeingDestroyed() instead.
696         if (!isBeingDestroyed())
697             DestroyWindow(m_viewWindow);
698         // Either we just destroyed m_viewWindow, or it's in the process of being destroyed. Either
699         // way, we clear it out to make sure we don't try to use it later.
700         m_viewWindow = 0;
701     }
702
703     setHostWindow(0);
704
705     setDownloadDelegate(0);
706     setEditingDelegate(0);
707     setFrameLoadDelegate(0);
708     setFrameLoadDelegatePrivate(0);
709     setHistoryDelegate(0);
710     setPolicyDelegate(0);
711     setResourceLoadDelegate(0);
712     setUIDelegate(0);
713     setFormDelegate(0);
714
715 #if ENABLE(INSPECTOR)
716     m_inspectorClient = 0;
717     if (m_webInspector)
718         m_webInspector->webViewClosed();
719 #endif // ENABLE(INSPECTOR)
720
721     delete m_page;
722     m_page = 0;
723
724     registerForIconNotification(false);
725     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
726     notifyCenter->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
727
728     if (COMPtr<WebPreferences> preferences = m_preferences) {
729         BSTR identifier = 0;
730         preferences->identifier(&identifier);
731
732         m_preferences = 0;
733         preferences->didRemoveFromWebView();
734         // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
735         preferences = 0;
736         if (identifier) {
737             WebPreferences::removeReferenceForIdentifier(identifier);
738             SysFreeString(identifier);
739         }
740     }
741
742     deleteBackingStore();
743     return S_OK;
744 }
745
746 void WebView::repaint(const WebCore::IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly)
747 {
748 #if USE(ACCELERATED_COMPOSITING)
749     if (isAcceleratedCompositing()) {
750         // The contentChanged, immediate, and repaintContentOnly parameters are all based on a non-
751         // compositing painting/scrolling model.
752         addToDirtyRegion(windowRect);
753         return;
754     }
755 #endif
756
757     if (!repaintContentOnly) {
758         RECT rect = windowRect;
759         ::InvalidateRect(m_viewWindow, &rect, false);
760     }
761     if (contentChanged)
762         addToDirtyRegion(windowRect);
763     if (immediate) {
764         if (repaintContentOnly)
765             updateBackingStore(core(topLevelFrame())->view());
766         else
767             ::UpdateWindow(m_viewWindow);
768     }
769 }
770
771 void WebView::deleteBackingStore()
772 {
773     pendingDeleteBackingStoreSet.remove(this);
774
775     if (m_deleteBackingStoreTimerActive) {
776         KillTimer(m_viewWindow, DeleteBackingStoreTimer);
777         m_deleteBackingStoreTimerActive = false;
778     }
779     m_backingStoreBitmap.clear();
780     m_backingStoreDirtyRegion.clear();
781     m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
782 }
783
784 bool WebView::ensureBackingStore()
785 {
786     RECT windowRect;
787     ::GetClientRect(m_viewWindow, &windowRect);
788     LONG width = windowRect.right - windowRect.left;
789     LONG height = windowRect.bottom - windowRect.top;
790     if (width > 0 && height > 0 && (width != m_backingStoreSize.cx || height != m_backingStoreSize.cy)) {
791         deleteBackingStore();
792
793         m_backingStoreSize.cx = width;
794         m_backingStoreSize.cy = height;
795         BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(m_backingStoreSize));
796
797         void* pixels = NULL;
798         m_backingStoreBitmap = RefCountedHBITMAP::create(::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0));
799         return true;
800     }
801
802     return false;
803 }
804
805 void WebView::addToDirtyRegion(const IntRect& dirtyRect)
806 {
807     // FIXME: We want an assert here saying that the dirtyRect is inside the clienRect,
808     // but it was being hit during our layout tests, and is being investigated in
809     // http://webkit.org/b/29350.
810
811 #if USE(ACCELERATED_COMPOSITING)
812     if (isAcceleratedCompositing()) {
813         m_backingLayer->setNeedsDisplayInRect(dirtyRect);
814         return;
815     }
816 #endif
817
818     HRGN newRegion = ::CreateRectRgn(dirtyRect.x(), dirtyRect.y(),
819                                      dirtyRect.maxX(), dirtyRect.maxY());
820     addToDirtyRegion(newRegion);
821 }
822
823 void WebView::addToDirtyRegion(HRGN newRegion)
824 {
825 #if USE(ACCELERATED_COMPOSITING)
826     ASSERT(!isAcceleratedCompositing());
827 #endif
828
829     LOCAL_GDI_COUNTER(0, __FUNCTION__);
830
831     if (m_backingStoreDirtyRegion) {
832         HRGN combinedRegion = ::CreateRectRgn(0,0,0,0);
833         ::CombineRgn(combinedRegion, m_backingStoreDirtyRegion->handle(), newRegion, RGN_OR);
834         ::DeleteObject(newRegion);
835         m_backingStoreDirtyRegion = RefCountedHRGN::create(combinedRegion);
836     } else
837         m_backingStoreDirtyRegion = RefCountedHRGN::create(newRegion);
838
839     if (m_uiDelegatePrivate)
840         m_uiDelegatePrivate->webViewDidInvalidate(this);
841 }
842
843 void WebView::scrollBackingStore(FrameView* frameView, int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect)
844 {
845 #if USE(ACCELERATED_COMPOSITING)
846     if (isAcceleratedCompositing()) {
847         // FIXME: We should be doing something smarter here, like moving tiles around and painting
848         // any newly-exposed tiles. <http://webkit.org/b/52714>
849         m_backingLayer->setNeedsDisplayInRect(scrollViewRect);
850         return;
851     }
852 #endif
853
854     LOCAL_GDI_COUNTER(0, __FUNCTION__);
855
856     // If there's no backing store we don't need to update it
857     if (!m_backingStoreBitmap) {
858         if (m_uiDelegatePrivate)
859             m_uiDelegatePrivate->webViewScrolled(this);
860
861         return;
862     }
863
864     // Make a region to hold the invalidated scroll area.
865     HRGN updateRegion = ::CreateRectRgn(0, 0, 0, 0);
866
867     // Collect our device context info and select the bitmap to scroll.
868     HWndDC windowDC(m_viewWindow);
869     HDC bitmapDC = ::CreateCompatibleDC(windowDC);
870     HGDIOBJ oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->handle());
871     
872     // Scroll the bitmap.
873     RECT scrollRectWin(scrollViewRect);
874     RECT clipRectWin(clipRect);
875     ::ScrollDC(bitmapDC, dx, dy, &scrollRectWin, &clipRectWin, updateRegion, 0);
876     RECT regionBox;
877     ::GetRgnBox(updateRegion, &regionBox);
878
879     // Flush.
880     GdiFlush();
881
882     // Add the dirty region to the backing store's dirty region.
883     addToDirtyRegion(updateRegion);
884
885     if (m_uiDelegatePrivate)
886         m_uiDelegatePrivate->webViewScrolled(this);
887
888     // Update the backing store.
889     updateBackingStore(frameView, bitmapDC, false);
890
891     // Clean up.
892     ::SelectObject(bitmapDC, oldBitmap);
893     ::DeleteDC(bitmapDC);
894 }
895
896 void WebView::sizeChanged(const IntSize& newSize)
897 {
898     deleteBackingStore();
899
900     if (Frame* coreFrame = core(topLevelFrame()))
901         coreFrame->view()->resize(newSize);
902
903 #if USE(ACCELERATED_COMPOSITING)
904     if (m_layerTreeHost)
905         m_layerTreeHost->resize();
906     if (m_backingLayer) {
907         m_backingLayer->setSize(newSize);
908         m_backingLayer->setNeedsDisplay();
909     }
910 #endif
911 }
912
913 // This emulates the Mac smarts for painting rects intelligently.  This is very
914 // important for us, since we double buffer based off dirty rects.
915 static void getUpdateRects(HRGN region, const IntRect& dirtyRect, Vector<IntRect>& rects)
916 {
917     ASSERT_ARG(region, region);
918
919     const int cRectThreshold = 10;
920     const float cWastedSpaceThreshold = 0.75f;
921
922     rects.clear();
923
924     DWORD regionDataSize = GetRegionData(region, sizeof(RGNDATA), NULL);
925     if (!regionDataSize) {
926         rects.append(dirtyRect);
927         return;
928     }
929
930     Vector<unsigned char> buffer(regionDataSize);
931     RGNDATA* regionData = reinterpret_cast<RGNDATA*>(buffer.data());
932     GetRegionData(region, regionDataSize, regionData);
933     if (regionData->rdh.nCount > cRectThreshold) {
934         rects.append(dirtyRect);
935         return;
936     }
937
938     double singlePixels = 0.0;
939     unsigned i;
940     RECT* rect;
941     for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++)
942         singlePixels += (rect->right - rect->left) * (rect->bottom - rect->top);
943
944     double unionPixels = dirtyRect.width() * dirtyRect.height();
945     double wastedSpace = 1.0 - (singlePixels / unionPixels);
946     if (wastedSpace <= cWastedSpaceThreshold) {
947         rects.append(dirtyRect);
948         return;
949     }
950
951     for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++)
952         rects.append(*rect);
953 }
954
955 void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStoreCompletelyDirty, WindowsToPaint windowsToPaint)
956 {
957 #if USE(ACCELERATED_COMPOSITING)
958     ASSERT(!isAcceleratedCompositing());
959 #endif
960
961     LOCAL_GDI_COUNTER(0, __FUNCTION__);
962
963     HDC bitmapDC = dc;
964     HGDIOBJ oldBitmap = 0;
965     if (!dc) {
966         HWndDC windowDC(m_viewWindow);
967         bitmapDC = ::CreateCompatibleDC(windowDC);
968         oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->handle());
969     }
970
971     if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
972         // Do a layout first so that everything we render to the backing store is always current.
973         if (Frame* coreFrame = core(m_mainFrame))
974             if (FrameView* view = coreFrame->view())
975                 view->updateLayoutAndStyleIfNeededRecursive();
976
977         Vector<IntRect> paintRects;
978         if (!backingStoreCompletelyDirty && m_backingStoreDirtyRegion) {
979             RECT regionBox;
980             ::GetRgnBox(m_backingStoreDirtyRegion->handle(), &regionBox);
981             getUpdateRects(m_backingStoreDirtyRegion->handle(), regionBox, paintRects);
982         } else {
983             RECT clientRect;
984             ::GetClientRect(m_viewWindow, &clientRect);
985             paintRects.append(clientRect);
986         }
987
988         for (unsigned i = 0; i < paintRects.size(); ++i)
989             paintIntoBackingStore(frameView, bitmapDC, paintRects[i], windowsToPaint);
990
991         if (m_uiDelegatePrivate)
992             m_uiDelegatePrivate->webViewPainted(this);
993
994         m_backingStoreDirtyRegion.clear();
995     }
996
997     if (!dc) {
998         ::SelectObject(bitmapDC, oldBitmap);
999         ::DeleteDC(bitmapDC);
1000     }
1001
1002     GdiFlush();
1003 }
1004
1005 void WebView::performLayeredWindowUpdate()
1006 {
1007     // The backing store may have been destroyed if the window rect was set to zero height or zero width.
1008     if (!m_backingStoreBitmap)
1009         return;
1010
1011     HWndDC hdcScreen(m_viewWindow);
1012     OwnPtr<HDC> hdcMem = adoptPtr(::CreateCompatibleDC(hdcScreen));
1013     HBITMAP hbmOld = static_cast<HBITMAP>(::SelectObject(hdcMem.get(), m_backingStoreBitmap->handle()));
1014
1015     BITMAP bmpInfo;
1016     ::GetObject(m_backingStoreBitmap->handle(), sizeof(bmpInfo), &bmpInfo);
1017     SIZE windowSize = { bmpInfo.bmWidth, bmpInfo.bmHeight };
1018
1019     BLENDFUNCTION blendFunction;
1020     blendFunction.BlendOp = AC_SRC_OVER;
1021     blendFunction.BlendFlags = 0;
1022     blendFunction.SourceConstantAlpha = 0xFF;
1023     blendFunction.AlphaFormat = AC_SRC_ALPHA;
1024
1025     POINT layerPos = { 0, 0 };
1026     ::UpdateLayeredWindow(m_viewWindow, hdcScreen, 0, &windowSize, hdcMem.get(), &layerPos, 0, &blendFunction, ULW_ALPHA);
1027
1028     ::SelectObject(hdcMem.get(), hbmOld);
1029 }
1030
1031 void WebView::paint(HDC dc, LPARAM options)
1032 {
1033     LOCAL_GDI_COUNTER(0, __FUNCTION__);
1034
1035 #if USE(ACCELERATED_COMPOSITING)
1036     if (isAcceleratedCompositing() && !usesLayeredWindow()) {
1037         m_layerTreeHost->flushPendingLayerChangesNow();
1038         // Flushing might have taken us out of compositing mode.
1039         if (isAcceleratedCompositing()) {
1040             // FIXME: We need to paint into dc (if provided). <http://webkit.org/b/52578>
1041             m_layerTreeHost->paint();
1042             ::ValidateRect(m_viewWindow, 0);
1043             return;
1044         }
1045     }
1046 #endif
1047
1048     Frame* coreFrame = core(m_mainFrame);
1049     if (!coreFrame)
1050         return;
1051     FrameView* frameView = coreFrame->view();
1052
1053     RECT rcPaint;
1054     HDC hdc;
1055     OwnPtr<HRGN> region;
1056     int regionType = NULLREGION;
1057     PAINTSTRUCT ps;
1058     WindowsToPaint windowsToPaint;
1059     if (!dc) {
1060         region = adoptPtr(CreateRectRgn(0,0,0,0));
1061         regionType = GetUpdateRgn(m_viewWindow, region.get(), false);
1062         hdc = BeginPaint(m_viewWindow, &ps);
1063         rcPaint = ps.rcPaint;
1064         // We're painting to the screen, and our child windows can handle
1065         // painting themselves to the screen.
1066         windowsToPaint = PaintWebViewOnly;
1067     } else {
1068         hdc = dc;
1069         ::GetClientRect(m_viewWindow, &rcPaint);
1070         if (options & PRF_ERASEBKGND)
1071             ::FillRect(hdc, &rcPaint, (HBRUSH)GetStockObject(WHITE_BRUSH));
1072         // Since we aren't painting to the screen, we want to paint all our
1073         // children into the HDC.
1074         windowsToPaint = PaintWebViewAndChildren;
1075     }
1076
1077     bool backingStoreCompletelyDirty = ensureBackingStore();
1078     if (!m_backingStoreBitmap) {
1079         if (!dc)
1080             EndPaint(m_viewWindow, &ps);
1081         return;
1082     }
1083
1084     m_paintCount++;
1085
1086     HDC bitmapDC = ::CreateCompatibleDC(hdc);
1087     HGDIOBJ oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->handle());
1088
1089     // Update our backing store if needed.
1090     updateBackingStore(frameView, bitmapDC, backingStoreCompletelyDirty, windowsToPaint);
1091
1092     // Now we blit the updated backing store
1093     IntRect windowDirtyRect = rcPaint;
1094     
1095     // Apply the same heuristic for this update region too.
1096     Vector<IntRect> blitRects;
1097     if (region && regionType == COMPLEXREGION)
1098         getUpdateRects(region.get(), windowDirtyRect, blitRects);
1099     else
1100         blitRects.append(windowDirtyRect);
1101
1102     for (unsigned i = 0; i < blitRects.size(); ++i)
1103         paintIntoWindow(bitmapDC, hdc, blitRects[i]);
1104
1105     ::SelectObject(bitmapDC, oldBitmap);
1106     ::DeleteDC(bitmapDC);
1107
1108     if (!dc)
1109         EndPaint(m_viewWindow, &ps);
1110
1111     m_paintCount--;
1112
1113     if (active())
1114         cancelDeleteBackingStoreSoon();
1115     else
1116         deleteBackingStoreSoon();
1117 }
1118
1119 void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, const IntRect& dirtyRect, WindowsToPaint windowsToPaint)
1120 {
1121     // FIXME: This function should never be called in accelerated compositing mode, and we should
1122     // assert as such. But currently it *is* sometimes called, so we can't assert yet. See
1123     // <http://webkit.org/b/58539>.
1124
1125     LOCAL_GDI_COUNTER(0, __FUNCTION__);
1126
1127     // FIXME: We want an assert here saying that the dirtyRect is inside the clienRect,
1128     // but it was being hit during our layout tests, and is being investigated in
1129     // http://webkit.org/b/29350.
1130
1131     RECT rect = dirtyRect;
1132
1133 #if FLASH_BACKING_STORE_REDRAW
1134     {
1135         HWndDC dc(m_viewWindow);
1136         OwnPtr<HBRUSH> yellowBrush(CreateSolidBrush(RGB(255, 255, 0)));
1137         FillRect(dc, &rect, yellowBrush.get());
1138         GdiFlush();
1139         Sleep(50);
1140         paintIntoWindow(bitmapDC, dc, dirtyRect);
1141     }
1142 #endif
1143
1144     GraphicsContext gc(bitmapDC, m_transparent);
1145     gc.setShouldIncludeChildWindows(windowsToPaint == PaintWebViewAndChildren);
1146     gc.save();
1147     if (m_transparent)
1148         gc.clearRect(dirtyRect);
1149     else
1150         FillRect(bitmapDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
1151
1152     COMPtr<IWebUIDelegatePrivate2> uiPrivate(Query, m_uiDelegate);
1153     if (uiPrivate)
1154         uiPrivate->drawBackground(this, reinterpret_cast<OLE_HANDLE>(bitmapDC), &rect);
1155
1156     if (frameView && frameView->frame() && frameView->frame()->contentRenderer()) {
1157         gc.clip(dirtyRect);
1158         frameView->paint(&gc, dirtyRect);
1159         if (m_shouldInvertColors)
1160             gc.fillRect(dirtyRect, Color::white, ColorSpaceDeviceRGB, CompositeDifference);
1161     }
1162     gc.restore();
1163 }
1164
1165 void WebView::paintIntoWindow(HDC bitmapDC, HDC windowDC, const IntRect& dirtyRect)
1166 {
1167     // FIXME: This function should never be called in accelerated compositing mode, and we should
1168     // assert as such. But currently it *is* sometimes called, so we can't assert yet. See
1169     // <http://webkit.org/b/58539>.
1170
1171     LOCAL_GDI_COUNTER(0, __FUNCTION__);
1172 #if FLASH_WINDOW_REDRAW
1173     OwnPtr<HBRUSH> greenBrush = CreateSolidBrush(RGB(0, 255, 0));
1174     RECT rect = dirtyRect;
1175     FillRect(windowDC, &rect, greenBrush.get());
1176     GdiFlush();
1177     Sleep(50);
1178 #endif
1179
1180     // Blit the dirty rect from the backing store into the same position
1181     // in the destination DC.
1182     BitBlt(windowDC, dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), bitmapDC,
1183            dirtyRect.x(), dirtyRect.y(), SRCCOPY);
1184 }
1185
1186 void WebView::frameRect(RECT* rect)
1187 {
1188     ::GetWindowRect(m_viewWindow, rect);
1189 }
1190
1191 class WindowCloseTimer : public WebCore::SuspendableTimer {
1192 public:
1193     static WindowCloseTimer* create(WebView*);
1194
1195 private:
1196     WindowCloseTimer(ScriptExecutionContext*, WebView*);
1197     virtual void contextDestroyed();
1198     virtual void fired();
1199
1200     WebView* m_webView;
1201 };
1202
1203 WindowCloseTimer* WindowCloseTimer::create(WebView* webView)
1204 {
1205     ASSERT_ARG(webView, webView);
1206     Frame* frame = core(webView->topLevelFrame());
1207     ASSERT(frame);
1208     if (!frame)
1209         return 0;
1210
1211     Document* document = frame->document();
1212     ASSERT(document);
1213     if (!document)
1214         return 0;
1215
1216     return new WindowCloseTimer(document, webView);
1217 }
1218
1219 WindowCloseTimer::WindowCloseTimer(ScriptExecutionContext* context, WebView* webView)
1220     : SuspendableTimer(context)
1221     , m_webView(webView)
1222 {
1223     ASSERT_ARG(context, context);
1224     ASSERT_ARG(webView, webView);
1225 }
1226
1227 void WindowCloseTimer::contextDestroyed()
1228 {
1229     SuspendableTimer::contextDestroyed();
1230     delete this;
1231 }
1232
1233 void WindowCloseTimer::fired()
1234 {
1235     m_webView->closeWindowTimerFired();
1236 }
1237
1238 void WebView::closeWindowSoon()
1239 {
1240     if (m_closeWindowTimer)
1241         return;
1242
1243     m_closeWindowTimer = WindowCloseTimer::create(this);
1244     if (!m_closeWindowTimer)
1245         return;
1246     m_closeWindowTimer->startOneShot(0);
1247
1248     AddRef();
1249 }
1250
1251 void WebView::closeWindowTimerFired()
1252 {
1253     closeWindow();
1254     Release();
1255 }
1256
1257 void WebView::closeWindow()
1258 {
1259     if (m_hasSpellCheckerDocumentTag) {
1260         if (m_editingDelegate)
1261             m_editingDelegate->closeSpellDocument(this);
1262         m_hasSpellCheckerDocumentTag = false;
1263     }
1264
1265     COMPtr<IWebUIDelegate> ui;
1266     if (SUCCEEDED(uiDelegate(&ui)))
1267         ui->webViewClose(this);
1268 }
1269
1270 bool WebView::canHandleRequest(const WebCore::ResourceRequest& request)
1271 {
1272     // On the mac there's an about url protocol implementation but CFNetwork doesn't have that.
1273     if (equalIgnoringCase(String(request.url().protocol()), "about"))
1274         return true;
1275
1276 #if USE(CFNETWORK)
1277     if (CFURLProtocolCanHandleRequest(request.cfURLRequest()))
1278         return true;
1279
1280     // FIXME: Mac WebKit calls _representationExistsForURLScheme here
1281     return false;
1282 #else
1283     return true;
1284 #endif
1285 }
1286
1287 String WebView::standardUserAgentWithApplicationName(const String& applicationName)
1288 {
1289     DEFINE_STATIC_LOCAL(String, osVersion, (windowsVersionForUAString()));
1290     DEFINE_STATIC_LOCAL(String, webKitVersion, (webKitVersionString()));
1291
1292     return makeString("Mozilla/5.0 (", osVersion, ") AppleWebKit/", webKitVersion, " (KHTML, like Gecko)", applicationName.isEmpty() ? "" : " ", applicationName);
1293 }
1294
1295 Page* WebView::page()
1296 {
1297     return m_page;
1298 }
1299
1300 bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam)
1301 {
1302     // Translate the screen coordinates into window coordinates
1303     POINT coords = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1304     if (coords.x == -1 || coords.y == -1) {
1305         // The contextMenuController() holds onto the last context menu that was popped up on the
1306         // page until a new one is created. We need to clear this menu before propagating the event
1307         // through the DOM so that we can detect if we create a new menu for this event, since we
1308         // won't create a new menu if the DOM swallows the event and the defaultEventHandler does
1309         // not run.
1310         m_page->contextMenuController()->clearContextMenu();
1311
1312         Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1313         return focusedFrame->eventHandler()->sendContextMenuEventForKey();
1314
1315     } else {
1316         if (!::ScreenToClient(m_viewWindow, &coords))
1317             return false;
1318     }
1319
1320     lParam = MAKELPARAM(coords.x, coords.y);
1321
1322     m_page->contextMenuController()->clearContextMenu();
1323
1324     IntPoint documentPoint(m_page->mainFrame()->view()->windowToContents(coords));
1325     HitTestResult result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(documentPoint, false);
1326     Frame* targetFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame();
1327
1328     targetFrame->view()->setCursor(pointerCursor());
1329     PlatformMouseEvent mouseEvent(m_viewWindow, WM_RBUTTONUP, wParam, lParam);
1330     bool handledEvent = targetFrame->eventHandler()->sendContextMenuEvent(mouseEvent);
1331     if (!handledEvent)
1332         return false;
1333
1334     ContextMenuController* contextMenuController = m_page->contextMenuController();
1335
1336     // Show the menu
1337     ContextMenu* coreMenu = contextMenuController->contextMenu();
1338     if (!coreMenu)
1339         return false;
1340
1341     Node* node = contextMenuController->hitTestResult().innerNonSharedNode();
1342     if (!node)
1343         return false;
1344
1345     Frame* frame = node->document()->frame();
1346     if (!frame)
1347         return false;
1348
1349     FrameView* view = frame->view();
1350     if (!view)
1351         return false;
1352
1353     POINT point(view->contentsToWindow(contextMenuController->hitTestResult().roundedPoint()));
1354
1355     // Translate the point to screen coordinates
1356     if (!::ClientToScreen(m_viewWindow, &point))
1357         return false;
1358
1359     BOOL hasCustomMenus = false;
1360     if (m_uiDelegate)
1361         m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1362
1363     if (hasCustomMenus)
1364         m_uiDelegate->trackCustomPopupMenu((IWebView*)this, (OLE_HANDLE)(ULONG64)coreMenu->nativeMenu(), &point);
1365     else {
1366         // Surprisingly, TPM_RIGHTBUTTON means that items are selectable with either the right OR left mouse button
1367         UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL
1368             | TPM_LEFTALIGN | TPM_HORPOSANIMATION;
1369         ::TrackPopupMenuEx(coreMenu->nativeMenu(), flags, point.x, point.y, m_viewWindow, 0);
1370     }
1371
1372     return true;
1373 }
1374
1375 bool WebView::onMeasureItem(WPARAM /*wParam*/, LPARAM lParam)
1376 {
1377     if (!m_uiDelegate)
1378         return false;
1379
1380     BOOL hasCustomMenus = false;
1381     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1382     if (!hasCustomMenus)
1383         return false;
1384
1385     m_uiDelegate->measureCustomMenuItem((IWebView*)this, (void*)lParam);
1386     return true;
1387 }
1388
1389 bool WebView::onDrawItem(WPARAM /*wParam*/, LPARAM lParam)
1390 {
1391     if (!m_uiDelegate)
1392         return false;
1393
1394     BOOL hasCustomMenus = false;
1395     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1396     if (!hasCustomMenus)
1397         return false;
1398
1399     m_uiDelegate->drawCustomMenuItem((IWebView*)this, (void*)lParam);
1400     return true;
1401 }
1402
1403 bool WebView::onInitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
1404 {
1405     if (!m_uiDelegate)
1406         return false;
1407
1408     HMENU menu = (HMENU)wParam;
1409     if (!menu)
1410         return false;
1411
1412     BOOL hasCustomMenus = false;
1413     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1414     if (!hasCustomMenus)
1415         return false;
1416
1417     m_uiDelegate->addCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu);
1418     return true;
1419 }
1420
1421 bool WebView::onUninitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
1422 {
1423     if (!m_uiDelegate)
1424         return false;
1425
1426     HMENU menu = (HMENU)wParam;
1427     if (!menu)
1428         return false;
1429
1430     BOOL hasCustomMenus = false;
1431     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1432     if (!hasCustomMenus)
1433         return false;
1434
1435     m_uiDelegate->cleanUpCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu);
1436     return true;
1437 }
1438
1439 void WebView::performContextMenuAction(WPARAM wParam, LPARAM lParam, bool byPosition)
1440 {
1441     ContextMenu* menu = m_page->contextMenuController()->contextMenu();
1442     ASSERT(menu);
1443
1444     ContextMenuItem* item = byPosition ? menu->itemAtIndex((unsigned)wParam) : menu->itemWithAction((ContextMenuAction)wParam);
1445     if (!item)
1446         return;
1447     m_page->contextMenuController()->contextMenuItemSelected(item);
1448 }
1449
1450 bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam)
1451 {
1452     static LONG globalClickCount;
1453     static IntPoint globalPrevPoint;
1454     static MouseButton globalPrevButton;
1455     static LONG globalPrevMouseDownTime;
1456
1457     if (message == WM_CANCELMODE) {
1458         m_page->mainFrame()->eventHandler()->lostMouseCapture();
1459         return true;
1460     }
1461
1462     // Create our event.
1463     // On WM_MOUSELEAVE we need to create a mouseout event, so we force the position
1464     // of the event to be at (MINSHORT, MINSHORT).
1465     LPARAM position = (message == WM_MOUSELEAVE) ? ((MINSHORT << 16) | MINSHORT) : lParam;
1466     PlatformMouseEvent mouseEvent(m_viewWindow, message, wParam, position, m_mouseActivated);
1467
1468     setMouseActivated(false);
1469
1470     bool insideThreshold = abs(globalPrevPoint.x() - mouseEvent.position().x()) < ::GetSystemMetrics(SM_CXDOUBLECLK) &&
1471                            abs(globalPrevPoint.y() - mouseEvent.position().y()) < ::GetSystemMetrics(SM_CYDOUBLECLK);
1472     LONG messageTime = ::GetMessageTime();
1473
1474     bool handled = false;
1475
1476     if (message == WM_LBUTTONDOWN || message == WM_MBUTTONDOWN || message == WM_RBUTTONDOWN) {
1477         // FIXME: I'm not sure if this is the "right" way to do this
1478         // but without this call, we never become focused since we don't allow
1479         // the default handling of mouse events.
1480         SetFocus(m_viewWindow);
1481
1482         // Always start capturing events when the mouse goes down in our HWND.
1483         ::SetCapture(m_viewWindow);
1484
1485         if (((messageTime - globalPrevMouseDownTime) < (LONG)::GetDoubleClickTime()) && 
1486             insideThreshold &&
1487             mouseEvent.button() == globalPrevButton)
1488             globalClickCount++;
1489         else
1490             // Reset the click count.
1491             globalClickCount = 1;
1492         globalPrevMouseDownTime = messageTime;
1493         globalPrevButton = mouseEvent.button();
1494         globalPrevPoint = mouseEvent.position();
1495         
1496         mouseEvent.setClickCount(globalClickCount);
1497         handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
1498     } else if (message == WM_LBUTTONDBLCLK || message == WM_MBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) {
1499         globalClickCount++;
1500         mouseEvent.setClickCount(globalClickCount);
1501         handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
1502     } else if (message == WM_LBUTTONUP || message == WM_MBUTTONUP || message == WM_RBUTTONUP) {
1503         // Record the global position and the button of the up.
1504         globalPrevButton = mouseEvent.button();
1505         globalPrevPoint = mouseEvent.position();
1506         mouseEvent.setClickCount(globalClickCount);
1507         m_page->mainFrame()->eventHandler()->handleMouseReleaseEvent(mouseEvent);
1508         ::ReleaseCapture();
1509     } else if (message == WM_MOUSELEAVE && m_mouseOutTracker) {
1510         // Once WM_MOUSELEAVE is fired windows clears this tracker
1511         // so there is no need to disable it ourselves.
1512         m_mouseOutTracker.clear();
1513         m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent);
1514         handled = true;
1515     } else if (message == WM_MOUSEMOVE) {
1516         if (!insideThreshold)
1517             globalClickCount = 0;
1518         mouseEvent.setClickCount(globalClickCount);
1519         handled = m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent);
1520         if (!m_mouseOutTracker) {
1521             m_mouseOutTracker = adoptPtr(new TRACKMOUSEEVENT);
1522             m_mouseOutTracker->cbSize = sizeof(TRACKMOUSEEVENT);
1523             m_mouseOutTracker->dwFlags = TME_LEAVE;
1524             m_mouseOutTracker->hwndTrack = m_viewWindow;
1525             ::TrackMouseEvent(m_mouseOutTracker.get());
1526         }
1527     }
1528     return handled;
1529 }
1530
1531 bool WebView::gestureNotify(WPARAM wParam, LPARAM lParam)
1532 {
1533     GESTURENOTIFYSTRUCT* gn = reinterpret_cast<GESTURENOTIFYSTRUCT*>(lParam);
1534
1535     Frame* coreFrame = core(m_mainFrame);
1536     if (!coreFrame)
1537         return false;
1538
1539     ScrollView* view = coreFrame->view();
1540     if (!view)
1541         return false;
1542
1543     // If we don't have this function, we shouldn't be receiving this message
1544     ASSERT(SetGestureConfigPtr());
1545
1546     bool hitScrollbar = false;
1547     POINT gestureBeginPoint = {gn->ptsLocation.x, gn->ptsLocation.y};
1548     HitTestRequest request(HitTestRequest::ReadOnly);
1549     for (Frame* childFrame = m_page->mainFrame(); childFrame; childFrame = EventHandler::subframeForTargetNode(m_gestureTargetNode.get())) {
1550         FrameView* frameView = childFrame->view();
1551         if (!frameView)
1552             break;
1553         RenderView* renderView = childFrame->document()->renderView();
1554         if (!renderView)
1555             break;
1556         RenderLayer* layer = renderView->layer();
1557         if (!layer)
1558             break;
1559
1560         HitTestResult result(frameView->screenToContents(gestureBeginPoint));
1561         layer->hitTest(request, result);
1562         m_gestureTargetNode = result.innerNode();
1563
1564         if (!hitScrollbar)
1565             hitScrollbar = result.scrollbar();
1566     }
1567
1568     if (!hitScrollbar) {
1569         // The hit testing above won't detect if we've hit the main frame's vertical scrollbar. Check that manually now.
1570         RECT webViewRect;
1571         GetWindowRect(m_viewWindow, &webViewRect);
1572         hitScrollbar = view->verticalScrollbar() && (gestureBeginPoint.x > (webViewRect.right - view->verticalScrollbar()->theme()->scrollbarThickness()));  
1573     }
1574
1575     bool canBeScrolled = false;
1576     if (m_gestureTargetNode) {
1577         for (RenderObject* renderer = m_gestureTargetNode->renderer(); renderer; renderer = renderer->parent()) {
1578             if (renderer->isBox() && toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()) {
1579                 canBeScrolled = true;
1580                 break;
1581             }
1582         }
1583     }
1584
1585     // We always allow two-fingered panning with inertia and a gutter (which limits movement to one
1586     // direction in most cases).
1587     DWORD dwPanWant = GC_PAN | GC_PAN_WITH_INERTIA | GC_PAN_WITH_GUTTER;
1588     // We never allow single-fingered horizontal panning. That gesture is reserved for creating text
1589     // selections. This matches IE.
1590     DWORD dwPanBlock = GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
1591
1592     if (hitScrollbar || !canBeScrolled) {
1593         // The part of the page under the gesture can't be scrolled, or the gesture is on a scrollbar.
1594         // Disallow single-fingered vertical panning in this case, too, so we'll fall back to the default
1595         // behavior (which allows the scrollbar thumb to be dragged, text selections to be made, etc.).
1596         dwPanBlock |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
1597     } else {
1598         // The part of the page the gesture is under can be scrolled, and we're not under a scrollbar.
1599         // Allow single-fingered vertical panning in this case, so the user will be able to pan the page
1600         // with one or two fingers.
1601         dwPanWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
1602     }
1603
1604     GESTURECONFIG gc = { GID_PAN, dwPanWant, dwPanBlock };
1605     return SetGestureConfigPtr()(m_viewWindow, 0, 1, &gc, sizeof(GESTURECONFIG));
1606 }
1607
1608 bool WebView::gesture(WPARAM wParam, LPARAM lParam) 
1609 {
1610     // We want to bail out if we don't have either of these functions
1611     if (!GetGestureInfoPtr() || !CloseGestureInfoHandlePtr())
1612         return false;
1613
1614     HGESTUREINFO gestureHandle = reinterpret_cast<HGESTUREINFO>(lParam);
1615     
1616     GESTUREINFO gi = {0};
1617     gi.cbSize = sizeof(GESTUREINFO);
1618
1619     if (!GetGestureInfoPtr()(gestureHandle, reinterpret_cast<PGESTUREINFO>(&gi)))
1620         return false;
1621
1622     switch (gi.dwID) {
1623     case GID_BEGIN:
1624         m_lastPanX = gi.ptsLocation.x;
1625         m_lastPanY = gi.ptsLocation.y;
1626
1627         break;
1628     case GID_END:
1629         m_gestureTargetNode = 0;
1630         break;
1631     case GID_PAN: {
1632         // Where are the fingers currently?
1633         long currentX = gi.ptsLocation.x;
1634         long currentY = gi.ptsLocation.y;
1635         // How far did we pan in each direction?
1636         long deltaX = currentX - m_lastPanX;
1637         long deltaY = currentY - m_lastPanY;
1638         // Calculate the overpan for window bounce
1639         m_yOverpan -= m_lastPanY - currentY;
1640         m_xOverpan -= m_lastPanX - currentX;
1641         // Update our class variables with updated values
1642         m_lastPanX = currentX;
1643         m_lastPanY = currentY;
1644
1645         Frame* coreFrame = core(m_mainFrame);
1646         if (!coreFrame) {
1647             CloseGestureInfoHandlePtr()(gestureHandle);
1648             return false;
1649         }
1650
1651         if (!m_gestureTargetNode || !m_gestureTargetNode->renderer())
1652             return false;
1653
1654         // We negate here since panning up moves the content up, but moves the scrollbar down.
1655         m_gestureTargetNode->renderer()->enclosingLayer()->scrollByRecursively(IntSize(-deltaX, -deltaY));
1656            
1657         if (!(UpdatePanningFeedbackPtr() && BeginPanningFeedbackPtr() && EndPanningFeedbackPtr())) {
1658             CloseGestureInfoHandlePtr()(gestureHandle);
1659             return true;
1660         }
1661
1662         if (gi.dwFlags & GF_BEGIN) {
1663             BeginPanningFeedbackPtr()(m_viewWindow);
1664             m_yOverpan = 0;
1665         } else if (gi.dwFlags & GF_END) {
1666             EndPanningFeedbackPtr()(m_viewWindow, true);
1667             m_yOverpan = 0;
1668         }
1669
1670         ScrollView* view = coreFrame->view();
1671         if (!view) {
1672             CloseGestureInfoHandlePtr()(gestureHandle);
1673             return true;
1674         }
1675         Scrollbar* vertScrollbar = view->verticalScrollbar();
1676         if (!vertScrollbar) {
1677             CloseGestureInfoHandlePtr()(gestureHandle);
1678             return true;
1679         }
1680
1681         // FIXME: Support Horizontal Window Bounce. <https://webkit.org/b/28500>.
1682         // FIXME: If the user starts panning down after a window bounce has started, the window doesn't bounce back 
1683         // until they release their finger. <https://webkit.org/b/28501>.
1684         if (vertScrollbar->currentPos() == 0)
1685             UpdatePanningFeedbackPtr()(m_viewWindow, 0, m_yOverpan, gi.dwFlags & GF_INERTIA);
1686         else if (vertScrollbar->currentPos() >= vertScrollbar->maximum())
1687             UpdatePanningFeedbackPtr()(m_viewWindow, 0, m_yOverpan, gi.dwFlags & GF_INERTIA);
1688
1689         CloseGestureInfoHandlePtr()(gestureHandle);
1690         return true;
1691     }
1692     default:
1693         break;
1694     }
1695
1696     // If we get to this point, the gesture has not been handled. We forward
1697     // the call to DefWindowProc by returning false, and we don't need to 
1698     // to call CloseGestureInfoHandle. 
1699     // http://msdn.microsoft.com/en-us/library/dd353228(VS.85).aspx
1700     return false;
1701 }
1702
1703 bool WebView::mouseWheel(WPARAM wParam, LPARAM lParam, bool isMouseHWheel)
1704 {
1705     // Ctrl+Mouse wheel doesn't ever go into WebCore.  It is used to
1706     // zoom instead (Mac zooms the whole Desktop, but Windows browsers trigger their
1707     // own local zoom modes for Ctrl+wheel).
1708     if (wParam & MK_CONTROL) {
1709         short delta = short(HIWORD(wParam));
1710         if (delta < 0)
1711             makeTextSmaller(0);
1712         else
1713             makeTextLarger(0);
1714         return true;
1715     }
1716     
1717     // 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.
1718     HWND focusedWindow = GetFocus();
1719     if (focusedWindow && focusedWindow != m_viewWindow) {
1720         // 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).
1721         WCHAR className[256];
1722
1723         // Make sure truncation won't affect the comparison.
1724         ASSERT(WTF_ARRAY_LENGTH(className) > wcslen(PopupMenuWin::popupClassName()));
1725
1726         if (GetClassNameW(focusedWindow, className, WTF_ARRAY_LENGTH(className)) && !wcscmp(className, PopupMenuWin::popupClassName())) {
1727             // We don't let the WebView scroll here for two reasons - 1) To match Firefox behavior, 2) If we do scroll, we lose the
1728             // focus ring around the select menu.
1729             SetFocus(m_viewWindow);
1730             return true;
1731         }
1732     }
1733
1734     PlatformWheelEvent wheelEvent(m_viewWindow, wParam, lParam, isMouseHWheel);
1735     Frame* coreFrame = core(m_mainFrame);
1736     if (!coreFrame)
1737         return false;
1738
1739     return coreFrame->eventHandler()->handleWheelEvent(wheelEvent);
1740 }
1741
1742 bool WebView::verticalScroll(WPARAM wParam, LPARAM /*lParam*/)
1743 {
1744     ScrollDirection direction;
1745     ScrollGranularity granularity;
1746     switch (LOWORD(wParam)) {
1747     case SB_LINEDOWN:
1748         granularity = ScrollByLine;
1749         direction = ScrollDown;
1750         break;
1751     case SB_LINEUP:
1752         granularity = ScrollByLine;
1753         direction = ScrollUp;
1754         break;
1755     case SB_PAGEDOWN:
1756         granularity = ScrollByDocument;
1757         direction = ScrollDown;
1758         break;
1759     case SB_PAGEUP:
1760         granularity = ScrollByDocument;
1761         direction = ScrollUp;
1762         break;
1763     default:
1764         return false;
1765         break;
1766     }
1767     
1768     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1769     return frame->eventHandler()->scrollRecursively(direction, granularity);
1770 }
1771
1772 bool WebView::horizontalScroll(WPARAM wParam, LPARAM /*lParam*/)
1773 {
1774     ScrollDirection direction;
1775     ScrollGranularity granularity;
1776     switch (LOWORD(wParam)) {
1777     case SB_LINELEFT:
1778         granularity = ScrollByLine;
1779         direction = ScrollLeft;
1780         break;
1781     case SB_LINERIGHT:
1782         granularity = ScrollByLine;
1783         direction = ScrollRight;
1784         break;
1785     case SB_PAGELEFT:
1786         granularity = ScrollByDocument;
1787         direction = ScrollLeft;
1788         break;
1789     case SB_PAGERIGHT:
1790         granularity = ScrollByDocument;
1791         direction = ScrollRight;
1792         break;
1793     default:
1794         return false;
1795     }
1796
1797     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1798     return frame->eventHandler()->scrollRecursively(direction, granularity);
1799 }
1800
1801
1802 bool WebView::execCommand(WPARAM wParam, LPARAM /*lParam*/)
1803 {
1804     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1805     switch (LOWORD(wParam)) {
1806         case SelectAll:
1807             return frame->editor()->command("SelectAll").execute();
1808         case Undo:
1809             return frame->editor()->command("Undo").execute();
1810         case Redo:
1811             return frame->editor()->command("Redo").execute();
1812     }
1813     return false;
1814 }
1815
1816 bool WebView::keyUp(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
1817 {
1818     PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformEvent::KeyUp, systemKeyDown);
1819
1820     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1821     m_currentCharacterCode = 0;
1822
1823     return frame->eventHandler()->keyEvent(keyEvent);
1824 }
1825
1826 static const unsigned CtrlKey = 1 << 0;
1827 static const unsigned AltKey = 1 << 1;
1828 static const unsigned ShiftKey = 1 << 2;
1829
1830
1831 struct KeyDownEntry {
1832     unsigned virtualKey;
1833     unsigned modifiers;
1834     const char* name;
1835 };
1836
1837 struct KeyPressEntry {
1838     unsigned charCode;
1839     unsigned modifiers;
1840     const char* name;
1841 };
1842
1843 static const KeyDownEntry keyDownEntries[] = {
1844     { VK_LEFT,   0,                  "MoveLeft"                                    },
1845     { VK_LEFT,   ShiftKey,           "MoveLeftAndModifySelection"                  },
1846     { VK_LEFT,   CtrlKey,            "MoveWordLeft"                                },
1847     { VK_LEFT,   CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection"              },
1848     { VK_RIGHT,  0,                  "MoveRight"                                   },
1849     { VK_RIGHT,  ShiftKey,           "MoveRightAndModifySelection"                 },
1850     { VK_RIGHT,  CtrlKey,            "MoveWordRight"                               },
1851     { VK_RIGHT,  CtrlKey | ShiftKey, "MoveWordRightAndModifySelection"             },
1852     { VK_UP,     0,                  "MoveUp"                                      },
1853     { VK_UP,     ShiftKey,           "MoveUpAndModifySelection"                    },
1854     { VK_PRIOR,  ShiftKey,           "MovePageUpAndModifySelection"                },
1855     { VK_DOWN,   0,                  "MoveDown"                                    },
1856     { VK_DOWN,   ShiftKey,           "MoveDownAndModifySelection"                  },
1857     { VK_NEXT,   ShiftKey,           "MovePageDownAndModifySelection"              },
1858     { VK_PRIOR,  0,                  "MovePageUp"                                  },
1859     { VK_NEXT,   0,                  "MovePageDown"                                },
1860     { VK_HOME,   0,                  "MoveToBeginningOfLine"                       },
1861     { VK_HOME,   ShiftKey,           "MoveToBeginningOfLineAndModifySelection"     },
1862     { VK_HOME,   CtrlKey,            "MoveToBeginningOfDocument"                   },
1863     { VK_HOME,   CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
1864
1865     { VK_END,    0,                  "MoveToEndOfLine"                             },
1866     { VK_END,    ShiftKey,           "MoveToEndOfLineAndModifySelection"           },
1867     { VK_END,    CtrlKey,            "MoveToEndOfDocument"                         },
1868     { VK_END,    CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection"       },
1869
1870     { VK_BACK,   0,                  "DeleteBackward"                              },
1871     { VK_BACK,   ShiftKey,           "DeleteBackward"                              },
1872     { VK_DELETE, 0,                  "DeleteForward"                               },
1873     { VK_BACK,   CtrlKey,            "DeleteWordBackward"                          },
1874     { VK_DELETE, CtrlKey,            "DeleteWordForward"                           },
1875     
1876     { 'B',       CtrlKey,            "ToggleBold"                                  },
1877     { 'I',       CtrlKey,            "ToggleItalic"                                },
1878
1879     { VK_ESCAPE, 0,                  "Cancel"                                      },
1880     { VK_OEM_PERIOD, CtrlKey,        "Cancel"                                      },
1881     { VK_TAB,    0,                  "InsertTab"                                   },
1882     { VK_TAB,    ShiftKey,           "InsertBacktab"                               },
1883     { VK_RETURN, 0,                  "InsertNewline"                               },
1884     { VK_RETURN, CtrlKey,            "InsertNewline"                               },
1885     { VK_RETURN, AltKey,             "InsertNewline"                               },
1886     { VK_RETURN, ShiftKey,           "InsertNewline"                               },
1887     { VK_RETURN, AltKey | ShiftKey,  "InsertNewline"                               },
1888
1889     // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled
1890     // in the application or in WebKit. We chose WebKit.
1891     { 'C',       CtrlKey,            "Copy"                                        },
1892     { 'V',       CtrlKey,            "Paste"                                       },
1893     { 'X',       CtrlKey,            "Cut"                                         },
1894     { 'A',       CtrlKey,            "SelectAll"                                   },
1895     { VK_INSERT, CtrlKey,            "Copy"                                        },
1896     { VK_DELETE, ShiftKey,           "Cut"                                         },
1897     { VK_INSERT, ShiftKey,           "Paste"                                       },
1898     { 'Z',       CtrlKey,            "Undo"                                        },
1899     { 'Z',       CtrlKey | ShiftKey, "Redo"                                        },
1900 };
1901
1902 static const KeyPressEntry keyPressEntries[] = {
1903     { '\t',   0,                  "InsertTab"                                   },
1904     { '\t',   ShiftKey,           "InsertBacktab"                               },
1905     { '\r',   0,                  "InsertNewline"                               },
1906     { '\r',   CtrlKey,            "InsertNewline"                               },
1907     { '\r',   AltKey,             "InsertNewline"                               },
1908     { '\r',   ShiftKey,           "InsertNewline"                               },
1909     { '\r',   AltKey | ShiftKey,  "InsertNewline"                               },
1910 };
1911
1912 const char* WebView::interpretKeyEvent(const KeyboardEvent* evt)
1913 {
1914     ASSERT(evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
1915
1916     static HashMap<int, const char*>* keyDownCommandsMap = 0;
1917     static HashMap<int, const char*>* keyPressCommandsMap = 0;
1918
1919     if (!keyDownCommandsMap) {
1920         keyDownCommandsMap = new HashMap<int, const char*>;
1921         keyPressCommandsMap = new HashMap<int, const char*>;
1922
1923         for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyDownEntries); ++i)
1924             keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
1925
1926         for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyPressEntries); ++i)
1927             keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
1928     }
1929
1930     unsigned modifiers = 0;
1931     if (evt->shiftKey())
1932         modifiers |= ShiftKey;
1933     if (evt->altKey())
1934         modifiers |= AltKey;
1935     if (evt->ctrlKey())
1936         modifiers |= CtrlKey;
1937
1938     if (evt->type() == eventNames().keydownEvent) {
1939         int mapKey = modifiers << 16 | evt->keyCode();
1940         return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
1941     }
1942
1943     int mapKey = modifiers << 16 | evt->charCode();
1944     return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
1945 }
1946
1947 bool WebView::handleEditingKeyboardEvent(KeyboardEvent* evt)
1948 {
1949     Node* node = evt->target()->toNode();
1950     ASSERT(node);
1951     Frame* frame = node->document()->frame();
1952     ASSERT(frame);
1953
1954     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
1955     if (!keyEvent || keyEvent->isSystemKey())  // do not treat this as text input if it's a system key event
1956         return false;
1957
1958     Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
1959
1960     if (keyEvent->type() == PlatformEvent::RawKeyDown) {
1961         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
1962         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
1963         // (e.g. Tab that inserts a Tab character, or Enter).
1964         return !command.isTextInsertion() && command.execute(evt);
1965     }
1966
1967      if (command.execute(evt))
1968         return true;
1969
1970     // Don't insert null or control characters as they can result in unexpected behaviour
1971     if (evt->charCode() < ' ')
1972         return false;
1973
1974     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
1975 }
1976
1977 bool WebView::keyDown(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
1978 {
1979 #if ENABLE(FULLSCREEN_API)
1980     // Trap the ESC key when in full screen mode.
1981     if (virtualKeyCode == VK_ESCAPE && isFullScreen()) {
1982         m_fullscreenController->exitFullScreen();
1983         return false;
1984     }
1985 #endif
1986     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1987
1988     PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformEvent::RawKeyDown, systemKeyDown);
1989     bool handled = frame->eventHandler()->keyEvent(keyEvent);
1990
1991     // These events cannot be canceled, and we have no default handling for them.
1992     // FIXME: match IE list more closely, see <http://msdn2.microsoft.com/en-us/library/ms536938.aspx>.
1993     if (systemKeyDown && virtualKeyCode != VK_RETURN)
1994         return false;
1995
1996     if (handled) {
1997         // FIXME: remove WM_UNICHAR, too
1998         MSG msg;
1999         // WM_SYSCHAR events should not be removed, because access keys are implemented in WebCore in WM_SYSCHAR handler.
2000         if (!systemKeyDown)
2001             ::PeekMessage(&msg, m_viewWindow, WM_CHAR, WM_CHAR, PM_REMOVE);
2002         return true;
2003     }
2004
2005     // We need to handle back/forward using either Ctrl+Left/Right Arrow keys.
2006     // FIXME: This logic should probably be in EventHandler::defaultArrowEventHandler().
2007     // FIXME: Should check that other modifiers aren't pressed.
2008     if (virtualKeyCode == VK_RIGHT && keyEvent.ctrlKey())
2009         return m_page->goForward();
2010     if (virtualKeyCode == VK_LEFT && keyEvent.ctrlKey())
2011         return m_page->goBack();
2012
2013     // Need to scroll the page if the arrow keys, pgup/dn, or home/end are hit.
2014     ScrollDirection direction;
2015     ScrollGranularity granularity;
2016     switch (virtualKeyCode) {
2017         case VK_LEFT:
2018             granularity = ScrollByLine;
2019             direction = ScrollLeft;
2020             break;
2021         case VK_RIGHT:
2022             granularity = ScrollByLine;
2023             direction = ScrollRight;
2024             break;
2025         case VK_UP:
2026             granularity = ScrollByLine;
2027             direction = ScrollUp;
2028             break;
2029         case VK_DOWN:
2030             granularity = ScrollByLine;
2031             direction = ScrollDown;
2032             break;
2033         case VK_HOME:
2034             granularity = ScrollByDocument;
2035             direction = ScrollUp;
2036             break;
2037         case VK_END:
2038             granularity = ScrollByDocument;
2039             direction = ScrollDown;
2040             break;
2041         case VK_PRIOR:
2042             granularity = ScrollByPage;
2043             direction = ScrollUp;
2044             break;
2045         case VK_NEXT:
2046             granularity = ScrollByPage;
2047             direction = ScrollDown;
2048             break;
2049         default:
2050             return false;
2051     }
2052
2053     return frame->eventHandler()->scrollRecursively(direction, granularity);
2054 }
2055
2056 bool WebView::keyPress(WPARAM charCode, LPARAM keyData, bool systemKeyDown)
2057 {
2058     Frame* frame = m_page->focusController()->focusedOrMainFrame();
2059
2060     PlatformKeyboardEvent keyEvent(m_viewWindow, charCode, keyData, PlatformEvent::Char, systemKeyDown);
2061     // IE does not dispatch keypress event for WM_SYSCHAR.
2062     if (systemKeyDown)
2063         return frame->eventHandler()->handleAccessKey(keyEvent);
2064     return frame->eventHandler()->keyEvent(keyEvent);
2065 }
2066
2067 void WebView::setIsBeingDestroyed()
2068 {
2069     m_isBeingDestroyed = true;
2070
2071     // Remove our this pointer from the window so we won't try to handle any more window messages.
2072     // See <http://webkit.org/b/55054>.
2073     ::SetWindowLongPtrW(m_viewWindow, 0, 0);
2074 }
2075
2076 void WebView::setShouldInvertColors(bool shouldInvertColors)
2077 {
2078     if (m_shouldInvertColors == shouldInvertColors)
2079         return;
2080
2081     m_shouldInvertColors = shouldInvertColors;
2082
2083 #if USE(ACCELERATED_COMPOSITING)
2084     if (m_layerTreeHost)
2085         m_layerTreeHost->setShouldInvertColors(shouldInvertColors);
2086 #endif
2087
2088     RECT windowRect = {0};
2089     frameRect(&windowRect);
2090     repaint(windowRect, true, true);
2091 }
2092
2093 bool WebView::registerWebViewWindowClass()
2094 {
2095     static bool haveRegisteredWindowClass = false;
2096     if (haveRegisteredWindowClass)
2097         return true;
2098
2099     haveRegisteredWindowClass = true;
2100
2101     WNDCLASSEX wcex;
2102
2103     wcex.cbSize = sizeof(WNDCLASSEX);
2104
2105     wcex.style          = CS_DBLCLKS;
2106     wcex.lpfnWndProc    = WebViewWndProc;
2107     wcex.cbClsExtra     = 0;
2108     wcex.cbWndExtra     = 4; // 4 bytes for the IWebView pointer
2109     wcex.hInstance      = gInstance;
2110     wcex.hIcon          = 0;
2111     wcex.hCursor        = ::LoadCursor(0, IDC_ARROW);
2112     wcex.hbrBackground  = 0;
2113     wcex.lpszMenuName   = 0;
2114     wcex.lpszClassName  = kWebViewWindowClassName;
2115     wcex.hIconSm        = 0;
2116
2117     return !!RegisterClassEx(&wcex);
2118 }
2119
2120 static HWND findTopLevelParent(HWND window)
2121 {
2122     if (!window)
2123         return 0;
2124
2125     HWND current = window;
2126     for (HWND parent = GetParent(current); current; current = parent, parent = GetParent(parent))
2127         if (!parent || !(GetWindowLongPtr(current, GWL_STYLE) & (WS_POPUP | WS_CHILD)))
2128             return current;
2129     ASSERT_NOT_REACHED();
2130     return 0;
2131 }
2132
2133 LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
2134 {
2135     LRESULT lResult = 0;
2136     LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0);
2137     WebView* webView = reinterpret_cast<WebView*>(longPtr);
2138     WebFrame* mainFrameImpl = webView ? webView->topLevelFrame() : 0;
2139     if (!mainFrameImpl)
2140         return DefWindowProc(hWnd, message, wParam, lParam);
2141
2142     // We shouldn't be trying to handle any window messages after WM_DESTROY.
2143     // See <http://webkit.org/b/55054>.
2144     ASSERT(!webView->isBeingDestroyed());
2145
2146     // hold a ref, since the WebView could go away in an event handler.
2147     COMPtr<WebView> protector(webView);
2148     ASSERT(webView);
2149
2150     // Windows Media Player has a modal message loop that will deliver messages
2151     // to us at inappropriate times and we will crash if we handle them when
2152     // they are delivered. We repost paint messages so that we eventually get
2153     // a chance to paint once the modal loop has exited, but other messages
2154     // aren't safe to repost, so we just drop them.
2155     if (PluginView::isCallingPlugin()) {
2156         if (message == WM_PAINT)
2157             PostMessage(hWnd, message, wParam, lParam);
2158         return 0;
2159     }
2160
2161     bool handled = true;
2162
2163     switch (message) {
2164         case WM_PAINT: {
2165             webView->paint(0, 0);
2166             if (webView->usesLayeredWindow())
2167                 webView->performLayeredWindowUpdate();
2168             break;
2169         }
2170         case WM_ERASEBKGND:
2171             if (webView->usesLayeredWindow()) {
2172                 // Don't perform a background erase for transparent views.
2173                 handled = true;
2174                 lResult = 1;
2175             }
2176             break;
2177         case WM_PRINTCLIENT:
2178             webView->paint((HDC)wParam, lParam);
2179             break;
2180         case WM_DESTROY:
2181             webView->setIsBeingDestroyed();
2182             webView->close();
2183             break;
2184         case WM_GESTURENOTIFY:
2185             handled = webView->gestureNotify(wParam, lParam);
2186             break;
2187         case WM_GESTURE:
2188             handled = webView->gesture(wParam, lParam);
2189             break;
2190         case WM_MOUSEMOVE:
2191         case WM_LBUTTONDOWN:
2192         case WM_MBUTTONDOWN:
2193         case WM_RBUTTONDOWN:
2194         case WM_LBUTTONDBLCLK:
2195         case WM_MBUTTONDBLCLK:
2196         case WM_RBUTTONDBLCLK:
2197         case WM_LBUTTONUP:
2198         case WM_MBUTTONUP:
2199         case WM_RBUTTONUP:
2200         case WM_MOUSELEAVE:
2201         case WM_CANCELMODE:
2202             if (Frame* coreFrame = core(mainFrameImpl))
2203                 if (coreFrame->view()->didFirstLayout())
2204                     handled = webView->handleMouseEvent(message, wParam, lParam);
2205             break;
2206         case WM_MOUSEWHEEL:
2207         case WM_VISTA_MOUSEHWHEEL:
2208             if (Frame* coreFrame = core(mainFrameImpl))
2209                 if (coreFrame->view()->didFirstLayout())
2210                     handled = webView->mouseWheel(wParam, lParam, message == WM_VISTA_MOUSEHWHEEL);
2211             break;
2212         case WM_SYSKEYDOWN:
2213             handled = webView->keyDown(wParam, lParam, true);
2214             break;
2215         case WM_KEYDOWN:
2216             handled = webView->keyDown(wParam, lParam);
2217             break;
2218         case WM_SYSKEYUP:
2219             handled = webView->keyUp(wParam, lParam, true);
2220             break;
2221         case WM_KEYUP:
2222             handled = webView->keyUp(wParam, lParam);
2223             break;
2224         case WM_SYSCHAR:
2225             handled = webView->keyPress(wParam, lParam, true);
2226             break;
2227         case WM_CHAR:
2228             handled = webView->keyPress(wParam, lParam);
2229             break;
2230         // FIXME: We need to check WM_UNICHAR to support supplementary characters (that don't fit in 16 bits).
2231         case WM_SIZE:
2232             if (lParam != 0)
2233                 webView->sizeChanged(IntSize(LOWORD(lParam), HIWORD(lParam)));
2234             break;
2235         case WM_SHOWWINDOW:
2236             lResult = DefWindowProc(hWnd, message, wParam, lParam);
2237             if (wParam == 0) {
2238                 // The window is being hidden (e.g., because we switched tabs).
2239                 // Null out our backing store.
2240                 webView->deleteBackingStore();
2241             }
2242             break;
2243         case WM_SETFOCUS: {
2244             COMPtr<IWebUIDelegate> uiDelegate;
2245             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
2246             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate
2247                 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
2248                 uiDelegatePrivate->webViewReceivedFocus(webView);
2249
2250             FocusController* focusController = webView->page()->focusController();
2251             if (Frame* frame = focusController->focusedFrame()) {
2252                 // Send focus events unless the previously focused window is a
2253                 // child of ours (for example a plugin).
2254                 if (!IsChild(hWnd, reinterpret_cast<HWND>(wParam)))
2255                     focusController->setFocused(true);
2256             } else
2257                 focusController->setFocused(true);
2258             break;
2259         }
2260         case WM_KILLFOCUS: {
2261             COMPtr<IWebUIDelegate> uiDelegate;
2262             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
2263             HWND newFocusWnd = reinterpret_cast<HWND>(wParam);
2264             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate
2265                 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
2266                 uiDelegatePrivate->webViewLostFocus(webView, (OLE_HANDLE)(ULONG64)newFocusWnd);
2267
2268             FocusController* focusController = webView->page()->focusController();
2269             Frame* frame = focusController->focusedOrMainFrame();
2270             webView->resetIME(frame);
2271             // Send blur events unless we're losing focus to a child of ours.
2272             if (!IsChild(hWnd, newFocusWnd))
2273                 focusController->setFocused(false);
2274
2275             // If we are pan-scrolling when we lose focus, stop the pan scrolling.
2276             frame->eventHandler()->stopAutoscrollTimer();
2277
2278             break;
2279         }
2280         case WM_WINDOWPOSCHANGED:
2281             if (reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW)
2282                 webView->updateActiveStateSoon();
2283             handled = false;
2284             break;
2285         case WM_CUT:
2286             webView->cut(0);
2287             break;
2288         case WM_COPY:
2289             webView->copy(0);
2290             break;
2291         case WM_PASTE:
2292             webView->paste(0);
2293             break;
2294         case WM_CLEAR:
2295             webView->delete_(0);
2296             break;
2297         case WM_COMMAND:
2298             if (HIWORD(wParam))
2299                 handled = webView->execCommand(wParam, lParam);
2300             else // If the high word of wParam is 0, the message is from a menu
2301                 webView->performContextMenuAction(wParam, lParam, false);
2302             break;
2303         case WM_MENUCOMMAND:
2304             webView->performContextMenuAction(wParam, lParam, true);
2305             break;
2306         case WM_CONTEXTMENU:
2307             handled = webView->handleContextMenuEvent(wParam, lParam);
2308             break;
2309         case WM_INITMENUPOPUP:
2310             handled = webView->onInitMenuPopup(wParam, lParam);
2311             break;
2312         case WM_MEASUREITEM:
2313             handled = webView->onMeasureItem(wParam, lParam);
2314             break;
2315         case WM_DRAWITEM:
2316             handled = webView->onDrawItem(wParam, lParam);
2317             break;
2318         case WM_UNINITMENUPOPUP:
2319             handled = webView->onUninitMenuPopup(wParam, lParam);
2320             break;
2321         case WM_XP_THEMECHANGED:
2322             if (Frame* coreFrame = core(mainFrameImpl)) {
2323                 webView->deleteBackingStore();
2324                 coreFrame->page()->theme()->themeChanged();
2325                 ScrollbarTheme::theme()->themeChanged();
2326                 RECT windowRect;
2327                 ::GetClientRect(hWnd, &windowRect);
2328                 ::InvalidateRect(hWnd, &windowRect, false);
2329 #if USE(ACCELERATED_COMPOSITING)
2330                 if (webView->isAcceleratedCompositing())
2331                     webView->m_backingLayer->setNeedsDisplay();
2332 #endif
2333            }
2334             break;
2335         case WM_MOUSEACTIVATE:
2336             webView->setMouseActivated(true);
2337             handled = false;
2338             break;
2339         case WM_GETDLGCODE: {
2340             COMPtr<IWebUIDelegate> uiDelegate;
2341             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
2342             LONG_PTR dlgCode = 0;
2343             UINT keyCode = 0;
2344             if (lParam) {
2345                 LPMSG lpMsg = (LPMSG)lParam;
2346                 if (lpMsg->message == WM_KEYDOWN)
2347                     keyCode = (UINT) lpMsg->wParam;
2348             }
2349             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate
2350                 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate
2351                 && SUCCEEDED(uiDelegatePrivate->webViewGetDlgCode(webView, keyCode, &dlgCode)))
2352                 return dlgCode;
2353             handled = false;
2354             break;
2355         }
2356         case WM_GETOBJECT:
2357             handled = webView->onGetObject(wParam, lParam, lResult);
2358             break;
2359         case WM_IME_STARTCOMPOSITION:
2360             handled = webView->onIMEStartComposition();
2361             break;
2362         case WM_IME_REQUEST:
2363             lResult = webView->onIMERequest(wParam, lParam);
2364             break;
2365         case WM_IME_COMPOSITION:
2366             handled = webView->onIMEComposition(lParam);
2367             break;
2368         case WM_IME_ENDCOMPOSITION:
2369             handled = webView->onIMEEndComposition();
2370             break;
2371         case WM_IME_CHAR:
2372             handled = webView->onIMEChar(wParam, lParam);
2373             break;
2374         case WM_IME_NOTIFY:
2375             handled = webView->onIMENotify(wParam, lParam, &lResult);
2376             break;
2377         case WM_IME_SELECT:
2378             handled = webView->onIMESelect(wParam, lParam);
2379             break;
2380         case WM_IME_SETCONTEXT:
2381             handled = webView->onIMESetContext(wParam, lParam);
2382             break;
2383         case WM_TIMER:
2384             switch (wParam) {
2385                 case UpdateActiveStateTimer:
2386                     KillTimer(hWnd, UpdateActiveStateTimer);
2387                     webView->updateActiveState();
2388                     break;
2389                 case DeleteBackingStoreTimer:
2390                     webView->deleteBackingStore();
2391                     break;
2392             }
2393             break;
2394         case WM_SETCURSOR:
2395             handled = ::SetCursor(webView->m_lastSetCursor);
2396             break;
2397         case WM_VSCROLL:
2398             handled = webView->verticalScroll(wParam, lParam);
2399             break;
2400         case WM_HSCROLL:
2401             handled = webView->horizontalScroll(wParam, lParam);
2402             break;
2403         default:
2404             handled = false;
2405             break;
2406     }
2407
2408     if (!handled)
2409         lResult = DefWindowProc(hWnd, message, wParam, lParam);
2410     
2411     // Let the client know whether we consider this message handled.
2412     return (message == WM_KEYDOWN || message == WM_SYSKEYDOWN || message == WM_KEYUP || message == WM_SYSKEYUP) ? !handled : lResult;
2413 }
2414
2415 bool WebView::developerExtrasEnabled() const
2416 {
2417     if (m_preferences->developerExtrasDisabledByOverride())
2418         return false;
2419
2420 #ifdef NDEBUG
2421     BOOL enabled;
2422     return SUCCEEDED(m_preferences->developerExtrasEnabled(&enabled)) && enabled;
2423 #else
2424     return true;
2425 #endif
2426 }
2427
2428 static String webKitVersionString()
2429 {
2430     LPWSTR buildNumberStringPtr;
2431     if (!::LoadStringW(gInstance, BUILD_NUMBER, reinterpret_cast<LPWSTR>(&buildNumberStringPtr), 0) || !buildNumberStringPtr)
2432         return "534+";
2433
2434     return buildNumberStringPtr;
2435 }
2436
2437 const String& WebView::userAgentForKURL(const KURL&)
2438 {
2439     if (m_userAgentOverridden)
2440         return m_userAgentCustom;
2441
2442     if (!m_userAgentStandard.length())
2443         m_userAgentStandard = WebView::standardUserAgentWithApplicationName(m_applicationName);
2444     return m_userAgentStandard;
2445 }
2446
2447 // IUnknown -------------------------------------------------------------------
2448
2449 HRESULT STDMETHODCALLTYPE WebView::QueryInterface(REFIID riid, void** ppvObject)
2450 {
2451     *ppvObject = 0;
2452     if (IsEqualGUID(riid, CLSID_WebView))
2453         *ppvObject = this;
2454     else if (IsEqualGUID(riid, IID_IUnknown))
2455         *ppvObject = static_cast<IWebView*>(this);
2456     else if (IsEqualGUID(riid, IID_IWebView))
2457         *ppvObject = static_cast<IWebView*>(this);
2458     else if (IsEqualGUID(riid, IID_IWebViewPrivate))
2459         *ppvObject = static_cast<IWebViewPrivate*>(this);
2460     else if (IsEqualGUID(riid, IID_IWebIBActions))
2461         *ppvObject = static_cast<IWebIBActions*>(this);
2462     else if (IsEqualGUID(riid, IID_IWebViewCSS))
2463         *ppvObject = static_cast<IWebViewCSS*>(this);
2464     else if (IsEqualGUID(riid, IID_IWebViewEditing))
2465         *ppvObject = static_cast<IWebViewEditing*>(this);
2466     else if (IsEqualGUID(riid, IID_IWebViewUndoableEditing))
2467         *ppvObject = static_cast<IWebViewUndoableEditing*>(this);
2468     else if (IsEqualGUID(riid, IID_IWebViewEditingActions))
2469         *ppvObject = static_cast<IWebViewEditingActions*>(this);
2470     else if (IsEqualGUID(riid, IID_IWebNotificationObserver))
2471         *ppvObject = static_cast<IWebNotificationObserver*>(this);
2472     else if (IsEqualGUID(riid, IID_IDropTarget))
2473         *ppvObject = static_cast<IDropTarget*>(this);
2474     else
2475         return E_NOINTERFACE;
2476
2477     AddRef();
2478     return S_OK;
2479 }
2480
2481 ULONG STDMETHODCALLTYPE WebView::AddRef(void)
2482 {
2483     ASSERT(!m_deletionHasBegun);
2484     return ++m_refCount;
2485 }
2486
2487 ULONG STDMETHODCALLTYPE WebView::Release(void)
2488 {
2489     ASSERT(!m_deletionHasBegun);
2490
2491     if (m_refCount == 1) {
2492         // Call close() now so that clients don't have to. (It's harmless to call close() multiple
2493         // times.) We do this here instead of in our destructor because close() can cause AddRef()
2494         // and Release() to be called, and if that happened in our destructor we would be destroyed
2495         // more than once.
2496         close();
2497     }
2498
2499     ULONG newRef = --m_refCount;
2500     if (!newRef) {
2501 #if !ASSERT_DISABLED
2502         m_deletionHasBegun = true;
2503 #endif
2504         delete(this);
2505     }
2506
2507     return newRef;
2508 }
2509
2510 // IWebView --------------------------------------------------------------------
2511
2512 HRESULT STDMETHODCALLTYPE WebView::canShowMIMEType( 
2513     /* [in] */ BSTR mimeType,
2514     /* [retval][out] */ BOOL* canShow)
2515 {
2516     String mimeTypeStr(mimeType, SysStringLen(mimeType));
2517
2518     if (!canShow)
2519         return E_POINTER;
2520
2521     *canShow = MIMETypeRegistry::isSupportedImageMIMEType(mimeTypeStr) ||
2522         MIMETypeRegistry::isSupportedNonImageMIMEType(mimeTypeStr) ||
2523         (m_page && m_page->pluginData() && m_page->pluginData()->supportsMimeType(mimeTypeStr)) ||
2524         shouldUseEmbeddedView(mimeTypeStr);
2525     
2526     return S_OK;
2527 }
2528
2529 HRESULT STDMETHODCALLTYPE WebView::canShowMIMETypeAsHTML( 
2530     /* [in] */ BSTR /*mimeType*/,
2531     /* [retval][out] */ BOOL* canShow)
2532 {
2533     // FIXME
2534     *canShow = TRUE;
2535     return S_OK;
2536 }
2537
2538 HRESULT STDMETHODCALLTYPE WebView::MIMETypesShownAsHTML( 
2539     /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
2540 {
2541     ASSERT_NOT_REACHED();
2542     return E_NOTIMPL;
2543 }
2544
2545 HRESULT STDMETHODCALLTYPE WebView::setMIMETypesShownAsHTML( 
2546         /* [size_is][in] */ BSTR* /*mimeTypes*/,
2547         /* [in] */ int /*cMimeTypes*/)
2548 {
2549     ASSERT_NOT_REACHED();
2550     return E_NOTIMPL;
2551 }
2552
2553 HRESULT STDMETHODCALLTYPE WebView::URLFromPasteboard( 
2554     /* [in] */ IDataObject* /*pasteboard*/,
2555     /* [retval][out] */ BSTR* /*url*/)
2556 {
2557     ASSERT_NOT_REACHED();
2558     return E_NOTIMPL;
2559 }
2560
2561 HRESULT STDMETHODCALLTYPE WebView::URLTitleFromPasteboard( 
2562     /* [in] */ IDataObject* /*pasteboard*/,
2563     /* [retval][out] */ BSTR* /*urlTitle*/)
2564 {
2565     ASSERT_NOT_REACHED();
2566     return E_NOTIMPL;
2567 }
2568
2569 static void WebKitSetApplicationCachePathIfNecessary()
2570 {
2571     static bool initialized = false;
2572     if (initialized)
2573         return;
2574
2575     String path = localUserSpecificStorageDirectory();
2576     if (!path.isNull())
2577         cacheStorage().setCacheDirectory(path);
2578
2579     initialized = true;
2580 }
2581
2582 bool WebView::shouldInitializeTrackPointHack()
2583 {
2584     static bool shouldCreateScrollbars;
2585     static bool hasRunTrackPointCheck;
2586
2587     if (hasRunTrackPointCheck)
2588         return shouldCreateScrollbars;
2589
2590     hasRunTrackPointCheck = true;
2591     const WCHAR trackPointKeys[][50] = { L"Software\\Lenovo\\TrackPoint",
2592         L"Software\\Lenovo\\UltraNav",
2593         L"Software\\Alps\\Apoint\\TrackPoint",
2594         L"Software\\Synaptics\\SynTPEnh\\UltraNavUSB",
2595         L"Software\\Synaptics\\SynTPEnh\\UltraNavPS2" };
2596
2597     for (int i = 0; i < 5; ++i) {
2598         HKEY trackPointKey;
2599         int readKeyResult = ::RegOpenKeyExW(HKEY_CURRENT_USER, trackPointKeys[i], 0, KEY_READ, &trackPointKey);
2600         ::RegCloseKey(trackPointKey);
2601         if (readKeyResult == ERROR_SUCCESS) {
2602             shouldCreateScrollbars = true;
2603             return shouldCreateScrollbars;
2604         }
2605     }
2606
2607     return shouldCreateScrollbars;
2608 }
2609     
2610 HRESULT STDMETHODCALLTYPE WebView::initWithFrame( 
2611     /* [in] */ RECT frame,
2612     /* [in] */ BSTR frameName,
2613     /* [in] */ BSTR groupName)
2614 {
2615     HRESULT hr = S_OK;
2616
2617     if (m_viewWindow)
2618         return E_FAIL;
2619
2620     registerWebViewWindowClass();
2621
2622     m_viewWindow = CreateWindowEx(0, kWebViewWindowClassName, 0, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
2623         frame.left, frame.top, frame.right - frame.left, frame.bottom - frame.top, m_hostWindow ? m_hostWindow : HWND_MESSAGE, 0, gInstance, 0);
2624     ASSERT(::IsWindow(m_viewWindow));
2625
2626     if (shouldInitializeTrackPointHack()) {
2627         // If we detected a registry key belonging to a TrackPoint driver, then create fake trackpoint
2628         // scrollbars, so the WebView will receive WM_VSCROLL and WM_HSCROLL messages. We create one
2629         // vertical scrollbar and one horizontal to allow for receiving both types of messages.
2630         ::CreateWindowW(L"SCROLLBAR", L"FAKETRACKPOINTHSCROLLBAR", WS_CHILD | WS_VISIBLE | SBS_HORZ, 0, 0, 0, 0, m_viewWindow, 0, gInstance, 0);
2631         ::CreateWindowW(L"SCROLLBAR", L"FAKETRACKPOINTVSCROLLBAR", WS_CHILD | WS_VISIBLE | SBS_VERT, 0, 0, 0, 0, m_viewWindow, 0, gInstance, 0);
2632     }
2633
2634     hr = registerDragDrop();
2635     if (FAILED(hr))
2636         return hr;
2637
2638     WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences();
2639     sharedPreferences->willAddToWebView();
2640     m_preferences = sharedPreferences;
2641
2642     static bool didOneTimeInitialization;
2643     if (!didOneTimeInitialization) {
2644 #if !LOG_DISABLED
2645         initializeLoggingChannelsIfNecessary();
2646 #endif // !LOG_DISABLED
2647 #if ENABLE(SQL_DATABASE)
2648         WebKitInitializeWebDatabasesIfNecessary();
2649 #endif
2650         WebKitSetApplicationCachePathIfNecessary();
2651         WebPlatformStrategies::initialize();
2652         Settings::setDefaultMinDOMTimerInterval(0.004);
2653
2654         didOneTimeInitialization = true;
2655      }
2656
2657 #if USE(SAFARI_THEME)
2658     BOOL shouldPaintNativeControls;
2659     if (SUCCEEDED(m_preferences->shouldPaintNativeControls(&shouldPaintNativeControls)))
2660         Settings::setShouldPaintNativeControls(shouldPaintNativeControls);
2661 #endif
2662
2663     BOOL useHighResolutionTimer;
2664     if (SUCCEEDED(m_preferences->shouldUseHighResolutionTimers(&useHighResolutionTimer)))
2665         Settings::setShouldUseHighResolutionTimers(useHighResolutionTimer);
2666
2667 #if ENABLE(INSPECTOR)
2668     m_inspectorClient = new WebInspectorClient(this);
2669 #endif // ENABLE(INSPECTOR)
2670
2671     Page::PageClients pageClients;
2672     pageClients.chromeClient = new WebChromeClient(this);
2673     pageClients.contextMenuClient = new WebContextMenuClient(this);
2674     pageClients.editorClient = new WebEditorClient(this);
2675     pageClients.dragClient = new WebDragClient(this);
2676 #if ENABLE(INSPECTOR)
2677     pageClients.inspectorClient = m_inspectorClient;
2678 #endif // ENABLE(INSPECTOR)
2679
2680     m_page = new Page(pageClients);
2681     provideGeolocationTo(m_page, new WebGeolocationClient(this));
2682
2683     BSTR localStoragePath;
2684     if (SUCCEEDED(m_preferences->localStorageDatabasePath(&localStoragePath))) {
2685         m_page->settings()->setLocalStorageDatabasePath(String(localStoragePath, SysStringLen(localStoragePath)));
2686         SysFreeString(localStoragePath);
2687     }
2688
2689     if (m_uiDelegate) {
2690         BSTR path;
2691         if (SUCCEEDED(m_uiDelegate->ftpDirectoryTemplatePath(this, &path))) {
2692             m_page->settings()->setFTPDirectoryTemplatePath(String(path, SysStringLen(path)));
2693             SysFreeString(path);
2694         }
2695     }
2696
2697     WebFrame* webFrame = WebFrame::createInstance();
2698     RefPtr<Frame> coreFrame = webFrame->init(this, m_page, 0);
2699     m_mainFrame = webFrame;
2700     webFrame->Release(); // The WebFrame is owned by the Frame, so release our reference to it.
2701
2702     coreFrame->tree()->setName(String(frameName, SysStringLen(frameName)));
2703     coreFrame->init();
2704     setGroupName(groupName);
2705
2706     addToAllWebViewsSet();
2707
2708     #pragma warning(suppress: 4244)
2709     SetWindowLongPtr(m_viewWindow, 0, (LONG_PTR)this);
2710     ShowWindow(m_viewWindow, SW_SHOW);
2711
2712     initializeToolTipWindow();
2713     windowAncestryDidChange();
2714
2715     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
2716     notifyCenter->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
2717     m_preferences->postPreferencesChangesNotification();
2718
2719     setSmartInsertDeleteEnabled(TRUE);
2720     return hr;
2721 }
2722
2723 static bool initCommonControls()
2724 {
2725     static bool haveInitialized = false;
2726     if (haveInitialized)
2727         return true;
2728
2729     INITCOMMONCONTROLSEX init;
2730     init.dwSize = sizeof(init);
2731     init.dwICC = ICC_TREEVIEW_CLASSES;
2732     haveInitialized = !!::InitCommonControlsEx(&init);
2733     return haveInitialized;
2734 }
2735
2736 void WebView::initializeToolTipWindow()
2737 {
2738     if (!initCommonControls())
2739         return;
2740
2741     m_toolTipHwnd = CreateWindowEx(WS_EX_TRANSPARENT, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
2742                                    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2743                                    m_viewWindow, 0, 0, 0);
2744     if (!m_toolTipHwnd)
2745         return;
2746
2747     TOOLINFO info = {0};
2748     info.cbSize = sizeof(info);
2749     info.uFlags = TTF_IDISHWND | TTF_SUBCLASS ;
2750     info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
2751
2752     ::SendMessage(m_toolTipHwnd, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info));
2753     ::SendMessage(m_toolTipHwnd, TTM_SETMAXTIPWIDTH, 0, maxToolTipWidth);
2754
2755     ::SetWindowPos(m_toolTipHwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
2756 }
2757
2758 void WebView::setToolTip(const String& toolTip)
2759 {
2760     if (!m_toolTipHwnd)
2761         return;
2762
2763     if (toolTip == m_toolTip)
2764         return;
2765
2766     m_toolTip = toolTip;
2767
2768     if (!m_toolTip.isEmpty()) {
2769         TOOLINFO info = {0};
2770         info.cbSize = sizeof(info);
2771         info.uFlags = TTF_IDISHWND;
2772         info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
2773         info.lpszText = const_cast<UChar*>(m_toolTip.charactersWithNullTermination());
2774         ::SendMessage(m_toolTipHwnd, TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info));
2775     }
2776
2777     ::SendMessage(m_toolTipHwnd, TTM_ACTIVATE, !m_toolTip.isEmpty(), 0);
2778 }
2779
2780 HRESULT WebView::notifyDidAddIcon(IWebNotification* notification)
2781 {
2782     COMPtr<IPropertyBag> propertyBag;
2783     HRESULT hr = notification->userInfo(&propertyBag);
2784     if (FAILED(hr))
2785         return hr;
2786     if (!propertyBag)
2787         return E_FAIL;
2788
2789     COMPtr<CFDictionaryPropertyBag> dictionaryPropertyBag;
2790     hr = propertyBag->QueryInterface(&dictionaryPropertyBag);
2791     if (FAILED(hr))
2792         return hr;
2793
2794     CFDictionaryRef dictionary = dictionaryPropertyBag->dictionary();
2795     if (!dictionary)
2796         return E_FAIL;
2797
2798     CFTypeRef value = CFDictionaryGetValue(dictionary, WebIconDatabase::iconDatabaseNotificationUserInfoURLKey());
2799     if (!value)
2800         return E_FAIL;
2801     if (CFGetTypeID(value) != CFStringGetTypeID())
2802         return E_FAIL;
2803
2804     String mainFrameURL;
2805     if (m_mainFrame)
2806         mainFrameURL = m_mainFrame->url().string();
2807
2808     if (!mainFrameURL.isEmpty() && mainFrameURL == String((CFStringRef)value))
2809         dispatchDidReceiveIconFromWebFrame(m_mainFrame);
2810
2811     return hr;
2812 }
2813
2814 void WebView::registerForIconNotification(bool listen)
2815 {
2816     IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
2817     if (listen)
2818         nc->addObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
2819     else
2820         nc->removeObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
2821 }
2822
2823 void WebView::dispatchDidReceiveIconFromWebFrame(WebFrame* frame)
2824 {
2825     registerForIconNotification(false);
2826
2827     if (m_frameLoadDelegate)
2828         // FIXME: <rdar://problem/5491010> - Pass in the right HBITMAP. 
2829         m_frameLoadDelegate->didReceiveIcon(this, 0, frame);
2830 }
2831
2832 HRESULT STDMETHODCALLTYPE WebView::setUIDelegate( 
2833     /* [in] */ IWebUIDelegate* d)
2834 {
2835     m_uiDelegate = d;
2836
2837     if (m_uiDelegatePrivate)
2838         m_uiDelegatePrivate = 0;
2839
2840     if (d) {
2841         if (FAILED(d->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&m_uiDelegatePrivate)))
2842             m_uiDelegatePrivate = 0;
2843     }
2844
2845     return S_OK;
2846 }
2847
2848 HRESULT STDMETHODCALLTYPE WebView::uiDelegate( 
2849     /* [out][retval] */ IWebUIDelegate** d)
2850 {
2851     if (!m_uiDelegate)
2852         return E_FAIL;
2853
2854     return m_uiDelegate.copyRefTo(d);
2855 }
2856
2857 HRESULT STDMETHODCALLTYPE WebView::setResourceLoadDelegate( 
2858     /* [in] */ IWebResourceLoadDelegate* d)
2859 {
2860     m_resourceLoadDelegate = d;
2861     return S_OK;
2862 }
2863
2864 HRESULT STDMETHODCALLTYPE WebView::resourceLoadDelegate( 
2865     /* [out][retval] */ IWebResourceLoadDelegate** d)
2866 {
2867     if (!m_resourceLoadDelegate)
2868         return E_FAIL;
2869
2870     return m_resourceLoadDelegate.copyRefTo(d);
2871 }
2872
2873 HRESULT STDMETHODCALLTYPE WebView::setDownloadDelegate( 
2874     /* [in] */ IWebDownloadDelegate* d)
2875 {
2876     m_downloadDelegate = d;
2877     return S_OK;
2878 }
2879
2880 HRESULT STDMETHODCALLTYPE WebView::downloadDelegate( 
2881     /* [out][retval] */ IWebDownloadDelegate** d)
2882 {
2883     if (!m_downloadDelegate)
2884         return E_FAIL;
2885
2886     return m_downloadDelegate.copyRefTo(d);
2887 }
2888
2889 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegate( 
2890     /* [in] */ IWebFrameLoadDelegate* d)
2891 {
2892     m_frameLoadDelegate = d;
2893     return S_OK;
2894 }
2895
2896 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegate( 
2897     /* [out][retval] */ IWebFrameLoadDelegate** d)
2898 {
2899     if (!m_frameLoadDelegate)
2900         return E_FAIL;
2901
2902     return m_frameLoadDelegate.copyRefTo(d);
2903 }
2904
2905 HRESULT STDMETHODCALLTYPE WebView::setPolicyDelegate( 
2906     /* [in] */ IWebPolicyDelegate* d)
2907 {
2908     m_policyDelegate = d;
2909     return S_OK;
2910 }
2911
2912 HRESULT STDMETHODCALLTYPE WebView::policyDelegate( 
2913     /* [out][retval] */ IWebPolicyDelegate** d)
2914 {
2915     if (!m_policyDelegate)
2916         return E_FAIL;
2917     return m_policyDelegate.copyRefTo(d);
2918 }
2919
2920 HRESULT STDMETHODCALLTYPE WebView::mainFrame( 
2921     /* [out][retval] */ IWebFrame** frame)
2922 {
2923     if (!frame) {
2924         ASSERT_NOT_REACHED();
2925         return E_POINTER;
2926     }
2927
2928     *frame = m_mainFrame;
2929     if (!m_mainFrame)
2930         return E_FAIL;
2931
2932     m_mainFrame->AddRef();
2933     return S_OK;
2934 }
2935
2936 HRESULT STDMETHODCALLTYPE WebView::focusedFrame( 
2937     /* [out][retval] */ IWebFrame** frame)
2938 {
2939     if (!frame) {
2940         ASSERT_NOT_REACHED();
2941         return E_POINTER;
2942     }
2943
2944     *frame = 0;
2945     Frame* f = m_page->focusController()->focusedFrame();
2946     if (!f)
2947         return E_FAIL;
2948
2949     WebFrame* webFrame = kit(f);
2950     if (!webFrame)
2951         return E_FAIL;
2952
2953     return webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
2954 }
2955
2956 HRESULT STDMETHODCALLTYPE WebView::backForwardList( 
2957     /* [out][retval] */ IWebBackForwardList** list)
2958 {
2959     if (!m_useBackForwardList)
2960         return E_FAIL;
2961  
2962     *list = WebBackForwardList::createInstance(static_cast<WebCore::BackForwardListImpl*>(m_page->backForwardList()));
2963
2964     return S_OK;
2965 }
2966
2967 HRESULT STDMETHODCALLTYPE WebView::setMaintainsBackForwardList( 
2968     /* [in] */ BOOL flag)
2969 {
2970     m_useBackForwardList = !!flag;
2971     return S_OK;
2972 }
2973
2974 HRESULT STDMETHODCALLTYPE WebView::goBack( 
2975     /* [retval][out] */ BOOL* succeeded)
2976 {
2977     *succeeded = m_page->goBack();
2978     return S_OK;
2979 }
2980
2981 HRESULT STDMETHODCALLTYPE WebView::goForward( 
2982     /* [retval][out] */ BOOL* succeeded)
2983 {
2984     *succeeded = m_page->goForward();
2985     return S_OK;
2986 }
2987
2988 HRESULT STDMETHODCALLTYPE WebView::goToBackForwardItem( 
2989     /* [in] */ IWebHistoryItem* item,
2990     /* [retval][out] */ BOOL* succeeded)
2991 {
2992     *succeeded = FALSE;
2993
2994     COMPtr<WebHistoryItem> webHistoryItem;
2995     HRESULT hr = item->QueryInterface(&webHistoryItem);
2996     if (FAILED(hr))
2997         return hr;
2998
2999     m_page->goToItem(webHistoryItem->historyItem(), FrameLoadTypeIndexedBackForward);
3000     *succeeded = TRUE;
3001
3002     return S_OK;
3003 }
3004
3005 HRESULT STDMETHODCALLTYPE WebView::setTextSizeMultiplier( 
3006     /* [in] */ float multiplier)
3007 {
3008     if (!m_mainFrame)
3009         return E_FAIL;
3010     setZoomMultiplier(multiplier, true);
3011     return S_OK;
3012 }
3013
3014 HRESULT STDMETHODCALLTYPE WebView::setPageSizeMultiplier( 
3015     /* [in] */ float multiplier)
3016 {
3017     if (!m_mainFrame)
3018         return E_FAIL;
3019     setZoomMultiplier(multiplier, false);
3020     return S_OK;
3021 }
3022
3023 void WebView::setZoomMultiplier(float multiplier, bool isTextOnly)
3024 {
3025     m_zoomMultiplier = multiplier;
3026     m_zoomsTextOnly = isTextOnly;
3027
3028     if (Frame* coreFrame = core(m_mainFrame)) {
3029         if (m_zoomsTextOnly)
3030             coreFrame->setPageAndTextZoomFactors(1, multiplier);
3031         else
3032             coreFrame->setPageAndTextZoomFactors(multiplier, 1);
3033     }
3034 }
3035
3036 HRESULT STDMETHODCALLTYPE WebView::textSizeMultiplier( 
3037     /* [retval][out] */ float* multiplier)
3038 {
3039     *multiplier = zoomMultiplier(true);
3040     return S_OK;
3041 }
3042
3043 HRESULT STDMETHODCALLTYPE WebView::pageSizeMultiplier( 
3044     /* [retval][out] */ float* multiplier)
3045 {
3046     *multiplier = zoomMultiplier(false);
3047     return S_OK;
3048 }
3049
3050 float WebView::zoomMultiplier(bool isTextOnly)
3051 {
3052     if (isTextOnly != m_zoomsTextOnly)
3053         return 1.0f;
3054     return m_zoomMultiplier;
3055 }
3056
3057 HRESULT STDMETHODCALLTYPE WebView::setApplicationNameForUserAgent( 
3058     /* [in] */ BSTR applicationName)
3059 {
3060     m_applicationName = String(applicationName, SysStringLen(applicationName));
3061     m_userAgentStandard = String();
3062     return S_OK;
3063 }
3064
3065 HRESULT STDMETHODCALLTYPE WebView::applicationNameForUserAgent( 
3066     /* [retval][out] */ BSTR* applicationName)
3067 {
3068     *applicationName = SysAllocStringLen(m_applicationName.characters(), m_applicationName.length());
3069     if (!*applicationName && m_applicationName.length())
3070         return E_OUTOFMEMORY;
3071     return S_OK;
3072 }
3073
3074 HRESULT STDMETHODCALLTYPE WebView::setCustomUserAgent( 
3075     /* [in] */ BSTR userAgentString)
3076 {
3077     m_userAgentOverridden = userAgentString;
3078     m_userAgentCustom = String(userAgentString, SysStringLen(userAgentString));
3079     return S_OK;
3080 }
3081
3082 HRESULT STDMETHODCALLTYPE WebView::customUserAgent( 
3083     /* [retval][out] */ BSTR* userAgentString)
3084 {
3085     *userAgentString = 0;
3086     if (!m_userAgentOverridden)
3087         return S_OK;
3088     *userAgentString = SysAllocStringLen(m_userAgentCustom.characters(), m_userAgentCustom.length());
3089     if (!*userAgentString && m_userAgentCustom.length())
3090         return E_OUTOFMEMORY;
3091     return S_OK;
3092 }
3093
3094 HRESULT STDMETHODCALLTYPE WebView::userAgentForURL( 
3095     /* [in] */ BSTR url,
3096     /* [retval][out] */ BSTR* userAgent)
3097 {
3098     String userAgentString = userAgentForKURL(MarshallingHelpers::BSTRToKURL(url));
3099     *userAgent = SysAllocStringLen(userAgentString.characters(), userAgentString.length());
3100     if (!*userAgent && userAgentString.length())
3101         return E_OUTOFMEMORY;
3102     return S_OK;
3103 }
3104
3105 HRESULT STDMETHODCALLTYPE WebView::supportsTextEncoding( 
3106     /* [retval][out] */ BOOL* supports)
3107 {
3108     *supports = TRUE;
3109     return S_OK;
3110 }
3111
3112 HRESULT STDMETHODCALLTYPE WebView::setCustomTextEncodingName( 
3113     /* [in] */ BSTR encodingName)
3114 {
3115     if (!m_mainFrame)
3116         return E_FAIL;
3117
3118     HRESULT hr;
3119     BSTR oldEncoding;
3120     hr = customTextEncodingName(&oldEncoding);
3121     if (FAILED(hr))
3122         return hr;
3123
3124     if (oldEncoding != encodingName && (!oldEncoding || !encodingName || wcscmp(oldEncoding, encodingName))) {
3125         if (Frame* coreFrame = core(m_mainFrame))
3126             coreFrame->loader()->reloadWithOverrideEncoding(String(encodingName, SysStringLen(encodingName)));
3127     }
3128
3129     return S_OK;
3130 }
3131
3132 HRESULT STDMETHODCALLTYPE WebView::customTextEncodingName( 
3133     /* [retval][out] */ BSTR* encodingName)
3134 {
3135     HRESULT hr = S_OK;
3136     COMPtr<IWebDataSource> dataSource;
3137     COMPtr<WebDataSource> dataSourceImpl;
3138     *encodingName = 0;
3139
3140     if (!m_mainFrame)
3141         return E_FAIL;
3142
3143     if (FAILED(m_mainFrame->provisionalDataSource(&dataSource)) || !dataSource) {
3144         hr = m_mainFrame->dataSource(&dataSource);
3145         if (FAILED(hr) || !dataSource)
3146             return hr;
3147     }
3148
3149     hr = dataSource->QueryInterface(IID_WebDataSource, (void**)&dataSourceImpl);
3150     if (FAILED(hr))
3151         return hr;
3152
3153     BString str = dataSourceImpl->documentLoader()->overrideEncoding();
3154     if (FAILED(hr))
3155         return hr;
3156
3157     if (!*encodingName)
3158         *encodingName = SysAllocStringLen(m_overrideEncoding.characters(), m_overrideEncoding.length());
3159
3160     if (!*encodingName && m_overrideEncoding.length())
3161         return E_OUTOFMEMORY;
3162
3163     return S_OK;
3164 }
3165
3166 HRESULT STDMETHODCALLTYPE WebView::setMediaStyle( 
3167     /* [in] */ BSTR /*media*/)
3168 {
3169     ASSERT_NOT_REACHED();
3170     return E_NOTIMPL;
3171 }
3172
3173 HRESULT STDMETHODCALLTYPE WebView::mediaStyle( 
3174     /* [retval][out] */ BSTR* /*media*/)
3175 {
3176     ASSERT_NOT_REACHED();
3177     return E_NOTIMPL;
3178 }
3179
3180 HRESULT STDMETHODCALLTYPE WebView::stringByEvaluatingJavaScriptFromString( 
3181     /* [in] */ BSTR script, // assumes input does not have "JavaScript" at the begining.
3182     /* [retval][out] */ BSTR* result)
3183 {
3184     if (!result) {
3185         ASSERT_NOT_REACHED();
3186         return E_POINTER;
3187     }
3188
3189     *result = 0;
3190
3191     Frame* coreFrame = core(m_mainFrame);
3192     if (!coreFrame)
3193         return E_FAIL;
3194
3195     JSC::JSValue scriptExecutionResult = coreFrame->script()->executeScript(WTF::String(script), true).jsValue();
3196     if (!scriptExecutionResult)
3197         return E_FAIL;
3198     else if (scriptExecutionResult.isString()) {
3199         JSC::ExecState* exec = coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec();
3200         JSC::JSLockHolder lock(exec);
3201         *result = BString(ustringToString(scriptExecutionResult.getString(exec)));
3202     }
3203
3204     return S_OK;
3205 }
3206
3207 HRESULT STDMETHODCALLTYPE WebView::windowScriptObject( 
3208     /* [retval][out] */ IWebScriptObject** /*webScriptObject*/)
3209 {
3210     ASSERT_NOT_REACHED();
3211     return E_NOTIMPL;
3212 }
3213
3214 HRESULT STDMETHODCALLTYPE WebView::setPreferences( 
3215     /* [in] */ IWebPreferences* prefs)
3216 {
3217     if (!prefs)
3218         prefs = WebPreferences::sharedStandardPreferences();
3219
3220     if (m_preferences == prefs)
3221         return S_OK;
3222
3223     COMPtr<WebPreferences> webPrefs(Query, prefs);
3224     if (!webPrefs)
3225         return E_NOINTERFACE;
3226     webPrefs->willAddToWebView();
3227
3228     COMPtr<WebPreferences> oldPrefs = m_preferences;
3229
3230     IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
3231     nc->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3232
3233     BSTR identifier = 0;
3234     oldPrefs->identifier(&identifier);
3235     oldPrefs->didRemoveFromWebView();
3236     oldPrefs = 0; // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
3237
3238     m_preferences = webPrefs;
3239
3240     if (identifier) {
3241         WebPreferences::removeReferenceForIdentifier(identifier);
3242         SysFreeString(identifier);
3243     }
3244
3245     nc->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3246
3247     m_preferences->postPreferencesChangesNotification();
3248
3249     return S_OK;
3250 }
3251
3252 HRESULT STDMETHODCALLTYPE WebView::preferences( 
3253     /* [retval][out] */ IWebPreferences** prefs)
3254 {
3255     if (!prefs)
3256         return E_POINTER;
3257     *prefs = m_preferences.get();
3258     if (m_preferences)
3259         m_preferences->AddRef();
3260     return S_OK;
3261 }
3262
3263 HRESULT STDMETHODCALLTYPE WebView::setPreferencesIdentifier( 
3264     /* [in] */ BSTR /*anIdentifier*/)
3265 {
3266     ASSERT_NOT_REACHED();
3267     return E_NOTIMPL;
3268 }
3269
3270 HRESULT STDMETHODCALLTYPE WebView::preferencesIdentifier( 
3271     /* [retval][out] */ BSTR* /*anIdentifier*/)
3272 {
3273     ASSERT_NOT_REACHED();
3274     return E_NOTIMPL;
3275 }
3276
3277 static void systemParameterChanged(WPARAM parameter)
3278 {
3279 #if USE(CG)
3280     if (parameter == SPI_SETFONTSMOOTHING || parameter == SPI_SETFONTSMOOTHINGTYPE || parameter == SPI_SETFONTSMOOTHINGCONTRAST || parameter == SPI_SETFONTSMOOTHINGORIENTATION)
3281         wkSystemFontSmoothingChanged();
3282 #endif
3283 }
3284
3285 void WebView::windowReceivedMessage(HWND, UINT message, WPARAM wParam, LPARAM)
3286 {
3287     switch (message) {
3288     case WM_NCACTIVATE:
3289         updateActiveStateSoon();
3290         if (!wParam)
3291             deleteBackingStoreSoon();
3292         break;
3293     case WM_SETTINGCHANGE:
3294         systemParameterChanged(wParam);
3295         break;
3296     }
3297 }
3298
3299 void WebView::updateActiveStateSoon() const
3300 {
3301     // This function is called while processing the WM_NCACTIVATE message.
3302     // While processing WM_NCACTIVATE when we are being deactivated, GetActiveWindow() will
3303     // still return our window. If we were to call updateActiveState() in that case, we would
3304     // wrongly think that we are still the active window. To work around this, we update our
3305     // active state after a 0-delay timer fires, at which point GetActiveWindow() will return
3306     // the newly-activated window.
3307
3308     SetTimer(m_viewWindow, UpdateActiveStateTimer, 0, 0);
3309 }
3310
3311 void WebView::deleteBackingStoreSoon()
3312 {
3313     if (pendingDeleteBackingStoreSet.size() > 2) {
3314         Vector<WebView*> views;
3315         HashSet<WebView*>::iterator end = pendingDeleteBackingStoreSet.end();
3316         for (HashSet<WebView*>::iterator it = pendingDeleteBackingStoreSet.begin(); it != end; ++it)
3317             views.append(*it);
3318         for (int i = 0; i < views.size(); ++i)
3319             views[i]->deleteBackingStore();
3320         ASSERT(pendingDeleteBackingStoreSet.isEmpty());
3321     }
3322
3323     pendingDeleteBackingStoreSet.add(this);
3324     m_deleteBackingStoreTimerActive = true;
3325     SetTimer(m_viewWindow, DeleteBackingStoreTimer, delayBeforeDeletingBackingStoreMsec, 0);
3326 }
3327
3328 void WebView::cancelDeleteBackingStoreSoon()
3329 {
3330     if (!m_deleteBackingStoreTimerActive)
3331         return;
3332     pendingDeleteBackingStoreSet.remove(this);
3333     m_deleteBackingStoreTimerActive = false;
3334     KillTimer(m_viewWindow, DeleteBackingStoreTimer);
3335 }
3336
3337 HRESULT STDMETHODCALLTYPE WebView::setHostWindow( 
3338     /* [in] */ OLE_HANDLE oleWindow)
3339 {
3340     HWND window = (HWND)(ULONG64)oleWindow;
3341     if (m_viewWindow) {
3342         if (window)
3343             SetParent(m_viewWindow, window);
3344         else if (!isBeingDestroyed()) {
3345             // Turn the WebView into a message-only window so it will no longer be a child of the
3346             // old host window and will be hidden from screen. We only do this when
3347             // isBeingDestroyed() is false because doing this while handling WM_DESTROY can leave
3348             // m_viewWindow in a weird state (see <http://webkit.org/b/29337>).
3349             SetParent(m_viewWindow, HWND_MESSAGE);
3350         }
3351     }
3352
3353     m_hostWindow = window;
3354
3355     windowAncestryDidChange();
3356
3357     return S_OK;
3358 }
3359
3360 HRESULT STDMETHODCALLTYPE WebView::hostWindow( 
3361     /* [retval][out] */ OLE_HANDLE* window)
3362 {
3363     *window = (OLE_HANDLE)(ULONG64)m_hostWindow;
3364     return S_OK;
3365 }
3366
3367
3368 static Frame *incrementFrame(Frame *curr, bool forward, bool wrapFlag)
3369 {
3370     return forward
3371         ? curr->tree()->traverseNextWithWrap(wrapFlag)
3372         : curr->tree()->traversePreviousWithWrap(wrapFlag);
3373 }
3374
3375 HRESULT STDMETHODCALLTYPE WebView::searchFor( 
3376     /* [in] */ BSTR str,
3377     /* [in] */ BOOL forward,
3378     /* [in] */ BOOL caseFlag,
3379     /* [in] */ BOOL wrapFlag,
3380     /* [retval][out] */ BOOL* found)
3381 {
3382     if (!found)
3383         return E_INVALIDARG;
3384     
3385     if (!m_page || !m_page->mainFrame())
3386         return E_UNEXPECTED;
3387
3388     if (!str || !SysStringLen(str))
3389         return E_INVALIDARG;
3390
3391     *found = m_page->findString(String(str, SysStringLen(str)), caseFlag ? TextCaseSensitive : TextCaseInsensitive, forward ? FindDirectionForward : FindDirectionBackward, wrapFlag);
3392     return S_OK;
3393 }
3394
3395 bool WebView::active()
3396 {
3397     HWND activeWindow = GetActiveWindow();
3398     if (usesLayeredWindow() && activeWindow == m_viewWindow)
3399         return true;
3400
3401     return (activeWindow && m_topLevelParent == findTopLevelParent(activeWindow));
3402 }
3403
3404 void WebView::updateActiveState()
3405 {
3406     m_page->focusController()->setActive(active());
3407 }
3408
3409 HRESULT STDMETHODCALLTYPE WebView::updateFocusedAndActiveState()
3410 {
3411     updateActiveState();
3412
3413     bool active = m_page->focusController()->isActive();
3414     Frame* mainFrame = m_page->mainFrame();
3415     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
3416     mainFrame->selection()->setFocused(active && mainFrame == focusedFrame);
3417
3418     return S_OK;
3419 }
3420
3421 HRESULT STDMETHODCALLTYPE WebView::executeCoreCommandByName(BSTR bName, BSTR bValue)
3422 {
3423     String name(bName, SysStringLen(bName));
3424     String value(bValue, SysStringLen(bValue));
3425
3426     m_page->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value);
3427
3428     return S_OK;
3429 }
3430
3431 HRESULT STDMETHODCALLTYPE WebView::clearMainFrameName()
3432 {
3433     m_page->mainFrame()->tree()->clearName();
3434
3435     return S_OK;
3436 }
3437
3438 HRESULT STDMETHODCALLTYPE WebView::markAllMatchesForText(
3439     BSTR str, BOOL caseSensitive, BOOL highlight, UINT limit, UINT* matches)
3440 {
3441     if (!matches)
3442         return E_INVALIDARG;
3443
3444     if (!m_page || !m_page->mainFrame())
3445         return E_UNEXPECTED;
3446
3447     if (!str || !SysStringLen(str))
3448         return E_INVALIDARG;
3449
3450     *matches = m_page->markAllMatchesForText(String(str, SysStringLen(str)), caseSensitive ? TextCaseSensitive : TextCaseInsensitive, highlight, limit);
3451     return S_OK;
3452 }
3453
3454 HRESULT STDMETHODCALLTYPE WebView::unmarkAllTextMatches()
3455 {
3456     if (!m_page || !m_page->mainFrame())
3457         return E_UNEXPECTED;
3458
3459     m_page->unmarkAllTextMatches();
3460     return S_OK;
3461 }
3462
3463 HRESULT STDMETHODCALLTYPE WebView::rectsForTextMatches(
3464     IEnumTextMatches** pmatches)
3465 {
3466     Vector<IntRect> allRects;
3467     WebCore::Frame* frame = m_page->mainFrame();
3468     do {
3469         if (Document* document = frame->document()) {
3470             IntRect visibleRect = frame->view()->visibleContentRect();
3471             Vector<IntRect> frameRects = document->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
3472             IntPoint frameOffset(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height());
3473             frameOffset = frame->view()->convertToContainingWindow(frameOffset);
3474
3475             Vector<IntRect>::iterator end = frameRects.end();
3476             for (Vector<IntRect>::iterator it = frameRects.begin(); it < end; it++) {
3477                 it->intersect(visibleRect);
3478                 it->move(frameOffset.x(), frameOffset.y());
3479                 allRects.append(*it);
3480             }
3481         }
3482         frame = incrementFrame(frame, true, false);
3483     } while (frame);
3484
3485     return createMatchEnumerator(&allRects, pmatches);
3486 }
3487
3488 HRESULT STDMETHODCALLTYPE WebView::generateSelectionImage(BOOL forceWhiteText, OLE_HANDLE* hBitmap)
3489 {
3490     *hBitmap = 0;
3491
3492     WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame();
3493
3494     if (frame) {
3495         HBITMAP bitmap = imageFromSelection(frame, forceWhiteText ? TRUE : FALSE);
3496         *hBitmap = (OLE_HANDLE)(ULONG64)bitmap;
3497     }
3498
3499     return S_OK;
3500 }
3501
3502 HRESULT STDMETHODCALLTYPE WebView::selectionRect(RECT* rc)
3503 {
3504     WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame();
3505
3506     if (frame) {
3507         IntRect ir = enclosingIntRect(frame->selection()->bounds());
3508         ir = frame->view()->convertToContainingWindow(ir);
3509         ir.move(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height());
3510         rc->left = ir.x();
3511         rc->top = ir.y();
3512         rc->bottom = rc->top + ir.height();
3513         rc->right = rc->left + ir.width();
3514     }
3515
3516     return S_OK;
3517 }
3518
3519 HRESULT STDMETHODCALLTYPE WebView::registerViewClass( 
3520     /* [in] */ IWebDocumentView* /*view*/,
3521     /* [in] */ IWebDocumentRepresentation* /*representation*/,
3522     /* [in] */ BSTR /*forMIMEType*/)
3523 {
3524     ASSERT_NOT_REACHED();
3525     return E_NOTIMPL;
3526 }
3527
3528 HRESULT STDMETHODCALLTYPE WebView::setGroupName( 
3529         /* [in] */ BSTR groupName)
3530 {
3531     if (!m_page)
3532         return S_OK;
3533     m_page->setGroupName(String(groupName, SysStringLen(groupName)));
3534     return S_OK;
3535 }
3536     
3537 HRESULT STDMETHODCALLTYPE WebView::groupName( 
3538         /* [retval][out] */ BSTR* groupName)
3539 {
3540     *groupName = 0;
3541     if (!m_page)
3542         return S_OK;
3543     String groupNameString = m_page->groupName();
3544     *groupName = SysAllocStringLen(groupNameString.characters(), groupNameString.length());
3545     if (!*groupName && groupNameString.length())
3546         return E_OUTOFMEMORY;
3547     return S_OK;
3548 }
3549     
3550 HRESULT STDMETHODCALLTYPE WebView::estimatedProgress( 
3551         /* [retval][out] */ double* estimatedProgress)
3552 {
3553     *estimatedProgress = m_page->progress()->estimatedProgress();
3554     return S_OK;
3555 }
3556     
3557 HRESULT STDMETHODCALLTYPE WebView::isLoading( 
3558         /* [retval][out] */ BOOL* isLoading)
3559 {
3560     COMPtr<IWebDataSource> dataSource;
3561     COMPtr<IWebDataSource> provisionalDataSource;
3562
3563     if (!isLoading)
3564         return E_POINTER;
3565
3566     *isLoading = FALSE;
3567
3568     if (!m_mainFrame)
3569         return E_FAIL;
3570
3571     if (SUCCEEDED(m_mainFrame->dataSource(&dataSource)))
3572         dataSource->isLoading(isLoading);
3573
3574     if (*isLoading)
3575         return S_OK;
3576
3577     if (SUCCEEDED(m_mainFrame->provisionalDataSource(&provisionalDataSource)))
3578         provisionalDataSource->isLoading(isLoading);
3579     return S_OK;
3580 }
3581     
3582 HRESULT STDMETHODCALLTYPE WebView::elementAtPoint( 
3583         /* [in] */ LPPOINT point,
3584         /* [retval][out] */ IPropertyBag** elementDictionary)
3585 {
3586     if (!elementDictionary) {
3587         ASSERT_NOT_REACHED();
3588         return E_POINTER;
3589     }
3590
3591     *elementDictionary = 0;
3592
3593     Frame* frame = core(m_mainFrame);
3594     if (!frame)
3595         return E_FAIL;
3596
3597     IntPoint webCorePoint = IntPoint(point->x, point->y);
3598     HitTestResult result = HitTestResult(webCorePoint);
3599     if (frame->contentRenderer())
3600         result = frame->eventHandler()->hitTestResultAtPoint(webCorePoint, false);
3601     *elementDictionary = WebElementPropertyBag::createInstance(result);
3602     return S_OK;
3603 }
3604     
3605 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForSelection( 
3606     /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
3607 {
3608     ASSERT_NOT_REACHED();
3609     return E_NOTIMPL;
3610 }
3611     
3612 HRESULT STDMETHODCALLTYPE WebView::writeSelectionWithPasteboardTypes( 
3613         /* [size_is][in] */ BSTR* /*types*/,
3614         /* [in] */ int /*cTypes*/,
3615         /* [in] */ IDataObject* /*pasteboard*/)
3616 {
3617     ASSERT_NOT_REACHED();
3618     return E_NOTIMPL;
3619 }
3620     
3621 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForElement( 
3622     /* [in] */ IPropertyBag* /*elementDictionary*/,
3623     /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
3624 {
3625     ASSERT_NOT_REACHED();
3626     return E_NOTIMPL;
3627 }
3628     
3629 HRESULT STDMETHODCALLTYPE WebView::writeElement( 
3630         /* [in] */ IPropertyBag* /*elementDictionary*/,
3631         /* [size_is][in] */ BSTR* /*withPasteboardTypes*/,
3632         /* [in] */ int /*cWithPasteboardTypes*/,
3633         /* [in] */ IDataObject* /*pasteboard*/)
3634 {
3635     ASSERT_NOT_REACHED();
3636     return E_NOTIMPL;
3637 }
3638     
3639 HRESULT STDMETHODCALLTYPE WebView::selectedText(
3640         /* [out, retval] */ BSTR* text)
3641 {
3642     if (!text) {
3643         ASSERT_NOT_REACHED();
3644         return E_POINTER;
3645     }
3646
3647     *text = 0;
3648
3649     Frame* focusedFrame = (m_page && m_page->focusController()) ? m_page->focusController()->focusedOrMainFrame() : 0;
3650     if (!focusedFrame)
3651         return E_FAIL;
3652
3653     String frameSelectedText = focusedFrame->editor()->selectedText();
3654     *text = SysAllocStringLen(frameSelectedText.characters(), frameSelectedText.length());
3655     if (!*text && frameSelectedText.length())
3656         return E_OUTOFMEMORY;
3657     return S_OK;
3658 }
3659
3660 HRESULT STDMETHODCALLTYPE WebView::centerSelectionInVisibleArea(
3661         /* [in] */ IUnknown* /* sender */)
3662 {
3663     Frame* coreFrame = core(m_mainFrame);
3664     if (!coreFrame)
3665         return E_FAIL;
3666
3667     coreFrame->selection()->revealSelection(ScrollAlignment::alignCenterAlways);
3668     return S_OK;
3669 }
3670
3671
3672 HRESULT STDMETHODCALLTYPE WebView::moveDragCaretToPoint( 
3673         /* [in] */ LPPOINT /*point*/)
3674 {
3675     ASSERT_NOT_REACHED();
3676     return E_NOTIMPL;
3677 }
3678     
3679 HRESULT STDMETHODCALLTYPE WebView::removeDragCaret( void)
3680 {
3681     ASSERT_NOT_REACHED();
3682     return E_NOTIMPL;
3683 }
3684     
3685 HRESULT STDMETHODCALLTYPE WebView::setDrawsBackground( 
3686         /* [in] */ BOOL /*drawsBackground*/)
3687 {
3688     ASSERT_NOT_REACHED();
3689     return E_NOTIMPL;
3690 }
3691     
3692 HRESULT STDMETHODCALLTYPE WebView::drawsBackground( 
3693         /* [retval][out] */ BOOL* /*drawsBackground*/)
3694 {
3695     ASSERT_NOT_REACHED();
3696     return E_NOTIMPL;
3697 }
3698     
3699 HRESULT STDMETHODCALLTYPE WebView::setMainFrameURL( 
3700         /* [in] */ BSTR /*urlString*/)
3701 {
3702     ASSERT_NOT_REACHED();
3703     return E_NOTIMPL;
3704 }
3705     
3706 HRESULT STDMETHODCALLTYPE WebView::mainFrameURL( 
3707         /* [retval][out] */ BSTR* urlString)
3708 {
3709     if (!urlString)
3710         return E_POINTER;
3711
3712     if (!m_mainFrame)
3713         return E_FAIL;
3714
3715     COMPtr<IWebDataSource> dataSource;
3716
3717     if (FAILED(m_mainFrame->provisionalDataSource(&dataSource))) {
3718         if (FAILED(m_mainFrame->dataSource(&dataSource)))
3719             return E_FAIL;
3720     }
3721
3722     if (!dataSource) {
3723         *urlString = 0;
3724         return S_OK;
3725     }
3726     
3727     COMPtr<IWebMutableURLRequest> request;
3728     if (FAILED(dataSource->request(&request)) || !request)
3729         return E_FAIL;
3730
3731     if (FAILED(request->URL(urlString)))
3732         return E_FAIL;
3733
3734     return S_OK;
3735 }
3736     
3737 HRESULT STDMETHODCALLTYPE WebView::mainFrameDocument( 
3738         /* [retval][out] */ IDOMDocument** document)
3739 {
3740     if (document)
3741         *document = 0;
3742     if (!m_mainFrame)
3743         return E_FAIL;
3744     return m_mainFrame->DOMDocument(document);
3745 }
3746     
3747 HRESULT STDMETHODCALLTYPE WebView::mainFrameTitle( 
3748         /* [retval][out] */ BSTR* /*title*/)
3749 {
3750     ASSERT_NOT_REACHED();
3751     return E_NOTIMPL;
3752 }
3753     
3754 HRESULT STDMETHODCALLTYPE WebView::mainFrameIcon( 
3755         /* [retval][out] */ OLE_HANDLE* /*hBitmap*/)
3756 {
3757     ASSERT_NOT_REACHED();
3758     return E_NOTIMPL;
3759 }
3760
3761 HRESULT STDMETHODCALLTYPE WebView::registerURLSchemeAsLocal( 
3762         /* [in] */ BSTR scheme)
3763 {
3764     if (!scheme)
3765         return E_POINTER;
3766
3767     SchemeRegistry::registerURLSchemeAsLocal(String(scheme, ::SysStringLen(scheme)));
3768
3769     return S_OK;
3770 }
3771
3772 // IWebIBActions ---------------------------------------------------------------
3773
3774 HRESULT STDMETHODCALLTYPE WebView::takeStringURLFrom( 
3775         /* [in] */ IUnknown* /*sender*/)
3776 {
3777     ASSERT_NOT_REACHED();
3778     return E_NOTIMPL;
3779 }
3780     
3781 HRESULT STDMETHODCALLTYPE WebView::stopLoading( 
3782         /* [in] */ IUnknown* /*sender*/)
3783 {
3784     if (!m_mainFrame)
3785         return E_FAIL;
3786
3787     return m_mainFrame->stopLoading();
3788 }
3789     
3790 HRESULT STDMETHODCALLTYPE WebView::reload( 
3791         /* [in] */ IUnknown* /*sender*/)
3792 {
3793     if (!m_mainFrame)
3794         return E_FAIL;
3795
3796     return m_mainFrame->reload();
3797 }
3798     
3799 HRESULT STDMETHODCALLTYPE WebView::canGoBack( 
3800         /* [in] */ IUnknown* /*sender*/,
3801         /* [retval][out] */ BOOL* result)
3802 {
3803     *result = !!(m_page->backForwardList()->backItem() && !m_page->defersLoading());
3804     return S_OK;
3805 }
3806     
3807 HRESULT STDMETHODCALLTYPE WebView::goBack( 
3808         /* [in] */ IUnknown* /*sender*/)
3809 {
3810     ASSERT_NOT_REACHED();
3811     return E_NOTIMPL;
3812 }
3813     
3814 HRESULT STDMETHODCALLTYPE WebView::canGoForward( 
3815         /* [in] */ IUnknown* /*sender*/,
3816         /* [retval][out] */ BOOL* result)
3817 {
3818     *result = !!(m_page->backForwardList()->forwardItem() && !m_page->defersLoading());
3819     return S_OK;
3820 }
3821     
3822 HRESULT STDMETHODCALLTYPE WebView::goForward( 
3823         /* [in] */ IUnknown* /*sender*/)
3824 {
3825     ASSERT_NOT_REACHED();
3826     return E_NOTIMPL;
3827 }
3828
3829 // FIXME: This code should move into WebCore so it can be shared by all the WebKits.
3830 #define MinimumZoomMultiplier   0.5f
3831 #define MaximumZoomMultiplier   3.0f
3832 #define ZoomMultiplierRatio     1.2f
3833
3834 HRESULT STDMETHODCALLTYPE WebView::canMakeTextLarger( 
3835         /* [in] */ IUnknown* /*sender*/,
3836         /* [retval][out] */ BOOL* result)
3837 {
3838     bool canGrowMore = canZoomIn(m_zoomsTextOnly);
3839     *result = canGrowMore ? TRUE : FALSE;
3840     return S_OK;
3841 }
3842
3843 HRESULT STDMETHODCALLTYPE WebView::canZoomPageIn( 
3844         /* [in] */ IUnknown* /*sender*/,
3845         /* [retval][out] */ BOOL* result)
3846 {
3847     bool canGrowMore = canZoomIn(false);
3848     *result = canGrowMore ? TRUE : FALSE;
3849     return S_OK;
3850 }
3851
3852 bool WebView::canZoomIn(bool isTextOnly)
3853 {
3854     return zoomMultiplier(isTextOnly) * ZoomMultiplierRatio < MaximumZoomMultiplier;
3855 }
3856     
3857 HRESULT STDMETHODCALLTYPE WebView::makeTextLarger( 
3858         /* [in] */ IUnknown* /*sender*/)
3859 {
3860     return zoomIn(m_zoomsTextOnly);
3861 }
3862
3863 HRESULT STDMETHODCALLTYPE WebView::zoomPageIn( 
3864         /* [in] */ IUnknown* /*sender*/)
3865 {
3866     return zoomIn(false);
3867 }
3868
3869 HRESULT WebView::zoomIn(bool isTextOnly)
3870 {
3871     if (!canZoomIn(isTextOnly))
3872         return E_FAIL;
3873     setZoomMultiplier(zoomMultiplier(isTextOnly) * ZoomMultiplierRatio, isTextOnly);
3874     return S_OK;
3875 }
3876
3877 HRESULT STDMETHODCALLTYPE WebView::canMakeTextSmaller( 
3878         /* [in] */ IUnknown* /*sender*/,
3879         /* [retval][out] */ BOOL* result)
3880 {
3881     bool canShrinkMore = canZoomOut(m_zoomsTextOnly);
3882     *result = canShrinkMore ? TRUE : FALSE;
3883     return S_OK;
3884 }
3885
3886 HRESULT STDMETHODCALLTYPE WebView::canZoomPageOut( 
3887         /* [in] */ IUnknown* /*sender*/,
3888         /* [retval][out] */ BOOL* result)
3889 {
3890     bool canShrinkMore = canZoomOut(false);
3891     *result = canShrinkMore ? TRUE : FALSE;
3892     return S_OK;
3893 }
3894
3895 bool WebView::canZoomOut(bool isTextOnly)
3896 {
3897     return zoomMultiplier(isTextOnly) / ZoomMultiplierRatio > MinimumZoomMultiplier;
3898 }
3899
3900 HRESULT STDMETHODCALLTYPE WebView::makeTextSmaller( 
3901         /* [in] */ IUnknown* /*sender*/)
3902 {
3903     return zoomOut(m_zoomsTextOnly);
3904 }
3905
3906 HRESULT STDMETHODCALLTYPE WebView::zoomPageOut( 
3907         /* [in] */ IUnknown* /*sender*/)
3908 {
3909     return zoomOut(false);
3910 }
3911
3912 HRESULT WebView::zoomOut(bool isTextOnly)
3913 {
3914     if (!canZoomOut(isTextOnly))
3915         return E_FAIL;
3916     setZoomMultiplier(zoomMultiplier(isTextOnly) / ZoomMultiplierRatio, isTextOnly);
3917     return S_OK;
3918 }
3919
3920 HRESULT STDMETHODCALLTYPE WebView::canMakeTextStandardSize( 
3921     /* [in] */ IUnknown* /*sender*/,
3922     /* [retval][out] */ BOOL* result)
3923 {
3924     // 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.
3925     bool notAlreadyStandard = canResetZoom(true);
3926     *result = notAlreadyStandard ? TRUE : FALSE;
3927     return S_OK;
3928 }
3929
3930 HRESULT STDMETHODCALLTYPE WebView::canResetPageZoom( 
3931     /* [in] */ IUnknown* /*sender*/,
3932     /* [retval][out] */ BOOL* result)
3933 {
3934     bool notAlreadyStandard = canResetZoom(false);
3935     *result = notAlreadyStandard ? TRUE : FALSE;
3936     return S_OK;
3937 }
3938
3939 bool WebView::canResetZoom(bool isTextOnly)
3940 {
3941     return zoomMultiplier(isTextOnly) != 1.0f;
3942 }
3943
3944 HRESULT STDMETHODCALLTYPE WebView::makeTextStandardSize( 
3945     /* [in] */ IUnknown* /*sender*/)
3946 {
3947     return resetZoom(true);
3948 }
3949
3950 HRESULT STDMETHODCALLTYPE WebView::resetPageZoom( 
3951     /* [in] */ IUnknown* /*sender*/)
3952 {
3953     return resetZoom(false);
3954 }
3955
3956 HRESULT WebView::resetZoom(bool isTextOnly)
3957 {
3958     if (!canResetZoom(isTextOnly))
3959         return E_FAIL;
3960     setZoomMultiplier(1.0f, isTextOnly);
3961     return S_OK;
3962 }
3963
3964 HRESULT STDMETHODCALLTYPE WebView::toggleContinuousSpellChecking( 
3965     /* [in] */ IUnknown* /*sender*/)
3966 {
3967     HRESULT hr;
3968     BOOL enabled;
3969     if (FAILED(hr = isContinuousSpellCheckingEnabled(&enabled)))
3970         return hr;
3971     return setContinuousSpellCheckingEnabled(enabled ? FALSE : TRUE);
3972 }
3973
3974 HRESULT STDMETHODCALLTYPE WebView::toggleSmartInsertDelete( 
3975     /* [in] */ IUnknown* /*sender*/)
3976 {
3977     BOOL enabled = FALSE;
3978     HRESULT hr = smartInsertDeleteEnabled(&enabled);
3979     if (FAILED(hr))
3980         return hr;
3981
3982     return setSmartInsertDeleteEnabled(enabled ? FALSE : TRUE);
3983 }
3984
3985 HRESULT STDMETHODCALLTYPE WebView::toggleGrammarChecking( 
3986     /* [in] */ IUnknown* /*sender*/)
3987 {
3988     BOOL enabled;
3989     HRESULT hr = isGrammarCheckingEnabled(&enabled);
3990     if (FAILED(hr))
3991         return hr;
3992
3993     return setGrammarCheckingEnabled(enabled ? FALSE : TRUE);
3994 }
3995
3996 HRESULT STDMETHODCALLTYPE WebView::reloadFromOrigin( 
3997         /* [in] */ IUnknown* /*sender*/)
3998 {
3999     if (!m_mainFrame)
4000         return E_FAIL;
4001
4002     return m_mainFrame->reloadFromOrigin();
4003 }
4004
4005 // IWebViewCSS -----------------------------------------------------------------
4006
4007 HRESULT STDMETHODCALLTYPE WebView::computedStyleForElement( 
4008         /* [in] */ IDOMElement* /*element*/,
4009         /* [in] */ BSTR /*pseudoElement*/,
4010         /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
4011 {
4012     ASSERT_NOT_REACHED();
4013     return E_NOTIMPL;
4014 }
4015
4016 // IWebViewEditing -------------------------------------------------------------
4017
4018 HRESULT STDMETHODCALLTYPE WebView::editableDOMRangeForPoint( 
4019         /* [in] */ LPPOINT /*point*/,
4020         /* [retval][out] */ IDOMRange** /*range*/)
4021 {
4022     ASSERT_NOT_REACHED();
4023     return E_NOTIMPL;
4024 }
4025     
4026 HRESULT STDMETHODCALLTYPE WebView::setSelectedDOMRange( 
4027         /* [in] */ IDOMRange* /*range*/,
4028         /* [in] */ WebSelectionAffinity /*affinity*/)
4029 {
4030     ASSERT_NOT_REACHED();
4031     return E_NOTIMPL;
4032 }
4033     
4034 HRESULT STDMETHODCALLTYPE WebView::selectedDOMRange( 
4035         /* [retval][out] */ IDOMRange** /*range*/)
4036 {
4037     ASSERT_NOT_REACHED();
4038     return E_NOTIMPL;
4039 }
4040     
4041 HRESULT STDMETHODCALLTYPE WebView::selectionAffinity( 
4042         /* [retval][out][retval][out] */ WebSelectionAffinity* /*affinity*/)
4043 {
4044     ASSERT_NOT_REACHED();
4045     return E_NOTIMPL;
4046 }
4047     
4048 HRESULT STDMETHODCALLTYPE WebView::setEditable( 
4049         /* [in] */ BOOL /*flag*/)
4050 {
4051     ASSERT_NOT_REACHED();
4052     return E_NOTIMPL;
4053 }
4054     
4055 HRESULT STDMETHODCALLTYPE WebView::isEditable( 
4056         /* [retval][out] */ BOOL* /*isEditable*/)
4057 {
4058     ASSERT_NOT_REACHED();
4059     return E_NOTIMPL;
4060 }
4061     
4062 HRESULT STDMETHODCALLTYPE WebView::setTypingStyle( 
4063         /* [in] */ IDOMCSSStyleDeclaration* /*style*/)
4064 {
4065     ASSERT_NOT_REACHED();
4066     return E_NOTIMPL;
4067 }
4068     
4069 HRESULT STDMETHODCALLTYPE WebView::typingStyle( 
4070         /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
4071 {
4072     ASSERT_NOT_REACHED();
4073     return E_NOTIMPL;
4074 }
4075     
4076 HRESULT STDMETHODCALLTYPE WebView::setSmartInsertDeleteEnabled( 
4077         /* [in] */ BOOL flag)
4078 {
4079     m_smartInsertDeleteEnabled = !!flag;
4080     if (m_smartInsertDeleteEnabled)
4081         setSelectTrailingWhitespaceEnabled(false);
4082     return S_OK;
4083 }
4084     
4085 HRESULT STDMETHODCALLTYPE WebView::smartInsertDeleteEnabled( 
4086         /* [retval][out] */ BOOL* enabled)
4087 {
4088     *enabled = m_smartInsertDeleteEnabled ? TRUE : FALSE;
4089     return S_OK;
4090 }
4091  
4092 HRESULT STDMETHODCALLTYPE WebView::setSelectTrailingWhitespaceEnabled( 
4093         /* [in] */ BOOL flag)
4094 {
4095     m_selectTrailingWhitespaceEnabled = !!flag;
4096     if (m_selectTrailingWhitespaceEnabled)
4097         setSmartInsertDeleteEnabled(false);
4098     return S_OK;
4099 }
4100     
4101 HRESULT STDMETHODCALLTYPE WebView::isSelectTrailingWhitespaceEnabled( 
4102         /* [retval][out] */ BOOL* enabled)
4103 {
4104     *enabled = m_selectTrailingWhitespaceEnabled ? TRUE : FALSE;
4105     return S_OK;
4106 }
4107
4108 HRESULT STDMETHODCALLTYPE WebView::setContinuousSpellCheckingEnabled( 
4109         /* [in] */ BOOL flag)
4110 {
4111     if (continuousSpellCheckingEnabled != !!flag) {
4112         continuousSpellCheckingEnabled = !!flag;
4113         COMPtr<IWebPreferences> prefs;
4114         if (SUCCEEDED(preferences(&prefs)))
4115             prefs->setContinuousSpellCheckingEnabled(flag);
4116     }
4117     
4118     BOOL spellCheckingEnabled;
4119     if (SUCCEEDED(isContinuousSpellCheckingEnabled(&spellCheckingEnabled)) && spellCheckingEnabled)
4120         preflightSpellChecker();
4121     else
4122         m_mainFrame->unmarkAllMisspellings();
4123
4124     return S_OK;
4125 }
4126     
4127 HRESULT STDMETHODCALLTYPE WebView::isContinuousSpellCheckingEnabled( 
4128         /* [retval][out] */ BOOL* enabled)
4129 {
4130     *enabled = (continuousSpellCheckingEnabled && continuousCheckingAllowed()) ? TRUE : FALSE;
4131     return S_OK;
4132 }
4133     
4134 HRESULT STDMETHODCALLTYPE WebView::spellCheckerDocumentTag( 
4135         /* [retval][out] */ int* tag)
4136 {
4137     // we just use this as a flag to indicate that we've spell checked the document
4138     // and need to close the spell checker out when the view closes.
4139     *tag = 0;
4140     m_hasSpellCheckerDocumentTag = true;
4141     return S_OK;
4142 }
4143
4144 static COMPtr<IWebEditingDelegate> spellingDelegateForTimer;
4145
4146 static void preflightSpellCheckerNow()
4147 {
4148     spellingDelegateForTimer->preflightChosenSpellServer();
4149     spellingDelegateForTimer = 0;
4150 }
4151
4152 static void CALLBACK preflightSpellCheckerTimerCallback(HWND, UINT, UINT_PTR id, DWORD)
4153 {
4154     ::KillTimer(0, id);
4155     preflightSpellCheckerNow();
4156 }
4157
4158 void WebView::preflightSpellChecker()
4159 {
4160     // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
4161     if (!m_editingDelegate)
4162         return;
4163
4164     BOOL exists;
4165     spellingDelegateForTimer = m_editingDelegate;
4166     if (SUCCEEDED(m_editingDelegate->sharedSpellCheckerExists(&exists)) && exists)
4167         preflightSpellCheckerNow();
4168     else
4169         ::SetTimer(0, 0, 2000, preflightSpellCheckerTimerCallback);
4170 }
4171
4172 bool WebView::continuousCheckingAllowed()
4173 {
4174     static bool allowContinuousSpellChecking = true;
4175     static bool readAllowContinuousSpellCheckingDefault = false;
4176     if (!readAllowContinuousSpellCheckingDefault) {
4177         COMPtr<IWebPreferences> prefs;
4178         if (SUCCEEDED(preferences(&prefs))) {
4179             BOOL allowed;
4180             prefs->allowContinuousSpellChecking(&allowed);
4181             allowContinuousSpellChecking = !!allowed;
4182         }
4183         readAllowContinuousSpellCheckingDefault = true;
4184     }
4185     return allowContinuousSpellChecking;
4186 }
4187
4188 HRESULT STDMETHODCALLTYPE WebView::undoManager( 
4189         /* [retval][out] */ IWebUndoManager** /*manager*/)
4190 {
4191     ASSERT_NOT_REACHED();
4192     return E_NOTIMPL;
4193 }
4194     
4195 HRESULT STDMETHODCALLTYPE WebView::setEditingDelegate( 
4196         /* [in] */ IWebEditingDelegate* d)
4197 {
4198     m_editingDelegate = d;
4199     return S_OK;
4200 }
4201     
4202 HRESULT STDMETHODCALLTYPE WebView::editingDelegate( 
4203         /* [retval][out] */ IWebEditingDelegate** d)
4204 {
4205     if (!d) {
4206         ASSERT_NOT_REACHED();
4207         return E_POINTER;
4208     }
4209
4210     *d = m_editingDelegate.get();
4211     if (!*d)
4212         return E_FAIL;
4213
4214     (*d)->AddRef();
4215     return S_OK;
4216 }
4217     
4218 HRESULT STDMETHODCALLTYPE WebView::styleDeclarationWithText( 
4219         /* [in] */ BSTR /*text*/,
4220         /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
4221 {
4222     ASSERT_NOT_REACHED();
4223     return E_NOTIMPL;
4224 }
4225     
4226 HRESULT STDMETHODCALLTYPE WebView::hasSelectedRange( 
4227         /* [retval][out] */ BOOL* hasSelectedRange)
4228 {
4229     *hasSelectedRange = m_page->mainFrame()->selection()->isRange();
4230     return S_OK;
4231 }
4232     
4233 HRESULT STDMETHODCALLTYPE WebView::cutEnabled( 
4234         /* [retval][out] */ BOOL* enabled)
4235 {
4236     Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
4237     *enabled = editor->canCut() || editor->canDHTMLCut();
4238     return S_OK;
4239 }
4240     
4241 HRESULT STDMETHODCALLTYPE WebView::copyEnabled( 
4242         /* [retval][out] */ BOOL* enabled)
4243 {
4244     Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
4245     *enabled = editor->canCopy() || editor->canDHTMLCopy();
4246     return S_OK;
4247 }
4248     
4249 HRESULT STDMETHODCALLTYPE WebView::pasteEnabled( 
4250         /* [retval][out] */ BOOL* enabled)
4251 {
4252     Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
4253     *enabled = editor->canPaste() || editor->canDHTMLPaste();
4254     return S_OK;
4255 }
4256     
4257 HRESULT STDMETHODCALLTYPE WebView::deleteEnabled( 
4258         /* [retval][out] */ BOOL* enabled)
4259 {
4260     *enabled = m_page->focusController()->focusedOrMainFrame()->editor()->canDelete();
4261     return S_OK;
4262 }
4263     
4264 HRESULT STDMETHODCALLTYPE WebView::editingEnabled( 
4265         /* [retval][out] */ BOOL* enabled)
4266 {
4267     *enabled = m_page->focusController()->focusedOrMainFrame()->editor()->canEdit();
4268     return S_OK;
4269 }
4270
4271 HRESULT STDMETHODCALLTYPE WebView::isGrammarCheckingEnabled( 
4272     /* [retval][out] */ BOOL* enabled)
4273 {
4274     *enabled = grammarCheckingEnabled ? TRUE : FALSE;
4275     return S_OK;
4276 }
4277
4278 HRESULT STDMETHODCALLTYPE WebView::setGrammarCheckingEnabled( 
4279     BOOL enabled)
4280 {
4281     if (!m_editingDelegate) {
4282         LOG_ERROR("No NSSpellChecker");
4283         return E_FAIL;
4284     }
4285
4286     if (grammarCheckingEnabled == !!enabled)
4287         return S_OK;
4288     
4289     grammarCheckingEnabled = !!enabled;
4290     COMPtr<IWebPreferences> prefs;
4291     if (SUCCEEDED(preferences(&prefs)))
4292         prefs->setGrammarCheckingEnabled(enabled);
4293     
4294     m_editingDelegate->updateGrammar();
4295
4296     // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
4297     // because grammar checking only occurs on code paths that already preflight spell checking appropriately.
4298     
4299     BOOL grammarEnabled;
4300     if (SUCCEEDED(isGrammarCheckingEnabled(&grammarEnabled)) && !grammarEnabled)
4301         m_mainFrame->unmarkAllBadGrammar();
4302
4303     return S_OK;
4304 }
4305
4306 // IWebViewUndoableEditing -----------------------------------------------------
4307
4308 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithNode( 
4309         /* [in] */ IDOMNode* /*node*/)
4310 {
4311     ASSERT_NOT_REACHED();
4312     return E_NOTIMPL;
4313 }
4314     
4315 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithText( 
4316         /* [in] */ BSTR text)
4317 {
4318     String textString(text, ::SysStringLen(text));
4319     Position start = m_page->mainFrame()->selection()->selection().start();
4320     m_page->focusController()->focusedOrMainFrame()->editor()->insertText(textString, 0);
4321     m_page->mainFrame()->selection()->setBase(start);
4322     return S_OK;
4323 }
4324     
4325 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithMarkupString( 
4326         /* [in] */ BSTR /*markupString*/)
4327 {
4328     ASSERT_NOT_REACHED();
4329     return E_NOTIMPL;
4330 }
4331     
4332 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithArchive( 
4333         /* [in] */ IWebArchive* /*archive*/)
4334 {
4335     ASSERT_NOT_REACHED();
4336     return E_NOTIMPL;
4337 }
4338     
4339 HRESULT STDMETHODCALLTYPE WebView::deleteSelection( void)
4340 {
4341     Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
4342     editor->deleteSelectionWithSmartDelete(editor->canSmartCopyOrDelete());
4343     return S_OK;
4344 }
4345
4346 HRESULT STDMETHODCALLTYPE WebView::clearSelection( void)
4347 {
4348     m_page->focusController()->focusedOrMainFrame()->selection()->clear();
4349     return S_OK;
4350 }
4351     
4352 HRESULT STDMETHODCALLTYPE WebView::applyStyle( 
4353         /* [in] */ IDOMCSSStyleDeclaration* /*style*/)
4354 {
4355     ASSERT_NOT_REACHED();
4356     return E_NOTIMPL;
4357 }
4358
4359 // IWebViewEditingActions ------------------------------------------------------
4360
4361 HRESULT STDMETHODCALLTYPE WebView::copy( 
4362         /* [in] */ IUnknown* /*sender*/)
4363 {
4364     m_page->focusController()->focusedOrMainFrame()->editor()->command("Copy").execute();
4365     return S_OK;
4366 }
4367
4368 HRESULT STDMETHODCALLTYPE WebView::cut( 
4369         /* [in] */ IUnknown* /*sender*/)
4370 {
4371     m_page->focusController()->focusedOrMainFrame()->editor()->command("Cut").execute();
4372     return S_OK;
4373 }
4374
4375 HRESULT STDMETHODCALLTYPE WebView::paste( 
4376         /* [in] */ IUnknown* /*sender*/)
4377 {
4378     m_page->focusController()->focusedOrMainFrame()->editor()->command("Paste").execute();
4379     return S_OK;
4380 }
4381
4382 HRESULT STDMETHODCALLTYPE WebView::copyURL( 
4383         /* [in] */ BSTR url)
4384 {
4385     m_page->focusController()->focusedOrMainFrame()->editor()->copyURL(MarshallingHelpers::BSTRToKURL(url), "");
4386     return S_OK;
4387 }
4388
4389
4390 HRESULT STDMETHODCALLTYPE WebView::copyFont( 
4391         /* [in] */ IUnknown* /*sender*/)
4392 {
4393     ASSERT_NOT_REACHED();
4394     return E_NOTIMPL;
4395 }
4396     
4397 HRESULT STDMETHODCALLTYPE WebView::pasteFont( 
4398         /* [in] */ IUnknown* /*sender*/)
4399 {
4400     ASSERT_NOT_REACHED();
4401     return E_NOTIMPL;
4402 }
4403     
4404 HRESULT STDMETHODCALLTYPE WebView::delete_( 
4405         /* [in] */ IUnknown* /*sender*/)
4406 {
4407     m_page->focusController()->focusedOrMainFrame()->editor()->command("Delete").execute();
4408     return S_OK;
4409 }
4410     
4411 HRESULT STDMETHODCALLTYPE WebView::pasteAsPlainText( 
4412         /* [in] */ IUnknown* /*sender*/)
4413 {
4414     ASSERT_NOT_REACHED();
4415     return E_NOTIMPL;
4416 }
4417     
4418 HRESULT STDMETHODCALLTYPE WebView::pasteAsRichText( 
4419         /* [in] */ IUnknown* /*sender*/)
4420 {
4421     ASSERT_NOT_REACHED();
4422     return E_NOTIMPL;
4423 }
4424     
4425 HRESULT STDMETHODCALLTYPE WebView::changeFont( 
4426         /* [in] */ IUnknown* /*sender*/)
4427 {
4428     ASSERT_NOT_REACHED();
4429     return E_NOTIMPL;
4430 }
4431     
4432 HRESULT STDMETHODCALLTYPE WebView::changeAttributes( 
4433         /* [in] */ IUnknown* /*sender*/)
4434 {
4435     ASSERT_NOT_REACHED();
4436     return E_NOTIMPL;
4437 }
4438     
4439 HRESULT STDMETHODCALLTYPE WebView::changeDocumentBackgroundColor( 
4440         /* [in] */ IUnknown* /*sender*/)
4441 {
4442     ASSERT_NOT_REACHED();
4443     return E_NOTIMPL;
4444 }
4445     
4446 HRESULT STDMETHODCALLTYPE WebView::changeColor( 
4447         /* [in] */ IUnknown* /*sender*/)
4448 {
4449     ASSERT_NOT_REACHED();
4450     return E_NOTIMPL;
4451 }
4452     
4453 HRESULT STDMETHODCALLTYPE WebView::alignCenter( 
4454         /* [in] */ IUnknown* /*sender*/)
4455 {
4456     ASSERT_NOT_REACHED();
4457     return E_NOTIMPL;
4458 }
4459     
4460 HRESULT STDMETHODCALLTYPE WebView::alignJustified( 
4461         /* [in] */ IUnknown* /*sender*/)
4462 {
4463     ASSERT_NOT_REACHED();
4464     return E_NOTIMPL;
4465 }
4466     
4467 HRESULT STDMETHODCALLTYPE WebView::alignLeft( 
4468         /* [in] */ IUnknown* /*sender*/)
4469 {
4470     ASSERT_NOT_REACHED();
4471     return E_NOTIMPL;
4472 }
4473     
4474 HRESULT STDMETHODCALLTYPE WebView::alignRight( 
4475         /* [in] */ IUnknown* /*sender*/)
4476 {
4477     ASSERT_NOT_REACHED();
4478     return E_NOTIMPL;
4479 }
4480     
4481 HRESULT STDMETHODCALLTYPE WebView::checkSpelling( 
4482         /* [in] */ IUnknown* /*sender*/)
4483 {
4484     if (!m_editingDelegate) {
4485         LOG_ERROR("No NSSpellChecker");
4486         return E_FAIL;
4487     }
4488     
4489     core(m_mainFrame)->editor()->advanceToNextMisspelling();
4490     return S_OK;
4491 }
4492     
4493 HRESULT STDMETHODCALLTYPE WebView::showGuessPanel( 
4494         /* [in] */ IUnknown* /*sender*/)
4495 {
4496     if (!m_editingDelegate) {
4497         LOG_ERROR("No NSSpellChecker");
4498         return E_FAIL;
4499     }
4500     
4501     // Post-Tiger, this menu item is a show/hide toggle, to match AppKit. Leave Tiger behavior alone
4502     // to match rest of OS X.
4503     BOOL showing;
4504     if (SUCCEEDED(m_editingDelegate->spellingUIIsShowing(&showing)) && showing) {
4505         m_editingDelegate->showSpellingUI(FALSE);
4506     }
4507     
4508     core(m_mainFrame)->editor()->advanceToNextMisspelling(true);
4509     m_editingDelegate->showSpellingUI(TRUE);
4510     return S_OK;
4511 }
4512     
4513 HRESULT STDMETHODCALLTYPE WebView::performFindPanelAction( 
4514         /* [in] */ IUnknown* /*sender*/)
4515 {
4516     ASSERT_NOT_REACHED();
4517     return E_NOTIMPL;
4518 }
4519     
4520 HRESULT STDMETHODCALLTYPE WebView::startSpeaking( 
4521         /* [in] */ IUnknown* /*sender*/)
4522 {
4523     ASSERT_NOT_REACHED();
4524     return E_NOTIMPL;
4525 }
4526     
4527 HRESULT STDMETHODCALLTYPE WebView::stopSpeaking( 
4528         /* [in] */ IUnknown* /*sender*/)
4529 {
4530     ASSERT_NOT_REACHED();
4531     return E_NOTIMPL;
4532 }
4533
4534 // IWebNotificationObserver -----------------------------------------------------------------
4535
4536 HRESULT STDMETHODCALLTYPE WebView::onNotify( 
4537     /* [in] */ IWebNotification* notification)
4538 {
4539     BSTR nameBSTR;
4540     HRESULT hr = notification->name(&nameBSTR);
4541     if (FAILED(hr))
4542         return hr;
4543
4544     BString name;
4545     name.adoptBSTR(nameBSTR);
4546
4547     if (!wcscmp(name, WebIconDatabase::iconDatabaseDidAddIconNotification()))
4548         return notifyDidAddIcon(notification);
4549
4550     if (!wcscmp(name, WebPreferences::webPreferencesChangedNotification()))
4551         return notifyPreferencesChanged(notification);
4552
4553     return hr;
4554 }
4555
4556 HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification)
4557 {
4558     HRESULT hr;
4559
4560     COMPtr<IUnknown> unkPrefs;
4561     hr = notification->getObject(&unkPrefs);
4562     if (FAILED(hr))
4563         return hr;
4564
4565     COMPtr<IWebPreferences> preferences(Query, unkPrefs);
4566     if (!preferences)
4567         return E_NOINTERFACE;
4568
4569     ASSERT(preferences == m_preferences);
4570
4571     BSTR str;
4572     int size;
4573     BOOL enabled;
4574
4575     Settings* settings = m_page->settings();
4576
4577     hr = preferences->cursiveFontFamily(&str);
4578     if (FAILED(hr))
4579         return hr;
4580     settings->setCursiveFontFamily(AtomicString(str, SysStringLen(str)));
4581     SysFreeString(str);
4582
4583     hr = preferences->defaultFixedFontSize(&size);
4584     if (FAILED(hr))
4585         return hr;
4586     settings->setDefaultFixedFontSize(size);
4587
4588     hr = preferences->defaultFontSize(&size);
4589     if (FAILED(hr))
4590         return hr;
4591     settings->setDefaultFontSize(size);
4592     
4593     hr = preferences->defaultTextEncodingName(&str);
4594     if (FAILED(hr))
4595         return hr;
4596     settings->setDefaultTextEncodingName(String(str, SysStringLen(str)));
4597     SysFreeString(str);
4598
4599     hr = preferences->fantasyFontFamily(&str);
4600     if (FAILED(hr))
4601         return hr;
4602     settings->setFantasyFontFamily(AtomicString(str, SysStringLen(str)));
4603     SysFreeString(str);
4604
4605     hr = preferences->fixedFontFamily(&str);
4606     if (FAILED(hr))
4607         return hr;
4608     settings->setFixedFontFamily(AtomicString(str, SysStringLen(str)));
4609     SysFreeString(str);
4610
4611 #if ENABLE(VIDEO_TRACK)
4612     hr = preferences->shouldDisplaySubtitles(&enabled);
4613     if (FAILED(hr))
4614         return hr;
4615     settings->setShouldDisplaySubtitles(enabled);
4616
4617     hr = preferences->shouldDisplayCaptions(&enabled);
4618     if (FAILED(hr))
4619         return hr;
4620     settings->setShouldDisplayCaptions(enabled);
4621
4622     hr = preferences->shouldDisplayTextDescriptions(&enabled);
4623     if (FAILED(hr))
4624         return hr;
4625     settings->setShouldDisplayTextDescriptions(enabled);
4626 #endif
4627
4628     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
4629     if (prefsPrivate) {
4630         hr = prefsPrivate->localStorageDatabasePath(&str);
4631         if (FAILED(hr))
4632             return hr;
4633         settings->setLocalStorageDatabasePath(String(str, SysStringLen(str)));
4634         SysFreeString(str);
4635     }
4636
4637     hr = preferences->pictographFontFamily(&str);
4638     if (FAILED(hr))
4639         return hr;
4640     settings->setPictographFontFamily(AtomicString(str, SysStringLen(str)));
4641     SysFreeString(str);
4642
4643     hr = preferences->isJavaEnabled(&enabled);
4644     if (FAILED(hr))
4645         return hr;
4646     settings->setJavaEnabled(!!enabled);
4647
4648     hr = preferences->isJavaScriptEnabled(&enabled);
4649     if (FAILED(hr))
4650         return hr;
4651     settings->setScriptEnabled(!!enabled);
4652
4653     hr = preferences->javaScriptCanOpenWindowsAutomatically(&enabled);
4654     if (FAILED(hr))
4655         return hr;
4656     settings->setJavaScriptCanOpenWindowsAutomatically(!!enabled);
4657
4658     hr = preferences->minimumFontSize(&size);
4659     if (FAILED(hr))
4660         return hr;
4661     settings->setMinimumFontSize(size);
4662
4663     hr = preferences->minimumLogicalFontSize(&size);
4664     if (FAILED(hr))
4665         return hr;
4666     settings->setMinimumLogicalFontSize(size);
4667
4668     hr = preferences->arePlugInsEnabled(&enabled);
4669     if (FAILED(hr))
4670         return hr;
4671     settings->setPluginsEnabled(!!enabled);
4672
4673     hr = preferences->isCSSRegionsEnabled(&enabled);
4674     if (FAILED(hr))
4675         return hr;
4676     settings->setCSSRegionsEnabled(!!enabled);
4677
4678     hr = preferences->privateBrowsingEnabled(&enabled);
4679     if (FAILED(hr))
4680         return hr;
4681     settings->setPrivateBrowsingEnabled(!!enabled);
4682
4683     hr = preferences->sansSerifFontFamily(&str);
4684     if (FAILED(hr))
4685         return hr;
4686     settings->setSansSerifFontFamily(AtomicString(str, SysStringLen(str)));
4687     SysFreeString(str);
4688
4689     hr = preferences->serifFontFamily(&str);
4690     if (FAILED(hr))
4691         return hr;
4692     settings->setSerifFontFamily(AtomicString(str, SysStringLen(str)));
4693     SysFreeString(str);
4694
4695     hr = preferences->standardFontFamily(&str);
4696     if (FAILED(hr))
4697         return hr;
4698     settings->setStandardFontFamily(AtomicString(str, SysStringLen(str)));
4699     SysFreeString(str);
4700
4701     hr = preferences->loadsImagesAutomatically(&enabled);
4702     if (FAILED(hr))
4703         return hr;
4704     settings->setLoadsImagesAutomatically(!!enabled);
4705
4706     hr = preferences->userStyleSheetEnabled(&enabled);
4707     if (FAILED(hr))
4708         return hr;
4709     if (enabled) {
4710         hr = preferences->userStyleSheetLocation(&str);
4711         if (FAILED(hr))
4712             return hr;
4713
4714         RetainPtr<CFStringRef> urlString(AdoptCF, String(str, SysStringLen(str)).createCFString());
4715         RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithString(kCFAllocatorDefault, urlString.get(), 0));
4716
4717         // Check if the passed in string is a path and convert it to a URL.
4718         // FIXME: This is a workaround for nightly builds until we can get Safari to pass 
4719         // in an URL here. See <rdar://problem/5478378>
4720         if (!url) {
4721             DWORD len = SysStringLen(str) + 1;
4722
4723             int result = WideCharToMultiByte(CP_UTF8, 0, str, len, 0, 0, 0, 0);
4724             Vector<UInt8> utf8Path(result);
4725             if (!WideCharToMultiByte(CP_UTF8, 0, str, len, (LPSTR)utf8Path.data(), result, 0, 0))
4726                 return E_FAIL;
4727
4728             url.adoptCF(CFURLCreateFromFileSystemRepresentation(0, utf8Path.data(), result - 1, false));
4729         }
4730
4731         settings->setUserStyleSheetLocation(url.get());
4732         SysFreeString(str);
4733     } else {
4734         settings->setUserStyleSheetLocation(KURL());
4735     }
4736
4737     hr = preferences->shouldPrintBackgrounds(&enabled);
4738     if (FAILED(hr))
4739         return hr;
4740     settings->setShouldPrintBackgrounds(!!enabled);
4741
4742     hr = preferences->textAreasAreResizable(&enabled);
4743     if (FAILED(hr))
4744         return hr;
4745     settings->setTextAreasAreResizable(!!enabled);
4746
4747     WebKitEditableLinkBehavior behavior;
4748     hr = preferences->editableLinkBehavior(&behavior);
4749     if (FAILED(hr))
4750         return hr;
4751     settings->setEditableLinkBehavior((EditableLinkBehavior)behavior);
4752
4753     hr = preferences->usesPageCache(&enabled);
4754     if (FAILED(hr))
4755         return hr;
4756     settings->setUsesPageCache(!!enabled);
4757
4758     hr = preferences->isDOMPasteAllowed(&enabled);
4759     if (FAILED(hr))
4760         return hr;
4761     settings->setDOMPasteAllowed(!!enabled);
4762
4763     hr = preferences->zoomsTextOnly(&enabled);
4764     if (FAILED(hr))
4765         return hr;
4766
4767     if (m_zoomsTextOnly != !!enabled)
4768         setZoomMultiplier(m_zoomMultiplier, enabled);
4769
4770     settings->setShowsURLsInToolTips(false);
4771
4772     settings->setForceFTPDirectoryListings(true);
4773     settings->setDeveloperExtrasEnabled(developerExtrasEnabled());
4774     settings->setNeedsSiteSpecificQuirks(s_allowSiteSpecificHacks);
4775
4776     FontSmoothingType smoothingType;
4777     hr = preferences->fontSmoothing(&smoothingType);
4778     if (FAILED(hr))
4779         return hr;
4780     settings->setFontRenderingMode(smoothingType != FontSmoothingTypeWindows ? NormalRenderingMode : AlternateRenderingMode);
4781
4782 #if USE(AVFOUNDATION)
4783     hr = preferences->avFoundationEnabled(&enabled);
4784     if (FAILED(hr))
4785         return hr;
4786     settings->setAVFoundationEnabled(enabled);
4787 #endif
4788
4789     if (prefsPrivate) {
4790         hr = prefsPrivate->authorAndUserStylesEnabled(&enabled);
4791         if (FAILED(hr))
4792             return hr;
4793         settings->setAuthorAndUserStylesEnabled(enabled);
4794     }
4795
4796     hr = prefsPrivate->inApplicationChromeMode(&enabled);
4797     if (FAILED(hr))
4798         return hr;
4799     settings->setApplicationChromeMode(enabled);
4800
4801     hr = prefsPrivate->offlineWebApplicationCacheEnabled(&enabled);
4802     if (FAILED(hr))
4803         return hr;
4804     settings->setOfflineWebApplicationCacheEnabled(enabled);
4805
4806 #if ENABLE(SQL_DATABASE)
4807     hr = prefsPrivate->databasesEnabled(&enabled);
4808     if (FAILED(hr))
4809         return hr;
4810     AbstractDatabase::setIsAvailable(enabled);
4811 #endif
4812
4813     hr = prefsPrivate->localStorageEnabled(&enabled);
4814     if (FAILED(hr))
4815         return hr;
4816     settings->setLocalStorageEnabled(enabled);
4817
4818     hr = prefsPrivate->experimentalNotificationsEnabled(&enabled);
4819     if (FAILED(hr))
4820         return hr;
4821     settings->setExperimentalNotificationsEnabled(enabled);
4822
4823     hr = prefsPrivate->isWebSecurityEnabled(&enabled);
4824     if (FAILED(hr))
4825         return hr;
4826     settings->setWebSecurityEnabled(!!enabled);
4827
4828     hr = prefsPrivate->allowUniversalAccessFromFileURLs(&enabled);
4829     if (FAILED(hr))
4830         return hr;
4831     settings->setAllowUniversalAccessFromFileURLs(!!enabled);
4832
4833     hr = prefsPrivate->allowFileAccessFromFileURLs(&enabled);
4834     if (FAILED(hr))
4835         return hr;
4836     settings->setAllowFileAccessFromFileURLs(!!enabled);
4837
4838     hr = prefsPrivate->javaScriptCanAccessClipboard(&enabled);
4839     if (FAILED(hr))
4840         return hr;
4841     settings->setJavaScriptCanAccessClipboard(!!enabled);
4842
4843     hr = prefsPrivate->isXSSAuditorEnabled(&enabled);
4844     if (FAILED(hr))
4845         return hr;
4846     settings->setXSSAuditorEnabled(!!enabled);
4847
4848 #if USE(SAFARI_THEME)
4849     hr = prefsPrivate->shouldPaintNativeControls(&enabled);
4850     if (FAILED(hr))
4851         return hr;
4852     settings->setShouldPaintNativeControls(!!enabled);
4853 #endif
4854
4855     hr = prefsPrivate->shouldUseHighResolutionTimers(&enabled);
4856     if (FAILED(hr))
4857         return hr;
4858     settings->setShouldUseHighResolutionTimers(enabled);
4859
4860     hr = prefsPrivate->isFrameFlatteningEnabled(&enabled);
4861     if (FAILED(hr))
4862         return hr;
4863     settings->setFrameFlatteningEnabled(enabled);
4864
4865 #if USE(ACCELERATED_COMPOSITING)
4866     hr = prefsPrivate->acceleratedCompositingEnabled(&enabled);
4867     if (FAILED(hr))
4868         return hr;
4869     settings->setAcceleratedCompositingEnabled(enabled);
4870 #endif
4871
4872     hr = prefsPrivate->showDebugBorders(&enabled);
4873     if (FAILED(hr))
4874         return hr;
4875     settings->setShowDebugBorders(enabled);
4876
4877     hr = prefsPrivate->showRepaintCounter(&enabled);
4878     if (FAILED(hr))
4879         return hr;
4880     settings->setShowRepaintCounter(enabled);
4881
4882 #if ENABLE(WEB_AUDIO)
4883     settings->setWebAudioEnabled(true);
4884 #endif // ENABLE(WEB_AUDIO)
4885
4886 #if ENABLE(WEBGL)
4887     settings->setWebGLEnabled(true);
4888 #endif // ENABLE(WEBGL)
4889
4890     hr = prefsPrivate->isDNSPrefetchingEnabled(&enabled);
4891     if (FAILED(hr))
4892         return hr;
4893     settings->setDNSPrefetchingEnabled(enabled);
4894
4895     hr = prefsPrivate->memoryInfoEnabled(&enabled);
4896     if (FAILED(hr))
4897         return hr;
4898     settings->setMemoryInfoEnabled(enabled);
4899     
4900     hr = prefsPrivate->hyperlinkAuditingEnabled(&enabled);
4901     if (FAILED(hr))
4902         return hr;
4903     settings->setHyperlinkAuditingEnabled(enabled);
4904
4905     hr = prefsPrivate->loadsSiteIconsIgnoringImageLoadingPreference(&enabled);
4906     if (FAILED(hr))
4907         return hr;
4908     settings->setLoadsSiteIconsIgnoringImageLoadingSetting(!!enabled);
4909
4910     hr = prefsPrivate->showsToolTipOverTruncatedText(&enabled);
4911     if (FAILED(hr))
4912         return hr;
4913
4914     settings->setShowsToolTipOverTruncatedText(enabled);
4915
4916     if (!m_closeWindowTimer)
4917         m_mainFrame->invalidate(); // FIXME
4918
4919     hr = updateSharedSettingsFromPreferencesIfNeeded(preferences.get());
4920     if (FAILED(hr))
4921         return hr;
4922
4923 #if ENABLE(FULLSCREEN_API)
4924     hr = prefsPrivate->isFullScreenEnabled(&enabled);
4925     if (FAILED(hr))
4926         return hr;
4927     settings->setFullScreenEnabled(enabled);
4928 #endif
4929
4930     hr = prefsPrivate->mediaPlaybackRequiresUserGesture(&enabled);
4931     if (FAILED(hr))
4932         return hr;
4933     settings->setMediaPlaybackRequiresUserGesture(enabled);
4934
4935     hr = prefsPrivate->mediaPlaybackAllowsInline(&enabled);
4936     if (FAILED(hr))
4937         return hr;
4938     settings->setMediaPlaybackAllowsInline(enabled);
4939
4940     hr = prefsPrivate->shouldInvertColors(&enabled);
4941     if (FAILED(hr))
4942         return hr;
4943     setShouldInvertColors(enabled);
4944
4945     hr = prefsPrivate->requestAnimationFrameEnabled(&enabled);
4946     if (FAILED(hr))
4947         return hr;
4948     settings->setRequestAnimationFrameEnabled(enabled);
4949
4950     return S_OK;
4951 }
4952
4953 HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences* preferences)
4954 {
4955     if (preferences != WebPreferences::sharedStandardPreferences())
4956         return S_OK;
4957
4958     WebKitCookieStorageAcceptPolicy acceptPolicy;
4959     HRESULT hr = preferences->cookieStorageAcceptPolicy(&acceptPolicy);
4960     if (FAILED(hr))
4961         return hr;
4962
4963 #if USE(CFNETWORK)
4964     // Set cookie storage accept policy
4965     if (RetainPtr<CFHTTPCookieStorageRef> cookieStorage = currentCFHTTPCookieStorage())
4966         CFHTTPCookieStorageSetCookieAcceptPolicy(cookieStorage.get(), acceptPolicy);
4967 #endif
4968
4969     return S_OK;
4970 }
4971
4972 // IWebViewPrivate ------------------------------------------------------------
4973
4974 HRESULT STDMETHODCALLTYPE WebView::MIMETypeForExtension(
4975     /* [in] */ BSTR extension,
4976     /* [retval][out] */ BSTR* mimeType)
4977 {
4978     if (!mimeType)
4979         return E_POINTER;
4980
4981     String extensionStr(extension, SysStringLen(extension));
4982
4983     *mimeType = BString(MIMETypeRegistry::getMIMETypeForExtension(extensionStr)).release();
4984
4985     return S_OK;
4986 }
4987
4988 HRESULT STDMETHODCALLTYPE WebView::setCustomDropTarget(
4989     /* [in] */ IDropTarget* dt)
4990 {
4991     ASSERT(::IsWindow(m_viewWindow));
4992     if (!dt)
4993         return E_POINTER;
4994     m_hasCustomDropTarget = true;
4995     revokeDragDrop();
4996     return ::RegisterDragDrop(m_viewWindow,dt);
4997 }
4998
4999 HRESULT STDMETHODCALLTYPE WebView::removeCustomDropTarget()
5000 {
5001     if (!m_hasCustomDropTarget)
5002         return S_OK;
5003     m_hasCustomDropTarget = false;
5004     revokeDragDrop();
5005     return registerDragDrop();
5006 }
5007
5008 HRESULT STDMETHODCALLTYPE WebView::setInViewSourceMode( 
5009         /* [in] */ BOOL flag)
5010 {
5011     if (!m_mainFrame)
5012         return E_FAIL;
5013
5014     return m_mainFrame->setInViewSourceMode(flag);
5015 }
5016     
5017 HRESULT STDMETHODCALLTYPE WebView::inViewSourceMode( 
5018         /* [retval][out] */ BOOL* flag)
5019 {
5020     if (!m_mainFrame)
5021         return E_FAIL;
5022
5023     return m_mainFrame->inViewSourceMode(flag);
5024 }
5025
5026 HRESULT STDMETHODCALLTYPE WebView::viewWindow( 
5027         /* [retval][out] */ OLE_HANDLE *window)
5028 {
5029     *window = (OLE_HANDLE)(ULONG64)m_viewWindow;
5030     return S_OK;
5031 }
5032
5033 HRESULT STDMETHODCALLTYPE WebView::setFormDelegate( 
5034     /* [in] */ IWebFormDelegate *formDelegate)
5035 {
5036     m_formDelegate = formDelegate;
5037     return S_OK;
5038 }
5039
5040 HRESULT STDMETHODCALLTYPE WebView::formDelegate( 
5041     /* [retval][out] */ IWebFormDelegate **formDelegate)
5042 {
5043     if (!m_formDelegate)
5044         return E_FAIL;
5045
5046     return m_formDelegate.copyRefTo(formDelegate);
5047 }
5048
5049 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegatePrivate( 
5050     /* [in] */ IWebFrameLoadDelegatePrivate* d)
5051 {
5052     m_frameLoadDelegatePrivate = d;
5053     return S_OK;
5054 }
5055
5056 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegatePrivate( 
5057     /* [out][retval] */ IWebFrameLoadDelegatePrivate** d)
5058 {
5059     if (!m_frameLoadDelegatePrivate)
5060         return E_FAIL;
5061         
5062     return m_frameLoadDelegatePrivate.copyRefTo(d);
5063 }
5064
5065 HRESULT STDMETHODCALLTYPE WebView::scrollOffset( 
5066     /* [retval][out] */ LPPOINT offset)
5067 {
5068     if (!offset)
5069         return E_POINTER;
5070     IntSize offsetIntSize = m_page->mainFrame()->view()->scrollOffset();
5071     offset->x = offsetIntSize.width();
5072     offset->y = offsetIntSize.height();
5073     return S_OK;
5074 }
5075
5076 HRESULT STDMETHODCALLTYPE WebView::scrollBy( 
5077     /* [in] */ LPPOINT offset)
5078 {
5079     if (!offset)
5080         return E_POINTER;
5081     m_page->mainFrame()->view()->scrollBy(IntSize(offset->x, offset->y));
5082     return S_OK;
5083 }
5084
5085 HRESULT STDMETHODCALLTYPE WebView::visibleContentRect( 
5086     /* [retval][out] */ LPRECT rect)
5087 {
5088     if (!rect)
5089         return E_POINTER;
5090     FloatRect visibleContent = m_page->mainFrame()->view()->visibleContentRect();
5091     rect->left = (LONG) visibleContent.x();
5092     rect->top = (LONG) visibleContent.y();
5093     rect->right = (LONG) visibleContent.maxX();
5094     rect->bottom = (LONG) visibleContent.maxY();
5095     return S_OK;
5096 }
5097
5098 static DWORD dragOperationToDragCursor(DragOperation op) {
5099     DWORD res = DROPEFFECT_NONE;
5100     if (op & DragOperationCopy) 
5101         res = DROPEFFECT_COPY;
5102     else if (op & DragOperationLink) 
5103         res = DROPEFFECT_LINK;
5104     else if (op & DragOperationMove) 
5105         res = DROPEFFECT_MOVE;
5106     else if (op & DragOperationGeneric) 
5107         res = DROPEFFECT_MOVE; //This appears to be the Firefox behaviour
5108     return res;
5109 }
5110
5111 DragOperation WebView::keyStateToDragOperation(DWORD grfKeyState) const
5112 {
5113     if (!m_page)
5114         return DragOperationNone;
5115
5116     // Conforms to Microsoft's key combinations as documented for 
5117     // IDropTarget::DragOver. Note, grfKeyState is the current 
5118     // state of the keyboard modifier keys on the keyboard. See:
5119     // <http://msdn.microsoft.com/en-us/library/ms680129(VS.85).aspx>.
5120     DragOperation operation = m_page->dragController()->sourceDragOperation();
5121
5122     if ((grfKeyState & (MK_CONTROL | MK_SHIFT)) == (MK_CONTROL | MK_SHIFT))
5123         operation = DragOperationLink;
5124     else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
5125         operation = DragOperationCopy;
5126     else if ((grfKeyState & MK_SHIFT) == MK_SHIFT)
5127         operation = DragOperationGeneric;
5128
5129     return operation;
5130 }
5131
5132 HRESULT STDMETHODCALLTYPE WebView::DragEnter(
5133         IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
5134 {
5135     m_dragData = 0;
5136
5137     if (m_dropTargetHelper)
5138         m_dropTargetHelper->DragEnter(m_viewWindow, pDataObject, (POINT*)&pt, *pdwEffect);
5139
5140     POINTL localpt = pt;
5141     ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
5142     DragData data(pDataObject, IntPoint(localpt.x, localpt.y), 
5143         IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
5144     *pdwEffect = dragOperationToDragCursor(m_page->dragController()->dragEntered(&data).operation);
5145
5146     m_lastDropEffect = *pdwEffect;
5147     m_dragData = pDataObject;
5148
5149     return S_OK;
5150 }
5151
5152 HRESULT STDMETHODCALLTYPE WebView::DragOver(
5153         DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
5154 {
5155     if (m_dropTargetHelper)
5156         m_dropTargetHelper->DragOver((POINT*)&pt, *pdwEffect);
5157
5158     if (m_dragData) {
5159         POINTL localpt = pt;
5160         ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
5161         DragData data(m_dragData.get(), IntPoint(localpt.x, localpt.y), 
5162             IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
5163         *pdwEffect = dragOperationToDragCursor(m_page->dragController()->dragUpdated(&data).operation);
5164     } else
5165         *pdwEffect = DROPEFFECT_NONE;
5166
5167     m_lastDropEffect = *pdwEffect;
5168     return S_OK;
5169 }
5170
5171 HRESULT STDMETHODCALLTYPE WebView::DragLeave()
5172 {
5173     if (m_dropTargetHelper)
5174         m_dropTargetHelper->DragLeave();
5175
5176     if (m_dragData) {
5177         DragData data(m_dragData.get(), IntPoint(), IntPoint(), 
5178             DragOperationNone);
5179         m_page->dragController()->dragExited(&data);
5180         m_dragData = 0;
5181     }
5182     return S_OK;
5183 }
5184
5185 HRESULT STDMETHODCALLTYPE WebView::Drop(
5186         IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
5187 {
5188     if (m_dropTargetHelper)
5189         m_dropTargetHelper->Drop(pDataObject, (POINT*)&pt, *pdwEffect);
5190
5191     m_dragData = 0;
5192     *pdwEffect = m_lastDropEffect;
5193     POINTL localpt = pt;
5194     ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
5195     DragData data(pDataObject, IntPoint(localpt.x, localpt.y), 
5196         IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
5197     m_page->dragController()->performDrag(&data);
5198     return S_OK;
5199 }
5200
5201 HRESULT STDMETHODCALLTYPE WebView::canHandleRequest( 
5202     IWebURLRequest *request,
5203     BOOL *result)
5204 {
5205     COMPtr<WebMutableURLRequest> requestImpl;
5206
5207     HRESULT hr = request->QueryInterface(&requestImpl);
5208     if (FAILED(hr))
5209         return hr;
5210
5211     *result = !!canHandleRequest(requestImpl->resourceRequest());
5212     return S_OK;
5213 }
5214
5215 HRESULT STDMETHODCALLTYPE WebView::standardUserAgentWithApplicationName( 
5216     BSTR applicationName,
5217     BSTR* groupName)
5218 {
5219     if (!groupName) {
5220         ASSERT_NOT_REACHED();
5221         return E_POINTER;
5222     }
5223
5224     *groupName;
5225
5226     if (!applicationName) {
5227         ASSERT_NOT_REACHED();
5228         return E_POINTER;
5229     }
5230
5231     BString applicationNameBString(applicationName);
5232     *groupName = BString(standardUserAgentWithApplicationName(String(applicationNameBString, SysStringLen(applicationNameBString)))).release();
5233     return S_OK;
5234 }
5235
5236 HRESULT STDMETHODCALLTYPE WebView::clearFocusNode()
5237 {
5238     if (m_page && m_page->focusController())
5239         m_page->focusController()->setFocusedNode(0, 0);
5240     return S_OK;
5241 }
5242
5243 HRESULT STDMETHODCALLTYPE WebView::setInitialFocus(
5244     /* [in] */ BOOL forward)
5245 {
5246     if (m_page && m_page->focusController()) {
5247         Frame* frame = m_page->focusController()->focusedOrMainFrame();
5248         frame->document()->setFocusedNode(0);
5249         m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0);
5250     }
5251     return S_OK;
5252 }
5253
5254 HRESULT STDMETHODCALLTYPE WebView::setTabKeyCyclesThroughElements( 
5255     /* [in] */ BOOL cycles)
5256 {
5257     if (m_page)
5258         m_page->setTabKeyCyclesThroughElements(!!cycles);
5259
5260     return S_OK;
5261 }
5262
5263 HRESULT STDMETHODCALLTYPE WebView::tabKeyCyclesThroughElements( 
5264     /* [retval][out] */ BOOL* result)
5265 {
5266     if (!result) {
5267         ASSERT_NOT_REACHED();
5268         return E_POINTER;
5269     }
5270
5271     *result = m_page && m_page->tabKeyCyclesThroughElements() ? TRUE : FALSE;
5272     return S_OK;
5273 }
5274
5275 HRESULT STDMETHODCALLTYPE WebView::setAllowSiteSpecificHacks(
5276     /* [in] */ BOOL allow)
5277 {
5278     s_allowSiteSpecificHacks = !!allow;
5279     // FIXME: This sets a global so it needs to call notifyPreferencesChanged
5280     // on all WebView objects (not just itself).
5281     return S_OK;
5282 }
5283
5284 HRESULT STDMETHODCALLTYPE WebView::addAdditionalPluginDirectory( 
5285         /* [in] */ BSTR directory)
5286 {
5287     PluginDatabase::installedPlugins()->addExtraPluginDirectory(String(directory, SysStringLen(directory)));
5288     return S_OK;
5289 }
5290
5291 HRESULT STDMETHODCALLTYPE WebView::loadBackForwardListFromOtherView( 
5292     /* [in] */ IWebView* otherView)
5293 {
5294     if (!m_page)
5295         return E_FAIL;
5296     
5297     // It turns out the right combination of behavior is done with the back/forward load
5298     // type.  (See behavior matrix at the top of WebFramePrivate.)  So we copy all the items
5299     // in the back forward list, and go to the current one.
5300     BackForwardList* backForwardList = m_page->backForwardList();
5301     ASSERT(!backForwardList->currentItem()); // destination list should be empty
5302
5303     COMPtr<WebView> otherWebView;
5304     if (FAILED(otherView->QueryInterface(&otherWebView)))
5305         return E_FAIL;
5306     BackForwardList* otherBackForwardList = otherWebView->m_page->backForwardList();
5307     if (!otherBackForwardList->currentItem())
5308         return S_OK; // empty back forward list, bail
5309     
5310     HistoryItem* newItemToGoTo = 0;
5311
5312     int lastItemIndex = otherBackForwardList->forwardListCount();
5313     for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
5314         if (!i) {
5315             // If this item is showing , save away its current scroll and form state,
5316             // since that might have changed since loading and it is normally not saved
5317             // until we leave that page.
5318             otherWebView->m_page->mainFrame()->loader()->history()->saveDocumentAndScrollState();
5319         }
5320         RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
5321         if (!i) 
5322             newItemToGoTo = newItem.get();
5323         backForwardList->addItem(newItem.release());
5324     }
5325     
5326     ASSERT(newItemToGoTo);
5327     m_page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
5328     return S_OK;
5329 }
5330
5331 HRESULT STDMETHODCALLTYPE WebView::clearUndoRedoOperations()
5332 {
5333     if (Frame* frame = m_page->focusController()->focusedOrMainFrame())
5334         frame->editor()->clearUndoRedoOperations();
5335     return S_OK;
5336 }
5337
5338 HRESULT STDMETHODCALLTYPE WebView::shouldClose( 
5339     /* [retval][out] */ BOOL* result)
5340 {
5341     if (!result) {
5342         ASSERT_NOT_REACHED();
5343         return E_POINTER;
5344     }
5345
5346     *result = TRUE;
5347     if (Frame* frame = m_page->mainFrame())
5348         *result = frame->loader()->shouldClose();
5349     return S_OK;
5350 }
5351
5352 HRESULT WebView::registerDragDrop()
5353 {
5354     ASSERT(::IsWindow(m_viewWindow));
5355     return ::RegisterDragDrop(m_viewWindow, this);
5356 }
5357
5358 HRESULT WebView::revokeDragDrop()
5359 {
5360     if (!m_viewWindow)
5361         return S_OK;
5362
5363     return ::RevokeDragDrop(m_viewWindow);
5364 }
5365
5366 HRESULT WebView::setProhibitsMainFrameScrolling(BOOL b)
5367 {
5368     if (!m_page)
5369         return E_FAIL;
5370
5371     m_page->mainFrame()->view()->setProhibitsScrolling(b);
5372     return S_OK;
5373 }
5374
5375 HRESULT WebView::setShouldApplyMacFontAscentHack(BOOL b)
5376 {
5377     SimpleFontData::setShouldApplyMacAscentHack(b);
5378     return S_OK;
5379 }
5380
5381 class IMMDict {
5382     typedef HIMC (CALLBACK *getContextPtr)(HWND);
5383     typedef BOOL (CALLBACK *releaseContextPtr)(HWND, HIMC);
5384     typedef LONG (CALLBACK *getCompositionStringPtr)(HIMC, DWORD, LPVOID, DWORD);
5385     typedef BOOL (CALLBACK *setCandidateWindowPtr)(HIMC, LPCANDIDATEFORM);
5386     typedef BOOL (CALLBACK *setOpenStatusPtr)(HIMC, BOOL);
5387     typedef BOOL (CALLBACK *notifyIMEPtr)(HIMC, DWORD, DWORD, DWORD);
5388     typedef BOOL (CALLBACK *associateContextExPtr)(HWND, HIMC, DWORD);
5389
5390 public:
5391     getContextPtr getContext;
5392     releaseContextPtr releaseContext;
5393     getCompositionStringPtr getCompositionString;
5394     setCandidateWindowPtr setCandidateWindow;
5395     setOpenStatusPtr setOpenStatus;
5396     notifyIMEPtr notifyIME;
5397     associateContextExPtr associateContextEx;
5398
5399     static const IMMDict& dict();
5400 private:
5401     IMMDict();
5402     HMODULE m_instance;
5403 };
5404
5405 const IMMDict& IMMDict::dict()
5406 {
5407     static IMMDict instance;
5408     return instance;
5409 }
5410
5411 IMMDict::IMMDict()
5412 {
5413     m_instance = ::LoadLibraryW(L"IMM32.DLL");
5414     getContext = reinterpret_cast<getContextPtr>(::GetProcAddress(m_instance, "ImmGetContext"));
5415     ASSERT(getContext);
5416     releaseContext = reinterpret_cast<releaseContextPtr>(::GetProcAddress(m_instance, "ImmReleaseContext"));
5417     ASSERT(releaseContext);
5418     getCompositionString = reinterpret_cast<getCompositionStringPtr>(::GetProcAddress(m_instance, "ImmGetCompositionStringW"));
5419     ASSERT(getCompositionString);
5420     setCandidateWindow = reinterpret_cast<setCandidateWindowPtr>(::GetProcAddress(m_instance, "ImmSetCandidateWindow"));
5421     ASSERT(setCandidateWindow);
5422     setOpenStatus = reinterpret_cast<setOpenStatusPtr>(::GetProcAddress(m_instance, "ImmSetOpenStatus"));
5423     ASSERT(setOpenStatus);
5424     notifyIME = reinterpret_cast<notifyIMEPtr>(::GetProcAddress(m_instance, "ImmNotifyIME"));
5425     ASSERT(notifyIME);
5426     associateContextEx = reinterpret_cast<associateContextExPtr>(::GetProcAddress(m_instance, "ImmAssociateContextEx"));
5427     ASSERT(associateContextEx);
5428 }
5429
5430 HIMC WebView::getIMMContext() 
5431 {
5432     HIMC context = IMMDict::dict().getContext(m_viewWindow);
5433     return context;
5434 }
5435
5436 void WebView::releaseIMMContext(HIMC hIMC)
5437 {
5438     if (!hIMC)
5439         return;
5440     IMMDict::dict().releaseContext(m_viewWindow, hIMC);
5441 }
5442
5443 void WebView::prepareCandidateWindow(Frame* targetFrame, HIMC hInputContext) 
5444 {
5445     IntRect caret;
5446     if (RefPtr<Range> range = targetFrame->selection()->selection().toNormalizedRange()) {
5447         ExceptionCode ec = 0;
5448         RefPtr<Range> tempRange = range->cloneRange(ec);
5449         caret = targetFrame->editor()->firstRectForRange(tempRange.get());
5450     }
5451     caret = targetFrame->view()->contentsToWindow(caret);
5452     CANDIDATEFORM form;
5453     form.dwIndex = 0;
5454     form.dwStyle = CFS_EXCLUDE;
5455     form.ptCurrentPos.x = caret.x();
5456     form.ptCurrentPos.y = caret.y() + caret.height();
5457     form.rcArea.top = caret.y();
5458     form.rcArea.bottom = caret.maxY();
5459     form.rcArea.left = caret.x();
5460     form.rcArea.right = caret.maxX();
5461     IMMDict::dict().setCandidateWindow(hInputContext, &form);
5462 }
5463
5464 void WebView::resetIME(Frame* targetFrame)
5465 {
5466     if (targetFrame)
5467         targetFrame->editor()->cancelComposition();
5468
5469     if (HIMC hInputContext = getIMMContext()) {
5470         IMMDict::dict().notifyIME(hInputContext, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
5471         releaseIMMContext(hInputContext);
5472     }
5473 }
5474
5475 void WebView::updateSelectionForIME()
5476 {
5477     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
5478     if (!targetFrame || !targetFrame->editor()->hasComposition())
5479         return;
5480     
5481     if (targetFrame->editor()->ignoreCompositionSelectionChange())
5482         return;
5483
5484     unsigned start;
5485     unsigned end;
5486     if (!targetFrame->editor()->getCompositionSelection(start, end))
5487         resetIME(targetFrame);
5488 }
5489
5490 void WebView::setInputMethodState(bool enabled)
5491 {
5492     IMMDict::dict().associateContextEx(m_viewWindow, 0, enabled ? IACE_DEFAULT : 0);
5493 }
5494
5495 void WebView::selectionChanged()
5496 {
5497     updateSelectionForIME();
5498 }
5499
5500 bool WebView::onIMEStartComposition()
5501 {
5502     LOG(TextInput, "onIMEStartComposition");
5503     m_inIMEComposition++;
5504     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
5505     if (!targetFrame)
5506         return true;
5507
5508     HIMC hInputContext = getIMMContext();
5509     prepareCandidateWindow(targetFrame, hInputContext);
5510     releaseIMMContext(hInputContext);
5511     return true;
5512 }
5513
5514 static bool getCompositionString(HIMC hInputContext, DWORD type, String& result)
5515 {
5516     int compositionLength = IMMDict::dict().getCompositionString(hInputContext, type, 0, 0);
5517     if (compositionLength <= 0)
5518         return false;
5519     Vector<UChar> compositionBuffer(compositionLength / 2);
5520     compositionLength = IMMDict::dict().getCompositionString(hInputContext, type, (LPVOID)compositionBuffer.data(), compositionLength);
5521     result = String(compositionBuffer.data(), compositionLength / 2);
5522     ASSERT(!compositionLength || compositionBuffer[0]);
5523     ASSERT(!compositionLength || compositionBuffer[compositionLength / 2 - 1]);
5524     return true;
5525 }
5526
5527 static void compositionToUnderlines(const Vector<DWORD>& clauses, const Vector<BYTE>& attributes, Vector<CompositionUnderline>& underlines)
5528 {
5529     if (clauses.isEmpty()) {
5530         underlines.clear();
5531         return;
5532     }
5533   
5534     const size_t numBoundaries = clauses.size() - 1;
5535     underlines.resize(numBoundaries);
5536     for (unsigned i = 0; i < numBoundaries; i++) {
5537         underlines[i].startOffset = clauses[i];
5538         underlines[i].endOffset = clauses[i + 1];
5539         BYTE attribute = attributes[clauses[i]];
5540         underlines[i].thick = attribute == ATTR_TARGET_CONVERTED || attribute == ATTR_TARGET_NOTCONVERTED;
5541         underlines[i].color = Color(0,0,0);
5542     }
5543 }
5544
5545 #if !LOG_DISABLED
5546 #define APPEND_ARGUMENT_NAME(name) \
5547     if (lparam & name) { \
5548         if (needsComma) \
5549             result += ", "; \
5550             result += #name; \
5551         needsComma = true; \
5552     }
5553
5554 static String imeCompositionArgumentNames(LPARAM lparam)
5555 {
5556     String result;
5557     bool needsComma = false;
5558     if (lparam & GCS_COMPATTR) {
5559         result = "GCS_COMPATTR";
5560         needsComma = true;
5561     }
5562     APPEND_ARGUMENT_NAME(GCS_COMPCLAUSE);
5563     APPEND_ARGUMENT_NAME(GCS_COMPREADSTR);
5564     APPEND_ARGUMENT_NAME(GCS_COMPREADATTR);
5565     APPEND_ARGUMENT_NAME(GCS_COMPREADCLAUSE);
5566     APPEND_ARGUMENT_NAME(GCS_COMPSTR);
5567     APPEND_ARGUMENT_NAME(GCS_CURSORPOS);
5568     APPEND_ARGUMENT_NAME(GCS_DELTASTART);
5569     APPEND_ARGUMENT_NAME(GCS_RESULTCLAUSE);
5570     APPEND_ARGUMENT_NAME(GCS_RESULTREADCLAUSE);
5571     APPEND_ARGUMENT_NAME(GCS_RESULTREADSTR);
5572     APPEND_ARGUMENT_NAME(GCS_RESULTSTR);
5573     APPEND_ARGUMENT_NAME(CS_INSERTCHAR);
5574     APPEND_ARGUMENT_NAME(CS_NOMOVECARET);
5575
5576     return result;
5577 }
5578
5579 static String imeNotificationName(WPARAM wparam)
5580 {
5581     switch (wparam) {
5582     case IMN_CHANGECANDIDATE:
5583         return "IMN_CHANGECANDIDATE";
5584     case IMN_CLOSECANDIDATE:
5585         return "IMN_CLOSECANDIDATE";
5586     case IMN_CLOSESTATUSWINDOW:
5587         return "IMN_CLOSESTATUSWINDOW";
5588     case IMN_GUIDELINE:
5589         return "IMN_GUIDELINE";
5590     case IMN_OPENCANDIDATE:
5591         return "IMN_OPENCANDIDATE";
5592     case IMN_OPENSTATUSWINDOW:
5593         return "IMN_OPENSTATUSWINDOW";
5594     case IMN_SETCANDIDATEPOS:
5595         return "IMN_SETCANDIDATEPOS";
5596     case IMN_SETCOMPOSITIONFONT:
5597         return "IMN_SETCOMPOSITIONFONT";
5598     case IMN_SETCOMPOSITIONWINDOW:
5599         return "IMN_SETCOMPOSITIONWINDOW";
5600     case IMN_SETCONVERSIONMODE:
5601         return "IMN_SETCONVERSIONMODE";
5602     case IMN_SETOPENSTATUS:
5603         return "IMN_SETOPENSTATUS";
5604     case IMN_SETSENTENCEMODE:
5605         return "IMN_SETSENTENCEMODE";
5606     case IMN_SETSTATUSWINDOWPOS:
5607         return "IMN_SETSTATUSWINDOWPOS";
5608     default:
5609         return "Unknown (" + String::number(wparam) + ")";
5610     }
5611 }
5612
5613 static String imeRequestName(WPARAM wparam)
5614 {
5615     switch (wparam) {
5616     case IMR_CANDIDATEWINDOW:
5617         return "IMR_CANDIDATEWINDOW";
5618     case IMR_COMPOSITIONFONT:
5619         return "IMR_COMPOSITIONFONT";
5620     case IMR_COMPOSITIONWINDOW:
5621         return "IMR_COMPOSITIONWINDOW";
5622     case IMR_CONFIRMRECONVERTSTRING:
5623         return "IMR_CONFIRMRECONVERTSTRING";
5624     case IMR_DOCUMENTFEED:
5625         return "IMR_DOCUMENTFEED";
5626     case IMR_QUERYCHARPOSITION:
5627         return "IMR_QUERYCHARPOSITION";
5628     case IMR_RECONVERTSTRING:
5629         return "IMR_RECONVERTSTRING";
5630     default:
5631         return "Unknown (" + String::number(wparam) + ")";
5632     }
5633 }
5634 #endif
5635
5636 bool WebView::onIMEComposition(LPARAM lparam)
5637 {
5638     LOG(TextInput, "onIMEComposition %s", imeCompositionArgumentNames(lparam).latin1().data());
5639     HIMC hInputContext = getIMMContext();
5640     if (!hInputContext)
5641         return true;
5642
5643     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
5644     if (!targetFrame || !targetFrame->editor()->canEdit())
5645         return true;
5646
5647     prepareCandidateWindow(targetFrame, hInputContext);
5648
5649     if (lparam & GCS_RESULTSTR || !lparam) {
5650         String compositionString;
5651         if (!getCompositionString(hInputContext, GCS_RESULTSTR, compositionString) && lparam)
5652             return true;
5653         
5654         targetFrame->editor()->confirmComposition(compositionString);
5655     } else {
5656         String compositionString;
5657         if (!getCompositionString(hInputContext, GCS_COMPSTR, compositionString))
5658             return true;
5659         
5660         // Composition string attributes
5661         int numAttributes = IMMDict::dict().getCompositionString(hInputContext, GCS_COMPATTR, 0, 0);
5662         Vector<BYTE> attributes(numAttributes);
5663         IMMDict::dict().getCompositionString(hInputContext, GCS_COMPATTR, attributes.data(), numAttributes);
5664
5665         // Get clauses
5666         int numClauses = IMMDict::dict().getCompositionString(hInputContext, GCS_COMPCLAUSE, 0, 0);
5667         Vector<DWORD> clauses(numClauses / sizeof(DWORD));
5668         IMMDict::dict().getCompositionString(hInputContext, GCS_COMPCLAUSE, clauses.data(), numClauses);
5669
5670         Vector<CompositionUnderline> underlines;
5671         compositionToUnderlines(clauses, attributes, underlines);
5672
5673         int cursorPosition = LOWORD(IMMDict::dict().getCompositionString(hInputContext, GCS_CURSORPOS, 0, 0));
5674
5675         targetFrame->editor()->setComposition(compositionString, underlines, cursorPosition, 0);
5676     }
5677
5678     return true;
5679 }
5680
5681 bool WebView::onIMEEndComposition()
5682 {
5683     LOG(TextInput, "onIMEEndComposition");
5684     // If the composition hasn't been confirmed yet, it needs to be cancelled.
5685     // This happens after deleting the last character from inline input hole.
5686     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
5687     if (targetFrame && targetFrame->editor()->hasComposition())
5688         targetFrame->editor()->confirmComposition(String());
5689
5690     if (m_inIMEComposition)
5691         m_inIMEComposition--;
5692
5693     return true;
5694 }
5695
5696 bool WebView::onIMEChar(WPARAM wparam, LPARAM lparam)
5697 {
5698     UNUSED_PARAM(wparam);
5699     UNUSED_PARAM(lparam);
5700     LOG(TextInput, "onIMEChar U+%04X %08X", wparam, lparam);
5701     return true;
5702 }
5703
5704 bool WebView::onIMENotify(WPARAM wparam, LPARAM, LRESULT*)
5705 {
5706     UNUSED_PARAM(wparam);
5707     LOG(TextInput, "onIMENotify %s", imeNotificationName(wparam).latin1().data());
5708     return false;
5709 }
5710
5711 LRESULT WebView::onIMERequestCharPosition(Frame* targetFrame, IMECHARPOSITION* charPos)
5712 {
5713     if (charPos->dwCharPos && !targetFrame->editor()->hasComposition())
5714         return 0;
5715     IntRect caret;
5716     if (RefPtr<Range> range = targetFrame->editor()->hasComposition() ? targetFrame->editor()->compositionRange() : targetFrame->selection()->selection().toNormalizedRange()) {
5717         ExceptionCode ec = 0;
5718         RefPtr<Range> tempRange = range->cloneRange(ec);
5719         tempRange->setStart(tempRange->startContainer(ec), tempRange->startOffset(ec) + charPos->dwCharPos, ec);
5720         caret = targetFrame->editor()->firstRectForRange(tempRange.get());
5721     }
5722     caret = targetFrame->view()->contentsToWindow(caret);
5723     charPos->pt.x = caret.x();
5724     charPos->pt.y = caret.y();
5725     ::ClientToScreen(m_viewWindow, &charPos->pt);
5726     charPos->cLineHeight = caret.height();
5727     ::GetWindowRect(m_viewWindow, &charPos->rcDocument);
5728     return true;
5729 }
5730
5731 LRESULT WebView::onIMERequestReconvertString(Frame* targetFrame, RECONVERTSTRING* reconvertString)
5732 {
5733     RefPtr<Range> selectedRange = targetFrame->selection()->toNormalizedRange();
5734     String text = selectedRange->text();
5735     if (!reconvertString)
5736         return sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar);
5737
5738     unsigned totalSize = sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar);
5739     if (totalSize > reconvertString->dwSize)
5740         return 0;
5741     reconvertString->dwCompStrLen = text.length();
5742     reconvertString->dwStrLen = text.length();
5743     reconvertString->dwTargetStrLen = text.length();
5744     reconvertString->dwStrOffset = sizeof(RECONVERTSTRING);
5745     memcpy(reconvertString + 1, text.characters(), text.length() * sizeof(UChar));
5746     return totalSize;
5747 }
5748
5749 LRESULT WebView::onIMERequest(WPARAM request, LPARAM data)
5750 {
5751     LOG(TextInput, "onIMERequest %s", imeRequestName(request).latin1().data());
5752     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
5753     if (!targetFrame || !targetFrame->editor()->canEdit())
5754         return 0;
5755
5756     switch (request) {
5757         case IMR_RECONVERTSTRING:
5758             return onIMERequestReconvertString(targetFrame, (RECONVERTSTRING*)data);
5759
5760         case IMR_QUERYCHARPOSITION:
5761             return onIMERequestCharPosition(targetFrame, (IMECHARPOSITION*)data);
5762     }
5763     return 0;
5764 }
5765
5766 bool WebView::onIMESelect(WPARAM wparam, LPARAM lparam)
5767 {
5768     UNUSED_PARAM(wparam);
5769     UNUSED_PARAM(lparam);
5770     LOG(TextInput, "onIMESelect locale %ld %s", lparam, wparam ? "select" : "deselect");
5771     return false;
5772 }
5773
5774 bool WebView::onIMESetContext(WPARAM wparam, LPARAM)
5775 {
5776     LOG(TextInput, "onIMESetContext %s", wparam ? "active" : "inactive");
5777     return false;
5778 }
5779
5780 HRESULT STDMETHODCALLTYPE WebView::inspector(IWebInspector** inspector)
5781 {
5782 #if ENABLE(INSPECTOR)
5783     if (!m_webInspector)
5784         m_webInspector.adoptRef(WebInspector::createInstance(this, m_inspectorClient));
5785
5786     return m_webInspector.copyRefTo(inspector);
5787 #else // !ENABLE(INSPECTOR)
5788     return S_OK;
5789 #endif // ENABLE(INSPECTOR)
5790 }
5791
5792
5793 HRESULT STDMETHODCALLTYPE WebView::windowAncestryDidChange()
5794 {
5795     HWND newParent;
5796     if (m_viewWindow)
5797         newParent = findTopLevelParent(m_hostWindow);
5798     else {
5799         // There's no point in tracking active state changes of our parent window if we don't have
5800         // a window ourselves.
5801         newParent = 0;
5802     }
5803
5804     if (newParent == m_topLevelParent)
5805         return S_OK;
5806
5807     if (m_topLevelParent)
5808         WindowMessageBroadcaster::removeListener(m_topLevelParent, this);
5809
5810     m_topLevelParent = newParent;
5811
5812     if (m_topLevelParent)
5813         WindowMessageBroadcaster::addListener(m_topLevelParent, this);
5814
5815     updateActiveState();
5816
5817     return S_OK;
5818 }
5819
5820 HRESULT STDMETHODCALLTYPE WebView::paintDocumentRectToContext(
5821     /* [in] */ RECT rect,
5822     /* [in] */ OLE_HANDLE deviceContext)
5823 {
5824     if (!deviceContext)
5825         return E_POINTER;
5826
5827     if (!m_mainFrame)
5828         return E_FAIL;
5829
5830     return m_mainFrame->paintDocumentRectToContext(rect, deviceContext);
5831 }
5832
5833 HRESULT STDMETHODCALLTYPE WebView::paintScrollViewRectToContextAtPoint(
5834     /* [in] */ RECT rect,
5835     /* [in] */ POINT pt,
5836     /* [in] */ OLE_HANDLE deviceContext)
5837 {
5838     if (!deviceContext)
5839         return E_POINTER;
5840
5841     if (!m_mainFrame)
5842         return E_FAIL;
5843
5844     return m_mainFrame->paintScrollViewRectToContextAtPoint(rect, pt, deviceContext);
5845 }
5846
5847 HRESULT STDMETHODCALLTYPE WebView::reportException(
5848     /* [in] */ JSContextRef context,
5849     /* [in] */ JSValueRef exception)
5850 {
5851     if (!context || !exception)
5852         return E_FAIL;
5853
5854     JSC::ExecState* execState = toJS(context);
5855     JSC::JSLockHolder lock(execState);
5856
5857     // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a WebView.
5858     if (!toJSDOMWindow(execState->lexicalGlobalObject()))
5859         return E_FAIL;
5860
5861     WebCore::reportException(execState, toJS(execState, exception));
5862     return S_OK;
5863 }
5864
5865 HRESULT STDMETHODCALLTYPE WebView::elementFromJS(
5866     /* [in] */ JSContextRef context,
5867     /* [in] */ JSValueRef nodeObject,
5868     /* [retval][out] */ IDOMElement **element)
5869 {
5870     if (!element)
5871         return E_POINTER;
5872
5873     *element = 0;
5874
5875     if (!context)
5876         return E_FAIL;
5877
5878     if (!nodeObject)
5879         return E_FAIL;
5880
5881     JSC::ExecState* exec = toJS(context);
5882     JSC::JSLockHolder lock(exec);
5883     Element* elt = toElement(toJS(exec, nodeObject));
5884     if (!elt)
5885         return E_FAIL;
5886
5887     *element = DOMElement::createInstance(elt);
5888     return S_OK;
5889 }
5890
5891 HRESULT STDMETHODCALLTYPE WebView::setCustomHTMLTokenizerTimeDelay(
5892     /* [in] */ double timeDelay)
5893 {
5894     if (!m_page)
5895         return E_FAIL;
5896
5897     m_page->setCustomHTMLTokenizerTimeDelay(timeDelay);
5898     return S_OK;
5899 }
5900
5901 HRESULT STDMETHODCALLTYPE WebView::setCustomHTMLTokenizerChunkSize(
5902     /* [in] */ int chunkSize)
5903 {
5904     if (!m_page)
5905         return E_FAIL;
5906
5907     m_page->setCustomHTMLTokenizerChunkSize(chunkSize);
5908     return S_OK;
5909 }
5910
5911 HRESULT STDMETHODCALLTYPE WebView::backingStore(
5912     /* [out, retval] */ OLE_HANDLE* hBitmap)
5913 {
5914     if (!hBitmap)
5915         return E_POINTER;
5916     if (!m_backingStoreBitmap)
5917         return E_FAIL;
5918     *hBitmap = reinterpret_cast<OLE_HANDLE>(m_backingStoreBitmap->handle());
5919     return S_OK;
5920 }
5921
5922 HRESULT STDMETHODCALLTYPE WebView::setTransparent(BOOL transparent)
5923 {
5924     if (m_transparent == !!transparent)
5925         return S_OK;
5926
5927     m_transparent = transparent;
5928     m_mainFrame->updateBackground();
5929     return S_OK;
5930 }
5931
5932 HRESULT STDMETHODCALLTYPE WebView::transparent(BOOL* transparent)
5933 {
5934     if (!transparent)
5935         return E_POINTER;
5936
5937     *transparent = this->transparent() ? TRUE : FALSE;
5938     return S_OK;
5939 }
5940
5941 static bool setWindowStyle(HWND window, int index, LONG_PTR newValue)
5942 {
5943     // According to MSDN, if the last value of the flag we are setting was zero,
5944     // then SetWindowLongPtr returns zero, even though the call succeeded. So,
5945     // we have to clear the error state, then check the last error after
5946     // setting the value to see if it actually was a failure.
5947     ::SetLastError(0);
5948     return ::SetWindowLongPtr(window, index, newValue) || !::GetLastError();
5949 }
5950
5951 HRESULT WebView::setUsesLayeredWindow(BOOL usesLayeredWindow)
5952 {
5953     if (m_usesLayeredWindow == !!usesLayeredWindow)
5954         return S_OK;
5955
5956     if (!m_viewWindow)
5957         return E_FAIL;
5958
5959     RECT rect;
5960     ::GetWindowRect(m_viewWindow, &rect);
5961
5962     LONG_PTR origExStyle = ::GetWindowLongPtr(m_viewWindow, GWL_EXSTYLE);
5963     LONG_PTR origStyle = ::GetWindowLongPtr(m_viewWindow, GWL_STYLE);
5964
5965     // The logic here has to account for the way SetParent works.
5966     // According to MSDN, to go from a child window to a popup window,
5967     // you must clear the child bit after setting the parent to 0.
5968     // On the other hand, to go from a popup window to a child, you
5969     // must clear the popup state before setting the parent.
5970     if (usesLayeredWindow) {
5971         LONG_PTR newExStyle = origExStyle | WS_EX_LAYERED;
5972         LONG_PTR newStyle = (origStyle & ~(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)) | WS_POPUP;
5973
5974         HWND origParent = ::SetParent(m_viewWindow, 0);
5975
5976         if (!setWindowStyle(m_viewWindow, GWL_STYLE, newStyle)) {
5977             ::SetParent(m_viewWindow, origParent);
5978             return E_FAIL;
5979         }
5980
5981         if (!setWindowStyle(m_viewWindow, GWL_EXSTYLE, newExStyle)) {
5982             setWindowStyle(m_viewWindow, GWL_STYLE, origStyle);
5983             ::SetParent(m_viewWindow, origParent);
5984             return E_FAIL;
5985         }
5986     } else {
5987         LONG_PTR newExStyle = origExStyle & ~WS_EX_LAYERED;
5988         LONG_PTR newStyle = (origStyle & ~WS_POPUP) | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
5989
5990         if (!setWindowStyle(m_viewWindow, GWL_EXSTYLE, newExStyle))
5991             return E_FAIL;
5992
5993         if (!setWindowStyle(m_viewWindow, GWL_STYLE, newStyle)) {
5994             setWindowStyle(m_viewWindow, GWL_EXSTYLE, origExStyle);
5995             return E_FAIL;
5996         }
5997
5998         ::SetParent(m_viewWindow, m_hostWindow ? m_hostWindow : HWND_MESSAGE);
5999     }
6000
6001     // MSDN indicates that SetWindowLongPtr doesn't take effect for some settings until a
6002     // SetWindowPos is called.
6003     ::SetWindowPos(m_viewWindow, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
6004         SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
6005
6006     m_usesLayeredWindow = usesLayeredWindow;
6007     return S_OK;
6008 }
6009
6010 HRESULT WebView::usesLayeredWindow(BOOL* usesLayeredWindow)
6011 {
6012     if (!usesLayeredWindow)
6013         return E_POINTER;
6014
6015     *usesLayeredWindow = this->usesLayeredWindow() ? TRUE : FALSE;
6016     return S_OK;
6017 }
6018
6019 HRESULT STDMETHODCALLTYPE WebView::setCookieEnabled(BOOL enable)
6020 {
6021     if (!m_page)
6022         return E_FAIL;
6023
6024     m_page->settings()->setCookieEnabled(enable);
6025     return S_OK;
6026 }
6027
6028 HRESULT STDMETHODCALLTYPE WebView::cookieEnabled(BOOL* enabled)
6029 {
6030     if (!enabled)
6031         return E_POINTER;
6032
6033     if (!m_page)
6034         return E_FAIL;
6035
6036     *enabled = m_page->settings()->cookieEnabled();
6037     return S_OK;
6038 }
6039
6040 HRESULT STDMETHODCALLTYPE WebView::setMediaVolume(float volume)
6041 {
6042     if (!m_page)
6043         return E_FAIL;
6044
6045     m_page->setMediaVolume(volume);
6046     return S_OK;
6047 }
6048
6049 HRESULT STDMETHODCALLTYPE WebView::mediaVolume(float* volume)
6050 {
6051     if (!volume)
6052         return E_POINTER;
6053
6054     if (!m_page)
6055         return E_FAIL;
6056
6057     *volume = m_page->mediaVolume();
6058     return S_OK;
6059 }
6060
6061 HRESULT STDMETHODCALLTYPE WebView::setDefersCallbacks(BOOL defersCallbacks)
6062 {
6063     if (!m_page)
6064         return E_FAIL;
6065
6066     m_page->setDefersLoading(defersCallbacks);
6067     return S_OK;
6068 }
6069
6070 HRESULT STDMETHODCALLTYPE WebView::defersCallbacks(BOOL* defersCallbacks)
6071 {
6072     if (!defersCallbacks)
6073         return E_POINTER;
6074
6075     if (!m_page)
6076         return E_FAIL;
6077
6078     *defersCallbacks = m_page->defersLoading();
6079     return S_OK;
6080 }
6081
6082 HRESULT STDMETHODCALLTYPE WebView::globalHistoryItem(IWebHistoryItem** item)
6083 {
6084     if (!item)
6085         return E_POINTER;
6086
6087     if (!m_page)
6088         return E_FAIL;
6089
6090     if (!m_globalHistoryItem) {
6091         *item = 0;
6092         return S_OK;
6093     }
6094
6095     *item = WebHistoryItem::createInstance(m_globalHistoryItem);
6096     return S_OK;
6097 }
6098
6099 HRESULT STDMETHODCALLTYPE WebView::setAlwaysUsesComplexTextCodePath(BOOL complex)
6100 {
6101     WebCoreSetAlwaysUsesComplexTextCodePath(complex);
6102
6103     return S_OK;
6104 }
6105
6106 HRESULT STDMETHODCALLTYPE WebView::alwaysUsesComplexTextCodePath(BOOL* complex)
6107 {
6108     if (!complex)
6109         return E_POINTER;
6110
6111     *complex = WebCoreAlwaysUsesComplexTextCodePath();
6112     return S_OK;
6113 }
6114
6115 HRESULT STDMETHODCALLTYPE WebView::registerEmbeddedViewMIMEType(BSTR mimeType)
6116 {
6117     if (!mimeType)
6118         return E_POINTER;
6119
6120     if (!m_embeddedViewMIMETypes)
6121         m_embeddedViewMIMETypes = adoptPtr(new HashSet<String>);
6122
6123     m_embeddedViewMIMETypes->add(String(mimeType, ::SysStringLen(mimeType)));
6124     return S_OK;
6125 }
6126
6127 bool WebView::shouldUseEmbeddedView(const WTF::String& mimeType) const
6128 {
6129     if (!m_embeddedViewMIMETypes)
6130         return false;
6131
6132     return m_embeddedViewMIMETypes->contains(mimeType);
6133 }
6134
6135 bool WebView::onGetObject(WPARAM wParam, LPARAM lParam, LRESULT& lResult) const
6136 {
6137     lResult = 0;
6138
6139     if (lParam != OBJID_CLIENT)
6140         return false;
6141
6142     AXObjectCache::enableAccessibility();
6143
6144     // Get the accessible object for the top-level frame.
6145     WebFrame* mainFrameImpl = topLevelFrame();
6146     if (!mainFrameImpl)
6147         return false;
6148
6149     COMPtr<IAccessible> accessible = mainFrameImpl->accessible();
6150     if (!accessible)
6151         return false;
6152
6153     if (!accessibilityLib) {
6154         if (!(accessibilityLib = ::LoadLibraryW(L"oleacc.dll")))
6155             return false;
6156     }
6157
6158     static LPFNLRESULTFROMOBJECT procPtr = reinterpret_cast<LPFNLRESULTFROMOBJECT>(::GetProcAddress(accessibilityLib, "LresultFromObject"));
6159     if (!procPtr)
6160         return false;
6161
6162     // LresultFromObject returns a reference to the accessible object, stored
6163     // in an LRESULT. If this call is not successful, Windows will handle the
6164     // request through DefWindowProc.
6165     return SUCCEEDED(lResult = procPtr(__uuidof(IAccessible), wParam, accessible.get()));
6166 }
6167
6168 STDMETHODIMP WebView::AccessibleObjectFromWindow(HWND hwnd, DWORD objectID, REFIID riid, void** ppObject)
6169 {
6170     ASSERT(accessibilityLib);
6171     static LPFNACCESSIBLEOBJECTFROMWINDOW procPtr = reinterpret_cast<LPFNACCESSIBLEOBJECTFROMWINDOW>(::GetProcAddress(accessibilityLib, "AccessibleObjectFromWindow"));
6172     if (!procPtr)
6173         return E_FAIL;
6174     return procPtr(hwnd, objectID, riid, ppObject);
6175 }
6176
6177 HRESULT WebView::setMemoryCacheDelegateCallsEnabled(BOOL enabled)
6178 {
6179     m_page->setMemoryCacheClientCallsEnabled(enabled);
6180     return S_OK;
6181 }
6182
6183 HRESULT WebView::setJavaScriptURLsAreAllowed(BOOL areAllowed)
6184 {
6185     m_page->setJavaScriptURLsAreAllowed(areAllowed);
6186     return S_OK;
6187 }
6188
6189 HRESULT WebView::setCanStartPlugins(BOOL canStartPlugins)
6190 {
6191     m_page->setCanStartMedia(canStartPlugins);
6192     return S_OK;
6193 }
6194
6195 static String toString(BSTR bstr)
6196 {
6197     return String(bstr, SysStringLen(bstr));
6198 }
6199
6200 static KURL toKURL(BSTR bstr)
6201 {
6202     return KURL(KURL(), toString(bstr));
6203 }
6204
6205 void WebView::enterFullscreenForNode(Node* node)
6206 {
6207     if (!node->hasTagName(HTMLNames::videoTag) || !node->isElementNode())
6208         return;
6209
6210 #if ENABLE(VIDEO)
6211     if (!static_cast<Element*>(node)->isMediaElement())
6212         return;
6213     HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
6214
6215     if (m_fullScreenVideoController) {
6216         if (m_fullScreenVideoController->mediaElement() == videoElement) {
6217             // The backend may just warn us that the underlaying plaftormMovie()
6218             // has changed. Just force an update.
6219             m_fullScreenVideoController->setMediaElement(videoElement);
6220             return; // No more to do.
6221         }
6222
6223         // First exit Fullscreen for the old mediaElement.
6224         m_fullScreenVideoController->mediaElement()->exitFullscreen();
6225         // This previous call has to trigger exitFullscreen,
6226         // which has to clear m_fullScreenVideoController.
6227         ASSERT(!m_fullScreenVideoController);
6228     }
6229
6230     m_fullScreenVideoController = adoptPtr(new FullscreenVideoController);
6231     m_fullScreenVideoController->setMediaElement(videoElement);
6232     m_fullScreenVideoController->enterFullscreen();
6233 #endif
6234 }
6235
6236 void WebView::exitFullscreen()
6237 {
6238 #if ENABLE(VIDEO)
6239     if (m_fullScreenVideoController)
6240         m_fullScreenVideoController->exitFullscreen();
6241     
6242 #endif
6243 }
6244
6245 static PassOwnPtr<Vector<String> > toStringVector(unsigned patternsCount, BSTR* patterns)
6246 {
6247     // Convert the patterns into a Vector.
6248     if (patternsCount == 0)
6249         return nullptr;
6250     OwnPtr<Vector<String> > patternsVector = adoptPtr(new Vector<String>);
6251     for (unsigned i = 0; i < patternsCount; ++i)
6252         patternsVector->append(toString(patterns[i]));
6253     return patternsVector.release();
6254 }
6255
6256 HRESULT WebView::addUserScriptToGroup(BSTR groupName, IWebScriptWorld* iWorld, BSTR source, BSTR url, 
6257                                       unsigned whitelistCount, BSTR* whitelist,
6258                                       unsigned blacklistCount, BSTR* blacklist,
6259                                       WebUserScriptInjectionTime injectionTime)
6260 {
6261     COMPtr<WebScriptWorld> world(Query, iWorld);
6262     if (!world)
6263         return E_POINTER;
6264
6265     String group = toString(groupName);
6266     if (group.isEmpty())
6267         return E_INVALIDARG;
6268
6269     PageGroup* pageGroup = PageGroup::pageGroup(group);
6270     ASSERT(pageGroup);
6271     if (!pageGroup)
6272         return E_FAIL;
6273
6274     pageGroup->addUserScriptToWorld(world->world(), toString(source), toKURL(url),
6275                                     toStringVector(whitelistCount, whitelist), toStringVector(blacklistCount, blacklist),
6276                                     injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd,
6277                                     InjectInAllFrames);
6278
6279     return S_OK;
6280 }
6281
6282 HRESULT WebView::addUserStyleSheetToGroup(BSTR groupName, IWebScriptWorld* iWorld, BSTR source, BSTR url,
6283                                           unsigned whitelistCount, BSTR* whitelist,
6284                                           unsigned blacklistCount, BSTR* blacklist)
6285 {
6286     COMPtr<WebScriptWorld> world(Query, iWorld);
6287     if (!world)
6288         return E_POINTER;
6289
6290     String group = toString(groupName);
6291     if (group.isEmpty())
6292         return E_INVALIDARG;
6293
6294     PageGroup* pageGroup = PageGroup::pageGroup(group);
6295     ASSERT(pageGroup);
6296     if (!pageGroup)
6297         return E_FAIL;
6298
6299     pageGroup->addUserStyleSheetToWorld(world->world(), toString(source), toKURL(url),
6300                                         toStringVector(whitelistCount, whitelist), toStringVector(blacklistCount, blacklist),
6301                                         InjectInAllFrames);
6302
6303     return S_OK;
6304 }
6305
6306 HRESULT WebView::removeUserScriptFromGroup(BSTR groupName, IWebScriptWorld* iWorld, BSTR url)
6307 {
6308     COMPtr<WebScriptWorld> world(Query, iWorld);
6309     if (!world)
6310         return E_POINTER;
6311
6312     String group = toString(groupName);
6313     if (group.isEmpty())
6314         return E_INVALIDARG;
6315
6316     PageGroup* pageGroup = PageGroup::pageGroup(group);
6317     ASSERT(pageGroup);
6318     if (!pageGroup)
6319         return E_FAIL;
6320
6321     pageGroup->removeUserScriptFromWorld(world->world(), toKURL(url));
6322
6323     return S_OK;
6324 }
6325
6326 HRESULT WebView::removeUserStyleSheetFromGroup(BSTR groupName, IWebScriptWorld* iWorld, BSTR url)
6327 {
6328     COMPtr<WebScriptWorld> world(Query, iWorld);
6329     if (!world)
6330         return E_POINTER;
6331
6332     String group = toString(groupName);
6333     if (group.isEmpty())
6334         return E_INVALIDARG;
6335
6336     PageGroup* pageGroup = PageGroup::pageGroup(group);
6337     ASSERT(pageGroup);
6338     if (!pageGroup)
6339         return E_FAIL;
6340
6341     pageGroup->removeUserStyleSheetFromWorld(world->world(), toKURL(url));
6342
6343     return S_OK;
6344 }
6345
6346 HRESULT WebView::removeUserScriptsFromGroup(BSTR groupName, IWebScriptWorld* iWorld)
6347 {
6348     COMPtr<WebScriptWorld> world(Query, iWorld);
6349     if (!world)
6350         return E_POINTER;
6351
6352     String group = toString(groupName);
6353     if (group.isEmpty())
6354         return E_INVALIDARG;
6355
6356     PageGroup* pageGroup = PageGroup::pageGroup(group);
6357     ASSERT(pageGroup);
6358     if (!pageGroup)
6359         return E_FAIL;
6360
6361     pageGroup->removeUserScriptsFromWorld(world->world());
6362     return S_OK;
6363 }
6364
6365 HRESULT WebView::removeUserStyleSheetsFromGroup(BSTR groupName, IWebScriptWorld* iWorld)
6366 {
6367     COMPtr<WebScriptWorld> world(Query, iWorld);
6368     if (!world)
6369         return E_POINTER;
6370
6371     String group = toString(groupName);
6372     if (group.isEmpty())
6373         return E_INVALIDARG;
6374
6375     PageGroup* pageGroup = PageGroup::pageGroup(group);
6376     ASSERT(pageGroup);
6377     if (!pageGroup)
6378         return E_FAIL;
6379
6380     pageGroup->removeUserStyleSheetsFromWorld(world->world());
6381     return S_OK;
6382 }
6383
6384 HRESULT WebView::removeAllUserContentFromGroup(BSTR groupName)
6385 {
6386     String group = toString(groupName);
6387     if (group.isEmpty())
6388         return E_INVALIDARG;
6389
6390     PageGroup* pageGroup = PageGroup::pageGroup(group);
6391     ASSERT(pageGroup);
6392     if (!pageGroup)
6393         return E_FAIL;
6394
6395     pageGroup->removeAllUserContent();
6396     return S_OK;
6397 }
6398
6399 HRESULT WebView::invalidateBackingStore(const RECT* rect)
6400 {
6401     if (!IsWindow(m_viewWindow))
6402         return S_OK;
6403
6404     RECT clientRect;
6405     if (!GetClientRect(m_viewWindow, &clientRect))
6406         return E_FAIL;
6407
6408     RECT rectToInvalidate;
6409     if (!rect)
6410         rectToInvalidate = clientRect;
6411     else if (!IntersectRect(&rectToInvalidate, &clientRect, rect))
6412         return S_OK;
6413
6414     repaint(rectToInvalidate, true);
6415     return S_OK;
6416 }
6417
6418 HRESULT WebView::addOriginAccessWhitelistEntry(BSTR sourceOrigin, BSTR destinationProtocol, BSTR destinationHost, BOOL allowDestinationSubdomains)
6419 {
6420     SecurityPolicy::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(String(sourceOrigin, SysStringLen(sourceOrigin))), String(destinationProtocol, SysStringLen(destinationProtocol)), String(destinationHost, SysStringLen(destinationHost)), allowDestinationSubdomains);
6421     return S_OK;
6422 }
6423
6424 HRESULT WebView::removeOriginAccessWhitelistEntry(BSTR sourceOrigin, BSTR destinationProtocol, BSTR destinationHost, BOOL allowDestinationSubdomains)
6425 {
6426     SecurityPolicy::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(String(sourceOrigin, SysStringLen(sourceOrigin))), String(destinationProtocol, SysStringLen(destinationProtocol)), String(destinationHost, SysStringLen(destinationHost)), allowDestinationSubdomains);
6427     return S_OK;
6428 }
6429
6430 HRESULT WebView::resetOriginAccessWhitelists()
6431 {
6432     SecurityPolicy::resetOriginAccessWhitelists();
6433     return S_OK;
6434 }
6435  
6436 HRESULT WebView::setHistoryDelegate(IWebHistoryDelegate* historyDelegate)
6437 {
6438     m_historyDelegate = historyDelegate;
6439     return S_OK;
6440 }
6441
6442 HRESULT WebView::historyDelegate(IWebHistoryDelegate** historyDelegate)
6443 {
6444     if (!historyDelegate)
6445         return E_POINTER;
6446
6447     return m_historyDelegate.copyRefTo(historyDelegate);
6448 }
6449
6450 HRESULT WebView::addVisitedLinks(BSTR* visitedURLs, unsigned visitedURLCount)
6451 {
6452     PageGroup& group = core(this)->group();
6453     
6454     for (unsigned i = 0; i < visitedURLCount; ++i) {
6455         BSTR url = visitedURLs[i];
6456         unsigned length = SysStringLen(url);
6457         group.addVisitedLink(url, length);
6458     }
6459
6460     return S_OK;
6461 }
6462
6463 void WebView::downloadURL(const KURL& url)
6464 {
6465     // It's the delegate's job to ref the WebDownload to keep it alive - otherwise it will be
6466     // destroyed when this function returns.
6467     COMPtr<WebDownload> download(AdoptCOM, WebDownload::createInstance(url, m_downloadDelegate.get()));
6468     download->start();
6469 }
6470
6471 #if USE(ACCELERATED_COMPOSITING)
6472 void WebView::setRootChildLayer(GraphicsLayer* layer)
6473 {
6474     setAcceleratedCompositing(layer ? true : false);
6475     if (!m_backingLayer)
6476         return;
6477     m_backingLayer->addChild(layer);
6478 }
6479
6480 void WebView::flushPendingGraphicsLayerChangesSoon()
6481 {
6482     if (!m_layerTreeHost)
6483         return;
6484     m_layerTreeHost->flushPendingGraphicsLayerChangesSoon();
6485 }
6486
6487 void WebView::setAcceleratedCompositing(bool accelerated)
6488 {
6489     if (m_isAcceleratedCompositing == accelerated || !CACFLayerTreeHost::acceleratedCompositingAvailable())
6490         return;
6491
6492     if (accelerated) {
6493         m_layerTreeHost = CACFLayerTreeHost::create();
6494         if (m_layerTreeHost) {
6495             m_isAcceleratedCompositing = true;
6496
6497             m_layerTreeHost->setShouldInvertColors(m_shouldInvertColors);
6498
6499             m_layerTreeHost->setClient(this);
6500             ASSERT(m_viewWindow);
6501             m_layerTreeHost->setWindow(m_viewWindow);
6502
6503             // FIXME: We could perhaps get better performance by never allowing this layer to
6504             // become tiled (or choosing a higher-than-normal tiling threshold).
6505             // <http://webkit.org/b/52603>
6506             m_backingLayer = GraphicsLayer::create(this);
6507             m_backingLayer->setDrawsContent(true);
6508             m_backingLayer->setContentsOpaque(true);
6509             RECT clientRect;
6510             ::GetClientRect(m_viewWindow, &clientRect);
6511             m_backingLayer->setSize(IntRect(clientRect).size());
6512             m_backingLayer->setNeedsDisplay();
6513
6514             m_layerTreeHost->setRootChildLayer(PlatformCALayer::platformCALayer(m_backingLayer->platformLayer()));
6515
6516             // We aren't going to be using our backing store while we're in accelerated compositing
6517             // mode. But don't delete it immediately, in case we switch out of accelerated
6518             // compositing mode soon (e.g., if we're only compositing for a :hover animation).
6519             deleteBackingStoreSoon();
6520         }
6521     } else {
6522         ASSERT(m_layerTreeHost);
6523         m_layerTreeHost->setClient(0);
6524         m_layerTreeHost->setWindow(0);
6525         m_layerTreeHost = 0;
6526         m_backingLayer = nullptr;
6527         m_isAcceleratedCompositing = false;
6528     }
6529 }
6530 #endif
6531
6532 #if PLATFORM(WIN) && USE(AVFOUNDATION)
6533 WebCore::GraphicsDeviceAdapter* WebView::graphicsDeviceAdapter() const
6534 {
6535     if (!m_layerTreeHost)
6536         return 0;
6537     return m_layerTreeHost->graphicsDeviceAdapter();
6538 }
6539 #endif
6540
6541 HRESULT WebView::unused1()
6542 {
6543     ASSERT_NOT_REACHED();
6544     return E_FAIL;
6545 }
6546
6547 HRESULT WebView::unused2()
6548 {
6549     ASSERT_NOT_REACHED();
6550     return E_FAIL;
6551 }
6552
6553 HRESULT WebView::unused3()
6554 {
6555     ASSERT_NOT_REACHED();
6556     return E_FAIL;
6557 }
6558
6559 HRESULT WebView::unused4()
6560 {
6561     ASSERT_NOT_REACHED();
6562     return E_FAIL;
6563 }
6564
6565 HRESULT WebView::unused5()
6566 {
6567     ASSERT_NOT_REACHED();
6568     return E_FAIL;
6569 }
6570
6571 HRESULT WebView::setGeolocationProvider(IWebGeolocationProvider* locationProvider)
6572 {
6573     m_geolocationProvider = locationProvider;
6574     return S_OK;
6575 }
6576
6577 HRESULT WebView::geolocationProvider(IWebGeolocationProvider** locationProvider)
6578 {
6579     if (!locationProvider)
6580         return E_POINTER;
6581
6582     if (!m_geolocationProvider)
6583         return E_FAIL;
6584
6585     return m_geolocationProvider.copyRefTo(locationProvider);
6586 }
6587
6588 HRESULT WebView::geolocationDidChangePosition(IWebGeolocationPosition* position)
6589 {
6590     if (!m_page)
6591         return E_FAIL;
6592     GeolocationController::from(m_page)->positionChanged(core(position));
6593     return S_OK;
6594 }
6595
6596 HRESULT WebView::geolocationDidFailWithError(IWebError* error)
6597 {
6598     if (!m_page)
6599         return E_FAIL;
6600     if (!error)
6601         return E_POINTER;
6602
6603     BSTR descriptionBSTR;
6604     if (FAILED(error->localizedDescription(&descriptionBSTR)))
6605         return E_FAIL;
6606     String descriptionString(descriptionBSTR, SysStringLen(descriptionBSTR));
6607     SysFreeString(descriptionBSTR);
6608
6609     RefPtr<GeolocationError> geolocationError = GeolocationError::create(GeolocationError::PositionUnavailable, descriptionString);
6610     GeolocationController::from(m_page)->errorOccurred(geolocationError.get());
6611     return S_OK;
6612 }
6613
6614 HRESULT WebView::setDomainRelaxationForbiddenForURLScheme(BOOL forbidden, BSTR scheme)
6615 {
6616     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden, String(scheme, SysStringLen(scheme)));
6617     return S_OK;
6618 }
6619
6620 HRESULT WebView::registerURLSchemeAsSecure(BSTR scheme)
6621 {
6622     SchemeRegistry::registerURLSchemeAsSecure(toString(scheme));
6623     return S_OK;
6624 }
6625
6626 HRESULT WebView::registerURLSchemeAsAllowingLocalStorageAccessInPrivateBrowsing(BSTR scheme)
6627 {
6628     SchemeRegistry::registerURLSchemeAsAllowingLocalStorageAccessInPrivateBrowsing(toString(scheme));
6629     return S_OK;
6630 }
6631
6632 HRESULT WebView::registerURLSchemeAsAllowingDatabaseAccessInPrivateBrowsing(BSTR scheme)
6633 {
6634     SchemeRegistry::registerURLSchemeAsAllowingDatabaseAccessInPrivateBrowsing(toString(scheme));
6635     return S_OK;
6636 }
6637
6638 HRESULT WebView::nextDisplayIsSynchronous()
6639 {
6640     m_nextDisplayIsSynchronous = true;
6641     return S_OK;
6642 }
6643
6644 #if USE(ACCELERATED_COMPOSITING)
6645 void WebView::notifyAnimationStarted(const GraphicsLayer*, double)
6646 {
6647     // We never set any animations on our backing layer.
6648     ASSERT_NOT_REACHED();
6649 }
6650
6651 void WebView::notifySyncRequired(const GraphicsLayer*)
6652 {
6653     flushPendingGraphicsLayerChangesSoon();
6654 }
6655
6656 void WebView::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& inClip)
6657 {
6658     Frame* frame = core(m_mainFrame);
6659     if (!frame)
6660         return;
6661
6662     context.save();
6663     context.clip(inClip);
6664     frame->view()->paint(&context, inClip);
6665     context.restore();
6666 }
6667
6668 bool WebView::showDebugBorders(const GraphicsLayer*) const
6669 {
6670     return m_page->settings()->showDebugBorders();
6671 }
6672
6673 bool WebView::showRepaintCounter(const GraphicsLayer*) const
6674 {
6675     return m_page->settings()->showRepaintCounter();
6676 }
6677
6678 void WebView::flushPendingGraphicsLayerChanges()
6679 {
6680     Frame* coreFrame = core(m_mainFrame);
6681     if (!coreFrame)
6682         return;
6683     FrameView* view = coreFrame->view();
6684     if (!view)
6685         return;
6686     if (!m_backingLayer)
6687         return;
6688
6689     view->updateLayoutAndStyleIfNeededRecursive();
6690
6691     // Updating layout might have taken us out of compositing mode.
6692     if (m_backingLayer)
6693         m_backingLayer->syncCompositingStateForThisLayerOnly();
6694
6695     view->syncCompositingStateIncludingSubframes();
6696 }
6697
6698 #endif
6699
6700 class EnumTextMatches : public IEnumTextMatches
6701 {
6702     long m_ref;
6703     UINT m_index;
6704     Vector<IntRect> m_rects;
6705 public:
6706     EnumTextMatches(Vector<IntRect>* rects) : m_index(0), m_ref(1)
6707     {
6708         m_rects = *rects;
6709     }
6710
6711     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv)
6712     {
6713         if (IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IEnumTextMatches)) {
6714             *ppv = this;
6715             AddRef();
6716         }
6717
6718         return *ppv?S_OK:E_NOINTERFACE;
6719     }
6720
6721     virtual ULONG STDMETHODCALLTYPE AddRef()
6722     {
6723         return m_ref++;
6724     }
6725     
6726     virtual ULONG STDMETHODCALLTYPE Release()
6727     {
6728         if (m_ref == 1) {
6729             delete this;
6730             return 0;
6731         }
6732         else
6733             return m_ref--;
6734     }
6735
6736     virtual HRESULT STDMETHODCALLTYPE Next(ULONG, RECT* rect, ULONG* pceltFetched)
6737     {
6738         if (m_index < m_rects.size()) {
6739             if (pceltFetched)
6740                 *pceltFetched = 1;
6741             *rect = m_rects[m_index];
6742             m_index++;
6743             return S_OK;
6744         }
6745
6746         if (pceltFetched)
6747             *pceltFetched = 0;
6748
6749         return S_FALSE;
6750     }
6751     virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
6752     {
6753         m_index += celt;
6754         return S_OK;
6755     }
6756     virtual HRESULT STDMETHODCALLTYPE Reset(void)
6757     {
6758         m_index = 0;
6759         return S_OK;
6760     }
6761     virtual HRESULT STDMETHODCALLTYPE Clone(IEnumTextMatches**)
6762     {
6763         return E_NOTIMPL;
6764     }
6765 };
6766
6767 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches)
6768 {
6769     *matches = new EnumTextMatches(rects);
6770     return (*matches)?S_OK:E_OUTOFMEMORY;
6771 }
6772
6773 Page* core(IWebView* iWebView)
6774 {
6775     Page* page = 0;
6776
6777     COMPtr<WebView> webView;
6778     if (SUCCEEDED(iWebView->QueryInterface(&webView)) && webView)
6779         page = webView->page();
6780
6781     return page;
6782 }
6783
6784 HRESULT WebView::defaultMinimumTimerInterval(double* interval)
6785 {
6786     if (!interval)
6787         return E_POINTER;
6788     *interval = Settings::defaultMinDOMTimerInterval();
6789     return S_OK;
6790 }
6791
6792 HRESULT WebView::setMinimumTimerInterval(double interval)
6793 {
6794     page()->settings()->setMinDOMTimerInterval(interval);
6795     return S_OK;
6796 }
6797
6798 HRESULT WebView::httpPipeliningEnabled(BOOL* enabled)
6799 {
6800     if (!enabled)
6801         return E_POINTER;
6802     *enabled = ResourceRequest::httpPipeliningEnabled();
6803     return S_OK;
6804 }
6805
6806 HRESULT WebView::setHTTPPipeliningEnabled(BOOL enabled)
6807 {
6808     ResourceRequest::setHTTPPipeliningEnabled(enabled);
6809     return S_OK;
6810 }
6811
6812 void WebView::setGlobalHistoryItem(HistoryItem* historyItem)
6813 {
6814     m_globalHistoryItem = historyItem;
6815 }
6816
6817 #if ENABLE(FULLSCREEN_API)
6818 bool WebView::supportsFullScreenForElement(const WebCore::Element*, bool withKeyboard) const
6819 {
6820     if (withKeyboard)
6821         return false;
6822
6823     BOOL enabled = FALSE;
6824     if (!m_preferences || FAILED(m_preferences->isFullScreenEnabled(&enabled)))
6825         return false;
6826
6827     return enabled;
6828 }
6829
6830 bool WebView::isFullScreen() const 
6831 {
6832     return m_fullscreenController && m_fullscreenController->isFullScreen();
6833 }
6834
6835 FullScreenController* WebView::fullScreenController()
6836 {
6837     if (!m_fullscreenController)
6838         m_fullscreenController = adoptPtr(new FullScreenController(this));
6839     return m_fullscreenController.get();
6840 }
6841
6842 void WebView::setFullScreenElement(PassRefPtr<Element> element)
6843 {
6844     m_fullScreenElement = element;
6845 }
6846
6847 HWND WebView::fullScreenClientWindow() const
6848 {
6849     return m_viewWindow;
6850 }
6851
6852 HWND WebView::fullScreenClientParentWindow() const
6853 {
6854     return m_hostWindow;
6855 }
6856
6857 void WebView::fullScreenClientSetParentWindow(HWND hostWindow)
6858 {
6859     setHostWindow(reinterpret_cast<OLE_HANDLE>(hostWindow));
6860 }
6861
6862 void WebView::fullScreenClientWillEnterFullScreen()
6863 {
6864     ASSERT(m_fullScreenElement);
6865     m_fullScreenElement->document()->webkitWillEnterFullScreenForElement(m_fullScreenElement.get());
6866 }
6867
6868 void WebView::fullScreenClientDidEnterFullScreen()
6869 {
6870     ASSERT(m_fullScreenElement);
6871     m_fullScreenElement->document()->webkitDidEnterFullScreenForElement(m_fullScreenElement.get());
6872 }
6873
6874 void WebView::fullScreenClientWillExitFullScreen()
6875 {
6876     ASSERT(m_fullScreenElement);
6877     m_fullScreenElement->document()->webkitWillExitFullScreenForElement(m_fullScreenElement.get());
6878 }
6879
6880 void WebView::fullScreenClientDidExitFullScreen()
6881 {
6882     ASSERT(m_fullScreenElement);
6883     m_fullScreenElement->document()->webkitDidExitFullScreenForElement(m_fullScreenElement.get());
6884     m_fullScreenElement = nullptr;
6885 }
6886
6887 void WebView::fullScreenClientForceRepaint()
6888 {
6889     ASSERT(m_fullScreenElement);
6890     RECT windowRect = {0};
6891     frameRect(&windowRect);
6892     repaint(windowRect, true /*contentChanged*/, true /*immediate*/, false /*contentOnly*/);
6893     m_fullscreenController->repaintCompleted();
6894 }
6895
6896 #endif
6897 // Used by TextInputController in DumpRenderTree
6898
6899 HRESULT STDMETHODCALLTYPE WebView::setCompositionForTesting(
6900     /* [in] */ BSTR composition, 
6901     /* [in] */ UINT from, 
6902     /* [in] */ UINT length)
6903 {
6904     if (!m_page)
6905         return E_FAIL;
6906
6907     Frame* frame = m_page->focusController()->focusedOrMainFrame();
6908     if (!frame || !frame->editor()->canEdit())
6909         return E_FAIL;
6910
6911     String compositionStr(composition, SysStringLen(composition));
6912
6913     Vector<CompositionUnderline> underlines;
6914     underlines.append(CompositionUnderline(0, compositionStr.length(), Color(Color::black), false));
6915     frame->editor()->setComposition(compositionStr, underlines, from, from + length);
6916
6917     return S_OK;
6918 }
6919
6920 HRESULT STDMETHODCALLTYPE WebView::hasCompositionForTesting(/* [out, retval] */ BOOL* result)
6921 {
6922     if (!m_page)
6923         return E_FAIL;
6924
6925     Frame* frame = m_page->focusController()->focusedOrMainFrame();
6926      if (!frame)
6927         return E_FAIL;
6928
6929     *result = frame && frame->editor()->hasComposition();
6930
6931     return S_OK;
6932 }
6933
6934 HRESULT STDMETHODCALLTYPE WebView::confirmCompositionForTesting(/* [in] */ BSTR composition)
6935 {
6936     if (!m_page)
6937         return E_FAIL;
6938
6939     Frame* frame = m_page->focusController()->focusedOrMainFrame();
6940     if (!frame || !frame->editor()->canEdit())
6941         return E_FAIL;
6942
6943     String compositionStr(composition, SysStringLen(composition));
6944
6945     if (compositionStr.isNull())
6946         frame->editor()->confirmComposition();
6947
6948     frame->editor()->confirmComposition(compositionStr);
6949
6950     return S_OK;
6951 }
6952
6953 HRESULT STDMETHODCALLTYPE WebView::compositionRangeForTesting(/* [out] */ UINT* startPosition, /* [out] */ UINT* length)
6954 {
6955     if (!m_page)
6956         return E_FAIL;
6957
6958     Frame* frame = m_page->focusController()->focusedOrMainFrame();
6959     if (!frame || !frame->editor()->canEdit())
6960         return E_FAIL;
6961
6962     RefPtr<Range> range = frame->editor()->compositionRange();
6963
6964     if (!range)
6965         return E_FAIL;
6966
6967     *startPosition = range->startOffset();
6968     *length = range->startOffset() + range->endOffset();
6969
6970     return S_OK;
6971 }
6972
6973
6974 HRESULT STDMETHODCALLTYPE WebView::firstRectForCharacterRangeForTesting(
6975     /* [in] */ UINT location, 
6976     /* [in] */ UINT length, 
6977     /* [out, retval] */ RECT* resultRect)
6978 {
6979     if (!m_page)
6980         return E_FAIL;
6981
6982     Frame* frame = m_page->focusController()->focusedOrMainFrame();
6983     if (!frame)
6984         return E_FAIL;
6985
6986     IntRect resultIntRect;
6987     resultIntRect.setLocation(IntPoint(0, 0));
6988     resultIntRect.setSize(IntSize(0, 0));
6989     
6990     if (location > INT_MAX)
6991         return E_FAIL;
6992     if (length > INT_MAX || location + length > INT_MAX)
6993         length = INT_MAX - location;
6994         
6995     RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(frame->selection()->rootEditableElementOrDocumentElement(), location, length);
6996
6997     if (!range)
6998         return E_FAIL;
6999     
7000     ASSERT(range->startContainer());
7001     ASSERT(range->endContainer());
7002      
7003     IntRect rect = frame->editor()->firstRectForRange(range.get());
7004     resultIntRect = frame->view()->contentsToWindow(rect);
7005
7006     resultRect->left = resultIntRect.x();
7007     resultRect->top = resultIntRect.y();
7008     resultRect->right = resultIntRect.x() + resultIntRect.width();
7009     resultRect->bottom = resultIntRect.y() + resultIntRect.height();
7010
7011     return S_OK;
7012 }
7013
7014 HRESULT STDMETHODCALLTYPE WebView::selectedRangeForTesting(/* [out] */ UINT* location, /* [out] */ UINT* length)
7015 {
7016     if (!m_page)
7017         return E_FAIL;
7018
7019     Frame* frame = m_page->focusController()->focusedOrMainFrame();
7020     if (!frame)
7021         return E_FAIL;
7022
7023     RefPtr<Range> range = frame->editor()->selectedRange();
7024
7025     size_t locationSize;
7026     size_t lengthSize;
7027     if (range && TextIterator::getLocationAndLengthFromRange(frame->selection()->rootEditableElementOrDocumentElement(), range.get(), locationSize, lengthSize)) {
7028         *location = static_cast<UINT>(locationSize);
7029         *length = static_cast<UINT>(lengthSize);
7030     }
7031
7032     return S_OK;
7033 }