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/npapi/webplugin_delegate_impl.h" | |
6 | |
7 #include <string> | |
8 #include <vector> | |
9 | |
10 #include "base/memory/scoped_ptr.h" | |
11 #include "base/message_loop/message_loop.h" | |
12 #include "base/process_util.h" | |
13 #include "base/strings/string_util.h" | |
14 #include "third_party/WebKit/public/web/WebInputEvent.h" | |
15 #include "webkit/glue/webkit_glue.h" | |
16 #include "webkit/plugins/npapi/plugin_instance.h" | |
17 #include "webkit/plugins/npapi/plugin_lib.h" | |
18 #include "webkit/plugins/npapi/plugin_stream_url.h" | |
19 #include "webkit/plugins/npapi/plugin_utils.h" | |
20 | |
21 using WebKit::WebCursorInfo; | |
22 using WebKit::WebInputEvent; | |
23 | |
24 namespace webkit { | |
25 namespace npapi { | |
26 | |
27 WebPluginDelegateImpl* WebPluginDelegateImpl::Create( | |
28 const base::FilePath& filename, | |
29 const std::string& mime_type) { | |
30 scoped_refptr<PluginLib> plugin_lib(PluginLib::CreatePluginLib(filename)); | |
31 if (plugin_lib.get() == NULL) | |
32 return NULL; | |
33 | |
34 NPError err = plugin_lib->NP_Initialize(); | |
35 if (err != NPERR_NO_ERROR) | |
36 return NULL; | |
37 | |
38 scoped_refptr<PluginInstance> instance(plugin_lib->CreateInstance(mime_type)); | |
39 return new WebPluginDelegateImpl(instance.get()); | |
40 } | |
41 | |
42 void WebPluginDelegateImpl::PluginDestroyed() { | |
43 if (handle_event_depth_) { | |
44 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | |
45 } else { | |
46 delete this; | |
47 } | |
48 } | |
49 | |
50 bool WebPluginDelegateImpl::Initialize( | |
51 const GURL& url, | |
52 const std::vector<std::string>& arg_names, | |
53 const std::vector<std::string>& arg_values, | |
54 WebPlugin* plugin, | |
55 bool load_manually) { | |
56 plugin_ = plugin; | |
57 | |
58 instance_->set_web_plugin(plugin_); | |
59 if (quirks_ & PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES) { | |
60 PluginLib* plugin_lib = instance()->plugin_lib(); | |
61 if (plugin_lib->instance_count() > 1) { | |
62 return false; | |
63 } | |
64 } | |
65 | |
66 if (quirks_ & PLUGIN_QUIRK_DIE_AFTER_UNLOAD) | |
67 webkit::npapi::SetForcefullyTerminatePluginProcess(true); | |
68 | |
69 int argc = 0; | |
70 scoped_ptr<char*[]> argn(new char*[arg_names.size()]); | |
71 scoped_ptr<char*[]> argv(new char*[arg_names.size()]); | |
72 for (size_t i = 0; i < arg_names.size(); ++i) { | |
73 if (quirks_ & PLUGIN_QUIRK_NO_WINDOWLESS && | |
74 LowerCaseEqualsASCII(arg_names[i], "windowlessvideo")) { | |
75 continue; | |
76 } | |
77 argn[argc] = const_cast<char*>(arg_names[i].c_str()); | |
78 argv[argc] = const_cast<char*>(arg_values[i].c_str()); | |
79 argc++; | |
80 } | |
81 | |
82 creation_succeeded_ = instance_->Start( | |
83 url, argn.get(), argv.get(), argc, load_manually); | |
84 if (!creation_succeeded_) { | |
85 VLOG(1) << "Couldn't start plug-in instance"; | |
86 return false; | |
87 } | |
88 | |
89 windowless_ = instance_->windowless(); | |
90 if (!windowless_) { | |
91 if (!WindowedCreatePlugin()) { | |
92 VLOG(1) << "Couldn't create windowed plug-in"; | |
93 return false; | |
94 } | |
95 } | |
96 | |
97 bool should_load = PlatformInitialize(); | |
98 | |
99 plugin_url_ = url.spec(); | |
100 | |
101 return should_load; | |
102 } | |
103 | |
104 void WebPluginDelegateImpl::DestroyInstance() { | |
105 if (instance_.get() && (instance_->npp()->ndata != NULL)) { | |
106 // Shutdown all streams before destroying so that | |
107 // no streams are left "in progress". Need to do | |
108 // this before calling set_web_plugin(NULL) because the | |
109 // instance uses the helper to do the download. | |
110 instance_->CloseStreams(); | |
111 | |
112 window_.window = NULL; | |
113 if (creation_succeeded_ && | |
114 !(quirks_ & PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY)) { | |
115 instance_->NPP_SetWindow(&window_); | |
116 } | |
117 | |
118 instance_->NPP_Destroy(); | |
119 | |
120 instance_->set_web_plugin(NULL); | |
121 | |
122 PlatformDestroyInstance(); | |
123 | |
124 instance_ = 0; | |
125 } | |
126 } | |
127 | |
128 void WebPluginDelegateImpl::UpdateGeometry( | |
129 const gfx::Rect& window_rect, | |
130 const gfx::Rect& clip_rect) { | |
131 | |
132 if (first_set_window_call_) { | |
133 first_set_window_call_ = false; | |
134 // Plugins like media player on Windows have a bug where in they handle the | |
135 // first geometry update and ignore the rest resulting in painting issues. | |
136 // This quirk basically ignores the first set window call sequence for | |
137 // these plugins and has been tested for Windows plugins only. | |
138 if (quirks_ & PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL) | |
139 return; | |
140 } | |
141 | |
142 if (windowless_) { | |
143 WindowlessUpdateGeometry(window_rect, clip_rect); | |
144 } else { | |
145 WindowedUpdateGeometry(window_rect, clip_rect); | |
146 } | |
147 } | |
148 | |
149 void WebPluginDelegateImpl::SetFocus(bool focused) { | |
150 DCHECK(windowless_); | |
151 // This is called when internal WebKit focus (the focused element on the page) | |
152 // changes, but plugins need to know about OS-level focus, so we have an extra | |
153 // layer of focus tracking. | |
154 // | |
155 // On Windows, historically browsers did not set focus events to windowless | |
156 // plugins when the toplevel window focus changes. Sending such focus events | |
157 // breaks full screen mode in Flash because it will come out of full screen | |
158 // mode when it loses focus, and its full screen window causes the browser to | |
159 // lose focus. | |
160 has_webkit_focus_ = focused; | |
161 #if !defined(OS_WIN) | |
162 if (containing_view_has_focus_) | |
163 SetPluginHasFocus(focused); | |
164 #else | |
165 SetPluginHasFocus(focused); | |
166 #endif | |
167 } | |
168 | |
169 void WebPluginDelegateImpl::SetPluginHasFocus(bool focused) { | |
170 if (focused == plugin_has_focus_) | |
171 return; | |
172 if (PlatformSetPluginHasFocus(focused)) | |
173 plugin_has_focus_ = focused; | |
174 } | |
175 | |
176 void WebPluginDelegateImpl::SetContentAreaHasFocus(bool has_focus) { | |
177 containing_view_has_focus_ = has_focus; | |
178 if (!windowless_) | |
179 return; | |
180 #if !defined(OS_WIN) // See SetFocus above. | |
181 SetPluginHasFocus(containing_view_has_focus_ && has_webkit_focus_); | |
182 #endif | |
183 } | |
184 | |
185 NPObject* WebPluginDelegateImpl::GetPluginScriptableObject() { | |
186 return instance_->GetPluginScriptableObject(); | |
187 } | |
188 | |
189 NPP WebPluginDelegateImpl::GetPluginNPP() { | |
190 return instance_->npp(); | |
191 } | |
192 | |
193 bool WebPluginDelegateImpl::GetFormValue(base::string16* value) { | |
194 return instance_->GetFormValue(value); | |
195 } | |
196 | |
197 void WebPluginDelegateImpl::DidFinishLoadWithReason(const GURL& url, | |
198 NPReason reason, | |
199 int notify_id) { | |
200 if (quirks_ & PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS && | |
201 reason == NPRES_NETWORK_ERR) { | |
202 // Flash needs this or otherwise it unloads the launching swf object. | |
203 reason = NPRES_DONE; | |
204 } | |
205 | |
206 instance()->DidFinishLoadWithReason(url, reason, notify_id); | |
207 } | |
208 | |
209 int WebPluginDelegateImpl::GetProcessId() { | |
210 // We are in process, so the plugin pid is this current process pid. | |
211 return base::GetCurrentProcId(); | |
212 } | |
213 | |
214 void WebPluginDelegateImpl::SendJavaScriptStream(const GURL& url, | |
215 const std::string& result, | |
216 bool success, | |
217 int notify_id) { | |
218 instance()->SendJavaScriptStream(url, result, success, notify_id); | |
219 } | |
220 | |
221 void WebPluginDelegateImpl::DidReceiveManualResponse( | |
222 const GURL& url, const std::string& mime_type, | |
223 const std::string& headers, uint32 expected_length, uint32 last_modified) { | |
224 if (!windowless_) { | |
225 // Calling NPP_WriteReady before NPP_SetWindow causes movies to not load in | |
226 // Flash. See http://b/issue?id=892174. | |
227 DCHECK(windowed_did_set_window_); | |
228 } | |
229 | |
230 instance()->DidReceiveManualResponse(url, mime_type, headers, | |
231 expected_length, last_modified); | |
232 } | |
233 | |
234 void WebPluginDelegateImpl::DidReceiveManualData(const char* buffer, | |
235 int length) { | |
236 instance()->DidReceiveManualData(buffer, length); | |
237 } | |
238 | |
239 void WebPluginDelegateImpl::DidFinishManualLoading() { | |
240 instance()->DidFinishManualLoading(); | |
241 } | |
242 | |
243 void WebPluginDelegateImpl::DidManualLoadFail() { | |
244 instance()->DidManualLoadFail(); | |
245 } | |
246 | |
247 base::FilePath WebPluginDelegateImpl::GetPluginPath() { | |
248 return instance()->plugin_lib()->plugin_info().path; | |
249 } | |
250 | |
251 void WebPluginDelegateImpl::WindowedUpdateGeometry( | |
252 const gfx::Rect& window_rect, | |
253 const gfx::Rect& clip_rect) { | |
254 if (WindowedReposition(window_rect, clip_rect) || | |
255 !windowed_did_set_window_) { | |
256 // Let the plugin know that it has been moved | |
257 WindowedSetWindow(); | |
258 } | |
259 } | |
260 | |
261 bool WebPluginDelegateImpl::HandleInputEvent( | |
262 const WebInputEvent& event, | |
263 WebCursor::CursorInfo* cursor_info) { | |
264 DCHECK(windowless_) << "events should only be received in windowless mode"; | |
265 | |
266 bool pop_user_gesture = false; | |
267 if (IsUserGesture(event)) { | |
268 pop_user_gesture = true; | |
269 instance()->PushPopupsEnabledState(true); | |
270 } | |
271 | |
272 bool handled = PlatformHandleInputEvent(event, cursor_info); | |
273 | |
274 if (pop_user_gesture) { | |
275 instance()->PopPopupsEnabledState(); | |
276 } | |
277 | |
278 return handled; | |
279 } | |
280 | |
281 bool WebPluginDelegateImpl::IsUserGesture(const WebInputEvent& event) { | |
282 switch (event.type) { | |
283 case WebInputEvent::MouseDown: | |
284 case WebInputEvent::MouseUp: | |
285 case WebInputEvent::KeyDown: | |
286 case WebInputEvent::KeyUp: | |
287 return true; | |
288 default: | |
289 return false; | |
290 } | |
291 return false; | |
292 } | |
293 | |
294 WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient( | |
295 unsigned long resource_id, const GURL& url, int notify_id) { | |
296 return instance()->CreateStream( | |
297 resource_id, url, std::string(), notify_id); | |
298 } | |
299 | |
300 WebPluginResourceClient* WebPluginDelegateImpl::CreateSeekableResourceClient( | |
301 unsigned long resource_id, int range_request_id) { | |
302 WebPluginResourceClient* resource_client = instance()->GetRangeRequest( | |
303 range_request_id); | |
304 if (resource_client) | |
305 resource_client->AddRangeRequestResourceId(resource_id); | |
306 return resource_client; | |
307 } | |
308 | |
309 } // namespace npapi | |
310 } // namespace webkit | |
OLD | NEW |