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 "ppapi/proxy/plugin_globals.h"
6
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/proxy/resource_reply_thread_registrar.h"
15 #include "ppapi/shared_impl/proxy_lock.h"
16 #include "ppapi/thunk/enter.h"
17
18 namespace ppapi {
19 namespace proxy {
20
21 // It performs necessary locking/unlocking of the proxy lock, and forwards all
22 // messages to the underlying sender.
23 class PluginGlobals::BrowserSender : public IPC::Sender {
24 public:
25 // |underlying_sender| must outlive this object.
BrowserSender(IPC::Sender * underlying_sender)26 explicit BrowserSender(IPC::Sender* underlying_sender)
27 : underlying_sender_(underlying_sender) {
28 }
29
~BrowserSender()30 virtual ~BrowserSender() {}
31
32 // IPC::Sender implementation.
Send(IPC::Message * msg)33 virtual bool Send(IPC::Message* msg) OVERRIDE {
34 if (msg->is_sync()) {
35 // Synchronous messages might be re-entrant, so we need to drop the lock.
36 ProxyAutoUnlock unlock;
37 return underlying_sender_->Send(msg);
38 }
39
40 return underlying_sender_->Send(msg);
41 }
42
43 private:
44 // Non-owning pointer.
45 IPC::Sender* underlying_sender_;
46
47 DISALLOW_COPY_AND_ASSIGN(BrowserSender);
48 };
49
50 PluginGlobals* PluginGlobals::plugin_globals_ = NULL;
51
PluginGlobals()52 PluginGlobals::PluginGlobals()
53 : ppapi::PpapiGlobals(),
54 plugin_proxy_delegate_(NULL),
55 callback_tracker_(new CallbackTracker),
56 resource_reply_thread_registrar_(
57 new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())) {
58 DCHECK(!plugin_globals_);
59 plugin_globals_ = this;
60
61 // ResourceTracker asserts that we have the lock when we add new resources,
62 // so we lock when creating the MessageLoopResource even though there is no
63 // chance of race conditions.
64 ProxyAutoLock lock;
65 loop_for_main_thread_ =
66 new MessageLoopResource(MessageLoopResource::ForMainThread());
67 }
68
PluginGlobals(PerThreadForTest per_thread_for_test)69 PluginGlobals::PluginGlobals(PerThreadForTest per_thread_for_test)
70 : ppapi::PpapiGlobals(per_thread_for_test),
71 plugin_proxy_delegate_(NULL),
72 callback_tracker_(new CallbackTracker),
73 resource_reply_thread_registrar_(
74 new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())) {
75 DCHECK(!plugin_globals_);
76 }
77
~PluginGlobals()78 PluginGlobals::~PluginGlobals() {
79 DCHECK(plugin_globals_ == this || !plugin_globals_);
80 {
81 ProxyAutoLock lock;
82 // Release the main-thread message loop. We should have the last reference
83 // count, so this will delete the MessageLoop resource. We do this before
84 // we clear plugin_globals_, because the Resource destructor tries to access
85 // this PluginGlobals.
86 DCHECK(!loop_for_main_thread_.get() || loop_for_main_thread_->HasOneRef());
87 loop_for_main_thread_ = NULL;
88 }
89 plugin_globals_ = NULL;
90 }
91
GetResourceTracker()92 ResourceTracker* PluginGlobals::GetResourceTracker() {
93 return &plugin_resource_tracker_;
94 }
95
GetVarTracker()96 VarTracker* PluginGlobals::GetVarTracker() {
97 return &plugin_var_tracker_;
98 }
99
GetCallbackTrackerForInstance(PP_Instance instance)100 CallbackTracker* PluginGlobals::GetCallbackTrackerForInstance(
101 PP_Instance instance) {
102 // In the plugin process, the callback tracker is always the same, regardless
103 // of the instance.
104 return callback_tracker_.get();
105 }
106
GetInstanceAPI(PP_Instance instance)107 thunk::PPB_Instance_API* PluginGlobals::GetInstanceAPI(PP_Instance instance) {
108 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
109 if (dispatcher)
110 return dispatcher->GetInstanceAPI();
111 return NULL;
112 }
113
GetResourceCreationAPI(PP_Instance instance)114 thunk::ResourceCreationAPI* PluginGlobals::GetResourceCreationAPI(
115 PP_Instance instance) {
116 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
117 if (dispatcher)
118 return dispatcher->GetResourceCreationAPI();
119 return NULL;
120 }
121
GetModuleForInstance(PP_Instance instance)122 PP_Module PluginGlobals::GetModuleForInstance(PP_Instance instance) {
123 // Currently proxied plugins don't use the PP_Module for anything useful.
124 return 0;
125 }
126
GetCmdLine()127 std::string PluginGlobals::GetCmdLine() {
128 return command_line_;
129 }
130
PreCacheFontForFlash(const void * logfontw)131 void PluginGlobals::PreCacheFontForFlash(const void* logfontw) {
132 ProxyAutoUnlock unlock;
133 plugin_proxy_delegate_->PreCacheFont(logfontw);
134 }
135
LogWithSource(PP_Instance instance,PP_LogLevel level,const std::string & source,const std::string & value)136 void PluginGlobals::LogWithSource(PP_Instance instance,
137 PP_LogLevel level,
138 const std::string& source,
139 const std::string& value) {
140 const std::string& fixed_up_source = source.empty() ? plugin_name_ : source;
141 PluginDispatcher::LogWithSource(instance, level, fixed_up_source, value);
142 }
143
BroadcastLogWithSource(PP_Module,PP_LogLevel level,const std::string & source,const std::string & value)144 void PluginGlobals::BroadcastLogWithSource(PP_Module /* module */,
145 PP_LogLevel level,
146 const std::string& source,
147 const std::string& value) {
148 // Since we have only one module in a plugin process, broadcast is always
149 // the same as "send to everybody" which is what the dispatcher implements
150 // for the "instance = 0" case.
151 LogWithSource(0, level, source, value);
152 }
153
GetCurrentMessageLoop()154 MessageLoopShared* PluginGlobals::GetCurrentMessageLoop() {
155 return MessageLoopResource::GetCurrent();
156 }
157
GetFileTaskRunner()158 base::TaskRunner* PluginGlobals::GetFileTaskRunner() {
159 if (!file_thread_.get()) {
160 file_thread_.reset(new base::Thread("Plugin::File"));
161 base::Thread::Options options;
162 options.message_loop_type = base::MessageLoop::TYPE_IO;
163 file_thread_->StartWithOptions(options);
164 }
165 return file_thread_->message_loop_proxy();
166 }
167
GetBrowserSender()168 IPC::Sender* PluginGlobals::GetBrowserSender() {
169 if (!browser_sender_.get()) {
170 browser_sender_.reset(
171 new BrowserSender(plugin_proxy_delegate_->GetBrowserSender()));
172 }
173
174 return browser_sender_.get();
175 }
176
GetUILanguage()177 std::string PluginGlobals::GetUILanguage() {
178 return plugin_proxy_delegate_->GetUILanguage();
179 }
180
SetActiveURL(const std::string & url)181 void PluginGlobals::SetActiveURL(const std::string& url) {
182 plugin_proxy_delegate_->SetActiveURL(url);
183 }
184
CreateBrowserFont(Connection connection,PP_Instance instance,const PP_BrowserFont_Trusted_Description & desc,const ppapi::Preferences & prefs)185 PP_Resource PluginGlobals::CreateBrowserFont(
186 Connection connection,
187 PP_Instance instance,
188 const PP_BrowserFont_Trusted_Description& desc,
189 const ppapi::Preferences& prefs) {
190 return plugin_proxy_delegate_->CreateBrowserFont(
191 connection, instance, desc, prefs);
192 }
193
loop_for_main_thread()194 MessageLoopResource* PluginGlobals::loop_for_main_thread() {
195 return loop_for_main_thread_.get();
196 }
197
IsPluginGlobals() const198 bool PluginGlobals::IsPluginGlobals() const {
199 return true;
200 }
201
202 } // namespace proxy
203 } // namespace ppapi
204