Home | History | Annotate | Download | only in proxy
      1 // Copyright (c) 2012 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 "ppapi/proxy/serialized_flash_menu.h"
      6 
      7 #include "ipc/ipc_message.h"
      8 #include "ppapi/c/private/ppb_flash_menu.h"
      9 #include "ppapi/proxy/ppapi_param_traits.h"
     10 
     11 namespace ppapi {
     12 namespace proxy {
     13 
     14 namespace {
     15 // Maximum depth of submenus allowed (e.g., 1 indicates that submenus are
     16 // allowed, but not sub-submenus).
     17 const int kMaxMenuDepth = 2;
     18 const uint32_t kMaxMenuEntries = 1000;
     19 
     20 bool CheckMenu(int depth, const PP_Flash_Menu* menu);
     21 void FreeMenu(const PP_Flash_Menu* menu);
     22 void WriteMenu(IPC::Message* m, const PP_Flash_Menu* menu);
     23 PP_Flash_Menu* ReadMenu(int depth, const IPC::Message* m, PickleIterator* iter);
     24 
     25 bool CheckMenuItem(int depth, const PP_Flash_MenuItem* item) {
     26   if (item->type == PP_FLASH_MENUITEM_TYPE_SUBMENU)
     27     return CheckMenu(depth, item->submenu);
     28   return true;
     29 }
     30 
     31 bool CheckMenu(int depth, const PP_Flash_Menu* menu) {
     32   if (depth > kMaxMenuDepth || !menu)
     33     return false;
     34   ++depth;
     35 
     36   if (menu->count && !menu->items)
     37     return false;
     38 
     39   for (uint32_t i = 0; i < menu->count; ++i) {
     40     if (!CheckMenuItem(depth, menu->items + i))
     41       return false;
     42   }
     43   return true;
     44 }
     45 
     46 void WriteMenuItem(IPC::Message* m, const PP_Flash_MenuItem* menu_item) {
     47   PP_Flash_MenuItem_Type type = menu_item->type;
     48   m->WriteUInt32(type);
     49   m->WriteString(menu_item->name ? menu_item->name : "");
     50   m->WriteInt(menu_item->id);
     51   IPC::ParamTraits<PP_Bool>::Write(m, menu_item->enabled);
     52   IPC::ParamTraits<PP_Bool>::Write(m, menu_item->checked);
     53   if (type == PP_FLASH_MENUITEM_TYPE_SUBMENU)
     54     WriteMenu(m, menu_item->submenu);
     55 }
     56 
     57 void WriteMenu(IPC::Message* m, const PP_Flash_Menu* menu) {
     58   m->WriteUInt32(menu->count);
     59   for (uint32_t i = 0; i < menu->count; ++i)
     60     WriteMenuItem(m, menu->items + i);
     61 }
     62 
     63 void FreeMenuItem(const PP_Flash_MenuItem* menu_item) {
     64   if (menu_item->name)
     65     delete [] menu_item->name;
     66   if (menu_item->submenu)
     67     FreeMenu(menu_item->submenu);
     68 }
     69 
     70 void FreeMenu(const PP_Flash_Menu* menu) {
     71   if (menu->items) {
     72     for (uint32_t i = 0; i < menu->count; ++i)
     73       FreeMenuItem(menu->items + i);
     74     delete [] menu->items;
     75   }
     76   delete menu;
     77 }
     78 
     79 bool ReadMenuItem(int depth,
     80                   const IPC::Message* m,
     81                   PickleIterator* iter,
     82                   PP_Flash_MenuItem* menu_item) {
     83   uint32_t type;
     84   if (!m->ReadUInt32(iter, &type))
     85     return false;
     86   if (type > PP_FLASH_MENUITEM_TYPE_SUBMENU)
     87     return false;
     88   menu_item->type = static_cast<PP_Flash_MenuItem_Type>(type);
     89   std::string name;
     90   if (!m->ReadString(iter, &name))
     91     return false;
     92   menu_item->name = new char[name.size() + 1];
     93   std::copy(name.begin(), name.end(), menu_item->name);
     94   menu_item->name[name.size()] = 0;
     95   if (!m->ReadInt(iter, &menu_item->id))
     96     return false;
     97   if (!IPC::ParamTraits<PP_Bool>::Read(m, iter, &menu_item->enabled))
     98     return false;
     99   if (!IPC::ParamTraits<PP_Bool>::Read(m, iter, &menu_item->checked))
    100     return false;
    101   if (type == PP_FLASH_MENUITEM_TYPE_SUBMENU) {
    102     menu_item->submenu = ReadMenu(depth, m, iter);
    103     if (!menu_item->submenu)
    104       return false;
    105   }
    106   return true;
    107 }
    108 
    109 PP_Flash_Menu* ReadMenu(int depth,
    110                         const IPC::Message* m,
    111                         PickleIterator* iter) {
    112   if (depth > kMaxMenuDepth)
    113     return NULL;
    114   ++depth;
    115 
    116   PP_Flash_Menu* menu = new PP_Flash_Menu;
    117   menu->items = NULL;
    118 
    119   if (!m->ReadUInt32(iter, &menu->count)) {
    120     FreeMenu(menu);
    121     return NULL;
    122   }
    123 
    124   if (menu->count == 0)
    125     return menu;
    126 
    127   if (menu->count > kMaxMenuEntries) {
    128     FreeMenu(menu);
    129     return NULL;
    130   }
    131 
    132   menu->items = new PP_Flash_MenuItem[menu->count];
    133   memset(menu->items, 0, sizeof(PP_Flash_MenuItem) * menu->count);
    134   for (uint32_t i = 0; i < menu->count; ++i) {
    135     if (!ReadMenuItem(depth, m, iter, menu->items + i)) {
    136       FreeMenu(menu);
    137       return NULL;
    138     }
    139   }
    140   return menu;
    141 }
    142 
    143 }  // anonymous namespace
    144 
    145 SerializedFlashMenu::SerializedFlashMenu()
    146     : pp_menu_(NULL),
    147       own_menu_(false) {
    148 }
    149 
    150 SerializedFlashMenu::~SerializedFlashMenu() {
    151   if (own_menu_)
    152     FreeMenu(pp_menu_);
    153 }
    154 
    155 bool SerializedFlashMenu::SetPPMenu(const PP_Flash_Menu* menu) {
    156   DCHECK(!pp_menu_);
    157   if (!CheckMenu(0, menu))
    158     return false;
    159   pp_menu_ = menu;
    160   own_menu_ = false;
    161   return true;
    162 }
    163 
    164 
    165 void SerializedFlashMenu::WriteToMessage(IPC::Message* m) const {
    166   WriteMenu(m, pp_menu_);
    167 }
    168 
    169 bool SerializedFlashMenu::ReadFromMessage(const IPC::Message* m,
    170                                           PickleIterator* iter) {
    171   DCHECK(!pp_menu_);
    172   pp_menu_ = ReadMenu(0, m, iter);
    173   if (!pp_menu_)
    174     return false;
    175 
    176   own_menu_ = true;
    177   return true;
    178 }
    179 
    180 }  // namespace proxy
    181 }  // namespace ppapi
    182