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 "content/child/npapi/webplugin_delegate_impl.h" | |
6 | |
7 #include <stddef.h> | |
8 | |
9 #include <string> | |
10 #include <vector> | |
11 | |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "base/message_loop/message_loop.h" | |
14 #include "base/process/process_handle.h" | |
15 #include "base/strings/string_util.h" | |
16 #include "base/strings/utf_string_conversions.h" | |
17 #include "build/build_config.h" | |
18 #include "content/child/npapi/plugin_instance.h" | |
19 #include "content/child/npapi/plugin_lib.h" | |
20 #include "third_party/WebKit/public/web/WebInputEvent.h" | |
21 | |
22 using blink::WebCursorInfo; | |
23 using blink::WebInputEvent; | |
24 | |
25 namespace content { | |
26 | |
27 WebPluginDelegateImpl* WebPluginDelegateImpl::Create( | |
28 WebPlugin* plugin, | |
29 const base::FilePath& filename, | |
30 const std::string& mime_type) { | |
31 scoped_refptr<PluginLib> plugin_lib(PluginLib::CreatePluginLib(filename)); | |
32 if (plugin_lib.get() == NULL) | |
33 return NULL; | |
34 | |
35 NPError err = plugin_lib->NP_Initialize(); | |
36 if (err != NPERR_NO_ERROR) | |
37 return NULL; | |
38 | |
39 scoped_refptr<PluginInstance> instance(plugin_lib->CreateInstance(mime_type)); | |
40 return new WebPluginDelegateImpl(plugin, instance.get()); | |
41 } | |
42 | |
43 void WebPluginDelegateImpl::PluginDestroyed() { | |
44 if (handle_event_depth_) { | |
45 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | |
46 } else { | |
47 delete this; | |
48 } | |
49 } | |
50 | |
51 bool WebPluginDelegateImpl::Initialize( | |
52 const GURL& url, | |
53 const std::vector<std::string>& arg_names, | |
54 const std::vector<std::string>& arg_values, | |
55 bool load_manually) { | |
56 if (instance_->plugin_lib()->plugin_info().name.find( | |
57 base::ASCIIToUTF16("QuickTime Plug-in")) != std::wstring::npos) { | |
58 quirks_ |= PLUGIN_QUIRK_COPY_STREAM_DATA; | |
59 } | |
60 | |
61 instance_->set_web_plugin(plugin_); | |
62 if (quirks_ & PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES) { | |
63 PluginLib* plugin_lib = instance()->plugin_lib(); | |
64 if (plugin_lib->instance_count() > 1) { | |
65 return false; | |
66 } | |
67 } | |
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 base::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 plugin instance"; | |
86 return false; | |
87 } | |
88 | |
89 bool should_load = PlatformInitialize(); | |
90 | |
91 plugin_url_ = url.spec(); | |
92 | |
93 return should_load; | |
94 } | |
95 | |
96 void WebPluginDelegateImpl::DestroyInstance() { | |
97 if (instance_.get() && (instance_->npp()->ndata != NULL)) { | |
98 window_.window = NULL; | |
99 if (creation_succeeded_ && | |
100 !(quirks_ & PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY)) { | |
101 instance_->NPP_SetWindow(&window_); | |
102 } | |
103 | |
104 instance_->NPP_Destroy(); | |
105 | |
106 instance_->set_web_plugin(NULL); | |
107 | |
108 PlatformDestroyInstance(); | |
109 | |
110 instance_ = 0; | |
111 } | |
112 } | |
113 | |
114 void WebPluginDelegateImpl::UpdateGeometry( | |
115 const gfx::Rect& window_rect, | |
116 const gfx::Rect& clip_rect) { | |
117 | |
118 if (first_set_window_call_) { | |
119 first_set_window_call_ = false; | |
120 // Plugins like media player on Windows have a bug where in they handle the | |
121 // first geometry update and ignore the rest resulting in painting issues. | |
122 // This quirk basically ignores the first set window call sequence for | |
123 // these plugins and has been tested for Windows plugins only. | |
124 if (quirks_ & PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL) | |
125 return; | |
126 } | |
127 | |
128 WindowlessUpdateGeometry(window_rect, clip_rect); | |
129 } | |
130 | |
131 void WebPluginDelegateImpl::SetFocus(bool focused) { | |
132 // This is called when internal WebKit focus (the focused element on the page) | |
133 // changes, but plugins need to know about OS-level focus, so we have an extra | |
134 // layer of focus tracking. | |
135 // | |
136 // On Windows, historically browsers did not set focus events to windowless | |
137 // plugins when the toplevel window focus changes. Sending such focus events | |
138 // breaks full screen mode in Flash because it will come out of full screen | |
139 // mode when it loses focus, and its full screen window causes the browser to | |
140 // lose focus. | |
141 has_webkit_focus_ = focused; | |
142 #if !defined(OS_WIN) | |
143 if (containing_view_has_focus_) | |
144 SetPluginHasFocus(focused); | |
145 #else | |
146 SetPluginHasFocus(focused); | |
147 #endif | |
148 } | |
149 | |
150 void WebPluginDelegateImpl::SetPluginHasFocus(bool focused) { | |
151 if (focused == plugin_has_focus_) | |
152 return; | |
153 if (PlatformSetPluginHasFocus(focused)) | |
154 plugin_has_focus_ = focused; | |
155 } | |
156 | |
157 void WebPluginDelegateImpl::SetContentAreaHasFocus(bool has_focus) { | |
158 containing_view_has_focus_ = has_focus; | |
159 #if !defined(OS_WIN) // See SetFocus above. | |
160 SetPluginHasFocus(containing_view_has_focus_ && has_webkit_focus_); | |
161 #endif | |
162 } | |
163 | |
164 int WebPluginDelegateImpl::GetProcessId() { | |
165 // We are in process, so the plugin pid is this current process pid. | |
166 return base::GetCurrentProcId(); | |
167 } | |
168 | |
169 base::FilePath WebPluginDelegateImpl::GetPluginPath() { | |
170 return instance()->plugin_lib()->plugin_info().path; | |
171 } | |
172 | |
173 bool WebPluginDelegateImpl::HandleInputEvent( | |
174 const WebInputEvent& event, | |
175 WebCursor::CursorInfo* cursor_info) { | |
176 bool pop_user_gesture = false; | |
177 if (IsUserGesture(event)) { | |
178 pop_user_gesture = true; | |
179 instance()->PushPopupsEnabledState(true); | |
180 } | |
181 | |
182 bool handled = PlatformHandleInputEvent(event, cursor_info); | |
183 | |
184 if (pop_user_gesture) { | |
185 instance()->PopPopupsEnabledState(); | |
186 } | |
187 | |
188 return handled; | |
189 } | |
190 | |
191 bool WebPluginDelegateImpl::IsUserGesture(const WebInputEvent& event) { | |
192 switch (event.type) { | |
193 case WebInputEvent::MouseDown: | |
194 case WebInputEvent::MouseUp: | |
195 case WebInputEvent::KeyDown: | |
196 case WebInputEvent::KeyUp: | |
197 return true; | |
198 default: | |
199 return false; | |
200 } | |
201 } | |
202 | |
203 } // namespace content | |
OLD | NEW |