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