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