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