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