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