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