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

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

Issue 193024: In prepartion for switching off the activex control, make WMP always use the ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 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
« no previous file with comments | « webkit/glue/plugins/webplugin_delegate_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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" 11 #include "base/iat_patch.h"
12 #include "base/lazy_instance.h" 12 #include "base/lazy_instance.h"
13 #include "base/message_loop.h" 13 #include "base/message_loop.h"
14 #include "base/registry.h"
15 #include "base/scoped_ptr.h"
14 #include "base/stats_counters.h" 16 #include "base/stats_counters.h"
15 #include "base/string_util.h" 17 #include "base/string_util.h"
18 #include "base/win_util.h"
16 #include "webkit/api/public/WebInputEvent.h" 19 #include "webkit/api/public/WebInputEvent.h"
17 #include "webkit/default_plugin/plugin_impl.h" 20 #include "webkit/default_plugin/plugin_impl.h"
18 #include "webkit/glue/glue_util.h" 21 #include "webkit/glue/glue_util.h"
19 #include "webkit/glue/plugins/plugin_constants_win.h" 22 #include "webkit/glue/plugins/plugin_constants_win.h"
20 #include "webkit/glue/plugins/plugin_instance.h" 23 #include "webkit/glue/plugins/plugin_instance.h"
21 #include "webkit/glue/plugins/plugin_lib.h" 24 #include "webkit/glue/plugins/plugin_lib.h"
22 #include "webkit/glue/plugins/plugin_list.h" 25 #include "webkit/glue/plugins/plugin_list.h"
23 #include "webkit/glue/plugins/plugin_stream_url.h" 26 #include "webkit/glue/plugins/plugin_stream_url.h"
24 #include "webkit/glue/webkit_glue.h" 27 #include "webkit/glue/webkit_glue.h"
25 #include "webkit/glue/webplugin.h" 28 #include "webkit/glue/webplugin.h"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 base::LazyInstance<std::list<MSG> > g_throttle_queue(base::LINKER_INITIALIZED); 63 base::LazyInstance<std::list<MSG> > g_throttle_queue(base::LINKER_INITIALIZED);
61 64
62 // Helper object for patching the TrackPopupMenu API. 65 // Helper object for patching the TrackPopupMenu API.
63 base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_track_popup_menu( 66 base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_track_popup_menu(
64 base::LINKER_INITIALIZED); 67 base::LINKER_INITIALIZED);
65 68
66 // Helper object for patching the SetCursor API. 69 // Helper object for patching the SetCursor API.
67 base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_set_cursor( 70 base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_set_cursor(
68 base::LINKER_INITIALIZED); 71 base::LINKER_INITIALIZED);
69 72
73 // Helper object for patching the RegEnumKeyExW API.
74 base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w(
75 base::LINKER_INITIALIZED);
76
70 // http://crbug.com/16114 77 // http://crbug.com/16114
71 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow 78 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow
72 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. 79 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL.
73 // Doing so allows removing NPP_SetWindow call during painting a windowless 80 // Doing so allows removing NPP_SetWindow call during painting a windowless
74 // plugin, which otherwise could trigger layout change while painting by 81 // plugin, which otherwise could trigger layout change while painting by
75 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes. 82 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes.
76 // TODO(dglazkov): If this approach doesn't produce regressions, move class to 83 // TODO(dglazkov): If this approach doesn't produce regressions, move class to
77 // webplugin_delegate_impl.h and implement for other platforms. 84 // webplugin_delegate_impl.h and implement for other platforms.
78 class DrawableContextEnforcer { 85 class DrawableContextEnforcer {
79 public: 86 public:
(...skipping 12 matching lines...) Expand all
92 99
93 DeleteDC(static_cast<HDC>(window_->window)); 100 DeleteDC(static_cast<HDC>(window_->window));
94 window_->window = NULL; 101 window_->window = NULL;
95 } 102 }
96 103
97 private: 104 private:
98 NPWindow* window_; 105 NPWindow* window_;
99 bool disposable_dc_; 106 bool disposable_dc_;
100 }; 107 };
101 108
109 // These are from ntddk.h
110 typedef LONG NTSTATUS;
111
112 #ifndef STATUS_SUCCESS
113 #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
114 #endif
115
116 #ifndef STATUS_BUFFER_TOO_SMALL
117 #define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
118 #endif
119
120 typedef enum _KEY_INFORMATION_CLASS {
121 KeyBasicInformation,
122 KeyNodeInformation,
123 KeyFullInformation,
124 KeyNameInformation,
125 KeyCachedInformation,
126 KeyVirtualizationInformation
127 } KEY_INFORMATION_CLASS;
128
129 typedef struct _KEY_NAME_INFORMATION {
130 ULONG NameLength;
131 WCHAR Name[1];
132 } KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
133
134 typedef DWORD (__stdcall *ZwQueryKeyType)(
135 HANDLE key_handle,
136 int key_information_class,
137 PVOID key_information,
138 ULONG length,
139 PULONG result_length);
140
141 // Returns a key's full path.
142 std::wstring GetKeyPath(HKEY key) {
143 if (key == NULL)
144 return L"";
145
146 HMODULE dll = GetModuleHandle(L"ntdll.dll");
147 if (dll == NULL)
148 return L"";
149
150 ZwQueryKeyType func = reinterpret_cast<ZwQueryKeyType>(
151 ::GetProcAddress(dll, "ZwQueryKey"));
152 if (func == NULL)
153 return L"";
154
155 DWORD size = 0;
156 DWORD result = 0;
157 result = func(key, KeyNameInformation, 0, 0, &size);
158 if (result != STATUS_BUFFER_TOO_SMALL)
159 return L"";
160
161 scoped_array<char> buffer(new char[size]);
162 if (buffer.get() == NULL)
163 return L"";
164
165 result = func(key, KeyNameInformation, buffer.get(), size, &size);
166 if (result != STATUS_SUCCESS)
167 return L"";
168
169 KEY_NAME_INFORMATION* info =
170 reinterpret_cast<KEY_NAME_INFORMATION*>(buffer.get());
171 return std::wstring(info->Name, info->NameLength / sizeof(wchar_t));
172 }
102 } // namespace 173 } // namespace
103 174
104 bool WebPluginDelegateImpl::IsPluginDelegateWindow(HWND window) { 175 bool WebPluginDelegateImpl::IsPluginDelegateWindow(HWND window) {
105 // We use a buffer that is one char longer than we need to detect cases where 176 // We use a buffer that is one char longer than we need to detect cases where
106 // kNativeWindowClassName is a prefix of the given window's class name. It 177 // kNativeWindowClassName is a prefix of the given window's class name. It
107 // happens that GetClassNameW will just silently truncate the class name to 178 // happens that GetClassNameW will just silently truncate the class name to
108 // fit into the given buffer. 179 // fit into the given buffer.
109 wchar_t class_name[arraysize(kNativeWindowClassName) + 1]; 180 wchar_t class_name[arraysize(kNativeWindowClassName) + 1];
110 if (!GetClassNameW(window, class_name, arraysize(class_name))) 181 if (!GetClassNameW(window, class_name, arraysize(class_name)))
111 return false; 182 return false;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 } 270 }
200 } 271 }
201 quirks_ |= PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS; 272 quirks_ |= PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS;
202 } else if (plugin_info.name.find(L"Windows Media Player") != 273 } else if (plugin_info.name.find(L"Windows Media Player") !=
203 std::wstring::npos) { 274 std::wstring::npos) {
204 // Windows Media Player needs two NPP_SetWindow calls. 275 // Windows Media Player needs two NPP_SetWindow calls.
205 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; 276 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE;
206 277
207 // Windowless mode doesn't work in the WMP NPAPI plugin. 278 // Windowless mode doesn't work in the WMP NPAPI plugin.
208 quirks_ |= PLUGIN_QUIRK_NO_WINDOWLESS; 279 quirks_ |= PLUGIN_QUIRK_NO_WINDOWLESS;
280
281 // Non-admin users on XP couldn't modify the key to force the new UI.
282 quirks_ |= PLUGIN_QUIRK_PATCH_REGENUMKEYEXW;
209 } else if (instance_->mime_type() == "audio/x-pn-realaudio-plugin" || 283 } else if (instance_->mime_type() == "audio/x-pn-realaudio-plugin" ||
210 filename == "nppl3260.dll") { 284 filename == "nppl3260.dll") {
211 quirks_ |= PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY; 285 quirks_ |= PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY;
212 } else if (plugin_info.name.find(L"VLC Multimedia Plugin") != 286 } else if (plugin_info.name.find(L"VLC Multimedia Plugin") !=
213 std::wstring::npos || 287 std::wstring::npos ||
214 plugin_info.name.find(L"VLC Multimedia Plug-in") != 288 plugin_info.name.find(L"VLC Multimedia Plug-in") !=
215 std::wstring::npos) { 289 std::wstring::npos) {
216 // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window 290 // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window
217 // handle 291 // handle
218 quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY; 292 quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY;
219 // VLC 0.8.6d and 0.8.6e crash if multiple instances are created. 293 // VLC 0.8.6d and 0.8.6e crash if multiple instances are created.
220 quirks_ |= PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES; 294 quirks_ |= PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES;
221 } else if (filename == "npctrl.dll") { 295 } else if (filename == "npctrl.dll") { // Silverlight
222 // Explanation for this quirk can be found in 296 // Explanation for this quirk can be found in
223 // WebPluginDelegateImpl::Initialize. 297 // WebPluginDelegateImpl::Initialize.
224 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; 298 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR;
225 } 299 }
226 } 300 }
227 301
228 WebPluginDelegateImpl::~WebPluginDelegateImpl() { 302 WebPluginDelegateImpl::~WebPluginDelegateImpl() {
229 if (::IsWindow(dummy_window_for_activation_)) { 303 if (::IsWindow(dummy_window_for_activation_)) {
230 ::DestroyWindow(dummy_window_for_activation_); 304 ::DestroyWindow(dummy_window_for_activation_);
231 } 305 }
(...skipping 17 matching lines...) Expand all
249 } 323 }
250 324
251 void WebPluginDelegateImpl::PlatformInitialize() { 325 void WebPluginDelegateImpl::PlatformInitialize() {
252 plugin_->SetWindow(windowed_handle_); 326 plugin_->SetWindow(windowed_handle_);
253 if (windowless_) { 327 if (windowless_) {
254 CreateDummyWindowForActivation(); 328 CreateDummyWindowForActivation();
255 handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); 329 handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
256 plugin_->SetWindowlessPumpEvent(handle_event_pump_messages_event_); 330 plugin_->SetWindowlessPumpEvent(handle_event_pump_messages_event_);
257 } 331 }
258 332
259 // The windowless version of the Silverlight plugin calls the 333 // Windowless plugins call the WindowFromPoint API and passes the result of
260 // WindowFromPoint API and passes the result of that to the 334 // that to the TrackPopupMenu API call as the owner window. This causes the
261 // TrackPopupMenu API call as the owner window. This causes the API 335 // API to fail as the API expects the window handle to live on the same thread
262 // to fail as the API expects the window handle to live on the same 336 // as the caller. It works in the other browsers as the plugin lives on the
263 // thread as the caller. It works in the other browsers as the plugin 337 // browser thread. Our workaround is to intercept the TrackPopupMenu API and
264 // lives on the browser thread. Our workaround is to intercept the 338 // replace the window handle with the dummy activation window.
265 // TrackPopupMenu API for Silverlight and replace the window handle
266 // with the dummy activation window.
267 if (windowless_ && !g_iat_patch_track_popup_menu.Pointer()->is_patched()) { 339 if (windowless_ && !g_iat_patch_track_popup_menu.Pointer()->is_patched()) {
268 g_iat_patch_track_popup_menu.Pointer()->Patch( 340 g_iat_patch_track_popup_menu.Pointer()->Patch(
269 GetPluginPath().value().c_str(), "user32.dll", "TrackPopupMenu", 341 GetPluginPath().value().c_str(), "user32.dll", "TrackPopupMenu",
270 WebPluginDelegateImpl::TrackPopupMenuPatch); 342 WebPluginDelegateImpl::TrackPopupMenuPatch);
271 } 343 }
272 344
273 // Windowless plugins can set cursors by calling the SetCursor API. This 345 // Windowless plugins can set cursors by calling the SetCursor API. This
274 // works because the thread inputs of the browser UI thread and the plugin 346 // works because the thread inputs of the browser UI thread and the plugin
275 // thread are attached. We intercept the SetCursor API for windowless plugins 347 // thread are attached. We intercept the SetCursor API for windowless plugins
276 // and remember the cursor being set. This is shipped over to the browser 348 // and remember the cursor being set. This is shipped over to the browser
277 // in the HandleEvent call, which ensures that the cursor does not change 349 // in the HandleEvent call, which ensures that the cursor does not change
278 // when a windowless plugin instance changes the cursor in a background tab. 350 // when a windowless plugin instance changes the cursor in a background tab.
279 if (windowless_ && !g_iat_patch_set_cursor.Pointer()->is_patched() && 351 if (windowless_ && !g_iat_patch_set_cursor.Pointer()->is_patched() &&
280 (quirks_ & PLUGIN_QUIRK_PATCH_SETCURSOR)) { 352 (quirks_ & PLUGIN_QUIRK_PATCH_SETCURSOR)) {
281 g_iat_patch_set_cursor.Pointer()->Patch( 353 g_iat_patch_set_cursor.Pointer()->Patch(
282 GetPluginPath().value().c_str(), "user32.dll", "SetCursor", 354 GetPluginPath().value().c_str(), "user32.dll", "SetCursor",
283 WebPluginDelegateImpl::SetCursorPatch); 355 WebPluginDelegateImpl::SetCursorPatch);
284 } 356 }
357
358 // On XP, WMP will use its old UI unless a registry key under HKLM has the
359 // name of the current process. We do it in the installer for admin users,
360 // for the rest patch this function.
361 if ((quirks_ & PLUGIN_QUIRK_PATCH_REGENUMKEYEXW) &&
362 win_util::GetWinVersion() == win_util::WINVERSION_XP &&
363 !RegKey().Open(HKEY_LOCAL_MACHINE,
364 L"SOFTWARE\\Microsoft\\MediaPlayer\\ShimInclusionList\\chrome.exe") &&
365 !g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) {
366 g_iat_patch_reg_enum_key_ex_w.Pointer()->Patch(
367 L"wmpdxm.dll", "advapi32.dll", "RegEnumKeyExW",
368 WebPluginDelegateImpl::RegEnumKeyExWPatch);
369 }
285 } 370 }
286 371
287 void WebPluginDelegateImpl::PlatformDestroyInstance() { 372 void WebPluginDelegateImpl::PlatformDestroyInstance() {
288 if (instance_->plugin_lib()) { 373 if (!instance_->plugin_lib())
289 // Unpatch if this is the last plugin instance. 374 return;
290 if (instance_->plugin_lib()->instance_count() == 1) {
291 if (g_iat_patch_set_cursor.Pointer()->is_patched()) {
292 g_iat_patch_set_cursor.Pointer()->Unpatch();
293 }
294 375
295 if (g_iat_patch_track_popup_menu.Pointer()->is_patched()) { 376 // Unpatch if this is the last plugin instance.
296 g_iat_patch_track_popup_menu.Pointer()->Unpatch(); 377 if (instance_->plugin_lib()->instance_count() != 1)
297 } 378 return;
298 } 379
299 } 380 if (g_iat_patch_set_cursor.Pointer()->is_patched())
381 g_iat_patch_set_cursor.Pointer()->Unpatch();
382
383 if (g_iat_patch_track_popup_menu.Pointer()->is_patched())
384 g_iat_patch_track_popup_menu.Pointer()->Unpatch();
385
386 if (g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched())
387 g_iat_patch_reg_enum_key_ex_w.Pointer()->Unpatch();
300 } 388 }
301 389
302 void WebPluginDelegateImpl::Paint(HDC hdc, const gfx::Rect& rect) { 390 void WebPluginDelegateImpl::Paint(HDC hdc, const gfx::Rect& rect) {
303 if (windowless_) 391 if (windowless_)
304 WindowlessPaint(hdc, rect); 392 WindowlessPaint(hdc, rect);
305 } 393 }
306 394
307 void WebPluginDelegateImpl::Print(HDC hdc) { 395 void WebPluginDelegateImpl::Print(HDC hdc) {
308 // Disabling the call to NPP_Print as it causes a crash in 396 // Disabling the call to NPP_Print as it causes a crash in
309 // flash in some cases. In any case this does not work as expected 397 // flash in some cases. In any case this does not work as expected
(...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 1237
1150 // It is ok to pass NULL here to GetCursor as we are not looking for cursor 1238 // It is ok to pass NULL here to GetCursor as we are not looking for cursor
1151 // types defined by Webkit. 1239 // types defined by Webkit.
1152 HCURSOR previous_cursor = 1240 HCURSOR previous_cursor =
1153 g_current_plugin_instance->current_windowless_cursor_.GetCursor(NULL); 1241 g_current_plugin_instance->current_windowless_cursor_.GetCursor(NULL);
1154 1242
1155 g_current_plugin_instance->current_windowless_cursor_.InitFromExternalCursor( 1243 g_current_plugin_instance->current_windowless_cursor_.InitFromExternalCursor(
1156 cursor); 1244 cursor);
1157 return previous_cursor; 1245 return previous_cursor;
1158 } 1246 }
1247
1248 LONG WINAPI WebPluginDelegateImpl::RegEnumKeyExWPatch(
1249 HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved,
1250 LPWSTR class_name, LPDWORD class_size, PFILETIME last_write_time) {
1251 DWORD orig_size = *name_size;
1252 LONG rv = RegEnumKeyExW(key, index, name, name_size, reserved, class_name,
1253 class_size, last_write_time);
1254 if (rv == ERROR_SUCCESS &&
1255 GetKeyPath(key).find(L"Microsoft\\MediaPlayer\\ShimInclusionList") !=
1256 std::wstring::npos) {
1257 static const wchar_t kChromeExeName[] = L"chrome.exe";
1258 wcsncpy_s(name, orig_size, kChromeExeName, arraysize(kChromeExeName));
1259 *name_size =
1260 std::min(orig_size, static_cast<DWORD>(arraysize(kChromeExeName)));
1261 }
1262
1263 return rv;
1264 }
OLDNEW
« no previous file with comments | « webkit/glue/plugins/webplugin_delegate_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698