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