content_browser_pepper_host_factory.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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 "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
6
7#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
8#include "content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.h"
9#include "content/browser/renderer_host/pepper/pepper_file_ref_host.h"
10#include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
11#include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h"
12#include "content/browser/renderer_host/pepper/pepper_gamepad_host.h"
13#include "content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h"
14#include "content/browser/renderer_host/pepper/pepper_network_monitor_host.h"
15#include "content/browser/renderer_host/pepper/pepper_network_proxy_host.h"
16#include "content/browser/renderer_host/pepper/pepper_print_settings_manager.h"
17#include "content/browser/renderer_host/pepper/pepper_printing_host.h"
18#include "content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h"
19#include "content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h"
20#include "content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h"
21#include "content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h"
22#include "ppapi/host/message_filter_host.h"
23#include "ppapi/host/ppapi_host.h"
24#include "ppapi/host/resource_host.h"
25#include "ppapi/proxy/ppapi_messages.h"
26#include "ppapi/shared_impl/ppapi_permissions.h"
27
28using ppapi::host::MessageFilterHost;
29using ppapi::host::ResourceHost;
30using ppapi::host::ResourceMessageFilter;
31using ppapi::UnpackMessage;
32
33namespace content {
34
35namespace {
36
37const size_t kMaxSocketsAllowed = 1024;
38
39bool CanCreateSocket() {
40  return
41      PepperTCPServerSocketMessageFilter::GetNumInstances() +
42      PepperTCPSocketMessageFilter::GetNumInstances() +
43      PepperUDPSocketMessageFilter::GetNumInstances() <
44      kMaxSocketsAllowed;
45}
46
47}  // namespace
48
49ContentBrowserPepperHostFactory::ContentBrowserPepperHostFactory(
50    BrowserPpapiHostImpl* host)
51    : host_(host) {
52}
53
54ContentBrowserPepperHostFactory::~ContentBrowserPepperHostFactory() {
55}
56
57scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
58    ppapi::host::PpapiHost* host,
59    const ppapi::proxy::ResourceMessageCallParams& params,
60    PP_Instance instance,
61    const IPC::Message& message) {
62  DCHECK(host == host_->GetPpapiHost());
63
64  // Make sure the plugin is giving us a valid instance for this resource.
65  if (!host_->IsValidInstance(instance))
66    return scoped_ptr<ResourceHost>();
67
68  // Public interfaces.
69  switch (message.type()) {
70    case PpapiHostMsg_FileSystem_Create::ID: {
71      PP_FileSystemType file_system_type;
72      if (!ppapi::UnpackMessage<PpapiHostMsg_FileSystem_Create>(message,
73          &file_system_type)) {
74        NOTREACHED();
75        return scoped_ptr<ResourceHost>();
76      }
77      return scoped_ptr<ResourceHost>(new PepperFileSystemBrowserHost(
78          host_, instance, params.pp_resource(), file_system_type));
79    }
80    case PpapiHostMsg_Gamepad_Create::ID: {
81      return scoped_ptr<ResourceHost>(new PepperGamepadHost(
82          host_, instance, params.pp_resource()));
83    }
84    case PpapiHostMsg_NetworkProxy_Create::ID: {
85      return scoped_ptr<ResourceHost>(new PepperNetworkProxyHost(
86          host_, instance, params.pp_resource()));
87    }
88    case PpapiHostMsg_HostResolver_Create::ID: {
89      scoped_refptr<ResourceMessageFilter> host_resolver(
90          new PepperHostResolverMessageFilter(host_, instance, false));
91      return scoped_ptr<ResourceHost>(new MessageFilterHost(
92          host_->GetPpapiHost(), instance, params.pp_resource(),
93          host_resolver));
94    }
95    case PpapiHostMsg_FileRef_CreateInternal::ID: {
96      PP_Resource file_system;
97      std::string internal_path;
98      if (!UnpackMessage<PpapiHostMsg_FileRef_CreateInternal>(
99          message, &file_system, &internal_path)) {
100        NOTREACHED();
101        return scoped_ptr<ResourceHost>();
102      }
103      return scoped_ptr<ResourceHost>(new PepperFileRefHost(
104          host_, instance, params.pp_resource(), file_system, internal_path));
105    }
106    case PpapiHostMsg_TCPSocket_Create::ID: {
107      ppapi::TCPSocketVersion version;
108      if (!UnpackMessage<PpapiHostMsg_TCPSocket_Create>(message, &version) ||
109          version == ppapi::TCP_SOCKET_VERSION_PRIVATE) {
110        return scoped_ptr<ResourceHost>();
111      }
112
113      return CreateNewTCPSocket(instance, params.pp_resource(), version);
114    }
115    case PpapiHostMsg_UDPSocket_Create::ID: {
116      if (CanCreateSocket()) {
117        scoped_refptr<ResourceMessageFilter> udp_socket(
118            new PepperUDPSocketMessageFilter(host_, instance, false));
119        return scoped_ptr<ResourceHost>(new MessageFilterHost(
120            host_->GetPpapiHost(), instance, params.pp_resource(), udp_socket));
121      } else {
122        return scoped_ptr<ResourceHost>();
123      }
124    }
125  }
126
127  // Dev interfaces.
128  if (GetPermissions().HasPermission(ppapi::PERMISSION_DEV)) {
129    switch (message.type()) {
130      case PpapiHostMsg_Printing_Create::ID: {
131        scoped_ptr<PepperPrintSettingsManager> manager(
132            new PepperPrintSettingsManagerImpl());
133        return scoped_ptr<ResourceHost>(new PepperPrintingHost(
134            host_->GetPpapiHost(), instance,
135            params.pp_resource(), manager.Pass()));
136      }
137      case PpapiHostMsg_TrueTypeFontSingleton_Create::ID: {
138        return scoped_ptr<ResourceHost>(new PepperTrueTypeFontListHost(
139            host_, instance, params.pp_resource()));
140      }
141    }
142  }
143
144  // Private interfaces.
145  if (GetPermissions().HasPermission(ppapi::PERMISSION_PRIVATE)) {
146    switch (message.type()) {
147      case PpapiHostMsg_BrowserFontSingleton_Create::ID:
148        return scoped_ptr<ResourceHost>(new PepperBrowserFontSingletonHost(
149            host_, instance, params.pp_resource()));
150    }
151  }
152
153  // Permissions for the following interfaces will be checked at the
154  // time of the corresponding instance's methods calls (because
155  // permission check can be performed only on the UI
156  // thread). Currently these interfaces are available only for
157  // whitelisted apps which may not have access to the other private
158  // interfaces.
159  if (message.type() == PpapiHostMsg_HostResolver_CreatePrivate::ID) {
160    scoped_refptr<ResourceMessageFilter> host_resolver(
161        new PepperHostResolverMessageFilter(host_, instance, true));
162    return scoped_ptr<ResourceHost>(new MessageFilterHost(
163        host_->GetPpapiHost(), instance, params.pp_resource(), host_resolver));
164  }
165  if (message.type() == PpapiHostMsg_TCPServerSocket_CreatePrivate::ID) {
166    if (CanCreateSocket()) {
167      scoped_refptr<ResourceMessageFilter> tcp_server_socket(
168          new PepperTCPServerSocketMessageFilter(this, host_, instance, true));
169      return scoped_ptr<ResourceHost>(new MessageFilterHost(
170          host_->GetPpapiHost(), instance, params.pp_resource(),
171          tcp_server_socket));
172    } else {
173      return scoped_ptr<ResourceHost>();
174    }
175  }
176  if (message.type() == PpapiHostMsg_TCPSocket_CreatePrivate::ID) {
177    return CreateNewTCPSocket(instance, params.pp_resource(),
178                              ppapi::TCP_SOCKET_VERSION_PRIVATE);
179  }
180  if (message.type() == PpapiHostMsg_UDPSocket_CreatePrivate::ID) {
181    if (CanCreateSocket()) {
182      scoped_refptr<ResourceMessageFilter> udp_socket(
183          new PepperUDPSocketMessageFilter(host_, instance, true));
184      return scoped_ptr<ResourceHost>(new MessageFilterHost(
185          host_->GetPpapiHost(), instance, params.pp_resource(), udp_socket));
186    } else {
187      return scoped_ptr<ResourceHost>();
188    }
189  }
190  if (message.type() == PpapiHostMsg_NetworkMonitor_Create::ID) {
191    return scoped_ptr<ResourceHost>(
192        new PepperNetworkMonitorHost(host_, instance, params.pp_resource()));
193  }
194
195  // Flash interfaces.
196  if (GetPermissions().HasPermission(ppapi::PERMISSION_FLASH)) {
197    switch (message.type()) {
198      case PpapiHostMsg_FlashFile_Create::ID: {
199        scoped_refptr<ResourceMessageFilter> file_filter(
200            new PepperFlashFileMessageFilter(instance, host_));
201        return scoped_ptr<ResourceHost>(new MessageFilterHost(
202            host_->GetPpapiHost(), instance, params.pp_resource(),
203            file_filter));
204      }
205    }
206  }
207
208  return scoped_ptr<ResourceHost>();
209}
210
211scoped_ptr<ppapi::host::ResourceHost>
212ContentBrowserPepperHostFactory::CreateAcceptedTCPSocket(
213    PP_Instance instance,
214    ppapi::TCPSocketVersion version,
215    scoped_ptr<net::TCPSocket> socket) {
216  if (!CanCreateSocket())
217    return scoped_ptr<ResourceHost>();
218  scoped_refptr<ResourceMessageFilter> tcp_socket(
219      new PepperTCPSocketMessageFilter(host_, instance, version,
220                                       socket.Pass()));
221  return scoped_ptr<ResourceHost>(new MessageFilterHost(
222      host_->GetPpapiHost(), instance, 0, tcp_socket));
223}
224
225scoped_ptr<ppapi::host::ResourceHost>
226ContentBrowserPepperHostFactory::CreateNewTCPSocket(
227    PP_Instance instance,
228    PP_Resource resource,
229    ppapi::TCPSocketVersion version) {
230  if (!CanCreateSocket())
231    return scoped_ptr<ResourceHost>();
232
233  scoped_refptr<ResourceMessageFilter> tcp_socket(
234      new PepperTCPSocketMessageFilter(this, host_, instance, version));
235  if (!tcp_socket)
236    return scoped_ptr<ResourceHost>();
237
238  return scoped_ptr<ResourceHost>(new MessageFilterHost(
239      host_->GetPpapiHost(), instance, resource, tcp_socket));
240}
241
242const ppapi::PpapiPermissions&
243ContentBrowserPepperHostFactory::GetPermissions() const {
244  return host_->GetPpapiHost()->permissions();
245}
246
247}  // namespace content
248