1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
content / browser / navigation_transitions / back_forward_transition_animation_manager_android.h [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_NAVIGATION_TRANSITIONS_BACK_FORWARD_TRANSITION_ANIMATION_MANAGER_ANDROID_H_
#define CONTENT_BROWSER_NAVIGATION_TRANSITIONS_BACK_FORWARD_TRANSITION_ANIMATION_MANAGER_ANDROID_H_
#include <memory>
#include "base/memory/raw_ptr.h"
#include "content/browser/navigation_transitions/back_forward_transition_animator.h"
#include "content/public/browser/back_forward_transition_animation_manager.h"
#include "ui/android/window_android.h"
namespace ui {
class BackGestureEvent;
}
namespace content {
class NavigationControllerImpl;
class NavigationRequest;
class WebContentsViewAndroid;
class RenderFrameHostImpl;
// A wrapper class that forwards the gesture event APIs to the `animator_`. It
// limits the APIs explosed to the embedder. Owned by `WebContentsViewAndroid`.
//
// If for some reason the history navigation couldn't be animated, this class
// won't create an `animator_`, and will start the history navigation via the
// `NavigationController`.
// TODO(crbug.com/40260440): We should always animate a gesture history
// navigation.
class CONTENT_EXPORT BackForwardTransitionAnimationManagerAndroid
: public BackForwardTransitionAnimationManager,
public ui::ViewAndroidObserver,
public ui::WindowAndroidObserver,
public RenderWidgetHostObserver,
public RenderFrameMetadataProvider::Observer,
public WebContentsObserver {
public:
BackForwardTransitionAnimationManagerAndroid(
WebContentsViewAndroid* web_contents_view_android,
NavigationControllerImpl* navigation_controller);
BackForwardTransitionAnimationManagerAndroid(
const BackForwardTransitionAnimationManagerAndroid&) = delete;
BackForwardTransitionAnimationManagerAndroid& operator=(
const BackForwardTransitionAnimationManagerAndroid&) = delete;
~BackForwardTransitionAnimationManagerAndroid() override;
// `NavigationTransitionAnimationManager`:
void OnGestureStarted(const ui::BackGestureEvent& gesture,
ui::BackGestureEventSwipeEdge edge,
NavigationDirection navigation_direction) override;
void OnGestureProgressed(const ui::BackGestureEvent& gesture) override;
void OnGestureCancelled() override;
void OnGestureInvoked() override;
void OnContentForNavigationEntryShown() override;
AnimationStage GetCurrentAnimationStage() override;
void SetFavicon(const SkBitmap& favicon) override;
// `ui::ViewAndroidObserver`:
void OnAttachedToWindow() override {}
void OnDetachedFromWindow() override;
// `ui::WindowAndroidObserver`:
void OnRootWindowVisibilityChanged(bool visible) override;
void OnAttachCompositor() override {}
void OnDetachCompositor() override;
void OnAnimate(base::TimeTicks frame_begin_time) override;
void OnActivityStopped() override {}
void OnActivityStarted() override {}
// `RenderWidgetHostObserver`:
void RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) override;
// `RenderFrameMetadataProvider::Observer`:
void OnRenderFrameMetadataChangedBeforeActivation(
const cc::RenderFrameMetadata& metadata) override {}
void OnRenderFrameMetadataChangedAfterActivation(
base::TimeTicks activation_time) override;
void OnRenderFrameSubmission() override {}
void OnLocalSurfaceIdChanged(
const cc::RenderFrameMetadata& metadata) override {}
// `WebContentsObserver`:
void DidStartNavigation(NavigationHandle* navigation_handle) override;
void ReadyToCommitNavigation(NavigationHandle* navigation_handle) override;
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
// This is called before the `old_host` is swapped out and before the
// `new_host` is swapped in.
//
// Note:
// 1. This API won't get called if the navigation does not commit
// (204/205/Download), or the navigation is cancelled (aborted by the user)
// or replaced (by another browser-initiated navigation). We use
// `DidFinishNavigation()` for those cases.
// 2. `old_host` might be the same as `new_host`. This can only happen for
// navigating away from a crashed frame (early-swap), or for same-RFH
// navigations.
//
// TODO(crbug.com/41487964): This also won't work for the initial
// navigation away from "about:blank". We might be able to treat this
// navigation as a same-doc one.
//
// TODO(crbug.com/40615943): Check the status of RD when it is close to
// launch. Without RD we need to make sure no frames from the old document is
// associated with the updated LocalSurfaceId (https://crbug.com/1445976).
void OnDidNavigatePrimaryMainFramePreCommit(
NavigationRequest* navigation_request,
RenderFrameHostImpl* old_host,
RenderFrameHostImpl* new_host);
// Notified when a unstarted navigation request is destroyed.
void OnNavigationCancelledBeforeStart(NavigationHandle* navigation_handle);
// `animator_` invokes this callback to notify the state changes of the
// current animation.
void OnAnimationStageChanged();
// Called upon ignoring an input event.
void MaybeRecordIgnoredInput(const blink::WebInputEvent& event);
// Called from the animator when a stable screenshot is not dismissed. This
// can happen to a very busy renderer when it couldn't submit a new frame
// after the navigation.
void OnPostNavigationFirstFrameTimeout();
void OnPhysicalBackingSizeChanged();
WebContentsViewAndroid* web_contents_view_android() const {
return web_contents_view_android_;
}
NavigationControllerImpl* navigation_controller() const {
return navigation_controller_;
}
void set_animator_factory_for_testing(
std::unique_ptr<BackForwardTransitionAnimator::Factory> factory) {
animator_factory_ = std::move(factory);
}
private:
// The browser test needs to access the test-only `animator_`.
friend class BackForwardTransitionAnimationManagerBrowserTest;
SkBitmap MaybeCopyContentAreaAsBitmapSync();
// If the animator state is terminal, this will synchronously destroy the
// animator. Terminal states are when all the animation has finished in the
// browser UI or when an unexpected navigation occurs during the animation.
void MaybeDestroyAnimator();
// Destroys the animator. Must only be called when there is a valid animator.
void DestroyAnimator();
// The owning `WebContentsViewAndroid`. Guaranteed to outlive `this`.
const raw_ptr<WebContentsViewAndroid> web_contents_view_android_;
// The navigation controller of the primary `FrameTree` of this `WebContents`.
// Its life time is bound to this `WebContents`, thus guaranteed to outlive
// this manager.
const raw_ptr<NavigationControllerImpl> navigation_controller_;
// The index of the destination entry in the history list. Set when the
// embedder notifies the animation manager upon a gesture's start. This is
// used to ensure the navigation is initiated at gesture end, even if the
// animation had to be terminated sooner.
//
// Use an index instead of an offset, in case during the animated transition
// the session history is updated (e.g., history.pushState()) and we don't
// want to lead the user to the wrong entry.
int destination_entry_index_ = -1;
// The actual implementation of the animation manager that manages the history
// navigation animation. One instance per gesture.
//
// Only instantiated if the user gesture will trigger an animated session
// history preview. Created when the eligible `OnGestureStarted()` arrives,
// and destroyed when `DestroyAnimator()` is called (either when
// the animations finished or animations have to aborted).
//
// `animator_` is only instantiated via `animator_factory_`. Tests can
// override the `animator_factory_` via `set_animator_factory_for_testing()`.
std::unique_ptr<BackForwardTransitionAnimator> animator_;
std::unique_ptr<BackForwardTransitionAnimator::Factory> animator_factory_;
};
} // namespace content
#endif // CONTENT_BROWSER_NAVIGATION_TRANSITIONS_BACK_FORWARD_TRANSITION_ANIMATION_MANAGER_ANDROID_H_