web_contents_view_aura.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/web_contents/web_contents_view_aura.h"
6
7#include "base/utf_string_conversions.h"
8#include "content/browser/renderer_host/dip_util.h"
9#include "content/browser/renderer_host/render_view_host_factory.h"
10#include "content/browser/web_contents/interstitial_page_impl.h"
11#include "content/browser/web_contents/web_contents_impl.h"
12#include "content/public/browser/notification_observer.h"
13#include "content/public/browser/notification_registrar.h"
14#include "content/public/browser/notification_source.h"
15#include "content/public/browser/notification_types.h"
16#include "content/public/browser/render_view_host.h"
17#include "content/public/browser/render_widget_host.h"
18#include "content/public/browser/render_widget_host_view.h"
19#include "content/public/browser/web_contents_delegate.h"
20#include "content/public/browser/web_contents_view_delegate.h"
21#include "content/public/browser/web_drag_dest_delegate.h"
22#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
23#include "ui/aura/client/aura_constants.h"
24#include "ui/aura/client/drag_drop_client.h"
25#include "ui/aura/client/drag_drop_delegate.h"
26#include "ui/aura/root_window.h"
27#include "ui/aura/window.h"
28#include "ui/base/clipboard/custom_data_helper.h"
29#include "ui/base/dragdrop/drag_drop_types.h"
30#include "ui/base/dragdrop/os_exchange_data.h"
31#include "ui/base/dragdrop/os_exchange_data_provider_aura.h"
32#include "ui/base/events/event.h"
33#include "ui/base/events/event_utils.h"
34#include "ui/base/hit_test.h"
35#include "ui/compositor/layer.h"
36#include "ui/gfx/screen.h"
37#include "webkit/glue/webdropdata.h"
38
39namespace content {
40WebContentsView* CreateWebContentsView(
41    WebContentsImpl* web_contents,
42    WebContentsViewDelegate* delegate,
43    RenderViewHostDelegateView** render_view_host_delegate_view) {
44  WebContentsViewAura* rv = new WebContentsViewAura(web_contents, delegate);
45  *render_view_host_delegate_view = rv;
46  return rv;
47}
48
49namespace {
50
51// Listens to all mouse drag events during a drag and drop and sends them to
52// the renderer.
53class WebDragSourceAura : public MessageLoopForUI::Observer,
54                          public NotificationObserver {
55 public:
56  WebDragSourceAura(aura::Window* window, WebContentsImpl* contents)
57      : window_(window),
58        contents_(contents) {
59    MessageLoopForUI::current()->AddObserver(this);
60    registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
61                   Source<WebContents>(contents));
62  }
63
64  virtual ~WebDragSourceAura() {
65    MessageLoopForUI::current()->RemoveObserver(this);
66  }
67
68  // MessageLoop::Observer implementation:
69  virtual base::EventStatus WillProcessEvent(
70      const base::NativeEvent& event) OVERRIDE {
71    return base::EVENT_CONTINUE;
72  }
73  virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
74    if (!contents_)
75      return;
76    ui::EventType type = ui::EventTypeFromNative(event);
77    RenderViewHost* rvh = NULL;
78    switch (type) {
79      case ui::ET_MOUSE_DRAGGED:
80        rvh = contents_->GetRenderViewHost();
81        if (rvh) {
82          gfx::Point screen_loc_in_pixel = ui::EventLocationFromNative(event);
83          gfx::Point screen_loc = ConvertPointToDIP(rvh->GetView(),
84              screen_loc_in_pixel);
85          gfx::Point client_loc = screen_loc;
86          aura::Window* window = rvh->GetView()->GetNativeView();
87          aura::Window::ConvertPointToTarget(window->GetRootWindow(),
88              window, &client_loc);
89          rvh->DragSourceMovedTo(client_loc.x(), client_loc.y(),
90              screen_loc.x(), screen_loc.y());
91        }
92        break;
93      default:
94        break;
95    }
96  }
97
98  virtual void Observe(int type,
99      const NotificationSource& source,
100      const NotificationDetails& details) OVERRIDE {
101    if (type != NOTIFICATION_WEB_CONTENTS_DISCONNECTED)
102      return;
103
104    // Cancel the drag if it is still in progress.
105    aura::client::DragDropClient* dnd_client =
106        aura::client::GetDragDropClient(window_->GetRootWindow());
107    if (dnd_client && dnd_client->IsDragDropInProgress())
108      dnd_client->DragCancel();
109
110    window_ = NULL;
111    contents_ = NULL;
112  }
113
114  aura::Window* window() const { return window_; }
115
116 private:
117  aura::Window* window_;
118  WebContentsImpl* contents_;
119  NotificationRegistrar registrar_;
120
121  DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
122};
123
124// Utility to fill a ui::OSExchangeDataProviderAura object from WebDropData.
125void PrepareDragData(const WebDropData& drop_data,
126                     ui::OSExchangeDataProviderAura* provider) {
127  if (!drop_data.text.string().empty())
128    provider->SetString(drop_data.text.string());
129  if (drop_data.url.is_valid())
130    provider->SetURL(drop_data.url, drop_data.url_title);
131  if (!drop_data.html.string().empty())
132    provider->SetHtml(drop_data.html.string(), drop_data.html_base_url);
133  if (!drop_data.filenames.empty()) {
134    std::vector<ui::OSExchangeData::FileInfo> filenames;
135    for (std::vector<WebDropData::FileInfo>::const_iterator it =
136             drop_data.filenames.begin();
137         it != drop_data.filenames.end(); ++it) {
138      filenames.push_back(
139          ui::OSExchangeData::FileInfo(
140              FilePath::FromUTF8Unsafe(UTF16ToUTF8(it->path)),
141              FilePath::FromUTF8Unsafe(UTF16ToUTF8(it->display_name))));
142    }
143    provider->SetFilenames(filenames);
144  }
145  if (!drop_data.custom_data.empty()) {
146    Pickle pickle;
147    ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle);
148    provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
149                             pickle);
150  }
151}
152
153// Utility to fill a WebDropData object from ui::OSExchangeData.
154void PrepareWebDropData(WebDropData* drop_data,
155                        const ui::OSExchangeData& data) {
156  string16 plain_text;
157  data.GetString(&plain_text);
158  if (!plain_text.empty())
159    drop_data->text = NullableString16(plain_text, false);
160
161  GURL url;
162  string16 url_title;
163  data.GetURLAndTitle(&url, &url_title);
164  if (url.is_valid()) {
165    drop_data->url = url;
166    drop_data->url_title = url_title;
167  }
168
169  string16 html;
170  GURL html_base_url;
171  data.GetHtml(&html, &html_base_url);
172  if (!html.empty())
173    drop_data->html = NullableString16(html, false);
174  if (html_base_url.is_valid())
175    drop_data->html_base_url = html_base_url;
176
177  std::vector<ui::OSExchangeData::FileInfo> files;
178  if (data.GetFilenames(&files) && !files.empty()) {
179    for (std::vector<ui::OSExchangeData::FileInfo>::const_iterator
180             it = files.begin(); it != files.end(); ++it) {
181      drop_data->filenames.push_back(
182          WebDropData::FileInfo(
183              UTF8ToUTF16(it->path.AsUTF8Unsafe()),
184              UTF8ToUTF16(it->display_name.AsUTF8Unsafe())));
185    }
186  }
187
188  Pickle pickle;
189  if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
190                          &pickle))
191    ui::ReadCustomDataIntoMap(pickle.data(), pickle.size(),
192                              &drop_data->custom_data);
193}
194
195// Utilities to convert between WebKit::WebDragOperationsMask and
196// ui::DragDropTypes.
197int ConvertFromWeb(WebKit::WebDragOperationsMask ops) {
198  int drag_op = ui::DragDropTypes::DRAG_NONE;
199  if (ops & WebKit::WebDragOperationCopy)
200    drag_op |= ui::DragDropTypes::DRAG_COPY;
201  if (ops & WebKit::WebDragOperationMove)
202    drag_op |= ui::DragDropTypes::DRAG_MOVE;
203  if (ops & WebKit::WebDragOperationLink)
204    drag_op |= ui::DragDropTypes::DRAG_LINK;
205  return drag_op;
206}
207
208WebKit::WebDragOperationsMask ConvertToWeb(int drag_op) {
209  int web_drag_op = WebKit::WebDragOperationNone;
210  if (drag_op & ui::DragDropTypes::DRAG_COPY)
211    web_drag_op |= WebKit::WebDragOperationCopy;
212  if (drag_op & ui::DragDropTypes::DRAG_MOVE)
213    web_drag_op |= WebKit::WebDragOperationMove;
214  if (drag_op & ui::DragDropTypes::DRAG_LINK)
215    web_drag_op |= WebKit::WebDragOperationLink;
216  return (WebKit::WebDragOperationsMask) web_drag_op;
217}
218
219int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) {
220  int web_input_event_modifiers = 0;
221  if (aura_event_flags & ui::EF_SHIFT_DOWN)
222    web_input_event_modifiers |= WebKit::WebInputEvent::ShiftKey;
223  if (aura_event_flags & ui::EF_CONTROL_DOWN)
224    web_input_event_modifiers |= WebKit::WebInputEvent::ControlKey;
225  if (aura_event_flags & ui::EF_ALT_DOWN)
226    web_input_event_modifiers |= WebKit::WebInputEvent::AltKey;
227  if (aura_event_flags & ui::EF_COMMAND_DOWN)
228    web_input_event_modifiers |= WebKit::WebInputEvent::MetaKey;
229  return web_input_event_modifiers;
230}
231
232}  // namespace
233
234
235////////////////////////////////////////////////////////////////////////////////
236// WebContentsViewAura, public:
237
238WebContentsViewAura::WebContentsViewAura(
239    WebContentsImpl* web_contents,
240    WebContentsViewDelegate* delegate)
241    : web_contents_(web_contents),
242      view_(NULL),
243      delegate_(delegate),
244      current_drag_op_(WebKit::WebDragOperationNone),
245      drag_dest_delegate_(NULL),
246      current_rvh_for_drag_(NULL) {
247}
248
249////////////////////////////////////////////////////////////////////////////////
250// WebContentsViewAura, private:
251
252WebContentsViewAura::~WebContentsViewAura() {
253  // Window needs a valid delegate during its destructor, so we explicitly
254  // delete it here.
255  window_.reset();
256}
257
258void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
259  if (web_contents_->GetInterstitialPage())
260    web_contents_->GetInterstitialPage()->SetSize(size);
261  RenderWidgetHostView* rwhv =
262      web_contents_->GetRenderWidgetHostView();
263  if (rwhv)
264    rwhv->SetSize(size);
265}
266
267void WebContentsViewAura::EndDrag(WebKit::WebDragOperationsMask ops) {
268  aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
269  gfx::Point screen_loc =
270      gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
271  gfx::Point client_loc = screen_loc;
272  RenderViewHost* rvh = web_contents_->GetRenderViewHost();
273  aura::Window* window = rvh->GetView()->GetNativeView();
274  aura::Window::ConvertPointToTarget(root_window, window, &client_loc);
275  rvh->DragSourceEndedAt(client_loc.x(), client_loc.y(), screen_loc.x(),
276      screen_loc.y(), ops);
277}
278
279////////////////////////////////////////////////////////////////////////////////
280// WebContentsViewAura, WebContentsView implementation:
281
282void WebContentsViewAura::CreateView(const gfx::Size& initial_size) {
283  // NOTE: we ignore |initial_size| since in some cases it's wrong (such as
284  // if the bookmark bar is not shown and you create a new tab). The right
285  // value is set shortly after this, so its safe to ignore.
286
287  window_.reset(new aura::Window(this));
288  window_->set_owned_by_parent(false);
289  window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
290  window_->SetTransparent(false);
291  window_->Init(ui::LAYER_NOT_DRAWN);
292  window_->SetParent(NULL);
293  window_->layer()->SetMasksToBounds(true);
294  window_->SetName("WebContentsViewAura");
295
296  // delegate_->GetDragDestDelegate() creates a new delegate on every call.
297  // Hence, we save a reference to it locally. Similar model is used on other
298  // platforms as well.
299  if (delegate_.get())
300    drag_dest_delegate_ = delegate_->GetDragDestDelegate();
301}
302
303RenderWidgetHostView* WebContentsViewAura::CreateViewForWidget(
304    RenderWidgetHost* render_widget_host) {
305  if (render_widget_host->GetView()) {
306    // During testing, the view will already be set up in most cases to the
307    // test view, so we don't want to clobber it with a real one. To verify that
308    // this actually is happening (and somebody isn't accidentally creating the
309    // view twice), we check for the RVH Factory, which will be set when we're
310    // making special ones (which go along with the special views).
311    DCHECK(RenderViewHostFactory::has_factory());
312    return render_widget_host->GetView();
313  }
314
315  view_ = RenderWidgetHostView::CreateViewForWidget(
316      render_widget_host);
317  view_->InitAsChild(NULL);
318  GetNativeView()->AddChild(view_->GetNativeView());
319  view_->Show();
320
321  // We listen to drag drop events in the newly created view's window.
322  aura::client::SetDragDropDelegate(view_->GetNativeView(), this);
323  return view_;
324}
325
326gfx::NativeView WebContentsViewAura::GetNativeView() const {
327  return window_.get();
328}
329
330gfx::NativeView WebContentsViewAura::GetContentNativeView() const {
331  return view_->GetNativeView();
332}
333
334gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const {
335  return window_->GetToplevelWindow();
336}
337
338void WebContentsViewAura::GetContainerBounds(gfx::Rect *out) const {
339  *out = window_->GetBoundsInScreen();
340}
341
342void WebContentsViewAura::SetPageTitle(const string16& title) {
343  window_->set_title(title);
344}
345
346void WebContentsViewAura::OnTabCrashed(base::TerminationStatus status,
347                                       int error_code) {
348  view_ = NULL;
349  // Set the focus to the parent because neither the view window nor this
350  // window can handle key events.
351  if (window_->HasFocus() && window_->parent())
352    window_->parent()->Focus();
353}
354
355void WebContentsViewAura::SizeContents(const gfx::Size& size) {
356  gfx::Rect bounds = window_->bounds();
357  if (bounds.size() != size) {
358    bounds.set_size(size);
359    window_->SetBounds(bounds);
360  } else {
361    // Our size matches what we want but the renderers size may not match.
362    // Pretend we were resized so that the renderers size is updated too.
363    SizeChangedCommon(size);
364  }
365}
366
367void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) {
368}
369
370void WebContentsViewAura::Focus() {
371  if (web_contents_->GetInterstitialPage()) {
372    web_contents_->GetInterstitialPage()->Focus();
373    return;
374  }
375
376  if (delegate_.get() && delegate_->Focus())
377    return;
378
379  RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
380  if (rwhv)
381    rwhv->Focus();
382}
383
384void WebContentsViewAura::SetInitialFocus() {
385  if (web_contents_->FocusLocationBarByDefault())
386    web_contents_->SetFocusToLocationBar(false);
387  else
388    Focus();
389}
390
391void WebContentsViewAura::StoreFocus() {
392  if (delegate_.get())
393    delegate_->StoreFocus();
394}
395
396void WebContentsViewAura::RestoreFocus() {
397  if (delegate_.get())
398    delegate_->RestoreFocus();
399}
400
401WebDropData* WebContentsViewAura::GetDropData() const {
402  return current_drop_data_.get();
403}
404
405bool WebContentsViewAura::IsEventTracking() const {
406  return false;
407}
408
409void WebContentsViewAura::CloseTabAfterEventTracking() {
410}
411
412gfx::Rect WebContentsViewAura::GetViewBounds() const {
413  return window_->GetBoundsInRootWindow();
414}
415
416////////////////////////////////////////////////////////////////////////////////
417// WebContentsViewAura, RenderViewHostDelegateView implementation:
418
419void WebContentsViewAura::ShowContextMenu(
420    const ContextMenuParams& params,
421    ContextMenuSourceType type) {
422  if (delegate_.get())
423    delegate_->ShowContextMenu(params, type);
424}
425
426void WebContentsViewAura::ShowPopupMenu(const gfx::Rect& bounds,
427                                        int item_height,
428                                        double item_font_size,
429                                        int selected_item,
430                                        const std::vector<WebMenuItem>& items,
431                                        bool right_aligned,
432                                        bool allow_multiple_selection) {
433  // External popup menus are only used on Mac and Android.
434  NOTIMPLEMENTED();
435}
436
437void WebContentsViewAura::StartDragging(
438    const WebDropData& drop_data,
439    WebKit::WebDragOperationsMask operations,
440    const gfx::ImageSkia& image,
441    const gfx::Vector2d& image_offset,
442    const DragEventSourceInfo& event_info) {
443  aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
444  if (!aura::client::GetDragDropClient(root_window))
445    return;
446
447  ui::OSExchangeDataProviderAura* provider = new ui::OSExchangeDataProviderAura;
448  PrepareDragData(drop_data, provider);
449  if (!image.isNull()) {
450    provider->set_drag_image(image);
451    provider->set_drag_image_offset(image_offset);
452  }
453  ui::OSExchangeData data(provider);  // takes ownership of |provider|.
454
455  scoped_ptr<WebDragSourceAura> drag_source(
456      new WebDragSourceAura(GetNativeView(), web_contents_));
457
458  // We need to enable recursive tasks on the message loop so we can get
459  // updates while in the system DoDragDrop loop.
460  int result_op = 0;
461  {
462    MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
463    result_op = aura::client::GetDragDropClient(root_window)->StartDragAndDrop(
464        data, root_window, GetContentNativeView(),
465        event_info.event_location, ConvertFromWeb(operations),
466        event_info.event_source);
467  }
468
469  // Bail out immediately if the contents view window is gone. Note that it is
470  // not safe to access any class members after system drag-and-drop returns
471  // since the class instance might be gone. The local variable |drag_source|
472  // is still valid and we can check its window property that is set to NULL
473  // when the contents are gone.
474  if (!drag_source->window())
475    return;
476
477  EndDrag(ConvertToWeb(result_op));
478  web_contents_->GetRenderViewHost()->DragSourceSystemDragEnded();
479}
480
481void WebContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) {
482  current_drag_op_ = operation;
483}
484
485void WebContentsViewAura::GotFocus() {
486  if (web_contents_->GetDelegate())
487    web_contents_->GetDelegate()->WebContentsFocused(web_contents_);
488}
489
490void WebContentsViewAura::TakeFocus(bool reverse) {
491  if (web_contents_->GetDelegate() &&
492      !web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) &&
493      delegate_.get()) {
494    delegate_->TakeFocus(reverse);
495  }
496}
497
498////////////////////////////////////////////////////////////////////////////////
499// WebContentsViewAura, aura::WindowDelegate implementation:
500
501gfx::Size WebContentsViewAura::GetMinimumSize() const {
502  return gfx::Size();
503}
504
505void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
506                                          const gfx::Rect& new_bounds) {
507  SizeChangedCommon(new_bounds.size());
508  if (delegate_.get())
509    delegate_->SizeChanged(new_bounds.size());
510
511  // Constrained web dialogs, need to be kept centered over our content area.
512  for (size_t i = 0; i < window_->children().size(); i++) {
513    if (window_->children()[i]->GetProperty(
514            aura::client::kConstrainedWindowKey)) {
515      gfx::Rect bounds = window_->children()[i]->bounds();
516      bounds.set_origin(
517          gfx::Point((new_bounds.width() - bounds.width()) / 2,
518                     (new_bounds.height() - bounds.height()) / 2));
519      window_->children()[i]->SetBounds(bounds);
520    }
521  }
522}
523
524void WebContentsViewAura::OnFocus(aura::Window* old_focused_window) {
525}
526
527void WebContentsViewAura::OnBlur() {
528}
529
530gfx::NativeCursor WebContentsViewAura::GetCursor(const gfx::Point& point) {
531  return gfx::kNullCursor;
532}
533
534int WebContentsViewAura::GetNonClientComponent(const gfx::Point& point) const {
535  return HTCLIENT;
536}
537
538bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
539    aura::Window* child,
540    const gfx::Point& location) {
541  return true;
542}
543
544bool WebContentsViewAura::CanFocus() {
545  // Do not take the focus if |view_| is gone because neither the view window
546  // nor this window can handle key events.
547  return view_ != NULL;
548}
549
550void WebContentsViewAura::OnCaptureLost() {
551}
552
553void WebContentsViewAura::OnPaint(gfx::Canvas* canvas) {
554}
555
556void WebContentsViewAura::OnDeviceScaleFactorChanged(
557    float device_scale_factor) {
558}
559
560void WebContentsViewAura::OnWindowDestroying() {
561}
562
563void WebContentsViewAura::OnWindowDestroyed() {
564}
565
566void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) {
567  if (visible)
568    web_contents_->WasShown();
569  else
570    web_contents_->WasHidden();
571}
572
573bool WebContentsViewAura::HasHitTestMask() const {
574  return false;
575}
576
577void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const {
578}
579
580scoped_refptr<ui::Texture> WebContentsViewAura::CopyTexture() {
581  // The layer we create doesn't have an external texture, so this should never
582  // get invoked.
583  NOTREACHED();
584  return scoped_refptr<ui::Texture>();
585}
586
587////////////////////////////////////////////////////////////////////////////////
588// WebContentsViewAura, ui::EventHandler implementation:
589
590ui::EventResult WebContentsViewAura::OnKeyEvent(ui::KeyEvent* event) {
591  return ui::ER_UNHANDLED;
592}
593
594ui::EventResult WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
595  if (!web_contents_->GetDelegate())
596    return ui::ER_UNHANDLED;
597
598  switch (event->type()) {
599    case ui::ET_MOUSE_PRESSED:
600      web_contents_->GetDelegate()->ActivateContents(web_contents_);
601      break;
602    case ui::ET_MOUSE_MOVED:
603      web_contents_->GetDelegate()->ContentsMouseEvent(
604          web_contents_,
605          gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
606          true);
607      break;
608    default:
609      break;
610  }
611  return ui::ER_UNHANDLED;
612}
613
614ui::EventResult WebContentsViewAura::OnTouchEvent(ui::TouchEvent* event) {
615  return ui::ER_UNHANDLED;
616}
617
618ui::EventResult WebContentsViewAura::OnGestureEvent(
619    ui::GestureEvent* event) {
620  return ui::ER_UNHANDLED;
621}
622
623////////////////////////////////////////////////////////////////////////////////
624// WebContentsViewAura, aura::client::DragDropDelegate implementation:
625
626void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
627  if (drag_dest_delegate_)
628    drag_dest_delegate_->DragInitialize(web_contents_);
629
630  current_drop_data_.reset(new WebDropData());
631
632  PrepareWebDropData(current_drop_data_.get(), event.data());
633  WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
634
635  gfx::Point screen_pt =
636      gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
637  current_rvh_for_drag_ = web_contents_->GetRenderViewHost();
638  web_contents_->GetRenderViewHost()->DragTargetDragEnter(
639      *current_drop_data_.get(), event.location(), screen_pt, op,
640      ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
641
642  if (drag_dest_delegate_) {
643    drag_dest_delegate_->OnReceiveDragData(event.data());
644    drag_dest_delegate_->OnDragEnter();
645  }
646}
647
648int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
649  DCHECK(current_rvh_for_drag_);
650  if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
651    OnDragEntered(event);
652
653  WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
654  gfx::Point screen_pt =
655      gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
656  web_contents_->GetRenderViewHost()->DragTargetDragOver(
657      event.location(), screen_pt, op,
658      ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
659
660  if (drag_dest_delegate_)
661    drag_dest_delegate_->OnDragOver();
662
663  return ConvertFromWeb(current_drag_op_);
664}
665
666void WebContentsViewAura::OnDragExited() {
667  DCHECK(current_rvh_for_drag_);
668  if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
669    return;
670
671  web_contents_->GetRenderViewHost()->DragTargetDragLeave();
672  if (drag_dest_delegate_)
673    drag_dest_delegate_->OnDragLeave();
674
675  current_drop_data_.reset();
676}
677
678int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
679  DCHECK(current_rvh_for_drag_);
680  if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
681    OnDragEntered(event);
682
683  web_contents_->GetRenderViewHost()->DragTargetDrop(
684      event.location(),
685      gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
686      ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
687  if (drag_dest_delegate_)
688    drag_dest_delegate_->OnDrop();
689  current_drop_data_.reset();
690  return current_drag_op_;
691}
692
693}  // namespace content
694