Elim cr-checkbox
[chromium-blink-merge.git] / ppapi / nacl_irt / ppapi_dispatcher.cc
blob42d900c8373c2c04a71b16987ccd0b73901ec6c7
1 // Copyright 2014 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.
5 #include "ppapi/nacl_irt/ppapi_dispatcher.h"
7 #include <map>
8 #include <set>
10 #include "base/command_line.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "build/build_config.h"
15 #include "components/tracing/child_trace_message_filter.h"
16 #include "ipc/ipc_channel_handle.h"
17 #include "ipc/ipc_logging.h"
18 #include "ipc/ipc_message.h"
19 #include "ppapi/c/ppp.h"
20 #include "ppapi/c/ppp_instance.h"
21 #include "ppapi/nacl_irt/manifest_service.h"
22 #include "ppapi/nacl_irt/plugin_startup.h"
23 #include "ppapi/proxy/plugin_dispatcher.h"
24 #include "ppapi/proxy/plugin_globals.h"
25 #include "ppapi/proxy/plugin_message_filter.h"
26 #include "ppapi/proxy/plugin_proxy_delegate.h"
27 #include "ppapi/proxy/ppapi_messages.h"
28 #include "ppapi/proxy/resource_reply_thread_registrar.h"
30 namespace ppapi {
32 PpapiDispatcher::PpapiDispatcher(
33 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
34 base::WaitableEvent* shutdown_event,
35 int browser_ipc_fd,
36 int renderer_ipc_fd)
37 : next_plugin_dispatcher_id_(0),
38 task_runner_(io_task_runner),
39 shutdown_event_(shutdown_event),
40 renderer_ipc_fd_(renderer_ipc_fd) {
41 IPC::ChannelHandle channel_handle(
42 "NaCl IPC", base::FileDescriptor(browser_ipc_fd, false));
44 proxy::PluginGlobals* globals = proxy::PluginGlobals::Get();
45 // Delay initializing the SyncChannel until after we add filters. This
46 // ensures that the filters won't miss any messages received by
47 // the channel.
48 channel_ =
49 IPC::SyncChannel::Create(this, GetIPCTaskRunner(), GetShutdownEvent());
50 scoped_refptr<ppapi::proxy::PluginMessageFilter> plugin_filter(
51 new ppapi::proxy::PluginMessageFilter(
52 NULL, globals->resource_reply_thread_registrar()));
53 channel_->AddFilter(plugin_filter.get());
54 globals->RegisterResourceMessageFilters(plugin_filter.get());
56 channel_->AddFilter(new tracing::ChildTraceMessageFilter(task_runner_.get()));
57 channel_->Init(channel_handle, IPC::Channel::MODE_SERVER, true);
60 base::SingleThreadTaskRunner* PpapiDispatcher::GetIPCTaskRunner() {
61 return task_runner_.get();
64 base::WaitableEvent* PpapiDispatcher::GetShutdownEvent() {
65 return shutdown_event_;
68 IPC::PlatformFileForTransit PpapiDispatcher::ShareHandleWithRemote(
69 base::PlatformFile handle,
70 base::ProcessId peer_pid,
71 bool should_close_source) {
72 return IPC::InvalidPlatformFileForTransit();
75 base::SharedMemoryHandle PpapiDispatcher::ShareSharedMemoryHandleWithRemote(
76 const base::SharedMemoryHandle& handle,
77 base::ProcessId remote_pid) {
78 return base::SharedMemory::NULLHandle();
81 std::set<PP_Instance>* PpapiDispatcher::GetGloballySeenInstanceIDSet() {
82 return &instances_;
85 uint32 PpapiDispatcher::Register(proxy::PluginDispatcher* plugin_dispatcher) {
86 if (!plugin_dispatcher ||
87 plugin_dispatchers_.size() >= std::numeric_limits<uint32>::max()) {
88 return 0;
91 uint32 id = 0;
92 do {
93 // Although it is unlikely, make sure that we won't cause any trouble
94 // when the counter overflows.
95 id = next_plugin_dispatcher_id_++;
96 } while (id == 0 ||
97 plugin_dispatchers_.find(id) != plugin_dispatchers_.end());
98 plugin_dispatchers_[id] = plugin_dispatcher;
99 return id;
102 void PpapiDispatcher::Unregister(uint32 plugin_dispatcher_id) {
103 plugin_dispatchers_.erase(plugin_dispatcher_id);
106 IPC::Sender* PpapiDispatcher::GetBrowserSender() {
107 return this;
110 std::string PpapiDispatcher::GetUILanguage() {
111 NOTIMPLEMENTED();
112 return std::string();
115 void PpapiDispatcher::PreCacheFontForFlash(const void* logfontw) {
116 NOTIMPLEMENTED();
119 void PpapiDispatcher::SetActiveURL(const std::string& url) {
120 NOTIMPLEMENTED();
123 PP_Resource PpapiDispatcher::CreateBrowserFont(
124 proxy::Connection connection,
125 PP_Instance instance,
126 const PP_BrowserFont_Trusted_Description& desc,
127 const Preferences& prefs) {
128 NOTIMPLEMENTED();
129 return 0;
132 bool PpapiDispatcher::OnMessageReceived(const IPC::Message& msg) {
133 IPC_BEGIN_MESSAGE_MAP(PpapiDispatcher, msg)
134 IPC_MESSAGE_HANDLER(PpapiMsg_InitializeNaClDispatcher,
135 OnMsgInitializeNaClDispatcher)
136 // All other messages are simply forwarded to a PluginDispatcher.
137 IPC_MESSAGE_UNHANDLED(OnPluginDispatcherMessageReceived(msg))
138 IPC_END_MESSAGE_MAP()
139 return true;
142 void PpapiDispatcher::OnChannelError() {
143 exit(1);
146 bool PpapiDispatcher::Send(IPC::Message* msg) {
147 return channel_->Send(msg);
150 void PpapiDispatcher::OnMsgInitializeNaClDispatcher(
151 const PpapiNaClPluginArgs& args) {
152 static bool command_line_and_logging_initialized = false;
153 if (command_line_and_logging_initialized) {
154 LOG(FATAL) << "InitializeNaClDispatcher must be called once per plugin.";
155 return;
158 command_line_and_logging_initialized = true;
159 base::CommandLine::Init(0, NULL);
160 for (size_t i = 0; i < args.switch_names.size(); ++i) {
161 DCHECK(i < args.switch_values.size());
162 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
163 args.switch_names[i], args.switch_values[i]);
165 logging::LoggingSettings settings;
166 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
167 logging::InitLogging(settings);
169 proxy::PluginGlobals::Get()->set_keepalive_throttle_interval_milliseconds(
170 args.keepalive_throttle_interval_milliseconds);
172 // Tell the process-global GetInterface which interfaces it can return to the
173 // plugin.
174 proxy::InterfaceList::SetProcessGlobalPermissions(args.permissions);
176 int32_t error = ::PPP_InitializeModule(
177 0 /* module */,
178 &proxy::PluginDispatcher::GetBrowserInterface);
179 if (error)
180 ::exit(error);
182 proxy::PluginDispatcher* dispatcher =
183 new proxy::PluginDispatcher(::PPP_GetInterface, args.permissions,
184 args.off_the_record);
185 IPC::ChannelHandle channel_handle(
186 "nacl",
187 base::FileDescriptor(renderer_ipc_fd_, false));
188 if (!dispatcher->InitPluginWithChannel(this, base::kNullProcessId,
189 channel_handle, false)) {
190 delete dispatcher;
191 return;
193 // From here, the dispatcher will manage its own lifetime according to the
194 // lifetime of the attached channel.
196 // Notify the renderer process, if necessary.
197 ManifestService* manifest_service = GetManifestService();
198 if (manifest_service)
199 manifest_service->StartupInitializationComplete();
202 void PpapiDispatcher::OnPluginDispatcherMessageReceived(
203 const IPC::Message& msg) {
204 // The first parameter should be a plugin dispatcher ID.
205 base::PickleIterator iter(msg);
206 uint32 id = 0;
207 if (!iter.ReadUInt32(&id)) {
208 NOTREACHED();
209 return;
211 std::map<uint32, proxy::PluginDispatcher*>::iterator dispatcher =
212 plugin_dispatchers_.find(id);
213 if (dispatcher != plugin_dispatchers_.end())
214 dispatcher->second->OnMessageReceived(msg);
217 } // namespace ppapi