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