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/task_runner.h"
8 #include "base/threading/thread.h"
9 #include "ipc/ipc_message.h"
10 #include "ipc/ipc_sender.h"
11 #include "ppapi/proxy/plugin_dispatcher.h"
12 #include "ppapi/proxy/plugin_proxy_delegate.h"
13 #include "ppapi/proxy/ppb_message_loop_proxy.h"
14 #include "ppapi/shared_impl/proxy_lock.h"
15 #include "ppapi/thunk/enter.h"
20 // It performs necessary locking/unlocking of the proxy lock, and forwards all
21 // messages to the underlying sender.
22 class PluginGlobals::BrowserSender
: public IPC::Sender
{
24 // |underlying_sender| must outlive this object.
25 explicit BrowserSender(IPC::Sender
* underlying_sender
)
26 : underlying_sender_(underlying_sender
) {
29 virtual ~BrowserSender() {}
31 // IPC::Sender implementation.
32 virtual bool Send(IPC::Message
* msg
) OVERRIDE
{
34 // Synchronous messages might be re-entrant, so we need to drop the lock.
35 ProxyAutoUnlock unlock
;
36 return underlying_sender_
->Send(msg
);
39 return underlying_sender_
->Send(msg
);
43 // Non-owning pointer.
44 IPC::Sender
* underlying_sender_
;
46 DISALLOW_COPY_AND_ASSIGN(BrowserSender
);
49 PluginGlobals
* PluginGlobals::plugin_globals_
= NULL
;
51 PluginGlobals::PluginGlobals()
52 : ppapi::PpapiGlobals(),
53 plugin_proxy_delegate_(NULL
),
54 callback_tracker_(new CallbackTracker
) {
55 DCHECK(!plugin_globals_
);
56 plugin_globals_
= this;
58 // ResourceTracker asserts that we have the lock when we add new resources,
59 // so we lock when creating the MessageLoopResource even though there is no
60 // chance of race conditions.
62 loop_for_main_thread_
=
63 new MessageLoopResource(MessageLoopResource::ForMainThread());
66 PluginGlobals::PluginGlobals(PerThreadForTest per_thread_for_test
)
67 : ppapi::PpapiGlobals(per_thread_for_test
),
68 plugin_proxy_delegate_(NULL
),
69 callback_tracker_(new CallbackTracker
) {
70 DCHECK(!plugin_globals_
);
73 PluginGlobals::~PluginGlobals() {
74 DCHECK(plugin_globals_
== this || !plugin_globals_
);
77 // Release the main-thread message loop. We should have the last reference
78 // count, so this will delete the MessageLoop resource. We do this before
79 // we clear plugin_globals_, because the Resource destructor tries to access
80 // this PluginGlobals.
81 DCHECK(!loop_for_main_thread_
.get() || loop_for_main_thread_
->HasOneRef());
82 loop_for_main_thread_
= NULL
;
84 plugin_globals_
= NULL
;
87 ResourceTracker
* PluginGlobals::GetResourceTracker() {
88 return &plugin_resource_tracker_
;
91 VarTracker
* PluginGlobals::GetVarTracker() {
92 return &plugin_var_tracker_
;
95 CallbackTracker
* PluginGlobals::GetCallbackTrackerForInstance(
96 PP_Instance instance
) {
97 // In the plugin process, the callback tracker is always the same, regardless
99 return callback_tracker_
.get();
102 thunk::PPB_Instance_API
* PluginGlobals::GetInstanceAPI(PP_Instance instance
) {
103 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
105 return dispatcher
->GetInstanceAPI();
109 thunk::ResourceCreationAPI
* PluginGlobals::GetResourceCreationAPI(
110 PP_Instance instance
) {
111 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
113 return dispatcher
->GetResourceCreationAPI();
117 PP_Module
PluginGlobals::GetModuleForInstance(PP_Instance instance
) {
118 // Currently proxied plugins don't use the PP_Module for anything useful.
122 std::string
PluginGlobals::GetCmdLine() {
123 return command_line_
;
126 void PluginGlobals::PreCacheFontForFlash(const void* logfontw
) {
127 ProxyAutoUnlock unlock
;
128 plugin_proxy_delegate_
->PreCacheFont(logfontw
);
131 base::Lock
* PluginGlobals::GetProxyLock() {
135 void PluginGlobals::LogWithSource(PP_Instance instance
,
137 const std::string
& source
,
138 const std::string
& value
) {
139 const std::string
& fixed_up_source
= source
.empty() ? plugin_name_
: source
;
140 PluginDispatcher::LogWithSource(instance
, level
, fixed_up_source
, value
);
143 void PluginGlobals::BroadcastLogWithSource(PP_Module
/* module */,
145 const std::string
& source
,
146 const std::string
& value
) {
147 // Since we have only one module in a plugin process, broadcast is always
148 // the same as "send to everybody" which is what the dispatcher implements
149 // for the "instance = 0" case.
150 LogWithSource(0, level
, source
, value
);
153 MessageLoopShared
* PluginGlobals::GetCurrentMessageLoop() {
154 return MessageLoopResource::GetCurrent();
157 base::TaskRunner
* PluginGlobals::GetFileTaskRunner(PP_Instance instance
) {
158 if (!file_thread_
.get()) {
159 file_thread_
.reset(new base::Thread("Plugin::File"));
160 base::Thread::Options options
;
161 options
.message_loop_type
= base::MessageLoop::TYPE_IO
;
162 file_thread_
->StartWithOptions(options
);
164 return file_thread_
->message_loop_proxy();
167 IPC::Sender
* PluginGlobals::GetBrowserSender() {
168 if (!browser_sender_
.get()) {
169 browser_sender_
.reset(
170 new BrowserSender(plugin_proxy_delegate_
->GetBrowserSender()));
173 return browser_sender_
.get();
176 std::string
PluginGlobals::GetUILanguage() {
177 return plugin_proxy_delegate_
->GetUILanguage();
180 void PluginGlobals::SetActiveURL(const std::string
& url
) {
181 plugin_proxy_delegate_
->SetActiveURL(url
);
184 PP_Resource
PluginGlobals::CreateBrowserFont(
185 Connection connection
,
186 PP_Instance instance
,
187 const PP_BrowserFont_Trusted_Description
& desc
,
188 const ppapi::Preferences
& prefs
) {
189 return plugin_proxy_delegate_
->CreateBrowserFont(
190 connection
, instance
, desc
, prefs
);
193 MessageLoopResource
* PluginGlobals::loop_for_main_thread() {
194 return loop_for_main_thread_
.get();
197 bool PluginGlobals::IsPluginGlobals() const {