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