Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / pepper / browser_ppapi_host_impl.cc
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/browser_ppapi_host_impl.h"
6
7 #include "base/metrics/sparse_histogram.h"
8 #include "content/browser/renderer_host/pepper/pepper_message_filter.h"
9 #include "content/browser/tracing/trace_message_filter.h"
10 #include "content/common/pepper_renderer_instance_data.h"
11 #include "content/public/common/process_type.h"
12 #include "ipc/ipc_message_macros.h"
13 #include "ppapi/proxy/ppapi_messages.h"
14
15 namespace content {
16
17 // static
18 BrowserPpapiHost* BrowserPpapiHost::CreateExternalPluginProcess(
19     IPC::Sender* sender,
20     ppapi::PpapiPermissions permissions,
21     base::ProcessHandle plugin_child_process,
22     IPC::ChannelProxy* channel,
23     int render_process_id,
24     int render_view_id,
25     const base::FilePath& profile_directory) {
26   // The plugin name and path shouldn't be needed for external plugins.
27   BrowserPpapiHostImpl* browser_ppapi_host =
28       new BrowserPpapiHostImpl(sender, permissions, std::string(),
29                                base::FilePath(), profile_directory,
30                                false /* in_process */,
31                                true /* external_plugin */);
32   browser_ppapi_host->set_plugin_process_handle(plugin_child_process);
33
34   scoped_refptr<PepperMessageFilter> pepper_message_filter(
35       new PepperMessageFilter());
36   channel->AddFilter(pepper_message_filter->GetFilter());
37   channel->AddFilter(browser_ppapi_host->message_filter());
38   channel->AddFilter((new TraceMessageFilter())->GetFilter());
39
40   return browser_ppapi_host;
41 }
42
43 BrowserPpapiHostImpl::BrowserPpapiHostImpl(
44     IPC::Sender* sender,
45     const ppapi::PpapiPermissions& permissions,
46     const std::string& plugin_name,
47     const base::FilePath& plugin_path,
48     const base::FilePath& profile_data_directory,
49     bool in_process,
50     bool external_plugin)
51     : ppapi_host_(new ppapi::host::PpapiHost(sender, permissions)),
52       plugin_process_handle_(base::kNullProcessHandle),
53       plugin_name_(plugin_name),
54       plugin_path_(plugin_path),
55       profile_data_directory_(profile_data_directory),
56       in_process_(in_process),
57       external_plugin_(external_plugin),
58       ssl_context_helper_(new SSLContextHelper()) {
59   message_filter_ = new HostMessageFilter(ppapi_host_.get(), this);
60   ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
61       new ContentBrowserPepperHostFactory(this)));
62 }
63
64 BrowserPpapiHostImpl::~BrowserPpapiHostImpl() {
65   // Notify the filter so it won't foward messages to us.
66   message_filter_->OnHostDestroyed();
67
68   // Delete the host explicitly first. This shutdown will destroy the
69   // resources, which may want to do cleanup in their destructors and expect
70   // their pointers to us to be valid.
71   ppapi_host_.reset();
72 }
73
74 ppapi::host::PpapiHost* BrowserPpapiHostImpl::GetPpapiHost() {
75   return ppapi_host_.get();
76 }
77
78 base::ProcessHandle BrowserPpapiHostImpl::GetPluginProcessHandle() const {
79   // Handle should previously have been set before use.
80   DCHECK(in_process_ || plugin_process_handle_ != base::kNullProcessHandle);
81   return plugin_process_handle_;
82 }
83
84 bool BrowserPpapiHostImpl::IsValidInstance(PP_Instance instance) const {
85   return instance_map_.find(instance) != instance_map_.end();
86 }
87
88 bool BrowserPpapiHostImpl::GetRenderFrameIDsForInstance(
89     PP_Instance instance,
90     int* render_process_id,
91     int* render_frame_id) const {
92   InstanceMap::const_iterator found = instance_map_.find(instance);
93   if (found == instance_map_.end()) {
94     *render_process_id = 0;
95     *render_frame_id = 0;
96     return false;
97   }
98
99   *render_process_id = found->second.render_process_id;
100   *render_frame_id = found->second.render_frame_id;
101   return true;
102 }
103
104 const std::string& BrowserPpapiHostImpl::GetPluginName() {
105   return plugin_name_;
106 }
107
108 const base::FilePath& BrowserPpapiHostImpl::GetPluginPath() {
109   return plugin_path_;
110 }
111
112 const base::FilePath& BrowserPpapiHostImpl::GetProfileDataDirectory() {
113   return profile_data_directory_;
114 }
115
116 GURL BrowserPpapiHostImpl::GetDocumentURLForInstance(PP_Instance instance) {
117   InstanceMap::const_iterator found = instance_map_.find(instance);
118   if (found == instance_map_.end())
119     return GURL();
120   return found->second.document_url;
121 }
122
123 GURL BrowserPpapiHostImpl::GetPluginURLForInstance(PP_Instance instance) {
124   InstanceMap::const_iterator found = instance_map_.find(instance);
125   if (found == instance_map_.end())
126     return GURL();
127   return found->second.plugin_url;
128 }
129
130 void BrowserPpapiHostImpl::SetOnKeepaliveCallback(
131       const BrowserPpapiHost::OnKeepaliveCallback& callback) {
132   on_keepalive_callback_ = callback;
133 }
134
135 void BrowserPpapiHostImpl::AddInstance(
136     PP_Instance instance,
137     const PepperRendererInstanceData& instance_data) {
138   DCHECK(instance_map_.find(instance) == instance_map_.end());
139   instance_map_[instance] = instance_data;
140 }
141
142 void BrowserPpapiHostImpl::DeleteInstance(PP_Instance instance) {
143   InstanceMap::iterator found = instance_map_.find(instance);
144   if (found == instance_map_.end()) {
145     NOTREACHED();
146     return;
147   }
148   instance_map_.erase(found);
149 }
150
151 BrowserPpapiHostImpl::HostMessageFilter::HostMessageFilter(
152     ppapi::host::PpapiHost* ppapi_host,
153     BrowserPpapiHostImpl* browser_ppapi_host_impl)
154         : ppapi_host_(ppapi_host),
155           browser_ppapi_host_impl_(browser_ppapi_host_impl) {
156 }
157
158 bool BrowserPpapiHostImpl::HostMessageFilter::OnMessageReceived(
159     const IPC::Message& msg) {
160   // Don't forward messages if our owner object has been destroyed.
161   if (!ppapi_host_)
162     return false;
163
164   bool handled = true;
165   IPC_BEGIN_MESSAGE_MAP(BrowserPpapiHostImpl::HostMessageFilter, msg)
166     // Add necessary message handlers here.
167     IPC_MESSAGE_HANDLER(PpapiHostMsg_Keepalive, OnKeepalive)
168     IPC_MESSAGE_HANDLER(PpapiHostMsg_LogInterfaceUsage,
169                         OnHostMsgLogInterfaceUsage)
170     IPC_MESSAGE_UNHANDLED(handled = ppapi_host_->OnMessageReceived(msg))
171   IPC_END_MESSAGE_MAP();
172   return handled;
173 }
174
175 void BrowserPpapiHostImpl::HostMessageFilter::OnHostDestroyed() {
176   DCHECK(ppapi_host_);
177   ppapi_host_ = NULL;
178   browser_ppapi_host_impl_ = NULL;
179 }
180
181 BrowserPpapiHostImpl::HostMessageFilter::~HostMessageFilter() {
182 }
183
184 void BrowserPpapiHostImpl::HostMessageFilter::OnKeepalive() {
185   if (browser_ppapi_host_impl_)
186     browser_ppapi_host_impl_->OnKeepalive();
187 }
188
189 void BrowserPpapiHostImpl::HostMessageFilter::OnHostMsgLogInterfaceUsage(
190     int hash) const {
191   UMA_HISTOGRAM_SPARSE_SLOWLY("Pepper.InterfaceUsed", hash);
192 }
193
194 void BrowserPpapiHostImpl::OnKeepalive() {
195   // An instance has been active. The on_keepalive_callback_ will be
196   // used to permit the content embedder to handle this, e.g. by tracking
197   // activity and shutting down processes that go idle.
198   //
199   // Currently embedders do not need to distinguish between instances having
200   // different idle state, and thus this implementation handles all instances
201   // for this module together.
202
203   if (on_keepalive_callback_.is_null())
204     return;
205
206   BrowserPpapiHost::OnKeepaliveInstanceData
207       instance_data(instance_map_.size());
208
209   InstanceMap::iterator instance = instance_map_.begin();
210   int i = 0;
211   while (instance != instance_map_.end()) {
212     instance_data[i].render_process_id = instance->second.render_process_id;
213     instance_data[i].render_frame_id = instance->second.render_frame_id;
214     instance_data[i].document_url = instance->second.document_url;
215     ++instance;
216     ++i;
217   }
218   on_keepalive_callback_.Run(instance_data, profile_data_directory_);
219 }
220
221 }  // namespace content