1 // Copyright 2013 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 "cc/input/browser_controls_offset_manager.h"
6 
7 #include <algorithm>
8 #include <cmath>
9 #include <limits>
10 #include <memory>
11 
12 #include "base/time/time.h"
13 #include "cc/input/browser_controls_offset_manager_client.h"
14 #include "cc/layers/layer_impl.h"
15 #include "cc/test/fake_impl_task_runner_provider.h"
16 #include "cc/test/fake_layer_tree_host_impl.h"
17 #include "cc/test/test_task_graph_runner.h"
18 #include "cc/trees/layer_tree_impl.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "ui/gfx/geometry/vector2d_f.h"
21 
22 namespace cc {
23 namespace {
24 
25 class MockBrowserControlsOffsetManagerClient
26     : public BrowserControlsOffsetManagerClient {
27  public:
MockBrowserControlsOffsetManagerClient(float top_controls_height,float browser_controls_show_threshold,float browser_controls_hide_threshold)28   MockBrowserControlsOffsetManagerClient(float top_controls_height,
29                                          float browser_controls_show_threshold,
30                                          float browser_controls_hide_threshold)
31       : host_impl_(&task_runner_provider_, &task_graph_runner_),
32         redraw_needed_(false),
33         update_draw_properties_needed_(false),
34         browser_controls_params_(
35             {top_controls_height, 0, 0, 0, false, false, false}),
36         bottom_controls_shown_ratio_(1.f),
37         top_controls_shown_ratio_(1.f),
38         browser_controls_show_threshold_(browser_controls_show_threshold),
39         browser_controls_hide_threshold_(browser_controls_hide_threshold) {
40     active_tree_ = std::make_unique<LayerTreeImpl>(
41         &host_impl_, new SyncedProperty<ScaleGroup>, new SyncedBrowserControls,
42         new SyncedBrowserControls, new SyncedElasticOverscroll);
43     root_scroll_layer_ = LayerImpl::Create(active_tree_.get(), 1);
44   }
45 
46   ~MockBrowserControlsOffsetManagerClient() override = default;
47 
DidChangeBrowserControlsPosition()48   void DidChangeBrowserControlsPosition() override {
49     redraw_needed_ = true;
50     update_draw_properties_needed_ = true;
51   }
52 
HaveRootScrollNode() const53   bool HaveRootScrollNode() const override { return true; }
54 
BottomControlsHeight() const55   float BottomControlsHeight() const override {
56     return browser_controls_params_.bottom_controls_height;
57   }
58 
BottomControlsMinHeight() const59   float BottomControlsMinHeight() const override {
60     return browser_controls_params_.bottom_controls_min_height;
61   }
62 
TopControlsHeight() const63   float TopControlsHeight() const override {
64     return browser_controls_params_.top_controls_height;
65   }
66 
TopControlsMinHeight() const67   float TopControlsMinHeight() const override {
68     return browser_controls_params_.top_controls_min_height;
69   }
70 
OnlyExpandTopControlsAtPageTop() const71   bool OnlyExpandTopControlsAtPageTop() const override {
72     return browser_controls_params_.only_expand_top_controls_at_page_top;
73   }
74 
ViewportScrollOffset() const75   gfx::ScrollOffset ViewportScrollOffset() const override {
76     return viewport_scroll_offset_;
77   }
78 
SetCurrentBrowserControlsShownRatio(float top_ratio,float bottom_ratio)79   void SetCurrentBrowserControlsShownRatio(float top_ratio,
80                                            float bottom_ratio) override {
81     AssertAndClamp(&top_ratio);
82     top_controls_shown_ratio_ = top_ratio;
83 
84     AssertAndClamp(&bottom_ratio);
85     bottom_controls_shown_ratio_ = bottom_ratio;
86   }
87 
AssertAndClamp(float * ratio)88   void AssertAndClamp(float* ratio) {
89     ASSERT_FALSE(std::isnan(*ratio));
90     ASSERT_FALSE(*ratio == std::numeric_limits<float>::infinity());
91     ASSERT_FALSE(*ratio == -std::numeric_limits<float>::infinity());
92     *ratio = std::max(*ratio, 0.f);
93   }
94 
CurrentBottomControlsShownRatio() const95   float CurrentBottomControlsShownRatio() const override {
96     return bottom_controls_shown_ratio_;
97   }
98 
CurrentTopControlsShownRatio() const99   float CurrentTopControlsShownRatio() const override {
100     return top_controls_shown_ratio_;
101   }
102 
SetNeedsCommit()103   void SetNeedsCommit() override {}
104 
rootScrollLayer()105   LayerImpl* rootScrollLayer() { return root_scroll_layer_.get(); }
106 
manager()107   BrowserControlsOffsetManager* manager() {
108     if (!manager_) {
109       manager_ = BrowserControlsOffsetManager::Create(
110           this, browser_controls_show_threshold_,
111           browser_controls_hide_threshold_);
112     }
113     return manager_.get();
114   }
115 
SetBrowserControlsParams(BrowserControlsParams params)116   void SetBrowserControlsParams(BrowserControlsParams params) {
117     browser_controls_params_ = params;
118 
119     manager()->OnBrowserControlsParamsChanged(
120         params.animate_browser_controls_height_changes);
121   }
122 
SetViewportScrollOffset(float x,float y)123   void SetViewportScrollOffset(float x, float y) {
124     viewport_scroll_offset_ = gfx::ScrollOffset(x, y);
125   }
126 
ScrollVerticallyBy(float dy)127   void ScrollVerticallyBy(float dy) {
128     gfx::Vector2dF viewport_scroll_delta = manager()->ScrollBy({0.f, dy});
129     viewport_scroll_offset_.Add(gfx::ScrollOffset(viewport_scroll_delta));
130   }
131 
132  private:
133   FakeImplTaskRunnerProvider task_runner_provider_;
134   TestTaskGraphRunner task_graph_runner_;
135   FakeLayerTreeHostImpl host_impl_;
136   std::unique_ptr<LayerTreeImpl> active_tree_;
137   std::unique_ptr<LayerImpl> root_scroll_layer_;
138   std::unique_ptr<BrowserControlsOffsetManager> manager_;
139   bool redraw_needed_;
140   bool update_draw_properties_needed_;
141 
142   BrowserControlsParams browser_controls_params_;
143   float bottom_controls_shown_ratio_;
144   float top_controls_shown_ratio_;
145   float browser_controls_show_threshold_;
146   float browser_controls_hide_threshold_;
147   gfx::ScrollOffset viewport_scroll_offset_;
148 };
149 
TEST(BrowserControlsOffsetManagerTest,EnsureScrollThresholdApplied)150 TEST(BrowserControlsOffsetManagerTest, EnsureScrollThresholdApplied) {
151   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
152   BrowserControlsOffsetManager* manager = client.manager();
153 
154   manager->ScrollBegin();
155 
156   // Scroll down to hide the controls entirely.
157   manager->ScrollBy(gfx::Vector2dF(0.f, 30.f));
158   EXPECT_FLOAT_EQ(-30.f, manager->ControlsTopOffset());
159 
160   manager->ScrollBy(gfx::Vector2dF(0.f, 30.f));
161   EXPECT_FLOAT_EQ(-60.f, manager->ControlsTopOffset());
162 
163   manager->ScrollBy(gfx::Vector2dF(0.f, 100.f));
164   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
165 
166   // Scroll back up a bit and ensure the controls don't move until we cross
167   // the threshold.
168   manager->ScrollBy(gfx::Vector2dF(0.f, -10.f));
169   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
170 
171   manager->ScrollBy(gfx::Vector2dF(0.f, -50.f));
172   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
173 
174   // After hitting the threshold, further scrolling up should result in the top
175   // controls showing.
176   manager->ScrollBy(gfx::Vector2dF(0.f, -10.f));
177   EXPECT_FLOAT_EQ(-90.f, manager->ControlsTopOffset());
178 
179   manager->ScrollBy(gfx::Vector2dF(0.f, -50.f));
180   EXPECT_FLOAT_EQ(-40.f, manager->ControlsTopOffset());
181 
182   // Reset the scroll threshold by going further up the page than the initial
183   // threshold.
184   manager->ScrollBy(gfx::Vector2dF(0.f, -100.f));
185   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
186 
187   // See that scrolling down the page now will result in the controls hiding.
188   manager->ScrollBy(gfx::Vector2dF(0.f, 20.f));
189   EXPECT_FLOAT_EQ(-20.f, manager->ControlsTopOffset());
190 
191   manager->ScrollEnd();
192 }
193 
TEST(BrowserControlsOffsetManagerTest,EnsureScrollThresholdAppliedWithMinHeight)194 TEST(BrowserControlsOffsetManagerTest,
195      EnsureScrollThresholdAppliedWithMinHeight) {
196   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
197   BrowserControlsOffsetManager* manager = client.manager();
198 
199   // First, set the min-height.
200   client.SetBrowserControlsParams({100.f, 20.f, 0.f, 0.f, false, false});
201 
202   manager->ScrollBegin();
203 
204   // Scroll down to hide the controls.
205   manager->ScrollBy(gfx::Vector2dF(0.f, 30.f));
206   EXPECT_FLOAT_EQ(-30.f, manager->ControlsTopOffset());
207 
208   manager->ScrollBy(gfx::Vector2dF(0.f, 30.f));
209   EXPECT_FLOAT_EQ(-60.f, manager->ControlsTopOffset());
210 
211   // Controls should stop scrolling when we hit the min-height.
212   manager->ScrollBy(gfx::Vector2dF(0.f, 100.f));
213   EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset());
214 
215   // Scroll back up a bit and ensure the controls don't move until we cross
216   // the threshold.
217   manager->ScrollBy(gfx::Vector2dF(0.f, -20.f));
218   EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset());
219 
220   manager->ScrollBy(gfx::Vector2dF(0.f, -60.f));
221   EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset());
222 
223   // After hitting the threshold, further scrolling up should result in the top
224   // controls starting to move.
225   manager->ScrollBy(gfx::Vector2dF(0.f, -10.f));
226   EXPECT_FLOAT_EQ(-70.f, manager->ControlsTopOffset());
227 
228   manager->ScrollBy(gfx::Vector2dF(0.f, -50.f));
229   EXPECT_FLOAT_EQ(-20.f, manager->ControlsTopOffset());
230 
231   // Reset the scroll threshold by going further up the page than the initial
232   // threshold.
233   manager->ScrollBy(gfx::Vector2dF(0.f, -100.f));
234   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
235 
236   // See that scrolling down the page now will result in the controls hiding.
237   manager->ScrollBy(gfx::Vector2dF(0.f, 20.f));
238   EXPECT_FLOAT_EQ(-20.f, manager->ControlsTopOffset());
239 
240   manager->ScrollEnd();
241 }
242 
TEST(BrowserControlsOffsetManagerTest,PartialShownHideAnimation)243 TEST(BrowserControlsOffsetManagerTest, PartialShownHideAnimation) {
244   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
245   BrowserControlsOffsetManager* manager = client.manager();
246   manager->ScrollBegin();
247   manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
248   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
249   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
250   manager->ScrollEnd();
251 
252   manager->ScrollBegin();
253   manager->ScrollBy(gfx::Vector2dF(0.f, -15.f));
254   EXPECT_FLOAT_EQ(-85.f, manager->ControlsTopOffset());
255   EXPECT_FLOAT_EQ(15.f, manager->ContentTopOffset());
256   manager->ScrollEnd();
257 
258   EXPECT_TRUE(manager->HasAnimation());
259 
260   base::TimeTicks time = base::TimeTicks::Now();
261 
262   // First animate will establish the animaion.
263   float previous = manager->TopControlsShownRatio();
264   manager->Animate(time);
265   EXPECT_EQ(manager->TopControlsShownRatio(), previous);
266 
267   while (manager->HasAnimation()) {
268     previous = manager->TopControlsShownRatio();
269     time = base::TimeDelta::FromMicroseconds(100) + time;
270     manager->Animate(time);
271     EXPECT_LT(manager->TopControlsShownRatio(), previous);
272   }
273   EXPECT_FALSE(manager->HasAnimation());
274   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
275   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
276 }
277 
TEST(BrowserControlsOffsetManagerTest,BottomControlsPartialShownHideAnimation)278 TEST(BrowserControlsOffsetManagerTest,
279      BottomControlsPartialShownHideAnimation) {
280   MockBrowserControlsOffsetManagerClient client(0.f, 0.5f, 0.5f);
281   client.SetBrowserControlsParams({0, 0, 100, 0, false, false});
282   BrowserControlsOffsetManager* manager = client.manager();
283   manager->ScrollBegin();
284   manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
285   EXPECT_FLOAT_EQ(0.f, manager->BottomControlsShownRatio());
286   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
287   manager->ScrollEnd();
288 
289   manager->ScrollBegin();
290   manager->ScrollBy(gfx::Vector2dF(0.f, -20.f));
291   EXPECT_FLOAT_EQ(0.2f, manager->BottomControlsShownRatio());
292   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
293   manager->ScrollEnd();
294 
295   EXPECT_TRUE(manager->HasAnimation());
296 
297   base::TimeTicks time = base::TimeTicks::Now();
298 
299   // First animate will establish the animaion.
300   float previous = manager->TopControlsShownRatio();
301   manager->Animate(time);
302   EXPECT_EQ(manager->TopControlsShownRatio(), previous);
303 
304   while (manager->HasAnimation()) {
305     previous = manager->BottomControlsShownRatio();
306     time = base::TimeDelta::FromMicroseconds(100) + time;
307     manager->Animate(time);
308     EXPECT_LT(manager->BottomControlsShownRatio(), previous);
309   }
310   EXPECT_FALSE(manager->HasAnimation());
311   EXPECT_FLOAT_EQ(0.f, manager->BottomControlsShownRatio());
312   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
313 }
314 
TEST(BrowserControlsOffsetManagerTest,PartialShownShowAnimation)315 TEST(BrowserControlsOffsetManagerTest, PartialShownShowAnimation) {
316   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
317   BrowserControlsOffsetManager* manager = client.manager();
318   manager->ScrollBegin();
319   manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
320   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
321   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
322   manager->ScrollEnd();
323 
324   manager->ScrollBegin();
325   manager->ScrollBy(gfx::Vector2dF(0.f, -70.f));
326   EXPECT_FLOAT_EQ(-30.f, manager->ControlsTopOffset());
327   EXPECT_FLOAT_EQ(70.f, manager->ContentTopOffset());
328   manager->ScrollEnd();
329 
330   EXPECT_TRUE(manager->HasAnimation());
331 
332   base::TimeTicks time = base::TimeTicks::Now();
333 
334   // First animate will establish the animaion.
335   float previous = manager->TopControlsShownRatio();
336   manager->Animate(time);
337   EXPECT_EQ(manager->TopControlsShownRatio(), previous);
338 
339   while (manager->HasAnimation()) {
340     previous = manager->TopControlsShownRatio();
341     time = base::TimeDelta::FromMicroseconds(100) + time;
342     manager->Animate(time);
343     EXPECT_GT(manager->TopControlsShownRatio(), previous);
344   }
345   EXPECT_FALSE(manager->HasAnimation());
346   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
347   EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset());
348 }
349 
TEST(BrowserControlsOffsetManagerTest,BottomControlsPartialShownShowAnimation)350 TEST(BrowserControlsOffsetManagerTest,
351      BottomControlsPartialShownShowAnimation) {
352   MockBrowserControlsOffsetManagerClient client(0.f, 0.5f, 0.5f);
353   client.SetBrowserControlsParams({0, 0, 100, 0, false, false});
354   BrowserControlsOffsetManager* manager = client.manager();
355 
356   manager->ScrollBegin();
357   manager->ScrollBy(gfx::Vector2dF(0.f, 20.f));
358   EXPECT_FLOAT_EQ(0.8f, manager->BottomControlsShownRatio());
359   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
360   manager->ScrollEnd();
361 
362   EXPECT_TRUE(manager->HasAnimation());
363 
364   base::TimeTicks time = base::TimeTicks::Now();
365 
366   // First animate will establish the animaion.
367   float previous = manager->TopControlsShownRatio();
368   manager->Animate(time);
369   EXPECT_EQ(manager->TopControlsShownRatio(), previous);
370 
371   while (manager->HasAnimation()) {
372     previous = manager->BottomControlsShownRatio();
373     time = base::TimeDelta::FromMicroseconds(100) + time;
374     manager->Animate(time);
375     EXPECT_GT(manager->BottomControlsShownRatio(), previous);
376   }
377   EXPECT_FALSE(manager->HasAnimation());
378   EXPECT_FLOAT_EQ(1.f, manager->BottomControlsShownRatio());
379   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
380 }
381 
TEST(BrowserControlsOffsetManagerTest,PartialHiddenWithAmbiguousThresholdShows)382 TEST(BrowserControlsOffsetManagerTest,
383      PartialHiddenWithAmbiguousThresholdShows) {
384   MockBrowserControlsOffsetManagerClient client(100.f, 0.25f, 0.25f);
385   BrowserControlsOffsetManager* manager = client.manager();
386 
387   manager->ScrollBegin();
388 
389   manager->ScrollBy(gfx::Vector2dF(0.f, 20.f));
390   EXPECT_FLOAT_EQ(-20.f, manager->ControlsTopOffset());
391   EXPECT_FLOAT_EQ(80.f, manager->ContentTopOffset());
392 
393   manager->ScrollEnd();
394   EXPECT_TRUE(manager->HasAnimation());
395 
396   base::TimeTicks time = base::TimeTicks::Now();
397 
398   // First animate will establish the animaion.
399   float previous = manager->TopControlsShownRatio();
400   manager->Animate(time);
401   EXPECT_EQ(manager->TopControlsShownRatio(), previous);
402 
403   while (manager->HasAnimation()) {
404     previous = manager->TopControlsShownRatio();
405     time = base::TimeDelta::FromMicroseconds(100) + time;
406     manager->Animate(time);
407     EXPECT_GT(manager->TopControlsShownRatio(), previous);
408   }
409   EXPECT_FALSE(manager->HasAnimation());
410   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
411   EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset());
412 }
413 
TEST(BrowserControlsOffsetManagerTest,PartialHiddenWithAmbiguousThresholdHides)414 TEST(BrowserControlsOffsetManagerTest,
415      PartialHiddenWithAmbiguousThresholdHides) {
416   MockBrowserControlsOffsetManagerClient client(100.f, 0.25f, 0.25f);
417   BrowserControlsOffsetManager* manager = client.manager();
418 
419   manager->ScrollBegin();
420 
421   manager->ScrollBy(gfx::Vector2dF(0.f, 30.f));
422   EXPECT_FLOAT_EQ(-30.f, manager->ControlsTopOffset());
423   EXPECT_FLOAT_EQ(70.f, manager->ContentTopOffset());
424 
425   manager->ScrollEnd();
426   EXPECT_TRUE(manager->HasAnimation());
427 
428   base::TimeTicks time = base::TimeTicks::Now();
429 
430   // First animate will establish the animaion.
431   float previous = manager->TopControlsShownRatio();
432   manager->Animate(time);
433   EXPECT_EQ(manager->TopControlsShownRatio(), previous);
434 
435   while (manager->HasAnimation()) {
436     previous = manager->TopControlsShownRatio();
437     time = base::TimeDelta::FromMicroseconds(100) + time;
438     manager->Animate(time);
439     EXPECT_LT(manager->TopControlsShownRatio(), previous);
440   }
441   EXPECT_FALSE(manager->HasAnimation());
442   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
443   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
444 }
445 
TEST(BrowserControlsOffsetManagerTest,PartialShownWithAmbiguousThresholdHides)446 TEST(BrowserControlsOffsetManagerTest,
447      PartialShownWithAmbiguousThresholdHides) {
448   MockBrowserControlsOffsetManagerClient client(100.f, 0.25f, 0.25f);
449   BrowserControlsOffsetManager* manager = client.manager();
450 
451   manager->ScrollBy(gfx::Vector2dF(0.f, 200.f));
452   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
453   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
454 
455   manager->ScrollBegin();
456 
457   manager->ScrollBy(gfx::Vector2dF(0.f, -20.f));
458   EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset());
459   EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
460 
461   manager->ScrollEnd();
462   EXPECT_TRUE(manager->HasAnimation());
463 
464   base::TimeTicks time = base::TimeTicks::Now();
465 
466   // First animate will establish the animaion.
467   float previous = manager->TopControlsShownRatio();
468   manager->Animate(time);
469   EXPECT_EQ(manager->TopControlsShownRatio(), previous);
470 
471   while (manager->HasAnimation()) {
472     previous = manager->TopControlsShownRatio();
473     time = base::TimeDelta::FromMicroseconds(100) + time;
474     manager->Animate(time);
475     EXPECT_LT(manager->TopControlsShownRatio(), previous);
476   }
477   EXPECT_FALSE(manager->HasAnimation());
478   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
479   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
480 }
481 
TEST(BrowserControlsOffsetManagerTest,PartialShownWithAmbiguousThresholdShows)482 TEST(BrowserControlsOffsetManagerTest,
483      PartialShownWithAmbiguousThresholdShows) {
484   MockBrowserControlsOffsetManagerClient client(100.f, 0.25f, 0.25f);
485   BrowserControlsOffsetManager* manager = client.manager();
486 
487   manager->ScrollBy(gfx::Vector2dF(0.f, 200.f));
488   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
489   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
490 
491   manager->ScrollBegin();
492 
493   manager->ScrollBy(gfx::Vector2dF(0.f, -30.f));
494   EXPECT_FLOAT_EQ(-70.f, manager->ControlsTopOffset());
495   EXPECT_FLOAT_EQ(30.f, manager->ContentTopOffset());
496 
497   manager->ScrollEnd();
498   EXPECT_TRUE(manager->HasAnimation());
499 
500   base::TimeTicks time = base::TimeTicks::Now();
501 
502   // First animate will establish the animaion.
503   float previous = manager->TopControlsShownRatio();
504   manager->Animate(time);
505   EXPECT_EQ(manager->TopControlsShownRatio(), previous);
506 
507   while (manager->HasAnimation()) {
508     previous = manager->TopControlsShownRatio();
509     time = base::TimeDelta::FromMicroseconds(100) + time;
510     manager->Animate(time);
511     EXPECT_GT(manager->TopControlsShownRatio(), previous);
512   }
513   EXPECT_FALSE(manager->HasAnimation());
514   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
515   EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset());
516 }
517 
TEST(BrowserControlsOffsetManagerTest,PinchIgnoresScroll)518 TEST(BrowserControlsOffsetManagerTest, PinchIgnoresScroll) {
519   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
520   BrowserControlsOffsetManager* manager = client.manager();
521 
522   // Hide the controls.
523   manager->ScrollBegin();
524   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
525 
526   manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
527   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
528 
529   manager->PinchBegin();
530   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
531 
532   // Scrolls are ignored during pinch.
533   manager->ScrollBy(gfx::Vector2dF(0.f, -15.f));
534   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
535   manager->PinchEnd();
536   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
537 
538   // Scrolls should no long be ignored.
539   manager->ScrollBy(gfx::Vector2dF(0.f, -15.f));
540   EXPECT_FLOAT_EQ(-85.f, manager->ControlsTopOffset());
541   EXPECT_FLOAT_EQ(15.f, manager->ContentTopOffset());
542   manager->ScrollEnd();
543 
544   EXPECT_TRUE(manager->HasAnimation());
545 }
546 
TEST(BrowserControlsOffsetManagerTest,PinchBeginStartsAnimationIfNecessary)547 TEST(BrowserControlsOffsetManagerTest, PinchBeginStartsAnimationIfNecessary) {
548   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
549   BrowserControlsOffsetManager* manager = client.manager();
550 
551   manager->ScrollBegin();
552   manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
553   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
554 
555   manager->PinchBegin();
556   EXPECT_FALSE(manager->HasAnimation());
557 
558   manager->PinchEnd();
559   EXPECT_FALSE(manager->HasAnimation());
560 
561   manager->ScrollBy(gfx::Vector2dF(0.f, -15.f));
562   EXPECT_FLOAT_EQ(-85.f, manager->ControlsTopOffset());
563   EXPECT_FLOAT_EQ(15.f, manager->ContentTopOffset());
564 
565   manager->PinchBegin();
566   EXPECT_TRUE(manager->HasAnimation());
567 
568   base::TimeTicks time = base::TimeTicks::Now();
569 
570   // First animate will establish the animaion.
571   float previous = manager->TopControlsShownRatio();
572   manager->Animate(time);
573   EXPECT_EQ(manager->TopControlsShownRatio(), previous);
574 
575   while (manager->HasAnimation()) {
576     previous = manager->TopControlsShownRatio();
577     time = base::TimeDelta::FromMicroseconds(100) + time;
578     manager->Animate(time);
579     EXPECT_LT(manager->TopControlsShownRatio(), previous);
580   }
581   EXPECT_FALSE(manager->HasAnimation());
582 
583   manager->PinchEnd();
584   EXPECT_FALSE(manager->HasAnimation());
585 
586   manager->ScrollBy(gfx::Vector2dF(0.f, -55.f));
587   EXPECT_FLOAT_EQ(-45.f, manager->ControlsTopOffset());
588   EXPECT_FLOAT_EQ(55.f, manager->ContentTopOffset());
589   EXPECT_FALSE(manager->HasAnimation());
590 
591   manager->ScrollEnd();
592   EXPECT_TRUE(manager->HasAnimation());
593 
594   time = base::TimeTicks::Now();
595 
596   // First animate will establish the animaion.
597   previous = manager->TopControlsShownRatio();
598   manager->Animate(time);
599   EXPECT_EQ(manager->TopControlsShownRatio(), previous);
600 
601   while (manager->HasAnimation()) {
602     previous = manager->TopControlsShownRatio();
603     time = base::TimeDelta::FromMicroseconds(100) + time;
604     manager->Animate(time);
605     EXPECT_GT(manager->TopControlsShownRatio(), previous);
606   }
607   EXPECT_FALSE(manager->HasAnimation());
608   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
609 }
610 
TEST(BrowserControlsOffsetManagerTest,HeightIncreaseWhenFullyShownAnimation)611 TEST(BrowserControlsOffsetManagerTest, HeightIncreaseWhenFullyShownAnimation) {
612   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
613   BrowserControlsOffsetManager* manager = client.manager();
614 
615   // Set the new height with animation.
616   client.SetBrowserControlsParams({150, 0, 0, 0, true, false});
617   EXPECT_TRUE(manager->HasAnimation());
618   EXPECT_FLOAT_EQ(150.f, manager->TopControlsHeight());
619   // Ratio should've been updated to avoid jumping to the new height.
620   EXPECT_FLOAT_EQ(100.f / 150.f, manager->TopControlsShownRatio());
621   // Min-height offset should stay 0 since only the height changed.
622   EXPECT_FLOAT_EQ(0.f, manager->TopControlsMinHeightOffset());
623 
624   base::TimeTicks time = base::TimeTicks::Now();
625 
626   // First animate will establish the animaion.
627   float previous = manager->TopControlsShownRatio();
628   manager->Animate(time);
629   EXPECT_EQ(manager->TopControlsShownRatio(), previous);
630 
631   while (manager->HasAnimation()) {
632     previous = manager->TopControlsShownRatio();
633     time = base::TimeDelta::FromMicroseconds(100) + time;
634     manager->Animate(time);
635     EXPECT_GT(manager->TopControlsShownRatio(), previous);
636   }
637   EXPECT_FALSE(manager->HasAnimation());
638   // Controls should be fully shown when the animation ends.
639   EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
640   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
641   EXPECT_FLOAT_EQ(150.f, manager->ContentTopOffset());
642   // Min-height offset should still be 0.
643   EXPECT_FLOAT_EQ(0.f, manager->TopControlsMinHeightOffset());
644 }
645 
TEST(BrowserControlsOffsetManagerTest,HeightDecreaseWhenFullyShownAnimation)646 TEST(BrowserControlsOffsetManagerTest, HeightDecreaseWhenFullyShownAnimation) {
647   MockBrowserControlsOffsetManagerClient client(150.f, 0.5f, 0.5f);
648   BrowserControlsOffsetManager* manager = client.manager();
649 
650   // Set the new height with animation.
651   client.SetBrowserControlsParams({100, 0, 0, 0, true, false});
652   EXPECT_TRUE(manager->HasAnimation());
653   EXPECT_FLOAT_EQ(100.f, manager->TopControlsHeight());
654   // Ratio should've been updated to avoid jumping to the new height.
655   // The ratio will be > 1 here.
656   EXPECT_FLOAT_EQ(150.f / 100.f, manager->TopControlsShownRatio());
657 
658   base::TimeTicks time = base::TimeTicks::Now();
659 
660   // First animate will establish the animaion.
661   float previous = manager->TopControlsShownRatio();
662   manager->Animate(time);
663   EXPECT_EQ(manager->TopControlsShownRatio(), previous);
664 
665   while (manager->HasAnimation()) {
666     previous = manager->TopControlsShownRatio();
667     time = base::TimeDelta::FromMicroseconds(100) + time;
668     manager->Animate(time);
669     EXPECT_LT(manager->TopControlsShownRatio(), previous);
670   }
671   EXPECT_FALSE(manager->HasAnimation());
672   // Controls should be fully shown when the animation ends.
673   EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
674   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
675   EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset());
676 }
677 
TEST(BrowserControlsOffsetManagerTest,MinHeightIncreaseWhenHiddenAnimation)678 TEST(BrowserControlsOffsetManagerTest, MinHeightIncreaseWhenHiddenAnimation) {
679   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
680   BrowserControlsOffsetManager* manager = client.manager();
681 
682   // Scroll to hide.
683   manager->ScrollBegin();
684   manager->ScrollBy(gfx::Vector2dF(0.f, 100.f));
685   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
686   manager->ScrollEnd();
687 
688   // Set the new min-height with animation.
689   client.SetBrowserControlsParams({100, 20, 0, 0, true, false});
690   EXPECT_TRUE(manager->HasAnimation());
691   EXPECT_FLOAT_EQ(20.f, manager->TopControlsMinHeight());
692   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
693   EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
694   EXPECT_FLOAT_EQ(0.f, manager->TopControlsMinHeightOffset());
695 
696   base::TimeTicks time = base::TimeTicks::Now();
697 
698   // First animate will establish the animation.
699   float previous_ratio = manager->TopControlsShownRatio();
700   float previous_min_height_offset = manager->TopControlsMinHeightOffset();
701   manager->Animate(time);
702   EXPECT_EQ(manager->TopControlsShownRatio(), previous_ratio);
703   EXPECT_EQ(manager->TopControlsMinHeightOffset(), previous_min_height_offset);
704 
705   while (manager->HasAnimation()) {
706     previous_ratio = manager->TopControlsShownRatio();
707     previous_min_height_offset = manager->TopControlsMinHeightOffset();
708     time = base::TimeDelta::FromMicroseconds(100) + time;
709     manager->Animate(time);
710     EXPECT_GT(manager->TopControlsShownRatio(), previous_ratio);
711     // Min-height offset is also animated.
712     EXPECT_GT(manager->TopControlsMinHeightOffset(),
713               previous_min_height_offset);
714   }
715   EXPECT_FALSE(manager->HasAnimation());
716   // Controls should be at the new min-height when the animation ends.
717   EXPECT_FLOAT_EQ(20.f / 100.f, manager->TopControlsShownRatio());
718   EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
719   // Min-height offset should be equal to the min-height at the end.
720   EXPECT_FLOAT_EQ(20.f, manager->TopControlsMinHeightOffset());
721 }
722 
TEST(BrowserControlsOffsetManagerTest,MinHeightSetToZeroWhenAtMinHeightAnimation)723 TEST(BrowserControlsOffsetManagerTest,
724      MinHeightSetToZeroWhenAtMinHeightAnimation) {
725   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
726   BrowserControlsOffsetManager* manager = client.manager();
727 
728   // Set the min-height.
729   client.SetBrowserControlsParams({100, 20, 0, 0, true, false});
730 
731   // Scroll to min-height.
732   manager->ScrollBegin();
733   manager->ScrollBy(gfx::Vector2dF(0.f, 80.f));
734   EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
735   manager->ScrollEnd();
736 
737   // Set the new min-height with animation.
738   client.SetBrowserControlsParams({100, 0, 0, 0, true, false});
739   EXPECT_TRUE(manager->HasAnimation());
740   EXPECT_FLOAT_EQ(0.f, manager->TopControlsMinHeight());
741   // The controls should still be at the min-height.
742   EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
743   // Min-height offset is equal to min-height.
744   EXPECT_FLOAT_EQ(20.f, manager->TopControlsMinHeightOffset());
745 
746   base::TimeTicks time = base::TimeTicks::Now();
747 
748   // First animate will establish the animaion.
749   float previous_ratio = manager->TopControlsShownRatio();
750   float previous_min_height_offset = manager->TopControlsMinHeightOffset();
751   manager->Animate(time);
752   EXPECT_EQ(manager->TopControlsShownRatio(), previous_ratio);
753 
754   while (manager->HasAnimation()) {
755     previous_ratio = manager->TopControlsShownRatio();
756     previous_min_height_offset = manager->TopControlsMinHeightOffset();
757     time = base::TimeDelta::FromMicroseconds(100) + time;
758     manager->Animate(time);
759     EXPECT_LT(manager->TopControlsShownRatio(), previous_ratio);
760     // Min-height offset is also animated.
761     EXPECT_LT(manager->TopControlsMinHeightOffset(),
762               previous_min_height_offset);
763   }
764   EXPECT_FALSE(manager->HasAnimation());
765   // Controls should be hidden when the animation ends.
766   EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
767   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
768   // Min-height offset will be equal to the new min-height.
769   EXPECT_FLOAT_EQ(0.f, manager->TopControlsMinHeightOffset());
770 }
771 
TEST(BrowserControlsOffsetManagerTest,EnsureNoAnimationCases)772 TEST(BrowserControlsOffsetManagerTest, EnsureNoAnimationCases) {
773   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
774   BrowserControlsOffsetManager* manager = client.manager();
775 
776   // No animation should run if only the min-height changes when the controls
777   // are fully shown.
778   client.SetBrowserControlsParams({100, 20, 0, 0, true, false});
779   EXPECT_FALSE(manager->HasAnimation());
780 
781   // Scroll to min-height.
782   manager->ScrollBegin();
783   manager->ScrollBy(gfx::Vector2dF(0.f, 80.f));
784   EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
785   manager->ScrollEnd();
786 
787   // No animation should run if only the height changes when the controls
788   // are at min-height.
789   client.SetBrowserControlsParams({150, 20, 0, 0, true, false});
790   EXPECT_FALSE(manager->HasAnimation());
791 
792   // Set the min-height to 0 without animation.
793   client.SetBrowserControlsParams({150, 0, 0, 0, false, false});
794   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
795 
796   // No animation should run if only the height changes when the controls are
797   // fully hidden.
798   client.SetBrowserControlsParams({100, 0, 0, 0, true, false});
799   EXPECT_FALSE(manager->HasAnimation());
800 }
801 
TEST(BrowserControlsOffsetManagerTest,HeightChangeAnimationJumpsToEndOnScroll)802 TEST(BrowserControlsOffsetManagerTest,
803      HeightChangeAnimationJumpsToEndOnScroll) {
804   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
805   BrowserControlsOffsetManager* manager = client.manager();
806 
807   EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset());
808 
809   // Change the params to start an animation.
810   client.SetBrowserControlsParams({150, 30, 0, 0, true, false});
811   EXPECT_TRUE(manager->HasAnimation());
812 
813   base::TimeTicks time = base::TimeTicks::Now();
814   // First animate will establish the animation.
815   float previous = manager->TopControlsShownRatio();
816   manager->Animate(time);
817   // Forward a little bit.
818   time = base::TimeDelta::FromMicroseconds(100) + time;
819   manager->Animate(time);
820 
821   // Animation should be in progress.
822   EXPECT_GT(manager->TopControlsShownRatio(), previous);
823 
824   manager->ScrollBegin();
825   // Scroll should cause the animation to jump to the end.
826   EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
827   EXPECT_FLOAT_EQ(150.f, manager->ContentTopOffset());
828   // Min-height offset should jump to the new min-height.
829   EXPECT_FLOAT_EQ(30.f, manager->TopControlsMinHeightOffset());
830   EXPECT_FALSE(manager->HasAnimation());
831   // Then, the scroll will move the controls as it would normally.
832   manager->ScrollBy(gfx::Vector2dF(0.f, 60.f));
833   EXPECT_FALSE(manager->HasAnimation());
834   EXPECT_FLOAT_EQ(90.f, manager->ContentTopOffset());
835   // Min-height offset won't change once the animation is complete.
836   EXPECT_FLOAT_EQ(30.f, manager->TopControlsMinHeightOffset());
837   manager->ScrollEnd();
838 }
839 
TEST(BrowserControlsOffsetManagerTest,HeightChangeMaintainsFullyVisibleControls)840 TEST(BrowserControlsOffsetManagerTest,
841      HeightChangeMaintainsFullyVisibleControls) {
842   MockBrowserControlsOffsetManagerClient client(0.f, 0.5f, 0.5f);
843   BrowserControlsOffsetManager* manager = client.manager();
844 
845   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
846 
847   client.SetBrowserControlsParams({100, 0, 0, 0, false, false});
848   EXPECT_FALSE(manager->HasAnimation());
849   EXPECT_FLOAT_EQ(100.f, manager->TopControlsHeight());
850   EXPECT_FLOAT_EQ(0, manager->ControlsTopOffset());
851 
852   client.SetBrowserControlsParams({50, 0, 0, 0, false, false});
853   EXPECT_FALSE(manager->HasAnimation());
854   EXPECT_FLOAT_EQ(50.f, manager->TopControlsHeight());
855   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
856 }
857 
TEST(BrowserControlsOffsetManagerTest,ShrinkingHeightKeepsBrowserControlsHidden)858 TEST(BrowserControlsOffsetManagerTest,
859      ShrinkingHeightKeepsBrowserControlsHidden) {
860   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
861   BrowserControlsOffsetManager* manager = client.manager();
862 
863   manager->ScrollBegin();
864   manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
865   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
866   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
867   manager->ScrollEnd();
868 
869   client.SetBrowserControlsParams({50, 0, 0, 0, false, false});
870   EXPECT_FALSE(manager->HasAnimation());
871   EXPECT_FLOAT_EQ(-50.f, manager->ControlsTopOffset());
872   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
873 
874   client.SetBrowserControlsParams({0, 0, 0, 0, false, false});
875   EXPECT_FALSE(manager->HasAnimation());
876   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
877   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
878 }
879 
TEST(BrowserControlsOffsetManagerTest,HeightChangeWithAnimateFalseDoesNotTriggerAnimation)880 TEST(BrowserControlsOffsetManagerTest,
881      HeightChangeWithAnimateFalseDoesNotTriggerAnimation) {
882   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
883   BrowserControlsOffsetManager* manager = client.manager();
884 
885   client.SetBrowserControlsParams({150, 0, 0, 0, false, false});
886   EXPECT_FALSE(manager->HasAnimation());
887   EXPECT_FLOAT_EQ(150.f, manager->TopControlsHeight());
888   EXPECT_FLOAT_EQ(0, manager->ControlsTopOffset());
889 
890   client.SetBrowserControlsParams({50, 0, 0, 0, false, false});
891   EXPECT_FALSE(manager->HasAnimation());
892   EXPECT_FLOAT_EQ(50.f, manager->TopControlsHeight());
893   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
894 }
895 
TEST(BrowserControlsOffsetManagerTest,MinHeightChangeWithAnimateFalseSnapsToNewMinHeight)896 TEST(BrowserControlsOffsetManagerTest,
897      MinHeightChangeWithAnimateFalseSnapsToNewMinHeight) {
898   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
899   BrowserControlsOffsetManager* manager = client.manager();
900 
901   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
902 
903   // Scroll to hide the controls.
904   manager->ScrollBegin();
905   manager->ScrollBy(gfx::Vector2dF(0.f, 100.f));
906   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
907   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
908   manager->ScrollEnd();
909 
910   // Change the min-height from 0 to 20.
911   client.SetBrowserControlsParams({100, 20, 0, 0, false, false});
912   EXPECT_FALSE(manager->HasAnimation());
913   EXPECT_FLOAT_EQ(20.f, manager->TopControlsMinHeight());
914   // Top controls should snap to the new min-height.
915   EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset());
916   EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
917   // Min-height offset snaps to the new min-height.
918   EXPECT_FLOAT_EQ(20.f, manager->TopControlsMinHeightOffset());
919 
920   // Change the min-height from 20 to 0.
921   client.SetBrowserControlsParams({100, 0, 0, 0, false, false});
922   EXPECT_FALSE(manager->HasAnimation());
923   EXPECT_FLOAT_EQ(0.f, manager->TopControlsMinHeight());
924   // Top controls should snap to the new min-height, 0.
925   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
926   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
927   // Min-height offset snaps to the new min-height.
928   EXPECT_FLOAT_EQ(0.f, manager->TopControlsMinHeightOffset());
929 }
930 
TEST(BrowserControlsOffsetManagerTest,ControlsStayAtMinHeightOnHeightChange)931 TEST(BrowserControlsOffsetManagerTest, ControlsStayAtMinHeightOnHeightChange) {
932   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
933   BrowserControlsOffsetManager* manager = client.manager();
934 
935   // Set the min-height to 20.
936   client.SetBrowserControlsParams({100, 20, 0, 0, false, false});
937 
938   // Scroll the controls to min-height.
939   manager->ScrollBegin();
940   manager->ScrollBy(gfx::Vector2dF(0.f, 100.f));
941   EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
942   manager->ScrollEnd();
943 
944   // Change the height from 100 to 120.
945   client.SetBrowserControlsParams({120, 20, 0, 0, false, false});
946   EXPECT_FALSE(manager->HasAnimation());
947   EXPECT_FLOAT_EQ(120.f, manager->TopControlsHeight());
948   EXPECT_FLOAT_EQ(20.f, manager->TopControlsMinHeight());
949   // Top controls should stay at the same visible height.
950   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
951   EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
952 
953   // Change the height from 120 back to 100.
954   client.SetBrowserControlsParams({100, 20, 0, 0, false, false});
955   EXPECT_FALSE(manager->HasAnimation());
956   EXPECT_FLOAT_EQ(100.f, manager->TopControlsHeight());
957   EXPECT_FLOAT_EQ(20.f, manager->TopControlsMinHeight());
958   // Top controls should still stay at the same visible height.
959   EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset());
960   EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
961 }
962 
TEST(BrowserControlsOffsetManagerTest,ControlsAdjustToNewHeight)963 TEST(BrowserControlsOffsetManagerTest, ControlsAdjustToNewHeight) {
964   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
965   BrowserControlsOffsetManager* manager = client.manager();
966 
967   // Scroll the controls a little.
968   manager->ScrollBegin();
969   manager->ScrollBy(gfx::Vector2dF(0.f, 40.f));
970   EXPECT_FLOAT_EQ(60.f, manager->ContentTopOffset());
971 
972   // Change the height from 100 to 120.
973   client.SetBrowserControlsParams({120, 0, 0, 0, false, false});
974 
975   // The shown ratios should be adjusted to keep the shown height same.
976   EXPECT_FLOAT_EQ(60.f, manager->ContentTopOffset());
977 
978   manager->ScrollEnd();
979 }
980 
TEST(BrowserControlsOffsetManagerTest,ScrollByWithZeroHeightControlsIsNoop)981 TEST(BrowserControlsOffsetManagerTest, ScrollByWithZeroHeightControlsIsNoop) {
982   MockBrowserControlsOffsetManagerClient client(0.f, 0.5f, 0.5f);
983   BrowserControlsOffsetManager* manager = client.manager();
984   manager->UpdateBrowserControlsState(BrowserControlsState::kBoth,
985                                       BrowserControlsState::kBoth, false);
986 
987   manager->ScrollBegin();
988   gfx::Vector2dF pending = manager->ScrollBy(gfx::Vector2dF(0.f, 20.f));
989   EXPECT_FLOAT_EQ(20.f, pending.y());
990   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
991   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
992   EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio());
993   manager->ScrollEnd();
994 }
995 
TEST(BrowserControlsOffsetManagerTest,ScrollThenRestoreBottomControls)996 TEST(BrowserControlsOffsetManagerTest, ScrollThenRestoreBottomControls) {
997   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
998   client.SetBrowserControlsParams({0, 0, 100, 0, false, false});
999   BrowserControlsOffsetManager* manager = client.manager();
1000   manager->ScrollBegin();
1001   manager->ScrollBy(gfx::Vector2dF(0.f, 20.f));
1002   EXPECT_FLOAT_EQ(80.f, manager->ContentBottomOffset());
1003   EXPECT_FLOAT_EQ(0.8f, manager->BottomControlsShownRatio());
1004   manager->ScrollEnd();
1005 
1006   manager->ScrollBegin();
1007   manager->ScrollBy(gfx::Vector2dF(0.f, -200.f));
1008   EXPECT_FLOAT_EQ(100.f, manager->ContentBottomOffset());
1009   EXPECT_FLOAT_EQ(1.f, manager->BottomControlsShownRatio());
1010   manager->ScrollEnd();
1011 }
1012 
TEST(BrowserControlsOffsetManagerTest,ScrollThenRestoreBottomControlsNoTopControls)1013 TEST(BrowserControlsOffsetManagerTest,
1014      ScrollThenRestoreBottomControlsNoTopControls) {
1015   MockBrowserControlsOffsetManagerClient client(0.f, 0.5f, 0.5f);
1016   client.SetBrowserControlsParams({0, 0, 100, 0, false, false});
1017   BrowserControlsOffsetManager* manager = client.manager();
1018   manager->ScrollBegin();
1019   manager->ScrollBy(gfx::Vector2dF(0.f, 20.f));
1020   EXPECT_FLOAT_EQ(80.f, manager->ContentBottomOffset());
1021   EXPECT_FLOAT_EQ(0.8f, manager->BottomControlsShownRatio());
1022   manager->ScrollEnd();
1023 
1024   manager->ScrollBegin();
1025   manager->ScrollBy(gfx::Vector2dF(0.f, -200.f));
1026   EXPECT_FLOAT_EQ(100.f, manager->ContentBottomOffset());
1027   EXPECT_FLOAT_EQ(1.f, manager->BottomControlsShownRatio());
1028   manager->ScrollEnd();
1029 }
1030 
TEST(BrowserControlsOffsetManagerTest,HideAndPeekBottomControls)1031 TEST(BrowserControlsOffsetManagerTest, HideAndPeekBottomControls) {
1032   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
1033   client.SetBrowserControlsParams({0, 0, 100, 0, false, false});
1034   BrowserControlsOffsetManager* manager = client.manager();
1035   manager->ScrollBegin();
1036   manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
1037   EXPECT_FLOAT_EQ(0.f, manager->ContentBottomOffset());
1038   EXPECT_FLOAT_EQ(0.f, manager->BottomControlsShownRatio());
1039   manager->ScrollEnd();
1040 
1041   manager->ScrollBegin();
1042   manager->ScrollBy(gfx::Vector2dF(0.f, -15.f));
1043   EXPECT_FLOAT_EQ(15.f, manager->ContentBottomOffset());
1044   EXPECT_FLOAT_EQ(0.15f, manager->BottomControlsShownRatio());
1045   manager->ScrollEnd();
1046 }
1047 
TEST(BrowserControlsOffsetManagerTest,HideAndImmediateShowKeepsControlsVisible)1048 TEST(BrowserControlsOffsetManagerTest,
1049      HideAndImmediateShowKeepsControlsVisible) {
1050   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
1051   client.SetBrowserControlsParams({0, 0, 100, 0, false, false});
1052   BrowserControlsOffsetManager* manager = client.manager();
1053   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
1054 
1055   manager->UpdateBrowserControlsState(BrowserControlsState::kBoth,
1056                                       BrowserControlsState::kHidden, true);
1057   EXPECT_TRUE(manager->HasAnimation());
1058   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
1059 
1060   manager->UpdateBrowserControlsState(BrowserControlsState::kBoth,
1061                                       BrowserControlsState::kShown, true);
1062   EXPECT_FALSE(manager->HasAnimation());
1063   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
1064 }
1065 
TEST(BrowserControlsOffsetManagerTest,ScrollWithMinHeightSetForTopControlsOnly)1066 TEST(BrowserControlsOffsetManagerTest,
1067      ScrollWithMinHeightSetForTopControlsOnly) {
1068   MockBrowserControlsOffsetManagerClient client(100, 0.5f, 0.5f);
1069   client.SetBrowserControlsParams({100, 30, 100, 0, false, false});
1070   BrowserControlsOffsetManager* manager = client.manager();
1071   EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio());
1072   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
1073 
1074   // Controls don't hide completely and stop at the min-height.
1075   manager->ScrollBegin();
1076   manager->ScrollBy(gfx::Vector2dF(0, 150));
1077   EXPECT_FLOAT_EQ(30.f / 100, client.CurrentTopControlsShownRatio());
1078   EXPECT_FLOAT_EQ(0.f, client.CurrentBottomControlsShownRatio());
1079   manager->ScrollEnd();
1080 
1081   // Controls scroll immediately from the min-height point.
1082   manager->ScrollBegin();
1083   manager->ScrollBy(gfx::Vector2dF(0, -70));
1084   EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio());
1085   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
1086   manager->ScrollEnd();
1087 }
1088 
TEST(BrowserControlsOffsetManagerTest,ScrollWithMinHeightSetForBothControls)1089 TEST(BrowserControlsOffsetManagerTest, ScrollWithMinHeightSetForBothControls) {
1090   MockBrowserControlsOffsetManagerClient client(100, 0.5f, 0.5f);
1091   client.SetBrowserControlsParams({100, 30, 100, 20, false, false});
1092   BrowserControlsOffsetManager* manager = client.manager();
1093   EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio());
1094   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
1095 
1096   // Controls don't hide completely and stop at the min-height.
1097   manager->ScrollBegin();
1098   manager->ScrollBy(gfx::Vector2dF(0, 150));
1099   EXPECT_FLOAT_EQ(30.f / 100, client.CurrentTopControlsShownRatio());
1100   EXPECT_FLOAT_EQ(20.f / 100, client.CurrentBottomControlsShownRatio());
1101   manager->ScrollEnd();
1102 
1103   manager->ScrollBegin();
1104   manager->ScrollBy(gfx::Vector2dF(0, -70));
1105   EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio());
1106   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
1107   manager->ScrollEnd();
1108 }
1109 
TEST(BrowserControlsOffsetManagerTest,ChangingBottomHeightFromZeroAnimates)1110 TEST(BrowserControlsOffsetManagerTest, ChangingBottomHeightFromZeroAnimates) {
1111   MockBrowserControlsOffsetManagerClient client(100, 0.5f, 0.5f);
1112   client.SetBrowserControlsParams({100, 30, 0, 0, false, false});
1113   BrowserControlsOffsetManager* manager = client.manager();
1114   EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio());
1115   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
1116 
1117   // Set the bottom controls height to 100 with animation.
1118   client.SetBrowserControlsParams({100, 30, 100, 0, true, false});
1119   EXPECT_TRUE(manager->HasAnimation());
1120   // The bottom controls should be hidden in the beginning.
1121   EXPECT_FLOAT_EQ(0.f, manager->ContentBottomOffset());
1122   EXPECT_FLOAT_EQ(0.f, client.CurrentBottomControlsShownRatio());
1123 
1124   base::TimeTicks time = base::TimeTicks::Now();
1125 
1126   // First animate will establish the animaion.
1127   float previous_ratio = manager->BottomControlsShownRatio();
1128   manager->Animate(time);
1129   EXPECT_EQ(manager->BottomControlsShownRatio(), previous_ratio);
1130 
1131   while (manager->HasAnimation()) {
1132     previous_ratio = manager->BottomControlsShownRatio();
1133     time = base::TimeDelta::FromMicroseconds(100) + time;
1134     manager->Animate(time);
1135     EXPECT_GT(manager->BottomControlsShownRatio(), previous_ratio);
1136   }
1137 
1138   // Now the bottom controls should be fully shown.
1139   EXPECT_FLOAT_EQ(100.f, manager->ContentBottomOffset());
1140   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
1141 }
1142 
TEST(BrowserControlsOffsetManagerTest,ChangingControlsHeightToZeroWithAnimationIsNoop)1143 TEST(BrowserControlsOffsetManagerTest,
1144      ChangingControlsHeightToZeroWithAnimationIsNoop) {
1145   MockBrowserControlsOffsetManagerClient client(100, 0.5f, 0.5f);
1146   client.SetBrowserControlsParams({100, 20, 80, 10, false, false});
1147   BrowserControlsOffsetManager* manager = client.manager();
1148   EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio());
1149   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
1150 
1151   // Set the bottom controls height to 0 with animation.
1152   client.SetBrowserControlsParams({100, 20, 0, 0, true, false});
1153 
1154   // There shouldn't be an animation because we can't animate controls with 0
1155   // height.
1156   EXPECT_FALSE(manager->HasAnimation());
1157   // Also, the bottom controls ratio should stay the same.
1158   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
1159 
1160   // Increase the top controls height with animation.
1161   client.SetBrowserControlsParams({120, 20, 0, 0, true, false});
1162   // This shouldn't override the bottom controls shown ratio.
1163   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
1164 }
1165 
TEST(BrowserControlsOffsetManagerTest,OnlyExpandTopControlsAtPageTop)1166 TEST(BrowserControlsOffsetManagerTest, OnlyExpandTopControlsAtPageTop) {
1167   MockBrowserControlsOffsetManagerClient client(0.f, 0.5f, 0.5f);
1168   client.SetBrowserControlsParams(
1169       {/*top_controls_height=*/100.f, 0, 0, 0, false, false,
1170        /*only_expand_top_controls_at_page_top=*/true});
1171   BrowserControlsOffsetManager* manager = client.manager();
1172 
1173   // Scroll down to hide the controls entirely.
1174   manager->ScrollBegin();
1175   client.ScrollVerticallyBy(150.f);
1176   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
1177   EXPECT_FLOAT_EQ(50.f, client.ViewportScrollOffset().y());
1178   manager->ScrollEnd();
1179 
1180   manager->ScrollBegin();
1181 
1182   // Scroll back up a bit and ensure the controls don't move until we're at
1183   // the top.
1184   client.ScrollVerticallyBy(-20.f);
1185   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
1186   EXPECT_FLOAT_EQ(30.f, client.ViewportScrollOffset().y());
1187 
1188   client.ScrollVerticallyBy(-10.f);
1189   EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
1190   EXPECT_FLOAT_EQ(20.f, client.ViewportScrollOffset().y());
1191 
1192   // After scrolling past the top, the top controls should start showing.
1193   client.ScrollVerticallyBy(-30.f);
1194   EXPECT_FLOAT_EQ(-90.f, manager->ControlsTopOffset());
1195   EXPECT_FLOAT_EQ(0.f, client.ViewportScrollOffset().y());
1196 
1197   client.ScrollVerticallyBy(-50.f);
1198   EXPECT_FLOAT_EQ(-40.f, manager->ControlsTopOffset());
1199   // The final offset is greater than gtest's epsilon.
1200   EXPECT_GT(0.0001f, client.ViewportScrollOffset().y());
1201 
1202   manager->ScrollEnd();
1203 }
1204 
1205 // Tests that if the min-height changes while we're animating to the previous
1206 // min-height, the animation gets updated to end at the new value.
TEST(BrowserControlsOffsetManagerTest,MinHeightChangeUpdatesAnimation)1207 TEST(BrowserControlsOffsetManagerTest, MinHeightChangeUpdatesAnimation) {
1208   MockBrowserControlsOffsetManagerClient client(100, 0.5f, 0.5f);
1209   client.SetBrowserControlsParams(
1210       {/*top_controls_height=*/100, /*top_controls_min_height=*/50, 0, 0,
1211        /*animate_browser_controls_height_changes=*/true, false, false});
1212   BrowserControlsOffsetManager* manager = client.manager();
1213 
1214   // Hide the controls to start an animation to min-height.
1215   EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
1216   manager->UpdateBrowserControlsState(BrowserControlsState::kHidden,
1217                                       BrowserControlsState::kBoth, true);
1218   base::TimeTicks time = base::TimeTicks::Now();
1219   manager->Animate(time);
1220   EXPECT_TRUE(manager->HasAnimation());
1221 
1222   // Update the min-height to a smaller value.
1223   client.SetBrowserControlsParams(
1224       {/*top_controls_height=*/100, /*top_controls_min_height=*/10, 0, 0,
1225        /*animate_browser_controls_height_changes=*/true, false, false});
1226   EXPECT_TRUE(manager->HasAnimation());
1227 
1228   // Make sure the animation finishes at the new min-height.
1229   while (manager->HasAnimation()) {
1230     time = base::TimeDelta::FromMicroseconds(100) + time;
1231     manager->Animate(time);
1232   }
1233   EXPECT_FALSE(manager->HasAnimation());
1234   EXPECT_FLOAT_EQ(0.1f, manager->TopControlsShownRatio());
1235 }
1236 
1237 }  // namespace
1238 }  // namespace cc
1239