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