Index: ppapi/proxy/serialized_flash_menu.cc |
diff --git a/ppapi/proxy/serialized_flash_menu.cc b/ppapi/proxy/serialized_flash_menu.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c7ef5ab80ca2c07def24f100d8c4878ba2e25f53 |
--- /dev/null |
+++ b/ppapi/proxy/serialized_flash_menu.cc |
@@ -0,0 +1,172 @@ |
+// 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 "ppapi/proxy/serialized_flash_menu.h" |
+ |
+#include "ipc/ipc_message.h" |
+#include "ppapi/c/private/ppb_flash_menu.h" |
+#include "ppapi/proxy/ppapi_param_traits.h" |
+ |
+namespace pp { |
+namespace proxy { |
+ |
+namespace { |
+// Maximum depth of submenus allowed (e.g., 1 indicates that submenus are |
+// allowed, but not sub-submenus). |
+const int kMaxMenuDepth = 2; |
+ |
+bool CheckMenu(int depth, const PP_Flash_Menu* menu); |
+void FreeMenu(const PP_Flash_Menu* menu); |
+void WriteMenu(IPC::Message* m, const PP_Flash_Menu* menu); |
+PP_Flash_Menu* ReadMenu(int depth, const IPC::Message* m, void** iter); |
+ |
+bool CheckMenuItem(int depth, const PP_Flash_MenuItem* item) { |
+ if (item->type == PP_FLASH_MENUITEM_TYPE_SUBMENU) |
+ return CheckMenu(depth, item->submenu); |
+ return true; |
+} |
+ |
+bool CheckMenu(int depth, const PP_Flash_Menu* menu) { |
+ if (depth > kMaxMenuDepth || !menu) |
+ return false; |
+ ++depth; |
+ |
+ if (menu->count && !menu->items) |
+ return false; |
+ |
+ for (uint32_t i = 0; i < menu->count; ++i) { |
+ if (!CheckMenuItem(depth, menu->items + i)) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+void WriteMenuItem(IPC::Message* m, const PP_Flash_MenuItem* menu_item) { |
+ PP_Flash_MenuItem_Type type = menu_item->type; |
+ m->WriteUInt32(type); |
+ m->WriteString(menu_item->name ? menu_item->name : ""); |
+ m->WriteInt(menu_item->id); |
+ IPC::ParamTraits<PP_Bool>::Write(m, menu_item->enabled); |
+ IPC::ParamTraits<PP_Bool>::Write(m, menu_item->checked); |
+ if (type == PP_FLASH_MENUITEM_TYPE_SUBMENU) |
+ WriteMenu(m, menu_item->submenu); |
+} |
+ |
+void WriteMenu(IPC::Message* m, const PP_Flash_Menu* menu) { |
+ m->WriteUInt32(menu->count); |
+ for (uint32_t i = 0; i < menu->count; ++i) |
+ WriteMenuItem(m, menu->items + i); |
+} |
+ |
+void FreeMenuItem(const PP_Flash_MenuItem* menu_item) { |
+ if (menu_item->name) |
+ delete [] menu_item->name; |
+ if (menu_item->submenu) |
+ FreeMenu(menu_item->submenu); |
+} |
+ |
+void FreeMenu(const PP_Flash_Menu* menu) { |
+ if (menu->items) { |
+ for (uint32_t i = 0; i < menu->count; ++i) |
+ FreeMenuItem(menu->items + i); |
+ delete [] menu->items; |
+ } |
+ delete menu; |
+} |
+ |
+bool ReadMenuItem(int depth, |
+ const IPC::Message* m, |
+ void** iter, |
+ PP_Flash_MenuItem* menu_item) { |
+ uint32_t type; |
+ if (!m->ReadUInt32(iter, &type)) |
+ return false; |
+ if (type > PP_FLASH_MENUITEM_TYPE_SUBMENU) |
+ return false; |
+ menu_item->type = static_cast<PP_Flash_MenuItem_Type>(type); |
+ std::string name; |
+ if (!m->ReadString(iter, &name)) |
+ return false; |
+ menu_item->name = new char[name.size() + 1]; |
+ std::copy(name.begin(), name.end(), menu_item->name); |
+ menu_item->name[name.size()] = 0; |
+ if (!m->ReadInt(iter, &menu_item->id)) |
+ return false; |
+ if (!IPC::ParamTraits<PP_Bool>::Read(m, iter, &menu_item->enabled)) |
+ return false; |
+ if (!IPC::ParamTraits<PP_Bool>::Read(m, iter, &menu_item->checked)) |
+ return false; |
+ if (type == PP_FLASH_MENUITEM_TYPE_SUBMENU) { |
+ menu_item->submenu = ReadMenu(depth, m, iter); |
+ if (!menu_item->submenu) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+PP_Flash_Menu* ReadMenu(int depth, const IPC::Message* m, void** iter) { |
+ if (depth > kMaxMenuDepth) |
+ return NULL; |
+ ++depth; |
+ |
+ PP_Flash_Menu* menu = new PP_Flash_Menu; |
+ menu->items = NULL; |
+ |
+ if (!m->ReadUInt32(iter, &menu->count)) { |
+ FreeMenu(menu); |
+ return NULL; |
+ } |
+ |
+ if (menu->count == 0) |
+ return menu; |
+ |
+ menu->items = new PP_Flash_MenuItem[menu->count]; |
+ memset(menu->items, 0, sizeof(PP_Flash_MenuItem) * menu->count); |
+ for (uint32_t i = 0; i < menu->count; ++i) { |
+ if (!ReadMenuItem(depth, m, iter, menu->items + i)) { |
+ FreeMenu(menu); |
+ return NULL; |
+ } |
+ } |
+ return menu; |
+} |
+ |
+} // anonymous namespace |
+ |
+SerializedFlashMenu::SerializedFlashMenu() |
+ : pp_menu_(NULL), |
+ own_menu_(false) { |
+} |
+ |
+SerializedFlashMenu::~SerializedFlashMenu() { |
+ if (own_menu_) |
+ FreeMenu(pp_menu_); |
+} |
+ |
+bool SerializedFlashMenu::SetPPMenu(const PP_Flash_Menu* menu) { |
+ DCHECK(!pp_menu_); |
+ if (!CheckMenu(0, menu)) |
+ return false; |
+ pp_menu_ = menu; |
+ own_menu_ = false; |
+ return true; |
+} |
+ |
+ |
+void SerializedFlashMenu::WriteToMessage(IPC::Message* m) const { |
+ WriteMenu(m, pp_menu_); |
+} |
+ |
+bool SerializedFlashMenu::ReadFromMessage(const IPC::Message* m, void** iter) { |
+ DCHECK(!pp_menu_); |
+ pp_menu_ = ReadMenu(0, m, iter); |
+ if (!pp_menu_) |
+ return false; |
+ |
+ own_menu_ = true; |
+ return true; |
+} |
+ |
+} // namespace proxy |
+} // namespace pp |