OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/web_contents/aura/overscroll_navigation_overlay.h" | 5 #include "content/browser/web_contents/aura/overscroll_navigation_overlay.h" |
6 | 6 |
7 #include "content/browser/frame_host/navigation_entry_impl.h" | 7 #include "content/browser/frame_host/navigation_entry_impl.h" |
8 #include "content/browser/renderer_host/render_view_host_impl.h" | 8 #include "content/browser/renderer_host/render_view_host_impl.h" |
9 #include "content/browser/web_contents/aura/image_window_delegate.h" | 9 #include "content/browser/web_contents/aura/image_window_delegate.h" |
10 #include "content/browser/web_contents/web_contents_impl.h" | 10 #include "content/browser/web_contents/web_contents_impl.h" |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 DISALLOW_COPY_AND_ASSIGN(OverlayDismissAnimator); | 110 DISALLOW_COPY_AND_ASSIGN(OverlayDismissAnimator); |
111 }; | 111 }; |
112 | 112 |
113 OverscrollNavigationOverlay::OverscrollNavigationOverlay( | 113 OverscrollNavigationOverlay::OverscrollNavigationOverlay( |
114 WebContentsImpl* web_contents) | 114 WebContentsImpl* web_contents) |
115 : web_contents_(web_contents), | 115 : web_contents_(web_contents), |
116 image_delegate_(NULL), | 116 image_delegate_(NULL), |
117 loading_complete_(false), | 117 loading_complete_(false), |
118 received_paint_update_(false), | 118 received_paint_update_(false), |
119 pending_entry_id_(0), | 119 pending_entry_id_(0), |
120 slide_direction_(SLIDE_UNKNOWN), | 120 slide_direction_(SLIDE_UNKNOWN) { |
121 need_paint_update_(true) { | |
122 } | 121 } |
123 | 122 |
124 OverscrollNavigationOverlay::~OverscrollNavigationOverlay() { | 123 OverscrollNavigationOverlay::~OverscrollNavigationOverlay() { |
125 } | 124 } |
126 | 125 |
127 void OverscrollNavigationOverlay::StartObserving() { | 126 void OverscrollNavigationOverlay::StartObserving() { |
128 loading_complete_ = false; | 127 loading_complete_ = false; |
129 received_paint_update_ = false; | 128 received_paint_update_ = false; |
| 129 overlay_dismiss_layer_.reset(); |
130 pending_entry_id_ = 0; | 130 pending_entry_id_ = 0; |
131 Observe(web_contents_); | 131 Observe(web_contents_); |
132 | 132 |
133 // Make sure the overlay window is on top. | 133 // Make sure the overlay window is on top. |
134 if (window_.get() && window_->parent()) | 134 if (window_.get() && window_->parent()) |
135 window_->parent()->StackChildAtTop(window_.get()); | 135 window_->parent()->StackChildAtTop(window_.get()); |
136 | 136 |
137 // Assumes the navigation has been initiated. | 137 // Assumes the navigation has been initiated. |
138 NavigationEntry* pending_entry = | 138 NavigationEntry* pending_entry = |
139 web_contents_->GetController().GetPendingEntry(); | 139 web_contents_->GetController().GetPendingEntry(); |
(...skipping 14 matching lines...) Expand all Loading... |
154 if (window_.get() && delegate->has_image()) { | 154 if (window_.get() && delegate->has_image()) { |
155 window_slider_.reset(new WindowSlider(this, | 155 window_slider_.reset(new WindowSlider(this, |
156 window_->parent(), | 156 window_->parent(), |
157 window_.get())); | 157 window_.get())); |
158 slide_direction_ = SLIDE_UNKNOWN; | 158 slide_direction_ = SLIDE_UNKNOWN; |
159 } else { | 159 } else { |
160 window_slider_.reset(); | 160 window_slider_.reset(); |
161 } | 161 } |
162 } | 162 } |
163 | 163 |
164 void OverscrollNavigationOverlay::SetupForTesting() { | |
165 need_paint_update_ = false; | |
166 } | |
167 | |
168 void OverscrollNavigationOverlay::StopObservingIfDone() { | 164 void OverscrollNavigationOverlay::StopObservingIfDone() { |
169 if ((need_paint_update_ && !received_paint_update_)) { | 165 // Normally we dismiss the overlay once we receive a paint update, however |
| 166 // for in-page navigations DidFirstVisuallyNonEmptyPaint() does not get |
| 167 // called, and we rely on loading_complete_ for those cases. |
| 168 if (!received_paint_update_ && !loading_complete_) |
170 return; | 169 return; |
171 } | |
172 | 170 |
173 // If a slide is in progress, then do not destroy the window or the slide. | 171 // If a slide is in progress, then do not destroy the window or the slide. |
174 if (window_slider_.get() && window_slider_->IsSlideInProgress()) | 172 if (window_slider_.get() && window_slider_->IsSlideInProgress()) |
175 return; | 173 return; |
176 | 174 |
177 scoped_ptr<ui::Layer> layer; | 175 // The layer to be animated by OverlayDismissAnimator |
178 if (window_.get()) | 176 scoped_ptr<ui::Layer> overlay_dismiss_layer; |
179 layer = window_->AcquireLayer(); | 177 if (overlay_dismiss_layer_) |
| 178 overlay_dismiss_layer = overlay_dismiss_layer_.Pass(); |
| 179 else if (window_.get()) |
| 180 overlay_dismiss_layer = window_->AcquireLayer(); |
180 Observe(NULL); | 181 Observe(NULL); |
181 window_slider_.reset(); | 182 window_slider_.reset(); |
182 window_.reset(); | 183 window_.reset(); |
183 image_delegate_ = NULL; | 184 image_delegate_ = NULL; |
184 if (layer.get()) { | 185 if (overlay_dismiss_layer.get()) { |
185 // OverlayDismissAnimator deletes the layer and itself when the animation | 186 // OverlayDismissAnimator deletes overlay_dismiss_layer and itself when the |
186 // completes. | 187 // animation completes. |
187 (new OverlayDismissAnimator(layer.Pass()))->Animate(); | 188 (new OverlayDismissAnimator(overlay_dismiss_layer.Pass()))->Animate(); |
188 } | 189 } |
189 } | 190 } |
190 | 191 |
191 ui::Layer* OverscrollNavigationOverlay::CreateSlideLayer(int offset) { | 192 ui::Layer* OverscrollNavigationOverlay::CreateSlideLayer(int offset) { |
192 const NavigationControllerImpl& controller = web_contents_->GetController(); | 193 const NavigationControllerImpl& controller = web_contents_->GetController(); |
193 const NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( | 194 const NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( |
194 controller.GetEntryAtOffset(offset)); | 195 controller.GetEntryAtOffset(offset)); |
195 | 196 |
196 gfx::Image image; | 197 gfx::Image image; |
197 if (entry && entry->screenshot().get()) { | 198 if (entry && entry->screenshot().get()) { |
198 std::vector<gfx::ImagePNGRep> image_reps; | 199 std::vector<gfx::ImagePNGRep> image_reps; |
199 image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), | 200 image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), |
200 ui::GetScaleFactorForNativeView(window_.get()))); | 201 ui::GetScaleFactorForNativeView(window_.get()))); |
201 image = gfx::Image(image_reps); | 202 image = gfx::Image(image_reps); |
202 } | 203 } |
203 if (!layer_delegate_) | 204 if (!layer_delegate_) |
204 layer_delegate_.reset(new ImageLayerDelegate()); | 205 layer_delegate_.reset(new ImageLayerDelegate()); |
205 layer_delegate_->SetImage(image); | 206 layer_delegate_->SetImage(image); |
206 | 207 |
207 ui::Layer* layer = new ui::Layer(ui::LAYER_TEXTURED); | 208 ui::Layer* layer = new ui::Layer(ui::LAYER_TEXTURED); |
208 layer->set_delegate(layer_delegate_.get()); | 209 layer->set_delegate(layer_delegate_.get()); |
209 return layer; | 210 return layer; |
210 } | 211 } |
211 | 212 |
212 void OverscrollNavigationOverlay::OnUpdateRect( | |
213 const ViewHostMsg_UpdateRect_Params& params) { | |
214 if (loading_complete_ && | |
215 ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params.flags)) { | |
216 NavigationEntry* visible_entry = | |
217 web_contents_->GetController().GetVisibleEntry(); | |
218 int visible_entry_id = visible_entry ? visible_entry->GetUniqueID() : 0; | |
219 if (visible_entry_id == pending_entry_id_ || !pending_entry_id_) { | |
220 // This is a paint update after the page has been loaded. So do not wait | |
221 // for a 'first non-empty' paint update. | |
222 received_paint_update_ = true; | |
223 StopObservingIfDone(); | |
224 } | |
225 } | |
226 } | |
227 | |
228 ui::Layer* OverscrollNavigationOverlay::CreateBackLayer() { | 213 ui::Layer* OverscrollNavigationOverlay::CreateBackLayer() { |
229 if (!web_contents_->GetController().CanGoBack()) | 214 if (!web_contents_->GetController().CanGoBack()) |
230 return NULL; | 215 return NULL; |
231 slide_direction_ = SLIDE_BACK; | 216 slide_direction_ = SLIDE_BACK; |
232 return CreateSlideLayer(-1); | 217 return CreateSlideLayer(-1); |
233 } | 218 } |
234 | 219 |
235 ui::Layer* OverscrollNavigationOverlay::CreateFrontLayer() { | 220 ui::Layer* OverscrollNavigationOverlay::CreateFrontLayer() { |
236 if (!web_contents_->GetController().CanGoForward()) | 221 if (!web_contents_->GetController().CanGoForward()) |
237 return NULL; | 222 return NULL; |
(...skipping 11 matching lines...) Expand all Loading... |
249 else if (slide_direction_ == SLIDE_FRONT) | 234 else if (slide_direction_ == SLIDE_FRONT) |
250 web_contents_->GetController().GoForward(); | 235 web_contents_->GetController().GoForward(); |
251 else | 236 else |
252 NOTREACHED(); | 237 NOTREACHED(); |
253 | 238 |
254 // Reset state and wait for the new navigation page to complete | 239 // Reset state and wait for the new navigation page to complete |
255 // loading/painting. | 240 // loading/painting. |
256 StartObserving(); | 241 StartObserving(); |
257 } | 242 } |
258 | 243 |
259 void OverscrollNavigationOverlay::OnWindowSlideCompleted() { | 244 void OverscrollNavigationOverlay::OnWindowSlideCompleted( |
| 245 scoped_ptr<ui::Layer> layer) { |
260 if (slide_direction_ == SLIDE_UNKNOWN) { | 246 if (slide_direction_ == SLIDE_UNKNOWN) { |
261 window_slider_.reset(); | 247 window_slider_.reset(); |
262 StopObservingIfDone(); | 248 StopObservingIfDone(); |
263 return; | 249 return; |
264 } | 250 } |
265 | 251 |
266 // Change the image used for the overlay window. | 252 // Change the image used for the overlay window. |
267 image_delegate_->SetImage(layer_delegate_->image()); | 253 image_delegate_->SetImage(layer_delegate_->image()); |
268 window_->layer()->SetTransform(gfx::Transform()); | 254 window_->layer()->SetTransform(gfx::Transform()); |
269 window_->SchedulePaintInRect(gfx::Rect(window_->bounds().size())); | 255 window_->SchedulePaintInRect(gfx::Rect(window_->bounds().size())); |
270 slide_direction_ = SLIDE_UNKNOWN; | 256 slide_direction_ = SLIDE_UNKNOWN; |
271 | 257 // We may end up dismissing the overlay before it has a chance to repaint, so |
272 // Make sure the overlay layer is repainted before we dismiss it, otherwise | 258 // set the slider layer to be the one animated by OverlayDismissAnimator. |
273 // OverlayDismissAnimator may end up showing the wrong screenshot during the | 259 if (layer.get()) |
274 // fadeout animation. | 260 overlay_dismiss_layer_ = layer.Pass(); |
275 if (received_paint_update_ && need_paint_update_) { | 261 StopObservingIfDone(); |
276 received_paint_update_ = false; | |
277 RenderWidgetHost* host = | |
278 web_contents_->GetRenderWidgetHostView()->GetRenderWidgetHost(); | |
279 RenderViewHostImpl* view_host = | |
280 static_cast<RenderViewHostImpl*> (RenderViewHost::From(host)); | |
281 view_host->ScheduleComposite(); | |
282 } else if (!need_paint_update_) { | |
283 StopObservingIfDone(); | |
284 } | |
285 } | 262 } |
286 | 263 |
287 void OverscrollNavigationOverlay::OnWindowSlideAborted() { | 264 void OverscrollNavigationOverlay::OnWindowSlideAborted() { |
288 StopObservingIfDone(); | 265 StopObservingIfDone(); |
289 } | 266 } |
290 | 267 |
291 void OverscrollNavigationOverlay::OnWindowSliderDestroyed() { | 268 void OverscrollNavigationOverlay::OnWindowSliderDestroyed() { |
292 // We only want to take an action here if WindowSlider is being destroyed | 269 // We only want to take an action here if WindowSlider is being destroyed |
293 // outside of OverscrollNavigationOverlay. If window_slider_.get() is NULL, | 270 // outside of OverscrollNavigationOverlay. If window_slider_.get() is NULL, |
294 // then OverscrollNavigationOverlay is the one destroying WindowSlider, and | 271 // then OverscrollNavigationOverlay is the one destroying WindowSlider, and |
295 // we don't need to do anything. | 272 // we don't need to do anything. |
296 // This check prevents StopObservingIfDone() being called multiple times | 273 // This check prevents StopObservingIfDone() being called multiple times |
297 // (including recursively) for a single event. | 274 // (including recursively) for a single event. |
298 if (window_slider_.get()) { | 275 if (window_slider_.get()) { |
299 // The slider has just been destroyed. Release the ownership. | 276 // The slider has just been destroyed. Release the ownership. |
300 WindowSlider* slider ALLOW_UNUSED = window_slider_.release(); | 277 WindowSlider* slider ALLOW_UNUSED = window_slider_.release(); |
301 StopObservingIfDone(); | 278 StopObservingIfDone(); |
302 } | 279 } |
303 } | 280 } |
304 | 281 |
305 void OverscrollNavigationOverlay::DocumentOnLoadCompletedInMainFrame() { | |
306 // Use the last committed entry rather than the active one, in case a | |
307 // pending entry has been created. | |
308 int committed_entry_id = | |
309 web_contents_->GetController().GetLastCommittedEntry()->GetUniqueID(); | |
310 // Consider the loading completed once the main frame has loaded. | |
311 if (committed_entry_id == pending_entry_id_ || !pending_entry_id_) { | |
312 loading_complete_ = true; | |
313 StopObservingIfDone(); | |
314 } | |
315 } | |
316 | |
317 void OverscrollNavigationOverlay::DidFirstVisuallyNonEmptyPaint() { | 282 void OverscrollNavigationOverlay::DidFirstVisuallyNonEmptyPaint() { |
318 int visible_entry_id = | 283 int visible_entry_id = |
319 web_contents_->GetController().GetVisibleEntry()->GetUniqueID(); | 284 web_contents_->GetController().GetVisibleEntry()->GetUniqueID(); |
320 if (visible_entry_id == pending_entry_id_ || !pending_entry_id_) { | 285 if (visible_entry_id == pending_entry_id_ || !pending_entry_id_) { |
321 received_paint_update_ = true; | 286 received_paint_update_ = true; |
322 StopObservingIfDone(); | 287 StopObservingIfDone(); |
323 } | 288 } |
324 } | 289 } |
325 | 290 |
326 void OverscrollNavigationOverlay::DidStopLoading(RenderViewHost* host) { | 291 void OverscrollNavigationOverlay::DidStopLoading(RenderViewHost* host) { |
327 // Use the last committed entry rather than the active one, in case a | 292 // Use the last committed entry rather than the active one, in case a |
328 // pending entry has been created. | 293 // pending entry has been created. |
329 int committed_entry_id = | 294 int committed_entry_id = |
330 web_contents_->GetController().GetLastCommittedEntry()->GetUniqueID(); | 295 web_contents_->GetController().GetLastCommittedEntry()->GetUniqueID(); |
331 if (committed_entry_id == pending_entry_id_ || !pending_entry_id_) { | 296 if (committed_entry_id == pending_entry_id_ || !pending_entry_id_) { |
332 loading_complete_ = true; | 297 loading_complete_ = true; |
333 if (!received_paint_update_ && need_paint_update_) { | |
334 // Force a repaint after the page is loaded. | |
335 RenderViewHostImpl* view = static_cast<RenderViewHostImpl*>(host); | |
336 view->ScheduleComposite(); | |
337 } | |
338 StopObservingIfDone(); | 298 StopObservingIfDone(); |
339 } | 299 } |
340 } | 300 } |
341 | 301 |
342 bool OverscrollNavigationOverlay::OnMessageReceived( | |
343 const IPC::Message& message) { | |
344 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
345 IPC_BEGIN_MESSAGE_MAP(OverscrollNavigationOverlay, message) | |
346 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect) | |
347 IPC_END_MESSAGE_MAP() | |
348 return false; | |
349 } | |
350 | |
351 } // namespace content | 302 } // namespace content |
OLD | NEW |