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 131base::Lock* PluginGlobals::GetProxyLock() { 132 return &proxy_lock_; 133} 134 135void PluginGlobals::LogWithSource(PP_Instance instance, 136 PP_LogLevel level, 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); 141} 142 143void PluginGlobals::BroadcastLogWithSource(PP_Module /* module */, 144 PP_LogLevel level, 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); 151} 152 153MessageLoopShared* PluginGlobals::GetCurrentMessageLoop() { 154 return MessageLoopResource::GetCurrent(); 155} 156 157base::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); 163 } 164 return file_thread_->message_loop_proxy(); 165} 166 167IPC::Sender* PluginGlobals::GetBrowserSender() { 168 if (!browser_sender_.get()) { 169 browser_sender_.reset( 170 new BrowserSender(plugin_proxy_delegate_->GetBrowserSender())); 171 } 172 173 return browser_sender_.get(); 174} 175 176std::string PluginGlobals::GetUILanguage() { 177 return plugin_proxy_delegate_->GetUILanguage(); 178} 179 180void PluginGlobals::SetActiveURL(const std::string& url) { 181 plugin_proxy_delegate_->SetActiveURL(url); 182} 183 184PP_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); 191} 192 193MessageLoopResource* PluginGlobals::loop_for_main_thread() { 194 return loop_for_main_thread_.get(); 195} 196 197bool PluginGlobals::IsPluginGlobals() const { 198 return true; 199} 200 201} // namespace proxy 202} // namespace ppapi 203