Chromium Code Reviews| 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..3622759461d2487c1c35630aed7c94d03df908d9 | 
| --- /dev/null | 
| +++ b/ppapi/proxy/serialized_flash_menu.cc | 
| @@ -0,0 +1,168 @@ | 
| +// 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(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); | 
| + | 
| 
 
viettrungluu
2011/02/08 18:18:09
Extra blank line.
 
piman
2011/02/15 02:11:22
Done.
 
 | 
| + | 
| +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) | 
| 
 
viettrungluu
2011/02/08 18:18:09
I wonder if we should handle |menu| (or |item->sub
 
piman
2011/02/15 02:11:22
Done. I made it to fail. Note that I changed the n
 
 | 
| + return false; | 
| + ++depth; | 
| + | 
| + 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(PP_Flash_MenuItem* menu_item) { | 
| + if (menu_item->name) | 
| + delete [] menu_item->name; | 
| + if (menu_item->submenu) | 
| + FreeMenu(menu_item->submenu); | 
| + delete menu_item; | 
| +} | 
| + | 
| +void FreeMenu(PP_Flash_Menu* menu) { | 
| + if (menu->items) { | 
| + for (uint32_t i = 0; i < menu->count; ++i) | 
| + FreeMenuItem(menu->items + i); | 
| + } | 
| + delete menu; | 
| +} | 
| + | 
| +class MenuDeallocator { | 
| + public: | 
| + void operator()(PP_Flash_Menu* menu) const { | 
| + if (menu) | 
| + FreeMenu(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; | 
| + | 
| + scoped_ptr_malloc<PP_Flash_Menu, MenuDeallocator> menu(new PP_Flash_Menu); | 
| 
 
viettrungluu
2011/02/08 18:18:09
This seems heavyweight and slightly hazardous (sin
 
piman
2011/02/15 02:11:22
Done.
 
 | 
| + menu->items = NULL; | 
| + | 
| + if (!m->ReadUInt32(iter, &menu->count)) | 
| + return NULL; | 
| + | 
| + if (menu->count == 0) | 
| + return menu.release(); | 
| + | 
| + 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)) | 
| + return NULL; | 
| + } | 
| + return menu.release(); | 
| +} | 
| + | 
| +} // anonymous namespace | 
| + | 
| +SerializedFlashMenu::SerializedFlashMenu() | 
| + : pp_menu_(NULL), | 
| + own_menu_(false) { | 
| +} | 
| + | 
| +SerializedFlashMenu::~SerializedFlashMenu() { | 
| +} | 
| 
 
viettrungluu
2011/02/08 18:18:09
Shouldn't you be checking |own_menu_| and possibly
 
piman
2011/02/15 02:11:22
Done.
 
 | 
| + | 
| +bool SerializedFlashMenu::SetPPMenu(const PP_Flash_Menu* menu) { | 
| + DCHECK(!pp_menu_); | 
| + if (!CheckMenu(0, menu)) | 
| + return false; | 
| + pp_menu_ = menu; | 
| + return true; | 
| 
 
viettrungluu
2011/02/08 18:18:09
What about |own_menu_|? (I guess since |pp_menu_|
 
piman
2011/02/15 02:11:22
Done. I changed it to be explicit.
 
 | 
| +} | 
| + | 
| + | 
| +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); | 
| + own_menu_ = true; | 
| + return !!pp_menu_; | 
| +} | 
| + | 
| +} // namespace proxy | 
| +} // namespace pp |