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