Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / renderer / pepper / host_globals.cc
bloba00748794b47daee8f3b24f2b53e1f15cf5d84d3
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.
5 #include "content/renderer/pepper/host_globals.h"
7 #include <limits>
9 #include "base/command_line.h"
10 #include "base/logging.h"
11 #include "base/rand_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/task_runner.h"
14 #include "content/public/common/content_switches.h"
15 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
16 #include "content/renderer/pepper/plugin_module.h"
17 #include "content/renderer/render_thread_impl.h"
18 #include "ppapi/shared_impl/api_id.h"
19 #include "ppapi/shared_impl/id_assignment.h"
20 #include "ppapi/shared_impl/proxy_lock.h"
21 #include "third_party/WebKit/public/platform/WebString.h"
22 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
23 #include "third_party/WebKit/public/web/WebDocument.h"
24 #include "third_party/WebKit/public/web/WebElement.h"
25 #include "third_party/WebKit/public/web/WebLocalFrame.h"
26 #include "third_party/WebKit/public/web/WebPluginContainer.h"
28 using ppapi::CheckIdType;
29 using ppapi::MakeTypedId;
30 using ppapi::PPIdType;
31 using ppapi::ResourceTracker;
32 using blink::WebConsoleMessage;
33 using blink::WebLocalFrame;
34 using blink::WebPluginContainer;
35 using blink::WebString;
37 namespace content {
39 namespace {
41 typedef std::set<WebPluginContainer*> ContainerSet;
43 // Adds all WebPluginContainers associated with the given module to the set.
44 void GetAllContainersForModule(PluginModule* module, ContainerSet* containers) {
45 const PluginModule::PluginInstanceSet& instances = module->GetAllInstances();
46 for (PluginModule::PluginInstanceSet::const_iterator i = instances.begin();
47 i != instances.end();
48 ++i) {
49 WebPluginContainer* container = (*i)->container();
50 // If "Delete" is called on an instance, the instance sets its container to
51 // NULL, but the instance may actually outlive its container. Callers of
52 // GetAllContainersForModule only want to know about valid containers.
53 if (container)
54 containers->insert(container);
58 WebConsoleMessage::Level LogLevelToWebLogLevel(PP_LogLevel level) {
59 switch (level) {
60 case PP_LOGLEVEL_TIP:
61 return WebConsoleMessage::LevelDebug;
62 case PP_LOGLEVEL_LOG:
63 return WebConsoleMessage::LevelLog;
64 case PP_LOGLEVEL_WARNING:
65 return WebConsoleMessage::LevelWarning;
66 case PP_LOGLEVEL_ERROR:
67 default:
68 return WebConsoleMessage::LevelError;
72 WebConsoleMessage MakeLogMessage(PP_LogLevel level,
73 const std::string& source,
74 const std::string& message) {
75 std::string result = source;
76 if (!result.empty())
77 result.append(": ");
78 result.append(message);
79 return WebConsoleMessage(LogLevelToWebLogLevel(level),
80 WebString(base::UTF8ToUTF16(result)));
83 } // namespace
85 HostGlobals* HostGlobals::host_globals_ = NULL;
87 HostGlobals::HostGlobals()
88 : ppapi::PpapiGlobals(),
89 resource_tracker_(ResourceTracker::SINGLE_THREADED) {
90 DCHECK(!host_globals_);
91 host_globals_ = this;
92 // We do not support calls off of the main thread on the host side, and thus
93 // do not lock.
94 ppapi::ProxyLock::DisableLocking();
97 HostGlobals::~HostGlobals() {
98 DCHECK(host_globals_ == this || !host_globals_);
99 host_globals_ = NULL;
102 ppapi::ResourceTracker* HostGlobals::GetResourceTracker() {
103 return &resource_tracker_;
106 ppapi::VarTracker* HostGlobals::GetVarTracker() { return &host_var_tracker_; }
108 ppapi::CallbackTracker* HostGlobals::GetCallbackTrackerForInstance(
109 PP_Instance instance) {
110 InstanceMap::iterator found = instance_map_.find(instance);
111 if (found == instance_map_.end())
112 return NULL;
113 return found->second->module()->GetCallbackTracker().get();
116 ppapi::thunk::PPB_Instance_API* HostGlobals::GetInstanceAPI(
117 PP_Instance instance) {
118 // The InstanceAPI is just implemented by the PluginInstance object.
119 return GetInstance(instance);
122 ppapi::thunk::ResourceCreationAPI* HostGlobals::GetResourceCreationAPI(
123 PP_Instance pp_instance) {
124 PepperPluginInstanceImpl* instance = GetInstance(pp_instance);
125 if (!instance)
126 return NULL;
127 return &instance->resource_creation();
130 PP_Module HostGlobals::GetModuleForInstance(PP_Instance instance) {
131 PepperPluginInstanceImpl* inst = GetInstance(instance);
132 if (!inst)
133 return 0;
134 return inst->module()->pp_module();
137 std::string HostGlobals::GetCmdLine() {
138 return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
139 switches::kPpapiFlashArgs);
142 void HostGlobals::PreCacheFontForFlash(const void* logfontw) {
143 // Not implemented in-process.
146 void HostGlobals::LogWithSource(PP_Instance instance,
147 PP_LogLevel level,
148 const std::string& source,
149 const std::string& value) {
150 PepperPluginInstanceImpl* instance_object =
151 HostGlobals::Get()->GetInstance(instance);
152 if (instance_object) {
153 instance_object->container()
154 ->element()
155 .document()
156 .frame()
157 ->addMessageToConsole(MakeLogMessage(level, source, value));
158 } else {
159 BroadcastLogWithSource(0, level, source, value);
163 void HostGlobals::BroadcastLogWithSource(PP_Module pp_module,
164 PP_LogLevel level,
165 const std::string& source,
166 const std::string& value) {
167 // Get the unique containers associated with the broadcast. This prevents us
168 // from sending the same message to the same console when there are two
169 // instances on the page.
170 ContainerSet containers;
171 PluginModule* module = GetModule(pp_module);
172 if (module) {
173 GetAllContainersForModule(module, &containers);
174 } else {
175 // Unknown module, get containers for all modules.
176 for (ModuleMap::const_iterator i = module_map_.begin();
177 i != module_map_.end();
178 ++i) {
179 GetAllContainersForModule(i->second, &containers);
183 WebConsoleMessage message = MakeLogMessage(level, source, value);
184 for (ContainerSet::iterator i = containers.begin(); i != containers.end();
185 ++i) {
186 WebLocalFrame* frame = (*i)->element().document().frame();
187 if (frame)
188 frame->addMessageToConsole(message);
192 base::TaskRunner* HostGlobals::GetFileTaskRunner() {
193 return RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get();
196 ppapi::MessageLoopShared* HostGlobals::GetCurrentMessageLoop() { return NULL; }
198 PP_Module HostGlobals::AddModule(PluginModule* module) {
199 #ifndef NDEBUG
200 // Make sure we're not adding one more than once.
201 for (ModuleMap::const_iterator i = module_map_.begin();
202 i != module_map_.end();
203 ++i)
204 DCHECK(i->second != module);
205 #endif
207 // See AddInstance.
208 PP_Module new_module;
209 do {
210 new_module = MakeTypedId(static_cast<PP_Module>(base::RandUint64()),
211 ppapi::PP_ID_TYPE_MODULE);
212 } while (!new_module || module_map_.find(new_module) != module_map_.end());
213 module_map_[new_module] = module;
214 return new_module;
217 void HostGlobals::ModuleDeleted(PP_Module module) {
218 DLOG_IF(ERROR, !CheckIdType(module, ppapi::PP_ID_TYPE_MODULE))
219 << module << " is not a PP_Module.";
220 ModuleMap::iterator found = module_map_.find(module);
221 if (found == module_map_.end()) {
222 NOTREACHED();
223 return;
225 module_map_.erase(found);
228 PluginModule* HostGlobals::GetModule(PP_Module module) {
229 DLOG_IF(ERROR, !CheckIdType(module, ppapi::PP_ID_TYPE_MODULE))
230 << module << " is not a PP_Module.";
231 ModuleMap::iterator found = module_map_.find(module);
232 if (found == module_map_.end())
233 return NULL;
234 return found->second;
237 PP_Instance HostGlobals::AddInstance(PepperPluginInstanceImpl* instance) {
238 DCHECK(instance_map_.find(instance->pp_instance()) == instance_map_.end());
240 // Use a random number for the instance ID. This helps prevent some
241 // accidents. See also AddModule below.
243 // Need to make sure the random number isn't a duplicate or 0.
244 PP_Instance new_instance;
245 do {
246 new_instance = MakeTypedId(static_cast<PP_Instance>(base::RandUint64()),
247 ppapi::PP_ID_TYPE_INSTANCE);
248 } while (!new_instance ||
249 instance_map_.find(new_instance) != instance_map_.end() ||
250 !instance->module()->ReserveInstanceID(new_instance));
252 instance_map_[new_instance] = instance;
254 resource_tracker_.DidCreateInstance(new_instance);
255 return new_instance;
258 void HostGlobals::InstanceDeleted(PP_Instance instance) {
259 resource_tracker_.DidDeleteInstance(instance);
260 host_var_tracker_.DidDeleteInstance(instance);
261 instance_map_.erase(instance);
264 void HostGlobals::InstanceCrashed(PP_Instance instance) {
265 resource_tracker_.DidDeleteInstance(instance);
266 host_var_tracker_.DidDeleteInstance(instance);
269 PepperPluginInstanceImpl* HostGlobals::GetInstance(PP_Instance instance) {
270 DLOG_IF(ERROR, !CheckIdType(instance, ppapi::PP_ID_TYPE_INSTANCE))
271 << instance << " is not a PP_Instance.";
272 InstanceMap::iterator found = instance_map_.find(instance);
273 if (found == instance_map_.end())
274 return NULL;
275 return found->second;
278 bool HostGlobals::IsHostGlobals() const { return true; }
280 } // namespace content