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