diff options
author | cevans@chromium.org <cevans@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-09 05:24:30 +0000 |
---|---|---|
committer | cevans@chromium.org <cevans@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-09 05:24:30 +0000 |
commit | 6a8b86ceacdc6060a788f8be5c09ba9d643ee5e1 (patch) | |
tree | 6058cb9ca68405fefc1499f907870995c487d7bb | |
parent | ce1c3f726da89df5e0a947f824f8f00cab485866 (diff) | |
download | chromium_src-6a8b86ceacdc6060a788f8be5c09ba9d643ee5e1.zip chromium_src-6a8b86ceacdc6060a788f8be5c09ba9d643ee5e1.tar.gz chromium_src-6a8b86ceacdc6060a788f8be5c09ba9d643ee5e1.tar.bz2 |
Implement a useful context menu for the blocked plug-in frame:
- Offers option to run plugin (clickjack-proof).
- Offers option to hide blocking placeholder.
- Retains Inspect Element; it's also useful to see the <embed>.
BUG=NONE
TEST=NONE
Review URL: http://codereview.chromium.org/5639004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@68719 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/generated_resources.grd | 12 | ||||
-rw-r--r-- | chrome/renderer/blocked_plugin.cc | 67 | ||||
-rw-r--r-- | chrome/renderer/blocked_plugin.h | 13 | ||||
-rw-r--r-- | chrome/renderer/custom_menu_listener.h | 22 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 18 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 13 | ||||
-rw-r--r-- | webkit/glue/plugins/webview_plugin.cc | 10 | ||||
-rw-r--r-- | webkit/glue/plugins/webview_plugin.h | 6 |
8 files changed, 156 insertions, 5 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index d8083ac..752a05b 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -500,6 +500,12 @@ each locale. --> <message name="IDS_CONTENT_CONTEXT_TRANSLATE_SELECTION" desc="The name of the Translate 'string' to English command of the content area context menu"> &Translate '<ph name="TEXT">$1<ex>les fleurs bleues</ex></ph>' to <ph name="LANGUAGE">$2<ex>English</ex></ph> </message> + <message name="IDS_CONTENT_CONTEXT_PLUGIN_RUN" desc="The name of the Run command on the blocked plugin context menu"> + Run this plugin + </message> + <message name="IDS_CONTENT_CONTEXT_PLUGIN_HIDE" desc="The name of the Hide command on the blocked plugin context menu"> + Hide this plugin + </message> </if> <if expr="pp_ifdef('use_titlecase')"> <message name="IDS_CONTENT_CONTEXT_BACK" desc="In Title Case: The name of the Back command in the content area context menu"> @@ -682,6 +688,12 @@ each locale. --> <message name="IDS_CONTENT_CONTEXT_TRANSLATE_SELECTION" desc="In Title Case: The name of the Translate 'string' to English command of the content area context menu"> &Translate '<ph name="TEXT">$1<ex>les fleurs bleues</ex></ph>' to <ph name="LANGUAGE">$2<ex>English</ex></ph> </message> + <message name="IDS_CONTENT_CONTEXT_PLUGIN_RUN" desc="In Title Case: The name of the Run command on the blocked plugin context menu"> + Run This Plugin + </message> + <message name="IDS_CONTENT_CONTEXT_PLUGIN_HIDE" desc="In Title Case: The name of the Hide command on the blocked plugin context menu"> + Hide This Plugin + </message> </if> <!-- Page menu --> diff --git a/chrome/renderer/blocked_plugin.cc b/chrome/renderer/blocked_plugin.cc index 6ebf837..e3d2a3a 100644 --- a/chrome/renderer/blocked_plugin.cc +++ b/chrome/renderer/blocked_plugin.cc @@ -14,20 +14,31 @@ #include "chrome/renderer/render_view.h" #include "grit/generated_resources.h" #include "grit/renderer_resources.h" +#include "third_party/WebKit/WebKit/chromium/public/WebContextMenuData.h" #include "third_party/WebKit/WebKit/chromium/public/WebData.h" #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/WebKit/chromium/public/WebMenuItemInfo.h" #include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h" +#include "third_party/WebKit/WebKit/chromium/public/WebPoint.h" +#include "third_party/WebKit/WebKit/chromium/public/WebVector.h" #include "third_party/WebKit/WebKit/chromium/public/WebView.h" #include "webkit/glue/plugins/plugin_group.h" #include "webkit/glue/plugins/webview_plugin.h" #include "webkit/glue/webpreferences.h" +using WebKit::WebContextMenuData; using WebKit::WebFrame; +using WebKit::WebMenuItemInfo; using WebKit::WebPlugin; using WebKit::WebPluginContainer; using WebKit::WebPluginParams; +using WebKit::WebPoint; +using WebKit::WebString; +using WebKit::WebVector; static const char* const kBlockedPluginDataURL = "chrome://blockedplugindata/"; +static const unsigned kMenuActionLoad = 1; +static const unsigned kMenuActionRemove = 2; BlockedPlugin::BlockedPlugin(RenderView* render_view, WebFrame* frame, @@ -47,7 +58,8 @@ BlockedPlugin::BlockedPlugin(RenderView* render_view, DictionaryValue values; values.SetString("message", message); - values.SetString("name", info.GetGroupName()); + name_ = info.GetGroupName(); + values.SetString("name", name_); // "t" is the id of the templates root node. std::string html_data = jstemplate_builder::GetTemplatesHtml( @@ -63,7 +75,9 @@ BlockedPlugin::BlockedPlugin(RenderView* render_view, NotificationService::AllSources()); } -BlockedPlugin::~BlockedPlugin() {} +BlockedPlugin::~BlockedPlugin() { + render_view_->CustomMenuListenerDestroyed(this); +} void BlockedPlugin::BindWebFrame(WebFrame* frame) { BindToJavascript(frame, "plugin"); @@ -74,6 +88,48 @@ void BlockedPlugin::WillDestroyPlugin() { delete this; } +void BlockedPlugin::ShowContextMenu(const WebKit::WebMouseEvent& event) { + WebContextMenuData menu_data; + WebVector<WebMenuItemInfo> custom_items(static_cast<size_t>(4)); + + WebMenuItemInfo name_item; + name_item.label = name_; + custom_items[0] = name_item; + + WebMenuItemInfo separator_item; + separator_item.type = WebMenuItemInfo::Separator; + custom_items[1] = separator_item; + + WebMenuItemInfo run_item; + run_item.action = kMenuActionLoad; + run_item.enabled = true; + run_item.label = WebString::fromUTF8( + l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_PLUGIN_RUN).c_str()); + custom_items[2] = run_item; + + WebMenuItemInfo hide_item; + hide_item.action = kMenuActionRemove; + hide_item.enabled = true; + hide_item.label = WebString::fromUTF8( + l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_PLUGIN_HIDE).c_str()); + custom_items[3] = hide_item; + + menu_data.customItems.swap(custom_items); + menu_data.mousePosition = WebPoint(event.windowX, event.windowY); + render_view_->showContextMenu(NULL, menu_data); + render_view_->CustomMenuListenerInstall(this); +} + +void BlockedPlugin::MenuItemSelected(unsigned id) { + if (id == kMenuActionLoad) { + LoadPlugin(); + } else if (id == kMenuActionRemove) { + HidePlugin(); + } else { + NOTREACHED(); + } +} + void BlockedPlugin::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { @@ -102,3 +158,10 @@ void BlockedPlugin::LoadPlugin() { plugin_->destroy(); } } + +void BlockedPlugin::HidePlugin() { + CHECK(plugin_); + WebPluginContainer* container = plugin_->container(); + container->element().setAttribute("style", "display: none;"); +} + diff --git a/chrome/renderer/blocked_plugin.h b/chrome/renderer/blocked_plugin.h index f8637a0..53859bc 100644 --- a/chrome/renderer/blocked_plugin.h +++ b/chrome/renderer/blocked_plugin.h @@ -8,6 +8,7 @@ #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" +#include "chrome/renderer/custom_menu_listener.h" #include "third_party/WebKit/WebKit/chromium/public/WebPluginParams.h" #include "webkit/glue/cpp_bound_class.h" #include "webkit/glue/plugins/webview_plugin.h" @@ -18,7 +19,8 @@ class RenderView; class BlockedPlugin : public CppBoundClass, public WebViewPlugin::Delegate, - public NotificationObserver { + public NotificationObserver, + public CustomMenuListener { public: BlockedPlugin(RenderView* render_view, WebKit::WebFrame* frame, @@ -33,12 +35,16 @@ class BlockedPlugin : public CppBoundClass, // WebViewPlugin::Delegate methods: virtual void BindWebFrame(WebKit::WebFrame* frame); virtual void WillDestroyPlugin(); + virtual void ShowContextMenu(const WebKit::WebMouseEvent&); // NotificationObserver methods: virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details); + // CustomMenuListener methods: + virtual void MenuItemSelected(unsigned id); + private: virtual ~BlockedPlugin(); @@ -50,10 +56,15 @@ class BlockedPlugin : public CppBoundClass, // Load the blocked plugin. void LoadPlugin(); + // Hide the blocked plugin. + void HidePlugin(); + RenderView* render_view_; WebKit::WebFrame* frame_; WebKit::WebPluginParams plugin_params_; WebViewPlugin* plugin_; + // The name of the plugin that was blocked. + string16 name_; NotificationRegistrar registrar_; }; diff --git a/chrome/renderer/custom_menu_listener.h b/chrome/renderer/custom_menu_listener.h new file mode 100644 index 0000000..5c61358 --- /dev/null +++ b/chrome/renderer/custom_menu_listener.h @@ -0,0 +1,22 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_CUSTOM_MENU_LISTENER_H_ +#define CHROME_RENDERER_CUSTOM_MENU_LISTENER_H_ +#pragma once + +// CustomMenuListener is an interface that can be registered with RenderView by +// classes that wish to use custom context menus. There is a single callback, +// MenuItemSelected(), which fires when a custom menu item was chosen by the +// user. +class CustomMenuListener { + public: + virtual void MenuItemSelected(unsigned id) = 0; + + protected: + virtual ~CustomMenuListener() {} +}; + +#endif // CHROME_RENDERER_CUSTOM_MENU_LISTENER_H_ + diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 74f84e1c..e29e30a 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -552,7 +552,8 @@ RenderView::RenderView(RenderThreadBase* render_thread, accessibility_ack_pending_(false), pending_app_icon_requests_(0), session_storage_namespace_id_(session_storage_namespace_id), - decrement_shared_popup_at_destruction_(false) { + decrement_shared_popup_at_destruction_(false), + custom_menu_listener_(NULL) { #if defined(OS_MACOSX) // On Mac, the select popups are rendered by the browser. // Note that we don't do this in RenderMain otherwise this would not be called @@ -842,6 +843,15 @@ WebPlugin* RenderView::CreatePluginNoCheck(WebFrame* frame, return CreateNPAPIPlugin(frame, params, info.path, mime_type); } +void RenderView::CustomMenuListenerInstall(CustomMenuListener* listening) { + custom_menu_listener_ = listening; +} + +void RenderView::CustomMenuListenerDestroyed(CustomMenuListener* dead) { + if (custom_menu_listener_ == dead) + custom_menu_listener_ = NULL; +} + void RenderView::RegisterPluginDelegate(WebPluginDelegateProxy* delegate) { plugin_delegates_.insert(delegate); // If the renderer is visible, set initial visibility and focus state. @@ -2435,6 +2445,7 @@ bool RenderView::runModalBeforeUnloadDialog( void RenderView::showContextMenu( WebFrame* frame, const WebContextMenuData& data) { + custom_menu_listener_ = NULL; ContextMenuParams params = ContextMenuParams(data); if (!params.misspelled_word.empty() && RenderThread::current()) { int misspelled_offset, misspelled_length; @@ -4713,7 +4724,10 @@ void RenderView::OnSetAltErrorPageURL(const GURL& url) { } void RenderView::OnCustomContextMenuAction(unsigned action) { - webview()->performCustomContextMenuAction(action); + if (custom_menu_listener_) + custom_menu_listener_->MenuItemSelected(action); + else + webview()->performCustomContextMenuAction(action); } void RenderView::OnTranslatePage(int page_id, diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index c273e64..cdd2102 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -55,6 +55,7 @@ class AudioMessageFilter; class AutoFillHelper; +class CustomMenuListener; class DictionaryValue; class DeviceOrientationDispatcher; class DevToolsAgent; @@ -337,6 +338,15 @@ class RenderView : public RenderWidget, // only by gears and this function can be deleted when we remove gears. uint32 GetCPBrowsingContext(); + // Handles registering and deregistering customer handlers for custom + // context menu events. + // To install a custom context menu, call showContextMenu() with your + // custom entries, followed immediately by CustomMenuListenerInstall() to + // register a listener for when a custom menu item is selected. Note that + // subsequent calls to showContextMenu() will clear the custom listener. + void CustomMenuListenerInstall(CustomMenuListener* listening); + void CustomMenuListenerDestroyed(CustomMenuListener* dead); + #if defined(OS_MACOSX) // Enables/disabled plugin IME for the given plugin. void SetPluginImeEnabled(bool enabled, int plugin_id); @@ -1463,6 +1473,9 @@ class RenderView : public RenderWidget, // The external popup for the currently showing select popup. scoped_ptr<ExternalPopupMenu> external_popup_menu_; + // The custom menu event listener, if any. + CustomMenuListener* custom_menu_listener_; + // --------------------------------------------------------------------------- // ADDING NEW DATA? Please see if it fits appropriately in one of the above // sections rather than throwing it randomly at the end. If you're adding a diff --git a/webkit/glue/plugins/webview_plugin.cc b/webkit/glue/plugins/webview_plugin.cc index 31403fe..e0f80e3 100644 --- a/webkit/glue/plugins/webview_plugin.cc +++ b/webkit/glue/plugins/webview_plugin.cc @@ -9,6 +9,7 @@ #include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" #include "third_party/WebKit/WebKit/chromium/public/WebElement.h" #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" #include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h" #include "third_party/WebKit/WebKit/chromium/public/WebSize.h" #include "third_party/WebKit/WebKit/chromium/public/WebURL.h" @@ -30,6 +31,7 @@ using WebKit::WebDragOperationsMask; using WebKit::WebFrame; using WebKit::WebImage; using WebKit::WebInputEvent; +using WebKit::WebMouseEvent; using WebKit::WebPlugin; using WebKit::WebPluginContainer; using WebKit::WebPoint; @@ -143,6 +145,14 @@ void WebViewPlugin::updateGeometry( bool WebViewPlugin::handleInputEvent(const WebInputEvent& event, WebCursorInfo& cursor) { + if (event.type == WebInputEvent::ContextMenu) { + if (delegate_) { + const WebMouseEvent& mouse_event = + reinterpret_cast<const WebMouseEvent&>(event); + delegate_->ShowContextMenu(mouse_event); + } + return true; + } current_cursor_ = cursor; bool handled = web_view_->handleInputEvent(event); cursor = current_cursor_; diff --git a/webkit/glue/plugins/webview_plugin.h b/webkit/glue/plugins/webview_plugin.h index 95f32a5..ac89c85 100644 --- a/webkit/glue/plugins/webview_plugin.h +++ b/webkit/glue/plugins/webview_plugin.h @@ -17,6 +17,9 @@ #include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h" #include "third_party/WebKit/WebKit/chromium/public/WebViewClient.h" +namespace WebKit { +class WebMouseEvent; +} struct WebPreferences; // This class implements the WebPlugin interface by forwarding drawing and @@ -39,6 +42,9 @@ class WebViewPlugin: public WebKit::WebPlugin, public WebKit::WebViewClient, // Called before the WebViewPlugin is destroyed. The delegate should delete // itself here. virtual void WillDestroyPlugin() = 0; + + // Called upon a context menu event. + virtual void ShowContextMenu(const WebKit::WebMouseEvent&) = 0; }; explicit WebViewPlugin(Delegate* delegate); |