OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/proxy/interface_list.h" | 5 #include "ppapi/proxy/interface_list.h" |
6 | 6 |
| 7 #include "base/lazy_instance.h" |
7 #include "base/memory/singleton.h" | 8 #include "base/memory/singleton.h" |
8 #include "ppapi/c/dev/ppb_audio_input_dev.h" | 9 #include "ppapi/c/dev/ppb_audio_input_dev.h" |
9 #include "ppapi/c/dev/ppb_buffer_dev.h" | 10 #include "ppapi/c/dev/ppb_buffer_dev.h" |
10 #include "ppapi/c/dev/ppb_char_set_dev.h" | 11 #include "ppapi/c/dev/ppb_char_set_dev.h" |
11 #include "ppapi/c/dev/ppb_console_dev.h" | 12 #include "ppapi/c/dev/ppb_console_dev.h" |
12 #include "ppapi/c/dev/ppb_crypto_dev.h" | 13 #include "ppapi/c/dev/ppb_crypto_dev.h" |
13 #include "ppapi/c/dev/ppb_cursor_control_dev.h" | 14 #include "ppapi/c/dev/ppb_cursor_control_dev.h" |
14 #include "ppapi/c/dev/ppb_device_ref_dev.h" | 15 #include "ppapi/c/dev/ppb_device_ref_dev.h" |
15 #include "ppapi/c/dev/ppb_font_dev.h" | 16 #include "ppapi/c/dev/ppb_font_dev.h" |
16 #include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h" | 17 #include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h" |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 class NoAPIName_Proxy { | 151 class NoAPIName_Proxy { |
151 public: | 152 public: |
152 static const ApiID kApiID = API_ID_NONE; | 153 static const ApiID kApiID = API_ID_NONE; |
153 }; | 154 }; |
154 | 155 |
155 template<typename ProxyClass> | 156 template<typename ProxyClass> |
156 InterfaceProxy* ProxyFactory(Dispatcher* dispatcher) { | 157 InterfaceProxy* ProxyFactory(Dispatcher* dispatcher) { |
157 return new ProxyClass(dispatcher); | 158 return new ProxyClass(dispatcher); |
158 } | 159 } |
159 | 160 |
| 161 base::LazyInstance<PpapiPermissions> g_process_global_permissions; |
| 162 |
160 } // namespace | 163 } // namespace |
161 | 164 |
162 InterfaceList::InterfaceList() { | 165 InterfaceList::InterfaceList() { |
163 memset(id_to_factory_, 0, sizeof(id_to_factory_)); | 166 memset(id_to_factory_, 0, sizeof(id_to_factory_)); |
164 | 167 |
165 // Register the API factories for each of the API types. This calls AddProxy | 168 // Register the API factories for each of the API types. This calls AddProxy |
166 // for each InterfaceProxy type we support. | 169 // for each InterfaceProxy type we support. |
167 #define PROXIED_API(api_name) \ | 170 #define PROXIED_API(api_name) \ |
168 AddProxy(PROXY_API_ID(api_name), &PROXY_FACTORY_NAME(api_name)); | 171 AddProxy(PROXY_API_ID(api_name), &PROXY_FACTORY_NAME(api_name)); |
169 | 172 |
170 // Register each proxied interface by calling AddPPB for each supported | 173 // Register each proxied interface by calling AddPPB for each supported |
171 // interface. | 174 // interface. Set current_required_permission to the appropriate value for |
| 175 // the value you want expanded by this macro. |
172 #define PROXIED_IFACE(api_name, iface_str, iface_struct) \ | 176 #define PROXIED_IFACE(api_name, iface_str, iface_struct) \ |
173 AddPPB(iface_str, PROXY_API_ID(api_name), \ | 177 AddPPB(iface_str, PROXY_API_ID(api_name), \ |
174 INTERFACE_THUNK_NAME(iface_struct)()); | 178 INTERFACE_THUNK_NAME(iface_struct)(), \ |
| 179 current_required_permission); |
175 | 180 |
176 #include "ppapi/thunk/interfaces_ppb_public_stable.h" | 181 { |
| 182 Permission current_required_permission = PERMISSION_NONE; |
| 183 #include "ppapi/thunk/interfaces_ppb_public_stable.h" |
| 184 } |
| 185 |
177 #if !defined(OS_NACL) | 186 #if !defined(OS_NACL) |
178 #include "ppapi/thunk/interfaces_ppb_public_dev.h" | 187 { |
179 #include "ppapi/thunk/interfaces_ppb_private.h" | 188 Permission current_required_permission = PERMISSION_DEV; |
| 189 #include "ppapi/thunk/interfaces_ppb_public_dev.h" |
| 190 } |
| 191 { |
| 192 Permission current_required_permission = PERMISSION_PRIVATE; |
| 193 #include "ppapi/thunk/interfaces_ppb_private.h" |
| 194 } |
180 #endif | 195 #endif |
181 | 196 |
182 #if !defined(OS_NACL) | 197 #if !defined(OS_NACL) |
183 #include "ppapi/thunk/interfaces_ppb_private_flash.h" | 198 { |
| 199 Permission current_required_permission = PERMISSION_FLASH; |
| 200 #include "ppapi/thunk/interfaces_ppb_private_flash.h" |
| 201 } |
184 #endif | 202 #endif |
185 | 203 |
186 #undef PROXIED_API | 204 #undef PROXIED_API |
187 #undef PROXIED_IFACE | 205 #undef PROXIED_IFACE |
188 | 206 |
189 // Manually add some special proxies. Some of these don't have interfaces | 207 // Manually add some special proxies. Some of these don't have interfaces |
190 // that they support, so aren't covered by the macros above, but have proxies | 208 // that they support, so aren't covered by the macros above, but have proxies |
191 // for message routing. Others have different implementations between the | 209 // for message routing. Others have different implementations between the |
192 // proxy and the impl and there's no obvious message routing. | 210 // proxy and the impl and there's no obvious message routing. |
193 AddProxy(API_ID_RESOURCE_CREATION, &ResourceCreationProxy::Create); | 211 AddProxy(API_ID_RESOURCE_CREATION, &ResourceCreationProxy::Create); |
194 AddProxy(API_ID_PPP_CLASS, &PPP_Class_Proxy::Create); | 212 AddProxy(API_ID_PPP_CLASS, &PPP_Class_Proxy::Create); |
195 AddPPB(PPB_CORE_INTERFACE_1_0, API_ID_PPB_CORE, | 213 AddPPB(PPB_CORE_INTERFACE_1_0, API_ID_PPB_CORE, |
196 PPB_Core_Proxy::GetPPB_Core_Interface()); | 214 PPB_Core_Proxy::GetPPB_Core_Interface(), PERMISSION_NONE); |
197 AddPPB(PPB_MESSAGELOOP_DEV_INTERFACE_0_1, API_ID_NONE, | 215 AddPPB(PPB_MESSAGELOOP_DEV_INTERFACE_0_1, API_ID_NONE, |
198 PPB_MessageLoop_Proxy::GetInterface()); | 216 PPB_MessageLoop_Proxy::GetInterface(), PERMISSION_DEV); |
199 AddPPB(PPB_OPENGLES2_INTERFACE_1_0, API_ID_NONE, | 217 AddPPB(PPB_OPENGLES2_INTERFACE_1_0, API_ID_NONE, |
200 PPB_OpenGLES2_Shared::GetInterface()); | 218 PPB_OpenGLES2_Shared::GetInterface(), PERMISSION_NONE); |
201 AddPPB(PPB_OPENGLES2_INSTANCEDARRAYS_INTERFACE_1_0, API_ID_NONE, | 219 AddPPB(PPB_OPENGLES2_INSTANCEDARRAYS_INTERFACE_1_0, API_ID_NONE, |
202 PPB_OpenGLES2_Shared::GetInstancedArraysInterface()); | 220 PPB_OpenGLES2_Shared::GetInstancedArraysInterface(), PERMISSION_NONE); |
203 AddPPB(PPB_OPENGLES2_FRAMEBUFFERBLIT_INTERFACE_1_0, API_ID_NONE, | 221 AddPPB(PPB_OPENGLES2_FRAMEBUFFERBLIT_INTERFACE_1_0, API_ID_NONE, |
204 PPB_OpenGLES2_Shared::GetFramebufferBlitInterface()); | 222 PPB_OpenGLES2_Shared::GetFramebufferBlitInterface(), PERMISSION_NONE); |
205 AddPPB(PPB_OPENGLES2_FRAMEBUFFERMULTISAMPLE_INTERFACE_1_0, API_ID_NONE, | 223 AddPPB(PPB_OPENGLES2_FRAMEBUFFERMULTISAMPLE_INTERFACE_1_0, API_ID_NONE, |
206 PPB_OpenGLES2_Shared::GetFramebufferMultisampleInterface()); | 224 PPB_OpenGLES2_Shared::GetFramebufferMultisampleInterface(), |
| 225 PERMISSION_NONE); |
207 AddPPB(PPB_OPENGLES2_CHROMIUMENABLEFEATURE_INTERFACE_1_0, API_ID_NONE, | 226 AddPPB(PPB_OPENGLES2_CHROMIUMENABLEFEATURE_INTERFACE_1_0, API_ID_NONE, |
208 PPB_OpenGLES2_Shared::GetChromiumEnableFeatureInterface()); | 227 PPB_OpenGLES2_Shared::GetChromiumEnableFeatureInterface(), |
| 228 PERMISSION_NONE); |
209 AddPPB(PPB_OPENGLES2_CHROMIUMMAPSUB_INTERFACE_1_0, API_ID_NONE, | 229 AddPPB(PPB_OPENGLES2_CHROMIUMMAPSUB_INTERFACE_1_0, API_ID_NONE, |
210 PPB_OpenGLES2_Shared::GetChromiumMapSubInterface()); | 230 PPB_OpenGLES2_Shared::GetChromiumMapSubInterface(), PERMISSION_NONE); |
211 AddPPB(PPB_OPENGLES2_CHROMIUMMAPSUB_DEV_INTERFACE_1_0, API_ID_NONE, | 231 AddPPB(PPB_OPENGLES2_CHROMIUMMAPSUB_DEV_INTERFACE_1_0, API_ID_NONE, |
212 PPB_OpenGLES2_Shared::GetChromiumMapSubInterface()); | 232 PPB_OpenGLES2_Shared::GetChromiumMapSubInterface(), PERMISSION_NONE); |
213 AddPPB(PPB_OPENGLES2_QUERY_INTERFACE_1_0, API_ID_NONE, | 233 AddPPB(PPB_OPENGLES2_QUERY_INTERFACE_1_0, API_ID_NONE, |
214 PPB_OpenGLES2_Shared::GetQueryInterface()); | 234 PPB_OpenGLES2_Shared::GetQueryInterface(), PERMISSION_NONE); |
215 #if !defined(OS_NACL) | 235 #if !defined(OS_NACL) |
216 AddPPB(PPB_FLASH_PRINT_INTERFACE_1_0, API_ID_PPB_FLASH, | 236 AddPPB(PPB_FLASH_PRINT_INTERFACE_1_0, API_ID_PPB_FLASH, |
217 PPB_Flash_Proxy::GetFlashPrintInterface()); | 237 PPB_Flash_Proxy::GetFlashPrintInterface(), |
| 238 PERMISSION_FLASH); |
218 #endif | 239 #endif |
219 AddPPB(PPB_VAR_ARRAY_BUFFER_INTERFACE_1_0, API_ID_NONE, | 240 AddPPB(PPB_VAR_ARRAY_BUFFER_INTERFACE_1_0, API_ID_NONE, |
220 PPB_Var_Shared::GetVarArrayBufferInterface1_0()); | 241 PPB_Var_Shared::GetVarArrayBufferInterface1_0(), |
| 242 PERMISSION_DEV); |
221 AddPPB(PPB_VAR_INTERFACE_1_1, API_ID_NONE, | 243 AddPPB(PPB_VAR_INTERFACE_1_1, API_ID_NONE, |
222 PPB_Var_Shared::GetVarInterface1_1()); | 244 PPB_Var_Shared::GetVarInterface1_1(), PERMISSION_NONE); |
223 AddPPB(PPB_VAR_INTERFACE_1_0, API_ID_NONE, | 245 AddPPB(PPB_VAR_INTERFACE_1_0, API_ID_NONE, |
224 PPB_Var_Shared::GetVarInterface1_0()); | 246 PPB_Var_Shared::GetVarInterface1_0(), PERMISSION_NONE); |
225 | 247 |
226 #if !defined(OS_NACL) | 248 #if !defined(OS_NACL) |
227 // PPB (browser) interfaces. | 249 // PPB (browser) interfaces. |
228 // Do not add more stuff here, they should be added to interface_list*.h | 250 // Do not add more stuff here, they should be added to interface_list*.h |
229 // TODO(brettw) remove these. | 251 // TODO(brettw) remove these. |
230 AddPPB(PPB_Instance_Proxy::GetInfoPrivate()); | 252 AddPPB(PPB_Instance_Proxy::GetInfoPrivate(), PERMISSION_PRIVATE); |
231 AddPPB(PPB_PDF_Proxy::GetInfo()); | 253 AddPPB(PPB_PDF_Proxy::GetInfo(), PERMISSION_PRIVATE); |
232 AddPPB(PPB_URLLoader_Proxy::GetTrustedInfo()); | 254 AddPPB(PPB_URLLoader_Proxy::GetTrustedInfo(), PERMISSION_PRIVATE); |
233 AddPPB(PPB_Var_Deprecated_Proxy::GetInfo()); | 255 AddPPB(PPB_Var_Deprecated_Proxy::GetInfo(), PERMISSION_DEV); |
234 | 256 |
235 // TODO(tomfinegan): Figure out where to put these once we refactor things | 257 // TODO(tomfinegan): Figure out where to put these once we refactor things |
236 // to load the PPP interface struct from the PPB interface. | 258 // to load the PPP interface struct from the PPB interface. |
237 AddProxy(API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE, | 259 AddProxy(API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE, |
238 &ProxyFactory<PPP_ContentDecryptor_Private_Proxy>); | 260 &ProxyFactory<PPP_ContentDecryptor_Private_Proxy>); |
239 AddPPP(PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE, | 261 AddPPP(PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE, |
240 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE, | 262 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE, |
241 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface()); | 263 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface()); |
242 #endif | 264 #endif |
243 AddPPB(PPB_Testing_Proxy::GetInfo()); | 265 AddPPB(PPB_Testing_Proxy::GetInfo(), PERMISSION_TESTING); |
244 | 266 |
245 // PPP (plugin) interfaces. | 267 // PPP (plugin) interfaces. |
246 // TODO(brettw) move these to interface_list*.h | 268 // TODO(brettw) move these to interface_list*.h |
247 AddProxy(API_ID_PPP_INSTANCE, &ProxyFactory<PPP_Instance_Proxy>); | 269 AddProxy(API_ID_PPP_INSTANCE, &ProxyFactory<PPP_Instance_Proxy>); |
248 AddPPP(PPP_INSTANCE_INTERFACE_1_1, API_ID_PPP_INSTANCE, | 270 AddPPP(PPP_INSTANCE_INTERFACE_1_1, API_ID_PPP_INSTANCE, |
249 PPP_Instance_Proxy::GetInstanceInterface()); | 271 PPP_Instance_Proxy::GetInstanceInterface()); |
250 AddProxy(API_ID_PPP_PRINTING, &ProxyFactory<PPP_Printing_Proxy>); | 272 AddProxy(API_ID_PPP_PRINTING, &ProxyFactory<PPP_Printing_Proxy>); |
251 AddPPP(PPP_PRINTING_DEV_INTERFACE, API_ID_PPP_PRINTING, | 273 AddPPP(PPP_PRINTING_DEV_INTERFACE, API_ID_PPP_PRINTING, |
252 PPP_Printing_Proxy::GetProxyInterface()); | 274 PPP_Printing_Proxy::GetProxyInterface()); |
253 AddProxy(API_ID_PPP_TEXT_INPUT, &ProxyFactory<PPP_TextInput_Proxy>); | 275 AddProxy(API_ID_PPP_TEXT_INPUT, &ProxyFactory<PPP_TextInput_Proxy>); |
(...skipping 15 matching lines...) Expand all Loading... |
269 } | 291 } |
270 | 292 |
271 InterfaceList::~InterfaceList() { | 293 InterfaceList::~InterfaceList() { |
272 } | 294 } |
273 | 295 |
274 // static | 296 // static |
275 InterfaceList* InterfaceList::GetInstance() { | 297 InterfaceList* InterfaceList::GetInstance() { |
276 return Singleton<InterfaceList>::get(); | 298 return Singleton<InterfaceList>::get(); |
277 } | 299 } |
278 | 300 |
| 301 // static |
| 302 void InterfaceList::SetProcessGlobalPermissions( |
| 303 const PpapiPermissions& permissions) { |
| 304 g_process_global_permissions.Get() = permissions; |
| 305 } |
| 306 |
279 ApiID InterfaceList::GetIDForPPBInterface(const std::string& name) const { | 307 ApiID InterfaceList::GetIDForPPBInterface(const std::string& name) const { |
280 NameToInterfaceInfoMap::const_iterator found = | 308 NameToInterfaceInfoMap::const_iterator found = |
281 name_to_browser_info_.find(name); | 309 name_to_browser_info_.find(name); |
282 if (found == name_to_browser_info_.end()) | 310 if (found == name_to_browser_info_.end()) |
283 return API_ID_NONE; | 311 return API_ID_NONE; |
284 return found->second.id; | 312 return found->second.id; |
285 } | 313 } |
286 | 314 |
287 ApiID InterfaceList::GetIDForPPPInterface(const std::string& name) const { | 315 ApiID InterfaceList::GetIDForPPPInterface(const std::string& name) const { |
288 NameToInterfaceInfoMap::const_iterator found = | 316 NameToInterfaceInfoMap::const_iterator found = |
289 name_to_plugin_info_.find(name); | 317 name_to_plugin_info_.find(name); |
290 if (found == name_to_plugin_info_.end()) | 318 if (found == name_to_plugin_info_.end()) |
291 return API_ID_NONE; | 319 return API_ID_NONE; |
292 return found->second.id; | 320 return found->second.id; |
293 } | 321 } |
294 | 322 |
295 InterfaceProxy::Factory InterfaceList::GetFactoryForID(ApiID id) const { | 323 InterfaceProxy::Factory InterfaceList::GetFactoryForID(ApiID id) const { |
296 int index = static_cast<int>(id); | 324 int index = static_cast<int>(id); |
297 COMPILE_ASSERT(API_ID_NONE == 0, none_must_be_zero); | 325 COMPILE_ASSERT(API_ID_NONE == 0, none_must_be_zero); |
298 if (id <= 0 || id >= API_ID_COUNT) | 326 if (id <= 0 || id >= API_ID_COUNT) |
299 return NULL; | 327 return NULL; |
300 return id_to_factory_[index]; | 328 return id_to_factory_[index]; |
301 } | 329 } |
302 | 330 |
303 const void* InterfaceList::GetInterfaceForPPB(const std::string& name) const { | 331 const void* InterfaceList::GetInterfaceForPPB(const std::string& name) const { |
304 NameToInterfaceInfoMap::const_iterator found = | 332 NameToInterfaceInfoMap::const_iterator found = |
305 name_to_browser_info_.find(name); | 333 name_to_browser_info_.find(name); |
306 if (found == name_to_browser_info_.end()) | 334 if (found == name_to_browser_info_.end()) |
307 return NULL; | 335 return NULL; |
308 return found->second.iface; | 336 |
| 337 if (g_process_global_permissions.Get().HasPermission( |
| 338 found->second.required_permission)) |
| 339 return found->second.iface; |
| 340 return NULL; |
309 } | 341 } |
310 | 342 |
311 const void* InterfaceList::GetInterfaceForPPP(const std::string& name) const { | 343 const void* InterfaceList::GetInterfaceForPPP(const std::string& name) const { |
312 NameToInterfaceInfoMap::const_iterator found = | 344 NameToInterfaceInfoMap::const_iterator found = |
313 name_to_plugin_info_.find(name); | 345 name_to_plugin_info_.find(name); |
314 if (found == name_to_plugin_info_.end()) | 346 if (found == name_to_plugin_info_.end()) |
315 return NULL; | 347 return NULL; |
316 return found->second.iface; | 348 return found->second.iface; |
317 } | 349 } |
318 | 350 |
319 void InterfaceList::AddProxy(ApiID id, | 351 void InterfaceList::AddProxy(ApiID id, |
320 InterfaceProxy::Factory factory) { | 352 InterfaceProxy::Factory factory) { |
321 // For interfaces with no corresponding _Proxy objects, the macros will | 353 // For interfaces with no corresponding _Proxy objects, the macros will |
322 // generate calls to this function with API_ID_NONE. This means we | 354 // generate calls to this function with API_ID_NONE. This means we |
323 // should just skip adding a factory for these functions. | 355 // should just skip adding a factory for these functions. |
324 if (id == API_ID_NONE) | 356 if (id == API_ID_NONE) |
325 return; | 357 return; |
326 | 358 |
327 // The factory should be an exact dupe of the one we already have if it | 359 // The factory should be an exact dupe of the one we already have if it |
328 // has already been registered before. | 360 // has already been registered before. |
329 int index = static_cast<int>(id); | 361 int index = static_cast<int>(id); |
330 DCHECK(!id_to_factory_[index] || id_to_factory_[index] == factory); | 362 DCHECK(!id_to_factory_[index] || id_to_factory_[index] == factory); |
331 | 363 |
332 id_to_factory_[index] = factory; | 364 id_to_factory_[index] = factory; |
333 } | 365 } |
334 | 366 |
335 void InterfaceList::AddPPB(const char* name, | 367 void InterfaceList::AddPPB(const char* name, |
336 ApiID id, | 368 ApiID id, |
337 const void* iface) { | 369 const void* iface, |
| 370 Permission perm) { |
338 DCHECK(name_to_browser_info_.find(name) == name_to_browser_info_.end()); | 371 DCHECK(name_to_browser_info_.find(name) == name_to_browser_info_.end()); |
339 name_to_browser_info_[name] = InterfaceInfo(id, iface); | 372 name_to_browser_info_[name] = InterfaceInfo(id, iface, perm); |
340 } | 373 } |
341 | 374 |
342 void InterfaceList::AddPPP(const char* name, | 375 void InterfaceList::AddPPP(const char* name, |
343 ApiID id, | 376 ApiID id, |
344 const void* iface) { | 377 const void* iface) { |
345 DCHECK(name_to_plugin_info_.find(name) == name_to_plugin_info_.end()); | 378 DCHECK(name_to_plugin_info_.find(name) == name_to_plugin_info_.end()); |
346 name_to_plugin_info_[name] = InterfaceInfo(id, iface); | 379 name_to_plugin_info_[name] = InterfaceInfo(id, iface, PERMISSION_NONE); |
347 } | 380 } |
348 | 381 |
349 void InterfaceList::AddPPB(const InterfaceProxy::Info* info) { | 382 void InterfaceList::AddPPB(const InterfaceProxy::Info* info, Permission perm) { |
350 AddProxy(info->id, info->create_proxy); | 383 AddProxy(info->id, info->create_proxy); |
351 AddPPB(info->name, info->id, info->interface_ptr); | 384 AddPPB(info->name, info->id, info->interface_ptr, perm); |
352 } | 385 } |
353 | 386 |
354 void InterfaceList::AddPPP(const InterfaceProxy::Info* info) { | 387 void InterfaceList::AddPPP(const InterfaceProxy::Info* info) { |
355 AddProxy(info->id, info->create_proxy); | 388 AddProxy(info->id, info->create_proxy); |
356 AddPPP(info->name, info->id, info->interface_ptr); | 389 AddPPP(info->name, info->id, info->interface_ptr); |
357 } | 390 } |
358 | 391 |
359 } // namespace proxy | 392 } // namespace proxy |
360 } // namespace ppapi | 393 } // namespace ppapi |
OLD | NEW |