Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(553)

Side by Side Diff: content/child/npapi/webplugin_delegate_impl_win.cc

Issue 1851093005: Remove content/child/npapi (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@remove_combined_01_02
Patch Set: rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 <stdint.h>
8 #include <string.h>
9
10 #include <map>
11 #include <set>
12 #include <string>
13 #include <vector>
14
15 #include "base/bind.h"
16 #include "base/compiler_specific.h"
17 #include "base/lazy_instance.h"
18 #include "base/macros.h"
19 #include "base/memory/scoped_ptr.h"
20 #include "base/message_loop/message_loop.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/synchronization/lock.h"
24 #include "base/version.h"
25 #include "base/win/windows_version.h"
26 #include "content/child/npapi/plugin_instance.h"
27 #include "content/child/npapi/plugin_lib.h"
28 #include "content/child/npapi/webplugin.h"
29 #include "content/common/cursors/webcursor.h"
30 #include "content/common/plugin_constants_win.h"
31 #include "content/public/common/content_constants.h"
32 #include "skia/ext/platform_canvas.h"
33 #include "third_party/WebKit/public/web/WebInputEvent.h"
34 #include "ui/gfx/win/dpi.h"
35 #include "ui/gfx/win/hwnd_util.h"
36
37 using blink::WebKeyboardEvent;
38 using blink::WebInputEvent;
39 using blink::WebMouseEvent;
40
41 namespace content {
42
43 namespace {
44
45 // http://crbug.com/16114
46 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow
47 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL.
48 // Doing so allows removing NPP_SetWindow call during painting a windowless
49 // plugin, which otherwise could trigger layout change while painting by
50 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes.
51 // TODO(dglazkov): If this approach doesn't produce regressions, move class to
52 // webplugin_delegate_impl.h and implement for other platforms.
53 class DrawableContextEnforcer {
54 public:
55 explicit DrawableContextEnforcer(NPWindow* window)
56 : window_(window),
57 disposable_dc_(window && !window->window) {
58 // If NPWindow is NULL, create a device context with monochrome 1x1 surface
59 // and stuff it to NPWindow.
60 if (disposable_dc_)
61 window_->window = CreateCompatibleDC(NULL);
62 }
63
64 ~DrawableContextEnforcer() {
65 if (!disposable_dc_)
66 return;
67
68 DeleteDC(static_cast<HDC>(window_->window));
69 window_->window = NULL;
70 }
71
72 private:
73 NPWindow* window_;
74 bool disposable_dc_;
75 };
76
77 } // namespace
78
79 WebPluginDelegateImpl::WebPluginDelegateImpl(WebPlugin* plugin,
80 PluginInstance* instance)
81 : plugin_(plugin),
82 instance_(instance),
83 quirks_(0),
84 handle_event_depth_(0),
85 first_set_window_call_(true),
86 plugin_has_focus_(false),
87 has_webkit_focus_(false),
88 containing_view_has_focus_(true),
89 creation_succeeded_(false),
90 user_gesture_msg_factory_(this) {
91 memset(&window_, 0, sizeof(window_));
92 }
93
94 WebPluginDelegateImpl::~WebPluginDelegateImpl() {
95 DestroyInstance();
96 }
97
98 bool WebPluginDelegateImpl::PlatformInitialize() {
99 return true;
100 }
101
102 void WebPluginDelegateImpl::PlatformDestroyInstance() {
103 }
104
105 void WebPluginDelegateImpl::Paint(SkCanvas* canvas, const gfx::Rect& rect) {
106 if (skia::SupportsPlatformPaint(canvas)) {
107 skia::ScopedPlatformPaint scoped_platform_paint(canvas);
108 HDC hdc = scoped_platform_paint.GetPlatformSurface();
109 WindowlessPaint(hdc, rect);
110 }
111 }
112
113 // Returns true if the message passed in corresponds to a user gesture.
114 static bool IsUserGestureMessage(unsigned int message) {
115 switch (message) {
116 case WM_LBUTTONDOWN:
117 case WM_LBUTTONUP:
118 case WM_RBUTTONDOWN:
119 case WM_RBUTTONUP:
120 case WM_MBUTTONDOWN:
121 case WM_MBUTTONUP:
122 case WM_KEYDOWN:
123 case WM_KEYUP:
124 return true;
125
126 default:
127 break;
128 }
129
130 return false;
131 }
132
133 void WebPluginDelegateImpl::WindowlessUpdateGeometry(
134 const gfx::Rect& window_rect,
135 const gfx::Rect& clip_rect) {
136 bool window_rect_changed = (window_rect_ != window_rect);
137 // Only resend to the instance if the geometry has changed.
138 if (!window_rect_changed && clip_rect == clip_rect_)
139 return;
140
141 clip_rect_ = clip_rect;
142 window_rect_ = window_rect;
143
144 WindowlessSetWindow();
145
146 if (window_rect_changed) {
147 WINDOWPOS win_pos = {0};
148 win_pos.x = window_rect_.x();
149 win_pos.y = window_rect_.y();
150 win_pos.cx = window_rect_.width();
151 win_pos.cy = window_rect_.height();
152
153 NPEvent pos_changed_event;
154 pos_changed_event.event = WM_WINDOWPOSCHANGED;
155 pos_changed_event.wParam = 0;
156 pos_changed_event.lParam = reinterpret_cast<uintptr_t>(&win_pos);
157
158 instance()->NPP_HandleEvent(&pos_changed_event);
159 }
160 }
161
162 void WebPluginDelegateImpl::WindowlessPaint(HDC hdc,
163 const gfx::Rect& damage_rect) {
164 DCHECK(hdc);
165
166 RECT damage_rect_win;
167 damage_rect_win.left = damage_rect.x(); // + window_rect_.x();
168 damage_rect_win.top = damage_rect.y(); // + window_rect_.y();
169 damage_rect_win.right = damage_rect_win.left + damage_rect.width();
170 damage_rect_win.bottom = damage_rect_win.top + damage_rect.height();
171
172 // Save away the old HDC as this could be a nested invocation.
173 void* old_dc = window_.window;
174 window_.window = hdc;
175
176 NPEvent paint_event;
177 paint_event.event = WM_PAINT;
178 paint_event.wParam = PtrToUlong(hdc);
179 paint_event.lParam = reinterpret_cast<uintptr_t>(&damage_rect_win);
180 instance()->NPP_HandleEvent(&paint_event);
181 window_.window = old_dc;
182 }
183
184 void WebPluginDelegateImpl::WindowlessSetWindow() {
185 if (!instance())
186 return;
187
188 if (window_rect_.IsEmpty()) // wait for geometry to be set.
189 return;
190
191 window_.clipRect.top = clip_rect_.y();
192 window_.clipRect.left = clip_rect_.x();
193 window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height();
194 window_.clipRect.right = clip_rect_.x() + clip_rect_.width();
195 window_.height = window_rect_.height();
196 window_.width = window_rect_.width();
197 window_.x = window_rect_.x();
198 window_.y = window_rect_.y();
199 window_.type = NPWindowTypeDrawable;
200 DrawableContextEnforcer enforcer(&window_);
201
202 NPError err = instance()->NPP_SetWindow(&window_);
203 DCHECK(err == NPERR_NO_ERROR);
204 }
205
206 bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) {
207 NPEvent focus_event;
208 focus_event.event = focused ? WM_SETFOCUS : WM_KILLFOCUS;
209 focus_event.wParam = 0;
210 focus_event.lParam = 0;
211
212 instance()->NPP_HandleEvent(&focus_event);
213 return true;
214 }
215
216 static bool NPEventFromWebMouseEvent(const WebMouseEvent& event,
217 NPEvent* np_event) {
218 np_event->lParam =
219 static_cast<uint32_t>(MAKELPARAM(event.windowX, event.windowY));
220 np_event->wParam = 0;
221
222 if (event.modifiers & WebInputEvent::ControlKey)
223 np_event->wParam |= MK_CONTROL;
224 if (event.modifiers & WebInputEvent::ShiftKey)
225 np_event->wParam |= MK_SHIFT;
226 if (event.modifiers & WebInputEvent::LeftButtonDown)
227 np_event->wParam |= MK_LBUTTON;
228 if (event.modifiers & WebInputEvent::MiddleButtonDown)
229 np_event->wParam |= MK_MBUTTON;
230 if (event.modifiers & WebInputEvent::RightButtonDown)
231 np_event->wParam |= MK_RBUTTON;
232
233 switch (event.type) {
234 case WebInputEvent::MouseMove:
235 case WebInputEvent::MouseLeave:
236 case WebInputEvent::MouseEnter:
237 np_event->event = WM_MOUSEMOVE;
238 return true;
239 case WebInputEvent::MouseDown:
240 switch (event.button) {
241 case WebMouseEvent::ButtonLeft:
242 np_event->event = WM_LBUTTONDOWN;
243 break;
244 case WebMouseEvent::ButtonMiddle:
245 np_event->event = WM_MBUTTONDOWN;
246 break;
247 case WebMouseEvent::ButtonRight:
248 np_event->event = WM_RBUTTONDOWN;
249 break;
250 case WebMouseEvent::ButtonNone:
251 break;
252 }
253 return true;
254 case WebInputEvent::MouseUp:
255 switch (event.button) {
256 case WebMouseEvent::ButtonLeft:
257 np_event->event = WM_LBUTTONUP;
258 break;
259 case WebMouseEvent::ButtonMiddle:
260 np_event->event = WM_MBUTTONUP;
261 break;
262 case WebMouseEvent::ButtonRight:
263 np_event->event = WM_RBUTTONUP;
264 break;
265 case WebMouseEvent::ButtonNone:
266 break;
267 }
268 return true;
269 default:
270 NOTREACHED();
271 return false;
272 }
273 }
274
275 static bool NPEventFromWebKeyboardEvent(const WebKeyboardEvent& event,
276 NPEvent* np_event) {
277 np_event->wParam = event.windowsKeyCode;
278
279 switch (event.type) {
280 case WebInputEvent::KeyDown:
281 np_event->event = WM_KEYDOWN;
282 np_event->lParam = 0;
283 return true;
284 case WebInputEvent::Char:
285 np_event->event = WM_CHAR;
286 np_event->lParam = 0;
287 return true;
288 case WebInputEvent::KeyUp:
289 np_event->event = WM_KEYUP;
290 np_event->lParam = 0x8000;
291 return true;
292 default:
293 NOTREACHED();
294 return false;
295 }
296 }
297
298 static bool NPEventFromWebInputEvent(const WebInputEvent& event,
299 NPEvent* np_event) {
300 switch (event.type) {
301 case WebInputEvent::MouseMove:
302 case WebInputEvent::MouseLeave:
303 case WebInputEvent::MouseEnter:
304 case WebInputEvent::MouseDown:
305 case WebInputEvent::MouseUp:
306 if (event.size < sizeof(WebMouseEvent)) {
307 NOTREACHED();
308 return false;
309 }
310 return NPEventFromWebMouseEvent(
311 *static_cast<const WebMouseEvent*>(&event), np_event);
312 case WebInputEvent::KeyDown:
313 case WebInputEvent::Char:
314 case WebInputEvent::KeyUp:
315 if (event.size < sizeof(WebKeyboardEvent)) {
316 NOTREACHED();
317 return false;
318 }
319 return NPEventFromWebKeyboardEvent(
320 *static_cast<const WebKeyboardEvent*>(&event), np_event);
321 default:
322 return false;
323 }
324 }
325
326 bool WebPluginDelegateImpl::PlatformHandleInputEvent(
327 const WebInputEvent& event, WebCursor::CursorInfo* cursor_info) {
328 DCHECK(cursor_info != NULL);
329
330 NPEvent np_event;
331 if (!NPEventFromWebInputEvent(event, &np_event)) {
332 return false;
333 }
334
335 handle_event_depth_++;
336
337 bool popups_enabled = false;
338
339 if (IsUserGestureMessage(np_event.event)) {
340 instance()->PushPopupsEnabledState(true);
341 popups_enabled = true;
342 }
343
344 bool ret = instance()->NPP_HandleEvent(&np_event) != 0;
345
346 if (popups_enabled) {
347 instance()->PopPopupsEnabledState();
348 }
349
350 // Flash and SilverLight always return false, even when they swallow the
351 // event. Flash does this because it passes the event to its window proc,
352 // which is supposed to return 0 if an event was handled. There are few
353 // exceptions, such as IME, where it sometimes returns true.
354 ret = true;
355
356 if (np_event.event == WM_MOUSEMOVE) {
357 current_windowless_cursor_.InitFromExternalCursor(GetCursor());
358 // Snag a reference to the current cursor ASAP in case the plugin modified
359 // it. There is a nasty race condition here with the multiprocess browser
360 // as someone might be setting the cursor in the main process as well.
361 current_windowless_cursor_.GetCursorInfo(cursor_info);
362 }
363
364 handle_event_depth_--;
365
366 return ret;
367 }
368
369 } // namespace content
OLDNEW
« no previous file with comments | « content/child/npapi/webplugin_delegate_impl_mac.mm ('k') | content/child/npapi/webplugin_resource_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698