web_contents_view_aura.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/web_contents/web_contents_view_aura.h"
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/auto_reset.h"
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/command_line.h"
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/metrics/histogram.h"
10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/strings/utf_string_conversions.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/dip_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/overscroll_controller.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/render_view_host_factory.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/render_view_host_impl.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/render_widget_host_impl.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_widget_host_view_aura.h"
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/web_contents/aura/image_window_delegate.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/aura/shadow_layer_delegate.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/aura/window_slider.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/interstitial_page_impl.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/navigation_entry_impl.h"
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/web_contents/touch_editable_impl_aura.h"
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/web_contents/web_contents_impl.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_observer.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/notification_types.h"
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/overscroll_configuration.h"
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/render_view_host.h"
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/render_widget_host.h"
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/render_widget_host_view.h"
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/web_contents_delegate.h"
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/web_contents_observer.h"
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/web_contents_view_delegate.h"
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/web_drag_dest_delegate.h"
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/common/content_switches.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/drop_data.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/WebKit/public/web/WebInputEvent.h"
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/aura/client/aura_constants.h"
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/client/drag_drop_client.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/drag_drop_delegate.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window_observer.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window_observer.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/clipboard/clipboard.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/clipboard/custom_data_helper.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/drag_drop_types.h"
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/base/dragdrop/drag_utils.h"
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/dragdrop/os_exchange_data.h"
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/hit_test.h"
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/compositor/layer.h"
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/events/event.h"
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/events/event_utils.h"
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h"
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_png_rep.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h"
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/screen.h"
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebContentsViewPort* CreateWebContentsView(
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebContentsImpl* web_contents,
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebContentsViewDelegate* delegate,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RenderViewHostDelegateView** render_view_host_delegate_view) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContentsViewAura* rv = new WebContentsViewAura(web_contents, delegate);
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *render_view_host_delegate_view = rv;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool IsScrollEndEffectEnabled() {
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switches::kScrollEndEffect) == "1";
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShouldNavigateForward(const NavigationController& controller,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           OverscrollMode mode) {
82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) &&
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         controller.CanGoForward();
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
85a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ShouldNavigateBack(const NavigationController& controller,
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                        OverscrollMode mode) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return mode == (base::i18n::IsRTL() ? OVERSCROLL_WEST : OVERSCROLL_EAST) &&
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         controller.CanGoBack();
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)RenderWidgetHostViewAura* ToRenderWidgetHostViewAura(
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    RenderWidgetHostView* view) {
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!view || RenderViewHostFactory::has_factory())
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return NULL;  // Can't cast to RenderWidgetHostViewAura in unit tests.
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RenderProcessHostImpl* process = static_cast<RenderProcessHostImpl*>(
976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      view->GetRenderWidgetHost()->GetProcess());
980de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (process->IsGuest())
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return NULL;
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return static_cast<RenderWidgetHostViewAura*>(view);
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// The window delegate for the overscroll window. This redirects trackpad events
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// to the web-contents window. The delegate destroys itself when the window is
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// destroyed.
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class OverscrollWindowDelegate : public ImageWindowDelegate {
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public:
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  OverscrollWindowDelegate(WebContentsImpl* web_contents,
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           OverscrollMode overscroll_mode)
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      : web_contents_(web_contents),
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        forward_events_(true) {
112ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch    const NavigationControllerImpl& controller = web_contents->GetController();
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const NavigationEntryImpl* entry = NULL;
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (ShouldNavigateForward(controller, overscroll_mode)) {
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      entry = NavigationEntryImpl::FromNavigationEntry(
116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          controller.GetEntryAtOffset(1));
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (ShouldNavigateBack(controller, overscroll_mode)) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry = NavigationEntryImpl::FromNavigationEntry(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          controller.GetEntryAtOffset(-1));
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Image image;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (entry && entry->screenshot().get()) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<gfx::ImagePNGRep> image_reps;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(),
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ui::GetScaleFactorForNativeView(web_contents_window())));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image = gfx::Image(image_reps);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetImage(image);
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void stop_forwarding_events() { forward_events_ = false; }
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private:
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual ~OverscrollWindowDelegate() {}
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  aura::Window* web_contents_window() {
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return web_contents_->GetView()->GetContentNativeView();
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Overridden from ui::EventHandler.
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (forward_events_ && web_contents_window())
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      web_contents_window()->delegate()->OnScrollEvent(event);
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (forward_events_ && web_contents_window())
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      web_contents_window()->delegate()->OnGestureEvent(event);
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  WebContents* web_contents_;
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The window is displayed both during the gesture, and after the gesture
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // while the navigation is in progress. During the gesture, it is necessary to
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // forward input events to the content page (e.g. when the overscroll window
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // slides under the cursor and starts receiving scroll events). However, once
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // the gesture is complete, and the window is being displayed as an overlay
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // window during navigation, events should not be forwarded anymore.
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool forward_events_;
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(OverscrollWindowDelegate);
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch};
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Listens to all mouse drag events during a drag and drop and sends them to
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// the renderer.
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass WebDragSourceAura : public base::MessageLoopForUI::Observer,
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          public NotificationObserver {
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  WebDragSourceAura(aura::Window* window, WebContentsImpl* contents)
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : window_(window),
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        contents_(contents) {
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::MessageLoopForUI::current()->AddObserver(this);
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    registrar_.Add(this,
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                   NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                   Source<WebContents>(contents));
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~WebDragSourceAura() {
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::MessageLoopForUI::current()->RemoveObserver(this);
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // MessageLoop::Observer implementation:
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual base::EventStatus WillProcessEvent(
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const base::NativeEvent& event) OVERRIDE {
186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return base::EVENT_CONTINUE;
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!contents_)
190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return;
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ui::EventType type = ui::EventTypeFromNative(event);
192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    RenderViewHost* rvh = NULL;
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    switch (type) {
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case ui::ET_MOUSE_DRAGGED:
195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        rvh = contents_->GetRenderViewHost();
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (rvh) {
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          gfx::Point screen_loc_in_pixel = ui::EventLocationFromNative(event);
198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          gfx::Point screen_loc = ConvertViewPointToDIP(rvh->GetView(),
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch              screen_loc_in_pixel);
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          gfx::Point client_loc = screen_loc;
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          aura::Window* window = rvh->GetView()->GetNativeView();
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          aura::Window::ConvertPointToTarget(window->GetRootWindow(),
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch              window, &client_loc);
204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          contents_->DragSourceMovedTo(client_loc.x(), client_loc.y(),
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch              screen_loc.x(), screen_loc.y());
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      default:
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
210e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
213a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  virtual void Observe(int type,
2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      const NotificationSource& source,
2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      const NotificationDetails& details) OVERRIDE {
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (type != NOTIFICATION_WEB_CONTENTS_DISCONNECTED)
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Cancel the drag if it is still in progress.
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    aura::client::DragDropClient* dnd_client =
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        aura::client::GetDragDropClient(window_->GetRootWindow());
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (dnd_client && dnd_client->IsDragDropInProgress())
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      dnd_client->DragCancel();
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    window_ = NULL;
2260de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    contents_ = NULL;
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  aura::Window* window() const { return window_; }
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private:
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  aura::Window* window_;
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebContentsImpl* contents_;
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  NotificationRegistrar registrar_;
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN)
240ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch// Fill out the OSExchangeData with a file contents, synthesizing a name if
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// necessary.
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void PrepareDragForFileContents(const DropData& drop_data,
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                ui::OSExchangeData::Provider* provider) {
244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::FilePath file_name(drop_data.file_description_filename);
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Images without ALT text will only have a file extension so we need to
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // synthesize one from the provided extension and URL.
247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (file_name.BaseName().RemoveExtension().empty()) {
248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const string16 extension = file_name.Extension();
249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Retrieve the name from the URL.
250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    file_name = base::FilePath(net::GetSuggestedFilename(
251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        drop_data.url, "", "", "", "", "")).ReplaceExtension(extension);
252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  provider->SetFileContents(file_name, drop_data.file_contents);
254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Utility to fill a ui::OSExchangeDataProvider object from DropData.
258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PrepareDragData(const DropData& drop_data,
259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     ui::OSExchangeData::Provider* provider) {
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN)
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // We set the file contents before the URL because the URL also sets file
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // contents (to a .URL shortcut).  We want to prefer file content data over
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // a shortcut so we add it first.
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!drop_data.file_contents.empty())
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PrepareDragForFileContents(drop_data, provider);
2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!drop_data.text.string().empty())
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    provider->SetString(drop_data.text.string());
2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (drop_data.url.is_valid())
2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    provider->SetURL(drop_data.url, drop_data.url_title);
2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!drop_data.html.string().empty())
2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    provider->SetHtml(drop_data.html.string(), drop_data.html_base_url);
2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!drop_data.filenames.empty()) {
2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    std::vector<ui::OSExchangeData::FileInfo> filenames;
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (std::vector<DropData::FileInfo>::const_iterator it =
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             drop_data.filenames.begin();
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)         it != drop_data.filenames.end(); ++it) {
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      filenames.push_back(
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          ui::OSExchangeData::FileInfo(
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)              base::FilePath::FromUTF8Unsafe(UTF16ToUTF8(it->path)),
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              base::FilePath::FromUTF8Unsafe(UTF16ToUTF8(it->display_name))));
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    provider->SetFilenames(filenames);
284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!drop_data.custom_data.empty()) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Pickle pickle;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             pickle);
290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Utility to fill a DropData object from ui::OSExchangeData.
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 plain_text;
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.GetString(&plain_text);
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!plain_text.empty())
298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    drop_data->text = base::NullableString16(plain_text, false);
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 url_title;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.GetURLAndTitle(&url, &url_title);
3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (url.is_valid()) {
3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    drop_data->url = url;
3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    drop_data->url_title = url_title;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  string16 html;
3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GURL html_base_url;
3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  data.GetHtml(&html, &html_base_url);
3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!html.empty())
3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    drop_data->html = base::NullableString16(html, false);
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (html_base_url.is_valid())
314c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    drop_data->html_base_url = html_base_url;
3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
316  std::vector<ui::OSExchangeData::FileInfo> files;
317  if (data.GetFilenames(&files) && !files.empty()) {
318    for (std::vector<ui::OSExchangeData::FileInfo>::const_iterator
319             it = files.begin(); it != files.end(); ++it) {
320      drop_data->filenames.push_back(
321          DropData::FileInfo(
322              UTF8ToUTF16(it->path.AsUTF8Unsafe()),
323              UTF8ToUTF16(it->display_name.AsUTF8Unsafe())));
324    }
325  }
326
327  Pickle pickle;
328  if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), &pickle))
329    ui::ReadCustomDataIntoMap(
330        pickle.data(), pickle.size(), &drop_data->custom_data);
331}
332
333// Utilities to convert between WebKit::WebDragOperationsMask and
334// ui::DragDropTypes.
335int ConvertFromWeb(WebKit::WebDragOperationsMask ops) {
336  int drag_op = ui::DragDropTypes::DRAG_NONE;
337  if (ops & WebKit::WebDragOperationCopy)
338    drag_op |= ui::DragDropTypes::DRAG_COPY;
339  if (ops & WebKit::WebDragOperationMove)
340    drag_op |= ui::DragDropTypes::DRAG_MOVE;
341  if (ops & WebKit::WebDragOperationLink)
342    drag_op |= ui::DragDropTypes::DRAG_LINK;
343  return drag_op;
344}
345
346WebKit::WebDragOperationsMask ConvertToWeb(int drag_op) {
347  int web_drag_op = WebKit::WebDragOperationNone;
348  if (drag_op & ui::DragDropTypes::DRAG_COPY)
349    web_drag_op |= WebKit::WebDragOperationCopy;
350  if (drag_op & ui::DragDropTypes::DRAG_MOVE)
351    web_drag_op |= WebKit::WebDragOperationMove;
352  if (drag_op & ui::DragDropTypes::DRAG_LINK)
353    web_drag_op |= WebKit::WebDragOperationLink;
354  return (WebKit::WebDragOperationsMask) web_drag_op;
355}
356
357int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) {
358  int web_input_event_modifiers = 0;
359  if (aura_event_flags & ui::EF_SHIFT_DOWN)
360    web_input_event_modifiers |= WebKit::WebInputEvent::ShiftKey;
361  if (aura_event_flags & ui::EF_CONTROL_DOWN)
362    web_input_event_modifiers |= WebKit::WebInputEvent::ControlKey;
363  if (aura_event_flags & ui::EF_ALT_DOWN)
364    web_input_event_modifiers |= WebKit::WebInputEvent::AltKey;
365  if (aura_event_flags & ui::EF_COMMAND_DOWN)
366    web_input_event_modifiers |= WebKit::WebInputEvent::MetaKey;
367  return web_input_event_modifiers;
368}
369
370// A LayerDelegate that paints an image for the layer.
371class ImageLayerDelegate : public ui::LayerDelegate {
372 public:
373  ImageLayerDelegate() {}
374
375  virtual ~ImageLayerDelegate() {}
376
377  void SetImage(const gfx::Image& image) {
378    image_ = image;
379    image_size_ = image.AsImageSkia().size();
380  }
381  const gfx::Image& image() const { return image_; }
382
383 private:
384  // Overridden from ui::LayerDelegate:
385  virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
386    if (image_.IsEmpty()) {
387      canvas->DrawColor(SK_ColorGRAY);
388    } else {
389      SkISize size = canvas->sk_canvas()->getDeviceSize();
390      if (size.width() != image_size_.width() ||
391          size.height() != image_size_.height()) {
392        canvas->DrawColor(SK_ColorWHITE);
393      }
394      canvas->DrawImageInt(image_.AsImageSkia(), 0, 0);
395    }
396  }
397
398  // Called when the layer's device scale factor has changed.
399  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
400  }
401
402  // Invoked prior to the bounds changing. The returned closured is run after
403  // the bounds change.
404  virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
405    return base::Closure();
406  }
407
408  gfx::Image image_;
409  gfx::Size image_size_;
410
411  DISALLOW_COPY_AND_ASSIGN(ImageLayerDelegate);
412};
413
414}  // namespace
415
416// When a history navigation is triggered at the end of an overscroll
417// navigation, it is necessary to show the history-screenshot until the page is
418// done navigating and painting. This class accomplishes this by showing the
419// screenshot window on top of the page until the page has completed loading and
420// painting.
421class OverscrollNavigationOverlay :
422    public RenderWidgetHostViewAura::PaintObserver,
423    public WindowSlider::Delegate {
424 public:
425  explicit OverscrollNavigationOverlay(WebContentsImpl* web_contents)
426      : web_contents_(web_contents),
427        image_delegate_(NULL),
428        view_(NULL),
429        loading_complete_(false),
430        received_paint_update_(false),
431        compositor_updated_(false),
432        slide_direction_(SLIDE_UNKNOWN),
433        need_paint_update_(true) {
434  }
435
436  virtual ~OverscrollNavigationOverlay() {
437    if (view_)
438      view_->set_paint_observer(NULL);
439  }
440
441  bool has_window() const { return !!window_.get(); }
442
443  void StartObservingView(RenderWidgetHostViewAura* view) {
444    if (view_)
445      view_->set_paint_observer(NULL);
446
447    loading_complete_ = false;
448    received_paint_update_ = false;
449    compositor_updated_ = false;
450    view_ = view;
451    if (view_)
452      view_->set_paint_observer(this);
453
454    // Make sure the overlay window is on top.
455    if (window_.get() && window_->parent())
456      window_->parent()->StackChildAtTop(window_.get());
457  }
458
459  void SetOverlayWindow(scoped_ptr<aura::Window> window,
460                        ImageWindowDelegate* delegate) {
461    window_ = window.Pass();
462    if (window_.get() && window_->parent())
463      window_->parent()->StackChildAtTop(window_.get());
464    image_delegate_ = delegate;
465
466    if (window_.get() && delegate->has_image()) {
467      window_slider_.reset(new WindowSlider(this,
468                                            window_->parent(),
469                                            window_.get()));
470      slide_direction_ = SLIDE_UNKNOWN;
471    } else {
472      window_slider_.reset();
473    }
474  }
475
476  void SetupForTesting() {
477    need_paint_update_ = false;
478  }
479
480 private:
481  // Stop observing the page if the page-load has completed and the page has
482  // been painted, and a window-slide isn't in progress.
483  void StopObservingIfDone() {
484    // If there is a screenshot displayed in the overlay window, then wait for
485    // the navigated page to complete loading and some paint update before
486    // hiding the overlay.
487    // If there is no screenshot in the overlay window, then hide this view
488    // as soon as there is any new painting notification.
489    if ((need_paint_update_ && !received_paint_update_) ||
490        (image_delegate_->has_image() && !loading_complete_)) {
491      return;
492    }
493
494    // If a slide is in progress, then do not destroy the window or the slide.
495    if (window_slider_.get() && window_slider_->IsSlideInProgress())
496      return;
497
498    window_slider_.reset();
499    window_.reset();
500    image_delegate_ = NULL;
501    if (view_) {
502      view_->set_paint_observer(NULL);
503      view_ = NULL;
504    }
505  }
506
507  // Creates a layer to be used for window-slide. |offset| is the offset of the
508  // NavigationEntry for the screenshot image to display.
509  ui::Layer* CreateSlideLayer(int offset) {
510    const NavigationControllerImpl& controller = web_contents_->GetController();
511    const NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
512        controller.GetEntryAtOffset(offset));
513
514    gfx::Image image;
515    if (entry && entry->screenshot().get()) {
516      std::vector<gfx::ImagePNGRep> image_reps;
517      image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(),
518            ui::GetScaleFactorForNativeView(window_.get())));
519      image = gfx::Image(image_reps);
520    }
521    layer_delegate_.SetImage(image);
522
523    ui::Layer* layer = new ui::Layer(ui::LAYER_TEXTURED);
524    layer->set_delegate(&layer_delegate_);
525    return layer;
526  }
527
528  // Overridden from WindowSlider::Delegate:
529  virtual ui::Layer* CreateBackLayer() OVERRIDE {
530    if (!web_contents_->GetController().CanGoBack())
531      return NULL;
532    slide_direction_ = SLIDE_BACK;
533    return CreateSlideLayer(-1);
534  }
535
536  virtual ui::Layer* CreateFrontLayer() OVERRIDE {
537    if (!web_contents_->GetController().CanGoForward())
538      return NULL;
539    slide_direction_ = SLIDE_FRONT;
540    return CreateSlideLayer(1);
541  }
542
543  virtual void OnWindowSlideComplete() OVERRIDE {
544    if (slide_direction_ == SLIDE_UNKNOWN) {
545      window_slider_.reset();
546      StopObservingIfDone();
547      return;
548    }
549
550    // Change the image used for the overlay window.
551    image_delegate_->SetImage(layer_delegate_.image());
552    window_->layer()->SetTransform(gfx::Transform());
553    window_->SchedulePaintInRect(gfx::Rect(window_->bounds().size()));
554
555    SlideDirection direction = slide_direction_;
556    slide_direction_ = SLIDE_UNKNOWN;
557
558    // Reset state and wait for the new navigation page to complete
559    // loading/painting.
560    StartObservingView(ToRenderWidgetHostViewAura(
561        web_contents_->GetRenderWidgetHostView()));
562
563    // Perform the navigation.
564    if (direction == SLIDE_BACK)
565      web_contents_->GetController().GoBack();
566    else if (direction == SLIDE_FRONT)
567      web_contents_->GetController().GoForward();
568    else
569      NOTREACHED();
570  }
571
572  virtual void OnWindowSlideAborted() OVERRIDE {
573    StopObservingIfDone();
574  }
575
576  virtual void OnWindowSliderDestroyed() OVERRIDE {
577    // The slider has just been destroyed. Release the ownership.
578    WindowSlider* slider ALLOW_UNUSED = window_slider_.release();
579    StopObservingIfDone();
580  }
581
582  // Overridden from RenderWidgetHostViewAura::PaintObserver:
583  virtual void OnPaintComplete() OVERRIDE {
584    received_paint_update_ = true;
585    StopObservingIfDone();
586  }
587
588  virtual void OnCompositingComplete() OVERRIDE {
589    received_paint_update_ = compositor_updated_;
590    StopObservingIfDone();
591  }
592
593  virtual void OnUpdateCompositorContent() OVERRIDE {
594    compositor_updated_ = true;
595  }
596
597  virtual void OnPageLoadComplete() OVERRIDE {
598    loading_complete_ = true;
599    StopObservingIfDone();
600  }
601
602  virtual void OnViewDestroyed() OVERRIDE {
603    DCHECK(view_);
604    view_->set_paint_observer(NULL);
605    view_ = NULL;
606  }
607
608  // The WebContents which is being navigated.
609  WebContentsImpl* web_contents_;
610
611  scoped_ptr<aura::Window> window_;
612
613  // This is the WindowDelegate of |window_|. The delegate manages its own
614  // lifetime (destroys itself when |window_| is destroyed).
615  ImageWindowDelegate* image_delegate_;
616
617  RenderWidgetHostViewAura* view_;
618  bool loading_complete_;
619  bool received_paint_update_;
620  bool compositor_updated_;
621
622  enum SlideDirection {
623    SLIDE_UNKNOWN,
624    SLIDE_BACK,
625    SLIDE_FRONT
626  };
627
628  // The |WindowSlider| that allows sliding history layers while the page is
629  // being reloaded.
630  scoped_ptr<WindowSlider> window_slider_;
631
632  // The direction of the in-progress slide (if any).
633  SlideDirection slide_direction_;
634
635  // The LayerDelegate used for the back/front layers during a slide.
636  ImageLayerDelegate layer_delegate_;
637
638  // During tests, the aura windows don't get any paint updates. So the overlay
639  // container keeps waiting for a paint update it never receives, causing a
640  // timeout. So during tests, disable the wait for paint updates.
641  bool need_paint_update_;
642
643  DISALLOW_COPY_AND_ASSIGN(OverscrollNavigationOverlay);
644};
645
646class WebContentsViewAura::WindowObserver
647    : public aura::WindowObserver, public aura::RootWindowObserver {
648 public:
649  explicit WindowObserver(WebContentsViewAura* view)
650      : view_(view),
651        parent_(NULL) {
652    view_->window_->AddObserver(this);
653  }
654
655  virtual ~WindowObserver() {
656    view_->window_->RemoveObserver(this);
657    if (view_->window_->GetRootWindow())
658      view_->window_->GetRootWindow()->RemoveRootWindowObserver(this);
659    if (parent_)
660      parent_->RemoveObserver(this);
661  }
662
663  // Overridden from aura::WindowObserver:
664  virtual void OnWindowParentChanged(aura::Window* window,
665                                     aura::Window* parent) OVERRIDE {
666    if (window == parent_)
667      return;
668    if (parent_)
669      parent_->RemoveObserver(this);
670    parent_ = parent;
671    if (parent)
672      parent->AddObserver(this);
673  }
674
675  virtual void OnWindowBoundsChanged(aura::Window* window,
676                                     const gfx::Rect& old_bounds,
677                                     const gfx::Rect& new_bounds) OVERRIDE {
678    SendScreenRects();
679    if (view_->touch_editable_)
680      view_->touch_editable_->UpdateEditingController();
681  }
682
683  virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
684    if (window != parent_)
685      window->GetRootWindow()->AddRootWindowObserver(this);
686  }
687
688  virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE {
689    if (window != parent_)
690      window->GetRootWindow()->RemoveRootWindowObserver(this);
691  }
692
693  // Overridden RootWindowObserver:
694  virtual void OnRootWindowHostMoved(const aura::RootWindow* root,
695                                     const gfx::Point& new_origin) OVERRIDE {
696    // This is for the desktop case (i.e. Aura desktop).
697    SendScreenRects();
698  }
699
700 private:
701  void SendScreenRects() {
702    RenderWidgetHostImpl::From(view_->web_contents_->GetRenderViewHost())->
703        SendScreenRects();
704  }
705
706  WebContentsViewAura* view_;
707
708  // We cache the old parent so that we can unregister when it's not the parent
709  // anymore.
710  aura::Window* parent_;
711
712  DISALLOW_COPY_AND_ASSIGN(WindowObserver);
713};
714
715#if defined(OS_WIN)
716// Constrained windows are added as children of the WebContent's view which may
717// overlap with windowed NPAPI plugins. In that case, tell the RWHV so that it
718// can update the plugins' cutout rects accordingly.
719class WebContentsViewAura::ChildWindowObserver : public aura::WindowObserver,
720                                                 public WebContentsObserver {
721 public:
722  explicit ChildWindowObserver(WebContentsViewAura* view)
723      : WebContentsObserver(view->web_contents_),
724        view_(view),
725        web_contents_destroyed_(false) {
726    view_->window_->AddObserver(this);
727  }
728
729  virtual ~ChildWindowObserver() {
730    view_->window_->RemoveObserver(this);
731    const aura::Window::Windows& children = view_->window_->children();
732    for (size_t i = 0; i < children.size(); ++i)
733      children[i]->RemoveObserver(this);
734  }
735
736  // Overridden from aura::WindowObserver:
737  virtual void OnWindowAdded(aura::Window* new_window) OVERRIDE {
738    // If new child windows are added to the WebContent's view, tell the RWHV.
739    // We also start watching them to know when their size is updated. Of
740    // course, ignore the shadow window that contains the RWHV and child windows
741    // of the child windows that we are watching.
742    RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
743        view_->web_contents_->GetRenderWidgetHostView());
744    aura::Window* content_window = view ? view->GetNativeView() : NULL;
745    if (new_window->parent() == view_->window_ &&
746        new_window != content_window) {
747      new_window->AddObserver(this);
748      UpdateConstrainedWindows(NULL);
749    }
750  }
751
752  virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE {
753    RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
754        view_->web_contents_->GetRenderWidgetHostView());
755    aura::Window* content_window = view ? view->GetNativeView() : NULL;
756    if (window->parent() == view_->window_ &&
757        window != content_window) {
758      window->RemoveObserver(this);
759      UpdateConstrainedWindows(window);
760    }
761  }
762
763  virtual void OnWindowBoundsChanged(aura::Window* window,
764                                     const gfx::Rect& old_bounds,
765                                     const gfx::Rect& new_bounds) OVERRIDE {
766    if (window->parent() == view_->window_ &&
767        window != view_->GetContentNativeView()) {
768      UpdateConstrainedWindows(NULL);
769    }
770  }
771
772  // Overridden from WebContentsObserver:
773  virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE {
774    web_contents_destroyed_ = true;
775  }
776
777 private:
778  void UpdateConstrainedWindows(aura::Window* exclude) {
779    if (web_contents_destroyed_)
780      return;
781
782    RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
783        view_->web_contents_->GetRenderWidgetHostView());
784    if (!view)
785      return;
786
787    std::vector<gfx::Rect> constrained_windows;
788    const aura::Window::Windows& children = view_->window_->children();
789    aura::Window* content = view_->GetContentNativeView();
790    for (size_t i = 0; i < children.size(); ++i) {
791      if (children[i] != content && children[i] != exclude)
792        constrained_windows.push_back(children[i]->GetBoundsInRootWindow());
793    }
794
795    view->UpdateConstrainedWindowRects(constrained_windows);
796  }
797
798  WebContentsViewAura* view_;
799  bool web_contents_destroyed_;
800
801  DISALLOW_COPY_AND_ASSIGN(ChildWindowObserver);
802};
803#endif
804
805////////////////////////////////////////////////////////////////////////////////
806// WebContentsViewAura, public:
807
808WebContentsViewAura::WebContentsViewAura(
809    WebContentsImpl* web_contents,
810    WebContentsViewDelegate* delegate)
811    : web_contents_(web_contents),
812      delegate_(delegate),
813      current_drag_op_(WebKit::WebDragOperationNone),
814      drag_dest_delegate_(NULL),
815      current_rvh_for_drag_(NULL),
816      overscroll_change_brightness_(false),
817      current_overscroll_gesture_(OVERSCROLL_NONE),
818      completed_overscroll_gesture_(OVERSCROLL_NONE),
819      touch_editable_(TouchEditableImplAura::Create()) {
820}
821
822////////////////////////////////////////////////////////////////////////////////
823// WebContentsViewAura, private:
824
825WebContentsViewAura::~WebContentsViewAura() {
826  if (!window_)
827    return;
828
829  window_observer_.reset();
830#if defined(OS_WIN)
831  child_window_observer_.reset();
832#endif
833  // Window needs a valid delegate during its destructor, so we explicitly
834  // delete it here.
835  window_.reset();
836}
837
838void WebContentsViewAura::SetupOverlayWindowForTesting() {
839  if (navigation_overlay_)
840    navigation_overlay_->SetupForTesting();
841}
842
843void WebContentsViewAura::SetTouchEditableForTest(
844    TouchEditableImplAura* touch_editable) {
845  touch_editable_.reset(touch_editable);
846  AttachTouchEditableToRenderView();
847}
848
849void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
850  if (web_contents_->GetInterstitialPage())
851    web_contents_->GetInterstitialPage()->SetSize(size);
852  RenderWidgetHostView* rwhv =
853      web_contents_->GetRenderWidgetHostView();
854  if (rwhv)
855    rwhv->SetSize(size);
856}
857
858void WebContentsViewAura::EndDrag(WebKit::WebDragOperationsMask ops) {
859  aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
860  gfx::Point screen_loc =
861      gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
862  gfx::Point client_loc = screen_loc;
863  RenderViewHost* rvh = web_contents_->GetRenderViewHost();
864  aura::Window* window = rvh->GetView()->GetNativeView();
865  aura::Window::ConvertPointToTarget(root_window, window, &client_loc);
866  if (!web_contents_)
867    return;
868  web_contents_->DragSourceEndedAt(client_loc.x(), client_loc.y(),
869      screen_loc.x(), screen_loc.y(), ops);
870}
871
872void WebContentsViewAura::PrepareOverscrollWindow() {
873  // If there is an existing |overscroll_window_| which is in the middle of an
874  // animation, then destroying the window here causes the animation to be
875  // completed immidiately, which triggers |OnImplicitAnimationsCompleted()|
876  // callback, and that tries to reset |overscroll_window_| again, causing a
877  // double-free. So use a temporary variable here.
878  if (overscroll_window_) {
879    base::AutoReset<OverscrollMode> reset_state(&current_overscroll_gesture_,
880                                                current_overscroll_gesture_);
881    scoped_ptr<aura::Window> reset_window(overscroll_window_.release());
882  }
883
884  OverscrollWindowDelegate* overscroll_delegate = new OverscrollWindowDelegate(
885      web_contents_,
886      current_overscroll_gesture_);
887  overscroll_window_.reset(new aura::Window(overscroll_delegate));
888  overscroll_window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
889  overscroll_window_->SetTransparent(true);
890  overscroll_window_->Init(ui::LAYER_TEXTURED);
891  overscroll_window_->layer()->SetMasksToBounds(false);
892  overscroll_window_->SetName("OverscrollOverlay");
893
894  overscroll_change_brightness_ = overscroll_delegate->has_image();
895  window_->AddChild(overscroll_window_.get());
896
897  gfx::Rect bounds = gfx::Rect(window_->bounds().size());
898  if (ShouldNavigateForward(web_contents_->GetController(),
899                            current_overscroll_gesture_)) {
900    // The overlay will be sliding in from the right edge towards the left in
901    // non-RTL, or sliding in from the left edge towards the right in RTL.
902    // So position the overlay window accordingly.
903    bounds.Offset(base::i18n::IsRTL() ? -bounds.width() : bounds.width(), 0);
904  }
905
906  aura::Window* animate_window = GetWindowToAnimateForOverscroll();
907  if (animate_window == overscroll_window_)
908    window_->StackChildAbove(overscroll_window_.get(), GetContentNativeView());
909  else
910    window_->StackChildBelow(overscroll_window_.get(), GetContentNativeView());
911
912  UpdateOverscrollWindowBrightness(0.f);
913
914  overscroll_window_->SetBounds(bounds);
915  overscroll_window_->Show();
916
917  overscroll_shadow_.reset(new ShadowLayerDelegate(animate_window->layer()));
918}
919
920void WebContentsViewAura::PrepareContentWindowForOverscroll() {
921  StopObservingImplicitAnimations();
922  aura::Window* content = GetContentNativeView();
923  content->layer()->GetAnimator()->AbortAllAnimations();
924  content->SetTransform(gfx::Transform());
925  content->layer()->SetLayerBrightness(0.f);
926}
927
928void WebContentsViewAura::ResetOverscrollTransform() {
929  if (!web_contents_->GetRenderWidgetHostView())
930    return;
931  aura::Window* target = GetWindowToAnimateForOverscroll();
932  if (!target)
933    return;
934  {
935    ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
936    settings.SetPreemptionStrategy(
937        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
938    settings.SetTweenType(gfx::Tween::EASE_OUT);
939    settings.AddObserver(this);
940    target->SetTransform(gfx::Transform());
941  }
942  {
943    ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
944    settings.SetPreemptionStrategy(
945        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
946    settings.SetTweenType(gfx::Tween::EASE_OUT);
947    UpdateOverscrollWindowBrightness(0.f);
948  }
949}
950
951void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) {
952  if (!web_contents_->GetRenderWidgetHostView())
953    return;
954
955  // Animate out the current view first. Navigate to the requested history at
956  // the end of the animation.
957  if (current_overscroll_gesture_ == OVERSCROLL_NONE)
958    return;
959
960  UMA_HISTOGRAM_ENUMERATION("Overscroll.Navigated",
961                            current_overscroll_gesture_, OVERSCROLL_COUNT);
962  OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
963      overscroll_window_->delegate());
964  delegate->stop_forwarding_events();
965
966  completed_overscroll_gesture_ = mode;
967  aura::Window* target = GetWindowToAnimateForOverscroll();
968  ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
969  settings.SetPreemptionStrategy(
970      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
971  settings.SetTweenType(gfx::Tween::EASE_OUT);
972  settings.AddObserver(this);
973  gfx::Transform transform;
974  int content_width =
975      web_contents_->GetRenderWidgetHostView()->GetViewBounds().width();
976  int translate_x = mode == OVERSCROLL_WEST ? -content_width : content_width;
977  transform.Translate(translate_x, 0);
978  target->SetTransform(transform);
979  UpdateOverscrollWindowBrightness(translate_x);
980}
981
982aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() {
983  if (current_overscroll_gesture_ == OVERSCROLL_NONE)
984    return NULL;
985
986  return ShouldNavigateForward(web_contents_->GetController(),
987                               current_overscroll_gesture_) ?
988      overscroll_window_.get() : GetContentNativeView();
989}
990
991gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x,
992                                                               int delta_y) {
993  if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
994      current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
995    return gfx::Vector2d(0, delta_y);
996  }
997  // For horizontal overscroll, scroll freely if a navigation is possible. Do a
998  // resistive scroll otherwise.
999  const NavigationControllerImpl& controller = web_contents_->GetController();
1000  const gfx::Rect& bounds = GetViewBounds();
1001  if (ShouldNavigateForward(controller, current_overscroll_gesture_))
1002    return gfx::Vector2d(std::max(-bounds.width(), delta_x), 0);
1003  else if (ShouldNavigateBack(controller, current_overscroll_gesture_))
1004    return gfx::Vector2d(std::min(bounds.width(), delta_x), 0);
1005  return gfx::Vector2d();
1006}
1007
1008void WebContentsViewAura::PrepareOverscrollNavigationOverlay() {
1009  OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
1010      overscroll_window_->delegate());
1011  overscroll_window_->SchedulePaintInRect(
1012      gfx::Rect(overscroll_window_->bounds().size()));
1013  overscroll_window_->SetBounds(gfx::Rect(window_->bounds().size()));
1014  overscroll_window_->SetTransform(gfx::Transform());
1015  navigation_overlay_->SetOverlayWindow(overscroll_window_.Pass(),
1016                                        delegate);
1017  navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura(
1018      web_contents_->GetRenderWidgetHostView()));
1019}
1020
1021void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x) {
1022  if (!overscroll_change_brightness_)
1023    return;
1024
1025  const float kBrightnessMin = -.1f;
1026  const float kBrightnessMax = -.01f;
1027
1028  float ratio = fabs(delta_x) / GetViewBounds().width();
1029  ratio = std::min(1.f, ratio);
1030  if (base::i18n::IsRTL())
1031    ratio = 1.f - ratio;
1032  float brightness = current_overscroll_gesture_ == OVERSCROLL_WEST ?
1033      kBrightnessMin + ratio * (kBrightnessMax - kBrightnessMin) :
1034      kBrightnessMax - ratio * (kBrightnessMax - kBrightnessMin);
1035  brightness = std::max(kBrightnessMin, brightness);
1036  brightness = std::min(kBrightnessMax, brightness);
1037  aura::Window* window = GetWindowToAnimateForOverscroll();
1038  window->layer()->SetLayerBrightness(brightness);
1039}
1040
1041void WebContentsViewAura::AttachTouchEditableToRenderView() {
1042  if (!touch_editable_)
1043    return;
1044  RenderWidgetHostViewAura* rwhva = ToRenderWidgetHostViewAura(
1045      web_contents_->GetRenderWidgetHostView());
1046  touch_editable_->AttachToView(rwhva);
1047}
1048
1049void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(int delta_y) {
1050  if (web_contents_->GetDelegate() && IsScrollEndEffectEnabled())
1051    web_contents_->GetDelegate()->OverscrollUpdate(delta_y);
1052}
1053
1054////////////////////////////////////////////////////////////////////////////////
1055// WebContentsViewAura, WebContentsView implementation:
1056
1057gfx::NativeView WebContentsViewAura::GetNativeView() const {
1058  return window_.get();
1059}
1060
1061gfx::NativeView WebContentsViewAura::GetContentNativeView() const {
1062  RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1063  return rwhv ? rwhv->GetNativeView() : NULL;
1064}
1065
1066gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const {
1067  return window_->GetToplevelWindow();
1068}
1069
1070void WebContentsViewAura::GetContainerBounds(gfx::Rect *out) const {
1071  *out = window_->GetBoundsInScreen();
1072}
1073
1074void WebContentsViewAura::OnTabCrashed(base::TerminationStatus status,
1075                                       int error_code) {
1076  // Set the focus to the parent because neither the view window nor this
1077  // window can handle key events.
1078  if (window_->HasFocus() && window_->parent())
1079    window_->parent()->Focus();
1080}
1081
1082void WebContentsViewAura::SizeContents(const gfx::Size& size) {
1083  gfx::Rect bounds = window_->bounds();
1084  if (bounds.size() != size) {
1085    bounds.set_size(size);
1086    window_->SetBounds(bounds);
1087  } else {
1088    // Our size matches what we want but the renderers size may not match.
1089    // Pretend we were resized so that the renderers size is updated too.
1090    SizeChangedCommon(size);
1091  }
1092}
1093
1094void WebContentsViewAura::Focus() {
1095  if (web_contents_->GetInterstitialPage()) {
1096    web_contents_->GetInterstitialPage()->Focus();
1097    return;
1098  }
1099
1100  if (delegate_.get() && delegate_->Focus())
1101    return;
1102
1103  RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1104  if (rwhv)
1105    rwhv->Focus();
1106}
1107
1108void WebContentsViewAura::SetInitialFocus() {
1109  if (web_contents_->FocusLocationBarByDefault())
1110    web_contents_->SetFocusToLocationBar(false);
1111  else
1112    Focus();
1113}
1114
1115void WebContentsViewAura::StoreFocus() {
1116  if (delegate_)
1117    delegate_->StoreFocus();
1118}
1119
1120void WebContentsViewAura::RestoreFocus() {
1121  if (delegate_)
1122    delegate_->RestoreFocus();
1123}
1124
1125DropData* WebContentsViewAura::GetDropData() const {
1126  return current_drop_data_.get();
1127}
1128
1129gfx::Rect WebContentsViewAura::GetViewBounds() const {
1130  return window_->GetBoundsInScreen();
1131}
1132
1133////////////////////////////////////////////////////////////////////////////////
1134// WebContentsViewAura, WebContentsViewPort implementation:
1135
1136void WebContentsViewAura::CreateView(
1137    const gfx::Size& initial_size, gfx::NativeView context) {
1138  // NOTE: we ignore |initial_size| since in some cases it's wrong (such as
1139  // if the bookmark bar is not shown and you create a new tab). The right
1140  // value is set shortly after this, so its safe to ignore.
1141
1142  window_.reset(new aura::Window(this));
1143  window_->set_owned_by_parent(false);
1144  window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
1145  window_->SetTransparent(false);
1146  window_->Init(ui::LAYER_NOT_DRAWN);
1147  aura::RootWindow* root_window = context ? context->GetRootWindow() : NULL;
1148  if (root_window) {
1149    // There are places where there is no context currently because object
1150    // hierarchies are built before they're attached to a Widget. (See
1151    // views::WebView as an example; GetWidget() returns NULL at the point
1152    // where we are created.)
1153    //
1154    // It should be OK to not set a default parent since such users will
1155    // explicitly add this WebContentsViewAura to their tree after they create
1156    // us.
1157    if (root_window) {
1158      window_->SetDefaultParentByRootWindow(
1159          root_window, root_window->GetBoundsInScreen());
1160    }
1161  }
1162  window_->layer()->SetMasksToBounds(true);
1163  window_->SetName("WebContentsViewAura");
1164
1165  window_observer_.reset(new WindowObserver(this));
1166#if defined(OS_WIN)
1167  child_window_observer_.reset(new ChildWindowObserver(this));
1168#endif
1169
1170  // delegate_->GetDragDestDelegate() creates a new delegate on every call.
1171  // Hence, we save a reference to it locally. Similar model is used on other
1172  // platforms as well.
1173  if (delegate_)
1174    drag_dest_delegate_ = delegate_->GetDragDestDelegate();
1175}
1176
1177RenderWidgetHostView* WebContentsViewAura::CreateViewForWidget(
1178    RenderWidgetHost* render_widget_host) {
1179  if (render_widget_host->GetView()) {
1180    // During testing, the view will already be set up in most cases to the
1181    // test view, so we don't want to clobber it with a real one. To verify that
1182    // this actually is happening (and somebody isn't accidentally creating the
1183    // view twice), we check for the RVH Factory, which will be set when we're
1184    // making special ones (which go along with the special views).
1185    DCHECK(RenderViewHostFactory::has_factory());
1186    return render_widget_host->GetView();
1187  }
1188
1189  RenderWidgetHostView* view =
1190      RenderWidgetHostView::CreateViewForWidget(render_widget_host);
1191  view->InitAsChild(NULL);
1192  GetNativeView()->AddChild(view->GetNativeView());
1193
1194  if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
1195    navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura(view));
1196  }
1197
1198  RenderWidgetHostImpl* host_impl =
1199      RenderWidgetHostImpl::From(render_widget_host);
1200
1201  if (!host_impl->is_hidden())
1202    view->Show();
1203
1204  // We listen to drag drop events in the newly created view's window.
1205  aura::client::SetDragDropDelegate(view->GetNativeView(), this);
1206
1207  if (host_impl->overscroll_controller() &&
1208      (!web_contents_->GetDelegate() ||
1209       web_contents_->GetDelegate()->CanOverscrollContent())) {
1210    host_impl->overscroll_controller()->set_delegate(this);
1211    if (!navigation_overlay_)
1212      navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
1213  }
1214
1215  AttachTouchEditableToRenderView();
1216  return view;
1217}
1218
1219RenderWidgetHostView* WebContentsViewAura::CreateViewForPopupWidget(
1220    RenderWidgetHost* render_widget_host) {
1221  return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host);
1222}
1223
1224void WebContentsViewAura::SetPageTitle(const string16& title) {
1225  window_->set_title(title);
1226}
1227
1228void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) {
1229}
1230
1231void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) {
1232  if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
1233    navigation_overlay_->StartObservingView(
1234        ToRenderWidgetHostViewAura(host->GetView()));
1235  }
1236  AttachTouchEditableToRenderView();
1237}
1238
1239void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) {
1240  RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>(
1241      web_contents_->GetRenderViewHost());
1242  if (host) {
1243    host->SetOverscrollControllerEnabled(enabled);
1244    if (enabled)
1245      host->overscroll_controller()->set_delegate(this);
1246  }
1247
1248  if (!enabled)
1249    navigation_overlay_.reset();
1250  else if (!navigation_overlay_)
1251    navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
1252}
1253
1254////////////////////////////////////////////////////////////////////////////////
1255// WebContentsViewAura, RenderViewHostDelegateView implementation:
1256
1257void WebContentsViewAura::ShowContextMenu(const ContextMenuParams& params) {
1258  if (touch_editable_)
1259    touch_editable_->EndTouchEditing();
1260  if (delegate_) {
1261    delegate_->ShowContextMenu(params);
1262    // WARNING: we may have been deleted during the call to ShowContextMenu().
1263  }
1264}
1265
1266void WebContentsViewAura::ShowPopupMenu(const gfx::Rect& bounds,
1267                                        int item_height,
1268                                        double item_font_size,
1269                                        int selected_item,
1270                                        const std::vector<MenuItem>& items,
1271                                        bool right_aligned,
1272                                        bool allow_multiple_selection) {
1273  // External popup menus are only used on Mac and Android.
1274  NOTIMPLEMENTED();
1275}
1276
1277void WebContentsViewAura::StartDragging(
1278    const DropData& drop_data,
1279    WebKit::WebDragOperationsMask operations,
1280    const gfx::ImageSkia& image,
1281    const gfx::Vector2d& image_offset,
1282    const DragEventSourceInfo& event_info) {
1283  aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
1284  if (!aura::client::GetDragDropClient(root_window)) {
1285    web_contents_->SystemDragEnded();
1286    return;
1287  }
1288
1289  if (touch_editable_)
1290    touch_editable_->EndTouchEditing();
1291
1292  ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider();
1293  PrepareDragData(drop_data, provider);
1294
1295  ui::OSExchangeData data(provider);  // takes ownership of |provider|.
1296
1297  if (!image.isNull()) {
1298    drag_utils::SetDragImageOnDataObject(image,
1299        gfx::Size(image.width(), image.height()), image_offset, &data);
1300  }
1301
1302  scoped_ptr<WebDragSourceAura> drag_source(
1303      new WebDragSourceAura(GetNativeView(), web_contents_));
1304
1305  // We need to enable recursive tasks on the message loop so we can get
1306  // updates while in the system DoDragDrop loop.
1307  int result_op = 0;
1308  {
1309    gfx::NativeView content_native_view = GetContentNativeView();
1310    base::MessageLoop::ScopedNestableTaskAllower allow(
1311        base::MessageLoop::current());
1312    result_op = aura::client::GetDragDropClient(root_window)
1313        ->StartDragAndDrop(data,
1314                           root_window,
1315                           content_native_view,
1316                           event_info.event_location,
1317                           ConvertFromWeb(operations),
1318                           event_info.event_source);
1319  }
1320
1321  // Bail out immediately if the contents view window is gone. Note that it is
1322  // not safe to access any class members in this case since |this| may already
1323  // be destroyed. The local variable |drag_source| will still be valid though,
1324  // so we can use it to determine if the window is gone.
1325  if (!drag_source->window()) {
1326    // Note that in this case, we don't need to call SystemDragEnded() since the
1327    // renderer is going away.
1328    return;
1329  }
1330
1331  EndDrag(ConvertToWeb(result_op));
1332  web_contents_->SystemDragEnded();
1333}
1334
1335void WebContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) {
1336  current_drag_op_ = operation;
1337}
1338
1339void WebContentsViewAura::GotFocus() {
1340  if (web_contents_->GetDelegate())
1341    web_contents_->GetDelegate()->WebContentsFocused(web_contents_);
1342}
1343
1344void WebContentsViewAura::TakeFocus(bool reverse) {
1345  if (web_contents_->GetDelegate() &&
1346      !web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) &&
1347      delegate_.get()) {
1348    delegate_->TakeFocus(reverse);
1349  }
1350}
1351
1352////////////////////////////////////////////////////////////////////////////////
1353// WebContentsViewAura, OverscrollControllerDelegate implementation:
1354
1355void WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
1356  if (current_overscroll_gesture_ == OVERSCROLL_NONE)
1357    return;
1358
1359  aura::Window* target = GetWindowToAnimateForOverscroll();
1360  ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
1361  settings.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET);
1362  gfx::Vector2d translate = GetTranslationForOverscroll(delta_x, delta_y);
1363  gfx::Transform transform;
1364
1365  // Vertical overscrolls don't participate in the navigation gesture.
1366  if (current_overscroll_gesture_ != OVERSCROLL_NORTH &&
1367      current_overscroll_gesture_ != OVERSCROLL_SOUTH) {
1368    transform.Translate(translate.x(), translate.y());
1369    target->SetTransform(transform);
1370    UpdateOverscrollWindowBrightness(delta_x);
1371  }
1372
1373  OverscrollUpdateForWebContentsDelegate(translate.y());
1374}
1375
1376void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) {
1377  UMA_HISTOGRAM_ENUMERATION("Overscroll.Completed", mode, OVERSCROLL_COUNT);
1378  OverscrollUpdateForWebContentsDelegate(0);
1379  NavigationControllerImpl& controller = web_contents_->GetController();
1380  if (ShouldNavigateForward(controller, mode) ||
1381      ShouldNavigateBack(controller, mode)) {
1382    CompleteOverscrollNavigation(mode);
1383    return;
1384  }
1385
1386  ResetOverscrollTransform();
1387}
1388
1389void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
1390                                                 OverscrollMode new_mode) {
1391  // Reset any in-progress overscroll animation first.
1392  ResetOverscrollTransform();
1393
1394  if (new_mode != OVERSCROLL_NONE && touch_editable_)
1395    touch_editable_->OverscrollStarted();
1396
1397  if (new_mode == OVERSCROLL_NONE ||
1398      !GetContentNativeView() ||
1399      ((new_mode == OVERSCROLL_EAST || new_mode == OVERSCROLL_WEST) &&
1400       navigation_overlay_.get() && navigation_overlay_->has_window())) {
1401    current_overscroll_gesture_ = OVERSCROLL_NONE;
1402    OverscrollUpdateForWebContentsDelegate(0);
1403  } else {
1404    aura::Window* target = GetWindowToAnimateForOverscroll();
1405    if (target) {
1406      StopObservingImplicitAnimations();
1407      target->layer()->GetAnimator()->AbortAllAnimations();
1408    }
1409    // Cleanup state of the content window first, because that can reset the
1410    // value of |current_overscroll_gesture_|.
1411    PrepareContentWindowForOverscroll();
1412
1413    current_overscroll_gesture_ = new_mode;
1414    if (current_overscroll_gesture_ == OVERSCROLL_EAST ||
1415        current_overscroll_gesture_ == OVERSCROLL_WEST)
1416      PrepareOverscrollWindow();
1417
1418    UMA_HISTOGRAM_ENUMERATION("Overscroll.Started", new_mode, OVERSCROLL_COUNT);
1419  }
1420  completed_overscroll_gesture_ = OVERSCROLL_NONE;
1421}
1422
1423////////////////////////////////////////////////////////////////////////////////
1424// WebContentsViewAura, ui::ImplicitAnimationObserver implementation:
1425
1426void WebContentsViewAura::OnImplicitAnimationsCompleted() {
1427  overscroll_shadow_.reset();
1428
1429  if (ShouldNavigateForward(web_contents_->GetController(),
1430                            completed_overscroll_gesture_)) {
1431    PrepareOverscrollNavigationOverlay();
1432    web_contents_->GetController().GoForward();
1433  } else if (ShouldNavigateBack(web_contents_->GetController(),
1434                                completed_overscroll_gesture_)) {
1435    PrepareOverscrollNavigationOverlay();
1436    web_contents_->GetController().GoBack();
1437  } else {
1438    if (touch_editable_)
1439      touch_editable_->OverscrollCompleted();
1440  }
1441
1442  aura::Window* content = GetContentNativeView();
1443  if (content) {
1444    content->SetTransform(gfx::Transform());
1445    content->layer()->SetLayerBrightness(0.f);
1446  }
1447  current_overscroll_gesture_ = OVERSCROLL_NONE;
1448  completed_overscroll_gesture_ = OVERSCROLL_NONE;
1449  overscroll_window_.reset();
1450}
1451
1452////////////////////////////////////////////////////////////////////////////////
1453// WebContentsViewAura, aura::WindowDelegate implementation:
1454
1455gfx::Size WebContentsViewAura::GetMinimumSize() const {
1456  return gfx::Size();
1457}
1458
1459gfx::Size WebContentsViewAura::GetMaximumSize() const {
1460  return gfx::Size();
1461}
1462
1463void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1464                                          const gfx::Rect& new_bounds) {
1465  SizeChangedCommon(new_bounds.size());
1466  if (delegate_)
1467    delegate_->SizeChanged(new_bounds.size());
1468
1469  // Constrained web dialogs, need to be kept centered over our content area.
1470  for (size_t i = 0; i < window_->children().size(); i++) {
1471    if (window_->children()[i]->GetProperty(
1472            aura::client::kConstrainedWindowKey)) {
1473      gfx::Rect bounds = window_->children()[i]->bounds();
1474      bounds.set_origin(
1475          gfx::Point((new_bounds.width() - bounds.width()) / 2,
1476                     (new_bounds.height() - bounds.height()) / 2));
1477      window_->children()[i]->SetBounds(bounds);
1478    }
1479  }
1480}
1481
1482gfx::NativeCursor WebContentsViewAura::GetCursor(const gfx::Point& point) {
1483  return gfx::kNullCursor;
1484}
1485
1486int WebContentsViewAura::GetNonClientComponent(const gfx::Point& point) const {
1487  return HTCLIENT;
1488}
1489
1490bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
1491    aura::Window* child,
1492    const gfx::Point& location) {
1493  return true;
1494}
1495
1496bool WebContentsViewAura::CanFocus() {
1497  // Do not take the focus if the render widget host view is gone because
1498  // neither the view window nor this window can handle key events.
1499  return web_contents_->GetRenderWidgetHostView() != NULL;
1500}
1501
1502void WebContentsViewAura::OnCaptureLost() {
1503}
1504
1505void WebContentsViewAura::OnPaint(gfx::Canvas* canvas) {
1506}
1507
1508void WebContentsViewAura::OnDeviceScaleFactorChanged(
1509    float device_scale_factor) {
1510}
1511
1512void WebContentsViewAura::OnWindowDestroying() {
1513  // This means the destructor is going to be called soon. If there is an
1514  // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL),
1515  // then destroying it in the WebContentsViewAura destructor can trigger other
1516  // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So
1517  // destroy the overscroll window here.
1518  navigation_overlay_.reset();
1519  overscroll_window_.reset();
1520}
1521
1522void WebContentsViewAura::OnWindowDestroyed() {
1523}
1524
1525void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1526  if (visible)
1527    web_contents_->WasShown();
1528  else
1529    web_contents_->WasHidden();
1530}
1531
1532bool WebContentsViewAura::HasHitTestMask() const {
1533  return false;
1534}
1535
1536void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const {
1537}
1538
1539void WebContentsViewAura::DidRecreateLayer(ui::Layer *old_layer,
1540                                           ui::Layer *new_layer) {
1541}
1542
1543////////////////////////////////////////////////////////////////////////////////
1544// WebContentsViewAura, ui::EventHandler implementation:
1545
1546void WebContentsViewAura::OnKeyEvent(ui::KeyEvent* event) {
1547}
1548
1549void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
1550  if (!web_contents_->GetDelegate())
1551    return;
1552
1553  switch (event->type()) {
1554    case ui::ET_MOUSE_PRESSED:
1555      web_contents_->GetDelegate()->ActivateContents(web_contents_);
1556      break;
1557    case ui::ET_MOUSE_MOVED:
1558    case ui::ET_MOUSE_EXITED:
1559      web_contents_->GetDelegate()->ContentsMouseEvent(
1560          web_contents_,
1561          gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1562          event->type() == ui::ET_MOUSE_MOVED);
1563      break;
1564    default:
1565      break;
1566  }
1567}
1568
1569////////////////////////////////////////////////////////////////////////////////
1570// WebContentsViewAura, aura::client::DragDropDelegate implementation:
1571
1572void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
1573  if (drag_dest_delegate_)
1574    drag_dest_delegate_->DragInitialize(web_contents_);
1575
1576  current_drop_data_.reset(new DropData());
1577
1578  PrepareDropData(current_drop_data_.get(), event.data());
1579  WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1580
1581  gfx::Point screen_pt =
1582      gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1583  current_rvh_for_drag_ = web_contents_->GetRenderViewHost();
1584  web_contents_->GetRenderViewHost()->DragTargetDragEnter(
1585      *current_drop_data_.get(), event.location(), screen_pt, op,
1586      ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1587
1588  if (drag_dest_delegate_) {
1589    drag_dest_delegate_->OnReceiveDragData(event.data());
1590    drag_dest_delegate_->OnDragEnter();
1591  }
1592}
1593
1594int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
1595  DCHECK(current_rvh_for_drag_);
1596  if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1597    OnDragEntered(event);
1598
1599  WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1600  gfx::Point screen_pt =
1601      gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1602  web_contents_->GetRenderViewHost()->DragTargetDragOver(
1603      event.location(), screen_pt, op,
1604      ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1605
1606  if (drag_dest_delegate_)
1607    drag_dest_delegate_->OnDragOver();
1608
1609  return ConvertFromWeb(current_drag_op_);
1610}
1611
1612void WebContentsViewAura::OnDragExited() {
1613  DCHECK(current_rvh_for_drag_);
1614  if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1615    return;
1616
1617  web_contents_->GetRenderViewHost()->DragTargetDragLeave();
1618  if (drag_dest_delegate_)
1619    drag_dest_delegate_->OnDragLeave();
1620
1621  current_drop_data_.reset();
1622}
1623
1624int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
1625  DCHECK(current_rvh_for_drag_);
1626  if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1627    OnDragEntered(event);
1628
1629  web_contents_->GetRenderViewHost()->DragTargetDrop(
1630      event.location(),
1631      gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1632      ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1633  if (drag_dest_delegate_)
1634    drag_dest_delegate_->OnDrop();
1635  current_drop_data_.reset();
1636  return current_drag_op_;
1637}
1638
1639}  // namespace content
1640