summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-31 21:41:08 +0000
committerviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-31 21:41:08 +0000
commitb29aa74b75d57e1dc78bb151f1b7b2153d13ae3f (patch)
treec06576af8874b736101b045e4e1d75cfed7ba897
parent314e594492cfd5c23225763cb46c5cd190b5551c (diff)
downloadchromium_src-b29aa74b75d57e1dc78bb151f1b7b2153d13ae3f.zip
chromium_src-b29aa74b75d57e1dc78bb151f1b7b2153d13ae3f.tar.gz
chromium_src-b29aa74b75d57e1dc78bb151f1b7b2153d13ae3f.tar.bz2
Pepper/Flapper: First pass at context menu implementation.
This meets the needs of Flapper. We may want to generalize/restrict/modify the API for inclusion into PPAPI, but hopefully this lays a foundation. BUG=none TEST=Flapper context menus work (with the right version of Flapper) Review URL: http://codereview.chromium.org/6253017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73193 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/renderer_host/pepper_message_filter.cc47
-rw-r--r--chrome/browser/renderer_host/pepper_message_filter.h44
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc15
-rw-r--r--chrome/browser/renderer_host/render_view_host.h8
-rw-r--r--chrome/browser/tab_contents/render_view_context_menu.cc160
-rw-r--r--chrome/common/render_messages.cc43
-rw-r--r--chrome/common/render_messages.h9
-rw-r--r--chrome/common/render_messages_internal.h6
-rw-r--r--chrome/renderer/blocked_plugin.cc4
-rw-r--r--chrome/renderer/blocked_plugin.h8
-rw-r--r--chrome/renderer/pepper_plugin_delegate_impl.cc64
-rw-r--r--chrome/renderer/pepper_plugin_delegate_impl.h26
-rw-r--r--chrome/renderer/render_view.cc17
-rw-r--r--chrome/renderer/render_view.h8
-rw-r--r--ppapi/c/pp_errors.h6
-rw-r--r--ppapi/c/private/ppb_flash.h13
-rw-r--r--ppapi/c/private/ppb_flash_menu.h57
-rw-r--r--ppapi/cpp/private/flash_menu.cc48
-rw-r--r--ppapi/cpp/private/flash_menu.h36
-rw-r--r--ppapi/ppapi_cpp.gypi1
-rw-r--r--webkit/glue/context_menu.cc10
-rw-r--r--webkit/glue/context_menu.h13
-rw-r--r--webkit/glue/webkit_glue.gypi2
-rw-r--r--webkit/glue/webmenuitem.h8
-rw-r--r--webkit/plugins/ppapi/mock_plugin_delegate.cc6
-rw-r--r--webkit/plugins/ppapi/mock_plugin_delegate.h3
-rw-r--r--webkit/plugins/ppapi/plugin_delegate.h10
-rw-r--r--webkit/plugins/ppapi/plugin_module.cc4
-rw-r--r--webkit/plugins/ppapi/ppb_flash_impl.cc14
-rw-r--r--webkit/plugins/ppapi/ppb_flash_menu_impl.cc223
-rw-r--r--webkit/plugins/ppapi/ppb_flash_menu_impl.h65
-rw-r--r--webkit/plugins/ppapi/resource.h3
32 files changed, 853 insertions, 128 deletions
diff --git a/chrome/browser/renderer_host/pepper_message_filter.cc b/chrome/browser/renderer_host/pepper_message_filter.cc
index 2090667..5558cb3 100644
--- a/chrome/browser/renderer_host/pepper_message_filter.cc
+++ b/chrome/browser/renderer_host/pepper_message_filter.cc
@@ -42,8 +42,8 @@ bool PepperMessageFilter::OnMessageReceived(const IPC::Message& msg,
#if defined(ENABLE_FLAPPER_HACKS)
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(PepperMessageFilter, msg, *message_was_ok)
- IPC_MESSAGE_HANDLER(PepperMsg_ConnectTcp, OnPepperConnectTcp)
- IPC_MESSAGE_HANDLER(PepperMsg_ConnectTcpAddress, OnPepperConnectTcpAddress)
+ IPC_MESSAGE_HANDLER(PepperMsg_ConnectTcp, OnConnectTcp)
+ IPC_MESSAGE_HANDLER(PepperMsg_ConnectTcpAddress, OnConnectTcpAddress)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
return handled;
@@ -143,7 +143,7 @@ class PepperMessageFilter::LookupRequest {
private:
void OnLookupFinished(int /*result*/) {
- pepper_message_filter_->PepperConnectTcpLookupFinished(
+ pepper_message_filter_->ConnectTcpLookupFinished(
routing_id_, request_id_, addresses_);
delete this;
}
@@ -163,11 +163,10 @@ class PepperMessageFilter::LookupRequest {
DISALLOW_COPY_AND_ASSIGN(LookupRequest);
};
-void PepperMessageFilter::OnPepperConnectTcp(
- int routing_id,
- int request_id,
- const std::string& host,
- uint16 port) {
+void PepperMessageFilter::OnConnectTcp(int routing_id,
+ int request_id,
+ const std::string& host,
+ uint16 port) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
net::URLRequestContext* req_context =
@@ -181,10 +180,9 @@ void PepperMessageFilter::OnPepperConnectTcp(
lookup_request->Start();
}
-void PepperMessageFilter::OnPepperConnectTcpAddress(
- int routing_id,
- int request_id,
- const PP_Flash_NetAddress& addr) {
+void PepperMessageFilter::OnConnectTcpAddress(int routing_id,
+ int request_id,
+ const PP_Flash_NetAddress& addr) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Validate the address and then continue (doing |connect()|) on a worker
@@ -193,22 +191,22 @@ void PepperMessageFilter::OnPepperConnectTcpAddress(
!base::WorkerPool::PostTask(FROM_HERE,
NewRunnableMethod(
this,
- &PepperMessageFilter::PepperConnectTcpAddressOnWorkerThread,
+ &PepperMessageFilter::ConnectTcpAddressOnWorkerThread,
routing_id, request_id, addr),
true)) {
- SendPepperConnectTcpACKError(routing_id, request_id);
+ SendConnectTcpACKError(routing_id, request_id);
}
}
-bool PepperMessageFilter::SendPepperConnectTcpACKError(int routing_id,
- int request_id) {
+bool PepperMessageFilter::SendConnectTcpACKError(int routing_id,
+ int request_id) {
return Send(
new PepperMsg_ConnectTcpACK(routing_id, request_id,
IPC::InvalidPlatformFileForTransit(),
kInvalidNetAddress, kInvalidNetAddress));
}
-void PepperMessageFilter::PepperConnectTcpLookupFinished(
+void PepperMessageFilter::ConnectTcpLookupFinished(
int routing_id,
int request_id,
const net::AddressList& addresses) {
@@ -220,17 +218,16 @@ void PepperMessageFilter::PepperConnectTcpLookupFinished(
!base::WorkerPool::PostTask(FROM_HERE,
NewRunnableMethod(
this,
- &PepperMessageFilter::PepperConnectTcpOnWorkerThread,
+ &PepperMessageFilter::ConnectTcpOnWorkerThread,
routing_id, request_id, addresses),
true)) {
- SendPepperConnectTcpACKError(routing_id, request_id);
+ SendConnectTcpACKError(routing_id, request_id);
}
}
-void PepperMessageFilter::PepperConnectTcpOnWorkerThread(
- int routing_id,
- int request_id,
- net::AddressList addresses) {
+void PepperMessageFilter::ConnectTcpOnWorkerThread(int routing_id,
+ int request_id,
+ net::AddressList addresses) {
DCHECK(!MessageLoop::current()); // Check we are on a worker thread.
IPC::PlatformFileForTransit socket_for_transit =
@@ -257,8 +254,8 @@ void PepperMessageFilter::PepperConnectTcpOnWorkerThread(
}
// TODO(vluu): Eliminate duplication between this and
-// |PepperConnectTcpOnWorkerThread()|.
-void PepperMessageFilter::PepperConnectTcpAddressOnWorkerThread(
+// |ConnectTcpOnWorkerThread()|.
+void PepperMessageFilter::ConnectTcpAddressOnWorkerThread(
int routing_id,
int request_id,
PP_Flash_NetAddress addr) {
diff --git a/chrome/browser/renderer_host/pepper_message_filter.h b/chrome/browser/renderer_host/pepper_message_filter.h
index ec36c08..d907361 100644
--- a/chrome/browser/renderer_host/pepper_message_filter.h
+++ b/chrome/browser/renderer_host/pepper_message_filter.h
@@ -31,34 +31,34 @@ class PepperMessageFilter : public BrowserMessageFilter {
#if defined(ENABLE_FLAPPER_HACKS)
// Message handlers.
- void OnPepperConnectTcp(int routing_id,
- int request_id,
- const std::string& host,
- uint16 port);
- void OnPepperConnectTcpAddress(int routing_id,
- int request_id,
- const PP_Flash_NetAddress& address);
+ void OnConnectTcp(int routing_id,
+ int request_id,
+ const std::string& host,
+ uint16 port);
+ void OnConnectTcpAddress(int routing_id,
+ int request_id,
+ const PP_Flash_NetAddress& address);
- // |Send()| a |ViewMsg_PepperConnectTcpACK|, which reports an error.
- bool SendPepperConnectTcpACKError(int routing_id,
- int request_id);
+ // |Send()| a |PepperMsg_ConnectTcpACK|, which reports an error.
+ bool SendConnectTcpACKError(int routing_id,
+ int request_id);
- // Used by |OnPepperConnectTcp()| (below).
+ // Used by |OnConnectTcp()| (below).
class LookupRequest;
friend class LookupRequest;
- // Continuation of |OnPepperConnectTcp()|.
- void PepperConnectTcpLookupFinished(int routing_id,
- int request_id,
- const net::AddressList& addresses);
- void PepperConnectTcpOnWorkerThread(int routing_id,
- int request_id,
- net::AddressList addresses);
+ // Continuation of |OnConnectTcp()|.
+ void ConnectTcpLookupFinished(int routing_id,
+ int request_id,
+ const net::AddressList& addresses);
+ void ConnectTcpOnWorkerThread(int routing_id,
+ int request_id,
+ net::AddressList addresses);
- // Continuation of |OnPepperConnectTcpAddress()|.
- void PepperConnectTcpAddressOnWorkerThread(int routing_id,
- int request_id,
- PP_Flash_NetAddress addr);
+ // Continuation of |OnConnectTcpAddress()|.
+ void ConnectTcpAddressOnWorkerThread(int routing_id,
+ int request_id,
+ PP_Flash_NetAddress addr);
#endif // ENABLE_FLAPPER_HACKS
Profile* profile_;
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 7378720..b5ea89e 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -1246,8 +1246,9 @@ void RenderViewHost::MediaPlayerActionAt(const gfx::Point& location,
Send(new ViewMsg_MediaPlayerActionAt(routing_id(), location, action));
}
-void RenderViewHost::ContextMenuClosed() {
- Send(new ViewMsg_ContextMenuClosed(routing_id()));
+void RenderViewHost::ContextMenuClosed(
+ const webkit_glue::CustomContextMenuContext& custom_context) {
+ Send(new ViewMsg_ContextMenuClosed(routing_id(), custom_context));
}
void RenderViewHost::PrintNodeUnderContextMenu() {
@@ -1500,8 +1501,12 @@ void RenderViewHost::UpdateBrowserWindowId(int window_id) {
Send(new ViewMsg_UpdateBrowserWindowId(routing_id(), window_id));
}
-void RenderViewHost::PerformCustomContextMenuAction(unsigned action) {
- Send(new ViewMsg_CustomContextMenuAction(routing_id(), action));
+void RenderViewHost::PerformCustomContextMenuAction(
+ const webkit_glue::CustomContextMenuContext& custom_context,
+ unsigned action) {
+ Send(new ViewMsg_CustomContextMenuAction(routing_id(),
+ custom_context,
+ action));
}
void RenderViewHost::SendContentSettings(const GURL& url,
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index df00cb1..9c1b81d 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -58,6 +58,7 @@ class Point;
} // namespace gfx
namespace webkit_glue {
+struct CustomContextMenuContext;
struct WebAccessibility;
} // namespace webkit_glue
@@ -318,7 +319,8 @@ class RenderViewHost : public RenderWidgetHost {
const WebKit::WebMediaPlayerAction& action);
// Notifies the renderer that the context menu has closed.
- void ContextMenuClosed();
+ void ContextMenuClosed(
+ const webkit_glue::CustomContextMenuContext& custom_context);
// Prints the node that's under the context menu.
void PrintNodeUnderContextMenu();
@@ -462,7 +464,9 @@ class RenderViewHost : public RenderWidgetHost {
void UpdateBrowserWindowId(int window_id);
// Tells the render view that a custom context action has been selected.
- void PerformCustomContextMenuAction(unsigned action);
+ void PerformCustomContextMenuAction(
+ const webkit_glue::CustomContextMenuContext& custom_context,
+ unsigned action);
// Informs renderer of updated content settings.
void SendContentSettings(const GURL& url,
diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc
index 0339888..2bd6ff1 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu.cc
@@ -60,6 +60,98 @@
using WebKit::WebContextMenuData;
using WebKit::WebMediaPlayerAction;
+namespace {
+
+bool IsCustomItemEnabled(const std::vector<WebMenuItem>& items, int id) {
+ DCHECK(id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
+ id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST);
+ for (size_t i = 0; i < items.size(); ++i) {
+ int action_id = IDC_CONTENT_CONTEXT_CUSTOM_FIRST + items[i].action;
+ if (action_id == id)
+ return items[i].enabled;
+ if (items[i].type == WebMenuItem::SUBMENU) {
+ if (IsCustomItemEnabled(items[i].submenu, id))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool IsCustomItemChecked(const std::vector<WebMenuItem>& items, int id) {
+ DCHECK(id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
+ id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST);
+ for (size_t i = 0; i < items.size(); ++i) {
+ int action_id = IDC_CONTENT_CONTEXT_CUSTOM_FIRST + items[i].action;
+ if (action_id == id)
+ return items[i].checked;
+ if (items[i].type == WebMenuItem::SUBMENU) {
+ if (IsCustomItemChecked(items[i].submenu, id))
+ return true;
+ }
+ }
+ return false;
+}
+
+const size_t kMaxCustomMenuDepth = 5;
+const size_t kMaxCustomMenuTotalItems = 1000;
+
+void AddCustomItemsToMenu(const std::vector<WebMenuItem>& items,
+ size_t depth,
+ size_t* total_items,
+ ui::SimpleMenuModel::Delegate* delegate,
+ ui::SimpleMenuModel* menu_model) {
+ if (depth > kMaxCustomMenuDepth) {
+ LOG(ERROR) << "Custom menu too deeply nested.";
+ return;
+ }
+ for (size_t i = 0; i < items.size(); ++i) {
+ if (IDC_CONTENT_CONTEXT_CUSTOM_FIRST + items[i].action >=
+ IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
+ LOG(ERROR) << "Custom menu action value too big.";
+ return;
+ }
+ if (*total_items >= kMaxCustomMenuTotalItems) {
+ LOG(ERROR) << "Custom menu too large (too many items).";
+ return;
+ }
+ (*total_items)++;
+ switch (items[i].type) {
+ case WebMenuItem::OPTION:
+ menu_model->AddItem(
+ items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
+ items[i].label);
+ break;
+ case WebMenuItem::CHECKABLE_OPTION:
+ menu_model->AddCheckItem(
+ items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
+ items[i].label);
+ break;
+ case WebMenuItem::GROUP:
+ // TODO(viettrungluu): I don't know what this is supposed to do.
+ NOTREACHED();
+ break;
+ case WebMenuItem::SEPARATOR:
+ menu_model->AddSeparator();
+ break;
+ case WebMenuItem::SUBMENU: {
+ ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate);
+ AddCustomItemsToMenu(items[i].submenu, depth + 1, total_items, delegate,
+ submenu);
+ menu_model->AddSubMenu(
+ items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
+ items[i].label,
+ submenu);
+ break;
+ }
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
+} // namespace
+
// static
const size_t RenderViewContextMenu::kMaxExtensionItemTitleLength = 75;
// static
@@ -358,7 +450,9 @@ void RenderViewContextMenu::InitMenu() {
bool has_selection = !params_.selection_text.empty();
if (AppendCustomItems()) {
- AppendDeveloperItems();
+ // Don't add items for Pepper menu.
+ if (!params_.custom_context.is_pepper_menu)
+ AppendDeveloperItems();
return;
}
@@ -424,23 +518,10 @@ void RenderViewContextMenu::LookUpInDictionary() {
}
bool RenderViewContextMenu::AppendCustomItems() {
- std::vector<WebMenuItem>& custom_items = params_.custom_items;
- for (size_t i = 0; i < custom_items.size(); ++i) {
- DCHECK(IDC_CONTENT_CONTEXT_CUSTOM_FIRST + custom_items[i].action <
- IDC_CONTENT_CONTEXT_CUSTOM_LAST);
- if (custom_items[i].type == WebMenuItem::SEPARATOR) {
- menu_model_.AddSeparator();
- } else if (custom_items[i].type == WebMenuItem::CHECKABLE_OPTION) {
- menu_model_.AddCheckItem(
- custom_items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
- custom_items[i].label);
- } else {
- menu_model_.AddItem(
- custom_items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
- custom_items[i].label);
- }
- }
- return custom_items.size() > 0;
+ size_t total_items = 0;
+ AddCustomItemsToMenu(params_.custom_items, 0, &total_items, this,
+ &menu_model_);
+ return total_items > 0;
}
void RenderViewContextMenu::AppendDeveloperItems() {
@@ -773,28 +854,10 @@ bool RenderViewContextMenu::IsCommandIdEnabled(int id) const {
return profile_->GetPrefs()->GetBoolean(prefs::kEnableSpellCheck);
}
- // Process custom actions range.
- if ((id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST) &&
- (id < IDC_CONTENT_CONTEXT_CUSTOM_LAST)) {
- unsigned action = id - IDC_CONTENT_CONTEXT_CUSTOM_FIRST;
- for (size_t i = 0; i < params_.custom_items.size(); ++i) {
- if (params_.custom_items[i].action == action)
- return params_.custom_items[i].enabled;
- }
- NOTREACHED();
- return false;
- }
-
- // Custom WebKit items.
+ // Custom items.
if (id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
- const std::vector<WebMenuItem>& custom_items = params_.custom_items;
- for (size_t i = 0; i < custom_items.size(); ++i) {
- int action_id = IDC_CONTENT_CONTEXT_CUSTOM_FIRST + custom_items[i].action;
- if (action_id == id)
- return custom_items[i].enabled;
- }
- return true;
+ return IsCustomItemEnabled(params_.custom_items, id);
}
// Extension items.
@@ -1020,16 +1083,10 @@ bool RenderViewContextMenu::IsCommandIdChecked(int id) const {
WebContextMenuData::MediaControls) != 0;
}
- // Custom WebKit items.
+ // Custom items.
if (id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
- const std::vector<WebMenuItem>& custom_items = params_.custom_items;
- for (size_t i = 0; i < custom_items.size(); ++i) {
- int action_id = IDC_CONTENT_CONTEXT_CUSTOM_FIRST + custom_items[i].action;
- if (action_id == id)
- return custom_items[i].checked;
- }
- return false;
+ return IsCustomItemChecked(params_.custom_items, id);
}
// Extension items.
@@ -1090,11 +1147,11 @@ void RenderViewContextMenu::ExecuteCommand(int id) {
}
// Process custom actions range.
- if ((id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST) &&
- (id < IDC_CONTENT_CONTEXT_CUSTOM_LAST)) {
+ if (id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
+ id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
unsigned action = id - IDC_CONTENT_CONTEXT_CUSTOM_FIRST;
- source_tab_contents_->render_view_host()->
- PerformCustomContextMenuAction(action);
+ source_tab_contents_->render_view_host()->PerformCustomContextMenuAction(
+ params_.custom_context, action);
return;
}
@@ -1399,7 +1456,8 @@ void RenderViewContextMenu::ExecuteCommand(int id) {
}
void RenderViewContextMenu::MenuClosed() {
- source_tab_contents_->render_view_host()->ContextMenuClosed();
+ source_tab_contents_->render_view_host()->ContextMenuClosed(
+ params_.custom_context);
}
bool RenderViewContextMenu::IsDevCommandEnabled(int id) const {
diff --git a/chrome/common/render_messages.cc b/chrome/common/render_messages.cc
index d872fec..28d8f90 100644
--- a/chrome/common/render_messages.cc
+++ b/chrome/common/render_messages.cc
@@ -55,12 +55,18 @@ struct ParamTraits<WebMenuItem::Type> {
case WebMenuItem::OPTION:
type = "OPTION";
break;
+ case WebMenuItem::CHECKABLE_OPTION:
+ type = "CHECKABLE_OPTION";
+ break;
case WebMenuItem::GROUP:
type = "GROUP";
break;
case WebMenuItem::SEPARATOR:
type = "SEPARATOR";
break;
+ case WebMenuItem::SUBMENU:
+ type = "SUBMENU";
+ break;
default:
type = "UNKNOWN";
break;
@@ -78,9 +84,9 @@ void ParamTraits<FontDescriptor>::Write(Message* m, const param_type& p) {
bool ParamTraits<FontDescriptor>::Read(const Message* m,
void** iter,
param_type* p) {
- return(
+ return
ReadParam(m, iter, &p->font_name) &&
- ReadParam(m, iter, &p->font_point_size));
+ ReadParam(m, iter, &p->font_point_size);
}
void ParamTraits<FontDescriptor>::Log(const param_type& p, std::string* l) {
@@ -88,6 +94,31 @@ void ParamTraits<FontDescriptor>::Log(const param_type& p, std::string* l) {
}
#endif
+void ParamTraits<webkit_glue::CustomContextMenuContext>::Write(
+ Message* m,
+ const param_type& p) {
+ WriteParam(m, p.is_pepper_menu);
+ WriteParam(m, p.request_id);
+}
+
+bool ParamTraits<webkit_glue::CustomContextMenuContext>::Read(const Message* m,
+ void** iter,
+ param_type* p) {
+ return
+ ReadParam(m, iter, &p->is_pepper_menu) &&
+ ReadParam(m, iter, &p->request_id);
+}
+
+void ParamTraits<webkit_glue::CustomContextMenuContext>::Log(
+ const param_type& p,
+ std::string* l) {
+ l->append("(");
+ LogParam(p.is_pepper_menu, l);
+ l->append(", ");
+ LogParam(p.request_id, l);
+ l->append(")");
+}
+
void ParamTraits<ContextMenuParams>::Write(Message* m, const param_type& p) {
WriteParam(m, p.media_type);
WriteParam(m, p.x);
@@ -112,6 +143,7 @@ void ParamTraits<ContextMenuParams>::Write(Message* m, const param_type& p) {
WriteParam(m, p.edit_flags);
WriteParam(m, p.security_info);
WriteParam(m, p.frame_charset);
+ WriteParam(m, p.custom_context);
WriteParam(m, p.custom_items);
}
@@ -141,6 +173,7 @@ bool ParamTraits<ContextMenuParams>::Read(const Message* m, void** iter,
ReadParam(m, iter, &p->edit_flags) &&
ReadParam(m, iter, &p->security_info) &&
ReadParam(m, iter, &p->frame_charset) &&
+ ReadParam(m, iter, &p->custom_context) &&
ReadParam(m, iter, &p->custom_items);
}
@@ -742,6 +775,7 @@ void ParamTraits<WebMenuItem>::Write(Message* m, const param_type& p) {
WriteParam(m, p.enabled);
WriteParam(m, p.checked);
WriteParam(m, p.action);
+ WriteParam(m, p.submenu);
}
bool ParamTraits<WebMenuItem>::Read(const Message* m,
@@ -752,7 +786,8 @@ bool ParamTraits<WebMenuItem>::Read(const Message* m,
ReadParam(m, iter, &p->type) &&
ReadParam(m, iter, &p->enabled) &&
ReadParam(m, iter, &p->checked) &&
- ReadParam(m, iter, &p->action);
+ ReadParam(m, iter, &p->action) &&
+ ReadParam(m, iter, &p->submenu);
}
void ParamTraits<WebMenuItem>::Log(const param_type& p, std::string* l) {
@@ -766,6 +801,8 @@ void ParamTraits<WebMenuItem>::Log(const param_type& p, std::string* l) {
LogParam(p.checked, l);
l->append(", ");
LogParam(p.action, l);
+ l->append(", ");
+ LogParam(p.submenu, l);
l->append(")");
}
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 6e5959a..2e94d53 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -49,6 +49,7 @@ class BlobData;
}
namespace webkit_glue {
+struct CustomContextMenuContext;
struct ResourceDevToolsInfo;
struct ResourceLoadTimingInfo;
struct ResourceResponseInfo;
@@ -144,6 +145,14 @@ struct ParamTraits<FontDescriptor> {
#endif
template <>
+struct ParamTraits<webkit_glue::CustomContextMenuContext> {
+ typedef webkit_glue::CustomContextMenuContext param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* p);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template <>
struct ParamTraits<ContextMenuParams> {
typedef ContextMenuParams param_type;
static void Write(Message* m, const param_type& p);
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index ba33f36..466f619 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -955,7 +955,8 @@ IPC_MESSAGE_CONTROL1(ViewMsg_SpellChecker_EnableAutoSpellCorrect,
bool /* enable */)
// Executes custom context menu action that was provided from WebKit.
-IPC_MESSAGE_ROUTED1(ViewMsg_CustomContextMenuAction,
+IPC_MESSAGE_ROUTED2(ViewMsg_CustomContextMenuAction,
+ webkit_glue::CustomContextMenuContext /* custom_context */,
unsigned /* action */)
// Tells the renderer to translate the page contents from one language to
@@ -1057,7 +1058,8 @@ IPC_MESSAGE_CONTROL1(ViewMsg_SpeechInput_SetFeatureEnabled,
// Sent in response to a ViewHostMsg_ContextMenu to let the renderer know that
// the menu has been closed.
-IPC_MESSAGE_ROUTED0(ViewMsg_ContextMenuClosed)
+IPC_MESSAGE_ROUTED1(ViewMsg_ContextMenuClosed,
+ webkit_glue::CustomContextMenuContext /* custom_context */)
//-----------------------------------------------------------------------------
// TabContents messages
diff --git a/chrome/renderer/blocked_plugin.cc b/chrome/renderer/blocked_plugin.cc
index 69e6f18..3133873 100644
--- a/chrome/renderer/blocked_plugin.cc
+++ b/chrome/renderer/blocked_plugin.cc
@@ -148,7 +148,9 @@ bool BlockedPlugin::OnMessageReceived(const IPC::Message& message) {
return false;
}
-void BlockedPlugin::OnMenuItemSelected(unsigned id) {
+void BlockedPlugin::OnMenuItemSelected(
+ const webkit_glue::CustomContextMenuContext& /* ignored */,
+ unsigned id) {
if (id == kMenuActionLoad) {
LoadPlugin();
} else if (id == kMenuActionRemove) {
diff --git a/chrome/renderer/blocked_plugin.h b/chrome/renderer/blocked_plugin.h
index 44e6699..eecff79 100644
--- a/chrome/renderer/blocked_plugin.h
+++ b/chrome/renderer/blocked_plugin.h
@@ -19,6 +19,10 @@ class PluginGroup;
}
}
+namespace webkit_glue {
+struct CustomContextMenuContext;
+}
+
class BlockedPlugin : public RenderViewObserver,
public CppBoundClass,
public webkit::npapi::WebViewPlugin::Delegate {
@@ -45,7 +49,9 @@ class BlockedPlugin : public RenderViewObserver,
// RenderViewObserver methods:
virtual bool OnMessageReceived(const IPC::Message& message);
- void OnMenuItemSelected(unsigned id);
+ void OnMenuItemSelected(
+ const webkit_glue::CustomContextMenuContext& /* ignored */,
+ unsigned id);
// Load the blocked plugin.
void LoadPlugin();
diff --git a/chrome/renderer/pepper_plugin_delegate_impl.cc b/chrome/renderer/pepper_plugin_delegate_impl.cc
index e6d7124..2d3a23e 100644
--- a/chrome/renderer/pepper_plugin_delegate_impl.cc
+++ b/chrome/renderer/pepper_plugin_delegate_impl.cc
@@ -35,6 +35,7 @@
#include "grit/locale_settings.h"
#include "ipc/ipc_channel_handle.h"
#include "ppapi/c/dev/pp_video_dev.h"
+#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_flash.h"
#include "ppapi/proxy/host_dispatcher.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserCompletion.h"
@@ -43,6 +44,7 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "ui/base/l10n/l10n_util.h"
#include "webkit/fileapi/file_system_callback_dispatcher.h"
+#include "webkit/glue/context_menu.h"
#include "webkit/plugins/npapi/webplugin.h"
#include "webkit/plugins/ppapi/ppb_file_io_impl.h"
#include "webkit/plugins/ppapi/plugin_module.h"
@@ -376,6 +378,8 @@ bool DispatcherWrapper::Init(
PepperPluginDelegateImpl::PepperPluginDelegateImpl(RenderView* render_view)
: render_view_(render_view),
+ has_saved_context_menu_action_(false),
+ saved_context_menu_action_(0),
id_generator_(0) {
}
@@ -818,8 +822,10 @@ int32_t PepperPluginDelegateImpl::ConnectTcp(
request_id,
std::string(host),
port);
- if (!render_view_->Send(msg))
+ if (!render_view_->Send(msg)) {
+ pending_connect_tcps_.Remove(request_id);
return PP_ERROR_FAILED;
+ }
return PP_ERROR_WOULDBLOCK;
}
@@ -833,8 +839,10 @@ int32_t PepperPluginDelegateImpl::ConnectTcpAddress(
new PepperMsg_ConnectTcpAddress(render_view_->routing_id(),
request_id,
*addr);
- if (!render_view_->Send(msg))
+ if (!render_view_->Send(msg)) {
+ pending_connect_tcps_.Remove(request_id);
return PP_ERROR_FAILED;
+ }
return PP_ERROR_WOULDBLOCK;
}
@@ -851,6 +859,58 @@ void PepperPluginDelegateImpl::OnConnectTcpACK(
connector->CompleteConnectTcp(socket, local_addr, remote_addr);
}
+int32_t PepperPluginDelegateImpl::ShowContextMenu(
+ webkit::ppapi::PPB_Flash_Menu_Impl* menu,
+ const gfx::Point& position) {
+ int request_id = pending_context_menus_.Add(
+ new scoped_refptr<webkit::ppapi::PPB_Flash_Menu_Impl>(menu));
+
+ ContextMenuParams params;
+ params.x = position.x();
+ params.y = position.y();
+ params.custom_context.is_pepper_menu = true;
+ params.custom_context.request_id = request_id;
+ params.custom_items = menu->menu_data();
+
+ IPC::Message* msg = new ViewHostMsg_ContextMenu(render_view_->routing_id(),
+ params);
+ if (!render_view_->Send(msg)) {
+ pending_context_menus_.Remove(request_id);
+ return PP_ERROR_FAILED;
+ }
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+void PepperPluginDelegateImpl::OnContextMenuClosed(
+ const webkit_glue::CustomContextMenuContext& custom_context) {
+ int request_id = custom_context.request_id;
+ scoped_refptr<webkit::ppapi::PPB_Flash_Menu_Impl> menu =
+ *pending_context_menus_.Lookup(request_id);
+ if (!menu) {
+ NOTREACHED() << "CompleteShowContextMenu() called twice for the same menu.";
+ return;
+ }
+ pending_context_menus_.Remove(request_id);
+
+ if (has_saved_context_menu_action_) {
+ menu->CompleteShow(PP_OK, saved_context_menu_action_);
+ has_saved_context_menu_action_ = false;
+ saved_context_menu_action_ = 0;
+ } else {
+ menu->CompleteShow(PP_ERROR_USERCANCEL, 0);
+ }
+}
+
+void PepperPluginDelegateImpl::OnCustomContextMenuAction(
+ const webkit_glue::CustomContextMenuContext& custom_context,
+ unsigned action) {
+ // Just save the action.
+ DCHECK(!has_saved_context_menu_action_);
+ has_saved_context_menu_action_ = true;
+ saved_context_menu_action_ = action;
+}
+
webkit::ppapi::FullscreenContainer*
PepperPluginDelegateImpl::CreateFullscreenContainer(
webkit::ppapi::PluginInstance* instance) {
diff --git a/chrome/renderer/pepper_plugin_delegate_impl.h b/chrome/renderer/pepper_plugin_delegate_impl.h
index 408163a..f589687 100644
--- a/chrome/renderer/pepper_plugin_delegate_impl.h
+++ b/chrome/renderer/pepper_plugin_delegate_impl.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -16,11 +16,13 @@
#include "ppapi/c/pp_errors.h"
#include "webkit/plugins/ppapi/plugin_delegate.h"
#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_flash_menu_impl.h"
class FilePath;
class RenderView;
namespace gfx {
+class Point;
class Rect;
}
@@ -38,6 +40,10 @@ class WebFileChooserCompletion;
struct WebFileChooserParams;
}
+namespace webkit_glue {
+struct CustomContextMenuContext;
+}
+
class TransportDIB;
class PepperPluginDelegateImpl
@@ -154,6 +160,17 @@ class PepperPluginDelegateImpl
base::PlatformFile socket,
const PP_Flash_NetAddress& local_addr,
const PP_Flash_NetAddress& remote_addr);
+ virtual int32_t ShowContextMenu(
+ webkit::ppapi::PPB_Flash_Menu_Impl* menu,
+ const gfx::Point& position);
+ void OnContextMenuClosed(
+ const webkit_glue::CustomContextMenuContext& custom_context);
+ void OnCustomContextMenuAction(
+ const webkit_glue::CustomContextMenuContext& custom_context,
+ unsigned action);
+ void CompleteShowContextMenu(int request_id,
+ bool did_select,
+ unsigned action);
virtual webkit::ppapi::FullscreenContainer*
CreateFullscreenContainer(
webkit::ppapi::PluginInstance* instance);
@@ -171,6 +188,10 @@ class PepperPluginDelegateImpl
std::set<webkit::ppapi::PluginInstance*> active_instances_;
+ // Used to send a single context menu "completion" upon menu close.
+ bool has_saved_context_menu_action_;
+ unsigned saved_context_menu_action_;
+
// TODO(viettrungluu): Get rid of |id_generator_| -- just use |IDMap::Add()|.
// Rename |messages_waiting_replies_| (to specify async open file).
int id_generator_;
@@ -179,6 +200,9 @@ class PepperPluginDelegateImpl
IDMap<scoped_refptr<webkit::ppapi::PPB_Flash_NetConnector_Impl>,
IDMapOwnPointer> pending_connect_tcps_;
+ IDMap<scoped_refptr<webkit::ppapi::PPB_Flash_Menu_Impl>,
+ IDMapOwnPointer> pending_context_menus_;
+
DISALLOW_COPY_AND_ASSIGN(PepperPluginDelegateImpl);
};
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 2dc7c80..25e3544 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -4716,8 +4716,13 @@ void RenderView::OnSetAltErrorPageURL(const GURL& url) {
alternate_error_page_url_ = url;
}
-void RenderView::OnCustomContextMenuAction(unsigned action) {
- webview()->performCustomContextMenuAction(action);
+void RenderView::OnCustomContextMenuAction(
+ const webkit_glue::CustomContextMenuContext& custom_context,
+ unsigned action) {
+ if (custom_context.is_pepper_menu)
+ pepper_delegate_.OnCustomContextMenuAction(custom_context, action);
+ else
+ webview()->performCustomContextMenuAction(action);
}
void RenderView::OnTranslatePage(int page_id,
@@ -5774,6 +5779,10 @@ void RenderView::OnJavaScriptStressTestControl(int cmd, int param) {
}
}
-void RenderView::OnContextMenuClosed() {
- context_menu_node_.reset();
+void RenderView::OnContextMenuClosed(
+ const webkit_glue::CustomContextMenuContext& custom_context) {
+ if (custom_context.is_pepper_menu)
+ pepper_delegate_.OnContextMenuClosed(custom_context);
+ else
+ context_menu_node_.reset();
}
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 92a3577..314224d 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -114,6 +114,7 @@ class PhishingClassifierDelegate;
}
namespace webkit_glue {
+struct CustomContextMenuContext;
class ImageResourceFetcher;
struct FileUploadData;
struct FormData;
@@ -826,7 +827,8 @@ class RenderView : public RenderWidget,
const PP_Flash_NetAddress& local_addr,
const PP_Flash_NetAddress& remote_addr);
#endif
- void OnContextMenuClosed();
+ void OnContextMenuClosed(
+ const webkit_glue::CustomContextMenuContext& custom_context);
void OnCopy();
void OnCopyImageAt(int x, int y);
#if defined(OS_MACOSX)
@@ -838,7 +840,9 @@ class RenderView : public RenderWidget,
void OnCSSInsertRequest(const std::wstring& frame_xpath,
const std::string& css,
const std::string& id);
- void OnCustomContextMenuAction(unsigned action);
+ void OnCustomContextMenuAction(
+ const webkit_glue::CustomContextMenuContext& custom_context,
+ unsigned action);
void OnDelete();
void OnDeterminePageLanguage();
void OnDisableScrollbarsForSmallWindows(
diff --git a/ppapi/c/pp_errors.h b/ppapi/c/pp_errors.h
index 2d07e90..0138f2f 100644
--- a/ppapi/c/pp_errors.h
+++ b/ppapi/c/pp_errors.h
@@ -75,7 +75,10 @@ enum {
PP_ERROR_FILECHANGED = -23,
/** Indicates failure due to a time limit being exceeded. */
- PP_ERROR_TIMEDOUT = -30
+ PP_ERROR_TIMEDOUT = -30,
+
+ /** Indicates that the user cancelled rather providing expected input. */
+ PP_ERROR_USERCANCEL = -40
};
/**
@@ -84,4 +87,3 @@ enum {
*/
#endif /* PPAPI_C_PP_ERRORS_H_ */
-
diff --git a/ppapi/c/private/ppb_flash.h b/ppapi/c/private/ppb_flash.h
index a7a5bab..3f8f222 100644
--- a/ppapi/c/private/ppb_flash.h
+++ b/ppapi/c/private/ppb_flash.h
@@ -19,7 +19,7 @@
// PPB_Flash -------------------------------------------------------------------
-#define PPB_FLASH_INTERFACE "PPB_Flash;4"
+#define PPB_FLASH_INTERFACE "PPB_Flash;5"
#ifdef _WIN32
typedef HANDLE PP_FileHandle;
@@ -116,6 +116,17 @@ struct PPB_Flash {
PP_Bool (*NavigateToURL)(PP_Instance instance,
const char* url,
const char* target);
+
+ // Runs a nested message loop. The plugin will be reentered from this call.
+ // This function is used in places where Flash would normally enter a nested
+ // message loop (e.g., when displaying context menus), but Pepper provides
+ // only an asynchronous call. After performing that asynchronous call, call
+ // |RunMessageLoop()|. In the callback, call |QuitMessageLoop()|.
+ void (*RunMessageLoop)();
+
+ // Posts a quit message for the outermost nested message loop. Use this to
+ // exit and return back to the caller after you call RunMessageLoop.
+ void (*QuitMessageLoop)();
};
// PPB_Flash_NetConnector ------------------------------------------------------
diff --git a/ppapi/c/private/ppb_flash_menu.h b/ppapi/c/private/ppb_flash_menu.h
new file mode 100644
index 0000000..a183baf
--- /dev/null
+++ b/ppapi/c/private/ppb_flash_menu.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2011 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 PPAPI_C_PRIVATE_PPB_FLASH_MENU_H_
+#define PPAPI_C_PRIVATE_PPB_FLASH_MENU_H_
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/pp_resource.h"
+
+// PPB_Flash -------------------------------------------------------------------
+
+#define PPB_FLASH_MENU_INTERFACE "PPB_Flash_Menu;1"
+
+struct PP_CompletionCallback;
+
+typedef enum {
+ // TODO(viettrungluu): Radio items not supported yet. Will also probably want
+ // special menu items tied to clipboard access.
+ PP_FLASH_MENUITEM_TYPE_NORMAL = 0,
+ PP_FLASH_MENUITEM_TYPE_CHECKBOX,
+ PP_FLASH_MENUITEM_TYPE_SEPARATOR,
+ PP_FLASH_MENUITEM_TYPE_SUBMENU
+} PP_Flash_MenuItem_Type;
+
+struct PP_Flash_MenuItem {
+ PP_Flash_MenuItem_Type type;
+ char* name;
+ int32_t id;
+ PP_Bool enabled;
+ PP_Bool checked;
+ struct PP_Flash_Menu* submenu;
+};
+
+struct PP_Flash_Menu {
+ uint32_t count;
+ struct PP_Flash_MenuItem* items;
+};
+
+struct PPB_Flash_Menu {
+ PP_Resource (*Create)(PP_Instance instance_id,
+ const struct PP_Flash_Menu* menu_data);
+ PP_Bool (*IsFlashMenu)(PP_Resource resource_id);
+
+ // Display a context menu at the given location. If the user selects an item,
+ // |selected_id| will be set to its |id| and the callback called with |PP_OK|.
+ // If the user dismisses the menu without selecting an item,
+ // |PP_ERROR_USERCANCEL| will be indicated.
+ int32_t (*Show)(PP_Resource menu_id,
+ const struct PP_Point* location,
+ int32_t* selected_id,
+ PP_CompletionCallback callback);
+};
+
+#endif // PPAPI_C_PRIVATE_PPB_FLASH_MENU_H_
diff --git a/ppapi/cpp/private/flash_menu.cc b/ppapi/cpp/private/flash_menu.cc
new file mode 100644
index 0000000..8596fc9
--- /dev/null
+++ b/ppapi/cpp/private/flash_menu.cc
@@ -0,0 +1,48 @@
+// Copyright (c) 2011 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.
+
+// TODO(viettrungluu): See the comment in corresponding .h file.
+
+#include "ppapi/cpp/private/flash_menu.h"
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/module_impl.h"
+#include "ppapi/cpp/point.h"
+
+namespace pp {
+
+namespace {
+
+template <> const char* interface_name<PPB_Flash_Menu>() {
+ return PPB_FLASH_MENU_INTERFACE;
+}
+
+} // namespace
+
+namespace flash {
+
+Menu::Menu(const Instance& instance, const struct PP_Flash_Menu* menu_data) {
+ if (has_interface<PPB_Flash_Menu>()) {
+ PassRefFromConstructor(get_interface<PPB_Flash_Menu>()->Create(
+ instance.pp_instance(), menu_data));
+ }
+}
+
+int32_t Menu::Show(const Point& location,
+ int32_t* selected_id,
+ const CompletionCallback& cc) {
+ if (!has_interface<PPB_Flash_Menu>())
+ return PP_ERROR_NOINTERFACE;
+ return get_interface<PPB_Flash_Menu>()->Show(
+ pp_resource(),
+ &location.pp_point(),
+ selected_id,
+ cc.pp_completion_callback());
+}
+
+} // namespace flash
+} // namespace pp
diff --git a/ppapi/cpp/private/flash_menu.h b/ppapi/cpp/private/flash_menu.h
new file mode 100644
index 0000000..a5d4408
--- /dev/null
+++ b/ppapi/cpp/private/flash_menu.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2011 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.
+
+// TODO(viettrungluu): This (and the .cc file) contain C++ wrappers for some
+// things in ppapi/c/private/ppb_flash_menu.h. This is currently not used in (or
+// even compiled with) Chromium.
+
+#ifndef PPAPI_CPP_PRIVATE_FLASH_MENU_H_
+#define PPAPI_CPP_PRIVATE_FLASH_MENU_H_
+
+#include "ppapi/c/private/ppb_flash_menu.h"
+#include "ppapi/cpp/resource.h"
+
+namespace pp {
+
+class CompletionCallback;
+class Instance;
+class Point;
+
+namespace flash {
+
+class Menu : public Resource {
+ public:
+ // TODO(viettrungluu): Write a proper C++ wrapper of |PP_Flash_Menu|.
+ Menu(const Instance& instance, const struct PP_Flash_Menu* menu_data);
+
+ int32_t Show(const Point& location,
+ int32_t* selected_id,
+ const CompletionCallback& cc);
+};
+
+} // namespace flash
+} // namespace pp
+
+#endif // PPAPI_CPP_PRIVATE_FLASH_H_
diff --git a/ppapi/ppapi_cpp.gypi b/ppapi/ppapi_cpp.gypi
index 79f5603..112edcd 100644
--- a/ppapi/ppapi_cpp.gypi
+++ b/ppapi/ppapi_cpp.gypi
@@ -82,6 +82,7 @@
# Private interfaces.
'c/private/ppb_flash.h',
+ 'c/private/ppb_flash_menu.h',
'c/private/ppb_nacl_private.h',
'c/private/ppb_pdf.h',
diff --git a/webkit/glue/context_menu.cc b/webkit/glue/context_menu.cc
index bdfe790..6db5c51 100644
--- a/webkit/glue/context_menu.cc
+++ b/webkit/glue/context_menu.cc
@@ -4,6 +4,15 @@
#include "webkit/glue/context_menu.h"
+namespace webkit_glue {
+
+CustomContextMenuContext::CustomContextMenuContext()
+ : is_pepper_menu(false),
+ request_id(0) {
+}
+
+} // namespace webkit_glue
+
ContextMenuParams::ContextMenuParams() {
}
@@ -30,6 +39,7 @@ ContextMenuParams::ContextMenuParams(const WebKit::WebContextMenuData& data)
edit_flags(data.editFlags),
security_info(data.securityInfo),
frame_charset(data.frameEncoding.utf8()) {
+ custom_context.is_pepper_menu = false;
for (size_t i = 0; i < data.customItems.size(); ++i)
custom_items.push_back(WebMenuItem(data.customItems[i]));
}
diff --git a/webkit/glue/context_menu.h b/webkit/glue/context_menu.h
index e1a88cb..2f38807 100644
--- a/webkit/glue/context_menu.h
+++ b/webkit/glue/context_menu.h
@@ -14,6 +14,18 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h"
+namespace webkit_glue {
+
+struct CustomContextMenuContext {
+ bool is_pepper_menu;
+ int request_id;
+
+ CustomContextMenuContext();
+};
+
+} // namespace webkit_glue
+
+// TODO(viettrungluu): Put this in the webkit_glue namespace.
// Parameters structure for ViewHostMsg_ContextMenu.
// FIXME(beng): This would be more useful in the future and more efficient
// if the parameters here weren't so literally mapped to what
@@ -94,6 +106,7 @@ struct ContextMenuParams {
// The character encoding of the frame on which the menu is invoked.
std::string frame_charset;
+ webkit_glue::CustomContextMenuContext custom_context;
std::vector<WebMenuItem> custom_items;
ContextMenuParams();
diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi
index 2de3fbc..31744a0 100644
--- a/webkit/glue/webkit_glue.gypi
+++ b/webkit/glue/webkit_glue.gypi
@@ -296,6 +296,8 @@
'../plugins/ppapi/ppb_flash_impl.cc',
'../plugins/ppapi/ppb_flash_impl.h',
'../plugins/ppapi/ppb_flash_impl_linux.cc',
+ '../plugins/ppapi/ppb_flash_menu_impl.cc',
+ '../plugins/ppapi/ppb_flash_menu_impl.h',
'../plugins/ppapi/ppb_font_impl.cc',
'../plugins/ppapi/ppb_font_impl.h',
'../plugins/ppapi/ppb_gles_chromium_texture_mapping_impl.cc',
diff --git a/webkit/glue/webmenuitem.h b/webkit/glue/webmenuitem.h
index f2eb448..c767bea 100644
--- a/webkit/glue/webmenuitem.h
+++ b/webkit/glue/webmenuitem.h
@@ -1,10 +1,12 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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 WEBMENUITEM_H_
#define WEBMENUITEM_H_
+#include <vector>
+
#include "base/string16.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebMenuItemInfo.h"
@@ -15,7 +17,8 @@ struct WebMenuItem {
OPTION = WebKit::WebMenuItemInfo::Option,
CHECKABLE_OPTION = WebKit::WebMenuItemInfo::CheckableOption,
GROUP = WebKit::WebMenuItemInfo::Group,
- SEPARATOR = WebKit::WebMenuItemInfo::Separator
+ SEPARATOR = WebKit::WebMenuItemInfo::Separator,
+ SUBMENU // This is currently only used by Pepper, not by WebKit.
};
string16 label;
@@ -23,6 +26,7 @@ struct WebMenuItem {
unsigned action;
bool enabled;
bool checked;
+ std::vector<WebMenuItem> submenu;
WebMenuItem() : type(OPTION), action(0), enabled(false), checked(false) {
}
diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.cc b/webkit/plugins/ppapi/mock_plugin_delegate.cc
index e072ebb..54e55ee 100644
--- a/webkit/plugins/ppapi/mock_plugin_delegate.cc
+++ b/webkit/plugins/ppapi/mock_plugin_delegate.cc
@@ -173,6 +173,12 @@ int32_t MockPluginDelegate::ConnectTcpAddress(
return PP_ERROR_FAILED;
}
+int32_t MockPluginDelegate::ShowContextMenu(
+ webkit::ppapi::PPB_Flash_Menu_Impl* menu,
+ const gfx::Point& position) {
+ return PP_ERROR_FAILED;
+}
+
FullscreenContainer* MockPluginDelegate::CreateFullscreenContainer(
PluginInstance* instance) {
return NULL;
diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.h b/webkit/plugins/ppapi/mock_plugin_delegate.h
index 5d652dd..75d4637 100644
--- a/webkit/plugins/ppapi/mock_plugin_delegate.h
+++ b/webkit/plugins/ppapi/mock_plugin_delegate.h
@@ -90,6 +90,9 @@ class MockPluginDelegate : public PluginDelegate {
virtual int32_t ConnectTcpAddress(
webkit::ppapi::PPB_Flash_NetConnector_Impl* connector,
const struct PP_Flash_NetAddress* addr);
+ virtual int32_t ShowContextMenu(
+ webkit::ppapi::PPB_Flash_Menu_Impl* menu,
+ const gfx::Point& position);
virtual FullscreenContainer* CreateFullscreenContainer(
PluginInstance* instance);
virtual std::string GetDefaultEncoding();
diff --git a/webkit/plugins/ppapi/plugin_delegate.h b/webkit/plugins/ppapi/plugin_delegate.h
index 94ffa61..8f36c3d 100644
--- a/webkit/plugins/ppapi/plugin_delegate.h
+++ b/webkit/plugins/ppapi/plugin_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -34,6 +34,7 @@ class FileSystemCallbackDispatcher;
}
namespace gfx {
+class Point;
class Rect;
}
@@ -64,6 +65,7 @@ class FileIO;
class FullscreenContainer;
class PluginInstance;
class PluginModule;
+class PPB_Flash_Menu_Impl;
class PPB_Flash_NetConnector_Impl;
// Virtual interface that the browser implements to implement features for
@@ -302,6 +304,12 @@ class PluginDelegate {
webkit::ppapi::PPB_Flash_NetConnector_Impl* connector,
const struct PP_Flash_NetAddress* addr) = 0;
+ // Show the given context menu at the given position (in the render view's
+ // coordinates).
+ virtual int32_t ShowContextMenu(
+ webkit::ppapi::PPB_Flash_Menu_Impl* menu,
+ const gfx::Point& position) = 0;
+
// Create a fullscreen container for a plugin instance. This effectively
// switches the plugin to fullscreen.
virtual FullscreenContainer* CreateFullscreenContainer(
diff --git a/webkit/plugins/ppapi/plugin_module.cc b/webkit/plugins/ppapi/plugin_module.cc
index cec7e79..332770ff 100644
--- a/webkit/plugins/ppapi/plugin_module.cc
+++ b/webkit/plugins/ppapi/plugin_module.cc
@@ -50,6 +50,7 @@
#include "ppapi/c/ppp.h"
#include "ppapi/c/ppp_instance.h"
#include "ppapi/c/private/ppb_flash.h"
+#include "ppapi/c/private/ppb_flash_menu.h"
#include "ppapi/c/private/ppb_pdf.h"
#include "ppapi/c/private/ppb_nacl_private.h"
#include "ppapi/c/trusted/ppb_image_data_trusted.h"
@@ -67,6 +68,7 @@
#include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
#include "webkit/plugins/ppapi/ppb_file_system_impl.h"
#include "webkit/plugins/ppapi/ppb_flash_impl.h"
+#include "webkit/plugins/ppapi/ppb_flash_menu_impl.h"
#include "webkit/plugins/ppapi/ppb_font_impl.h"
#include "webkit/plugins/ppapi/ppb_graphics_2d_impl.h"
#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
@@ -242,6 +244,8 @@ const void* GetInterface(const char* name) {
return PluginInstance::GetFindInterface();
if (strcmp(name, PPB_FLASH_INTERFACE) == 0)
return PPB_Flash_Impl::GetInterface();
+ if (strcmp(name, PPB_FLASH_MENU_INTERFACE) == 0)
+ return PPB_Flash_Menu_Impl::GetInterface();
if (strcmp(name, PPB_FONT_DEV_INTERFACE) == 0)
return PPB_Font_Impl::GetInterface();
if (strcmp(name, PPB_FULLSCREEN_DEV_INTERFACE) == 0)
diff --git a/webkit/plugins/ppapi/ppb_flash_impl.cc b/webkit/plugins/ppapi/ppb_flash_impl.cc
index 33e0d11..36ba4ac 100644
--- a/webkit/plugins/ppapi/ppb_flash_impl.cc
+++ b/webkit/plugins/ppapi/ppb_flash_impl.cc
@@ -7,6 +7,7 @@
#include <string.h>
#include "base/file_path.h"
+#include "base/message_loop.h"
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "googleurl/src/gurl.h"
@@ -217,6 +218,17 @@ PP_Bool NavigateToURL(PP_Instance pp_instance,
return BoolToPPBool(instance->NavigateToURL(url, target));
}
+void RunMessageLoop() {
+ bool old_state = MessageLoop::current()->NestableTasksAllowed();
+ MessageLoop::current()->SetNestableTasksAllowed(true);
+ MessageLoop::current()->Run();
+ MessageLoop::current()->SetNestableTasksAllowed(old_state);
+}
+
+void QuitMessageLoop() {
+ MessageLoop::current()->QuitNow();
+}
+
const PPB_Flash ppb_flash = {
&SetInstanceAlwaysOnTop,
&PPB_Flash_Impl::DrawGlyphs,
@@ -229,6 +241,8 @@ const PPB_Flash ppb_flash = {
&GetModuleLocalDirContents,
&FreeModuleLocalDirContents,
&NavigateToURL,
+ &RunMessageLoop,
+ &QuitMessageLoop,
};
} // namespace
diff --git a/webkit/plugins/ppapi/ppb_flash_menu_impl.cc b/webkit/plugins/ppapi/ppb_flash_menu_impl.cc
new file mode 100644
index 0000000..67776fe
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_flash_menu_impl.cc
@@ -0,0 +1,223 @@
+// Copyright (c) 2011 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.
+
+#include "webkit/plugins/ppapi/ppb_flash_menu_impl.h"
+
+#include "base/utf_string_conversions.h"
+#include "gfx/point.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "webkit/glue/webmenuitem.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PP_Resource Create(PP_Instance instance_id, const PP_Flash_Menu* menu_data) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return 0;
+
+ scoped_refptr<PPB_Flash_Menu_Impl> menu(new PPB_Flash_Menu_Impl(instance));
+ if (!menu->Init(menu_data))
+ return 0;
+
+ return menu->GetReference();
+}
+
+PP_Bool IsFlashMenu(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_Flash_Menu_Impl>(resource));
+}
+
+int32_t Show(PP_Resource menu_id,
+ const PP_Point* location,
+ int32_t* selected_id,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_Flash_Menu_Impl> menu(
+ Resource::GetAs<PPB_Flash_Menu_Impl>(menu_id));
+ if (!menu.get())
+ return PP_ERROR_BADRESOURCE;
+
+ return menu->Show(location, selected_id, callback);
+}
+
+const PPB_Flash_Menu ppb_flash_menu = {
+ &Create,
+ &IsFlashMenu,
+ &Show,
+};
+
+// Maximum depth of submenus allowed (e.g., 1 indicates that submenus are
+// allowed, but not sub-submenus).
+const size_t kMaxMenuDepth = 2;
+
+// Maximum number of entries in any single menu (including separators).
+const size_t kMaxMenuEntries = 50;
+
+// Maximum total number of entries in the |menu_id_map| (see below).
+// (Limit to 500 real entries; reserve the 0 action as an invalid entry.)
+const size_t kMaxMenuIdMapEntries = 501;
+
+// Converts menu data from one form to another.
+// - |depth| is the current nested depth (call it starting with 0).
+// - |menu_id_map| is such that |menu_id_map[output_item.action] ==
+// input_item.id| (where |action| is what a |WebMenuItem| has, |id| is what a
+// |PP_Flash_MenuItem| has).
+bool ConvertMenuData(const PP_Flash_Menu* in_menu,
+ size_t depth,
+ PPB_Flash_Menu_Impl::MenuData* out_menu,
+ std::vector<int32_t>* menu_id_map) {
+ if (depth > kMaxMenuDepth)
+ return false;
+
+ // Clear the output, just in case.
+ out_menu->clear();
+
+ if (!in_menu || !in_menu->count)
+ return true; // Nothing else to do.
+
+ if (!in_menu->items || in_menu->count > kMaxMenuEntries)
+ return false;
+ for (uint32_t i = 0; i < in_menu->count; i++) {
+ WebMenuItem item;
+
+ PP_Flash_MenuItem_Type type = in_menu->items[i].type;
+ switch (type) {
+ case PP_FLASH_MENUITEM_TYPE_NORMAL:
+ item.type = WebMenuItem::OPTION;
+ break;
+ case PP_FLASH_MENUITEM_TYPE_CHECKBOX:
+ item.type = WebMenuItem::CHECKABLE_OPTION;
+ break;
+ case PP_FLASH_MENUITEM_TYPE_SEPARATOR:
+ item.type = WebMenuItem::SEPARATOR;
+ break;
+ case PP_FLASH_MENUITEM_TYPE_SUBMENU:
+ item.type = WebMenuItem::SUBMENU;
+ break;
+ default:
+ return false;
+ }
+ if (in_menu->items[i].name)
+ item.label = UTF8ToUTF16(in_menu->items[i].name);
+ if (menu_id_map->size() >= kMaxMenuIdMapEntries)
+ return false;
+ item.action = static_cast<unsigned>(menu_id_map->size());
+ // This sets |(*menu_id_map)[item.action] = in_menu->items[i].id|.
+ menu_id_map->push_back(in_menu->items[i].id);
+ item.enabled = PPBoolToBool(in_menu->items[i].enabled);
+ item.checked = PPBoolToBool(in_menu->items[i].checked);
+ if (type == PP_FLASH_MENUITEM_TYPE_SUBMENU) {
+ if (!ConvertMenuData(in_menu->items[i].submenu, depth + 1, &item.submenu,
+ menu_id_map))
+ return false;
+ }
+
+ out_menu->push_back(item);
+ }
+
+ return true;
+}
+
+} // namespace
+
+PPB_Flash_Menu_Impl::PPB_Flash_Menu_Impl(PluginInstance* instance)
+ : Resource(instance) {
+}
+
+bool PPB_Flash_Menu_Impl::Init(const PP_Flash_Menu* menu_data) {
+ menu_id_map_.clear();
+ menu_id_map_.push_back(0); // Reserve |menu_id_map_[0]|.
+ if (!ConvertMenuData(menu_data, 0, &menu_data_, &menu_id_map_)) {
+ menu_id_map_.clear();
+ return false;
+ }
+
+ return true;
+}
+
+PPB_Flash_Menu_Impl::~PPB_Flash_Menu_Impl() {
+}
+
+// static
+const PPB_Flash_Menu* PPB_Flash_Menu_Impl::GetInterface() {
+ return &ppb_flash_menu;
+}
+
+PPB_Flash_Menu_Impl* PPB_Flash_Menu_Impl::AsPPB_Flash_Menu_Impl() {
+ return this;
+}
+
+int32_t PPB_Flash_Menu_Impl::Show(const PP_Point* location,
+ int32_t* selected_id_out,
+ PP_CompletionCallback callback) {
+ // |location| is not (currently) optional.
+ // TODO(viettrungluu): Make it optional and default to the current mouse pos?
+ if (!location)
+ return PP_ERROR_BADARGUMENT;
+
+ if (!callback.func) {
+ NOTIMPLEMENTED();
+ return PP_ERROR_BADARGUMENT;
+ }
+
+ if (callback_.get() && !callback_->completed())
+ return PP_ERROR_INPROGRESS;
+
+ PP_Resource resource_id = GetReferenceNoAddRef();
+ if (!resource_id) {
+ NOTREACHED();
+ return PP_ERROR_FAILED;
+ }
+
+ int32_t rv = instance()->delegate()->ShowContextMenu(
+ this, gfx::Point(instance()->position().x() + location->x,
+ instance()->position().y() + location->y));
+ if (rv == PP_ERROR_WOULDBLOCK) {
+ // Record callback and output buffers.
+ callback_ = new TrackedCompletionCallback(
+ instance()->module()->GetCallbackTracker(), resource_id, callback);
+ selected_id_out_ = selected_id_out;
+ } else {
+ // This should never be completed synchronously successfully.
+ DCHECK_NE(rv, PP_OK);
+ }
+ return rv;
+
+ NOTIMPLEMENTED();
+ return PP_ERROR_FAILED;
+}
+
+void PPB_Flash_Menu_Impl::CompleteShow(int32_t result,
+ unsigned action) {
+ int32_t rv = PP_ERROR_ABORTED;
+ if (!callback_->aborted()) {
+ CHECK(!callback_->completed());
+ rv = result;
+
+ // Write output data.
+ if (selected_id_out_ && result == PP_OK) {
+ // We reserved action 0 to be invalid.
+ if (action == 0 || action >= menu_id_map_.size()) {
+ NOTREACHED() << "Invalid action received.";
+ rv = PP_ERROR_FAILED;
+ } else {
+ *selected_id_out_ = menu_id_map_[action];
+ }
+ }
+ }
+
+ scoped_refptr<TrackedCompletionCallback> callback;
+ callback.swap(callback_);
+ selected_id_out_ = NULL;
+
+ callback->Run(rv); // Will complete abortively if necessary.
+}
+
+} // namespace ppapi
+} // namespace webkit
diff --git a/webkit/plugins/ppapi/ppb_flash_menu_impl.h b/webkit/plugins/ppapi/ppb_flash_menu_impl.h
new file mode 100644
index 0000000..610e46e
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_flash_menu_impl.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2011 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 WEBKIT_PLUGINS_PPAPI_PPB_FLASH_MENU_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_FLASH_MENU_IMPL_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/private/ppb_flash_menu.h"
+#include "webkit/plugins/ppapi/callbacks.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+struct WebMenuItem;
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_Flash_Menu_Impl : public Resource {
+ public:
+ explicit PPB_Flash_Menu_Impl(PluginInstance* instance);
+ virtual ~PPB_Flash_Menu_Impl();
+
+ static const PPB_Flash_Menu* GetInterface();
+
+ bool Init(const PP_Flash_Menu* menu_data);
+
+ // Resource override.
+ virtual PPB_Flash_Menu_Impl* AsPPB_Flash_Menu_Impl();
+
+ // PPB_Flash_Menu implementation.
+ int32_t Show(const PP_Point* location,
+ int32_t* selected_id_out,
+ PP_CompletionCallback callback);
+
+ // Called to complete |Show()|.
+ void CompleteShow(int32_t result, unsigned action);
+
+ typedef std::vector<WebMenuItem> MenuData;
+ const MenuData& menu_data() const { return menu_data_; }
+
+ private:
+ MenuData menu_data_;
+
+ // We send |WebMenuItem|s, which have an |unsigned| "action" field instead of
+ // an |int32_t| ID. (Chrome also limits the range of valid values for
+ // actions.) This maps actions to IDs.
+ std::vector<int32_t> menu_id_map_;
+
+ // Any pending callback (for |Show()|).
+ scoped_refptr<TrackedCompletionCallback> callback_;
+
+ // Output buffers to be filled in when the callback is completed successfully.
+ int32_t* selected_id_out_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Flash_Menu_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_FLASH_MENU_IMPL_H_
diff --git a/webkit/plugins/ppapi/resource.h b/webkit/plugins/ppapi/resource.h
index fb4f2ef..10664f9 100644
--- a/webkit/plugins/ppapi/resource.h
+++ b/webkit/plugins/ppapi/resource.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -25,6 +25,7 @@ namespace ppapi {
F(PPB_FileIO_Impl) \
F(PPB_FileRef_Impl) \
F(PPB_FileSystem_Impl) \
+ F(PPB_Flash_Menu_Impl) \
F(PPB_Flash_NetConnector_Impl) \
F(PPB_Font_Impl) \
F(PPB_Graphics2D_Impl) \