15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/browser_plugin/browser_plugin_embedder.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/values.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/browser_plugin/browser_plugin_guest.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/renderer_host/render_view_host_impl.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/web_contents_impl.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/browser_plugin/browser_plugin_constants.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/browser_plugin/browser_plugin_messages.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/common/drag_messages.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/gpu/gpu_messages.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_context.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/browser_plugin_guest_manager.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/content_browser_client.h"
187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/native_web_keyboard_event.h"
1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/user_metrics.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_switches.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/result_codes.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/url_constants.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/events/keycodes/keyboard_codes.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BrowserPluginEmbedder::BrowserPluginEmbedder(WebContentsImpl* web_contents)
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : WebContentsObserver(web_contents),
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      guest_drag_ending_(false),
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      weak_ptr_factory_(this) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserPluginEmbedder::~BrowserPluginEmbedder() {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserPluginEmbedder* BrowserPluginEmbedder::Create(
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebContentsImpl* web_contents) {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new BrowserPluginEmbedder(web_contents);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BrowserPluginEmbedder::DragEnteredGuest(BrowserPluginGuest* guest) {
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  guest_dragging_over_ = guest->AsWeakPtr();
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BrowserPluginEmbedder::DragLeftGuest(BrowserPluginGuest* guest) {
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Avoid race conditions in switching between guests being hovered over by
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // only un-setting if the caller is marked as the guest being dragged over.
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (guest_dragging_over_.get() == guest) {
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    guest_dragging_over_.reset();
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BrowserPluginEmbedder::StartDrag(BrowserPluginGuest* guest) {
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  guest_started_drag_ = guest->AsWeakPtr();
5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  guest_drag_ending_ = false;
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)WebContentsImpl* BrowserPluginEmbedder::GetWebContents() const {
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return static_cast<WebContentsImpl*>(web_contents());
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)BrowserPluginGuestManager*
66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)BrowserPluginEmbedder::GetBrowserPluginGuestManager() const {
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return GetWebContents()->GetBrowserContext()->GetGuestManager();
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserPluginEmbedder::ClearGuestDragStateIfApplicable() {
7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // The order at which we observe SystemDragEnded() and DragSourceEndedAt() is
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // platform dependent.
7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // In OSX, we see SystemDragEnded() first, where in aura, we see
7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // DragSourceEndedAt() first. For this reason, we check if both methods were
7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // called before resetting |guest_started_drag_|.
7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (guest_drag_ending_) {
7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (guest_started_drag_)
7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      guest_started_drag_.reset();
7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  } else {
8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    guest_drag_ending_ = true;
8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BrowserPluginEmbedder::DidSendScreenRectsCallback(
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   WebContents* guest_web_contents) {
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static_cast<RenderViewHostImpl*>(
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      guest_web_contents->GetRenderViewHost())->SendScreenRects();
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Not handled => Iterate over all guests.
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BrowserPluginEmbedder::DidSendScreenRects() {
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetBrowserPluginGuestManager()->ForEachGuest(
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          GetWebContents(), base::Bind(
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)              &BrowserPluginEmbedder::DidSendScreenRectsCallback,
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)              base::Unretained(this)));
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BrowserPluginEmbedder::OnMessageReceived(const IPC::Message& message) {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool handled = true;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(BrowserPluginEmbedder, message)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Attach, OnAttach)
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IPC_MESSAGE_HANDLER_GENERIC(DragHostMsg_UpdateDragCursor,
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                OnUpdateDragCursor(&handled));
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IPC_END_MESSAGE_MAP()
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return handled;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BrowserPluginEmbedder::DragSourceEndedAt(int client_x, int client_y,
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int screen_x, int screen_y, blink::WebDragOperation operation) {
11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (guest_started_drag_) {
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Point guest_offset =
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        guest_started_drag_->GetScreenCoordinates(gfx::Point());
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    guest_started_drag_->DragSourceEndedAt(client_x - guest_offset.x(),
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        client_y - guest_offset.y(), screen_x, screen_y, operation);
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ClearGuestDragStateIfApplicable();
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BrowserPluginEmbedder::SystemDragEnded() {
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // When the embedder's drag/drop operation ends, we need to pass the message
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // to the guest that initiated the drag/drop operation. This will ensure that
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the guest's RVH state is reset properly.
12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (guest_started_drag_)
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    guest_started_drag_->EndSystemDrag();
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  guest_dragging_over_.reset();
12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ClearGuestDragStateIfApplicable();
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BrowserPluginEmbedder::OnUpdateDragCursor(bool* handled) {
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *handled = (guest_dragging_over_.get() != NULL);
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void BrowserPluginEmbedder::OnAttach(
13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    int browser_plugin_instance_id,
13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const BrowserPluginHostMsg_Attach_Params& params) {
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WebContents* guest_web_contents =
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetBrowserPluginGuestManager()->GetGuestByInstanceID(
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          GetWebContents(), browser_plugin_instance_id);
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!guest_web_contents)
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BrowserPluginGuest* guest = static_cast<WebContentsImpl*>(guest_web_contents)
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  ->GetBrowserPluginGuest();
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  guest->Attach(browser_plugin_instance_id, GetWebContents(), params);
14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool BrowserPluginEmbedder::HandleKeyboardEvent(
14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const NativeWebKeyboardEvent& event) {
15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if ((event.windowsKeyCode != ui::VKEY_ESCAPE) ||
15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      (event.modifiers & blink::WebInputEvent::InputModifiers)) {
15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bool event_consumed = false;
15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  GetBrowserPluginGuestManager()->ForEachGuest(
15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      GetWebContents(),
15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::Bind(&BrowserPluginEmbedder::UnlockMouseIfNecessaryCallback,
15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 base::Unretained(this),
16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 &event_consumed));
16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return event_consumed;
16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool BrowserPluginEmbedder::UnlockMouseIfNecessaryCallback(bool* mouse_unlocked,
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                                           WebContents* guest) {
16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  *mouse_unlocked |= static_cast<WebContentsImpl*>(guest)
16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         ->GetBrowserPluginGuest()
16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         ->mouse_locked();
17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  guest->GotResponseToLockMouseRequest(false);
17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Returns false to iterate over all guests.
17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return false;
174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
177