OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 14 matching lines...) Expand all Loading... |
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" | 25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" |
26 #include "webkit/glue/webkit_glue.h" | 26 #include "webkit/glue/webkit_glue.h" |
27 #include "webkit/plugins/npapi/default_plugin_shared.h" | 27 #include "webkit/plugins/npapi/default_plugin_shared.h" |
28 #include "webkit/plugins/npapi/plugin_constants_win.h" | 28 #include "webkit/plugins/npapi/plugin_constants_win.h" |
29 #include "webkit/plugins/npapi/plugin_group.h" | 29 #include "webkit/plugins/npapi/plugin_group.h" |
30 #include "webkit/plugins/npapi/plugin_instance.h" | 30 #include "webkit/plugins/npapi/plugin_instance.h" |
31 #include "webkit/plugins/npapi/plugin_lib.h" | 31 #include "webkit/plugins/npapi/plugin_lib.h" |
32 #include "webkit/plugins/npapi/plugin_list.h" | 32 #include "webkit/plugins/npapi/plugin_list.h" |
33 #include "webkit/plugins/npapi/plugin_stream_url.h" | 33 #include "webkit/plugins/npapi/plugin_stream_url.h" |
34 #include "webkit/plugins/npapi/webplugin.h" | 34 #include "webkit/plugins/npapi/webplugin.h" |
| 35 #include "webkit/plugins/npapi/webplugin_ime_win.h" |
35 | 36 |
36 using WebKit::WebCursorInfo; | 37 using WebKit::WebCursorInfo; |
37 using WebKit::WebKeyboardEvent; | 38 using WebKit::WebKeyboardEvent; |
38 using WebKit::WebInputEvent; | 39 using WebKit::WebInputEvent; |
39 using WebKit::WebMouseEvent; | 40 using WebKit::WebMouseEvent; |
| 41 using WebKit::WebCompositionEvent; |
40 | 42 |
41 namespace webkit { | 43 namespace webkit { |
42 namespace npapi { | 44 namespace npapi { |
43 | 45 |
44 namespace { | 46 namespace { |
45 | 47 |
46 const wchar_t kWebPluginDelegateProperty[] = L"WebPluginDelegateProperty"; | 48 const wchar_t kWebPluginDelegateProperty[] = L"WebPluginDelegateProperty"; |
47 const wchar_t kPluginNameAtomProperty[] = L"PluginNameAtom"; | 49 const wchar_t kPluginNameAtomProperty[] = L"PluginNameAtom"; |
48 const wchar_t kDummyActivationWindowName[] = L"DummyWindowForActivation"; | 50 const wchar_t kDummyActivationWindowName[] = L"DummyWindowForActivation"; |
49 const wchar_t kPluginFlashThrottle[] = L"FlashThrottle"; | 51 const wchar_t kPluginFlashThrottle[] = L"FlashThrottle"; |
(...skipping 29 matching lines...) Expand all Loading... |
79 base::LINKER_INITIALIZED); | 81 base::LINKER_INITIALIZED); |
80 | 82 |
81 // Helper object for patching the SetCursor API. | 83 // Helper object for patching the SetCursor API. |
82 base::LazyInstance<app::win::IATPatchFunction> g_iat_patch_set_cursor( | 84 base::LazyInstance<app::win::IATPatchFunction> g_iat_patch_set_cursor( |
83 base::LINKER_INITIALIZED); | 85 base::LINKER_INITIALIZED); |
84 | 86 |
85 // Helper object for patching the RegEnumKeyExW API. | 87 // Helper object for patching the RegEnumKeyExW API. |
86 base::LazyInstance<app::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w( | 88 base::LazyInstance<app::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w( |
87 base::LINKER_INITIALIZED); | 89 base::LINKER_INITIALIZED); |
88 | 90 |
| 91 // Helper object for patching the GetProcAddress API. |
| 92 base::LazyInstance<app::win::IATPatchFunction> g_iat_patch_get_proc_address( |
| 93 base::LINKER_INITIALIZED); |
| 94 |
89 // http://crbug.com/16114 | 95 // http://crbug.com/16114 |
90 // 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 |
91 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. | 97 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. |
92 // Doing so allows removing NPP_SetWindow call during painting a windowless | 98 // Doing so allows removing NPP_SetWindow call during painting a windowless |
93 // plugin, which otherwise could trigger layout change while painting by | 99 // plugin, which otherwise could trigger layout change while painting by |
94 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes. | 100 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes. |
95 // 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 |
96 // webplugin_delegate_impl.h and implement for other platforms. | 102 // webplugin_delegate_impl.h and implement for other platforms. |
97 class DrawableContextEnforcer { | 103 class DrawableContextEnforcer { |
98 public: | 104 public: |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 | 297 |
292 if (instance_->mime_type() == "application/x-shockwave-flash" || | 298 if (instance_->mime_type() == "application/x-shockwave-flash" || |
293 filename == kFlashPlugin) { | 299 filename == kFlashPlugin) { |
294 // Flash only requests windowless plugins if we return a Mozilla user | 300 // Flash only requests windowless plugins if we return a Mozilla user |
295 // agent. | 301 // agent. |
296 instance_->set_use_mozilla_user_agent(); | 302 instance_->set_use_mozilla_user_agent(); |
297 quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; | 303 quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; |
298 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; | 304 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; |
299 quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS; | 305 quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS; |
300 quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE; | 306 quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE; |
| 307 quirks_ |= PLUGIN_QUIRK_EMULATE_IME; |
301 } else if (filename == kAcrobatReaderPlugin) { | 308 } else if (filename == kAcrobatReaderPlugin) { |
302 // Check for the version number above or equal 9. | 309 // Check for the version number above or equal 9. |
303 int major_version = GetPluginMajorVersion(plugin_info); | 310 int major_version = GetPluginMajorVersion(plugin_info); |
304 if (major_version >= 9) { | 311 if (major_version >= 9) { |
305 quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; | 312 quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; |
306 // 9.2 needs this. | 313 // 9.2 needs this. |
307 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; | 314 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; |
308 } | 315 } |
309 quirks_ |= PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS; | 316 quirks_ |= PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS; |
310 } else if (plugin_info.name.find(L"Windows Media Player") != | 317 } else if (plugin_info.name.find(L"Windows Media Player") != |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 base::win::GetVersion() == base::win::VERSION_XP && | 434 base::win::GetVersion() == base::win::VERSION_XP && |
428 (base::win::RegKey().Open(HKEY_LOCAL_MACHINE, | 435 (base::win::RegKey().Open(HKEY_LOCAL_MACHINE, |
429 L"SOFTWARE\\Microsoft\\MediaPlayer\\ShimInclusionList\\chrome.exe", | 436 L"SOFTWARE\\Microsoft\\MediaPlayer\\ShimInclusionList\\chrome.exe", |
430 KEY_READ) != ERROR_SUCCESS) && | 437 KEY_READ) != ERROR_SUCCESS) && |
431 !g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) { | 438 !g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) { |
432 g_iat_patch_reg_enum_key_ex_w.Pointer()->Patch( | 439 g_iat_patch_reg_enum_key_ex_w.Pointer()->Patch( |
433 L"wmpdxm.dll", "advapi32.dll", "RegEnumKeyExW", | 440 L"wmpdxm.dll", "advapi32.dll", "RegEnumKeyExW", |
434 WebPluginDelegateImpl::RegEnumKeyExWPatch); | 441 WebPluginDelegateImpl::RegEnumKeyExWPatch); |
435 } | 442 } |
436 | 443 |
| 444 // Flash retrieves the pointers to IMM32 functions with GetProcAddress() calls |
| 445 // and use them to retrieve IME data. We add a patch to this function so we |
| 446 // can dispatch these IMM32 calls to the WebPluginIMEWin class, which emulates |
| 447 // IMM32 functions for Flash. |
| 448 if (!g_iat_patch_get_proc_address.Pointer()->is_patched() && |
| 449 (quirks_ & PLUGIN_QUIRK_EMULATE_IME)) { |
| 450 g_iat_patch_get_proc_address.Pointer()->Patch( |
| 451 GetPluginPath().value().c_str(), "kernel32.dll", "GetProcAddress", |
| 452 GetProcAddressPatch); |
| 453 } |
| 454 |
437 return true; | 455 return true; |
438 } | 456 } |
439 | 457 |
440 void WebPluginDelegateImpl::PlatformDestroyInstance() { | 458 void WebPluginDelegateImpl::PlatformDestroyInstance() { |
441 if (!instance_->plugin_lib()) | 459 if (!instance_->plugin_lib()) |
442 return; | 460 return; |
443 | 461 |
444 // Unpatch if this is the last plugin instance. | 462 // Unpatch if this is the last plugin instance. |
445 if (instance_->plugin_lib()->instance_count() != 1) | 463 if (instance_->plugin_lib()->instance_count() != 1) |
446 return; | 464 return; |
(...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1164 *static_cast<const WebMouseEvent*>(&event), np_event); | 1182 *static_cast<const WebMouseEvent*>(&event), np_event); |
1165 case WebInputEvent::KeyDown: | 1183 case WebInputEvent::KeyDown: |
1166 case WebInputEvent::Char: | 1184 case WebInputEvent::Char: |
1167 case WebInputEvent::KeyUp: | 1185 case WebInputEvent::KeyUp: |
1168 if (event.size < sizeof(WebKeyboardEvent)) { | 1186 if (event.size < sizeof(WebKeyboardEvent)) { |
1169 NOTREACHED(); | 1187 NOTREACHED(); |
1170 return false; | 1188 return false; |
1171 } | 1189 } |
1172 return NPEventFromWebKeyboardEvent( | 1190 return NPEventFromWebKeyboardEvent( |
1173 *static_cast<const WebKeyboardEvent*>(&event), np_event); | 1191 *static_cast<const WebKeyboardEvent*>(&event), np_event); |
| 1192 case WebInputEvent::RawCompositionSet: |
| 1193 case WebInputEvent::RawCompositionConfirm: |
| 1194 return WebPluginIMEWin::NPEventFromWebCompositionEvent(&event, np_event); |
1174 default: | 1195 default: |
1175 return false; | 1196 return false; |
1176 } | 1197 } |
1177 } | 1198 } |
1178 | 1199 |
1179 bool WebPluginDelegateImpl::PlatformHandleInputEvent( | 1200 bool WebPluginDelegateImpl::PlatformHandleInputEvent( |
1180 const WebInputEvent& event, WebCursorInfo* cursor_info) { | 1201 const WebInputEvent& event, WebCursorInfo* cursor_info) { |
1181 DCHECK(cursor_info != NULL); | 1202 DCHECK(cursor_info != NULL); |
1182 | 1203 |
1183 NPEvent np_event; | 1204 NPEvent np_event; |
1184 if (!NPEventFromWebInputEvent(event, &np_event)) { | 1205 if (!NPEventFromWebInputEvent(event, &np_event)) { |
1185 return false; | 1206 return false; |
1186 } | 1207 } |
1187 | 1208 |
| 1209 // Send an IME event to our IME emulator to update its status. (We create an |
| 1210 // IME emulator when we receive the first IME event because not all plug-ins |
| 1211 // need the emulator.) |
| 1212 if (WebInputEvent::isCompositionEventType(event.type)) { |
| 1213 if (!plugin_ime_.get()) |
| 1214 plugin_ime_.reset(new WebPluginIMEWin); |
| 1215 plugin_ime_->Update(&event); |
| 1216 } |
| 1217 |
1188 HWND last_focus_window = NULL; | 1218 HWND last_focus_window = NULL; |
1189 | 1219 |
1190 if (ShouldTrackEventForModalLoops(&np_event)) { | 1220 if (ShouldTrackEventForModalLoops(&np_event)) { |
1191 // A windowless plugin can enter a modal loop in a NPP_HandleEvent call. | 1221 // A windowless plugin can enter a modal loop in a NPP_HandleEvent call. |
1192 // For e.g. Flash puts up a context menu when we right click on the | 1222 // For e.g. Flash puts up a context menu when we right click on the |
1193 // windowless plugin area. We detect this by setting up a message filter | 1223 // windowless plugin area. We detect this by setting up a message filter |
1194 // hook pror to calling NPP_HandleEvent on the plugin and unhook on | 1224 // hook pror to calling NPP_HandleEvent on the plugin and unhook on |
1195 // return from NPP_HandleEvent. If the plugin does enter a modal loop | 1225 // return from NPP_HandleEvent. If the plugin does enter a modal loop |
1196 // in that context we unhook on receiving the first notification in | 1226 // in that context we unhook on receiving the first notification in |
1197 // the message filter hook. | 1227 // the message filter hook. |
(...skipping 20 matching lines...) Expand all Loading... |
1218 | 1248 |
1219 handle_event_depth_++; | 1249 handle_event_depth_++; |
1220 | 1250 |
1221 bool popups_enabled = false; | 1251 bool popups_enabled = false; |
1222 | 1252 |
1223 if (IsUserGestureMessage(np_event.event)) { | 1253 if (IsUserGestureMessage(np_event.event)) { |
1224 instance()->PushPopupsEnabledState(true); | 1254 instance()->PushPopupsEnabledState(true); |
1225 popups_enabled = true; | 1255 popups_enabled = true; |
1226 } | 1256 } |
1227 | 1257 |
1228 bool ret = instance()->NPP_HandleEvent(&np_event) != 0; | 1258 // Send the input event to the plug-in. When the input event is an IME event, |
| 1259 // we call WebPluginIMEWin::SendEvent() to send all window messages stored in |
| 1260 // the IME emulator to the plug-in. (This function internally uses a mutex to |
| 1261 // prevent two or more plug-ins from accessing an IME emulator though its hook |
| 1262 // functions at once.) On the other hand, we send non-IME events directly to |
| 1263 // the plug-in because the IME emulator allows accessing its data only while |
| 1264 // it sends IME mesages. |
| 1265 bool ret = true; |
| 1266 if (WebInputEvent::isCompositionEventType(event.type) && plugin_ime_.get()) { |
| 1267 ret = plugin_ime_->SendEvents(instance()); |
| 1268 } else { |
| 1269 ret = instance()->NPP_HandleEvent(&np_event) != 0; |
| 1270 } |
1229 | 1271 |
1230 if (popups_enabled) { | 1272 if (popups_enabled) { |
1231 instance()->PopPopupsEnabledState(); | 1273 instance()->PopPopupsEnabledState(); |
1232 } | 1274 } |
1233 | 1275 |
1234 // Flash and SilverLight always return false, even when they swallow the | 1276 // Flash and SilverLight always return false, even when they swallow the |
1235 // event. Flash does this because it passes the event to its window proc, | 1277 // event. Flash does this because it passes the event to its window proc, |
1236 // which is supposed to return 0 if an event was handled. There are few | 1278 // which is supposed to return 0 if an event was handled. There are few |
1237 // exceptions, such as IME, where it sometimes returns true. | 1279 // exceptions, such as IME, where it sometimes returns true. |
1238 ret = true; | 1280 ret = true; |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1365 std::wstring::npos) { | 1407 std::wstring::npos) { |
1366 static const wchar_t kChromeExeName[] = L"chrome.exe"; | 1408 static const wchar_t kChromeExeName[] = L"chrome.exe"; |
1367 wcsncpy_s(name, orig_size, kChromeExeName, arraysize(kChromeExeName)); | 1409 wcsncpy_s(name, orig_size, kChromeExeName, arraysize(kChromeExeName)); |
1368 *name_size = | 1410 *name_size = |
1369 std::min(orig_size, static_cast<DWORD>(arraysize(kChromeExeName))); | 1411 std::min(orig_size, static_cast<DWORD>(arraysize(kChromeExeName))); |
1370 } | 1412 } |
1371 | 1413 |
1372 return rv; | 1414 return rv; |
1373 } | 1415 } |
1374 | 1416 |
| 1417 bool WebPluginDelegateImpl::GetIMEStatus(int* input_type, |
| 1418 gfx::Rect* caret_rect) { |
| 1419 if (!plugin_ime_.get()) |
| 1420 return false; |
| 1421 return plugin_ime_->GetStatus(input_type, caret_rect); |
| 1422 } |
| 1423 |
| 1424 // static |
| 1425 FARPROC WINAPI WebPluginDelegateImpl::GetProcAddressPatch(HMODULE module, |
| 1426 LPCSTR name) { |
| 1427 FARPROC imm_function = WebPluginIMEWin::GetProcAddress(name); |
| 1428 if (imm_function) |
| 1429 return imm_function; |
| 1430 return ::GetProcAddress(module, name); |
| 1431 } |
| 1432 |
1375 void WebPluginDelegateImpl::HandleCaptureForMessage(HWND window, | 1433 void WebPluginDelegateImpl::HandleCaptureForMessage(HWND window, |
1376 UINT message) { | 1434 UINT message) { |
1377 if (!WebPluginDelegateImpl::IsPluginDelegateWindow(window)) | 1435 if (!WebPluginDelegateImpl::IsPluginDelegateWindow(window)) |
1378 return; | 1436 return; |
1379 | 1437 |
1380 switch (message) { | 1438 switch (message) { |
1381 case WM_LBUTTONDOWN: | 1439 case WM_LBUTTONDOWN: |
1382 case WM_MBUTTONDOWN: | 1440 case WM_MBUTTONDOWN: |
1383 case WM_RBUTTONDOWN: | 1441 case WM_RBUTTONDOWN: |
1384 ::SetCapture(window); | 1442 ::SetCapture(window); |
(...skipping 11 matching lines...) Expand all Loading... |
1396 ::ReleaseCapture(); | 1454 ::ReleaseCapture(); |
1397 break; | 1455 break; |
1398 | 1456 |
1399 default: | 1457 default: |
1400 break; | 1458 break; |
1401 } | 1459 } |
1402 } | 1460 } |
1403 | 1461 |
1404 } // namespace npapi | 1462 } // namespace npapi |
1405 } // namespace webkit | 1463 } // namespace webkit |
OLD | NEW |