Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(717)

Unified Diff: webkit/plugins/ppapi/ppb_flash_menu_impl.cc

Issue 6253017: Pepper/Flapper: First pass at context menu implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: make brettw happier Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webkit/plugins/ppapi/ppb_flash_menu_impl.h ('k') | webkit/plugins/ppapi/resource.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/plugins/ppapi/ppb_flash_menu_impl.cc
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 0000000000000000000000000000000000000000..67776feefbd71762acd113b3f9f3ceac041d562c
--- /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
« no previous file with comments | « webkit/plugins/ppapi/ppb_flash_menu_impl.h ('k') | webkit/plugins/ppapi/resource.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698