15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/web_contents/aura/overscroll_navigation_overlay.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/frame_host/navigation_entry_impl.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/renderer_host/render_view_host_impl.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/web_contents/aura/image_window_delegate.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/web_contents/web_contents_impl.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/common/view_messages.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
13effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "content/public/browser/render_widget_host_view.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/window.h"
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/base/layout.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/compositor/layer.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/compositor/layer_animation_observer.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/canvas.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/image/image_png_rep.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/image/image_skia.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace content {
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace {
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Returns true if the entry's URL or any of the URLs in entry's redirect chain
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// match |url|.
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool DoesEntryMatchURL(NavigationEntry* entry, const GURL& url) {
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (entry->GetURL() == url)
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return true;
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const std::vector<GURL>& redirect_chain = entry->GetRedirectChain();
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (std::vector<GURL>::const_iterator it = redirect_chain.begin();
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       it != redirect_chain.end();
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       it++) {
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (*it == url)
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return true;
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return false;
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A LayerDelegate that paints an image for the layer.
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ImageLayerDelegate : public ui::LayerDelegate {
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ImageLayerDelegate() {}
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~ImageLayerDelegate() {}
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetImage(const gfx::Image& image) {
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    image_ = image;
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    image_size_ = image.AsImageSkia().size();
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::Image& image() const { return image_; }
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Overridden from ui::LayerDelegate:
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (image_.IsEmpty()) {
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      canvas->DrawColor(SK_ColorWHITE);
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SkISize size = canvas->sk_canvas()->getDeviceSize();
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (size.width() != image_size_.width() ||
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          size.height() != image_size_.height()) {
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        canvas->DrawColor(SK_ColorWHITE);
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      canvas->DrawImageInt(image_.AsImageSkia(), 0, 0);
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnDelegatedFrameDamage(
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const gfx::Rect& damage_rect_in_dip) OVERRIDE {}
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Called when the layer's device scale factor has changed.
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Invoked prior to the bounds changing. The returned closured is run after
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the bounds change.
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return base::Closure();
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Image image_;
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Size image_size_;
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ImageLayerDelegate);
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Responsible for fading out and deleting the layer of the overlay window.
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class OverlayDismissAnimator
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : public ui::LayerAnimationObserver {
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Takes ownership of the layer.
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  explicit OverlayDismissAnimator(scoped_ptr<ui::Layer> layer)
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : layer_(layer.Pass()) {
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CHECK(layer_.get());
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Starts the fadeout animation on the layer. When the animation finishes,
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // the object deletes itself along with the layer.
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void Animate() {
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK(layer_.get());
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ui::LayerAnimator* animator = layer_->GetAnimator();
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // This makes SetOpacity() animate with default duration (which could be
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // zero, e.g. when running tests).
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ui::ScopedLayerAnimationSettings settings(animator);
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    animator->AddObserver(this);
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    layer_->SetOpacity(0);
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Overridden from ui::LayerAnimationObserver
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnLayerAnimationEnded(
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ui::LayerAnimationSequence* sequence) OVERRIDE {
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    delete this;
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnLayerAnimationAborted(
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ui::LayerAnimationSequence* sequence) OVERRIDE {
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    delete this;
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnLayerAnimationScheduled(
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ui::LayerAnimationSequence* sequence) OVERRIDE {}
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual ~OverlayDismissAnimator() {}
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<ui::Layer> layer_;
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OverlayDismissAnimator);
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)OverscrollNavigationOverlay::OverscrollNavigationOverlay(
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebContentsImpl* web_contents)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : web_contents_(web_contents),
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      image_delegate_(NULL),
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      loading_complete_(false),
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      received_paint_update_(false),
14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      slide_direction_(SLIDE_UNKNOWN) {
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)OverscrollNavigationOverlay::~OverscrollNavigationOverlay() {
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OverscrollNavigationOverlay::StartObserving() {
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  loading_complete_ = false;
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  received_paint_update_ = false;
14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  overlay_dismiss_layer_.reset();
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Observe(web_contents_);
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Make sure the overlay window is on top.
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (window_.get() && window_->parent())
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window_->parent()->StackChildAtTop(window_.get());
155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Assumes the navigation has been initiated.
157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  NavigationEntry* pending_entry =
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      web_contents_->GetController().GetPendingEntry();
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Save url of the pending entry to identify when it loads and paints later.
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Under some circumstances navigation can leave a null pending entry -
161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // see comments in NavigationControllerImpl::NavigateToPendingEntry().
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  pending_entry_url_ = pending_entry ? pending_entry->GetURL() : GURL();
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OverscrollNavigationOverlay::SetOverlayWindow(
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<aura::Window> window,
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ImageWindowDelegate* delegate) {
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window_ = window.Pass();
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (window_.get() && window_->parent())
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window_->parent()->StackChildAtTop(window_.get());
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  image_delegate_ = delegate;
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (window_.get() && delegate->has_image()) {
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window_slider_.reset(new WindowSlider(this,
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          window_->parent(),
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          window_.get()));
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    slide_direction_ = SLIDE_UNKNOWN;
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window_slider_.reset();
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OverscrollNavigationOverlay::StopObservingIfDone() {
18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Normally we dismiss the overlay once we receive a paint update, however
18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // for in-page navigations DidFirstVisuallyNonEmptyPaint() does not get
18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // called, and we rely on loading_complete_ for those cases.
18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!received_paint_update_ && !loading_complete_)
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If a slide is in progress, then do not destroy the window or the slide.
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (window_slider_.get() && window_slider_->IsSlideInProgress())
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // The layer to be animated by OverlayDismissAnimator
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<ui::Layer> overlay_dismiss_layer;
19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (overlay_dismiss_layer_)
19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    overlay_dismiss_layer = overlay_dismiss_layer_.Pass();
19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  else if (window_.get())
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    overlay_dismiss_layer = window_->AcquireLayer();
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Observe(NULL);
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window_slider_.reset();
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window_.reset();
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  image_delegate_ = NULL;
20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (overlay_dismiss_layer.get()) {
20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // OverlayDismissAnimator deletes overlay_dismiss_layer and itself when the
20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // animation completes.
20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    (new OverlayDismissAnimator(overlay_dismiss_layer.Pass()))->Animate();
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ui::Layer* OverscrollNavigationOverlay::CreateSlideLayer(int offset) {
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const NavigationControllerImpl& controller = web_contents_->GetController();
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      controller.GetEntryAtOffset(offset));
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Image image;
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (entry && entry->screenshot().get()) {
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::vector<gfx::ImagePNGRep> image_reps;
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), 1.0f));
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    image = gfx::Image(image_reps);
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!layer_delegate_)
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    layer_delegate_.reset(new ImageLayerDelegate());
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  layer_delegate_->SetImage(image);
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::Layer* layer = new ui::Layer(ui::LAYER_TEXTURED);
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  layer->set_delegate(layer_delegate_.get());
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return layer;
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ui::Layer* OverscrollNavigationOverlay::CreateBackLayer() {
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!web_contents_->GetController().CanGoBack())
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  slide_direction_ = SLIDE_BACK;
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return CreateSlideLayer(-1);
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ui::Layer* OverscrollNavigationOverlay::CreateFrontLayer() {
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!web_contents_->GetController().CanGoForward())
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  slide_direction_ = SLIDE_FRONT;
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return CreateSlideLayer(1);
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid OverscrollNavigationOverlay::OnWindowSlideCompleting() {
246effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (slide_direction_ == SLIDE_UNKNOWN)
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Perform the navigation.
250effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (slide_direction_ == SLIDE_BACK)
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    web_contents_->GetController().GoBack();
252effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  else if (slide_direction_ == SLIDE_FRONT)
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    web_contents_->GetController().GoForward();
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    NOTREACHED();
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Reset state and wait for the new navigation page to complete
258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // loading/painting.
259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  StartObserving();
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
26246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void OverscrollNavigationOverlay::OnWindowSlideCompleted(
26346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<ui::Layer> layer) {
264effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (slide_direction_ == SLIDE_UNKNOWN) {
265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    window_slider_.reset();
266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    StopObservingIfDone();
267effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
268effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
269effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
270effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Change the image used for the overlay window.
271effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  image_delegate_->SetImage(layer_delegate_->image());
272effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  window_->layer()->SetTransform(gfx::Transform());
273effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  window_->SchedulePaintInRect(gfx::Rect(window_->bounds().size()));
274effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  slide_direction_ = SLIDE_UNKNOWN;
27546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // We may end up dismissing the overlay before it has a chance to repaint, so
27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // set the slider layer to be the one animated by OverlayDismissAnimator.
27746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (layer.get())
27846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    overlay_dismiss_layer_ = layer.Pass();
27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  StopObservingIfDone();
280effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OverscrollNavigationOverlay::OnWindowSlideAborted() {
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StopObservingIfDone();
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OverscrollNavigationOverlay::OnWindowSliderDestroyed() {
287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We only want to take an action here if WindowSlider is being destroyed
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // outside of OverscrollNavigationOverlay. If window_slider_.get() is NULL,
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // then OverscrollNavigationOverlay is the one destroying WindowSlider, and
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // we don't need to do anything.
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // This check prevents StopObservingIfDone() being called multiple times
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // (including recursively) for a single event.
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (window_slider_.get()) {
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // The slider has just been destroyed. Release the ownership.
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    WindowSlider* slider ALLOW_UNUSED = window_slider_.release();
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    StopObservingIfDone();
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void OverscrollNavigationOverlay::DidFirstVisuallyNonEmptyPaint() {
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NavigationEntry* visible_entry =
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      web_contents_->GetController().GetVisibleEntry();
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (pending_entry_url_.is_empty() ||
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DoesEntryMatchURL(visible_entry, pending_entry_url_)) {
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    received_paint_update_ = true;
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    StopObservingIfDone();
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OverscrollNavigationOverlay::DidStopLoading(RenderViewHost* host) {
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Don't compare URLs in this case - it's possible they won't match if
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // a gesture-nav initiated navigation was interrupted by some other in-site
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // navigation ((e.g., from a script, or from a bookmark).
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  loading_complete_ = true;
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  StopObservingIfDone();
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace content
319