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