Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ppapi / proxy / plugin_globals.cc
blob64ff47b4110ceee320d74392299acbe2386ef0ea
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.
5 #include "ppapi/proxy/plugin_globals.h"
7 #include "base/location.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/task_runner.h"
10 #include "base/threading/thread.h"
11 #include "ipc/ipc_message.h"
12 #include "ipc/ipc_sender.h"
13 #include "ppapi/proxy/plugin_dispatcher.h"
14 #include "ppapi/proxy/plugin_message_filter.h"
15 #include "ppapi/proxy/plugin_proxy_delegate.h"
16 #include "ppapi/proxy/ppapi_messages.h"
17 #include "ppapi/proxy/ppb_message_loop_proxy.h"
18 #include "ppapi/proxy/resource_reply_thread_registrar.h"
19 #include "ppapi/proxy/udp_socket_filter.h"
20 #include "ppapi/shared_impl/ppapi_constants.h"
21 #include "ppapi/shared_impl/proxy_lock.h"
22 #include "ppapi/thunk/enter.h"
24 namespace ppapi {
25 namespace proxy {
27 // It performs necessary locking/unlocking of the proxy lock, and forwards all
28 // messages to the underlying sender.
29 class PluginGlobals::BrowserSender : public IPC::Sender {
30 public:
31 // |underlying_sender| must outlive this object.
32 explicit BrowserSender(IPC::Sender* underlying_sender)
33 : underlying_sender_(underlying_sender) {
36 ~BrowserSender() override {}
38 // IPC::Sender implementation.
39 bool Send(IPC::Message* msg) override {
40 if (msg->is_sync()) {
41 // Synchronous messages might be re-entrant, so we need to drop the lock.
42 ProxyAutoUnlock unlock;
43 return underlying_sender_->Send(msg);
46 return underlying_sender_->Send(msg);
49 private:
50 // Non-owning pointer.
51 IPC::Sender* underlying_sender_;
53 DISALLOW_COPY_AND_ASSIGN(BrowserSender);
56 PluginGlobals* PluginGlobals::plugin_globals_ = NULL;
58 PluginGlobals::PluginGlobals(
59 const scoped_refptr<base::TaskRunner>& ipc_task_runner)
60 : ppapi::PpapiGlobals(),
61 plugin_proxy_delegate_(NULL),
62 callback_tracker_(new CallbackTracker),
63 ipc_task_runner_(ipc_task_runner),
64 resource_reply_thread_registrar_(
65 new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())),
66 udp_socket_filter_(new UDPSocketFilter()),
67 plugin_recently_active_(false),
68 keepalive_throttle_interval_milliseconds_(
69 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds),
70 weak_factory_(this) {
71 DCHECK(!plugin_globals_);
72 plugin_globals_ = this;
74 // ResourceTracker asserts that we have the lock when we add new resources,
75 // so we lock when creating the MessageLoopResource even though there is no
76 // chance of race conditions.
77 ProxyAutoLock lock;
78 loop_for_main_thread_ =
79 new MessageLoopResource(MessageLoopResource::ForMainThread());
82 PluginGlobals::PluginGlobals(
83 PerThreadForTest per_thread_for_test,
84 const scoped_refptr<base::TaskRunner>& ipc_task_runner)
85 : ppapi::PpapiGlobals(per_thread_for_test),
86 plugin_proxy_delegate_(NULL),
87 callback_tracker_(new CallbackTracker),
88 ipc_task_runner_(ipc_task_runner),
89 resource_reply_thread_registrar_(
90 new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())),
91 plugin_recently_active_(false),
92 keepalive_throttle_interval_milliseconds_(
93 kKeepaliveThrottleIntervalDefaultMilliseconds),
94 weak_factory_(this) {
95 DCHECK(!plugin_globals_);
98 PluginGlobals::~PluginGlobals() {
99 DCHECK(plugin_globals_ == this || !plugin_globals_);
101 ProxyAutoLock lock;
102 // Release the main-thread message loop. We should have the last reference
103 // count, so this will delete the MessageLoop resource. We do this before
104 // we clear plugin_globals_, because the Resource destructor tries to access
105 // this PluginGlobals.
106 DCHECK(!loop_for_main_thread_.get() || loop_for_main_thread_->HasOneRef());
107 loop_for_main_thread_ = NULL;
109 plugin_globals_ = NULL;
112 ResourceTracker* PluginGlobals::GetResourceTracker() {
113 return &plugin_resource_tracker_;
116 VarTracker* PluginGlobals::GetVarTracker() {
117 return &plugin_var_tracker_;
120 CallbackTracker* PluginGlobals::GetCallbackTrackerForInstance(
121 PP_Instance instance) {
122 // In the plugin process, the callback tracker is always the same, regardless
123 // of the instance.
124 return callback_tracker_.get();
127 thunk::PPB_Instance_API* PluginGlobals::GetInstanceAPI(PP_Instance instance) {
128 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
129 if (dispatcher)
130 return dispatcher->GetInstanceAPI();
131 return NULL;
134 thunk::ResourceCreationAPI* PluginGlobals::GetResourceCreationAPI(
135 PP_Instance instance) {
136 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
137 if (dispatcher)
138 return dispatcher->GetResourceCreationAPI();
139 return NULL;
142 PP_Module PluginGlobals::GetModuleForInstance(PP_Instance instance) {
143 // Currently proxied plugins don't use the PP_Module for anything useful.
144 return 0;
147 std::string PluginGlobals::GetCmdLine() {
148 return command_line_;
151 void PluginGlobals::PreCacheFontForFlash(const void* logfontw) {
152 ProxyAutoUnlock unlock;
153 plugin_proxy_delegate_->PreCacheFontForFlash(logfontw);
156 void PluginGlobals::LogWithSource(PP_Instance instance,
157 PP_LogLevel level,
158 const std::string& source,
159 const std::string& value) {
160 const std::string& fixed_up_source = source.empty() ? plugin_name_ : source;
161 PluginDispatcher::LogWithSource(instance, level, fixed_up_source, value);
164 void PluginGlobals::BroadcastLogWithSource(PP_Module /* module */,
165 PP_LogLevel level,
166 const std::string& source,
167 const std::string& value) {
168 // Since we have only one module in a plugin process, broadcast is always
169 // the same as "send to everybody" which is what the dispatcher implements
170 // for the "instance = 0" case.
171 LogWithSource(0, level, source, value);
174 MessageLoopShared* PluginGlobals::GetCurrentMessageLoop() {
175 return MessageLoopResource::GetCurrent();
178 base::TaskRunner* PluginGlobals::GetFileTaskRunner() {
179 if (!file_thread_.get()) {
180 file_thread_.reset(new base::Thread("Plugin::File"));
181 base::Thread::Options options;
182 options.message_loop_type = base::MessageLoop::TYPE_IO;
183 file_thread_->StartWithOptions(options);
185 return file_thread_->task_runner().get();
188 void PluginGlobals::MarkPluginIsActive() {
189 if (!plugin_recently_active_) {
190 plugin_recently_active_ = true;
191 if (!GetBrowserSender() || !base::MessageLoop::current())
192 return;
193 GetBrowserSender()->Send(new PpapiHostMsg_Keepalive());
194 DCHECK(keepalive_throttle_interval_milliseconds_);
195 GetMainThreadMessageLoop()->PostDelayedTask(
196 FROM_HERE,
197 RunWhileLocked(base::Bind(&PluginGlobals::OnReleaseKeepaliveThrottle,
198 weak_factory_.GetWeakPtr())),
199 base::TimeDelta::FromMilliseconds(
200 keepalive_throttle_interval_milliseconds_));
204 IPC::Sender* PluginGlobals::GetBrowserSender() {
205 // CAUTION: This function is called without the ProxyLock. See also
206 // InterfaceList::GetInterfaceForPPB.
208 // See also SetPluginProxyDelegate. That initializes browser_sender_ before
209 // the plugin can start threads, and it may be cleared after the
210 // plugin has torn down threads. So this pointer is expected to remain valid
211 // during the lifetime of the plugin.
212 return browser_sender_.get();
215 std::string PluginGlobals::GetUILanguage() {
216 return plugin_proxy_delegate_->GetUILanguage();
219 void PluginGlobals::SetActiveURL(const std::string& url) {
220 plugin_proxy_delegate_->SetActiveURL(url);
223 PP_Resource PluginGlobals::CreateBrowserFont(
224 Connection connection,
225 PP_Instance instance,
226 const PP_BrowserFont_Trusted_Description& desc,
227 const ppapi::Preferences& prefs) {
228 return plugin_proxy_delegate_->CreateBrowserFont(
229 connection, instance, desc, prefs);
232 void PluginGlobals::SetPluginProxyDelegate(PluginProxyDelegate* delegate) {
233 DCHECK(delegate && !plugin_proxy_delegate_);
234 plugin_proxy_delegate_ = delegate;
235 browser_sender_.reset(
236 new BrowserSender(plugin_proxy_delegate_->GetBrowserSender()));
239 void PluginGlobals::ResetPluginProxyDelegate() {
240 DCHECK(plugin_proxy_delegate_);
241 plugin_proxy_delegate_ = NULL;
242 browser_sender_.reset();
245 MessageLoopResource* PluginGlobals::loop_for_main_thread() {
246 return loop_for_main_thread_.get();
249 void PluginGlobals::RegisterResourceMessageFilters(
250 ppapi::proxy::PluginMessageFilter* plugin_filter) {
251 plugin_filter->AddResourceMessageFilter(udp_socket_filter_.get());
254 void PluginGlobals::set_keepalive_throttle_interval_milliseconds(unsigned i) {
255 keepalive_throttle_interval_milliseconds_ = i;
258 bool PluginGlobals::IsPluginGlobals() const {
259 return true;
262 void PluginGlobals::OnReleaseKeepaliveThrottle() {
263 ppapi::ProxyLock::AssertAcquiredDebugOnly();
264 plugin_recently_active_ = false;
267 } // namespace proxy
268 } // namespace ppapi