OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/plugins/npapi/webplugin_delegate_impl.h" | 5 #include "webkit/plugins/npapi/webplugin_delegate_impl.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 LAZY_INSTANCE_INITIALIZER; | 85 LAZY_INSTANCE_INITIALIZER; |
86 | 86 |
87 // Helper object for patching the RegEnumKeyExW API. | 87 // Helper object for patching the RegEnumKeyExW API. |
88 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w = | 88 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w = |
89 LAZY_INSTANCE_INITIALIZER; | 89 LAZY_INSTANCE_INITIALIZER; |
90 | 90 |
91 // Helper object for patching the GetProcAddress API. | 91 // Helper object for patching the GetProcAddress API. |
92 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_get_proc_address = | 92 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_get_proc_address = |
93 LAZY_INSTANCE_INITIALIZER; | 93 LAZY_INSTANCE_INITIALIZER; |
94 | 94 |
95 // Helper object for patching the GetKeyState API. | |
96 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_get_key_state = | |
97 LAZY_INSTANCE_INITIALIZER; | |
98 | |
99 // Saved key state globals and helper access functions. | |
100 SHORT (WINAPI *g_iat_orig_get_key_state)(int vkey); | |
101 typedef size_t SavedStateType; | |
102 const size_t kBitsPerType = sizeof(SavedStateType) * 8; | |
103 // Bit array of key state corresponding to virtual key index (0=up, 1=down). | |
104 SavedStateType g_saved_key_state[256 / kBitsPerType]; | |
105 | |
106 bool GetSavedKeyState(WPARAM vkey) { | |
107 CHECK_LT(vkey, kBitsPerType * sizeof(g_saved_key_state)); | |
108 if (g_saved_key_state[vkey / kBitsPerType] & 1 << (vkey % kBitsPerType)) | |
109 return true; | |
110 return false; | |
111 } | |
112 | |
113 void SetSavedKeyState(WPARAM vkey) { | |
114 CHECK_LT(vkey, kBitsPerType * sizeof(g_saved_key_state)); | |
115 // Cache the key state only for keys blocked by UIPI. | |
116 if (g_iat_orig_get_key_state(vkey) == 0) | |
117 g_saved_key_state[vkey / kBitsPerType] |= 1 << (vkey % kBitsPerType); | |
118 } | |
119 | |
120 void UnsetSavedKeyState(WPARAM vkey) { | |
121 CHECK_LT(vkey, kBitsPerType * sizeof(g_saved_key_state)); | |
122 g_saved_key_state[vkey / kBitsPerType] &= ~(1 << (vkey % kBitsPerType)); | |
123 } | |
124 | |
125 void ClearSavedKeyState() { | |
126 memset(g_saved_key_state, 0, sizeof(g_saved_key_state)); | |
127 } | |
128 | |
129 // Helper objects for patching VirtualQuery, VirtualProtect. | |
130 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_virtual_protect = | |
131 LAZY_INSTANCE_INITIALIZER; | |
132 BOOL (WINAPI *g_iat_orig_virtual_protect)(LPVOID address, | |
133 SIZE_T size, | |
134 DWORD new_protect, | |
135 PDWORD old_protect); | |
136 | |
137 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_virtual_free = | |
138 LAZY_INSTANCE_INITIALIZER; | |
139 BOOL (WINAPI *g_iat_orig_virtual_free)(LPVOID address, | |
140 SIZE_T size, | |
141 DWORD free_type); | |
142 | |
143 const DWORD kExecPageMask = PAGE_EXECUTE_READ; | |
144 static volatile intptr_t g_max_exec_mem_size; | |
145 static scoped_ptr<base::Lock> g_exec_mem_lock; | |
146 | |
147 void UpdateExecMemSize(intptr_t size) { | |
148 base::AutoLock locked(*g_exec_mem_lock); | |
149 | |
150 static intptr_t s_exec_mem_size = 0; | |
151 | |
152 // Floor to zero since shutdown may unmap pages created before our hooks. | |
153 s_exec_mem_size = std::max(0, s_exec_mem_size + size); | |
154 if (s_exec_mem_size > g_max_exec_mem_size) | |
155 g_max_exec_mem_size = s_exec_mem_size; | |
156 } | |
157 | |
158 // http://crbug.com/16114 | 95 // http://crbug.com/16114 |
159 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow | 96 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow |
160 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. | 97 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. |
161 // Doing so allows removing NPP_SetWindow call during painting a windowless | 98 // Doing so allows removing NPP_SetWindow call during painting a windowless |
162 // plugin, which otherwise could trigger layout change while painting by | 99 // plugin, which otherwise could trigger layout change while painting by |
163 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes. | 100 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes. |
164 // TODO(dglazkov): If this approach doesn't produce regressions, move class to | 101 // TODO(dglazkov): If this approach doesn't produce regressions, move class to |
165 // webplugin_delegate_impl.h and implement for other platforms. | 102 // webplugin_delegate_impl.h and implement for other platforms. |
166 class DrawableContextEnforcer { | 103 class DrawableContextEnforcer { |
167 public: | 104 public: |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 int code, WPARAM wParam, LPARAM lParam) { | 267 int code, WPARAM wParam, LPARAM lParam) { |
331 if (code == HC_ACTION) { | 268 if (code == HC_ACTION) { |
332 MOUSEHOOKSTRUCT* hook_struct = reinterpret_cast<MOUSEHOOKSTRUCT*>(lParam); | 269 MOUSEHOOKSTRUCT* hook_struct = reinterpret_cast<MOUSEHOOKSTRUCT*>(lParam); |
333 if (hook_struct) | 270 if (hook_struct) |
334 HandleCaptureForMessage(hook_struct->hwnd, wParam); | 271 HandleCaptureForMessage(hook_struct->hwnd, wParam); |
335 } | 272 } |
336 | 273 |
337 return CallNextHookEx(NULL, code, wParam, lParam); | 274 return CallNextHookEx(NULL, code, wParam, lParam); |
338 } | 275 } |
339 | 276 |
340 // In addition to the key state we maintain, we also mask in the original | |
341 // return value. This is done because system keys (e.g. tab, enter, shift) | |
342 // and toggles (e.g. capslock, numlock) don't ever seem to be blocked. | |
343 SHORT WINAPI WebPluginDelegateImpl::GetKeyStatePatch(int vkey) { | |
344 if (GetSavedKeyState(vkey)) | |
345 return g_iat_orig_get_key_state(vkey) | 0x8000; | |
346 return g_iat_orig_get_key_state(vkey); | |
347 } | |
348 | |
349 // We need to track RX memory usage in plugins to prevent JIT spraying attacks. | |
350 // This is done by hooking VirtualProtect and VirtualFree. | |
351 BOOL WINAPI WebPluginDelegateImpl::VirtualProtectPatch(LPVOID address, | |
352 SIZE_T size, | |
353 DWORD new_protect, | |
354 PDWORD old_protect) { | |
355 if (g_iat_orig_virtual_protect(address, size, new_protect, old_protect)) { | |
356 bool is_exec = new_protect == kExecPageMask; | |
357 bool was_exec = *old_protect == kExecPageMask; | |
358 if (is_exec && !was_exec) { | |
359 UpdateExecMemSize(static_cast<intptr_t>(size)); | |
360 } else if (!is_exec && was_exec) { | |
361 UpdateExecMemSize(-(static_cast<intptr_t>(size))); | |
362 } | |
363 | |
364 return TRUE; | |
365 } | |
366 | |
367 return FALSE; | |
368 } | |
369 | |
370 BOOL WINAPI WebPluginDelegateImpl::VirtualFreePatch(LPVOID address, | |
371 SIZE_T size, | |
372 DWORD free_type) { | |
373 MEMORY_BASIC_INFORMATION mem_info; | |
374 if (::VirtualQuery(address, &mem_info, sizeof(mem_info))) { | |
375 size_t exec_size = 0; | |
376 void* base_address = mem_info.AllocationBase; | |
377 do { | |
378 if (mem_info.Protect == kExecPageMask) | |
379 exec_size += mem_info.RegionSize; | |
380 BYTE* next = reinterpret_cast<BYTE*>(mem_info.BaseAddress) + | |
381 mem_info.RegionSize; | |
382 if (!::VirtualQuery(next, &mem_info, sizeof(mem_info))) | |
383 break; | |
384 } while (base_address == mem_info.AllocationBase); | |
385 | |
386 if (exec_size) | |
387 UpdateExecMemSize(-(static_cast<intptr_t>(exec_size))); | |
388 } | |
389 | |
390 return g_iat_orig_virtual_free(address, size, free_type); | |
391 } | |
392 | |
393 WebPluginDelegateImpl::WebPluginDelegateImpl( | 277 WebPluginDelegateImpl::WebPluginDelegateImpl( |
394 gfx::PluginWindowHandle containing_view, | 278 gfx::PluginWindowHandle containing_view, |
395 PluginInstance* instance) | 279 PluginInstance* instance) |
396 : parent_(containing_view), | 280 : parent_(containing_view), |
397 instance_(instance), | 281 instance_(instance), |
398 quirks_(0), | 282 quirks_(0), |
399 plugin_(NULL), | 283 plugin_(NULL), |
400 windowless_(false), | 284 windowless_(false), |
401 windowed_handle_(NULL), | 285 windowed_handle_(NULL), |
402 windowed_did_set_window_(false), | 286 windowed_did_set_window_(false), |
403 plugin_wnd_proc_(NULL), | 287 plugin_wnd_proc_(NULL), |
404 last_message_(0), | 288 last_message_(0), |
405 is_calling_wndproc(false), | 289 is_calling_wndproc(false), |
406 dummy_window_for_activation_(NULL), | 290 dummy_window_for_activation_(NULL), |
407 parent_proxy_window_(NULL), | |
408 handle_event_message_filter_hook_(NULL), | 291 handle_event_message_filter_hook_(NULL), |
409 handle_event_pump_messages_event_(NULL), | 292 handle_event_pump_messages_event_(NULL), |
410 user_gesture_message_posted_(false), | 293 user_gesture_message_posted_(false), |
411 ALLOW_THIS_IN_INITIALIZER_LIST(user_gesture_msg_factory_(this)), | 294 ALLOW_THIS_IN_INITIALIZER_LIST(user_gesture_msg_factory_(this)), |
412 handle_event_depth_(0), | 295 handle_event_depth_(0), |
413 mouse_hook_(NULL), | 296 mouse_hook_(NULL), |
414 first_set_window_call_(true), | 297 first_set_window_call_(true), |
415 plugin_has_focus_(false), | 298 plugin_has_focus_(false), |
416 has_webkit_focus_(false), | 299 has_webkit_focus_(false), |
417 containing_view_has_focus_(true), | 300 containing_view_has_focus_(true), |
418 creation_succeeded_(false) { | 301 creation_succeeded_(false) { |
419 memset(&window_, 0, sizeof(window_)); | 302 memset(&window_, 0, sizeof(window_)); |
420 | 303 |
421 const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info(); | 304 const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info(); |
422 std::wstring filename = | 305 std::wstring filename = |
423 StringToLowerASCII(plugin_info.path.BaseName().value()); | 306 StringToLowerASCII(plugin_info.path.BaseName().value()); |
424 | 307 |
425 if (instance_->mime_type() == kFlashPluginSwfMimeType || | 308 if (instance_->mime_type() == kFlashPluginSwfMimeType || |
426 filename == kFlashPlugin) { | 309 filename == kFlashPlugin) { |
427 // Flash only requests windowless plugins if we return a Mozilla user | 310 // Flash only requests windowless plugins if we return a Mozilla user |
428 // agent. | 311 // agent. |
429 instance_->set_use_mozilla_user_agent(); | 312 instance_->set_use_mozilla_user_agent(); |
430 quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; | 313 quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; |
431 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; | 314 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; |
432 quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS; | 315 quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS; |
433 quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE; | 316 quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE; |
434 if (filename == kBuiltinFlashPlugin && | |
435 base::win::GetVersion() >= base::win::VERSION_VISTA) { | |
436 quirks_ |= PLUGIN_QUIRK_REPARENT_IN_BROWSER | | |
437 PLUGIN_QUIRK_PATCH_GETKEYSTATE | | |
438 PLUGIN_QUIRK_PATCH_VM_API; | |
439 } | |
440 quirks_ |= PLUGIN_QUIRK_EMULATE_IME; | 317 quirks_ |= PLUGIN_QUIRK_EMULATE_IME; |
441 } else if (filename == kAcrobatReaderPlugin) { | 318 } else if (filename == kAcrobatReaderPlugin) { |
442 // Check for the version number above or equal 9. | 319 // Check for the version number above or equal 9. |
443 int major_version = GetPluginMajorVersion(plugin_info); | 320 int major_version = GetPluginMajorVersion(plugin_info); |
444 if (major_version >= 9) { | 321 if (major_version >= 9) { |
445 quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; | 322 quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; |
446 // 9.2 needs this. | 323 // 9.2 needs this. |
447 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; | 324 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; |
448 } | 325 } |
449 quirks_ |= PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS; | 326 quirks_ |= PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 } else if (plugin_info.name.find(L"DivX Web Player") != | 363 } else if (plugin_info.name.find(L"DivX Web Player") != |
487 std::wstring::npos) { | 364 std::wstring::npos) { |
488 // The divx plugin sets its size on the first NPP_SetWindow call and never | 365 // The divx plugin sets its size on the first NPP_SetWindow call and never |
489 // updates its size. We should call the underlying NPP_SetWindow only when | 366 // updates its size. We should call the underlying NPP_SetWindow only when |
490 // we have the correct size. | 367 // we have the correct size. |
491 quirks_ |= PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL; | 368 quirks_ |= PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL; |
492 } | 369 } |
493 } | 370 } |
494 | 371 |
495 WebPluginDelegateImpl::~WebPluginDelegateImpl() { | 372 WebPluginDelegateImpl::~WebPluginDelegateImpl() { |
496 if (::IsWindow(dummy_window_for_activation_)) { | 373 if (::IsWindow(dummy_window_for_activation_)) |
497 // Sandboxed Flash stacks two dummy windows to prevent UIPI failures | 374 ::DestroyWindow(dummy_window_for_activation_); |
498 if (::IsWindow(parent_proxy_window_)) | |
499 ::DestroyWindow(parent_proxy_window_); | |
500 else | |
501 ::DestroyWindow(dummy_window_for_activation_); | |
502 } | |
503 | 375 |
504 DestroyInstance(); | 376 DestroyInstance(); |
505 | 377 |
506 if (!windowless_) | 378 if (!windowless_) |
507 WindowedDestroyWindow(); | 379 WindowedDestroyWindow(); |
508 | 380 |
509 if (handle_event_pump_messages_event_) { | 381 if (handle_event_pump_messages_event_) { |
510 CloseHandle(handle_event_pump_messages_event_); | 382 CloseHandle(handle_event_pump_messages_event_); |
511 } | 383 } |
512 } | 384 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 // and use them to retrieve IME data. We add a patch to this function so we | 454 // and use them to retrieve IME data. We add a patch to this function so we |
583 // can dispatch these IMM32 calls to the WebPluginIMEWin class, which emulates | 455 // can dispatch these IMM32 calls to the WebPluginIMEWin class, which emulates |
584 // IMM32 functions for Flash. | 456 // IMM32 functions for Flash. |
585 if (!g_iat_patch_get_proc_address.Pointer()->is_patched() && | 457 if (!g_iat_patch_get_proc_address.Pointer()->is_patched() && |
586 (quirks_ & PLUGIN_QUIRK_EMULATE_IME)) { | 458 (quirks_ & PLUGIN_QUIRK_EMULATE_IME)) { |
587 g_iat_patch_get_proc_address.Pointer()->Patch( | 459 g_iat_patch_get_proc_address.Pointer()->Patch( |
588 GetPluginPath().value().c_str(), "kernel32.dll", "GetProcAddress", | 460 GetPluginPath().value().c_str(), "kernel32.dll", "GetProcAddress", |
589 GetProcAddressPatch); | 461 GetProcAddressPatch); |
590 } | 462 } |
591 | 463 |
592 // Under UIPI the key state does not get forwarded properly to the child | |
593 // plugin window. So, instead we track the key state manually and intercept | |
594 // GetKeyState. | |
595 if ((quirks_ & PLUGIN_QUIRK_PATCH_GETKEYSTATE) && | |
596 !g_iat_patch_get_key_state.Pointer()->is_patched()) { | |
597 g_iat_orig_get_key_state = ::GetKeyState; | |
598 g_iat_patch_get_key_state.Pointer()->Patch( | |
599 L"gcswf32.dll", "user32.dll", "GetKeyState", | |
600 WebPluginDelegateImpl::GetKeyStatePatch); | |
601 } | |
602 | |
603 // Hook the VM calls so we can track the amount of executable memory being | |
604 // allocated by Flash (and potentially other plugins). | |
605 if (quirks_ & PLUGIN_QUIRK_PATCH_VM_API) { | |
606 if (!g_exec_mem_lock.get()) | |
607 g_exec_mem_lock.reset(new base::Lock()); | |
608 | |
609 if (!g_iat_patch_virtual_protect.Pointer()->is_patched()) { | |
610 g_iat_orig_virtual_protect = ::VirtualProtect; | |
611 g_iat_patch_virtual_protect.Pointer()->Patch( | |
612 L"gcswf32.dll", "kernel32.dll", "VirtualProtect", | |
613 WebPluginDelegateImpl::VirtualProtectPatch); | |
614 } | |
615 if (!g_iat_patch_virtual_free.Pointer()->is_patched()) { | |
616 g_iat_orig_virtual_free = ::VirtualFree; | |
617 g_iat_patch_virtual_free.Pointer()->Patch( | |
618 L"gcswf32.dll", "kernel32.dll", "VirtualFree", | |
619 WebPluginDelegateImpl::VirtualFreePatch); | |
620 } | |
621 } | |
622 | |
623 return true; | 464 return true; |
624 } | 465 } |
625 | 466 |
626 void WebPluginDelegateImpl::PlatformDestroyInstance() { | 467 void WebPluginDelegateImpl::PlatformDestroyInstance() { |
627 if (!instance_->plugin_lib()) | 468 if (!instance_->plugin_lib()) |
628 return; | 469 return; |
629 | 470 |
630 // Unpatch if this is the last plugin instance. | 471 // Unpatch if this is the last plugin instance. |
631 if (instance_->plugin_lib()->instance_count() != 1) | 472 if (instance_->plugin_lib()->instance_count() != 1) |
632 return; | 473 return; |
633 | 474 |
634 // Pass back the stats for max executable memory. | |
635 if (quirks_ & PLUGIN_QUIRK_PATCH_VM_API) { | |
636 plugin_->ReportExecutableMemory(g_max_exec_mem_size); | |
637 g_max_exec_mem_size = 0; | |
638 } | |
639 | |
640 if (g_iat_patch_set_cursor.Pointer()->is_patched()) | 475 if (g_iat_patch_set_cursor.Pointer()->is_patched()) |
641 g_iat_patch_set_cursor.Pointer()->Unpatch(); | 476 g_iat_patch_set_cursor.Pointer()->Unpatch(); |
642 | 477 |
643 if (g_iat_patch_track_popup_menu.Pointer()->is_patched()) | 478 if (g_iat_patch_track_popup_menu.Pointer()->is_patched()) |
644 g_iat_patch_track_popup_menu.Pointer()->Unpatch(); | 479 g_iat_patch_track_popup_menu.Pointer()->Unpatch(); |
645 | 480 |
646 if (g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) | 481 if (g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) |
647 g_iat_patch_reg_enum_key_ex_w.Pointer()->Unpatch(); | 482 g_iat_patch_reg_enum_key_ex_w.Pointer()->Unpatch(); |
648 | 483 |
649 if (mouse_hook_) { | 484 if (mouse_hook_) { |
650 UnhookWindowsHookEx(mouse_hook_); | 485 UnhookWindowsHookEx(mouse_hook_); |
651 mouse_hook_ = NULL; | 486 mouse_hook_ = NULL; |
652 } | 487 } |
653 } | 488 } |
654 | 489 |
655 void WebPluginDelegateImpl::Paint(WebKit::WebCanvas* canvas, | 490 void WebPluginDelegateImpl::Paint(WebKit::WebCanvas* canvas, |
656 const gfx::Rect& rect) { | 491 const gfx::Rect& rect) { |
657 if (windowless_ && skia::SupportsPlatformPaint(canvas)) { | 492 if (windowless_ && skia::SupportsPlatformPaint(canvas)) { |
658 skia::ScopedPlatformPaint scoped_platform_paint(canvas); | 493 skia::ScopedPlatformPaint scoped_platform_paint(canvas); |
659 HDC hdc = scoped_platform_paint.GetPlatformSurface(); | 494 HDC hdc = scoped_platform_paint.GetPlatformSurface(); |
660 WindowlessPaint(hdc, rect); | 495 WindowlessPaint(hdc, rect); |
661 } | 496 } |
662 } | 497 } |
663 | 498 |
664 bool WebPluginDelegateImpl::WindowedCreatePlugin() { | 499 bool WebPluginDelegateImpl::WindowedCreatePlugin() { |
665 DCHECK(!windowed_handle_); | 500 DCHECK(!windowed_handle_); |
666 | 501 |
667 RegisterNativeWindowClass(); | 502 RegisterNativeWindowClass(); |
668 | 503 |
669 // UIPI requires reparenting in the (medium-integrity) browser process. | |
670 bool reparent_in_browser = (quirks_ & PLUGIN_QUIRK_REPARENT_IN_BROWSER) != 0; | |
671 | |
672 // The window will be sized and shown later. | 504 // The window will be sized and shown later. |
673 windowed_handle_ = CreateWindowEx( | 505 windowed_handle_ = CreateWindowEx( |
674 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, | 506 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, |
675 kNativeWindowClassName, | 507 kNativeWindowClassName, |
676 0, | 508 0, |
677 WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, | 509 WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, |
678 0, | 510 0, |
679 0, | 511 0, |
680 0, | 512 0, |
681 0, | 513 0, |
682 reparent_in_browser ? NULL : parent_, | 514 parent_, |
683 0, | 515 0, |
684 GetModuleHandle(NULL), | 516 GetModuleHandle(NULL), |
685 0); | 517 0); |
686 if (windowed_handle_ == 0) | 518 if (windowed_handle_ == 0) |
687 return false; | 519 return false; |
688 | 520 |
689 if (reparent_in_browser) { | 521 if (IsWindow(parent_)) { |
690 plugin_->ReparentPluginWindow(windowed_handle_, parent_); | |
691 } else if (IsWindow(parent_)) { | |
692 // This is a tricky workaround for Issue 2673 in chromium "Flash: IME not | 522 // This is a tricky workaround for Issue 2673 in chromium "Flash: IME not |
693 // available". To use IMEs in this window, we have to make Windows attach | 523 // available". To use IMEs in this window, we have to make Windows attach |
694 // IMEs to this window (i.e. load IME DLLs, attach them to this process, | 524 // IMEs to this window (i.e. load IME DLLs, attach them to this process, |
695 // and add their message hooks to this window). Windows attaches IMEs while | 525 // and add their message hooks to this window). Windows attaches IMEs while |
696 // this process creates a top-level window. On the other hand, to layout | 526 // this process creates a top-level window. On the other hand, to layout |
697 // this window correctly in the given parent window (RenderWidgetHostHWND), | 527 // this window correctly in the given parent window (RenderWidgetHostHWND), |
698 // this window should be a child window of the parent window. | 528 // this window should be a child window of the parent window. |
699 // To satisfy both of the above conditions, this code once creates a | 529 // To satisfy both of the above conditions, this code once creates a |
700 // top-level window and change it to a child window of the parent window. | 530 // top-level window and change it to a child window of the parent window. |
701 SetWindowLongPtr(windowed_handle_, GWL_STYLE, | 531 SetWindowLongPtr(windowed_handle_, GWL_STYLE, |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
903 DCHECK(old_flash_proc); | 733 DCHECK(old_flash_proc); |
904 g_window_handle_proc_map.Get()[window] = old_flash_proc; | 734 g_window_handle_proc_map.Get()[window] = old_flash_proc; |
905 } | 735 } |
906 | 736 |
907 return TRUE; | 737 return TRUE; |
908 } | 738 } |
909 | 739 |
910 bool WebPluginDelegateImpl::CreateDummyWindowForActivation() { | 740 bool WebPluginDelegateImpl::CreateDummyWindowForActivation() { |
911 DCHECK(!dummy_window_for_activation_); | 741 DCHECK(!dummy_window_for_activation_); |
912 | 742 |
913 // Built-in Flash runs with UIPI, but in windowless mode Flash sometimes | |
914 // tries to attach windows to the parent (which fails under UIPI). To make | |
915 // it work we add an extra dummy parent in the low-integrity process. | |
916 if (quirks_ & PLUGIN_QUIRK_REPARENT_IN_BROWSER) { | |
917 parent_proxy_window_ = CreateWindowEx( | |
918 0, | |
919 L"Static", | |
920 kDummyActivationWindowName, | |
921 WS_POPUP, | |
922 0, | |
923 0, | |
924 0, | |
925 0, | |
926 0, | |
927 0, | |
928 GetModuleHandle(NULL), | |
929 0); | |
930 | |
931 if (parent_proxy_window_ == 0) | |
932 return false; | |
933 plugin_->ReparentPluginWindow(parent_proxy_window_, parent_); | |
934 } | |
935 | |
936 dummy_window_for_activation_ = CreateWindowEx( | 743 dummy_window_for_activation_ = CreateWindowEx( |
937 0, | 744 0, |
938 L"Static", | 745 L"Static", |
939 kDummyActivationWindowName, | 746 kDummyActivationWindowName, |
940 WS_CHILD, | 747 WS_CHILD, |
941 0, | 748 0, |
942 0, | 749 0, |
943 0, | 750 0, |
944 0, | 751 0, |
945 parent_proxy_window_ ? parent_proxy_window_ : parent_, | 752 parent_, |
946 0, | 753 0, |
947 GetModuleHandle(NULL), | 754 GetModuleHandle(NULL), |
948 0); | 755 0); |
949 | 756 |
950 if (dummy_window_for_activation_ == 0) | 757 if (dummy_window_for_activation_ == 0) |
951 return false; | 758 return false; |
952 | 759 |
953 // Flash creates background windows which use excessive CPU in our | 760 // Flash creates background windows which use excessive CPU in our |
954 // environment; we wrap these windows and throttle them so that they don't | 761 // environment; we wrap these windows and throttle them so that they don't |
955 // get out of hand. | 762 // get out of hand. |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1126 // Flash may flood the message queue with WM_USER+1 message causing 100% CPU | 933 // Flash may flood the message queue with WM_USER+1 message causing 100% CPU |
1127 // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We | 934 // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We |
1128 // prevent this by throttling the messages. | 935 // prevent this by throttling the messages. |
1129 if (message == WM_USER + 1 && | 936 if (message == WM_USER + 1 && |
1130 delegate->GetQuirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) { | 937 delegate->GetQuirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) { |
1131 WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd, | 938 WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd, |
1132 message, wparam, lparam); | 939 message, wparam, lparam); |
1133 return FALSE; | 940 return FALSE; |
1134 } | 941 } |
1135 | 942 |
1136 // Track the keystate to work around a UIPI issue. | |
1137 if (delegate->GetQuirks() & PLUGIN_QUIRK_PATCH_GETKEYSTATE) { | |
1138 switch (message) { | |
1139 case WM_KEYDOWN: | |
1140 SetSavedKeyState(wparam); | |
1141 break; | |
1142 | |
1143 case WM_KEYUP: | |
1144 UnsetSavedKeyState(wparam); | |
1145 break; | |
1146 | |
1147 // Clear out the saved keystate whenever the Flash thread loses focus. | |
1148 case WM_KILLFOCUS: | |
1149 case WM_SETFOCUS: | |
1150 if (::GetCurrentThreadId() != ::GetWindowThreadProcessId( | |
1151 reinterpret_cast<HWND>(wparam), NULL)) { | |
1152 ClearSavedKeyState(); | |
1153 } | |
1154 break; | |
1155 | |
1156 default: | |
1157 break; | |
1158 } | |
1159 } | |
1160 | |
1161 LRESULT result; | 943 LRESULT result; |
1162 uint32 old_message = delegate->last_message_; | 944 uint32 old_message = delegate->last_message_; |
1163 delegate->last_message_ = message; | 945 delegate->last_message_ = message; |
1164 | 946 |
1165 static UINT custom_msg = RegisterWindowMessage(kPaintMessageName); | 947 static UINT custom_msg = RegisterWindowMessage(kPaintMessageName); |
1166 if (message == custom_msg) { | 948 if (message == custom_msg) { |
1167 // Get the invalid rect which is in screen coordinates and convert to | 949 // Get the invalid rect which is in screen coordinates and convert to |
1168 // window coordinates. | 950 // window coordinates. |
1169 gfx::Rect invalid_rect; | 951 gfx::Rect invalid_rect; |
1170 invalid_rect.set_x(wparam >> 16); | 952 invalid_rect.set_x(wparam >> 16); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1317 } | 1099 } |
1318 | 1100 |
1319 bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) { | 1101 bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) { |
1320 DCHECK(instance()->windowless()); | 1102 DCHECK(instance()->windowless()); |
1321 | 1103 |
1322 NPEvent focus_event; | 1104 NPEvent focus_event; |
1323 focus_event.event = focused ? WM_SETFOCUS : WM_KILLFOCUS; | 1105 focus_event.event = focused ? WM_SETFOCUS : WM_KILLFOCUS; |
1324 focus_event.wParam = 0; | 1106 focus_event.wParam = 0; |
1325 focus_event.lParam = 0; | 1107 focus_event.lParam = 0; |
1326 | 1108 |
1327 if (GetQuirks() & PLUGIN_QUIRK_PATCH_GETKEYSTATE) | |
1328 ClearSavedKeyState(); | |
1329 | |
1330 instance()->NPP_HandleEvent(&focus_event); | 1109 instance()->NPP_HandleEvent(&focus_event); |
1331 return true; | 1110 return true; |
1332 } | 1111 } |
1333 | 1112 |
1334 static bool NPEventFromWebMouseEvent(const WebMouseEvent& event, | 1113 static bool NPEventFromWebMouseEvent(const WebMouseEvent& event, |
1335 NPEvent* np_event) { | 1114 NPEvent* np_event) { |
1336 np_event->lParam = static_cast<uint32>(MAKELPARAM(event.windowX, | 1115 np_event->lParam = static_cast<uint32>(MAKELPARAM(event.windowX, |
1337 event.windowY)); | 1116 event.windowY)); |
1338 np_event->wParam = 0; | 1117 np_event->wParam = 0; |
1339 | 1118 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1439 | 1218 |
1440 bool WebPluginDelegateImpl::PlatformHandleInputEvent( | 1219 bool WebPluginDelegateImpl::PlatformHandleInputEvent( |
1441 const WebInputEvent& event, WebCursorInfo* cursor_info) { | 1220 const WebInputEvent& event, WebCursorInfo* cursor_info) { |
1442 DCHECK(cursor_info != NULL); | 1221 DCHECK(cursor_info != NULL); |
1443 | 1222 |
1444 NPEvent np_event; | 1223 NPEvent np_event; |
1445 if (!NPEventFromWebInputEvent(event, &np_event)) { | 1224 if (!NPEventFromWebInputEvent(event, &np_event)) { |
1446 return false; | 1225 return false; |
1447 } | 1226 } |
1448 | 1227 |
1449 if (GetQuirks() & PLUGIN_QUIRK_PATCH_GETKEYSTATE) { | |
1450 if (np_event.event == WM_KEYDOWN) | |
1451 SetSavedKeyState(np_event.wParam); | |
1452 else if (np_event.event == WM_KEYUP) | |
1453 UnsetSavedKeyState(np_event.wParam); | |
1454 } | |
1455 | |
1456 // Allow this plug-in to access this IME emulator through IMM32 API while the | 1228 // Allow this plug-in to access this IME emulator through IMM32 API while the |
1457 // plug-in is processing this event. | 1229 // plug-in is processing this event. |
1458 if (GetQuirks() & PLUGIN_QUIRK_EMULATE_IME) { | 1230 if (GetQuirks() & PLUGIN_QUIRK_EMULATE_IME) { |
1459 if (!plugin_ime_.get()) | 1231 if (!plugin_ime_.get()) |
1460 plugin_ime_.reset(new WebPluginIMEWin); | 1232 plugin_ime_.reset(new WebPluginIMEWin); |
1461 } | 1233 } |
1462 WebPluginIMEWin::ScopedLock lock(plugin_ime_.get()); | 1234 WebPluginIMEWin::ScopedLock lock(plugin_ime_.get()); |
1463 | 1235 |
1464 HWND last_focus_window = NULL; | 1236 HWND last_focus_window = NULL; |
1465 | 1237 |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1696 ::ReleaseCapture(); | 1468 ::ReleaseCapture(); |
1697 break; | 1469 break; |
1698 | 1470 |
1699 default: | 1471 default: |
1700 break; | 1472 break; |
1701 } | 1473 } |
1702 } | 1474 } |
1703 | 1475 |
1704 } // namespace npapi | 1476 } // namespace npapi |
1705 } // namespace webkit | 1477 } // namespace webkit |
OLD | NEW |