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 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 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#include <WebCore/ContextMenu.h>
34#include <WebCore/ContextMenuController.h>
35#include <WebCore/Editor.h>
36#include <WebCore/Event.h>
37#include <WebCore/FrameLoadRequest.h>
38#include <WebCore/FrameLoader.h>
39#include <WebCore/MainFrame.h>
40#include <WebCore/NotImplemented.h>
41#include <WebCore/Page.h>
42#include <WebCore/ResourceRequest.h>
43
44using namespace WebCore;
45
46WebContextMenuClient::WebContextMenuClient(WebView* webView)
47    : m_webView(webView)
48{
49}
50
51void WebContextMenuClient::contextMenuDestroyed()
52{
53    delete this;
54}
55
56PassOwnPtr<ContextMenu> WebContextMenuClient::customizeMenu(PassOwnPtr<ContextMenu> popMenu)
57{
58    OwnPtr<ContextMenu> menu = popMenu;
59
60    COMPtr<IWebUIDelegate> uiDelegate;
61    if (FAILED(m_webView->uiDelegate(&uiDelegate)))
62        return menu.release();
63
64    ASSERT(uiDelegate);
65
66    HMENU nativeMenu = menu->platformContextMenu();
67    COMPtr<WebElementPropertyBag> propertyBag;
68    propertyBag.adoptRef(WebElementPropertyBag::createInstance(m_webView->page()->contextMenuController().hitTestResult()));
69    // FIXME: We need to decide whether to do the default before calling this delegate method
70    if (FAILED(uiDelegate->contextMenuItemsForElement(m_webView, propertyBag.get(), nativeMenu, &nativeMenu))) {
71        ::DestroyMenu(nativeMenu);
72        return menu.release();
73    }
74
75    OwnPtr<ContextMenu> customizedMenu = adoptPtr(new ContextMenu(nativeMenu));
76    ::DestroyMenu(nativeMenu);
77
78    return customizedMenu.release();
79}
80
81void WebContextMenuClient::contextMenuItemSelected(ContextMenuItem* item, const ContextMenu* parentMenu)
82{
83    ASSERT(item->type() == ActionType || item->type() == CheckableActionType);
84
85    COMPtr<IWebUIDelegate> uiDelegate;
86    if (FAILED(m_webView->uiDelegate(&uiDelegate)))
87        return;
88
89    ASSERT(uiDelegate);
90
91    COMPtr<WebElementPropertyBag> propertyBag;
92    propertyBag.adoptRef(WebElementPropertyBag::createInstance(m_webView->page()->contextMenuController().hitTestResult()));
93
94    // This call would leak the MENUITEMINFO's subMenu if it had one, but on Windows, subMenus can't be selected, so there is
95    // no way we would get to this point. Also, it can't be a separator, because separators cannot be selected.
96    ASSERT(item->type() != SubmenuType);
97    ASSERT(item->type() != SeparatorType);
98
99    // ContextMenuItem::platformContextMenuItem doesn't set the dwTypeData of the MENUITEMINFO, but no WebKit clients
100    // use the title in IWebUIDelegate::contextMenuItemSelected, so we don't need to populate it here.
101    MENUITEMINFO selectedItem = item->platformContextMenuItem();
102
103    uiDelegate->contextMenuItemSelected(m_webView, &selectedItem, propertyBag.get());
104}
105
106void WebContextMenuClient::downloadURL(const URL& url)
107{
108    m_webView->downloadURL(url);
109}
110
111void WebContextMenuClient::searchWithGoogle(const Frame* frame)
112{
113    String searchString = frame->editor().selectedText();
114    searchString.stripWhiteSpace();
115    String encoded = encodeWithURLEscapeSequences(searchString);
116    encoded.replace("%20", "+");
117
118    String url("http://www.google.com/search?q=");
119    url.append(encoded);
120    url.append("&ie=UTF-8&oe=UTF-8");
121
122    if (Page* page = frame->page()) {
123        UserGestureIndicator indicator(DefinitelyProcessingUserGesture);
124        page->mainFrame().loader().urlSelected(URL(ParsedURLString, url), String(), 0, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer);
125    }
126}
127
128void WebContextMenuClient::lookUpInDictionary(Frame*)
129{
130    notImplemented();
131}
132
133void WebContextMenuClient::speak(const String&)
134{
135    notImplemented();
136}
137
138void WebContextMenuClient::stopSpeaking()
139{
140    notImplemented();
141}
142
143bool WebContextMenuClient::isSpeaking()
144{
145    notImplemented();
146    return false;
147}
148