| 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 "chrome/renderer/webplugin_delegate_proxy.h" | 5 #include "chrome/renderer/webplugin_delegate_proxy.h" |
| 6 | 6 |
| 7 #include <atlbase.h> | 7 #include <atlbase.h> |
| 8 | 8 |
| 9 #include "generated_resources.h" | 9 #include "generated_resources.h" |
| 10 | 10 |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 : render_view_(render_view), | 135 : render_view_(render_view), |
| 136 mime_type_(mime_type), | 136 mime_type_(mime_type), |
| 137 clsid_(clsid), | 137 clsid_(clsid), |
| 138 plugin_(NULL), | 138 plugin_(NULL), |
| 139 windowless_(false), | 139 windowless_(false), |
| 140 first_paint_(true), | 140 first_paint_(true), |
| 141 npobject_(NULL), | 141 npobject_(NULL), |
| 142 send_deferred_update_geometry_(false), | 142 send_deferred_update_geometry_(false), |
| 143 visible_(false), | 143 visible_(false), |
| 144 sad_plugin_(NULL), | 144 sad_plugin_(NULL), |
| 145 window_script_object_(NULL), | 145 window_script_object_(NULL) { |
| 146 modal_loop_pump_messages_event_(NULL) { | |
| 147 } | 146 } |
| 148 | 147 |
| 149 WebPluginDelegateProxy::~WebPluginDelegateProxy() { | 148 WebPluginDelegateProxy::~WebPluginDelegateProxy() { |
| 150 if (npobject_) | 149 if (npobject_) |
| 151 NPN_ReleaseObject(npobject_); | 150 NPN_ReleaseObject(npobject_); |
| 152 | 151 |
| 153 if (window_script_object_) { | 152 if (window_script_object_) { |
| 154 window_script_object_->set_proxy(NULL); | 153 window_script_object_->set_proxy(NULL); |
| 155 window_script_object_->set_invalid(); | 154 window_script_object_->set_invalid(); |
| 156 } | 155 } |
| 157 | |
| 158 if (modal_loop_pump_messages_event_) { | |
| 159 CloseHandle(modal_loop_pump_messages_event_); | |
| 160 } | |
| 161 } | 156 } |
| 162 | 157 |
| 163 void WebPluginDelegateProxy::PluginDestroyed() { | 158 void WebPluginDelegateProxy::PluginDestroyed() { |
| 164 plugin_ = NULL; | 159 plugin_ = NULL; |
| 165 | 160 |
| 166 if (channel_host_) { | 161 if (channel_host_) { |
| 167 if (npobject_) { | 162 if (npobject_) { |
| 168 // When we destroy the plugin instance, the NPObjectStub NULLs out its | 163 // When we destroy the plugin instance, the NPObjectStub NULLs out its |
| 169 // pointer to the npobject (see NPObjectStub::OnChannelError). Therefore, | 164 // pointer to the npobject (see NPObjectStub::OnChannelError). Therefore, |
| 170 // we release the object before destroying the instance to avoid leaking. | 165 // we release the object before destroying the instance to avoid leaking. |
| 171 NPN_ReleaseObject(npobject_); | 166 NPN_ReleaseObject(npobject_); |
| 172 npobject_ = NULL; | 167 npobject_ = NULL; |
| 173 } | 168 } |
| 174 | 169 |
| 175 channel_host_->RemoveRoute(instance_id_); | 170 channel_host_->RemoveRoute(instance_id_); |
| 176 Send(new PluginMsg_DestroyInstance(instance_id_)); | 171 Send(new PluginMsg_DestroyInstance(instance_id_)); |
| 177 } | 172 } |
| 178 render_view_->PluginDestroyed(this); | 173 render_view_->PluginDestroyed(this); |
| 179 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 174 MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 180 } | 175 } |
| 181 | 176 |
| 182 void WebPluginDelegateProxy::FlushGeometryUpdates() { | 177 void WebPluginDelegateProxy::FlushGeometryUpdates() { |
| 183 if (send_deferred_update_geometry_) { | 178 if (send_deferred_update_geometry_) { |
| 184 send_deferred_update_geometry_ = false; | 179 send_deferred_update_geometry_ = false; |
| 185 Send(new PluginMsg_UpdateGeometry(instance_id_, | 180 Send(new PluginMsg_UpdateGeometry(instance_id_, |
| 186 plugin_rect_, | 181 plugin_rect_, |
| 187 deferred_clip_rect_, | 182 deferred_clip_rect_, |
| 188 visible_)); | 183 visible_, |
| 184 NULL, |
| 185 NULL)); |
| 189 } | 186 } |
| 190 } | 187 } |
| 191 | 188 |
| 192 bool WebPluginDelegateProxy::Initialize(const GURL& url, char** argn, | 189 bool WebPluginDelegateProxy::Initialize(const GURL& url, char** argn, |
| 193 char** argv, int argc, | 190 char** argv, int argc, |
| 194 WebPlugin* plugin, | 191 WebPlugin* plugin, |
| 195 bool load_manually) { | 192 bool load_manually) { |
| 196 std::wstring channel_name, plugin_path; | 193 std::wstring channel_name, plugin_path; |
| 197 if (!RenderThread::current()->Send(new ViewHostMsg_OpenChannelToPlugin( | 194 if (!RenderThread::current()->Send(new ViewHostMsg_OpenChannelToPlugin( |
| 198 url, mime_type_, clsid_, webkit_glue::GetWebKitLocale(), | 195 url, mime_type_, clsid_, webkit_glue::GetWebKitLocale(), |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 OnGetCPBrowsingContext) | 315 OnGetCPBrowsingContext) |
| 319 IPC_MESSAGE_UNHANDLED_ERROR() | 316 IPC_MESSAGE_UNHANDLED_ERROR() |
| 320 IPC_END_MESSAGE_MAP() | 317 IPC_END_MESSAGE_MAP() |
| 321 } | 318 } |
| 322 | 319 |
| 323 void WebPluginDelegateProxy::OnChannelError() { | 320 void WebPluginDelegateProxy::OnChannelError() { |
| 324 OnInvalidate(); | 321 OnInvalidate(); |
| 325 render_view_->PluginCrashed(plugin_path_); | 322 render_view_->PluginCrashed(plugin_path_); |
| 326 } | 323 } |
| 327 | 324 |
| 325 // Copied from render_widget.cc |
| 326 static size_t GetPaintBufSize(const gfx::Rect& rect) { |
| 327 // TODO(darin): protect against overflow |
| 328 return 4 * rect.width() * rect.height(); |
| 329 } |
| 330 |
| 328 void WebPluginDelegateProxy::UpdateGeometry(const gfx::Rect& window_rect, | 331 void WebPluginDelegateProxy::UpdateGeometry(const gfx::Rect& window_rect, |
| 329 const gfx::Rect& clip_rect, | 332 const gfx::Rect& clip_rect, |
| 330 bool visible) { | 333 bool visible) { |
| 331 plugin_rect_ = window_rect; | 334 if (!windowless_) { |
| 332 | |
| 333 if (windowless_) { | |
| 334 IPC::Message* msg = new PluginMsg_UpdateGeometry( | |
| 335 instance_id_, window_rect, clip_rect, visible); | |
| 336 msg->set_unblock(true); | |
| 337 Send(msg); | |
| 338 } else { | |
| 339 deferred_clip_rect_ = clip_rect; | 335 deferred_clip_rect_ = clip_rect; |
| 340 visible_ = visible; | 336 visible_ = visible; |
| 341 send_deferred_update_geometry_ = true; | 337 send_deferred_update_geometry_ = true; |
| 338 return; |
| 342 } | 339 } |
| 340 |
| 341 HANDLE windowless_buffer_handle = NULL; |
| 342 bool moved = plugin_rect_.x() != window_rect.x() || |
| 343 plugin_rect_.y() != window_rect.y(); |
| 344 plugin_rect_ = window_rect; |
| 345 if (!windowless_canvas_.get() || |
| 346 (window_rect.width() != windowless_canvas_->getDevice()->width() || |
| 347 window_rect.height() != windowless_canvas_->getDevice()->height())) { |
| 348 // Create a shared memory section that the plugin paints asynchronously. |
| 349 windowless_canvas_.reset(); |
| 350 if (!windowless_buffer_lock_) |
| 351 windowless_buffer_lock_.Set(CreateMutex(NULL, FALSE, NULL)); |
| 352 windowless_buffer_.reset(new SharedMemory()); |
| 353 size_t size = GetPaintBufSize(plugin_rect_); |
| 354 if (!windowless_buffer_->Create(L"", false, true, size)) { |
| 355 DCHECK(false); |
| 356 windowless_buffer_.reset(); |
| 357 return; |
| 358 } |
| 359 |
| 360 windowless_canvas_.reset(new gfx::PlatformCanvasWin( |
| 361 plugin_rect_.width(), plugin_rect_.height(), false, |
| 362 windowless_buffer_->handle())); |
| 363 windowless_canvas_->translate(static_cast<SkScalar>(-plugin_rect_.x()), |
| 364 static_cast<SkScalar>(-plugin_rect_.y())); |
| 365 windowless_canvas_->getTopPlatformDevice().accessBitmap(true). |
| 366 eraseARGB(0, 0, 0, 0); |
| 367 windowless_buffer_handle = windowless_buffer_->handle(); |
| 368 } else if (moved) { |
| 369 windowless_canvas_->resetMatrix(); |
| 370 windowless_canvas_->translate(static_cast<SkScalar>(-plugin_rect_.x()), |
| 371 static_cast<SkScalar>(-plugin_rect_.y())); |
| 372 } |
| 373 |
| 374 IPC::Message* msg = new PluginMsg_UpdateGeometry( |
| 375 instance_id_, window_rect, clip_rect, visible, windowless_buffer_handle, |
| 376 windowless_buffer_lock_); |
| 377 msg->set_unblock(true); |
| 378 Send(msg); |
| 343 } | 379 } |
| 344 | 380 |
| 345 void WebPluginDelegateProxy::Paint(HDC hdc, const gfx::Rect& damaged_rect) { | 381 void WebPluginDelegateProxy::Paint(HDC hdc, const gfx::Rect& damaged_rect) { |
| 346 // If the plugin is no longer connected (channel crashed) draw a crashed | 382 // If the plugin is no longer connected (channel crashed) draw a crashed |
| 347 // plugin bitmap | 383 // plugin bitmap |
| 348 if (!channel_host_->channel_valid()) { | 384 if (!channel_host_->channel_valid()) { |
| 349 PaintSadPlugin(hdc, damaged_rect); | 385 PaintSadPlugin(hdc, damaged_rect); |
| 350 return; | 386 return; |
| 351 } | 387 } |
| 352 | 388 |
| 353 // Can't duplicate an HDC handle, so get all the parameters we need in | 389 // No paint events for windowed plugins. However, if it is the first paint |
| 354 // order to recreate the same HDC in the plugin process. | 390 // we don't know yet whether the plugin is windowless or not, so we have to |
| 355 PluginMsg_Paint_Params params; | 391 // send the event. |
| 356 HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP)); | 392 if (!windowless_ && !first_paint_) { |
| 357 if (bitmap == NULL) { | 393 // TODO(maruel): That's not true for printing and thumbnail capture. |
| 358 NOTREACHED(); | 394 // We shall use PrintWindow() to draw the window. |
| 359 return; | 395 return; |
| 360 } | 396 } |
| 397 first_paint_ = false; |
| 361 | 398 |
| 362 DIBSECTION dibsection = { 0 }; | 399 // We got a paint before the plugin's coordinates, so there's no buffer to |
| 363 int result = GetObject(bitmap, sizeof(dibsection), &dibsection); | 400 // copy from. |
| 364 if (!result) { | 401 if (!windowless_buffer_.get()) |
| 365 NOTREACHED(); | |
| 366 return; | |
| 367 } | |
| 368 | |
| 369 win_util::ScopedHRGN hrgn(CreateRectRgn(0, 0, 0, 0)); | |
| 370 result = GetClipRgn(hdc, hrgn); | |
| 371 if (result == -1) { | |
| 372 NOTREACHED(); | |
| 373 return; | |
| 374 } | |
| 375 | |
| 376 params.size.SetSize(dibsection.dsBmih.biWidth, dibsection.dsBmih.biHeight); | |
| 377 if (result == 0) { | |
| 378 // No clipping region. | |
| 379 params.clip_rect.set_width(params.size.width()); | |
| 380 params.clip_rect.set_height(params.size.height()); | |
| 381 } else { | |
| 382 RECT clip_rect; | |
| 383 result = GetRgnBox(hrgn, &clip_rect); | |
| 384 DCHECK_NE(result, 0); | |
| 385 params.clip_rect = clip_rect; | |
| 386 } | |
| 387 | |
| 388 if (!GetWorldTransform(hdc, ¶ms.xf)) { | |
| 389 NOTREACHED(); | |
| 390 return; | |
| 391 } | |
| 392 | |
| 393 params.damaged_rect = damaged_rect; | |
| 394 params.shared_memory = dibsection.dshSection; | |
| 395 | |
| 396 // Normal painting code path. | |
| 397 if (dibsection.dshSection) { | |
| 398 // No paint events for windowed plugins. However, if it is the first paint | |
| 399 // we don't know yet whether the plugin is windowless or not, so we have to | |
| 400 // send the event. | |
| 401 if (!windowless_ && !first_paint_) { | |
| 402 // TODO(maruel): That's not true for printing and thumbnail capture. | |
| 403 // We shall use PrintWindow() to draw the window. | |
| 404 return; | |
| 405 } | |
| 406 first_paint_ = false; | |
| 407 | |
| 408 DCHECK(params.size.width()); | |
| 409 DCHECK(params.size.height()); | |
| 410 Send(new PluginMsg_Paint(instance_id_, params)); | |
| 411 return; | |
| 412 } | |
| 413 | |
| 414 params.size.SetSize(damaged_rect.width(), damaged_rect.height()); | |
| 415 // Pass the window size instead. | |
| 416 if (!windowless_) | |
| 417 params.damaged_rect = plugin_rect_; | |
| 418 | |
| 419 // When the thumbnail is painted or during printing, a shared memory handle | |
| 420 // isn't given to CreateDIBSection so we don't get one now. | |
| 421 size_t bytes = 0; | |
| 422 SharedMemoryHandle emf_buffer = NULL; | |
| 423 PluginMsg_PaintIntoSharedMemory* msg = | |
| 424 new PluginMsg_PaintIntoSharedMemory(instance_id_, params, &emf_buffer, | |
| 425 &bytes); | |
| 426 if (!Send(msg)) | |
| 427 return; | 402 return; |
| 428 | 403 |
| 429 if (!emf_buffer) { | 404 // Limit the damaged rectangle to whatever is contained inside the plugin |
| 430 NOTREACHED(); | 405 // rectangle, as that's the rectangle that we'll bitblt to the hdc. |
| 431 return; | 406 gfx::Rect rect = damaged_rect.Intersect(plugin_rect_); |
| 432 } | |
| 433 | 407 |
| 434 // memory's destructor will automatically close emf_buffer. | 408 DWORD wait_result = WaitForSingleObject(windowless_buffer_lock_, INFINITE); |
| 435 SharedMemory memory(emf_buffer, true); | 409 DCHECK(wait_result == WAIT_OBJECT_0); |
| 436 if (!memory.Map(bytes)) { | |
| 437 NOTREACHED(); | |
| 438 return; | |
| 439 } | |
| 440 | 410 |
| 441 gfx::Emf emf; | 411 BLENDFUNCTION m_bf; |
| 442 if (!emf.CreateFromData(memory.memory(), bytes)) { | 412 m_bf.BlendOp = AC_SRC_OVER; |
| 443 NOTREACHED(); | 413 m_bf.BlendFlags = 0; |
| 444 return; | 414 m_bf.SourceConstantAlpha = 255; |
| 445 } | 415 m_bf.AlphaFormat = AC_SRC_ALPHA; |
| 446 emf.Playback(hdc, NULL); | 416 |
| 417 HDC new_hdc = windowless_canvas_->getTopPlatformDevice().getBitmapDC(); |
| 418 AlphaBlend(hdc, rect.x(), rect.y(), rect.width(), rect.height(), |
| 419 new_hdc, rect.x(), rect.y(), rect.width(), rect.height(), m_bf); |
| 420 |
| 421 BOOL result = ReleaseMutex(windowless_buffer_lock_); |
| 422 DCHECK(result); |
| 447 } | 423 } |
| 448 | 424 |
| 449 void WebPluginDelegateProxy::Print(HDC hdc) { | 425 void WebPluginDelegateProxy::Print(HDC hdc) { |
| 450 PluginMsg_PrintResponse_Params params = { 0 }; | 426 PluginMsg_PrintResponse_Params params = { 0 }; |
| 451 Send(new PluginMsg_Print(instance_id_, ¶ms)); | 427 Send(new PluginMsg_Print(instance_id_, ¶ms)); |
| 452 | 428 |
| 453 SharedMemory memory(params.shared_memory, true); | 429 SharedMemory memory(params.shared_memory, true); |
| 454 if (!memory.Map(params.size)) { | 430 if (!memory.Map(params.size)) { |
| 455 NOTREACHED(); | 431 NOTREACHED(); |
| 456 return; | 432 return; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 NOTREACHED() << "GetWindowHandle can't be called on the proxy."; | 488 NOTREACHED() << "GetWindowHandle can't be called on the proxy."; |
| 513 return NULL; | 489 return NULL; |
| 514 } | 490 } |
| 515 | 491 |
| 516 void WebPluginDelegateProxy::OnSetWindow( | 492 void WebPluginDelegateProxy::OnSetWindow( |
| 517 HWND window, HANDLE modal_loop_pump_messages_event) { | 493 HWND window, HANDLE modal_loop_pump_messages_event) { |
| 518 windowless_ = window == NULL; | 494 windowless_ = window == NULL; |
| 519 if (plugin_) | 495 if (plugin_) |
| 520 plugin_->SetWindow(window, modal_loop_pump_messages_event); | 496 plugin_->SetWindow(window, modal_loop_pump_messages_event); |
| 521 | 497 |
| 522 modal_loop_pump_messages_event_ = modal_loop_pump_messages_event; | 498 DCHECK(modal_loop_pump_messages_event_ == NULL); |
| 499 modal_loop_pump_messages_event_.Set(modal_loop_pump_messages_event); |
| 523 } | 500 } |
| 524 | 501 |
| 525 void WebPluginDelegateProxy::OnCancelResource(int id) { | 502 void WebPluginDelegateProxy::OnCancelResource(int id) { |
| 526 if (plugin_) | 503 if (plugin_) |
| 527 plugin_->CancelResource(id); | 504 plugin_->CancelResource(id); |
| 528 } | 505 } |
| 529 | 506 |
| 530 void WebPluginDelegateProxy::OnInvalidate() { | 507 void WebPluginDelegateProxy::OnInvalidate() { |
| 531 if (plugin_) | 508 if (plugin_) |
| 532 plugin_->Invalidate(); | 509 plugin_->Invalidate(); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 return proxy; | 639 return proxy; |
| 663 } | 640 } |
| 664 | 641 |
| 665 void WebPluginDelegateProxy::URLRequestRouted(const std::string& url, | 642 void WebPluginDelegateProxy::URLRequestRouted(const std::string& url, |
| 666 bool notify_needed, | 643 bool notify_needed, |
| 667 void* notify_data) { | 644 void* notify_data) { |
| 668 Send(new PluginMsg_URLRequestRouted(instance_id_, url, notify_needed, | 645 Send(new PluginMsg_URLRequestRouted(instance_id_, url, notify_needed, |
| 669 notify_data)); | 646 notify_data)); |
| 670 } | 647 } |
| 671 | 648 |
| OLD | NEW |