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

Side by Side 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, 10 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 unified diff | Download patch | Annotate | Revision Log
« 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "webkit/plugins/ppapi/ppb_flash_menu_impl.h"
6
7 #include "base/utf_string_conversions.h"
8 #include "gfx/point.h"
9 #include "ppapi/c/pp_completion_callback.h"
10 #include "webkit/glue/webmenuitem.h"
11 #include "webkit/plugins/ppapi/common.h"
12 #include "webkit/plugins/ppapi/plugin_delegate.h"
13 #include "webkit/plugins/ppapi/plugin_module.h"
14 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
15
16 namespace webkit {
17 namespace ppapi {
18
19 namespace {
20
21 PP_Resource Create(PP_Instance instance_id, const PP_Flash_Menu* menu_data) {
22 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
23 if (!instance)
24 return 0;
25
26 scoped_refptr<PPB_Flash_Menu_Impl> menu(new PPB_Flash_Menu_Impl(instance));
27 if (!menu->Init(menu_data))
28 return 0;
29
30 return menu->GetReference();
31 }
32
33 PP_Bool IsFlashMenu(PP_Resource resource) {
34 return BoolToPPBool(!!Resource::GetAs<PPB_Flash_Menu_Impl>(resource));
35 }
36
37 int32_t Show(PP_Resource menu_id,
38 const PP_Point* location,
39 int32_t* selected_id,
40 PP_CompletionCallback callback) {
41 scoped_refptr<PPB_Flash_Menu_Impl> menu(
42 Resource::GetAs<PPB_Flash_Menu_Impl>(menu_id));
43 if (!menu.get())
44 return PP_ERROR_BADRESOURCE;
45
46 return menu->Show(location, selected_id, callback);
47 }
48
49 const PPB_Flash_Menu ppb_flash_menu = {
50 &Create,
51 &IsFlashMenu,
52 &Show,
53 };
54
55 // Maximum depth of submenus allowed (e.g., 1 indicates that submenus are
56 // allowed, but not sub-submenus).
57 const size_t kMaxMenuDepth = 2;
58
59 // Maximum number of entries in any single menu (including separators).
60 const size_t kMaxMenuEntries = 50;
61
62 // Maximum total number of entries in the |menu_id_map| (see below).
63 // (Limit to 500 real entries; reserve the 0 action as an invalid entry.)
64 const size_t kMaxMenuIdMapEntries = 501;
65
66 // Converts menu data from one form to another.
67 // - |depth| is the current nested depth (call it starting with 0).
68 // - |menu_id_map| is such that |menu_id_map[output_item.action] ==
69 // input_item.id| (where |action| is what a |WebMenuItem| has, |id| is what a
70 // |PP_Flash_MenuItem| has).
71 bool ConvertMenuData(const PP_Flash_Menu* in_menu,
72 size_t depth,
73 PPB_Flash_Menu_Impl::MenuData* out_menu,
74 std::vector<int32_t>* menu_id_map) {
75 if (depth > kMaxMenuDepth)
76 return false;
77
78 // Clear the output, just in case.
79 out_menu->clear();
80
81 if (!in_menu || !in_menu->count)
82 return true; // Nothing else to do.
83
84 if (!in_menu->items || in_menu->count > kMaxMenuEntries)
85 return false;
86 for (uint32_t i = 0; i < in_menu->count; i++) {
87 WebMenuItem item;
88
89 PP_Flash_MenuItem_Type type = in_menu->items[i].type;
90 switch (type) {
91 case PP_FLASH_MENUITEM_TYPE_NORMAL:
92 item.type = WebMenuItem::OPTION;
93 break;
94 case PP_FLASH_MENUITEM_TYPE_CHECKBOX:
95 item.type = WebMenuItem::CHECKABLE_OPTION;
96 break;
97 case PP_FLASH_MENUITEM_TYPE_SEPARATOR:
98 item.type = WebMenuItem::SEPARATOR;
99 break;
100 case PP_FLASH_MENUITEM_TYPE_SUBMENU:
101 item.type = WebMenuItem::SUBMENU;
102 break;
103 default:
104 return false;
105 }
106 if (in_menu->items[i].name)
107 item.label = UTF8ToUTF16(in_menu->items[i].name);
108 if (menu_id_map->size() >= kMaxMenuIdMapEntries)
109 return false;
110 item.action = static_cast<unsigned>(menu_id_map->size());
111 // This sets |(*menu_id_map)[item.action] = in_menu->items[i].id|.
112 menu_id_map->push_back(in_menu->items[i].id);
113 item.enabled = PPBoolToBool(in_menu->items[i].enabled);
114 item.checked = PPBoolToBool(in_menu->items[i].checked);
115 if (type == PP_FLASH_MENUITEM_TYPE_SUBMENU) {
116 if (!ConvertMenuData(in_menu->items[i].submenu, depth + 1, &item.submenu,
117 menu_id_map))
118 return false;
119 }
120
121 out_menu->push_back(item);
122 }
123
124 return true;
125 }
126
127 } // namespace
128
129 PPB_Flash_Menu_Impl::PPB_Flash_Menu_Impl(PluginInstance* instance)
130 : Resource(instance) {
131 }
132
133 bool PPB_Flash_Menu_Impl::Init(const PP_Flash_Menu* menu_data) {
134 menu_id_map_.clear();
135 menu_id_map_.push_back(0); // Reserve |menu_id_map_[0]|.
136 if (!ConvertMenuData(menu_data, 0, &menu_data_, &menu_id_map_)) {
137 menu_id_map_.clear();
138 return false;
139 }
140
141 return true;
142 }
143
144 PPB_Flash_Menu_Impl::~PPB_Flash_Menu_Impl() {
145 }
146
147 // static
148 const PPB_Flash_Menu* PPB_Flash_Menu_Impl::GetInterface() {
149 return &ppb_flash_menu;
150 }
151
152 PPB_Flash_Menu_Impl* PPB_Flash_Menu_Impl::AsPPB_Flash_Menu_Impl() {
153 return this;
154 }
155
156 int32_t PPB_Flash_Menu_Impl::Show(const PP_Point* location,
157 int32_t* selected_id_out,
158 PP_CompletionCallback callback) {
159 // |location| is not (currently) optional.
160 // TODO(viettrungluu): Make it optional and default to the current mouse pos?
161 if (!location)
162 return PP_ERROR_BADARGUMENT;
163
164 if (!callback.func) {
165 NOTIMPLEMENTED();
166 return PP_ERROR_BADARGUMENT;
167 }
168
169 if (callback_.get() && !callback_->completed())
170 return PP_ERROR_INPROGRESS;
171
172 PP_Resource resource_id = GetReferenceNoAddRef();
173 if (!resource_id) {
174 NOTREACHED();
175 return PP_ERROR_FAILED;
176 }
177
178 int32_t rv = instance()->delegate()->ShowContextMenu(
179 this, gfx::Point(instance()->position().x() + location->x,
180 instance()->position().y() + location->y));
181 if (rv == PP_ERROR_WOULDBLOCK) {
182 // Record callback and output buffers.
183 callback_ = new TrackedCompletionCallback(
184 instance()->module()->GetCallbackTracker(), resource_id, callback);
185 selected_id_out_ = selected_id_out;
186 } else {
187 // This should never be completed synchronously successfully.
188 DCHECK_NE(rv, PP_OK);
189 }
190 return rv;
191
192 NOTIMPLEMENTED();
193 return PP_ERROR_FAILED;
194 }
195
196 void PPB_Flash_Menu_Impl::CompleteShow(int32_t result,
197 unsigned action) {
198 int32_t rv = PP_ERROR_ABORTED;
199 if (!callback_->aborted()) {
200 CHECK(!callback_->completed());
201 rv = result;
202
203 // Write output data.
204 if (selected_id_out_ && result == PP_OK) {
205 // We reserved action 0 to be invalid.
206 if (action == 0 || action >= menu_id_map_.size()) {
207 NOTREACHED() << "Invalid action received.";
208 rv = PP_ERROR_FAILED;
209 } else {
210 *selected_id_out_ = menu_id_map_[action];
211 }
212 }
213 }
214
215 scoped_refptr<TrackedCompletionCallback> callback;
216 callback.swap(callback_);
217 selected_id_out_ = NULL;
218
219 callback->Run(rv); // Will complete abortively if necessary.
220 }
221
222 } // namespace ppapi
223 } // namespace webkit
OLDNEW
« 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