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