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