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