Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/glue/plugins/webplugin_delegate_impl.h" | 5 #include "webkit/glue/plugins/webplugin_delegate_impl.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| 11 #include "base/iat_patch.h" | |
| 12 #include "base/lazy_instance.h" | |
| 11 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
| 12 #include "base/stats_counters.h" | 14 #include "base/stats_counters.h" |
| 13 #include "base/string_util.h" | 15 #include "base/string_util.h" |
| 14 #include "webkit/default_plugin/plugin_impl.h" | 16 #include "webkit/default_plugin/plugin_impl.h" |
| 15 #include "webkit/glue/glue_util.h" | 17 #include "webkit/glue/glue_util.h" |
| 16 #include "webkit/glue/webplugin.h" | 18 #include "webkit/glue/webplugin.h" |
| 17 #include "webkit/glue/plugins/plugin_constants_win.h" | 19 #include "webkit/glue/plugins/plugin_constants_win.h" |
| 18 #include "webkit/glue/plugins/plugin_instance.h" | 20 #include "webkit/glue/plugins/plugin_instance.h" |
| 19 #include "webkit/glue/plugins/plugin_lib.h" | 21 #include "webkit/glue/plugins/plugin_lib.h" |
| 20 #include "webkit/glue/plugins/plugin_list.h" | 22 #include "webkit/glue/plugins/plugin_list.h" |
| 21 #include "webkit/glue/plugins/plugin_stream_url.h" | 23 #include "webkit/glue/plugins/plugin_stream_url.h" |
| 22 #include "webkit/glue/webkit_glue.h" | 24 #include "webkit/glue/webkit_glue.h" |
| 23 | 25 |
| 24 static StatsCounter windowless_queue("Plugin.ThrottleQueue"); | 26 namespace { |
| 25 | 27 |
| 26 static const wchar_t kWebPluginDelegateProperty[] = | 28 const wchar_t kWebPluginDelegateProperty[] = L"WebPluginDelegateProperty"; |
| 27 L"WebPluginDelegateProperty"; | 29 const wchar_t kPluginNameAtomProperty[] = L"PluginNameAtom"; |
| 28 static const wchar_t kPluginNameAtomProperty[] = L"PluginNameAtom"; | 30 const wchar_t kDummyActivationWindowName[] = L"DummyWindowForActivation"; |
| 29 static const wchar_t kDummyActivationWindowName[] = L"DummyWindowForActivation"; | 31 const wchar_t kPluginOrigProc[] = L"OriginalPtr"; |
| 30 static const wchar_t kPluginOrigProc[] = L"OriginalPtr"; | 32 const wchar_t kPluginFlashThrottle[] = L"FlashThrottle"; |
| 31 static const wchar_t kPluginFlashThrottle[] = L"FlashThrottle"; | |
| 32 | 33 |
| 33 // The fastest we are willing to process WM_USER+1 events for Flash. | 34 // The fastest we are willing to process WM_USER+1 events for Flash. |
| 34 // Flash can easily exceed the limits of our CPU if we don't throttle it. | 35 // Flash can easily exceed the limits of our CPU if we don't throttle it. |
| 35 // The throttle has been chosen by testing various delays and compromising | 36 // The throttle has been chosen by testing various delays and compromising |
| 36 // on acceptable Flash performance and reasonable CPU consumption. | 37 // on acceptable Flash performance and reasonable CPU consumption. |
| 37 // | 38 // |
| 38 // I'd like to make the throttle delay variable, based on the amount of | 39 // I'd like to make the throttle delay variable, based on the amount of |
| 39 // time currently required to paint Flash plugins. There isn't a good | 40 // time currently required to paint Flash plugins. There isn't a good |
| 40 // way to count the time spent in aggregate plugin painting, however, so | 41 // way to count the time spent in aggregate plugin painting, however, so |
| 41 // this seems to work well enough. | 42 // this seems to work well enough. |
| 42 static const int kFlashWMUSERMessageThrottleDelayMs = 5; | 43 const int kFlashWMUSERMessageThrottleDelayMs = 5; |
| 43 | 44 |
| 44 std::list<MSG> WebPluginDelegateImpl::throttle_queue_; | 45 // The current instance of the plugin which entered the modal loop. |
| 46 WebPluginDelegateImpl* g_current_plugin_instance = NULL; | |
| 45 | 47 |
| 46 WebPluginDelegateImpl* WebPluginDelegateImpl::current_plugin_instance_ = NULL; | 48 base::LazyInstance<std::list<MSG> > g_throttle_queue(base::LINKER_INITIALIZED); |
| 47 | 49 |
| 48 iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_track_popup_menu_; | 50 // Helper object for patching the TrackPopupMenu API. |
| 49 iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_set_cursor_; | 51 base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_track_popup_menu( |
| 52 base::LINKER_INITIALIZED); | |
| 53 | |
| 54 // Helper object for patching the SetCursor API. | |
| 55 base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_set_cursor( | |
| 56 base::LINKER_INITIALIZED); | |
| 57 | |
| 58 } // namespace | |
| 50 | 59 |
| 51 WebPluginDelegateImpl* WebPluginDelegateImpl::Create( | 60 WebPluginDelegateImpl* WebPluginDelegateImpl::Create( |
| 52 const FilePath& filename, | 61 const FilePath& filename, |
| 53 const std::string& mime_type, | 62 const std::string& mime_type, |
| 54 gfx::NativeView containing_view) { | 63 gfx::NativeView containing_view) { |
| 55 scoped_refptr<NPAPI::PluginLib> plugin = | 64 scoped_refptr<NPAPI::PluginLib> plugin = |
| 56 NPAPI::PluginLib::CreatePluginLib(filename); | 65 NPAPI::PluginLib::CreatePluginLib(filename); |
| 57 if (plugin.get() == NULL) | 66 if (plugin.get() == NULL) |
| 58 return NULL; | 67 return NULL; |
| 59 | 68 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 wchar_t window_title[MAX_PATH + 1] = {0}; | 114 wchar_t window_title[MAX_PATH + 1] = {0}; |
| 106 if (GetWindowText(window, window_title, arraysize(window_title))) { | 115 if (GetWindowText(window, window_title, arraysize(window_title))) { |
| 107 return (0 == lstrcmpiW(window_title, kDummyActivationWindowName)); | 116 return (0 == lstrcmpiW(window_title, kDummyActivationWindowName)); |
| 108 } | 117 } |
| 109 return false; | 118 return false; |
| 110 } | 119 } |
| 111 | 120 |
| 112 LRESULT CALLBACK WebPluginDelegateImpl::HandleEventMessageFilterHook( | 121 LRESULT CALLBACK WebPluginDelegateImpl::HandleEventMessageFilterHook( |
| 113 int code, WPARAM wParam, LPARAM lParam) { | 122 int code, WPARAM wParam, LPARAM lParam) { |
| 114 | 123 |
| 115 DCHECK(current_plugin_instance_); | 124 DCHECK(g_current_plugin_instance); |
| 116 current_plugin_instance_->OnModalLoopEntered(); | 125 g_current_plugin_instance->OnModalLoopEntered(); |
| 117 return CallNextHookEx(NULL, code, wParam, lParam); | 126 return CallNextHookEx(NULL, code, wParam, lParam); |
| 118 } | 127 } |
| 119 | 128 |
| 120 WebPluginDelegateImpl::WebPluginDelegateImpl( | 129 WebPluginDelegateImpl::WebPluginDelegateImpl( |
| 121 gfx::NativeView containing_view, | 130 gfx::NativeView containing_view, |
| 122 NPAPI::PluginInstance *instance) | 131 NPAPI::PluginInstance *instance) |
| 123 : parent_(containing_view), | 132 : parent_(containing_view), |
| 124 instance_(instance), | 133 instance_(instance), |
| 125 quirks_(0), | 134 quirks_(0), |
| 126 plugin_(NULL), | 135 plugin_(NULL), |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 254 plugin_url_ = url.spec(); | 263 plugin_url_ = url.spec(); |
| 255 | 264 |
| 256 // The windowless version of the Silverlight plugin calls the | 265 // The windowless version of the Silverlight plugin calls the |
| 257 // WindowFromPoint API and passes the result of that to the | 266 // WindowFromPoint API and passes the result of that to the |
| 258 // TrackPopupMenu API call as the owner window. This causes the API | 267 // TrackPopupMenu API call as the owner window. This causes the API |
| 259 // to fail as the API expects the window handle to live on the same | 268 // to fail as the API expects the window handle to live on the same |
| 260 // thread as the caller. It works in the other browsers as the plugin | 269 // thread as the caller. It works in the other browsers as the plugin |
| 261 // lives on the browser thread. Our workaround is to intercept the | 270 // lives on the browser thread. Our workaround is to intercept the |
| 262 // TrackPopupMenu API for Silverlight and replace the window handle | 271 // TrackPopupMenu API for Silverlight and replace the window handle |
| 263 // with the dummy activation window. | 272 // with the dummy activation window. |
| 264 if (windowless_ && !iat_patch_track_popup_menu_.is_patched() && | 273 if (windowless_ && !g_iat_patch_track_popup_menu.Pointer()->is_patched() && |
| 265 (quirks_ & PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU)) { | 274 (quirks_ & PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU)) { |
| 266 iat_patch_track_popup_menu_.Patch( | 275 g_iat_patch_track_popup_menu.Pointer()->Patch( |
| 267 plugin_module_handle_, "user32.dll", "TrackPopupMenu", | 276 plugin_module_handle_, "user32.dll", "TrackPopupMenu", |
| 268 WebPluginDelegateImpl::TrackPopupMenuPatch); | 277 WebPluginDelegateImpl::TrackPopupMenuPatch); |
| 269 } | 278 } |
| 270 | 279 |
| 271 // Windowless plugins can set cursors by calling the SetCursor API. This | 280 // Windowless plugins can set cursors by calling the SetCursor API. This |
| 272 // works because the thread inputs of the browser UI thread and the plugin | 281 // works because the thread inputs of the browser UI thread and the plugin |
| 273 // thread are attached. We intercept the SetCursor API for windowless plugins | 282 // thread are attached. We intercept the SetCursor API for windowless plugins |
| 274 // and remember the cursor being set. This is shipped over to the browser | 283 // and remember the cursor being set. This is shipped over to the browser |
| 275 // in the HandleEvent call, which ensures that the cursor does not change | 284 // in the HandleEvent call, which ensures that the cursor does not change |
| 276 // when a windowless plugin instance changes the cursor in a background tab. | 285 // when a windowless plugin instance changes the cursor in a background tab. |
| 277 if (windowless_ && !iat_patch_set_cursor_.is_patched() && | 286 if (windowless_ && !g_iat_patch_set_cursor.Pointer()->is_patched() && |
| 278 (quirks_ & PLUGIN_QUIRK_PATCH_SETCURSOR)) { | 287 (quirks_ & PLUGIN_QUIRK_PATCH_SETCURSOR)) { |
| 279 iat_patch_set_cursor_.Patch(plugin_module_handle_, "user32.dll", | 288 g_iat_patch_set_cursor.Pointer()->Patch( |
| 280 "SetCursor", | 289 plugin_module_handle_, "user32.dll", "SetCursor", |
| 281 WebPluginDelegateImpl::SetCursorPatch); | 290 WebPluginDelegateImpl::SetCursorPatch); |
| 282 } | 291 } |
| 283 return true; | 292 return true; |
| 284 } | 293 } |
| 285 | 294 |
| 286 void WebPluginDelegateImpl::DestroyInstance() { | 295 void WebPluginDelegateImpl::DestroyInstance() { |
| 287 if (instance_ && (instance_->npp()->ndata != NULL)) { | 296 if (instance_ && (instance_->npp()->ndata != NULL)) { |
| 288 // Shutdown all streams before destroying so that | 297 // Shutdown all streams before destroying so that |
| 289 // no streams are left "in progress". Need to do | 298 // no streams are left "in progress". Need to do |
| 290 // this before calling set_web_plugin(NULL) because the | 299 // this before calling set_web_plugin(NULL) because the |
| 291 // instance uses the helper to do the download. | 300 // instance uses the helper to do the download. |
| 292 instance_->CloseStreams(); | 301 instance_->CloseStreams(); |
| 293 | 302 |
| 294 window_.window = NULL; | 303 window_.window = NULL; |
| 295 if (!(quirks_ & PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY)) { | 304 if (!(quirks_ & PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY)) { |
| 296 instance_->NPP_SetWindow(&window_); | 305 instance_->NPP_SetWindow(&window_); |
| 297 } | 306 } |
| 298 | 307 |
| 299 instance_->NPP_Destroy(); | 308 instance_->NPP_Destroy(); |
| 300 | 309 |
| 301 instance_->set_web_plugin(NULL); | 310 instance_->set_web_plugin(NULL); |
| 302 | 311 |
| 303 if (instance_->plugin_lib()) { | 312 if (instance_->plugin_lib()) { |
| 304 // Unpatch if this is the last plugin instance. | 313 // Unpatch if this is the last plugin instance. |
| 305 if (instance_->plugin_lib()->instance_count() == 1) { | 314 if (instance_->plugin_lib()->instance_count() == 1) { |
| 306 if (iat_patch_set_cursor_.is_patched()) { | 315 if (g_iat_patch_set_cursor.Pointer()->is_patched()) { |
| 307 iat_patch_set_cursor_.Unpatch(); | 316 g_iat_patch_set_cursor.Pointer()->Unpatch(); |
| 308 } | 317 } |
| 309 | 318 |
| 310 if (iat_patch_track_popup_menu_.is_patched()) { | 319 if (g_iat_patch_track_popup_menu.Pointer()->is_patched()) { |
| 311 iat_patch_track_popup_menu_.Unpatch(); | 320 g_iat_patch_track_popup_menu.Pointer()->Unpatch(); |
| 312 } | 321 } |
| 313 } | 322 } |
| 314 } | 323 } |
| 315 | 324 |
| 316 instance_ = 0; | 325 instance_ = 0; |
| 317 } | 326 } |
| 318 } | 327 } |
| 319 | 328 |
| 320 void WebPluginDelegateImpl::UpdateGeometry( | 329 void WebPluginDelegateImpl::UpdateGeometry( |
| 321 const gfx::Rect& window_rect, | 330 const gfx::Rect& window_rect, |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 497 DestroyWindow(windowed_handle_); | 506 DestroyWindow(windowed_handle_); |
| 498 windowed_handle_ = 0; | 507 windowed_handle_ = 0; |
| 499 } | 508 } |
| 500 } | 509 } |
| 501 | 510 |
| 502 // Erase all messages in the queue destined for a particular window. | 511 // Erase all messages in the queue destined for a particular window. |
| 503 // When windows are closing, callers should use this function to clear | 512 // When windows are closing, callers should use this function to clear |
| 504 // the queue. | 513 // the queue. |
| 505 // static | 514 // static |
| 506 void WebPluginDelegateImpl::ClearThrottleQueueForWindow(HWND window) { | 515 void WebPluginDelegateImpl::ClearThrottleQueueForWindow(HWND window) { |
| 516 std::list<MSG>* throttle_queue = g_throttle_queue.Pointer(); | |
| 517 | |
| 507 std::list<MSG>::iterator it; | 518 std::list<MSG>::iterator it; |
| 508 for (it = throttle_queue_.begin(); it != throttle_queue_.end(); ) { | 519 for (it = throttle_queue->begin(); it != throttle_queue->end(); ) { |
| 509 if (it->hwnd == window) { | 520 if (it->hwnd == window) { |
| 510 it = throttle_queue_.erase(it); | 521 it = throttle_queue->erase(it); |
| 511 windowless_queue.Decrement(); | |
| 512 } else { | 522 } else { |
| 513 it++; | 523 it++; |
| 514 } | 524 } |
| 515 } | 525 } |
| 516 } | 526 } |
| 517 | 527 |
| 518 // Delayed callback for processing throttled messages. | 528 // Delayed callback for processing throttled messages. |
| 519 // Throttled messages are aggregated globally across all plugins. | 529 // Throttled messages are aggregated globally across all plugins. |
| 520 // static | 530 // static |
| 521 void WebPluginDelegateImpl::OnThrottleMessage() { | 531 void WebPluginDelegateImpl::OnThrottleMessage() { |
| 522 // The current algorithm walks the list and processes the first | 532 // The current algorithm walks the list and processes the first |
| 523 // message it finds for each plugin. It is important to service | 533 // message it finds for each plugin. It is important to service |
| 524 // all active plugins with each pass through the throttle, otherwise | 534 // all active plugins with each pass through the throttle, otherwise |
| 525 // we see video jankiness. | 535 // we see video jankiness. |
| 536 std::list<MSG>* throttle_queue = g_throttle_queue.Pointer(); | |
| 526 std::map<HWND, int> processed; | 537 std::map<HWND, int> processed; |
| 527 | 538 |
| 528 std::list<MSG>::iterator it = throttle_queue_.begin(); | 539 std::list<MSG>::iterator it = throttle_queue->begin(); |
| 529 while (it != throttle_queue_.end()) { | 540 while (it != throttle_queue->end()) { |
| 530 const MSG& msg = *it; | 541 const MSG& msg = *it; |
| 531 if (processed.find(msg.hwnd) == processed.end()) { | 542 if (processed.find(msg.hwnd) == processed.end()) { |
| 532 WNDPROC proc = reinterpret_cast<WNDPROC>(msg.time); | 543 WNDPROC proc = reinterpret_cast<WNDPROC>(msg.time); |
| 533 // It is possible that the window was closed after we queued | 544 // It is possible that the window was closed after we queued |
| 534 // this message. This is a rare event; just verify the window | 545 // this message. This is a rare event; just verify the window |
| 535 // is alive. (see also bug 1259488) | 546 // is alive. (see also bug 1259488) |
| 536 if (IsWindow(msg.hwnd)) | 547 if (IsWindow(msg.hwnd)) |
| 537 CallWindowProc(proc, msg.hwnd, msg.message, msg.wParam, msg.lParam); | 548 CallWindowProc(proc, msg.hwnd, msg.message, msg.wParam, msg.lParam); |
| 538 processed[msg.hwnd] = 1; | 549 processed[msg.hwnd] = 1; |
| 539 it = throttle_queue_.erase(it); | 550 it = throttle_queue->erase(it); |
| 540 windowless_queue.Decrement(); | |
| 541 } else { | 551 } else { |
| 542 it++; | 552 it++; |
| 543 } | 553 } |
| 544 } | 554 } |
| 545 | 555 |
| 546 if (throttle_queue_.size() > 0) | 556 if (throttle_queue->size() > 0) |
| 547 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 557 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 548 NewRunnableFunction(&WebPluginDelegateImpl::OnThrottleMessage), | 558 NewRunnableFunction(&WebPluginDelegateImpl::OnThrottleMessage), |
| 549 kFlashWMUSERMessageThrottleDelayMs); | 559 kFlashWMUSERMessageThrottleDelayMs); |
| 550 } | 560 } |
| 551 | 561 |
| 552 // Schedule a windows message for delivery later. | 562 // Schedule a windows message for delivery later. |
| 553 // static | 563 // static |
| 554 void WebPluginDelegateImpl::ThrottleMessage(WNDPROC proc, HWND hwnd, | 564 void WebPluginDelegateImpl::ThrottleMessage(WNDPROC proc, HWND hwnd, |
| 555 UINT message, WPARAM wParam, | 565 UINT message, WPARAM wParam, |
| 556 LPARAM lParam) { | 566 LPARAM lParam) { |
| 557 MSG msg; | 567 MSG msg; |
| 558 msg.time = reinterpret_cast<DWORD>(proc); | 568 msg.time = reinterpret_cast<DWORD>(proc); |
| 559 msg.hwnd = hwnd; | 569 msg.hwnd = hwnd; |
| 560 msg.message = message; | 570 msg.message = message; |
| 561 msg.wParam = wParam; | 571 msg.wParam = wParam; |
| 562 msg.lParam = lParam; | 572 msg.lParam = lParam; |
| 563 throttle_queue_.push_back(msg); | |
| 564 windowless_queue.Increment(); | |
| 565 | 573 |
| 566 if (throttle_queue_.size() == 1) { | 574 std::list<MSG>* throttle_queue = g_throttle_queue.Pointer(); |
| 575 | |
|
jam
2009/01/23 19:26:23
nit: no need for extra line?
| |
| 576 throttle_queue->push_back(msg); | |
| 577 | |
| 578 if (throttle_queue->size() == 1) { | |
| 567 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 579 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 568 NewRunnableFunction(&WebPluginDelegateImpl::OnThrottleMessage), | 580 NewRunnableFunction(&WebPluginDelegateImpl::OnThrottleMessage), |
| 569 kFlashWMUSERMessageThrottleDelayMs); | 581 kFlashWMUSERMessageThrottleDelayMs); |
| 570 } | 582 } |
| 571 } | 583 } |
| 572 | 584 |
| 573 // We go out of our way to find the hidden windows created by Flash for | 585 // We go out of our way to find the hidden windows created by Flash for |
| 574 // windowless plugins. We throttle the rate at which they deliver messages | 586 // windowless plugins. We throttle the rate at which they deliver messages |
| 575 // so that they will not consume outrageous amounts of CPU. | 587 // so that they will not consume outrageous amounts of CPU. |
| 576 // static | 588 // static |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 808 invalid_rect.Offset(-window_rect.left, -window_rect.top); | 820 invalid_rect.Offset(-window_rect.left, -window_rect.top); |
| 809 | 821 |
| 810 // The plugin window might have non-client area. If we don't pass in | 822 // The plugin window might have non-client area. If we don't pass in |
| 811 // RDW_FRAME then the children don't receive WM_NCPAINT messages while | 823 // RDW_FRAME then the children don't receive WM_NCPAINT messages while |
| 812 // scrolling, which causes painting problems (http://b/issue?id=923945). | 824 // scrolling, which causes painting problems (http://b/issue?id=923945). |
| 813 RedrawWindow(hwnd, &invalid_rect.ToRECT(), NULL, | 825 RedrawWindow(hwnd, &invalid_rect.ToRECT(), NULL, |
| 814 RDW_UPDATENOW | RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_FRAME); | 826 RDW_UPDATENOW | RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_FRAME); |
| 815 return FALSE; | 827 return FALSE; |
| 816 } | 828 } |
| 817 | 829 |
| 818 current_plugin_instance_ = delegate; | 830 g_current_plugin_instance = delegate; |
| 819 | 831 |
| 820 switch (message) { | 832 switch (message) { |
| 821 case WM_NCDESTROY: { | 833 case WM_NCDESTROY: { |
| 822 RemoveProp(hwnd, kWebPluginDelegateProperty); | 834 RemoveProp(hwnd, kWebPluginDelegateProperty); |
| 823 ATOM plugin_name_atom = reinterpret_cast <ATOM>( | 835 ATOM plugin_name_atom = reinterpret_cast <ATOM>( |
| 824 RemoveProp(hwnd, kPluginNameAtomProperty)); | 836 RemoveProp(hwnd, kPluginNameAtomProperty)); |
| 825 if (plugin_name_atom != 0) | 837 if (plugin_name_atom != 0) |
| 826 GlobalDeleteAtom(plugin_name_atom); | 838 GlobalDeleteAtom(plugin_name_atom); |
| 827 ClearThrottleQueueForWindow(hwnd); | 839 ClearThrottleQueueForWindow(hwnd); |
| 828 break; | 840 break; |
| 829 } | 841 } |
| 830 // Flash may flood the message queue with WM_USER+1 message causing 100% CPU | 842 // Flash may flood the message queue with WM_USER+1 message causing 100% CPU |
| 831 // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We | 843 // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We |
| 832 // prevent this by throttling the messages. | 844 // prevent this by throttling the messages. |
| 833 case WM_USER + 1: { | 845 case WM_USER + 1: { |
| 834 if (delegate->quirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) { | 846 if (delegate->quirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) { |
| 835 WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd, | 847 WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd, |
| 836 message, wparam, lparam); | 848 message, wparam, lparam); |
| 837 current_plugin_instance_ = NULL; | 849 g_current_plugin_instance = NULL; |
| 838 return FALSE; | 850 return FALSE; |
| 839 } | 851 } |
| 840 break; | 852 break; |
| 841 } | 853 } |
| 842 default: { | 854 default: { |
| 843 break; | 855 break; |
| 844 } | 856 } |
| 845 } | 857 } |
| 846 | 858 |
| 847 delegate->last_message_ = message; | 859 delegate->last_message_ = message; |
| 848 delegate->is_calling_wndproc = true; | 860 delegate->is_calling_wndproc = true; |
| 849 | 861 |
| 850 if (!delegate->user_gesture_message_posted_ && | 862 if (!delegate->user_gesture_message_posted_ && |
| 851 IsUserGestureMessage(message)) { | 863 IsUserGestureMessage(message)) { |
| 852 delegate->user_gesture_message_posted_ = true; | 864 delegate->user_gesture_message_posted_ = true; |
| 853 | 865 |
| 854 delegate->instance()->PushPopupsEnabledState(true); | 866 delegate->instance()->PushPopupsEnabledState(true); |
| 855 | 867 |
| 856 MessageLoop::current()->PostTask(FROM_HERE, | 868 MessageLoop::current()->PostTask(FROM_HERE, |
| 857 delegate->user_gesture_msg_factory_.NewRunnableMethod( | 869 delegate->user_gesture_msg_factory_.NewRunnableMethod( |
| 858 &WebPluginDelegateImpl::OnUserGestureEnd)); | 870 &WebPluginDelegateImpl::OnUserGestureEnd)); |
| 859 } | 871 } |
| 860 | 872 |
| 861 LRESULT result = CallWindowProc(delegate->plugin_wnd_proc_, hwnd, message, | 873 LRESULT result = CallWindowProc(delegate->plugin_wnd_proc_, hwnd, message, |
| 862 wparam, lparam); | 874 wparam, lparam); |
| 863 delegate->is_calling_wndproc = false; | 875 delegate->is_calling_wndproc = false; |
| 864 current_plugin_instance_ = NULL; | 876 g_current_plugin_instance = NULL; |
| 865 return result; | 877 return result; |
| 866 } | 878 } |
| 867 | 879 |
| 868 void WebPluginDelegateImpl::WindowlessUpdateGeometry( | 880 void WebPluginDelegateImpl::WindowlessUpdateGeometry( |
| 869 const gfx::Rect& window_rect, | 881 const gfx::Rect& window_rect, |
| 870 const gfx::Rect& clip_rect) { | 882 const gfx::Rect& clip_rect) { |
| 871 // Only resend to the instance if the geometry has changed. | 883 // Only resend to the instance if the geometry has changed. |
| 872 if (window_rect == window_rect_ && clip_rect == clip_rect_) | 884 if (window_rect == window_rect_ && clip_rect == clip_rect_) |
| 873 return; | 885 return; |
| 874 | 886 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 996 // in that context we unhook on receiving the first notification in | 1008 // in that context we unhook on receiving the first notification in |
| 997 // the message filter hook. | 1009 // the message filter hook. |
| 998 handle_event_message_filter_hook_ = | 1010 handle_event_message_filter_hook_ = |
| 999 SetWindowsHookEx(WH_MSGFILTER, HandleEventMessageFilterHook, NULL, | 1011 SetWindowsHookEx(WH_MSGFILTER, HandleEventMessageFilterHook, NULL, |
| 1000 GetCurrentThreadId()); | 1012 GetCurrentThreadId()); |
| 1001 } | 1013 } |
| 1002 | 1014 |
| 1003 bool old_task_reentrancy_state = | 1015 bool old_task_reentrancy_state = |
| 1004 MessageLoop::current()->NestableTasksAllowed(); | 1016 MessageLoop::current()->NestableTasksAllowed(); |
| 1005 | 1017 |
| 1006 current_plugin_instance_ = this; | 1018 g_current_plugin_instance = this; |
| 1007 | 1019 |
| 1008 handle_event_depth_++; | 1020 handle_event_depth_++; |
| 1009 | 1021 |
| 1010 bool pop_user_gesture = false; | 1022 bool pop_user_gesture = false; |
| 1011 | 1023 |
| 1012 if (IsUserGestureMessage(event->event)) { | 1024 if (IsUserGestureMessage(event->event)) { |
| 1013 pop_user_gesture = true; | 1025 pop_user_gesture = true; |
| 1014 instance()->PushPopupsEnabledState(true); | 1026 instance()->PushPopupsEnabledState(true); |
| 1015 } | 1027 } |
| 1016 | 1028 |
| 1017 bool ret = instance()->NPP_HandleEvent(event) != 0; | 1029 bool ret = instance()->NPP_HandleEvent(event) != 0; |
| 1018 | 1030 |
| 1019 if (event->event == WM_MOUSEMOVE) { | 1031 if (event->event == WM_MOUSEMOVE) { |
| 1020 // Snag a reference to the current cursor ASAP in case the plugin modified | 1032 // Snag a reference to the current cursor ASAP in case the plugin modified |
| 1021 // it. There is a nasty race condition here with the multiprocess browser | 1033 // it. There is a nasty race condition here with the multiprocess browser |
| 1022 // as someone might be setting the cursor in the main process as well. | 1034 // as someone might be setting the cursor in the main process as well. |
| 1023 *cursor = current_windowless_cursor_; | 1035 *cursor = current_windowless_cursor_; |
| 1024 } | 1036 } |
| 1025 | 1037 |
| 1026 if (pop_user_gesture) { | 1038 if (pop_user_gesture) { |
| 1027 instance()->PopPopupsEnabledState(); | 1039 instance()->PopPopupsEnabledState(); |
| 1028 } | 1040 } |
| 1029 | 1041 |
| 1030 handle_event_depth_--; | 1042 handle_event_depth_--; |
| 1031 | 1043 |
| 1032 current_plugin_instance_ = NULL; | 1044 g_current_plugin_instance = NULL; |
| 1033 | 1045 |
| 1034 MessageLoop::current()->SetNestableTasksAllowed(old_task_reentrancy_state); | 1046 MessageLoop::current()->SetNestableTasksAllowed(old_task_reentrancy_state); |
| 1035 | 1047 |
| 1036 if (handle_event_message_filter_hook_) { | 1048 if (handle_event_message_filter_hook_) { |
| 1037 UnhookWindowsHookEx(handle_event_message_filter_hook_); | 1049 UnhookWindowsHookEx(handle_event_message_filter_hook_); |
| 1038 handle_event_message_filter_hook_ = NULL; | 1050 handle_event_message_filter_hook_ = NULL; |
| 1039 } | 1051 } |
| 1040 | 1052 |
| 1041 // We could have multiple NPP_HandleEvent calls nested together in case | 1053 // We could have multiple NPP_HandleEvent calls nested together in case |
| 1042 // the plugin enters a modal loop. Reset the pump messages event when | 1054 // the plugin enters a modal loop. Reset the pump messages event when |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1118 } | 1130 } |
| 1119 | 1131 |
| 1120 void WebPluginDelegateImpl::OnUserGestureEnd() { | 1132 void WebPluginDelegateImpl::OnUserGestureEnd() { |
| 1121 user_gesture_message_posted_ = false; | 1133 user_gesture_message_posted_ = false; |
| 1122 instance()->PopPopupsEnabledState(); | 1134 instance()->PopPopupsEnabledState(); |
| 1123 } | 1135 } |
| 1124 | 1136 |
| 1125 BOOL WINAPI WebPluginDelegateImpl::TrackPopupMenuPatch( | 1137 BOOL WINAPI WebPluginDelegateImpl::TrackPopupMenuPatch( |
| 1126 HMENU menu, unsigned int flags, int x, int y, int reserved, | 1138 HMENU menu, unsigned int flags, int x, int y, int reserved, |
| 1127 HWND window, const RECT* rect) { | 1139 HWND window, const RECT* rect) { |
| 1128 if (current_plugin_instance_) { | 1140 if (g_current_plugin_instance) { |
| 1129 unsigned long window_process_id = 0; | 1141 unsigned long window_process_id = 0; |
| 1130 unsigned long window_thread_id = | 1142 unsigned long window_thread_id = |
| 1131 GetWindowThreadProcessId(window, &window_process_id); | 1143 GetWindowThreadProcessId(window, &window_process_id); |
| 1132 // TrackPopupMenu fails if the window passed in belongs to a different | 1144 // TrackPopupMenu fails if the window passed in belongs to a different |
| 1133 // thread. | 1145 // thread. |
| 1134 if (::GetCurrentThreadId() != window_thread_id) { | 1146 if (::GetCurrentThreadId() != window_thread_id) { |
| 1135 window = current_plugin_instance_->dummy_window_for_activation_; | 1147 window = g_current_plugin_instance->dummy_window_for_activation_; |
| 1136 } | 1148 } |
| 1137 } | 1149 } |
| 1138 return TrackPopupMenu(menu, flags, x, y, reserved, window, rect); | 1150 return TrackPopupMenu(menu, flags, x, y, reserved, window, rect); |
| 1139 } | 1151 } |
| 1140 | 1152 |
| 1141 HCURSOR WINAPI WebPluginDelegateImpl::SetCursorPatch(HCURSOR cursor) { | 1153 HCURSOR WINAPI WebPluginDelegateImpl::SetCursorPatch(HCURSOR cursor) { |
| 1142 // The windowless flash plugin periodically calls SetCursor in a wndproc | 1154 // The windowless flash plugin periodically calls SetCursor in a wndproc |
| 1143 // instantiated on the plugin thread. This causes annoying cursor flicker | 1155 // instantiated on the plugin thread. This causes annoying cursor flicker |
| 1144 // when the mouse is moved on a foreground tab, with a windowless plugin | 1156 // when the mouse is moved on a foreground tab, with a windowless plugin |
| 1145 // instance in a background tab. We just ignore the call here. | 1157 // instance in a background tab. We just ignore the call here. |
| 1146 if (!current_plugin_instance_) | 1158 if (!g_current_plugin_instance) |
| 1147 return GetCursor(); | 1159 return GetCursor(); |
| 1148 | 1160 |
| 1149 if (!current_plugin_instance_->windowless()) { | 1161 if (!g_current_plugin_instance->windowless()) { |
| 1150 return SetCursor(cursor); | 1162 return SetCursor(cursor); |
| 1151 } | 1163 } |
| 1152 | 1164 |
| 1153 // It is ok to pass NULL here to GetCursor as we are not looking for cursor | 1165 // It is ok to pass NULL here to GetCursor as we are not looking for cursor |
| 1154 // types defined by Webkit. | 1166 // types defined by Webkit. |
| 1155 HCURSOR previous_cursor = | 1167 HCURSOR previous_cursor = |
| 1156 current_plugin_instance_->current_windowless_cursor_.GetCursor(NULL); | 1168 g_current_plugin_instance->current_windowless_cursor_.GetCursor(NULL); |
| 1157 | 1169 |
| 1158 current_plugin_instance_->current_windowless_cursor_.InitFromExternalCursor( | 1170 g_current_plugin_instance->current_windowless_cursor_.InitFromExternalCursor( |
| 1159 cursor); | 1171 cursor); |
| 1160 return previous_cursor; | 1172 return previous_cursor; |
| 1161 } | 1173 } |
| OLD | NEW |