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