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