2 * Copyright (C) 2006, 2007 Apple, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "WebKitDLL.h"
30 #include "CFDictionaryPropertyBag.h"
31 #include "DOMCoreClasses.h"
32 #include "IWebNotification.h"
33 #include "WebDebugProgram.h"
34 #include "WebDocumentLoader.h"
35 #include "WebEditorClient.h"
36 #include "WebElementPropertyBag.h"
38 #include "WebBackForwardList.h"
39 #include "WebChromeClient.h"
40 #include "WebContextMenuClient.h"
41 #include "WebDragClient.h"
42 #include "WebIconDatabase.h"
43 #include "WebInspectorClient.h"
45 #include "WebKitStatisticsPrivate.h"
46 #include "WebMutableURLRequest.h"
47 #include "WebNotificationCenter.h"
48 #include "WebPreferences.h"
49 #pragma warning( push, 0 )
50 #include <CoreGraphics/CGContext.h>
51 #include <CFNetwork/CFHTTPCookiesPriv.h>
52 #include <WebCore/BString.h>
53 #include <WebCore/Cache.h>
54 #include <WebCore/CommandByName.h>
55 #include <WebCore/ContextMenu.h>
56 #include <WebCore/ContextMenuController.h>
57 #include <WebCore/CString.h>
58 #include <WebCore/Cursor.h>
59 #include <WebCore/Document.h>
60 #include <WebCore/DragController.h>
61 #include <WebCore/DragData.h>
62 #include <WebCore/Editor.h>
63 #include <WebCore/EventHandler.h>
64 #include <WebCore/FocusController.h>
65 #include <WebCore/FrameLoader.h>
66 #include <WebCore/FrameTree.h>
67 #include <WebCore/FrameView.h>
68 #include <WebCore/FrameWin.h>
69 #include <WebCore/GDIObjectCounter.h>
70 #include <WebCore/GraphicsContext.h>
71 #include <WebCore/HistoryItem.h>
72 #include <WebCore/HitTestResult.h>
73 #include <WebCore/IntRect.h>
74 #include <WebCore/KeyboardEvent.h>
75 #include <WebCore/Language.h>
76 #include <WebCore/MIMETypeRegistry.h>
77 #include <WebCore/NotImplemented.h>
78 #include <WebCore/Page.h>
79 #include <WebCore/PageCache.h>
80 #include <WebCore/PlatformKeyboardEvent.h>
81 #include <WebCore/PlatformMouseEvent.h>
82 #include <WebCore/PlatformWheelEvent.h>
83 #include <WebCore/PluginDatabaseWin.h>
84 #include <WebCore/PlugInInfoStore.h>
85 #include <WebCore/ProgressTracker.h>
86 #include <WebCore/ResourceHandle.h>
87 #include <WebCore/ResourceHandleClient.h>
88 #include <WebCore/SelectionController.h>
89 #include <WebCore/Settings.h>
90 #include <WebCore/TypingCommand.h>
92 #include <JavaScriptCore/collector.h>
93 #include <JavaScriptCore/value.h>
94 #include <CFNetwork/CFURLProtocolPriv.h>
100 using namespace WebCore;
104 const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass";
106 const int WM_XP_THEMECHANGED = 0x031A;
107 const int WM_VISTA_MOUSEHWHEEL = 0x020E;
109 static const int maxToolTipWidth = 250;
111 static ATOM registerWebView();
112 static LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
114 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches);
116 static bool continuousSpellCheckingEnabled;
117 static bool grammarCheckingEnabled;
119 // WebView ----------------------------------------------------------------
121 bool WebView::s_allowSiteSpecificHacks = false;
129 , m_hasCustomDropTarget(false)
130 , m_useBackForwardList(true)
131 , m_userAgentOverridden(false)
132 , m_textSizeMultiplier(1)
133 , m_mouseActivated(false)
135 , m_currentCharacterCode(0)
136 , m_isBeingDestroyed(false)
138 , m_hasSpellCheckerDocumentTag(false)
139 , m_smartInsertDeleteEnabled(false)
141 , m_inIMEComposition(0)
143 , m_closeWindowTimer(this, &WebView::closeWindowTimerFired)
145 KJS::Collector::registerAsMainThread();
147 m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
149 CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper,(void**)&m_dropTargetHelper);
151 COMPtr<IWebPreferences> prefs;
152 if (SUCCEEDED(preferences(&prefs))) {
154 if (SUCCEEDED(prefs->continuousSpellCheckingEnabled(&enabled)))
155 continuousSpellCheckingEnabled = !!enabled;
156 if (SUCCEEDED(prefs->grammarCheckingEnabled(&enabled)))
157 grammarCheckingEnabled = !!enabled;
160 WebDebugProgram::viewAdded(this);
167 deleteBackingStore();
169 // <rdar://4958382> m_viewWindow will be destroyed when m_hostWindow is destroyed, but if
170 // setHostWindow was never called we will leak our HWND. If we still have a valid HWND at
171 // this point, we should just destroy it ourselves.
172 if (::IsWindow(m_viewWindow))
173 ::DestroyWindow(m_viewWindow);
177 WebDebugProgram::viewRemoved(this);
182 WebView* WebView::createInstance()
184 WebView* instance = new WebView();
189 void WebView::close()
196 Frame* frame = m_page->mainFrame();
198 frame->loader()->detachFromParent();
200 m_page->setGroupName(String());
203 setDownloadDelegate(0);
204 setEditingDelegate(0);
205 setFrameLoadDelegate(0);
206 setFrameLoadDelegatePrivate(0);
207 setPolicyDelegate(0);
208 setResourceLoadDelegate(0);
215 registerForIconNotification(false);
216 IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
217 COMPtr<IWebPreferences> prefs;
218 if (SUCCEEDED(preferences(&prefs)))
219 notifyCenter->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), prefs.get());
220 prefs = 0; // make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
223 if (SUCCEEDED(m_preferences->identifier(&identifier)))
224 WebPreferences::removeReferenceForIdentifier(identifier);
226 SysFreeString(identifier);
230 deleteBackingStore();
233 void WebView::deleteBackingStore()
235 m_backingStoreBitmap.clear();
236 m_backingStoreDirtyRegion.clear();
238 m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
241 bool WebView::ensureBackingStore()
244 ::GetClientRect(m_viewWindow, &windowRect);
245 LONG width = windowRect.right - windowRect.left;
246 LONG height = windowRect.bottom - windowRect.top;
247 if (width > 0 && height > 0 && (width != m_backingStoreSize.cx || height != m_backingStoreSize.cy)) {
248 deleteBackingStore();
250 m_backingStoreSize.cx = width;
251 m_backingStoreSize.cy = height;
252 BITMAPINFO bitmapInfo;
253 bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
254 bitmapInfo.bmiHeader.biWidth = width;
255 bitmapInfo.bmiHeader.biHeight = -height;
256 bitmapInfo.bmiHeader.biPlanes = 1;
257 bitmapInfo.bmiHeader.biBitCount = 32;
258 bitmapInfo.bmiHeader.biCompression = BI_RGB;
259 bitmapInfo.bmiHeader.biSizeImage = 0;
260 bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
261 bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
262 bitmapInfo.bmiHeader.biClrUsed = 0;
263 bitmapInfo.bmiHeader.biClrImportant = 0;
266 m_backingStoreBitmap.set(::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, NULL, 0));
273 void WebView::addToDirtyRegion(const IntRect& dirtyRect)
275 HRGN newRegion = ::CreateRectRgn(dirtyRect.x(), dirtyRect.y(),
276 dirtyRect.right(), dirtyRect.bottom());
277 addToDirtyRegion(newRegion);
280 void WebView::addToDirtyRegion(HRGN newRegion)
282 LOCAL_GDI_COUNTER(0, __FUNCTION__);
284 if (m_backingStoreDirtyRegion) {
285 HRGN combinedRegion = ::CreateRectRgn(0,0,0,0);
286 ::CombineRgn(combinedRegion, m_backingStoreDirtyRegion.get(), newRegion, RGN_OR);
287 ::DeleteObject(newRegion);
288 m_backingStoreDirtyRegion.set(combinedRegion);
290 m_backingStoreDirtyRegion.set(newRegion);
293 void WebView::scrollBackingStore(FrameView* frameView, int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect)
295 LOCAL_GDI_COUNTER(0, __FUNCTION__);
297 // If there's no backing store we don't need to update it
298 if (!m_backingStoreBitmap) {
299 if (m_uiDelegatePrivate)
300 m_uiDelegatePrivate->webViewScrolled(this);
305 // Make a region to hold the invalidated scroll area.
306 HRGN updateRegion = ::CreateRectRgn(0, 0, 0, 0);
308 // Collect our device context info and select the bitmap to scroll.
309 HDC windowDC = ::GetDC(m_viewWindow);
310 HDC bitmapDC = ::CreateCompatibleDC(windowDC);
311 ::SelectObject(bitmapDC, m_backingStoreBitmap.get());
313 // Scroll the bitmap.
314 RECT scrollRectWin(scrollViewRect);
315 RECT clipRectWin(clipRect);
316 ::ScrollDC(bitmapDC, dx, dy, &scrollRectWin, &clipRectWin, updateRegion, 0);
318 ::GetRgnBox(updateRegion, ®ionBox);
323 // Add the dirty region to the backing store's dirty region.
324 addToDirtyRegion(updateRegion);
326 if (m_uiDelegatePrivate)
327 m_uiDelegatePrivate->webViewScrolled(this);
329 // Update the backing store.
330 updateBackingStore(frameView, bitmapDC, false);
333 ::DeleteDC(bitmapDC);
334 ::ReleaseDC(m_viewWindow, windowDC);
338 void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStoreCompletelyDirty)
340 LOCAL_GDI_COUNTER(0, __FUNCTION__);
345 windowDC = ::GetDC(m_viewWindow);
346 bitmapDC = ::CreateCompatibleDC(windowDC);
347 ::SelectObject(bitmapDC, m_backingStoreBitmap.get());
350 if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
351 // Do a layout first so that everything we render to the backing store is always current.
352 if (Frame* coreFrame = core(m_mainFrame))
353 if (FrameView* view = coreFrame->view())
354 view->layoutIfNeededRecursive();
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;
362 if (!backingStoreCompletelyDirty) {
363 ::GetRgnBox(m_backingStoreDirtyRegion.get(), ®ionBox);
364 DWORD regionDataSize = GetRegionData(m_backingStoreDirtyRegion.get(), sizeof(RGNDATA), NULL);
365 if (regionDataSize) {
366 RGNDATA* regionData = (RGNDATA*)malloc(regionDataSize);
367 GetRegionData(m_backingStoreDirtyRegion.get(), regionDataSize, regionData);
368 if (regionData->rdh.nCount <= cRectThreshold) {
369 double unionPixels = (regionBox.right - regionBox.left) * (regionBox.bottom - regionBox.top);
370 double singlePixels = 0;
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);
387 ::GetClientRect(m_viewWindow, ®ionBox);
390 paintIntoBackingStore(frameView, bitmapDC, ®ionBox);
392 if (m_uiDelegatePrivate) {
393 COMPtr<IWebUIDelegatePrivate2> uiDelegatePrivate2(Query, m_uiDelegatePrivate);
394 if (uiDelegatePrivate2)
395 uiDelegatePrivate2->webViewPainted(this);
398 m_backingStoreDirtyRegion.clear();
402 ::DeleteDC(bitmapDC);
403 ::ReleaseDC(m_viewWindow, windowDC);
409 void WebView::paint(HDC dc, LPARAM options)
411 LOCAL_GDI_COUNTER(0, __FUNCTION__);
413 Frame* coreFrame = core(m_mainFrame);
416 FrameView* frameView = coreFrame->view();
423 int regionType = NULLREGION;
426 region.set(CreateRectRgn(0,0,0,0));
427 regionType = GetUpdateRgn(m_viewWindow, region.get(), false);
428 hdc = BeginPaint(m_viewWindow, &ps);
429 rcPaint = ps.rcPaint;
432 ::GetClientRect(m_viewWindow, &rcPaint);
433 if (options & PRF_ERASEBKGND)
434 ::FillRect(hdc, &rcPaint, (HBRUSH)GetStockObject(WHITE_BRUSH));
437 HDC bitmapDC = ::CreateCompatibleDC(hdc);
438 bool backingStoreCompletelyDirty = ensureBackingStore();
439 ::SelectObject(bitmapDC, m_backingStoreBitmap.get());
441 // Update our backing store if needed.
442 updateBackingStore(frameView, bitmapDC, backingStoreCompletelyDirty);
444 // Now we blit the updated backing store
445 IntRect windowDirtyRect = rcPaint;
447 // Apply the same heuristic for this update region too.
448 bool useWindowDirtyRect = true;
449 if (region && regionType == COMPLEXREGION) {
450 LOCAL_GDI_COUNTER(1, __FUNCTION__" (COMPLEXREGION)");
452 const int cRectThreshold = 10;
453 const float cWastedSpaceThreshold = 0.75f;
454 DWORD regionDataSize = GetRegionData(region.get(), sizeof(RGNDATA), NULL);
455 if (regionDataSize) {
456 RGNDATA* regionData = (RGNDATA*)malloc(regionDataSize);
457 GetRegionData(region.get(), regionDataSize, regionData);
458 if (regionData->rdh.nCount <= cRectThreshold) {
459 double unionPixels = windowDirtyRect.width() * windowDirtyRect.height();
460 double singlePixels = 0;
464 for (i = 0, rect = (RECT*)regionData->Buffer; i < regionData->rdh.nCount; i++, rect++)
465 singlePixels += (rect->right - rect->left) * (rect->bottom - rect->top);
466 double wastedSpace = 1.0 - (singlePixels / unionPixels);
467 if (wastedSpace > cWastedSpaceThreshold) {
468 // Paint individual rects.
469 useWindowDirtyRect = false;
470 for (i = 0, rect = (RECT*)regionData->Buffer; i < regionData->rdh.nCount; i++, rect++)
471 paintIntoWindow(bitmapDC, hdc, rect);
478 if (useWindowDirtyRect)
479 paintIntoWindow(bitmapDC, hdc, &rcPaint);
481 ::DeleteDC(bitmapDC);
483 // Paint the gripper.
484 COMPtr<IWebUIDelegate> ui;
485 if (SUCCEEDED(uiDelegate(&ui))) {
486 COMPtr<IWebUIDelegatePrivate> uiPrivate;
487 if (SUCCEEDED(ui->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) {
489 if (SUCCEEDED(uiPrivate->webViewResizerRect(this, &r))) {
490 LOCAL_GDI_COUNTER(2, __FUNCTION__" webViewDrawResizer delegate call");
491 uiPrivate->webViewDrawResizer(this, hdc, (frameView->resizerOverlapsContent() ? true : false), &r);
497 EndPaint(m_viewWindow, &ps);
502 void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, LPRECT dirtyRect)
504 LOCAL_GDI_COUNTER(0, __FUNCTION__);
506 #if FLASH_BACKING_STORE_REDRAW
507 HDC dc = ::GetDC(m_viewWindow);
508 OwnPtr<HBRUSH> yellowBrush = CreateSolidBrush(RGB(255, 255, 0));
509 FillRect(dc, dirtyRect, yellowBrush.get());
512 paintIntoWindow(bitmapDC, dc, dirtyRect);
513 ::ReleaseDC(m_viewWindow, dc);
516 FillRect(bitmapDC, dirtyRect, (HBRUSH)GetStockObject(WHITE_BRUSH));
517 if (frameView && frameView->frame() && frameView->frame()->renderer()) {
518 GraphicsContext gc(bitmapDC);
520 gc.clip(IntRect(*dirtyRect));
521 frameView->paint(&gc, IntRect(*dirtyRect));
526 void WebView::paintIntoWindow(HDC bitmapDC, HDC windowDC, LPRECT dirtyRect)
528 LOCAL_GDI_COUNTER(0, __FUNCTION__);
529 #if FLASH_WINDOW_REDRAW
530 OwnPtr<HBRUSH> greenBrush = CreateSolidBrush(RGB(0, 255, 0));
531 FillRect(windowDC, dirtyRect, greenBrush.get());
536 // Blit the dirty rect from the backing store into the same position
537 // in the destination DC.
538 BitBlt(windowDC, dirtyRect->left, dirtyRect->top, dirtyRect->right - dirtyRect->left, dirtyRect->bottom - dirtyRect->top, bitmapDC,
539 dirtyRect->left, dirtyRect->top, SRCCOPY);
542 void WebView::frameRect(RECT* rect)
544 ::GetWindowRect(m_viewWindow, rect);
547 void WebView::closeWindowSoon()
549 m_closeWindowTimer.startOneShot(0);
553 void WebView::closeWindowTimerFired(WebCore::Timer<WebView>*)
559 void WebView::closeWindow()
561 if (m_hasSpellCheckerDocumentTag) {
562 if (m_editingDelegate)
563 m_editingDelegate->closeSpellDocument(this);
564 m_hasSpellCheckerDocumentTag = false;
567 COMPtr<IWebUIDelegate> ui;
568 if (SUCCEEDED(uiDelegate(&ui)))
569 ui->webViewClose(this);
572 bool WebView::canHandleRequest(const WebCore::ResourceRequest& request)
574 // On the mac there's an about url protocol implementation but CFNetwork doesn't have that.
575 if (equalIgnoringCase(String(request.url().protocol()), "about"))
578 if (CFURLProtocolCanHandleRequest(request.cfURLRequest()))
581 // FIXME: Mac WebKit calls _representationExistsForURLScheme here
585 Page* WebView::page()
590 bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam)
592 static const int contextMenuMargin = 1;
594 // Translate the screen coordinates into window coordinates
595 POINT coords = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
596 if (coords.x == -1 || coords.y == -1) {
597 FrameView* view = m_page->mainFrame()->view();
601 int rightAligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT);
604 // The context menu event was generated from the keyboard, so show the context menu by the current selection.
605 Position start = m_page->mainFrame()->selectionController()->selection().start();
606 Position end = m_page->mainFrame()->selectionController()->selection().end();
608 if (!start.node() || !end.node())
609 location = IntPoint(rightAligned ? view->contentsWidth() - contextMenuMargin : contextMenuMargin, contextMenuMargin);
611 RenderObject* renderer = start.node()->renderer();
615 // Calculate the rect of the first line of the selection (cribbed from -[WebCoreFrameBridge firstRectForDOMRange:]).
616 int extraWidthToEndOfLine = 0;
617 IntRect startCaretRect = renderer->caretRect(start.offset(), DOWNSTREAM, &extraWidthToEndOfLine);
618 IntRect endCaretRect = renderer->caretRect(end.offset(), UPSTREAM);
621 if (startCaretRect.y() == endCaretRect.y())
622 firstRect = IntRect(min(startCaretRect.x(), endCaretRect.x()), startCaretRect.y(), abs(endCaretRect.x() - startCaretRect.x()), max(startCaretRect.height(), endCaretRect.height()));
624 firstRect = IntRect(startCaretRect.x(), startCaretRect.y(), startCaretRect.width() + extraWidthToEndOfLine, startCaretRect.height());
626 location = IntPoint(rightAligned ? firstRect.right() : firstRect.x(), firstRect.bottom());
629 location = view->contentsToWindow(location);
630 // FIXME: The IntSize(0, -1) is a hack to get the hit-testing to result in the selected element.
631 // Ideally we'd have the position of a context menu event be separate from its target node.
632 coords = location + IntSize(0, -1);
634 if (!::ScreenToClient(m_viewWindow, &coords))
638 lParam = MAKELPARAM(coords.x, coords.y);
640 // The contextMenuController() holds onto the last context menu that was popped up on the
641 // page until a new one is created. We need to clear this menu before propagating the event
642 // through the DOM so that we can detect if we create a new menu for this event, since we
643 // won't create a new menu if the DOM swallows the event and the defaultEventHandler does
645 m_page->contextMenuController()->clearContextMenu();
647 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
648 focusedFrame->view()->setCursor(pointerCursor());
649 PlatformMouseEvent mouseEvent(m_viewWindow, WM_RBUTTONUP, wParam, lParam);
650 bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(mouseEvent);
655 ContextMenu* coreMenu = m_page->contextMenuController()->contextMenu();
659 Node* node = coreMenu->hitTestResult().innerNonSharedNode();
663 Frame* frame = node->document()->frame();
667 FrameView* view = frame->view();
671 POINT point(view->contentsToWindow(coreMenu->hitTestResult().point()));
673 // Translate the point to screen coordinates
674 if (!::ClientToScreen(view->containingWindow(), &point))
677 BOOL hasCustomMenus = false;
679 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
682 m_uiDelegate->trackCustomPopupMenu((IWebView*)this, (OLE_HANDLE)(ULONG64)coreMenu->platformDescription(), &point);
684 // Surprisingly, TPM_RIGHTBUTTON means that items are selectable with either the right OR left mouse button
685 UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL
686 | TPM_LEFTALIGN | TPM_HORPOSANIMATION;
687 ::TrackPopupMenuEx(coreMenu->platformDescription(), flags, point.x, point.y, view->containingWindow(), 0);
693 bool WebView::onMeasureItem(WPARAM /*wParam*/, LPARAM lParam)
698 BOOL hasCustomMenus = false;
699 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
703 m_uiDelegate->measureCustomMenuItem((IWebView*)this, (void*)lParam);
707 bool WebView::onDrawItem(WPARAM /*wParam*/, LPARAM lParam)
712 BOOL hasCustomMenus = false;
713 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
717 m_uiDelegate->drawCustomMenuItem((IWebView*)this, (void*)lParam);
721 bool WebView::onInitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
726 HMENU menu = (HMENU)wParam;
730 BOOL hasCustomMenus = false;
731 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
735 m_uiDelegate->addCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu);
739 bool WebView::onUninitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
744 HMENU menu = (HMENU)wParam;
748 BOOL hasCustomMenus = false;
749 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
753 m_uiDelegate->cleanUpCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu);
757 void WebView::performContextMenuAction(WPARAM wParam, LPARAM lParam, bool byPosition)
759 ContextMenu* menu = m_page->contextMenuController()->contextMenu();
762 ContextMenuItem* item = byPosition ? menu->itemAtIndex((unsigned)wParam, (HMENU)lParam) : menu->itemWithAction((ContextMenuAction)wParam);
765 m_page->contextMenuController()->contextMenuItemSelected(item);
769 bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam)
771 static LONG globalClickCount;
772 static IntPoint globalPrevPoint;
773 static MouseButton globalPrevButton;
774 static LONG globalPrevMouseDownTime;
777 PlatformMouseEvent mouseEvent(m_viewWindow, message, wParam, lParam, m_mouseActivated);
779 bool insideThreshold = abs(globalPrevPoint.x() - mouseEvent.pos().x()) < ::GetSystemMetrics(SM_CXDOUBLECLK) &&
780 abs(globalPrevPoint.y() - mouseEvent.pos().y()) < ::GetSystemMetrics(SM_CYDOUBLECLK);
781 LONG messageTime = ::GetMessageTime();
783 bool handled = false;
784 if (message == WM_LBUTTONDOWN || message == WM_MBUTTONDOWN || message == WM_RBUTTONDOWN) {
785 // FIXME: I'm not sure if this is the "right" way to do this
786 // but without this call, we never become focused since we don't allow
787 // the default handling of mouse events.
788 SetFocus(m_viewWindow);
790 // Always start capturing events when the mouse goes down in our HWND.
791 ::SetCapture(m_viewWindow);
793 if (((messageTime - globalPrevMouseDownTime) < (LONG)::GetDoubleClickTime()) &&
795 mouseEvent.button() == globalPrevButton)
798 // Reset the click count.
799 globalClickCount = 1;
800 globalPrevMouseDownTime = messageTime;
801 globalPrevButton = mouseEvent.button();
802 globalPrevPoint = mouseEvent.pos();
804 mouseEvent.setClickCount(globalClickCount);
805 handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
806 } else if (message == WM_LBUTTONDBLCLK || message == WM_MBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) {
808 mouseEvent.setClickCount(globalClickCount);
809 handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
810 } else if (message == WM_LBUTTONUP || message == WM_MBUTTONUP || message == WM_RBUTTONUP) {
811 // Record the global position and the button of the up.
812 globalPrevButton = mouseEvent.button();
813 globalPrevPoint = mouseEvent.pos();
814 mouseEvent.setClickCount(globalClickCount);
815 m_page->mainFrame()->eventHandler()->handleMouseReleaseEvent(mouseEvent);
817 } else if (message == WM_MOUSEMOVE) {
818 if (!insideThreshold)
819 globalClickCount = 0;
820 mouseEvent.setClickCount(globalClickCount);
821 handled = m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent);
823 setMouseActivated(false);
827 bool WebView::mouseWheel(WPARAM wParam, LPARAM lParam, bool isHorizontal)
829 // Ctrl+Mouse wheel doesn't ever go into WebCore. It is used to
830 // zoom instead (Mac zooms the whole Desktop, but Windows browsers trigger their
831 // own local zoom modes for Ctrl+wheel).
832 if (wParam & MK_CONTROL) {
833 short delta = short(HIWORD(wParam));
841 PlatformWheelEvent wheelEvent(m_viewWindow, wParam, lParam, isHorizontal);
842 Frame* coreFrame = core(m_mainFrame);
846 return coreFrame->eventHandler()->handleWheelEvent(wheelEvent);
849 bool WebView::execCommand(WPARAM wParam, LPARAM /*lParam*/)
851 Frame* frame = m_page->focusController()->focusedOrMainFrame();
852 bool handled = false;
853 switch (LOWORD(wParam)) {
855 handled = frame->editor()->execCommand("SelectAll");
858 handled = frame->editor()->execCommand("Undo");
861 handled = frame->editor()->execCommand("Redo");
869 bool WebView::keyUp(WPARAM virtualKeyCode, LPARAM keyData)
871 // Don't send key events for shift, ctrl, alt and capslock keys when they're by themselves
872 if (virtualKeyCode == VK_SHIFT || virtualKeyCode == VK_CONTROL || virtualKeyCode == VK_MENU || virtualKeyCode == VK_CAPITAL)
875 PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, m_currentCharacterCode);
877 // Don't send key events for alt+space and alt+f4.
878 if (keyEvent.altKey() && (virtualKeyCode == VK_SPACE || virtualKeyCode == VK_F4))
881 Frame* frame = m_page->focusController()->focusedOrMainFrame();
882 m_currentCharacterCode = 0;
884 return frame->eventHandler()->keyEvent(keyEvent);
887 static const unsigned CtrlKey = 1 << 0;
888 static const unsigned AltKey = 1 << 1;
889 static const unsigned ShiftKey = 1 << 2;
898 static const KeyEntry keyEntries[] = {
899 { VK_LEFT, 0, "MoveLeft" },
900 { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" },
901 { VK_LEFT, CtrlKey, "MoveWordLeft" },
902 { VK_LEFT, CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection" },
903 { VK_RIGHT, 0, "MoveRight" },
904 { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" },
905 { VK_RIGHT, CtrlKey, "MoveWordRight" },
906 { VK_RIGHT, CtrlKey | ShiftKey, "MoveWordRightAndModifySelection" },
907 { VK_UP, 0, "MoveUp" },
908 { VK_UP, ShiftKey, "MoveUpAndModifySelection" },
909 { VK_PRIOR, ShiftKey, "MoveUpAndModifySelection" },
910 { VK_DOWN, 0, "MoveDown" },
911 { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" },
912 { VK_NEXT, ShiftKey, "MoveDownAndModifySelection" },
913 { VK_PRIOR, 0, "MoveUpByPageAndModifyCaret" },
914 { VK_NEXT, 0, "MoveDownByPageAndModifyCaret" },
915 { VK_HOME, 0, "MoveToBeginningOfLine" },
916 { VK_HOME, ShiftKey, "MoveToBeginningOfLineAndModifySelection" },
917 { VK_HOME, CtrlKey, "MoveToBeginningOfDocument" },
918 { VK_HOME, CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
920 { VK_END, 0, "MoveToEndOfLine" },
921 { VK_END, ShiftKey, "MoveToEndOfLineAndModifySelection" },
922 { VK_END, CtrlKey, "MoveToEndOfDocument" },
923 { VK_END, CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection" },
925 { VK_BACK, 0, "BackwardDelete" },
926 { VK_BACK, ShiftKey, "BackwardDelete" },
927 { VK_DELETE, 0, "ForwardDelete" },
928 { VK_DELETE, ShiftKey, "ForwardDelete" },
929 { VK_BACK, CtrlKey, "DeleteWordBackward" },
930 { VK_DELETE, CtrlKey, "DeleteWordForward" },
932 { 'B', CtrlKey, "ToggleBold" },
933 { 'I', CtrlKey, "ToggleItalic" },
935 { VK_ESCAPE, 0, "Cancel" },
936 { VK_OEM_PERIOD, CtrlKey, "Cancel" },
937 { VK_TAB, 0, "InsertTab" },
938 { VK_TAB, ShiftKey, "InsertBacktab" },
939 { VK_RETURN, 0, "InsertNewline" },
940 { VK_RETURN, CtrlKey, "InsertNewline" },
941 { VK_RETURN, AltKey, "InsertNewline" },
942 { VK_RETURN, AltKey | ShiftKey, "InsertNewline" },
944 { 'C', CtrlKey, "Copy" },
945 { 'V', CtrlKey, "Paste" },
946 { 'X', CtrlKey, "Cut" },
947 { 'A', CtrlKey, "SelectAll" },
948 { 'Z', CtrlKey, "Undo" },
949 { 'Z', CtrlKey | ShiftKey, "Redo" },
952 const char* WebView::interpretKeyEvent(const KeyboardEvent* evt)
954 const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
958 static HashMap<int, const char*>* commandsMap = 0;
961 commandsMap = new HashMap<int, const char*>;
963 for (unsigned i = 0; i < _countof(keyEntries); i++)
964 commandsMap->set(keyEntries[i].modifiers << 16 | keyEntries[i].virtualKey, keyEntries[i].name);
967 unsigned modifiers = 0;
968 if (keyEvent->shiftKey())
969 modifiers |= ShiftKey;
970 if (keyEvent->altKey())
972 if (keyEvent->ctrlKey())
973 modifiers |= CtrlKey;
975 return commandsMap->get(modifiers << 16 | keyEvent->WindowsKeyCode());
978 bool WebView::handleEditingKeyboardEvent(KeyboardEvent* evt)
980 String command(interpretKeyEvent(evt));
982 Node* node = evt->target()->toNode();
984 Frame* frame = node->document()->frame();
987 if (!command.isEmpty())
988 if (frame->editor()->execCommand(command, evt))
991 if (!evt->keyEvent())
994 if (evt->keyEvent()->text().length() == 1) {
995 UChar ch = evt->keyEvent()->text()[0];
996 // Don't insert null or control characters as they can reslt in unexpected behaviour
1001 return frame->editor()->insertText(evt->keyEvent()->text(), evt);
1004 bool WebView::keyDown(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
1006 // Don't send key events for shift, ctrl, alt and capslock keys when they're by themselves
1007 if (virtualKeyCode == VK_SHIFT || virtualKeyCode == VK_CONTROL || virtualKeyCode == VK_MENU || virtualKeyCode == VK_CAPITAL)
1010 // Don't send key events for alt+space and alt+f4, since the OS needs to handle that.
1011 if (systemKeyDown && (virtualKeyCode == VK_SPACE || virtualKeyCode == VK_F4))
1015 // If the next message is a WM_CHAR message, then take it out of the queue, and use
1016 // the message parameters to get the character code to construct the PlatformKeyboardEvent.
1017 if (systemKeyDown) {
1018 if (::PeekMessage(&msg, m_viewWindow, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE))
1019 m_currentCharacterCode = (UChar)msg.wParam;
1020 } else if (::PeekMessage(&msg, m_viewWindow, WM_CHAR, WM_CHAR, PM_REMOVE))
1021 m_currentCharacterCode = (UChar)msg.wParam;
1023 // FIXME: We need to check WM_UNICHAR to support supplementary characters.
1024 // FIXME: We may need to handle other messages for international text.
1026 m_inIMEKeyDown = virtualKeyCode == VK_PROCESSKEY;
1027 if (virtualKeyCode == VK_PROCESSKEY && !m_inIMEComposition)
1028 virtualKeyCode = MapVirtualKey(LOBYTE(HIWORD(keyData)), 1);
1030 PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, m_currentCharacterCode);
1031 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1032 bool handled = frame->eventHandler()->keyEvent(keyEvent);
1033 m_inIMEKeyDown = false;
1037 // We need to handle back/forward using either Backspace(+Shift) or Ctrl+Left/Right Arrow keys.
1038 int windowsKeyCode = keyEvent.WindowsKeyCode();
1039 if ((windowsKeyCode == VK_BACK && keyEvent.shiftKey()) || (windowsKeyCode == VK_RIGHT && keyEvent.ctrlKey()))
1040 m_page->goForward();
1041 else if (windowsKeyCode == VK_BACK || (windowsKeyCode == VK_LEFT && keyEvent.ctrlKey()))
1044 // Need to scroll the page if the arrow keys, space(shift), pgup/dn, or home/end are hit.
1045 ScrollDirection direction;
1046 ScrollGranularity granularity;
1047 switch (windowsKeyCode) {
1049 granularity = ScrollByLine;
1050 direction = ScrollLeft;
1053 granularity = ScrollByLine;
1054 direction = ScrollRight;
1057 granularity = ScrollByLine;
1058 direction = ScrollUp;
1061 granularity = ScrollByLine;
1062 direction = ScrollDown;
1065 granularity = ScrollByDocument;
1066 direction = ScrollUp;
1069 granularity = ScrollByDocument;
1070 direction = ScrollDown;
1073 granularity = ScrollByPage;
1074 direction = (GetKeyState(VK_SHIFT) & 0x8000) ? ScrollUp : ScrollDown;
1077 granularity = ScrollByPage;
1078 direction = ScrollUp;
1081 granularity = ScrollByPage;
1082 direction = ScrollDown;
1085 // We return true here so the WM_CHAR handler won't pick up unhandled messages.
1089 if (!frame->eventHandler()->scrollOverflow(direction, granularity))
1090 frame->view()->scroll(direction, granularity);
1095 bool WebView::inResizer(LPARAM lParam)
1097 if (!m_uiDelegatePrivate)
1101 if (FAILED(m_uiDelegatePrivate->webViewResizerRect(this, &r)))
1105 pt.x = LOWORD(lParam);
1106 pt.y = HIWORD(lParam);
1107 return !!PtInRect(&r, pt);
1110 void WebView::initializeCacheSizesIfNecessary()
1112 static bool didInitialize;
1116 COMPtr<IWebPreferences> prefs;
1117 if (FAILED(preferences(&prefs)))
1121 if (SUCCEEDED(prefs->pageCacheSize(&pageCacheSize)))
1122 pageCache()->setCapacity(pageCacheSize);
1124 UINT objectCacheSize;
1125 if (SUCCEEDED(prefs->objectCacheSize(&objectCacheSize)))
1126 cache()->setCapacities(0, objectCacheSize, objectCacheSize);
1128 didInitialize = true;
1131 static ATOM registerWebViewWindowClass()
1133 static bool haveRegisteredWindowClass = false;
1134 if (haveRegisteredWindowClass)
1139 wcex.cbSize = sizeof(WNDCLASSEX);
1141 wcex.style = CS_DBLCLKS;
1142 wcex.lpfnWndProc = WebViewWndProc;
1143 wcex.cbClsExtra = 0;
1144 wcex.cbWndExtra = 4; // 4 bytes for the IWebView pointer
1145 wcex.hInstance = gInstance;
1147 wcex.hCursor = ::LoadCursor(0, IDC_ARROW);
1148 wcex.hbrBackground = 0;
1149 wcex.lpszMenuName = 0;
1150 wcex.lpszClassName = kWebViewWindowClassName;
1153 return RegisterClassEx(&wcex);
1157 extern HCURSOR lastSetCursor;
1160 static LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1162 LRESULT lResult = 0;
1163 LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0);
1164 WebView* webView = reinterpret_cast<WebView*>(longPtr);
1165 WebFrame* mainFrameImpl = webView ? webView->topLevelFrame() : 0;
1166 if (!mainFrameImpl || webView->isBeingDestroyed())
1167 return DefWindowProc(hWnd, message, wParam, lParam);
1171 bool handled = true;
1175 COMPtr<IWebDataSource> dataSource;
1176 mainFrameImpl->dataSource(&dataSource);
1177 Frame* coreFrame = core(mainFrameImpl);
1178 if (!webView->isPainting() && (!dataSource || coreFrame && (coreFrame->view()->didFirstLayout() || !coreFrame->loader()->committedFirstRealDocumentLoad())))
1179 webView->paint(0, 0);
1181 ValidateRect(hWnd, 0);
1184 case WM_PRINTCLIENT:
1185 webView->paint((HDC)wParam, lParam);
1189 webView->setIsBeingDestroyed();
1190 webView->revokeDragDrop();
1193 if (webView->inResizer(lParam))
1194 SetCursor(LoadCursor(0, IDC_SIZENWSE));
1196 case WM_LBUTTONDOWN:
1197 case WM_MBUTTONDOWN:
1198 case WM_RBUTTONDOWN:
1199 case WM_LBUTTONDBLCLK:
1200 case WM_MBUTTONDBLCLK:
1201 case WM_RBUTTONDBLCLK:
1205 if (Frame* coreFrame = core(mainFrameImpl))
1206 if (coreFrame->view()->didFirstLayout())
1207 handled = webView->handleMouseEvent(message, wParam, lParam);
1210 case WM_VISTA_MOUSEHWHEEL:
1211 if (Frame* coreFrame = core(mainFrameImpl))
1212 if (coreFrame->view()->didFirstLayout())
1213 handled = webView->mouseWheel(wParam, lParam, (wParam & MK_SHIFT) || message == WM_VISTA_MOUSEHWHEEL);
1216 handled = webView->keyDown(wParam, lParam, true);
1219 handled = webView->keyDown(wParam, lParam);
1223 handled = webView->keyUp(wParam, lParam);
1226 if (webView->isBeingDestroyed())
1227 // If someone has sent us this message while we're being destroyed, we should bail out so we don't crash.
1231 webView->deleteBackingStore();
1232 if (Frame* coreFrame = core(mainFrameImpl)) {
1233 coreFrame->view()->resize(LOWORD(lParam), HIWORD(lParam));
1235 if (!coreFrame->loader()->isLoading())
1236 coreFrame->sendResizeEvent();
1241 lResult = DefWindowProc(hWnd, message, wParam, lParam);
1243 // The window is being hidden (e.g., because we switched tabs.
1244 // Null out our backing store.
1245 webView->deleteBackingStore();
1248 COMPtr<IWebUIDelegate> uiDelegate;
1249 COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
1250 if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate &&
1251 SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
1252 uiDelegatePrivate->webViewReceivedFocus(webView);
1253 // FIXME: Merge this logic with updateActiveState, and switch this over to use updateActiveState
1255 // It's ok to just always do setWindowHasFocus, since we won't fire the focus event on the DOM
1256 // window unless the value changes. It's also ok to do setIsActive inside focus,
1257 // because Windows has no concept of having to update control tints (e.g., graphite vs. aqua)
1258 // and therefore only needs to update the selection (which is limited to the focused frame).
1259 FocusController* focusController = webView->page()->focusController();
1260 if (Frame* frame = focusController->focusedFrame()) {
1261 frame->setIsActive(true);
1263 // If the previously focused window is a child of ours (for example a plugin), don't send any
1265 if (!IsChild(hWnd, reinterpret_cast<HWND>(wParam)))
1266 frame->setWindowHasFocus(true);
1268 focusController->setFocusedFrame(webView->page()->mainFrame());
1271 case WM_KILLFOCUS: {
1272 COMPtr<IWebUIDelegate> uiDelegate;
1273 COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
1274 if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate &&
1275 SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
1276 uiDelegatePrivate->webViewLostFocus(webView, (OLE_HANDLE)(ULONG64)wParam);
1277 // FIXME: Merge this logic with updateActiveState, and switch this over to use updateActiveState
1279 // However here we have to be careful. If we are losing focus because of a deactivate,
1280 // then we need to remember our focused target for restoration later.
1281 // If we are losing focus to another part of our window, then we are no longer focused for real
1282 // and we need to clear out the focused target.
1283 FocusController* focusController = webView->page()->focusController();
1284 webView->resetIME(focusController->focusedOrMainFrame());
1285 if (GetAncestor(hWnd, GA_ROOT) != GetFocus()) {
1286 if (Frame* frame = focusController->focusedFrame()) {
1287 frame->setIsActive(false);
1289 // If we're losing focus to a child of ours, don't send blur events.
1290 if (!IsChild(hWnd, reinterpret_cast<HWND>(wParam)))
1291 frame->setWindowHasFocus(false);
1294 focusController->setFocusedFrame(0);
1307 webView->delete_(0);
1311 handled = webView->execCommand(wParam, lParam);
1312 else // If the high word of wParam is 0, the message is from a menu
1313 webView->performContextMenuAction(wParam, lParam, false);
1315 case WM_MENUCOMMAND:
1316 webView->performContextMenuAction(wParam, lParam, true);
1318 case WM_CONTEXTMENU:
1319 handled = webView->handleContextMenuEvent(wParam, lParam);
1321 case WM_INITMENUPOPUP:
1322 handled = webView->onInitMenuPopup(wParam, lParam);
1324 case WM_MEASUREITEM:
1325 handled = webView->onMeasureItem(wParam, lParam);
1328 handled = webView->onDrawItem(wParam, lParam);
1330 case WM_UNINITMENUPOPUP:
1331 handled = webView->onUninitMenuPopup(wParam, lParam);
1333 case WM_XP_THEMECHANGED:
1334 if (Frame* coreFrame = core(mainFrameImpl)) {
1335 webView->deleteBackingStore();
1336 coreFrame->view()->themeChanged();
1339 case WM_MOUSEACTIVATE:
1340 webView->setMouseActivated(true);
1342 case WM_GETDLGCODE: {
1343 COMPtr<IWebUIDelegate> uiDelegate;
1344 COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
1345 LONG_PTR dlgCode = 0;
1348 LPMSG lpMsg = (LPMSG)lParam;
1349 if (lpMsg->message == WM_KEYDOWN)
1350 keyCode = (UINT) lpMsg->wParam;
1352 if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate &&
1353 SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate &&
1354 SUCCEEDED(uiDelegatePrivate->webViewGetDlgCode(webView, keyCode, &dlgCode)))
1360 case WM_IME_STARTCOMPOSITION:
1361 handled = webView->onIMEStartComposition();
1363 case WM_IME_REQUEST:
1364 webView->onIMERequest(wParam, lParam, &lResult);
1366 case WM_IME_COMPOSITION:
1367 handled = webView->onIMEComposition(lParam);
1369 case WM_IME_ENDCOMPOSITION:
1370 handled = webView->onIMEEndComposition();
1373 handled = webView->onIMEChar(wParam, lParam);
1376 handled = webView->onIMENotify(wParam, lParam, &lResult);
1379 handled = webView->onIMESelect(wParam, lParam);
1381 case WM_IME_SETCONTEXT:
1382 handled = webView->onIMESetContext(wParam, lParam);
1385 if (lastSetCursor) {
1386 SetCursor(lastSetCursor);
1396 lResult = DefWindowProc(hWnd, message, wParam, lParam);
1401 HRESULT WebView::updateWebCoreSettingsFromPreferences(IWebPreferences* preferences)
1408 Settings* settings = m_page->settings();
1410 hr = preferences->cursiveFontFamily(&str);
1413 settings->setCursiveFontFamily(AtomicString(str, SysStringLen(str)));
1416 hr = preferences->defaultFixedFontSize(&size);
1419 settings->setDefaultFixedFontSize(size);
1421 hr = preferences->defaultFontSize(&size);
1424 settings->setDefaultFontSize(size);
1426 hr = preferences->defaultTextEncodingName(&str);
1429 settings->setDefaultTextEncodingName(String(str, SysStringLen(str)));
1432 hr = preferences->fantasyFontFamily(&str);
1435 settings->setFantasyFontFamily(AtomicString(str, SysStringLen(str)));
1438 hr = preferences->fixedFontFamily(&str);
1441 settings->setFixedFontFamily(AtomicString(str, SysStringLen(str)));
1444 hr = preferences->isJavaEnabled(&enabled);
1447 settings->setJavaEnabled(!!enabled);
1449 hr = preferences->isJavaScriptEnabled(&enabled);
1452 settings->setJavaScriptEnabled(!!enabled);
1454 hr = preferences->javaScriptCanOpenWindowsAutomatically(&enabled);
1457 settings->setJavaScriptCanOpenWindowsAutomatically(!!enabled);
1459 hr = preferences->minimumFontSize(&size);
1462 settings->setMinimumFontSize(size);
1464 hr = preferences->minimumLogicalFontSize(&size);
1467 settings->setMinimumLogicalFontSize(size);
1469 hr = preferences->arePlugInsEnabled(&enabled);
1472 settings->setPluginsEnabled(!!enabled);
1474 hr = preferences->privateBrowsingEnabled(&enabled);
1477 settings->setPrivateBrowsingEnabled(!!enabled);
1479 hr = preferences->sansSerifFontFamily(&str);
1482 settings->setSansSerifFontFamily(AtomicString(str, SysStringLen(str)));
1485 hr = preferences->serifFontFamily(&str);
1488 settings->setSerifFontFamily(AtomicString(str, SysStringLen(str)));
1491 hr = preferences->standardFontFamily(&str);
1494 settings->setStandardFontFamily(AtomicString(str, SysStringLen(str)));
1497 hr = preferences->loadsImagesAutomatically(&enabled);
1500 settings->setLoadsImagesAutomatically(!!enabled);
1502 hr = preferences->userStyleSheetEnabled(&enabled);
1506 hr = preferences->userStyleSheetLocation(&str);
1510 RetainPtr<CFStringRef> urlString(AdoptCF, String(str, SysStringLen(str)).createCFString());
1511 RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithString(kCFAllocatorDefault, urlString.get(), 0));
1513 // Check if the passed in string is a path and convert it to a URL.
1514 // FIXME: This is a workaround for nightly builds until we can get Safari to pass
1515 // in an URL here. See <rdar://problem/5478378>
1517 DWORD len = SysStringLen(str) + 1;
1519 int result = WideCharToMultiByte(CP_UTF8, 0, str, len, 0, 0, 0, 0);
1520 Vector<UInt8> utf8Path(result);
1521 if (!WideCharToMultiByte(CP_UTF8, 0, str, len, (LPSTR)utf8Path.data(), result, 0, 0))
1524 url.adoptCF(CFURLCreateFromFileSystemRepresentation(0, utf8Path.data(), result - 1, false));
1527 settings->setUserStyleSheetLocation(url.get());
1530 settings->setUserStyleSheetLocation(KURL(DeprecatedString("")));
1533 hr = preferences->shouldPrintBackgrounds(&enabled);
1536 settings->setShouldPrintBackgrounds(!!enabled);
1538 hr = preferences->textAreasAreResizable(&enabled);
1541 settings->setTextAreasAreResizable(!!enabled);
1543 WebKitEditableLinkBehavior behavior;
1544 hr = preferences->editableLinkBehavior(&behavior);
1547 settings->setEditableLinkBehavior((EditableLinkBehavior)behavior);
1549 WebKitCookieStorageAcceptPolicy acceptPolicy;
1550 hr = preferences->cookieStorageAcceptPolicy(&acceptPolicy);
1554 hr = preferences->usesPageCache(&enabled);
1557 settings->setUsesPageCache(!!enabled);
1559 hr = preferences->isDOMPasteAllowed(&enabled);
1562 settings->setDOMPasteAllowed(!!enabled);
1564 ResourceHandle::setCookieStorageAcceptPolicy(acceptPolicy);
1566 settings->setShowsURLsInToolTips(false);
1568 settings->setForceFTPDirectoryListings(true);
1570 settings->setDeveloperExtrasEnabled(developerExtrasEnabled());
1572 m_mainFrame->invalidate(); // FIXME
1577 bool WebView::developerExtrasEnabled() const
1579 COMPtr<WebPreferences> webPrefs;
1580 if (SUCCEEDED(m_preferences->QueryInterface(IID_WebPreferences, (void**)&webPrefs)) && webPrefs->developerExtrasDisabledByOverride())
1584 BOOL enabled = FALSE;
1585 COMPtr<IWebPreferencesPrivate> prefsPrivate;
1586 return SUCCEEDED(m_preferences->QueryInterface(&prefsPrivate)) && SUCCEEDED(prefsPrivate->developerExtrasEnabled(&enabled)) && enabled;
1592 static String osVersion()
1595 OSVERSIONINFO versionInfo = {0};
1596 versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
1597 GetVersionEx(&versionInfo);
1599 if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
1600 if (versionInfo.dwMajorVersion == 4) {
1601 if (versionInfo.dwMinorVersion == 0)
1602 osVersion = "Windows 95";
1603 else if (versionInfo.dwMinorVersion == 10)
1604 osVersion = "Windows 98";
1605 else if (versionInfo.dwMinorVersion == 90)
1606 osVersion = "Windows 98; Win 9x 4.90";
1608 } else if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1609 osVersion = String::format("Windows NT %d.%d", versionInfo.dwMajorVersion, versionInfo.dwMinorVersion);
1611 if (!osVersion.length())
1612 osVersion = String::format("Windows %d.%d", versionInfo.dwMajorVersion, versionInfo.dwMinorVersion);
1617 static String webKitVersion()
1619 String versionStr = "420+";
1622 struct LANGANDCODEPAGE {
1627 TCHAR path[MAX_PATH];
1628 GetModuleFileName(gInstance, path, ARRAYSIZE(path));
1630 DWORD versionSize = GetFileVersionInfoSize(path, &handle);
1633 data = malloc(versionSize);
1636 if (!GetFileVersionInfo(path, 0, versionSize, data))
1639 if (!VerQueryValue(data, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate))
1642 _stprintf_s(key, ARRAYSIZE(key), TEXT("\\StringFileInfo\\%04x%04x\\ProductVersion"), lpTranslate[0].wLanguage, lpTranslate[0].wCodePage);
1643 LPCTSTR productVersion;
1644 UINT productVersionLength;
1645 if (!VerQueryValue(data, (LPTSTR)(LPCTSTR)key, (void**)&productVersion, &productVersionLength))
1647 versionStr = String(productVersion, productVersionLength);
1655 const String& WebView::userAgentForKURL(const KURL&)
1657 if (m_userAgentOverridden)
1658 return m_userAgentCustom;
1660 if (!m_userAgentStandard.length())
1661 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());
1662 return m_userAgentStandard;
1665 // IUnknown -------------------------------------------------------------------
1667 HRESULT STDMETHODCALLTYPE WebView::QueryInterface(REFIID riid, void** ppvObject)
1670 if (IsEqualGUID(riid, CLSID_WebView))
1672 else if (IsEqualGUID(riid, IID_IUnknown))
1673 *ppvObject = static_cast<IWebView*>(this);
1674 else if (IsEqualGUID(riid, IID_IWebView))
1675 *ppvObject = static_cast<IWebView*>(this);
1676 else if (IsEqualGUID(riid, IID_IWebViewPrivate))
1677 *ppvObject = static_cast<IWebViewPrivate*>(this);
1678 else if (IsEqualGUID(riid, IID_IWebIBActions))
1679 *ppvObject = static_cast<IWebIBActions*>(this);
1680 else if (IsEqualGUID(riid, IID_IWebViewCSS))
1681 *ppvObject = static_cast<IWebViewCSS*>(this);
1682 else if (IsEqualGUID(riid, IID_IWebViewEditing))
1683 *ppvObject = static_cast<IWebViewEditing*>(this);
1684 else if (IsEqualGUID(riid, IID_IWebViewUndoableEditing))
1685 *ppvObject = static_cast<IWebViewUndoableEditing*>(this);
1686 else if (IsEqualGUID(riid, IID_IWebViewEditingActions))
1687 *ppvObject = static_cast<IWebViewEditingActions*>(this);
1688 else if (IsEqualGUID(riid, IID_IWebNotificationObserver))
1689 *ppvObject = static_cast<IWebNotificationObserver*>(this);
1690 else if (IsEqualGUID(riid, IID_IDropTarget))
1691 *ppvObject = static_cast<IDropTarget*>(this);
1693 return E_NOINTERFACE;
1699 ULONG STDMETHODCALLTYPE WebView::AddRef(void)
1701 return ++m_refCount;
1704 ULONG STDMETHODCALLTYPE WebView::Release(void)
1706 ULONG newRef = --m_refCount;
1713 // IWebView --------------------------------------------------------------------
1715 HRESULT STDMETHODCALLTYPE WebView::canShowMIMEType(
1716 /* [in] */ BSTR mimeType,
1717 /* [retval][out] */ BOOL* canShow)
1719 String mimeTypeStr(mimeType, SysStringLen(mimeType));
1724 *canShow = MIMETypeRegistry::isSupportedImageMIMEType(mimeTypeStr) ||
1725 MIMETypeRegistry::isSupportedNonImageMIMEType(mimeTypeStr) ||
1726 PlugInInfoStore::supportsMIMEType(mimeTypeStr);
1731 HRESULT STDMETHODCALLTYPE WebView::canShowMIMETypeAsHTML(
1732 /* [in] */ BSTR /*mimeType*/,
1733 /* [retval][out] */ BOOL* canShow)
1740 HRESULT STDMETHODCALLTYPE WebView::MIMETypesShownAsHTML(
1741 /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
1743 ASSERT_NOT_REACHED();
1747 HRESULT STDMETHODCALLTYPE WebView::setMIMETypesShownAsHTML(
1748 /* [size_is][in] */ BSTR* /*mimeTypes*/,
1749 /* [in] */ int /*cMimeTypes*/)
1751 ASSERT_NOT_REACHED();
1755 HRESULT STDMETHODCALLTYPE WebView::URLFromPasteboard(
1756 /* [in] */ IDataObject* /*pasteboard*/,
1757 /* [retval][out] */ BSTR* /*url*/)
1759 ASSERT_NOT_REACHED();
1763 HRESULT STDMETHODCALLTYPE WebView::URLTitleFromPasteboard(
1764 /* [in] */ IDataObject* /*pasteboard*/,
1765 /* [retval][out] */ BSTR* /*urlTitle*/)
1767 ASSERT_NOT_REACHED();
1771 HRESULT STDMETHODCALLTYPE WebView::initWithFrame(
1772 /* [in] */ RECT frame,
1773 /* [in] */ BSTR frameName,
1774 /* [in] */ BSTR groupName)
1781 registerWebViewWindowClass();
1783 if (!::IsWindow(m_hostWindow)) {
1784 ASSERT_NOT_REACHED();
1788 m_viewWindow = CreateWindowEx(0, kWebViewWindowClassName, 0, WS_CHILD | WS_CLIPCHILDREN,
1789 frame.left, frame.top, frame.right - frame.left, frame.bottom - frame.top, m_hostWindow, 0, gInstance, 0);
1790 ASSERT(::IsWindow(m_viewWindow));
1792 hr = registerDragDrop();
1796 m_groupName = String(groupName, SysStringLen(groupName));
1798 m_page = new Page(new WebChromeClient(this), new WebContextMenuClient(this), new WebEditorClient(this), new WebDragClient(this), new WebInspectorClient(this));
1799 // FIXME: 4931464 - When we do cache pages on Windows this needs to be removed so the "should I cache this page?" check
1800 // in FrameLoader::provisionalLoadStarted() doesn't always fail
1801 m_page->settings()->setUsesPageCache(false);
1803 // Try to set the FTP Directory template path in WebCore when the first WebView is initialized
1804 static bool setFTPDirectoryTemplatePathOnce = false;
1806 if (!setFTPDirectoryTemplatePathOnce && m_uiDelegate) {
1807 COMPtr<IWebUIDelegate2> uiDelegate2;
1808 if (SUCCEEDED(m_uiDelegate->QueryInterface(IID_IWebUIDelegate2, (void**)&uiDelegate2))) {
1810 if (SUCCEEDED(uiDelegate2->ftpDirectoryTemplatePath(this, &path))) {
1811 m_page->settings()->setFTPDirectoryTemplatePath(String(path, SysStringLen(path)));
1812 SysFreeString(path);
1813 setFTPDirectoryTemplatePathOnce = true;
1818 WebFrame* webFrame = WebFrame::createInstance();
1819 webFrame->initWithWebFrameView(0 /*FIXME*/, this, m_page, 0);
1820 m_mainFrame = webFrame;
1821 webFrame->Release(); // The WebFrame is owned by the Frame, so release our reference to it.
1822 m_page->mainFrame()->view()->resize(frame.right - frame.left, frame.bottom - frame.top);
1824 m_page->mainFrame()->tree()->setName(String(frameName, SysStringLen(frameName)));
1825 m_page->mainFrame()->init();
1826 m_page->setGroupName(m_groupName);
1828 #pragma warning(suppress: 4244)
1829 SetWindowLongPtr(m_viewWindow, 0, (LONG_PTR)this);
1830 ShowWindow(m_viewWindow, SW_SHOW);
1832 initializeCacheSizesIfNecessary();
1833 initializeToolTipWindow();
1835 // Update WebCore with preferences. These values will either come from an archived WebPreferences,
1836 // or from the standard preferences, depending on whether this method was called from initWithCoder:
1837 // or initWithFrame, respectively.
1838 //[self _updateWebCoreSettingsFromPreferences: [self preferences]];
1839 COMPtr<IWebPreferences> prefs;
1840 if (FAILED(preferences(&prefs)))
1842 hr = updateWebCoreSettingsFromPreferences(prefs.get());
1846 // Use default cookie storage
1847 RetainPtr<CFHTTPCookieStorageRef> cookies(AdoptCF, CFHTTPCookieStorageCreateFromFile(kCFAllocatorDefault, 0, 0));
1848 ResourceHandle::setCookieStorage(cookies.get());
1850 // Register to receive notifications whenever preference values change.
1851 //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
1852 // name:WebPreferencesChangedNotification object:[self preferences]];
1853 IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
1854 if (!WebPreferences::webPreferencesChangedNotification())
1855 return E_OUTOFMEMORY;
1856 notifyCenter->addObserver(this, WebPreferences::webPreferencesChangedNotification(), prefs.get());
1858 setSmartInsertDeleteEnabled(TRUE);
1862 static bool initCommonControls()
1864 static bool haveInitialized = false;
1865 if (haveInitialized)
1868 INITCOMMONCONTROLSEX init;
1869 init.dwSize = sizeof(init);
1870 init.dwICC = ICC_TREEVIEW_CLASSES;
1871 haveInitialized = !!::InitCommonControlsEx(&init);
1872 return haveInitialized;
1875 void WebView::initializeToolTipWindow()
1877 if (!initCommonControls())
1880 m_toolTipHwnd = CreateWindowEx(0, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
1881 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1882 m_viewWindow, 0, 0, 0);
1886 TOOLINFO info = {0};
1887 info.cbSize = sizeof(info);
1888 info.uFlags = TTF_IDISHWND | TTF_SUBCLASS ;
1889 info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
1891 ::SendMessage(m_toolTipHwnd, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info));
1892 ::SendMessage(m_toolTipHwnd, TTM_SETMAXTIPWIDTH, 0, maxToolTipWidth);
1894 ::SetWindowPos(m_toolTipHwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1897 void WebView::setToolTip(const String& toolTip)
1902 if (toolTip == m_toolTip)
1905 m_toolTip = toolTip;
1907 if (!m_toolTip.isEmpty()) {
1908 TOOLINFO info = {0};
1909 info.cbSize = sizeof(info);
1910 info.uFlags = TTF_IDISHWND;
1911 info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
1912 info.lpszText = const_cast<UChar*>(m_toolTip.charactersWithNullTermination());
1913 ::SendMessage(m_toolTipHwnd, TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info));
1916 ::SendMessage(m_toolTipHwnd, TTM_ACTIVATE, !m_toolTip.isEmpty(), 0);
1919 HRESULT WebView::notifyDidAddIcon(IWebNotification* notification)
1921 COMPtr<IPropertyBag> propertyBag;
1922 HRESULT hr = notification->userInfo(&propertyBag);
1928 COMPtr<CFDictionaryPropertyBag> dictionaryPropertyBag;
1929 hr = propertyBag->QueryInterface(IID_CFDictionaryPropertyBag, (void**)&dictionaryPropertyBag);
1933 CFDictionaryRef dictionary = dictionaryPropertyBag->dictionary();
1937 CFTypeRef value = CFDictionaryGetValue(dictionary, WebIconDatabase::iconDatabaseNotificationUserInfoURLKey());
1940 if (CFGetTypeID(value) != CFStringGetTypeID())
1943 String mainFrameURL;
1945 mainFrameURL = m_mainFrame->url().url();
1947 if (!mainFrameURL.isEmpty() && mainFrameURL == String((CFStringRef)value))
1948 dispatchDidReceiveIconFromWebFrame(m_mainFrame);
1953 void WebView::registerForIconNotification(bool listen)
1955 IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
1957 nc->addObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
1959 nc->removeObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
1962 void WebView::dispatchDidReceiveIconFromWebFrame(WebFrame* frame)
1964 registerForIconNotification(false);
1966 if (m_frameLoadDelegate)
1967 // FIXME: <rdar://problem/5491010> - Pass in the right HBITMAP.
1968 m_frameLoadDelegate->didReceiveIcon(this, 0, frame);
1971 HRESULT STDMETHODCALLTYPE WebView::setUIDelegate(
1972 /* [in] */ IWebUIDelegate* d)
1976 if (m_uiDelegatePrivate)
1977 m_uiDelegatePrivate = 0;
1980 if (FAILED(d->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&m_uiDelegatePrivate)))
1981 m_uiDelegatePrivate = 0;
1987 HRESULT STDMETHODCALLTYPE WebView::uiDelegate(
1988 /* [out][retval] */ IWebUIDelegate** d)
1993 return m_uiDelegate.copyRefTo(d);
1996 HRESULT STDMETHODCALLTYPE WebView::setResourceLoadDelegate(
1997 /* [in] */ IWebResourceLoadDelegate* d)
1999 m_resourceLoadDelegate = d;
2003 HRESULT STDMETHODCALLTYPE WebView::resourceLoadDelegate(
2004 /* [out][retval] */ IWebResourceLoadDelegate** d)
2006 if (!m_resourceLoadDelegate)
2009 return m_resourceLoadDelegate.copyRefTo(d);
2012 HRESULT STDMETHODCALLTYPE WebView::setDownloadDelegate(
2013 /* [in] */ IWebDownloadDelegate* d)
2015 m_downloadDelegate = d;
2019 HRESULT STDMETHODCALLTYPE WebView::downloadDelegate(
2020 /* [out][retval] */ IWebDownloadDelegate** d)
2022 if (!m_downloadDelegate)
2025 return m_downloadDelegate.copyRefTo(d);
2028 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegate(
2029 /* [in] */ IWebFrameLoadDelegate* d)
2031 m_frameLoadDelegate = d;
2035 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegate(
2036 /* [out][retval] */ IWebFrameLoadDelegate** d)
2038 if (!m_frameLoadDelegate)
2041 return m_frameLoadDelegate.copyRefTo(d);
2044 HRESULT STDMETHODCALLTYPE WebView::setPolicyDelegate(
2045 /* [in] */ IWebPolicyDelegate* d)
2047 m_policyDelegate = d;
2051 HRESULT STDMETHODCALLTYPE WebView::policyDelegate(
2052 /* [out][retval] */ IWebPolicyDelegate** d)
2054 if (!m_policyDelegate)
2056 return m_policyDelegate.copyRefTo(d);
2059 HRESULT STDMETHODCALLTYPE WebView::mainFrame(
2060 /* [out][retval] */ IWebFrame** frame)
2063 ASSERT_NOT_REACHED();
2067 *frame = m_mainFrame;
2071 m_mainFrame->AddRef();
2075 HRESULT STDMETHODCALLTYPE WebView::focusedFrame(
2076 /* [out][retval] */ IWebFrame** frame)
2079 ASSERT_NOT_REACHED();
2084 Frame* f = m_page->focusController()->focusedFrame();
2088 WebFrame* webFrame = kit(f);
2092 return webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
2094 HRESULT STDMETHODCALLTYPE WebView::backForwardList(
2095 /* [out][retval] */ IWebBackForwardList** list)
2097 if (!m_useBackForwardList)
2100 *list = WebBackForwardList::createInstance(m_page->backForwardList());
2105 HRESULT STDMETHODCALLTYPE WebView::setMaintainsBackForwardList(
2106 /* [in] */ BOOL flag)
2108 m_useBackForwardList = !!flag;
2112 HRESULT STDMETHODCALLTYPE WebView::goBack(
2113 /* [retval][out] */ BOOL* succeeded)
2115 *succeeded = m_page->goBack();
2119 HRESULT STDMETHODCALLTYPE WebView::goForward(
2120 /* [retval][out] */ BOOL* succeeded)
2122 *succeeded = m_page->goForward();
2126 HRESULT STDMETHODCALLTYPE WebView::goToBackForwardItem(
2127 /* [in] */ IWebHistoryItem* item,
2128 /* [retval][out] */ BOOL* succeeded)
2132 COMPtr<WebHistoryItem> webHistoryItem;
2133 HRESULT hr = item->QueryInterface(CLSID_WebHistoryItem, (void**)&webHistoryItem);
2137 m_page->goToItem(webHistoryItem->historyItem(), FrameLoadTypeIndexedBackForward);
2143 HRESULT STDMETHODCALLTYPE WebView::setTextSizeMultiplier(
2144 /* [in] */ float multiplier)
2146 if (m_textSizeMultiplier != multiplier)
2147 m_textSizeMultiplier = multiplier;
2152 m_mainFrame->setTextSizeMultiplier(multiplier);
2156 HRESULT STDMETHODCALLTYPE WebView::textSizeMultiplier(
2157 /* [retval][out] */ float* multiplier)
2159 *multiplier = m_textSizeMultiplier;
2163 HRESULT STDMETHODCALLTYPE WebView::setApplicationNameForUserAgent(
2164 /* [in] */ BSTR applicationName)
2166 m_applicationName = String(applicationName, SysStringLen(applicationName));
2167 m_userAgentStandard = String();
2171 HRESULT STDMETHODCALLTYPE WebView::applicationNameForUserAgent(
2172 /* [retval][out] */ BSTR* applicationName)
2174 *applicationName = SysAllocStringLen(m_applicationName.characters(), m_applicationName.length());
2175 if (!*applicationName && m_applicationName.length())
2176 return E_OUTOFMEMORY;
2180 HRESULT STDMETHODCALLTYPE WebView::setCustomUserAgent(
2181 /* [in] */ BSTR userAgentString)
2183 m_userAgentOverridden = true;
2184 m_userAgentCustom = String(userAgentString, SysStringLen(userAgentString));
2188 HRESULT STDMETHODCALLTYPE WebView::customUserAgent(
2189 /* [retval][out] */ BSTR* userAgentString)
2191 *userAgentString = 0;
2192 if (!m_userAgentOverridden)
2194 *userAgentString = SysAllocStringLen(m_userAgentCustom.characters(), m_userAgentCustom.length());
2195 if (!*userAgentString && m_userAgentCustom.length())
2196 return E_OUTOFMEMORY;
2200 HRESULT STDMETHODCALLTYPE WebView::userAgentForURL(
2201 /* [in] */ BSTR url,
2202 /* [retval][out] */ BSTR* userAgent)
2204 DeprecatedString urlStr((DeprecatedChar*)url, SysStringLen(url));
2205 String userAgentString = this->userAgentForKURL(KURL(urlStr));
2206 *userAgent = SysAllocStringLen(userAgentString.characters(), userAgentString.length());
2207 if (!*userAgent && userAgentString.length())
2208 return E_OUTOFMEMORY;
2212 HRESULT STDMETHODCALLTYPE WebView::supportsTextEncoding(
2213 /* [retval][out] */ BOOL* supports)
2219 HRESULT STDMETHODCALLTYPE WebView::setCustomTextEncodingName(
2220 /* [in] */ BSTR encodingName)
2227 hr = customTextEncodingName(&oldEncoding);
2231 if (oldEncoding != encodingName && (!oldEncoding || !encodingName || _tcscmp(oldEncoding, encodingName))) {
2232 if (Frame* coreFrame = core(m_mainFrame))
2233 coreFrame->loader()->reloadAllowingStaleData(String(encodingName, SysStringLen(encodingName)));
2239 HRESULT STDMETHODCALLTYPE WebView::customTextEncodingName(
2240 /* [retval][out] */ BSTR* encodingName)
2243 COMPtr<IWebDataSource> dataSource;
2244 COMPtr<WebDataSource> dataSourceImpl;
2250 if (FAILED(m_mainFrame->provisionalDataSource(&dataSource)) || !dataSource) {
2251 hr = m_mainFrame->dataSource(&dataSource);
2252 if (FAILED(hr) || !dataSource)
2256 hr = dataSource->QueryInterface(IID_WebDataSource, (void**)&dataSourceImpl);
2260 BString str = dataSourceImpl->documentLoader()->overrideEncoding();
2265 *encodingName = SysAllocStringLen(m_overrideEncoding.characters(), m_overrideEncoding.length());
2267 if (!*encodingName && m_overrideEncoding.length())
2268 return E_OUTOFMEMORY;
2273 HRESULT STDMETHODCALLTYPE WebView::setMediaStyle(
2274 /* [in] */ BSTR /*media*/)
2276 ASSERT_NOT_REACHED();
2280 HRESULT STDMETHODCALLTYPE WebView::mediaStyle(
2281 /* [retval][out] */ BSTR* /*media*/)
2283 ASSERT_NOT_REACHED();
2287 HRESULT STDMETHODCALLTYPE WebView::stringByEvaluatingJavaScriptFromString(
2288 /* [in] */ BSTR script, // assumes input does not have "JavaScript" at the begining.
2289 /* [retval][out] */ BSTR* result)
2292 ASSERT_NOT_REACHED();
2298 Frame* coreFrame = core(m_mainFrame);
2302 KJS::JSValue* scriptExecutionResult = coreFrame->loader()->executeScript(WebCore::String(script), true);
2303 if(!scriptExecutionResult)
2305 else if (scriptExecutionResult->isString()) {
2307 *result = BString(String(scriptExecutionResult->getString()));
2313 HRESULT STDMETHODCALLTYPE WebView::windowScriptObject(
2314 /* [retval][out] */ IWebScriptObject** /*webScriptObject*/)
2316 ASSERT_NOT_REACHED();
2320 HRESULT STDMETHODCALLTYPE WebView::setPreferences(
2321 /* [in] */ IWebPreferences* prefs)
2323 if (m_preferences == prefs)
2326 IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
2327 COMPtr<IWebPreferences> oldPrefs;
2328 if (SUCCEEDED(preferences(&oldPrefs)) && oldPrefs) {
2329 nc->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), oldPrefs.get());
2330 BSTR identifier = 0;
2331 HRESULT hr = oldPrefs->identifier(&identifier);
2332 oldPrefs = 0; // make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
2334 WebPreferences::removeReferenceForIdentifier(identifier);
2336 SysFreeString(identifier);
2338 m_preferences = prefs;
2339 COMPtr<IWebPreferences> newPrefs;
2340 if (SUCCEEDED(preferences(&newPrefs)))
2341 nc->addObserver(this, WebPreferences::webPreferencesChangedNotification(), newPrefs.get());
2342 HRESULT hr = nc->postNotificationName(WebPreferences::webPreferencesChangedNotification(), newPrefs.get(), 0);
2349 HRESULT STDMETHODCALLTYPE WebView::preferences(
2350 /* [retval][out] */ IWebPreferences** prefs)
2355 m_preferences = WebPreferences::sharedStandardPreferences();
2357 m_preferences.copyRefTo(prefs);
2361 HRESULT STDMETHODCALLTYPE WebView::setPreferencesIdentifier(
2362 /* [in] */ BSTR /*anIdentifier*/)
2364 ASSERT_NOT_REACHED();
2368 HRESULT STDMETHODCALLTYPE WebView::preferencesIdentifier(
2369 /* [retval][out] */ BSTR* /*anIdentifier*/)
2371 ASSERT_NOT_REACHED();
2375 HRESULT STDMETHODCALLTYPE WebView::setHostWindow(
2376 /* [in] */ OLE_HANDLE oleWindow)
2378 HWND window = (HWND)(ULONG64)oleWindow;
2379 if (m_viewWindow && window)
2380 SetParent(m_viewWindow, window);
2382 m_hostWindow = window;
2387 HRESULT STDMETHODCALLTYPE WebView::hostWindow(
2388 /* [retval][out] */ OLE_HANDLE* window)
2390 *window = (OLE_HANDLE)(ULONG64)m_hostWindow;
2395 static Frame *incrementFrame(Frame *curr, bool forward, bool wrapFlag)
2398 ? curr->tree()->traverseNextWithWrap(wrapFlag)
2399 : curr->tree()->traversePreviousWithWrap(wrapFlag);
2402 HRESULT STDMETHODCALLTYPE WebView::searchFor(
2403 /* [in] */ BSTR str,
2404 /* [in] */ BOOL forward,
2405 /* [in] */ BOOL caseFlag,
2406 /* [in] */ BOOL wrapFlag,
2407 /* [retval][out] */ BOOL* found)
2410 return E_INVALIDARG;
2412 if (!m_page || !m_page->mainFrame())
2413 return E_UNEXPECTED;
2415 if (!str || !SysStringLen(str))
2416 return E_INVALIDARG;
2418 String search(str, SysStringLen(str));
2421 WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame();
2422 WebCore::Frame* startFrame = frame;
2424 *found = frame->findString(search, !!forward, !!caseFlag, false, true);
2426 if (frame != startFrame)
2427 startFrame->selectionController()->clear();
2428 m_page->focusController()->setFocusedFrame(frame);
2431 frame = incrementFrame(frame, !!forward, !!wrapFlag);
2432 } while (frame && frame != startFrame);
2434 // Search contents of startFrame, on the other side of the selection that we did earlier.
2435 // We cheat a bit and just research with wrap on
2436 if (wrapFlag && !startFrame->selectionController()->isNone()) {
2437 *found = startFrame->findString(search, !!forward, !!caseFlag, true, true);
2438 m_page->focusController()->setFocusedFrame(frame);
2444 HRESULT STDMETHODCALLTYPE WebView::updateActiveState()
2446 Frame* frame = m_page->mainFrame();
2448 HWND window = ::GetAncestor(m_viewWindow, GA_ROOT);
2449 HWND activeWindow = ::GetActiveWindow();
2450 bool windowIsKey = window == activeWindow;
2451 activeWindow = ::GetAncestor(activeWindow, GA_ROOTOWNER);
2453 bool windowOrSheetIsKey = windowIsKey || (window == activeWindow);
2455 frame->setIsActive(windowIsKey);
2457 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
2458 frame->setWindowHasFocus(frame == focusedFrame && windowOrSheetIsKey);
2463 HRESULT STDMETHODCALLTYPE WebView::markAllMatchesForText(
2464 BSTR str, BOOL caseSensitive, BOOL highlight, UINT limit, UINT* matches)
2467 return E_INVALIDARG;
2469 if (!m_page || !m_page->mainFrame())
2470 return E_UNEXPECTED;
2472 if (!str || !SysStringLen(str))
2473 return E_INVALIDARG;
2475 String search(str, SysStringLen(str));
2478 WebCore::Frame* frame = m_page->mainFrame();
2480 frame->setMarkedTextMatchesAreHighlighted(!!highlight);
2481 *matches += frame->markAllMatchesForText(search, !!caseSensitive, (limit == 0)? 0 : (limit - *matches));
2482 frame = incrementFrame(frame, true, false);
2489 HRESULT STDMETHODCALLTYPE WebView::unmarkAllTextMatches()
2491 if (!m_page || !m_page->mainFrame())
2492 return E_UNEXPECTED;
2494 WebCore::Frame* frame = m_page->mainFrame();
2496 if (Document* document = frame->document())
2497 document->removeMarkers(DocumentMarker::TextMatch);
2498 frame = incrementFrame(frame, true, false);
2505 HRESULT STDMETHODCALLTYPE WebView::rectsForTextMatches(
2506 IEnumTextMatches** pmatches)
2508 Vector<IntRect> allRects;
2509 WebCore::Frame* frame = m_page->mainFrame();
2511 if (Document* document = frame->document()) {
2512 IntRect visibleRect = enclosingIntRect(frame->view()->visibleContentRect());
2513 Vector<IntRect> frameRects = document->renderedRectsForMarkers(DocumentMarker::TextMatch);
2514 IntPoint frameOffset(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height());
2515 frameOffset = frame->view()->convertToContainingWindow(frameOffset);
2517 Vector<IntRect>::iterator end = frameRects.end();
2518 for (Vector<IntRect>::iterator it = frameRects.begin(); it < end; it++) {
2519 it->intersect(visibleRect);
2520 it->move(frameOffset.x(), frameOffset.y());
2521 allRects.append(*it);
2524 frame = incrementFrame(frame, true, false);
2527 return createMatchEnumerator(&allRects, pmatches);
2530 HRESULT STDMETHODCALLTYPE WebView::generateSelectionImage(BOOL forceWhiteText, OLE_HANDLE* hBitmap)
2534 WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame();
2537 HBITMAP bitmap = imageFromSelection(frame, forceWhiteText ? TRUE : FALSE);
2538 *hBitmap = (OLE_HANDLE)(ULONG64)bitmap;
2544 HRESULT STDMETHODCALLTYPE WebView::selectionImageRect(RECT* rc)
2546 WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame();
2549 IntRect ir = enclosingIntRect(frame->selectionRect());
2550 ir = frame->view()->convertToContainingWindow(ir);
2551 ir.move(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height());
2554 rc->bottom = rc->top + ir.height();
2555 rc->right = rc->left + ir.width();
2561 HRESULT STDMETHODCALLTYPE WebView::registerViewClass(
2562 /* [in] */ IWebDocumentView* /*view*/,
2563 /* [in] */ IWebDocumentRepresentation* /*representation*/,
2564 /* [in] */ BSTR /*forMIMEType*/)
2566 ASSERT_NOT_REACHED();
2570 HRESULT STDMETHODCALLTYPE WebView::setGroupName(
2571 /* [in] */ BSTR groupName)
2573 m_groupName = String(groupName, SysStringLen(groupName));
2577 HRESULT STDMETHODCALLTYPE WebView::groupName(
2578 /* [retval][out] */ BSTR* groupName)
2580 *groupName = SysAllocStringLen(m_groupName.characters(), m_groupName.length());
2581 if (!*groupName && m_groupName.length())
2582 return E_OUTOFMEMORY;
2586 HRESULT STDMETHODCALLTYPE WebView::estimatedProgress(
2587 /* [retval][out] */ double* estimatedProgress)
2589 *estimatedProgress = m_page->progress()->estimatedProgress();
2593 HRESULT STDMETHODCALLTYPE WebView::isLoading(
2594 /* [retval][out] */ BOOL* isLoading)
2596 COMPtr<IWebDataSource> dataSource;
2597 COMPtr<IWebDataSource> provisionalDataSource;
2604 if (SUCCEEDED(m_mainFrame->dataSource(&dataSource)))
2605 dataSource->isLoading(isLoading);
2610 if (SUCCEEDED(m_mainFrame->provisionalDataSource(&provisionalDataSource)))
2611 provisionalDataSource->isLoading(isLoading);
2615 HRESULT STDMETHODCALLTYPE WebView::elementAtPoint(
2616 /* [in] */ LPPOINT point,
2617 /* [retval][out] */ IPropertyBag** elementDictionary)
2619 if (!elementDictionary) {
2620 ASSERT_NOT_REACHED();
2624 *elementDictionary = 0;
2626 Frame* frame = core(m_mainFrame);
2630 IntPoint webCorePoint = IntPoint(point->x, point->y);
2631 HitTestResult result = HitTestResult(webCorePoint);
2632 if (frame->renderer())
2633 result = frame->eventHandler()->hitTestResultAtPoint(webCorePoint, false);
2634 *elementDictionary = WebElementPropertyBag::createInstance(result);
2638 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForSelection(
2639 /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
2641 ASSERT_NOT_REACHED();
2645 HRESULT STDMETHODCALLTYPE WebView::writeSelectionWithPasteboardTypes(
2646 /* [size_is][in] */ BSTR* /*types*/,
2647 /* [in] */ int /*cTypes*/,
2648 /* [in] */ IDataObject* /*pasteboard*/)
2650 ASSERT_NOT_REACHED();
2654 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForElement(
2655 /* [in] */ IPropertyBag* /*elementDictionary*/,
2656 /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
2658 ASSERT_NOT_REACHED();
2662 HRESULT STDMETHODCALLTYPE WebView::writeElement(
2663 /* [in] */ IPropertyBag* /*elementDictionary*/,
2664 /* [size_is][in] */ BSTR* /*withPasteboardTypes*/,
2665 /* [in] */ int /*cWithPasteboardTypes*/,
2666 /* [in] */ IDataObject* /*pasteboard*/)
2668 ASSERT_NOT_REACHED();
2672 HRESULT STDMETHODCALLTYPE WebView::selectedText(
2673 /* [out, retval] */ BSTR* text)
2676 ASSERT_NOT_REACHED();
2682 Frame* focusedFrame = (m_page && m_page->focusController()) ? m_page->focusController()->focusedOrMainFrame() : 0;
2686 String frameSelectedText = focusedFrame->selectedText();
2687 *text = SysAllocStringLen(frameSelectedText.characters(), frameSelectedText.length());
2688 if (!*text && frameSelectedText.length())
2689 return E_OUTOFMEMORY;
2693 HRESULT STDMETHODCALLTYPE WebView::centerSelectionInVisibleArea(
2694 /* [in] */ IUnknown* /* sender */)
2696 Frame* coreFrame = core(m_mainFrame);
2700 coreFrame->revealSelection(RenderLayer::gAlignCenterAlways);
2705 HRESULT STDMETHODCALLTYPE WebView::moveDragCaretToPoint(
2706 /* [in] */ LPPOINT /*point*/)
2708 ASSERT_NOT_REACHED();
2712 HRESULT STDMETHODCALLTYPE WebView::removeDragCaret( void)
2714 ASSERT_NOT_REACHED();
2718 HRESULT STDMETHODCALLTYPE WebView::setDrawsBackground(
2719 /* [in] */ BOOL /*drawsBackground*/)
2721 ASSERT_NOT_REACHED();
2725 HRESULT STDMETHODCALLTYPE WebView::drawsBackground(
2726 /* [retval][out] */ BOOL* /*drawsBackground*/)
2728 ASSERT_NOT_REACHED();
2732 HRESULT STDMETHODCALLTYPE WebView::setMainFrameURL(
2733 /* [in] */ BSTR /*urlString*/)
2735 ASSERT_NOT_REACHED();
2739 HRESULT STDMETHODCALLTYPE WebView::mainFrameURL(
2740 /* [retval][out] */ BSTR* /*urlString*/)
2742 ASSERT_NOT_REACHED();
2746 HRESULT STDMETHODCALLTYPE WebView::mainFrameDocument(
2747 /* [retval][out] */ IDOMDocument** document)
2753 return m_mainFrame->DOMDocument(document);
2756 HRESULT STDMETHODCALLTYPE WebView::mainFrameTitle(
2757 /* [retval][out] */ BSTR* /*title*/)
2759 ASSERT_NOT_REACHED();
2763 HRESULT STDMETHODCALLTYPE WebView::mainFrameIcon(
2764 /* [retval][out] */ OLE_HANDLE* /*hBitmap*/)
2766 ASSERT_NOT_REACHED();
2770 // IWebIBActions ---------------------------------------------------------------
2772 HRESULT STDMETHODCALLTYPE WebView::takeStringURLFrom(
2773 /* [in] */ IUnknown* /*sender*/)
2775 ASSERT_NOT_REACHED();
2779 HRESULT STDMETHODCALLTYPE WebView::stopLoading(
2780 /* [in] */ IUnknown* /*sender*/)
2785 return m_mainFrame->stopLoading();
2788 HRESULT STDMETHODCALLTYPE WebView::reload(
2789 /* [in] */ IUnknown* /*sender*/)
2794 return m_mainFrame->reload();
2797 HRESULT STDMETHODCALLTYPE WebView::canGoBack(
2798 /* [in] */ IUnknown* /*sender*/,
2799 /* [retval][out] */ BOOL* result)
2801 *result = !!m_page->backForwardList()->backItem();
2805 HRESULT STDMETHODCALLTYPE WebView::goBack(
2806 /* [in] */ IUnknown* /*sender*/)
2808 ASSERT_NOT_REACHED();
2812 HRESULT STDMETHODCALLTYPE WebView::canGoForward(
2813 /* [in] */ IUnknown* /*sender*/,
2814 /* [retval][out] */ BOOL* result)
2816 *result = !!m_page->backForwardList()->forwardItem();
2820 HRESULT STDMETHODCALLTYPE WebView::goForward(
2821 /* [in] */ IUnknown* /*sender*/)
2823 ASSERT_NOT_REACHED();
2827 #define MinimumTextSizeMultiplier 0.5f
2828 #define MaximumTextSizeMultiplier 3.0f
2829 #define TextSizeMultiplierRatio 1.2f
2831 HRESULT STDMETHODCALLTYPE WebView::canMakeTextLarger(
2832 /* [in] */ IUnknown* /*sender*/,
2833 /* [retval][out] */ BOOL* result)
2835 bool canGrowMore = m_textSizeMultiplier*TextSizeMultiplierRatio < MaximumTextSizeMultiplier;
2836 *result = canGrowMore ? TRUE : FALSE;
2840 HRESULT STDMETHODCALLTYPE WebView::makeTextLarger(
2841 /* [in] */ IUnknown* /*sender*/)
2843 float newScale = m_textSizeMultiplier*TextSizeMultiplierRatio;
2844 bool canGrowMore = newScale < MaximumTextSizeMultiplier;
2847 return setTextSizeMultiplier(newScale);
2851 HRESULT STDMETHODCALLTYPE WebView::canMakeTextSmaller(
2852 /* [in] */ IUnknown* /*sender*/,
2853 /* [retval][out] */ BOOL* result)
2855 bool canShrinkMore = m_textSizeMultiplier/TextSizeMultiplierRatio > MinimumTextSizeMultiplier;
2856 *result = canShrinkMore ? TRUE : FALSE;
2860 HRESULT STDMETHODCALLTYPE WebView::makeTextSmaller(
2861 /* [in] */ IUnknown* /*sender*/)
2863 float newScale = m_textSizeMultiplier/TextSizeMultiplierRatio;
2864 bool canShrinkMore = newScale > MinimumTextSizeMultiplier;
2867 return setTextSizeMultiplier(newScale);
2870 HRESULT STDMETHODCALLTYPE WebView::canMakeTextStandardSize(
2871 /* [in] */ IUnknown* /*sender*/,
2872 /* [retval][out] */ BOOL* result)
2874 bool notAlreadyStandard = m_textSizeMultiplier != 1.0f;
2875 *result = notAlreadyStandard ? TRUE : FALSE;
2879 HRESULT STDMETHODCALLTYPE WebView::makeTextStandardSize(
2880 /* [in] */ IUnknown* /*sender*/)
2882 bool notAlreadyStandard = m_textSizeMultiplier != 1.0f;
2883 if (notAlreadyStandard)
2884 return setTextSizeMultiplier(1.0f);
2888 HRESULT STDMETHODCALLTYPE WebView::toggleContinuousSpellChecking(
2889 /* [in] */ IUnknown* /*sender*/)
2893 if (FAILED(hr = isContinuousSpellCheckingEnabled(&enabled)))
2895 return setContinuousSpellCheckingEnabled(enabled ? FALSE : TRUE);
2898 HRESULT STDMETHODCALLTYPE WebView::toggleSmartInsertDelete(
2899 /* [in] */ IUnknown* /*sender*/)
2901 BOOL enabled = FALSE;
2902 HRESULT hr = smartInsertDeleteEnabled(&enabled);
2906 return setSmartInsertDeleteEnabled(enabled ? FALSE : TRUE);
2909 HRESULT STDMETHODCALLTYPE WebView::toggleGrammarChecking(
2910 /* [in] */ IUnknown* /*sender*/)
2913 HRESULT hr = isGrammarCheckingEnabled(&enabled);
2917 return setGrammarCheckingEnabled(enabled ? FALSE : TRUE);
2920 // IWebViewCSS -----------------------------------------------------------------
2922 HRESULT STDMETHODCALLTYPE WebView::computedStyleForElement(
2923 /* [in] */ IDOMElement* /*element*/,
2924 /* [in] */ BSTR /*pseudoElement*/,
2925 /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
2927 ASSERT_NOT_REACHED();
2931 // IWebViewEditing -------------------------------------------------------------
2933 HRESULT STDMETHODCALLTYPE WebView::editableDOMRangeForPoint(
2934 /* [in] */ LPPOINT /*point*/,
2935 /* [retval][out] */ IDOMRange** /*range*/)
2937 ASSERT_NOT_REACHED();
2941 HRESULT STDMETHODCALLTYPE WebView::setSelectedDOMRange(
2942 /* [in] */ IDOMRange* /*range*/,
2943 /* [in] */ WebSelectionAffinity /*affinity*/)
2945 ASSERT_NOT_REACHED();
2949 HRESULT STDMETHODCALLTYPE WebView::selectedDOMRange(
2950 /* [retval][out] */ IDOMRange** /*range*/)
2952 ASSERT_NOT_REACHED();
2956 HRESULT STDMETHODCALLTYPE WebView::selectionAffinity(
2957 /* [retval][out][retval][out] */ WebSelectionAffinity* /*affinity*/)
2959 ASSERT_NOT_REACHED();
2963 HRESULT STDMETHODCALLTYPE WebView::setEditable(
2964 /* [in] */ BOOL /*flag*/)
2966 ASSERT_NOT_REACHED();
2970 HRESULT STDMETHODCALLTYPE WebView::isEditable(
2971 /* [retval][out] */ BOOL* /*isEditable*/)
2973 ASSERT_NOT_REACHED();
2977 HRESULT STDMETHODCALLTYPE WebView::setTypingStyle(
2978 /* [in] */ IDOMCSSStyleDeclaration* /*style*/)
2980 ASSERT_NOT_REACHED();
2984 HRESULT STDMETHODCALLTYPE WebView::typingStyle(
2985 /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
2987 ASSERT_NOT_REACHED();
2991 HRESULT STDMETHODCALLTYPE WebView::setSmartInsertDeleteEnabled(
2992 /* [in] */ BOOL flag)
2994 m_smartInsertDeleteEnabled = !!flag;
2998 HRESULT STDMETHODCALLTYPE WebView::smartInsertDeleteEnabled(
2999 /* [retval][out] */ BOOL* enabled)
3001 *enabled = m_smartInsertDeleteEnabled ? TRUE : FALSE;
3005 HRESULT STDMETHODCALLTYPE WebView::setContinuousSpellCheckingEnabled(
3006 /* [in] */ BOOL flag)
3008 if (continuousSpellCheckingEnabled != !!flag) {
3009 continuousSpellCheckingEnabled = !!flag;
3010 COMPtr<IWebPreferences> prefs;
3011 if (SUCCEEDED(preferences(&prefs)))
3012 prefs->setContinuousSpellCheckingEnabled(flag);
3015 BOOL spellCheckingEnabled;
3016 if (SUCCEEDED(isContinuousSpellCheckingEnabled(&spellCheckingEnabled)) && spellCheckingEnabled)
3017 preflightSpellChecker();
3019 m_mainFrame->unmarkAllMisspellings();
3024 HRESULT STDMETHODCALLTYPE WebView::isContinuousSpellCheckingEnabled(
3025 /* [retval][out] */ BOOL* enabled)
3027 *enabled = (continuousSpellCheckingEnabled && continuousCheckingAllowed()) ? TRUE : FALSE;
3031 HRESULT STDMETHODCALLTYPE WebView::spellCheckerDocumentTag(
3032 /* [retval][out] */ int* tag)
3034 // we just use this as a flag to indicate that we've spell checked the document
3035 // and need to close the spell checker out when the view closes.
3037 m_hasSpellCheckerDocumentTag = true;
3041 static COMPtr<IWebEditingDelegate> spellingDelegateForTimer;
3043 static void preflightSpellCheckerNow()
3045 spellingDelegateForTimer->preflightChosenSpellServer();
3046 spellingDelegateForTimer = 0;
3049 static void CALLBACK preflightSpellCheckerTimerCallback(HWND, UINT, UINT_PTR id, DWORD)
3052 preflightSpellCheckerNow();
3055 void WebView::preflightSpellChecker()
3057 // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
3058 if (!m_editingDelegate)
3062 spellingDelegateForTimer = m_editingDelegate;
3063 if (SUCCEEDED(m_editingDelegate->sharedSpellCheckerExists(&exists)) && exists)
3064 preflightSpellCheckerNow();
3066 ::SetTimer(0, 0, 2000, preflightSpellCheckerTimerCallback);
3069 bool WebView::continuousCheckingAllowed()
3071 static bool allowContinuousSpellChecking = true;
3072 static bool readAllowContinuousSpellCheckingDefault = false;
3073 if (!readAllowContinuousSpellCheckingDefault) {
3074 COMPtr<IWebPreferences> prefs;
3075 if (SUCCEEDED(preferences(&prefs))) {
3077 prefs->allowContinuousSpellChecking(&allowed);
3078 allowContinuousSpellChecking = !!allowed;
3080 readAllowContinuousSpellCheckingDefault = true;
3082 return allowContinuousSpellChecking;
3085 HRESULT STDMETHODCALLTYPE WebView::undoManager(
3086 /* [retval][out] */ IWebUndoManager** /*manager*/)
3088 ASSERT_NOT_REACHED();
3092 HRESULT STDMETHODCALLTYPE WebView::setEditingDelegate(
3093 /* [in] */ IWebEditingDelegate* d)
3095 m_editingDelegate = d;
3099 HRESULT STDMETHODCALLTYPE WebView::editingDelegate(
3100 /* [retval][out] */ IWebEditingDelegate** d)
3103 ASSERT_NOT_REACHED();
3107 *d = m_editingDelegate.get();
3115 HRESULT STDMETHODCALLTYPE WebView::styleDeclarationWithText(
3116 /* [in] */ BSTR /*text*/,
3117 /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
3119 ASSERT_NOT_REACHED();
3123 HRESULT STDMETHODCALLTYPE WebView::hasSelectedRange(
3124 /* [retval][out] */ BOOL* hasSelectedRange)
3126 *hasSelectedRange = m_page->mainFrame()->selectionController()->isRange();
3130 HRESULT STDMETHODCALLTYPE WebView::cutEnabled(
3131 /* [retval][out] */ BOOL* enabled)
3133 Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
3134 *enabled = editor->canCut() || editor->canDHTMLCut();
3138 HRESULT STDMETHODCALLTYPE WebView::copyEnabled(
3139 /* [retval][out] */ BOOL* enabled)
3141 Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
3142 *enabled = editor->canCopy() || editor->canDHTMLCopy();
3146 HRESULT STDMETHODCALLTYPE WebView::pasteEnabled(
3147 /* [retval][out] */ BOOL* enabled)
3149 Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
3150 *enabled = editor->canPaste() || editor->canDHTMLPaste();
3154 HRESULT STDMETHODCALLTYPE WebView::deleteEnabled(
3155 /* [retval][out] */ BOOL* enabled)
3157 *enabled = m_page->focusController()->focusedOrMainFrame()->editor()->canDelete();
3161 HRESULT STDMETHODCALLTYPE WebView::editingEnabled(
3162 /* [retval][out] */ BOOL* enabled)
3164 *enabled = m_page->focusController()->focusedOrMainFrame()->editor()->canEdit();
3168 HRESULT STDMETHODCALLTYPE WebView::isGrammarCheckingEnabled(
3169 /* [retval][out] */ BOOL* enabled)
3171 *enabled = grammarCheckingEnabled ? TRUE : FALSE;
3175 HRESULT STDMETHODCALLTYPE WebView::setGrammarCheckingEnabled(
3178 if (grammarCheckingEnabled == !!enabled)
3181 grammarCheckingEnabled = !!enabled;
3182 COMPtr<IWebPreferences> prefs;
3183 if (SUCCEEDED(preferences(&prefs)))
3184 prefs->setGrammarCheckingEnabled(enabled);
3186 m_editingDelegate->updateGrammar();
3188 // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
3189 // because grammar checking only occurs on code paths that already preflight spell checking appropriately.
3191 BOOL grammarEnabled;
3192 if (SUCCEEDED(isGrammarCheckingEnabled(&grammarEnabled)) && !grammarEnabled)
3193 m_mainFrame->unmarkAllBadGrammar();
3198 // IWebViewUndoableEditing -----------------------------------------------------
3200 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithNode(
3201 /* [in] */ IDOMNode* /*node*/)
3203 ASSERT_NOT_REACHED();
3207 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithText(
3208 /* [in] */ BSTR text)
3210 String textString(text, ::SysStringLen(text));
3211 Position start = m_page->mainFrame()->selectionController()->selection().start();
3212 m_page->focusController()->focusedOrMainFrame()->editor()->insertText(textString, 0);
3213 m_page->mainFrame()->selectionController()->setBase(start);
3217 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithMarkupString(
3218 /* [in] */ BSTR /*markupString*/)
3220 ASSERT_NOT_REACHED();
3224 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithArchive(
3225 /* [in] */ IWebArchive* /*archive*/)
3227 ASSERT_NOT_REACHED();
3231 HRESULT STDMETHODCALLTYPE WebView::deleteSelection( void)
3233 m_page->focusController()->focusedOrMainFrame()->editor()->deleteSelectionWithSmartDelete();
3237 HRESULT STDMETHODCALLTYPE WebView::clearSelection( void)
3239 m_page->focusController()->focusedOrMainFrame()->selectionController()->clear();
3243 HRESULT STDMETHODCALLTYPE WebView::applyStyle(
3244 /* [in] */ IDOMCSSStyleDeclaration* /*style*/)
3246 ASSERT_NOT_REACHED();
3250 // IWebViewEditingActions ------------------------------------------------------
3252 HRESULT STDMETHODCALLTYPE WebView::copy(
3253 /* [in] */ IUnknown* /*sender*/)
3255 m_page->focusController()->focusedOrMainFrame()->editor()->execCommand("Copy");
3259 HRESULT STDMETHODCALLTYPE WebView::cut(
3260 /* [in] */ IUnknown* /*sender*/)
3262 m_page->focusController()->focusedOrMainFrame()->editor()->execCommand("Cut");
3266 HRESULT STDMETHODCALLTYPE WebView::paste(
3267 /* [in] */ IUnknown* /*sender*/)
3269 m_page->focusController()->focusedOrMainFrame()->editor()->execCommand("Paste");
3273 HRESULT STDMETHODCALLTYPE WebView::copyURL(
3274 /* [in] */ BSTR url)
3276 String temp(url, SysStringLen(url));
3277 m_page->focusController()->focusedOrMainFrame()->editor()->copyURL(KURL(temp.deprecatedString()), "");
3282 HRESULT STDMETHODCALLTYPE WebView::copyFont(
3283 /* [in] */ IUnknown* /*sender*/)
3285 ASSERT_NOT_REACHED();
3289 HRESULT STDMETHODCALLTYPE WebView::pasteFont(
3290 /* [in] */ IUnknown* /*sender*/)
3292 ASSERT_NOT_REACHED();
3296 HRESULT STDMETHODCALLTYPE WebView::delete_(
3297 /* [in] */ IUnknown* /*sender*/)
3299 m_page->focusController()->focusedOrMainFrame()->editor()->execCommand("Delete");
3303 HRESULT STDMETHODCALLTYPE WebView::pasteAsPlainText(
3304 /* [in] */ IUnknown* /*sender*/)
3306 ASSERT_NOT_REACHED();
3310 HRESULT STDMETHODCALLTYPE WebView::pasteAsRichText(
3311 /* [in] */ IUnknown* /*sender*/)
3313 ASSERT_NOT_REACHED();
3317 HRESULT STDMETHODCALLTYPE WebView::changeFont(
3318 /* [in] */ IUnknown* /*sender*/)
3320 ASSERT_NOT_REACHED();
3324 HRESULT STDMETHODCALLTYPE WebView::changeAttributes(
3325 /* [in] */ IUnknown* /*sender*/)
3327 ASSERT_NOT_REACHED();
3331 HRESULT STDMETHODCALLTYPE WebView::changeDocumentBackgroundColor(
3332 /* [in] */ IUnknown* /*sender*/)
3334 ASSERT_NOT_REACHED();
3338 HRESULT STDMETHODCALLTYPE WebView::changeColor(
3339 /* [in] */ IUnknown* /*sender*/)
3341 ASSERT_NOT_REACHED();
3345 HRESULT STDMETHODCALLTYPE WebView::alignCenter(
3346 /* [in] */ IUnknown* /*sender*/)
3348 ASSERT_NOT_REACHED();
3352 HRESULT STDMETHODCALLTYPE WebView::alignJustified(
3353 /* [in] */ IUnknown* /*sender*/)
3355 ASSERT_NOT_REACHED();
3359 HRESULT STDMETHODCALLTYPE WebView::alignLeft(
3360 /* [in] */ IUnknown* /*sender*/)
3362 ASSERT_NOT_REACHED();
3366 HRESULT STDMETHODCALLTYPE WebView::alignRight(
3367 /* [in] */ IUnknown* /*sender*/)
3369 ASSERT_NOT_REACHED();
3373 HRESULT STDMETHODCALLTYPE WebView::checkSpelling(
3374 /* [in] */ IUnknown* /*sender*/)
3376 if (!m_editingDelegate) {
3377 LOG_ERROR("No NSSpellChecker");
3381 core(m_mainFrame)->editor()->advanceToNextMisspelling();
3385 HRESULT STDMETHODCALLTYPE WebView::showGuessPanel(
3386 /* [in] */ IUnknown* /*sender*/)
3388 if (!m_editingDelegate) {
3389 LOG_ERROR("No NSSpellChecker");
3393 // Post-Tiger, this menu item is a show/hide toggle, to match AppKit. Leave Tiger behavior alone
3394 // to match rest of OS X.
3396 if (SUCCEEDED(m_editingDelegate->spellingUIIsShowing(&showing)) && showing) {
3397 m_editingDelegate->showSpellingUI(FALSE);
3400 core(m_mainFrame)->editor()->advanceToNextMisspelling(true);
3401 m_editingDelegate->showSpellingUI(TRUE);
3405 HRESULT STDMETHODCALLTYPE WebView::performFindPanelAction(
3406 /* [in] */ IUnknown* /*sender*/)
3408 ASSERT_NOT_REACHED();
3412 HRESULT STDMETHODCALLTYPE WebView::startSpeaking(
3413 /* [in] */ IUnknown* /*sender*/)
3415 ASSERT_NOT_REACHED();
3419 HRESULT STDMETHODCALLTYPE WebView::stopSpeaking(
3420 /* [in] */ IUnknown* /*sender*/)
3422 ASSERT_NOT_REACHED();
3426 // IWebNotificationObserver -----------------------------------------------------------------
3428 HRESULT STDMETHODCALLTYPE WebView::onNotify(
3429 /* [in] */ IWebNotification* notification)
3432 HRESULT hr = notification->name(&nameBSTR);
3437 name.adoptBSTR(nameBSTR);
3439 if (!_tcscmp(name, WebIconDatabase::iconDatabaseDidAddIconNotification()))
3440 return notifyDidAddIcon(notification);
3442 COMPtr<IUnknown> unkPrefs;
3443 hr = notification->getObject(&unkPrefs);
3447 COMPtr<IWebPreferences> preferences;
3448 hr = unkPrefs->QueryInterface(IID_IWebPreferences, (void**)&preferences);
3452 hr = updateWebCoreSettingsFromPreferences(preferences.get());
3457 // IWebViewPrivate ------------------------------------------------------------
3459 HRESULT STDMETHODCALLTYPE WebView::setCustomDropTarget(
3460 /* [in] */ IDropTarget* dt)
3462 ASSERT(::IsWindow(m_viewWindow));
3465 m_hasCustomDropTarget = true;
3467 return ::RegisterDragDrop(m_viewWindow,dt);
3470 HRESULT STDMETHODCALLTYPE WebView::removeCustomDropTarget()
3472 if (!m_hasCustomDropTarget)
3474 m_hasCustomDropTarget = false;
3476 return registerDragDrop();
3479 HRESULT STDMETHODCALLTYPE WebView::setInViewSourceMode(
3480 /* [in] */ BOOL flag)
3485 return m_mainFrame->setInViewSourceMode(flag);
3488 HRESULT STDMETHODCALLTYPE WebView::inViewSourceMode(
3489 /* [retval][out] */ BOOL* flag)
3494 return m_mainFrame->inViewSourceMode(flag);
3497 HRESULT STDMETHODCALLTYPE WebView::viewWindow(
3498 /* [retval][out] */ OLE_HANDLE *window)
3500 *window = (OLE_HANDLE)(ULONG64)m_viewWindow;
3504 HRESULT STDMETHODCALLTYPE WebView::setFormDelegate(
3505 /* [in] */ IWebFormDelegate *formDelegate)
3507 m_formDelegate = formDelegate;
3511 HRESULT STDMETHODCALLTYPE WebView::formDelegate(
3512 /* [retval][out] */ IWebFormDelegate **formDelegate)
3514 if (!m_formDelegate)
3517 return m_formDelegate.copyRefTo(formDelegate);
3520 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegatePrivate(
3521 /* [in] */ IWebFrameLoadDelegatePrivate* d)
3523 m_frameLoadDelegatePrivate = d;
3527 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegatePrivate(
3528 /* [out][retval] */ IWebFrameLoadDelegatePrivate** d)
3530 if (!m_frameLoadDelegatePrivate)
3533 return m_frameLoadDelegatePrivate.copyRefTo(d);
3536 HRESULT STDMETHODCALLTYPE WebView::scrollOffset(
3537 /* [retval][out] */ LPPOINT offset)
3541 IntSize offsetIntSize = m_page->mainFrame()->view()->scrollOffset();
3542 offset->x = offsetIntSize.width();
3543 offset->y = offsetIntSize.height();
3547 HRESULT STDMETHODCALLTYPE WebView::scrollBy(
3548 /* [in] */ LPPOINT offset)
3552 m_page->mainFrame()->view()->scrollBy(offset->x, offset->y);
3556 HRESULT STDMETHODCALLTYPE WebView::visibleContentRect(
3557 /* [retval][out] */ LPRECT rect)
3561 FloatRect visibleContent = m_page->mainFrame()->view()->visibleContentRect();
3562 rect->left = (LONG) visibleContent.x();
3563 rect->top = (LONG) visibleContent.y();
3564 rect->right = (LONG) visibleContent.right();
3565 rect->bottom = (LONG) visibleContent.bottom();
3569 static DWORD dragOperationToDragCursor(DragOperation op) {
3570 DWORD res = DROPEFFECT_NONE;
3571 if (op & DragOperationCopy)
3572 res = DROPEFFECT_COPY;
3573 else if (op & DragOperationLink)
3574 res = DROPEFFECT_LINK;
3575 else if (op & DragOperationMove)
3576 res = DROPEFFECT_MOVE;
3577 else if (op & DragOperationGeneric)
3578 res = DROPEFFECT_MOVE; //This appears to be the Firefox behaviour
3582 static DragOperation keyStateToDragOperation(DWORD) {
3583 //FIXME: This is currently very simple, it may need to actually
3584 //work out an appropriate DragOperation in future -- however this
3585 //behaviour appears to match FireFox
3586 return (DragOperation)(DragOperationCopy | DragOperationLink);
3589 HRESULT STDMETHODCALLTYPE WebView::DragEnter(
3590 IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
3594 if (m_dropTargetHelper)
3595 m_dropTargetHelper->DragEnter(m_viewWindow, pDataObject, (POINT*)&pt, *pdwEffect);
3597 POINTL localpt = pt;
3598 ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
3599 DragData data(pDataObject, IntPoint(localpt.x, localpt.y),
3600 IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
3601 *pdwEffect = dragOperationToDragCursor(m_page->dragController()->dragEntered(&data));
3603 m_dragData = pDataObject;
3608 HRESULT STDMETHODCALLTYPE WebView::DragOver(
3609 DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
3611 if (m_dropTargetHelper)
3612 m_dropTargetHelper->DragOver((POINT*)&pt, *pdwEffect);
3615 POINTL localpt = pt;
3616 ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
3617 DragData data(m_dragData.get(), IntPoint(localpt.x, localpt.y),
3618 IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
3619 *pdwEffect = dragOperationToDragCursor(m_page->dragController()->dragUpdated(&data));
3621 *pdwEffect = DROPEFFECT_NONE;
3626 HRESULT STDMETHODCALLTYPE WebView::DragLeave()
3628 if (m_dropTargetHelper)
3629 m_dropTargetHelper->DragLeave();
3632 DragData data(m_dragData.get(), IntPoint(), IntPoint(),
3634 m_page->dragController()->dragExited(&data);
3640 HRESULT STDMETHODCALLTYPE WebView::Drop(
3641 IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
3643 if (m_dropTargetHelper)
3644 m_dropTargetHelper->Drop(pDataObject, (POINT*)&pt, *pdwEffect);
3647 *pdwEffect = DROPEFFECT_NONE;
3648 POINTL localpt = pt;
3649 ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
3650 DragData data(pDataObject, IntPoint(localpt.x, localpt.y),
3651 IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
3652 m_page->dragController()->performDrag(&data);
3656 HRESULT STDMETHODCALLTYPE WebView::canHandleRequest(
3657 IWebURLRequest *request,
3660 COMPtr<WebMutableURLRequest> requestImpl;
3662 HRESULT hr = request->QueryInterface(CLSID_WebMutableURLRequest, (void**)&requestImpl);
3666 *result = !!canHandleRequest(requestImpl->resourceRequest());
3670 HRESULT STDMETHODCALLTYPE WebView::clearFocusNode()
3672 if (m_page && m_page->focusController())
3673 m_page->focusController()->setFocusedNode(0, 0);
3677 HRESULT STDMETHODCALLTYPE WebView::setTabKeyCyclesThroughElements(
3678 /* [in] */ BOOL cycles)
3681 m_page->setTabKeyCyclesThroughElements(!!cycles);
3686 HRESULT STDMETHODCALLTYPE WebView::tabKeyCyclesThroughElements(
3687 /* [retval][out] */ BOOL* result)
3690 ASSERT_NOT_REACHED();
3694 *result = m_page && m_page->tabKeyCyclesThroughElements() ? TRUE : FALSE;
3698 HRESULT STDMETHODCALLTYPE WebView::setAllowSiteSpecificHacks(
3699 /* [in] */ BOOL allow)
3701 s_allowSiteSpecificHacks = !!allow;
3705 HRESULT STDMETHODCALLTYPE WebView::addAdditionalPluginPath(
3706 /* [in] */ BSTR path)
3708 PluginDatabaseWin::installedPlugins()->addExtraPluginPath(String(path, SysStringLen(path)));
3712 HRESULT STDMETHODCALLTYPE WebView::loadBackForwardListFromOtherView(
3713 /* [in] */ IWebView* otherView)
3718 // It turns out the right combination of behavior is done with the back/forward load
3719 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items
3720 // in the back forward list, and go to the current one.
3721 BackForwardList* backForwardList = m_page->backForwardList();
3722 ASSERT(!backForwardList->currentItem()); // destination list should be empty
3724 COMPtr<WebView> otherWebView;
3725 if (FAILED(otherView->QueryInterface(CLSID_WebView, (void**)&otherWebView)))
3727 BackForwardList* otherBackForwardList = otherWebView->m_page->backForwardList();
3728 if (!otherBackForwardList->currentItem())
3729 return S_OK; // empty back forward list, bail
3731 HistoryItem* newItemToGoTo = 0;
3733 int lastItemIndex = otherBackForwardList->forwardListCount();
3734 for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
3736 // If this item is showing , save away its current scroll and form state,
3737 // since that might have changed since loading and it is normally not saved
3738 // until we leave that page.
3739 otherWebView->m_page->mainFrame()->loader()->saveDocumentAndScrollState();
3741 RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
3743 newItemToGoTo = newItem.get();
3744 backForwardList->addItem(newItem.release());