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

Side by Side Diff: webkit/plugins/npapi/webplugin_delegate_impl_win.cc

Issue 7082034: Send IME events to windowless plug-ins (Chromium side) (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 6 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 | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698