| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 "content/renderer/browser_plugin/browser_plugin.h" | 5 #include "content/renderer/browser_plugin/browser_plugin.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 #include "ui/events/keycodes/keyboard_codes.h" | 33 #include "ui/events/keycodes/keyboard_codes.h" |
| 34 | 34 |
| 35 using blink::WebCanvas; | 35 using blink::WebCanvas; |
| 36 using blink::WebPluginContainer; | 36 using blink::WebPluginContainer; |
| 37 using blink::WebPluginParams; | 37 using blink::WebPluginParams; |
| 38 using blink::WebPoint; | 38 using blink::WebPoint; |
| 39 using blink::WebRect; | 39 using blink::WebRect; |
| 40 using blink::WebURL; | 40 using blink::WebURL; |
| 41 using blink::WebVector; | 41 using blink::WebVector; |
| 42 | 42 |
| 43 namespace { |
| 44 typedef std::map<blink::WebPluginContainer*, content::BrowserPlugin*> |
| 45 PluginContainerMap; |
| 46 static base::LazyInstance<PluginContainerMap> g_plugin_container_map = |
| 47 LAZY_INSTANCE_INITIALIZER; |
| 48 |
| 49 } // namespace |
| 50 |
| 43 namespace content { | 51 namespace content { |
| 44 | 52 |
| 45 BrowserPlugin::BrowserPlugin(RenderViewImpl* render_view, | 53 BrowserPlugin::BrowserPlugin(RenderViewImpl* render_view, |
| 46 blink::WebFrame* frame, | 54 blink::WebFrame* frame, |
| 47 bool auto_navigate) | 55 bool auto_navigate) |
| 48 : guest_instance_id_(browser_plugin::kInstanceIDNone), | 56 : guest_instance_id_(browser_plugin::kInstanceIDNone), |
| 49 attached_(false), | 57 attached_(false), |
| 50 render_view_(render_view->AsWeakPtr()), | 58 render_view_(render_view->AsWeakPtr()), |
| 51 render_view_routing_id_(render_view->GetRoutingID()), | 59 render_view_routing_id_(render_view->GetRoutingID()), |
| 52 container_(NULL), | 60 container_(NULL), |
| 53 paint_ack_received_(true), | 61 paint_ack_received_(true), |
| 54 last_device_scale_factor_(GetDeviceScaleFactor()), | 62 last_device_scale_factor_(GetDeviceScaleFactor()), |
| 55 sad_guest_(NULL), | 63 sad_guest_(NULL), |
| 56 guest_crashed_(false), | 64 guest_crashed_(false), |
| 57 content_window_routing_id_(MSG_ROUTING_NONE), | 65 content_window_routing_id_(MSG_ROUTING_NONE), |
| 58 plugin_focused_(false), | 66 plugin_focused_(false), |
| 59 visible_(true), | 67 visible_(true), |
| 60 auto_navigate_(auto_navigate), | 68 auto_navigate_(auto_navigate), |
| 61 mouse_locked_(false), | 69 mouse_locked_(false), |
| 62 browser_plugin_manager_(render_view->GetBrowserPluginManager()), | 70 browser_plugin_manager_(render_view->GetBrowserPluginManager()), |
| 63 weak_ptr_factory_(this) { | 71 weak_ptr_factory_(this) { |
| 64 } | 72 } |
| 65 | 73 |
| 66 BrowserPlugin::~BrowserPlugin() { | 74 BrowserPlugin::~BrowserPlugin() { |
| 75 browser_plugin_manager()->RemoveBrowserPluginInternal( |
| 76 browser_plugin_instance_id_); |
| 67 // If the BrowserPlugin has never navigated then the browser process and | 77 // If the BrowserPlugin has never navigated then the browser process and |
| 68 // BrowserPluginManager don't know about it and so there is nothing to do | 78 // BrowserPluginManager don't know about it and so there is nothing to do |
| 69 // here. | 79 // here. |
| 70 if (!HasGuestInstanceID()) | 80 if (!HasGuestInstanceID()) |
| 71 return; | 81 return; |
| 72 browser_plugin_manager()->RemoveBrowserPlugin(guest_instance_id_); | 82 browser_plugin_manager()->RemoveBrowserPlugin(guest_instance_id_); |
| 73 browser_plugin_manager()->Send( | 83 browser_plugin_manager()->Send( |
| 74 new BrowserPluginHostMsg_PluginDestroyed(render_view_routing_id_, | 84 new BrowserPluginHostMsg_PluginDestroyed(render_view_routing_id_, |
| 75 guest_instance_id_)); | 85 guest_instance_id_)); |
| 76 } | 86 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 | 161 |
| 152 if (compositing_helper_) | 162 if (compositing_helper_) |
| 153 compositing_helper_->SetContentsOpaque(opaque); | 163 compositing_helper_->SetContentsOpaque(opaque); |
| 154 | 164 |
| 155 browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetContentsOpaque( | 165 browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetContentsOpaque( |
| 156 render_view_routing_id_, | 166 render_view_routing_id_, |
| 157 guest_instance_id_, | 167 guest_instance_id_, |
| 158 opaque)); | 168 opaque)); |
| 159 } | 169 } |
| 160 | 170 |
| 161 void BrowserPlugin::Attach(int guest_instance_id, | 171 void BrowserPlugin::Attach(int guest_instance_id) { |
| 162 scoped_ptr<base::DictionaryValue> extra_params) { | 172 CHECK_NE(browser_plugin::kInstanceIDNone, guest_instance_id); |
| 163 CHECK(guest_instance_id != browser_plugin::kInstanceIDNone); | |
| 164 | |
| 165 // If this BrowserPlugin is already attached to a guest, then kill the guest. | 173 // If this BrowserPlugin is already attached to a guest, then kill the guest. |
| 166 if (HasGuestInstanceID()) { | 174 if (HasGuestInstanceID()) { |
| 167 if (guest_instance_id == guest_instance_id_) | 175 if (guest_instance_id == guest_instance_id_) |
| 168 return; | 176 return; |
| 169 guest_crashed_ = false; | 177 guest_crashed_ = false; |
| 170 EnableCompositing(false); | 178 EnableCompositing(false); |
| 171 if (compositing_helper_) { | 179 if (compositing_helper_) { |
| 172 compositing_helper_->OnContainerDestroy(); | 180 compositing_helper_->OnContainerDestroy(); |
| 173 compositing_helper_ = NULL; | 181 compositing_helper_ = NULL; |
| 174 } | 182 } |
| 175 browser_plugin_manager()->RemoveBrowserPlugin(guest_instance_id_); | 183 browser_plugin_manager()->RemoveBrowserPlugin(guest_instance_id_); |
| 176 browser_plugin_manager()->Send(new BrowserPluginHostMsg_PluginDestroyed( | 184 browser_plugin_manager()->Send(new BrowserPluginHostMsg_PluginDestroyed( |
| 177 render_view_routing_id_, guest_instance_id_)); | 185 render_view_routing_id_, guest_instance_id_)); |
| 178 } | 186 } |
| 179 | 187 |
| 180 // This API may be called directly without setting the src attribute. | |
| 181 // In that case, we need to make sure we don't allocate another instance ID. | |
| 182 guest_instance_id_ = guest_instance_id; | 188 guest_instance_id_ = guest_instance_id; |
| 183 browser_plugin_manager()->AddBrowserPlugin(guest_instance_id, this); | 189 browser_plugin_manager()->AddBrowserPlugin(guest_instance_id, this); |
| 184 | 190 |
| 185 BrowserPluginHostMsg_Attach_Params attach_params; | 191 BrowserPluginHostMsg_Attach_Params attach_params; |
| 186 attach_params.focused = ShouldGuestBeFocused(); | 192 attach_params.focused = ShouldGuestBeFocused(); |
| 187 attach_params.visible = visible_; | 193 attach_params.visible = visible_; |
| 188 attach_params.opaque = !GetAllowTransparencyAttribute(); | 194 attach_params.opaque = !GetAllowTransparencyAttribute(); |
| 189 attach_params.origin = plugin_rect().origin(); | 195 attach_params.origin = plugin_rect().origin(); |
| 190 GetSizeParams(&attach_params.resize_guest_params, false); | 196 GetSizeParams(&attach_params.resize_guest_params, false); |
| 191 | 197 |
| 192 browser_plugin_manager()->Send( | 198 browser_plugin_manager()->Send(new BrowserPluginHostMsg_Attach( |
| 193 new BrowserPluginHostMsg_Attach(render_view_routing_id_, | 199 render_view_routing_id_, |
| 194 guest_instance_id_, attach_params, | 200 browser_plugin_instance_id_, |
| 195 *extra_params)); | 201 attach_params)); |
| 196 } | 202 } |
| 197 | 203 |
| 198 void BrowserPlugin::DidCommitCompositorFrame() { | 204 void BrowserPlugin::DidCommitCompositorFrame() { |
| 199 if (compositing_helper_.get()) | 205 if (compositing_helper_.get()) |
| 200 compositing_helper_->DidCommitCompositorFrame(); | 206 compositing_helper_->DidCommitCompositorFrame(); |
| 201 } | 207 } |
| 202 | 208 |
| 203 void BrowserPlugin::OnAdvanceFocus(int guest_instance_id, bool reverse) { | 209 void BrowserPlugin::OnAdvanceFocus(int guest_instance_id, bool reverse) { |
| 204 DCHECK(render_view_.get()); | 210 DCHECK(render_view_.get()); |
| 205 render_view_->GetWebView()->advanceFocus(reverse); | 211 render_view_->GetWebView()->advanceFocus(reverse); |
| 206 } | 212 } |
| 207 | 213 |
| 208 void BrowserPlugin::OnAttachACK(int guest_instance_id) { | 214 void BrowserPlugin::OnAttachACK(int guest_instance_id) { |
| 215 DCHECK(!attached()); |
| 209 attached_ = true; | 216 attached_ = true; |
| 210 } | 217 } |
| 211 | 218 |
| 212 void BrowserPlugin::OnBuffersSwapped( | 219 void BrowserPlugin::OnBuffersSwapped( |
| 213 int instance_id, | 220 int instance_id, |
| 214 const FrameMsg_BuffersSwapped_Params& params) { | 221 const FrameMsg_BuffersSwapped_Params& params) { |
| 215 EnableCompositing(true); | 222 EnableCompositing(true); |
| 216 | 223 |
| 217 compositing_helper_->OnBuffersSwapped(params.size, | 224 compositing_helper_->OnBuffersSwapped(params.size, |
| 218 params.mailbox, | 225 params.mailbox, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 OnLockMouseACK(false); | 299 OnLockMouseACK(false); |
| 293 return; | 300 return; |
| 294 } | 301 } |
| 295 render_view_->mouse_lock_dispatcher()->UnlockMouse(this); | 302 render_view_->mouse_lock_dispatcher()->UnlockMouse(this); |
| 296 } | 303 } |
| 297 } | 304 } |
| 298 | 305 |
| 299 void BrowserPlugin::OnShouldAcceptTouchEvents(int guest_instance_id, | 306 void BrowserPlugin::OnShouldAcceptTouchEvents(int guest_instance_id, |
| 300 bool accept) { | 307 bool accept) { |
| 301 if (container()) { | 308 if (container()) { |
| 302 container()->requestTouchEventType(accept ? | 309 container()->requestTouchEventType( |
| 303 blink::WebPluginContainer::TouchEventRequestTypeRaw : | 310 accept ? WebPluginContainer::TouchEventRequestTypeRaw |
| 304 blink::WebPluginContainer::TouchEventRequestTypeNone); | 311 : WebPluginContainer::TouchEventRequestTypeNone); |
| 305 } | 312 } |
| 306 } | 313 } |
| 307 | 314 |
| 308 void BrowserPlugin::OnUpdateRect( | 315 void BrowserPlugin::OnUpdateRect( |
| 309 int guest_instance_id, | 316 int guest_instance_id, |
| 310 const BrowserPluginMsg_UpdateRect_Params& params) { | 317 const BrowserPluginMsg_UpdateRect_Params& params) { |
| 311 // Note that there is no need to send ACK for this message. | 318 // Note that there is no need to send ACK for this message. |
| 312 // If the guest has updated pixels then it is no longer crashed. | 319 // If the guest has updated pixels then it is no longer crashed. |
| 313 guest_crashed_ = false; | 320 guest_crashed_ = false; |
| 314 | 321 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 should_be_focused)); | 389 should_be_focused)); |
| 383 } | 390 } |
| 384 | 391 |
| 385 bool BrowserPlugin::ShouldGuestBeFocused() const { | 392 bool BrowserPlugin::ShouldGuestBeFocused() const { |
| 386 bool embedder_focused = false; | 393 bool embedder_focused = false; |
| 387 if (render_view_.get()) | 394 if (render_view_.get()) |
| 388 embedder_focused = render_view_->has_focus(); | 395 embedder_focused = render_view_->has_focus(); |
| 389 return plugin_focused_ && embedder_focused; | 396 return plugin_focused_ && embedder_focused; |
| 390 } | 397 } |
| 391 | 398 |
| 392 blink::WebPluginContainer* BrowserPlugin::container() const { | 399 WebPluginContainer* BrowserPlugin::container() const { |
| 393 return container_; | 400 return container_; |
| 394 } | 401 } |
| 395 | 402 |
| 396 bool BrowserPlugin::initialize(WebPluginContainer* container) { | 403 bool BrowserPlugin::initialize(WebPluginContainer* container) { |
| 397 if (!container) | 404 if (!container) |
| 398 return false; | 405 return false; |
| 399 | 406 |
| 400 // Tell |container| to allow this plugin to use script objects. | 407 // Tell |container| to allow this plugin to use script objects. |
| 401 npp_.reset(new NPP_t); | 408 npp_.reset(new NPP_t); |
| 402 container->allowScriptObjects(); | 409 container->allowScriptObjects(); |
| 403 | 410 |
| 404 bindings_.reset(new BrowserPluginBindings(this)); | 411 bindings_.reset(new BrowserPluginBindings(this)); |
| 405 container_ = container; | 412 container_ = container; |
| 406 container_->setWantsWheelEvents(true); | 413 container_->setWantsWheelEvents(true); |
| 407 // This is a way to notify observers of our attributes that we have the | 414 |
| 408 // bindings ready. This also means that this plugin is available in render | 415 g_plugin_container_map.Get().insert(std::make_pair(container_, this)); |
| 409 // tree. | 416 |
| 410 UpdateDOMAttribute("internalbindings", "true"); | 417 // This is a way to notify observers of our attributes that this plugin is |
| 418 // available in render tree. |
| 419 browser_plugin_instance_id_ = browser_plugin_manager()->GetNextInstanceID(); |
| 420 UpdateDOMAttribute("internalinstanceid", |
| 421 base::StringPrintf("%d", browser_plugin_instance_id_)); |
| 422 |
| 423 browser_plugin_manager()->AddBrowserPluginInternal( |
| 424 browser_plugin_instance_id_, this); |
| 411 return true; | 425 return true; |
| 412 } | 426 } |
| 413 | 427 |
| 414 void BrowserPlugin::EnableCompositing(bool enable) { | 428 void BrowserPlugin::EnableCompositing(bool enable) { |
| 415 bool enabled = !!compositing_helper_; | 429 bool enabled = !!compositing_helper_; |
| 416 if (enabled == enable) | 430 if (enabled == enable) |
| 417 return; | 431 return; |
| 418 | 432 |
| 419 if (enable) { | 433 if (enable) { |
| 420 DCHECK(!compositing_helper_.get()); | 434 DCHECK(!compositing_helper_.get()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 433 } | 447 } |
| 434 } | 448 } |
| 435 | 449 |
| 436 void BrowserPlugin::destroy() { | 450 void BrowserPlugin::destroy() { |
| 437 // If the plugin was initialized then it has a valid |npp_| identifier, and | 451 // If the plugin was initialized then it has a valid |npp_| identifier, and |
| 438 // the |container_| must clear references to the plugin's script objects. | 452 // the |container_| must clear references to the plugin's script objects. |
| 439 DCHECK(!npp_ || container_); | 453 DCHECK(!npp_ || container_); |
| 440 if (container_) | 454 if (container_) |
| 441 container_->clearScriptObjects(); | 455 container_->clearScriptObjects(); |
| 442 | 456 |
| 457 // The BrowserPlugin's WebPluginContainer is deleted immediately after this |
| 458 // call returns, so let's not keep a reference to it around. |
| 459 g_plugin_container_map.Get().erase(container_); |
| 460 |
| 443 if (compositing_helper_.get()) | 461 if (compositing_helper_.get()) |
| 444 compositing_helper_->OnContainerDestroy(); | 462 compositing_helper_->OnContainerDestroy(); |
| 445 container_ = NULL; | 463 container_ = NULL; |
| 446 // Will be a no-op if the mouse is not currently locked. | 464 // Will be a no-op if the mouse is not currently locked. |
| 447 if (render_view_.get()) | 465 if (render_view_.get()) |
| 448 render_view_->mouse_lock_dispatcher()->OnLockTargetDestroyed(this); | 466 render_view_->mouse_lock_dispatcher()->OnLockTargetDestroyed(this); |
| 449 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 467 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 450 } | 468 } |
| 451 | 469 |
| 452 NPObject* BrowserPlugin::scriptableObject() { | 470 NPObject* BrowserPlugin::scriptableObject() { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 SkIntToScalar(plugin_rect_.height())); | 518 SkIntToScalar(plugin_rect_.height())); |
| 501 canvas->clipRect(image_data_rect); | 519 canvas->clipRect(image_data_rect); |
| 502 // Paint black or white in case we have nothing in our backing store or we | 520 // Paint black or white in case we have nothing in our backing store or we |
| 503 // need to show a gutter. | 521 // need to show a gutter. |
| 504 SkPaint paint; | 522 SkPaint paint; |
| 505 paint.setStyle(SkPaint::kFill_Style); | 523 paint.setStyle(SkPaint::kFill_Style); |
| 506 paint.setColor(guest_crashed_ ? SK_ColorBLACK : SK_ColorWHITE); | 524 paint.setColor(guest_crashed_ ? SK_ColorBLACK : SK_ColorWHITE); |
| 507 canvas->drawRect(image_data_rect, paint); | 525 canvas->drawRect(image_data_rect, paint); |
| 508 } | 526 } |
| 509 | 527 |
| 528 // static. |
| 529 BrowserPlugin* BrowserPlugin::FromNode(blink::WebNode& node) { |
| 530 blink::WebPluginContainer* container = node.pluginContainer(); |
| 531 if (!container) |
| 532 return NULL; |
| 533 |
| 534 PluginContainerMap* browser_plugins = g_plugin_container_map.Pointer(); |
| 535 PluginContainerMap::iterator it = browser_plugins->find(container); |
| 536 return it == browser_plugins->end() ? NULL : it->second; |
| 537 } |
| 538 |
| 510 // static | 539 // static |
| 511 bool BrowserPlugin::ShouldForwardToBrowserPlugin( | 540 bool BrowserPlugin::ShouldForwardToBrowserPlugin( |
| 512 const IPC::Message& message) { | 541 const IPC::Message& message) { |
| 513 switch (message.type()) { | 542 switch (message.type()) { |
| 514 case BrowserPluginMsg_AdvanceFocus::ID: | 543 case BrowserPluginMsg_AdvanceFocus::ID: |
| 515 case BrowserPluginMsg_Attach_ACK::ID: | |
| 516 case BrowserPluginMsg_BuffersSwapped::ID: | 544 case BrowserPluginMsg_BuffersSwapped::ID: |
| 517 case BrowserPluginMsg_CompositorFrameSwapped::ID: | 545 case BrowserPluginMsg_CompositorFrameSwapped::ID: |
| 518 case BrowserPluginMsg_CopyFromCompositingSurface::ID: | 546 case BrowserPluginMsg_CopyFromCompositingSurface::ID: |
| 519 case BrowserPluginMsg_GuestContentWindowReady::ID: | 547 case BrowserPluginMsg_GuestContentWindowReady::ID: |
| 520 case BrowserPluginMsg_GuestGone::ID: | 548 case BrowserPluginMsg_GuestGone::ID: |
| 521 case BrowserPluginMsg_SetCursor::ID: | 549 case BrowserPluginMsg_SetCursor::ID: |
| 522 case BrowserPluginMsg_SetMouseLock::ID: | 550 case BrowserPluginMsg_SetMouseLock::ID: |
| 523 case BrowserPluginMsg_ShouldAcceptTouchEvents::ID: | 551 case BrowserPluginMsg_ShouldAcceptTouchEvents::ID: |
| 524 case BrowserPluginMsg_UpdateRect::ID: | 552 case BrowserPluginMsg_UpdateRect::ID: |
| 525 return true; | 553 return true; |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 const blink::WebMouseEvent& event) { | 844 const blink::WebMouseEvent& event) { |
| 817 browser_plugin_manager()->Send( | 845 browser_plugin_manager()->Send( |
| 818 new BrowserPluginHostMsg_HandleInputEvent(render_view_routing_id_, | 846 new BrowserPluginHostMsg_HandleInputEvent(render_view_routing_id_, |
| 819 guest_instance_id_, | 847 guest_instance_id_, |
| 820 plugin_rect_, | 848 plugin_rect_, |
| 821 &event)); | 849 &event)); |
| 822 return true; | 850 return true; |
| 823 } | 851 } |
| 824 | 852 |
| 825 } // namespace content | 853 } // namespace content |
| OLD | NEW |