1/*
2 * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "WebContextMenuClient.h"
28
29#include "UserGestureIndicator.h"
30#include "WebElementPropertyBag.h"
31#include "WebLocalizableStrings.h"
32#include "WebView.h"
33
34#include <WebCore/ContextMenu.h>
35#include <WebCore/ContextMenuController.h>
36#include <WebCore/Editor.h>
37#include <WebCore/Event.h>
38#include <WebCore/Frame.h>
39#include <WebCore/FrameLoader.h>
40#include <WebCore/FrameLoadRequest.h>
41#include <WebCore/Page.h>
42#include <WebCore/ResourceRequest.h>
43#include <WebCore/NotImplemented.h>
44
45using namespace WebCore;
46
47WebContextMenuClient::WebContextMenuClient(WebView* webView)
48    : m_webView(webView)
49{
50}
51
52void WebContextMenuClient::contextMenuDestroyed()
53{
54    delete this;
55}
56
57PassOwnPtr<ContextMenu> WebContextMenuClient::customizeMenu(PassOwnPtr<ContextMenu> popMenu)
58{
59    OwnPtr<ContextMenu> menu = popMenu;
60
61    COMPtr<IWebUIDelegate> uiDelegate;
62    if (FAILED(m_webView->uiDelegate(&uiDelegate)))
63        return menu.release();
64
65    ASSERT(uiDelegate);
66
67    HMENU nativeMenu = menu->platformContextMenu();
68    COMPtr<WebElementPropertyBag> propertyBag;
69    propertyBag.adoptRef(WebElementPropertyBag::createInstance(m_webView->page()->contextMenuController()->hitTestResult()));
70    // FIXME: We need to decide whether to do the default before calling this delegate method
71    if (FAILED(uiDelegate->contextMenuItemsForElement(m_webView, propertyBag.get(), (OLE_HANDLE)(ULONG64)nativeMenu, (OLE_HANDLE*)&nativeMenu))) {
72        ::DestroyMenu(nativeMenu);
73        return menu.release();
74    }
75
76    OwnPtr<ContextMenu> customizedMenu = adoptPtr(new ContextMenu(nativeMenu));
77    ::DestroyMenu(nativeMenu);
78
79    return customizedMenu.release();
80}
81
82void WebContextMenuClient::contextMenuItemSelected(ContextMenuItem* item, const ContextMenu* parentMenu)
83{
84    ASSERT(item->type() == ActionType || item->type() == CheckableActionType);
85
86    COMPtr<IWebUIDelegate> uiDelegate;
87    if (FAILED(m_webView->uiDelegate(&uiDelegate)))
88        return;
89
90    ASSERT(uiDelegate);
91
92    COMPtr<WebElementPropertyBag> propertyBag;
93    propertyBag.adoptRef(WebElementPropertyBag::createInstance(m_webView->page()->contextMenuController()->hitTestResult()));
94
95    // This call would leak the MENUITEMINFO's subMenu if it had one, but on Windows, subMenus can't be selected, so there is
96    // no way we would get to this point. Also, it can't be a separator, because separators cannot be selected.
97    ASSERT(item->type() != SubmenuType);
98    ASSERT(item->type() != SeparatorType);
99
100    // ContextMenuItem::platformContextMenuItem doesn't set the dwTypeData of the MENUITEMINFO, but no WebKit clients
101    // use the title in IWebUIDelegate::contextMenuItemSelected, so we don't need to populate it here.
102    MENUITEMINFO selectedItem = item->platformContextMenuItem();
103
104    uiDelegate->contextMenuItemSelected(m_webView, &selectedItem, propertyBag.get());
105}
106
107void WebContextMenuClient::downloadURL(const KURL& url)
108{
109    m_webView->downloadURL(url);
110}
111
112void WebContextMenuClient::searchWithGoogle(const Frame* frame)
113{
114    String searchString = frame->editor().selectedText();
115    searchString.stripWhiteSpace();
116    String encoded = encodeWithURLEscapeSequences(searchString);
117    encoded.replace("%20", "+");
118
119    String url("http://www.google.com/search?q=");
120    url.append(encoded);
121    url.append("&ie=UTF-8&oe=UTF-8");
122
123    if (Page* page = frame->page()) {
124        UserGestureIndicator indicator(DefinitelyProcessingNewUserGesture);
125        page->mainFrame()->loader()->urlSelected(KURL(ParsedURLString, url), String(), 0, false, false, MaybeSendReferrer);
126    }
127}
128
129void WebContextMenuClient::lookUpInDictionary(Frame*)
130{
131    notImplemented();
132}
133
134void WebContextMenuClient::speak(const String&)
135{
136    notImplemented();
137}
138
139void WebContextMenuClient::stopSpeaking()
140{
141    notImplemented();
142}
143
144bool WebContextMenuClient::isSpeaking()
145{
146    notImplemented();
147    return false;
148}
149