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