OLD | NEW |
| (Empty) |
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 "webkit/plugins/ppapi/host_globals.h" | |
6 | |
7 #include <limits> | |
8 | |
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 "ppapi/shared_impl/api_id.h" | |
15 #include "ppapi/shared_impl/id_assignment.h" | |
16 #include "third_party/WebKit/public/platform/WebString.h" | |
17 #include "third_party/WebKit/public/web/WebConsoleMessage.h" | |
18 #include "third_party/WebKit/public/web/WebDocument.h" | |
19 #include "third_party/WebKit/public/web/WebElement.h" | |
20 #include "third_party/WebKit/public/web/WebFrame.h" | |
21 #include "third_party/WebKit/public/web/WebPluginContainer.h" | |
22 #include "webkit/plugins/plugin_switches.h" | |
23 #include "webkit/plugins/ppapi/plugin_module.h" | |
24 #include "webkit/plugins/ppapi/ppapi_plugin_instance_impl.h" | |
25 | |
26 using ppapi::CheckIdType; | |
27 using ppapi::MakeTypedId; | |
28 using ppapi::PPIdType; | |
29 using ppapi::ResourceTracker; | |
30 using WebKit::WebConsoleMessage; | |
31 using WebKit::WebString; | |
32 | |
33 namespace webkit { | |
34 namespace ppapi { | |
35 | |
36 namespace { | |
37 | |
38 typedef std::set<WebKit::WebPluginContainer*> ContainerSet; | |
39 | |
40 // Adds all WebPluginContainers associated with the given module to the set. | |
41 void GetAllContainersForModule(PluginModule* module, | |
42 ContainerSet* containers) { | |
43 const PluginModule::PluginInstanceSet& instances = | |
44 module->GetAllInstances(); | |
45 for (PluginModule::PluginInstanceSet::const_iterator i = instances.begin(); | |
46 i != instances.end(); ++i) | |
47 containers->insert((*i)->container()); | |
48 } | |
49 | |
50 WebConsoleMessage::Level LogLevelToWebLogLevel(PP_LogLevel level) { | |
51 switch (level) { | |
52 case PP_LOGLEVEL_TIP: | |
53 return WebConsoleMessage::LevelDebug; | |
54 case PP_LOGLEVEL_LOG: | |
55 return WebConsoleMessage::LevelLog; | |
56 case PP_LOGLEVEL_WARNING: | |
57 return WebConsoleMessage::LevelWarning; | |
58 case PP_LOGLEVEL_ERROR: | |
59 default: | |
60 return WebConsoleMessage::LevelError; | |
61 } | |
62 } | |
63 | |
64 WebConsoleMessage MakeLogMessage(PP_LogLevel level, | |
65 const std::string& source, | |
66 const std::string& message) { | |
67 std::string result = source; | |
68 if (!result.empty()) | |
69 result.append(": "); | |
70 result.append(message); | |
71 return WebConsoleMessage(LogLevelToWebLogLevel(level), | |
72 WebString(UTF8ToUTF16(result))); | |
73 } | |
74 | |
75 } // namespace | |
76 | |
77 HostGlobals* HostGlobals::host_globals_ = NULL; | |
78 | |
79 HostGlobals::HostGlobals() | |
80 : ::ppapi::PpapiGlobals(), | |
81 resource_tracker_(ResourceTracker::SINGLE_THREADED) { | |
82 DCHECK(!host_globals_); | |
83 host_globals_ = this; | |
84 } | |
85 | |
86 HostGlobals::HostGlobals( | |
87 ::ppapi::PpapiGlobals::PerThreadForTest per_thread_for_test) | |
88 : ::ppapi::PpapiGlobals(per_thread_for_test), | |
89 resource_tracker_(ResourceTracker::SINGLE_THREADED) { | |
90 DCHECK(!host_globals_); | |
91 } | |
92 | |
93 HostGlobals::~HostGlobals() { | |
94 DCHECK(host_globals_ == this || !host_globals_); | |
95 host_globals_ = NULL; | |
96 } | |
97 | |
98 ::ppapi::ResourceTracker* HostGlobals::GetResourceTracker() { | |
99 return &resource_tracker_; | |
100 } | |
101 | |
102 ::ppapi::VarTracker* HostGlobals::GetVarTracker() { | |
103 return &host_var_tracker_; | |
104 } | |
105 | |
106 ::ppapi::CallbackTracker* HostGlobals::GetCallbackTrackerForInstance( | |
107 PP_Instance instance) { | |
108 InstanceMap::iterator found = instance_map_.find(instance); | |
109 if (found == instance_map_.end()) | |
110 return NULL; | |
111 return found->second->module()->GetCallbackTracker().get(); | |
112 } | |
113 | |
114 ::ppapi::thunk::PPB_Instance_API* HostGlobals::GetInstanceAPI( | |
115 PP_Instance instance) { | |
116 // The InstanceAPI is just implemented by the PluginInstance object. | |
117 return GetInstance(instance); | |
118 } | |
119 | |
120 ::ppapi::thunk::ResourceCreationAPI* HostGlobals::GetResourceCreationAPI( | |
121 PP_Instance pp_instance) { | |
122 PluginInstanceImpl* instance = GetInstance(pp_instance); | |
123 if (!instance) | |
124 return NULL; | |
125 return &instance->resource_creation(); | |
126 } | |
127 | |
128 PP_Module HostGlobals::GetModuleForInstance(PP_Instance instance) { | |
129 PluginInstanceImpl* inst = GetInstance(instance); | |
130 if (!inst) | |
131 return 0; | |
132 return inst->module()->pp_module(); | |
133 } | |
134 | |
135 std::string HostGlobals::GetCmdLine() { | |
136 return CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
137 switches::kPpapiFlashArgs); | |
138 } | |
139 | |
140 void HostGlobals::PreCacheFontForFlash(const void* logfontw) { | |
141 // Not implemented in-process. | |
142 } | |
143 | |
144 base::Lock* HostGlobals::GetProxyLock() { | |
145 // We do not lock on the host side. | |
146 return NULL; | |
147 } | |
148 | |
149 void HostGlobals::LogWithSource(PP_Instance instance, | |
150 PP_LogLevel level, | |
151 const std::string& source, | |
152 const std::string& value) { | |
153 PluginInstanceImpl* instance_object = | |
154 HostGlobals::Get()->GetInstance(instance); | |
155 if (instance_object) { | |
156 instance_object->container()->element().document().frame()-> | |
157 addMessageToConsole(MakeLogMessage(level, source, value)); | |
158 } else { | |
159 BroadcastLogWithSource(0, level, source, value); | |
160 } | |
161 } | |
162 | |
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(); ++i) { | |
178 GetAllContainersForModule(i->second, &containers); | |
179 } | |
180 } | |
181 | |
182 WebConsoleMessage message = MakeLogMessage(level, source, value); | |
183 for (ContainerSet::iterator i = containers.begin(); | |
184 i != containers.end(); ++i) | |
185 (*i)->element().document().frame()->addMessageToConsole(message); | |
186 } | |
187 | |
188 base::TaskRunner* HostGlobals::GetFileTaskRunner(PP_Instance instance) { | |
189 scoped_refptr<PluginInstanceImpl> plugin_instance = GetInstance(instance); | |
190 DCHECK(plugin_instance.get()); | |
191 scoped_refptr<base::MessageLoopProxy> message_loop = | |
192 plugin_instance->delegate()->GetFileThreadMessageLoopProxy(); | |
193 return message_loop.get(); | |
194 } | |
195 | |
196 ::ppapi::MessageLoopShared* HostGlobals::GetCurrentMessageLoop() { | |
197 return NULL; | |
198 } | |
199 | |
200 PP_Module HostGlobals::AddModule(PluginModule* module) { | |
201 #ifndef NDEBUG | |
202 // Make sure we're not adding one more than once. | |
203 for (ModuleMap::const_iterator i = module_map_.begin(); | |
204 i != module_map_.end(); ++i) | |
205 DCHECK(i->second != module); | |
206 #endif | |
207 | |
208 // See AddInstance. | |
209 PP_Module new_module; | |
210 do { | |
211 new_module = MakeTypedId(static_cast<PP_Module>(base::RandUint64()), | |
212 ::ppapi::PP_ID_TYPE_MODULE); | |
213 } while (!new_module || | |
214 module_map_.find(new_module) != module_map_.end()); | |
215 module_map_[new_module] = module; | |
216 return new_module; | |
217 } | |
218 | |
219 void HostGlobals::ModuleDeleted(PP_Module module) { | |
220 DLOG_IF(ERROR, !CheckIdType(module, ::ppapi::PP_ID_TYPE_MODULE)) | |
221 << module << " is not a PP_Module."; | |
222 ModuleMap::iterator found = module_map_.find(module); | |
223 if (found == module_map_.end()) { | |
224 NOTREACHED(); | |
225 return; | |
226 } | |
227 module_map_.erase(found); | |
228 } | |
229 | |
230 PluginModule* HostGlobals::GetModule(PP_Module module) { | |
231 DLOG_IF(ERROR, !CheckIdType(module, ::ppapi::PP_ID_TYPE_MODULE)) | |
232 << module << " is not a PP_Module."; | |
233 ModuleMap::iterator found = module_map_.find(module); | |
234 if (found == module_map_.end()) | |
235 return NULL; | |
236 return found->second; | |
237 } | |
238 | |
239 PP_Instance HostGlobals::AddInstance(PluginInstanceImpl* instance) { | |
240 DCHECK(instance_map_.find(instance->pp_instance()) == instance_map_.end()); | |
241 | |
242 // Use a random number for the instance ID. This helps prevent some | |
243 // accidents. See also AddModule below. | |
244 // | |
245 // Need to make sure the random number isn't a duplicate or 0. | |
246 PP_Instance new_instance; | |
247 do { | |
248 new_instance = MakeTypedId(static_cast<PP_Instance>(base::RandUint64()), | |
249 ::ppapi::PP_ID_TYPE_INSTANCE); | |
250 } while (!new_instance || | |
251 instance_map_.find(new_instance) != instance_map_.end() || | |
252 !instance->module()->ReserveInstanceID(new_instance)); | |
253 | |
254 instance_map_[new_instance] = instance; | |
255 | |
256 resource_tracker_.DidCreateInstance(new_instance); | |
257 return new_instance; | |
258 } | |
259 | |
260 void HostGlobals::InstanceDeleted(PP_Instance instance) { | |
261 resource_tracker_.DidDeleteInstance(instance); | |
262 host_var_tracker_.DidDeleteInstance(instance); | |
263 instance_map_.erase(instance); | |
264 } | |
265 | |
266 void HostGlobals::InstanceCrashed(PP_Instance instance) { | |
267 resource_tracker_.DidDeleteInstance(instance); | |
268 host_var_tracker_.DidDeleteInstance(instance); | |
269 } | |
270 | |
271 PluginInstanceImpl* HostGlobals::GetInstance(PP_Instance instance) { | |
272 DLOG_IF(ERROR, !CheckIdType(instance, ::ppapi::PP_ID_TYPE_INSTANCE)) | |
273 << instance << " is not a PP_Instance."; | |
274 InstanceMap::iterator found = instance_map_.find(instance); | |
275 if (found == instance_map_.end()) | |
276 return NULL; | |
277 return found->second; | |
278 } | |
279 | |
280 bool HostGlobals::IsHostGlobals() const { | |
281 return true; | |
282 } | |
283 | |
284 } // namespace ppapi | |
285 } // namespace webkit | |
OLD | NEW |