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