summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcevans@chromium.org <cevans@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-09 05:24:30 +0000
committercevans@chromium.org <cevans@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-09 05:24:30 +0000
commit6a8b86ceacdc6060a788f8be5c09ba9d643ee5e1 (patch)
tree6058cb9ca68405fefc1499f907870995c487d7bb
parentce1c3f726da89df5e0a947f824f8f00cab485866 (diff)
downloadchromium_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.grd12
-rw-r--r--chrome/renderer/blocked_plugin.cc67
-rw-r--r--chrome/renderer/blocked_plugin.h13
-rw-r--r--chrome/renderer/custom_menu_listener.h22
-rw-r--r--chrome/renderer/render_view.cc18
-rw-r--r--chrome/renderer/render_view.h13
-rw-r--r--webkit/glue/plugins/webview_plugin.cc10
-rw-r--r--webkit/glue/plugins/webview_plugin.h6
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">
&amp;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">
&amp;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);