OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 "chrome/browser/sessions/session_restore_stats_collector.h" |
| 6 |
| 7 #include "base/message_loop/message_loop.h" |
| 8 #include "base/test/simple_test_tick_clock.h" |
| 9 #include "chrome/test/base/testing_profile.h" |
| 10 #include "content/public/browser/notification_service.h" |
| 11 #include "content/public/browser/notification_types.h" |
| 12 #include "content/public/browser/render_widget_host.h" |
| 13 #include "content/public/browser/render_widget_host_view.h" |
| 14 #include "content/public/browser/web_contents.h" |
| 15 #include "content/public/test/test_browser_thread.h" |
| 16 #include "content/public/test/test_web_contents_factory.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 |
| 19 namespace { |
| 20 |
| 21 using TabLoaderStats = SessionRestoreStatsCollector::TabLoaderStats; |
| 22 using StatsReportingDelegate = |
| 23 SessionRestoreStatsCollector::StatsReportingDelegate; |
| 24 |
| 25 // A mock StatsReportingDelegate. This is used by the unittests to validate the |
| 26 // reporting and lifetime behaviour of the SessionRestoreStatsCollector under |
| 27 // test. |
| 28 class MockStatsReportingDelegate : public StatsReportingDelegate { |
| 29 public: |
| 30 MockStatsReportingDelegate() |
| 31 : report_tab_loader_stats_call_count_(0u), |
| 32 report_tab_deferred_call_count_(0u), |
| 33 report_deferred_tab_loaded_call_count_(0u), |
| 34 report_stats_collector_death_call_count_(0u) {} |
| 35 |
| 36 ~MockStatsReportingDelegate() override { EnsureNoUnexpectedCalls(); } |
| 37 |
| 38 void ReportTabLoaderStats(const TabLoaderStats& stats) override { |
| 39 report_tab_loader_stats_call_count_++; |
| 40 tab_loader_stats_ = stats; |
| 41 } |
| 42 |
| 43 void ReportTabDeferred() override { report_tab_deferred_call_count_++; } |
| 44 |
| 45 void ReportDeferredTabLoaded() override { |
| 46 report_deferred_tab_loaded_call_count_++; |
| 47 } |
| 48 |
| 49 // This is not part of the StatsReportingDelegate, but an added function that |
| 50 // is invoked by the PassthroughStatsReportingDelegate when it dies. This |
| 51 // allows the tests to be notified the moment the underlying stats collector |
| 52 // terminates itself. |
| 53 void ReportStatsCollectorDeath() { |
| 54 report_stats_collector_death_call_count_++; |
| 55 } |
| 56 |
| 57 void ExpectReportTabLoaderStatsCalled(size_t tab_count, |
| 58 size_t tabs_loaded, |
| 59 int foreground_tab_first_loaded_ms, |
| 60 int foreground_tab_first_paint_ms, |
| 61 int non_deferred_tabs_loaded_ms, |
| 62 size_t parallel_tab_loads) { |
| 63 EXPECT_LT(0u, report_tab_loader_stats_call_count_); |
| 64 report_tab_loader_stats_call_count_--; |
| 65 |
| 66 EXPECT_EQ(tab_count, tab_loader_stats_.tab_count); |
| 67 EXPECT_EQ(tabs_loaded, tab_loader_stats_.tabs_loaded); |
| 68 EXPECT_EQ(base::TimeDelta::FromMilliseconds(foreground_tab_first_loaded_ms), |
| 69 tab_loader_stats_.foreground_tab_first_loaded); |
| 70 EXPECT_EQ(base::TimeDelta::FromMilliseconds(foreground_tab_first_paint_ms), |
| 71 tab_loader_stats_.foreground_tab_first_paint); |
| 72 EXPECT_EQ(base::TimeDelta::FromMilliseconds(non_deferred_tabs_loaded_ms), |
| 73 tab_loader_stats_.non_deferred_tabs_loaded); |
| 74 EXPECT_EQ(parallel_tab_loads, tab_loader_stats_.parallel_tab_loads); |
| 75 } |
| 76 |
| 77 void ExpectReportTabDeferredCalled() { |
| 78 EXPECT_LT(0u, report_tab_deferred_call_count_); |
| 79 report_tab_deferred_call_count_--; |
| 80 } |
| 81 |
| 82 void ExpectReportDeferredTabLoadedCalled() { |
| 83 EXPECT_LT(0u, report_deferred_tab_loaded_call_count_); |
| 84 report_deferred_tab_loaded_call_count_--; |
| 85 } |
| 86 |
| 87 void ExpectReportStatsCollectorDeathCalled() { |
| 88 EXPECT_LT(0u, report_stats_collector_death_call_count_); |
| 89 report_stats_collector_death_call_count_--; |
| 90 } |
| 91 |
| 92 void EnsureNoUnexpectedCalls() { |
| 93 EXPECT_EQ(0u, report_tab_loader_stats_call_count_); |
| 94 EXPECT_EQ(0u, report_tab_deferred_call_count_); |
| 95 EXPECT_EQ(0u, report_deferred_tab_loaded_call_count_); |
| 96 EXPECT_EQ(0u, report_stats_collector_death_call_count_); |
| 97 |
| 98 report_tab_loader_stats_call_count_ = 0u; |
| 99 report_tab_deferred_call_count_ = 0u; |
| 100 report_deferred_tab_loaded_call_count_ = 0u; |
| 101 report_stats_collector_death_call_count_ = 0u; |
| 102 tab_loader_stats_ = TabLoaderStats(); |
| 103 } |
| 104 |
| 105 private: |
| 106 size_t report_tab_loader_stats_call_count_; |
| 107 size_t report_tab_deferred_call_count_; |
| 108 size_t report_deferred_tab_loaded_call_count_; |
| 109 size_t report_stats_collector_death_call_count_; |
| 110 TabLoaderStats tab_loader_stats_; |
| 111 |
| 112 DISALLOW_COPY_AND_ASSIGN(MockStatsReportingDelegate); |
| 113 }; |
| 114 |
| 115 // A pass-through stats reporting delegate. This is used to decouple the |
| 116 // lifetime of the mock reporting delegate from the SessionRestoreStatsCollector |
| 117 // under test. The SessionRestoreStatsCollector has ownership of this delegate, |
| 118 // which will notify the mock delegate upon its death. |
| 119 class PassthroughStatsReportingDelegate : public StatsReportingDelegate { |
| 120 public: |
| 121 PassthroughStatsReportingDelegate() : reporting_delegate_(nullptr) {} |
| 122 ~PassthroughStatsReportingDelegate() override { |
| 123 reporting_delegate_->ReportStatsCollectorDeath(); |
| 124 } |
| 125 |
| 126 void set_reporting_delegate(MockStatsReportingDelegate* reporting_delegate) { |
| 127 reporting_delegate_ = reporting_delegate; |
| 128 } |
| 129 |
| 130 void ReportTabLoaderStats(const TabLoaderStats& tab_loader_stats) override { |
| 131 reporting_delegate_->ReportTabLoaderStats(tab_loader_stats); |
| 132 } |
| 133 |
| 134 void ReportTabDeferred() override { |
| 135 reporting_delegate_->ReportTabDeferred(); |
| 136 } |
| 137 |
| 138 void ReportDeferredTabLoaded() override { |
| 139 reporting_delegate_->ReportDeferredTabLoaded(); |
| 140 } |
| 141 |
| 142 private: |
| 143 MockStatsReportingDelegate* reporting_delegate_; |
| 144 |
| 145 DISALLOW_COPY_AND_ASSIGN(PassthroughStatsReportingDelegate); |
| 146 }; |
| 147 |
| 148 } // namespace |
| 149 |
| 150 class TestSessionRestoreStatsCollector : public SessionRestoreStatsCollector { |
| 151 public: |
| 152 using SessionRestoreStatsCollector::Observe; |
| 153 |
| 154 TestSessionRestoreStatsCollector( |
| 155 scoped_ptr<base::TickClock> tick_clock, |
| 156 scoped_ptr<StatsReportingDelegate> reporting_delegate) |
| 157 : SessionRestoreStatsCollector(tick_clock->NowTicks(), |
| 158 reporting_delegate.Pass()) { |
| 159 set_tick_clock(tick_clock.Pass()); |
| 160 } |
| 161 |
| 162 private: |
| 163 friend class base::RefCounted<TestSessionRestoreStatsCollector>; |
| 164 |
| 165 ~TestSessionRestoreStatsCollector() override {} |
| 166 |
| 167 base::SimpleTestTickClock* test_tick_clock_; |
| 168 |
| 169 DISALLOW_COPY_AND_ASSIGN(TestSessionRestoreStatsCollector); |
| 170 }; |
| 171 |
| 172 class SessionRestoreStatsCollectorTest : public testing::Test { |
| 173 public: |
| 174 using RestoredTab = SessionRestoreDelegate::RestoredTab; |
| 175 |
| 176 SessionRestoreStatsCollectorTest() |
| 177 : ui_thread_(content::BrowserThread::UI, &message_loop_) {} |
| 178 |
| 179 void SetUp() override { |
| 180 test_web_contents_factory_.reset(new content::TestWebContentsFactory); |
| 181 |
| 182 // Ownership of the reporting delegate is passed to the |
| 183 // SessionRestoreStatsCollector, but a raw pointer is kept to it so it can |
| 184 // be queried by the test. |
| 185 passthrough_reporting_delegate_ = new PassthroughStatsReportingDelegate(); |
| 186 |
| 187 // Ownership of this clock is passed to the SessionRestoreStatsCollector. |
| 188 // A raw pointer is kept to it so that it can be modified from the outside. |
| 189 // The unittest must take care to access the clock only while the |
| 190 // SessionRestoreStatsCollector under test is still alive. |
| 191 test_tick_clock_ = new base::SimpleTestTickClock(); |
| 192 |
| 193 // Create a stats collector, keep a raw pointer to it, and detach from it. |
| 194 // The stats collector will stay alive as long as it has not yet completed |
| 195 // its job, and will clean itself up when done. |
| 196 scoped_refptr<TestSessionRestoreStatsCollector> stats_collector = |
| 197 new TestSessionRestoreStatsCollector( |
| 198 scoped_ptr<base::TickClock>(test_tick_clock_), |
| 199 scoped_ptr<StatsReportingDelegate>( |
| 200 passthrough_reporting_delegate_)); |
| 201 stats_collector_ = stats_collector.get(); |
| 202 stats_collector = nullptr; |
| 203 } |
| 204 |
| 205 void TearDown() override { |
| 206 passthrough_reporting_delegate_ = nullptr; |
| 207 test_tick_clock_ = nullptr; |
| 208 stats_collector_ = nullptr; |
| 209 |
| 210 // Clean up any tabs that were generated by the unittest. |
| 211 restored_tabs_.clear(); |
| 212 test_web_contents_factory_.reset(); |
| 213 } |
| 214 |
| 215 // Advances the test clock by 1ms. |
| 216 void Tick() { |
| 217 test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(1)); |
| 218 } |
| 219 |
| 220 void Show(size_t tab_index) { |
| 221 restored_tabs_[tab_index].contents()->GetRenderWidgetHostView()->Show(); |
| 222 } |
| 223 |
| 224 void Hide(size_t tab_index) { |
| 225 restored_tabs_[tab_index].contents()->GetRenderWidgetHostView()->Hide(); |
| 226 } |
| 227 |
| 228 // Creates a restored tab backed by dummy WebContents/NavigationController/ |
| 229 // RenderWidgetHost/RenderWidgetHostView. Returns the index of the restored |
| 230 // tab for future simulation of events. |
| 231 void CreateRestoredTab(bool is_active) { |
| 232 content::WebContents* contents = |
| 233 test_web_contents_factory_->CreateWebContents(&testing_profile_); |
| 234 restored_tabs_.push_back(RestoredTab(contents, is_active, false, false)); |
| 235 if (is_active) |
| 236 Show(restored_tabs_.size() - 1); |
| 237 } |
| 238 |
| 239 // Helper function for various notification generation. |
| 240 void GenerateControllerNotification(size_t tab_index, int type) { |
| 241 content::WebContents* contents = restored_tabs_[tab_index].contents(); |
| 242 content::NavigationController* controller = &contents->GetController(); |
| 243 stats_collector_->Observe( |
| 244 type, content::Source<content::NavigationController>(controller), |
| 245 content::NotificationService::NoDetails()); |
| 246 } |
| 247 |
| 248 // Generates a load start notification for the given tab. |
| 249 void GenerateLoadStart(size_t tab_index) { |
| 250 GenerateControllerNotification(tab_index, content::NOTIFICATION_LOAD_START); |
| 251 } |
| 252 |
| 253 // Generates a load stop notification for the given tab. |
| 254 void GenerateLoadStop(size_t tab_index) { |
| 255 GenerateControllerNotification(tab_index, content::NOTIFICATION_LOAD_STOP); |
| 256 } |
| 257 |
| 258 // Generates a web contents destroyed notification for the given tab. |
| 259 void GenerateWebContentsDestroyed(size_t tab_index) { |
| 260 content::WebContents* contents = restored_tabs_[tab_index].contents(); |
| 261 stats_collector_->Observe(content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 262 content::Source<content::WebContents>(contents), |
| 263 content::NotificationService::NoDetails()); |
| 264 } |
| 265 |
| 266 // Generates a paint notification for the given tab. |
| 267 void GenerateRenderWidgetHostDidUpdateBackingStore(size_t tab_index) { |
| 268 content::WebContents* contents = restored_tabs_[tab_index].contents(); |
| 269 content::RenderWidgetHost* host = |
| 270 contents->GetRenderWidgetHostView()->GetRenderWidgetHost(); |
| 271 stats_collector_->Observe( |
| 272 content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, |
| 273 content::Source<content::RenderWidgetHost>(host), |
| 274 content::NotificationService::NoDetails()); |
| 275 } |
| 276 |
| 277 // Defers a tab. |
| 278 void DeferTab(size_t tab_index) { |
| 279 content::WebContents* contents = restored_tabs_[tab_index].contents(); |
| 280 content::NavigationController* controller = &contents->GetController(); |
| 281 stats_collector_->DeferTab(controller); |
| 282 } |
| 283 |
| 284 // Inputs to the stats collector. Reset prior to each test. |
| 285 base::SimpleTestTickClock* test_tick_clock_; |
| 286 std::vector<RestoredTab> restored_tabs_; |
| 287 |
| 288 // Infrastructure needed for using the TestWebContentsFactory. These are |
| 289 // initialized once by the fixture and reused across unittests. |
| 290 base::MessageLoop message_loop_; |
| 291 TestingProfile testing_profile_; |
| 292 content::TestBrowserThread ui_thread_; |
| 293 |
| 294 // A new web contents factory is generated per test. This automatically cleans |
| 295 // up any tabs created by previous tests. |
| 296 scoped_ptr<content::TestWebContentsFactory> test_web_contents_factory_; |
| 297 |
| 298 // These are recreated for each test. The reporting delegate allows the test |
| 299 // to observe the behaviour of the SessionRestoreStatsCollector under test. |
| 300 PassthroughStatsReportingDelegate* passthrough_reporting_delegate_; |
| 301 TestSessionRestoreStatsCollector* stats_collector_; |
| 302 |
| 303 private: |
| 304 DISALLOW_COPY_AND_ASSIGN(SessionRestoreStatsCollectorTest); |
| 305 }; |
| 306 |
| 307 TEST_F(SessionRestoreStatsCollectorTest, SingleTabPaintBeforeLoad) { |
| 308 MockStatsReportingDelegate mock_reporting_delegate; |
| 309 passthrough_reporting_delegate_->set_reporting_delegate( |
| 310 &mock_reporting_delegate); |
| 311 |
| 312 CreateRestoredTab(true); |
| 313 stats_collector_->TrackTabs(restored_tabs_); |
| 314 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 315 |
| 316 Tick(); // 1ms. |
| 317 GenerateRenderWidgetHostDidUpdateBackingStore(0); |
| 318 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 319 |
| 320 Tick(); // 2ms. |
| 321 GenerateLoadStop(0); |
| 322 mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 1, 2, 1, 2, 1); |
| 323 mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); |
| 324 } |
| 325 |
| 326 TEST_F(SessionRestoreStatsCollectorTest, SingleTabPaintAfterLoad) { |
| 327 MockStatsReportingDelegate mock_reporting_delegate; |
| 328 passthrough_reporting_delegate_->set_reporting_delegate( |
| 329 &mock_reporting_delegate); |
| 330 |
| 331 CreateRestoredTab(true); |
| 332 stats_collector_->TrackTabs(restored_tabs_); |
| 333 |
| 334 Tick(); // 1ms. |
| 335 GenerateLoadStop(0); |
| 336 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 337 |
| 338 Tick(); // 2ms. |
| 339 GenerateRenderWidgetHostDidUpdateBackingStore(0); |
| 340 mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 1, 1, 2, 1, 1); |
| 341 mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); |
| 342 } |
| 343 |
| 344 TEST_F(SessionRestoreStatsCollectorTest, MultipleTabsLoadSerially) { |
| 345 MockStatsReportingDelegate mock_reporting_delegate; |
| 346 passthrough_reporting_delegate_->set_reporting_delegate( |
| 347 &mock_reporting_delegate); |
| 348 |
| 349 CreateRestoredTab(true); |
| 350 CreateRestoredTab(false); |
| 351 CreateRestoredTab(false); |
| 352 stats_collector_->TrackTabs(restored_tabs_); |
| 353 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 354 |
| 355 // Foreground tab paints then finishes loading. |
| 356 Tick(); // 1ms. |
| 357 GenerateRenderWidgetHostDidUpdateBackingStore(0); |
| 358 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 359 Tick(); // 2ms. |
| 360 GenerateLoadStop(0); |
| 361 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 362 |
| 363 // First background tab starts loading, paints, then finishes loading. |
| 364 Tick(); // 3ms. |
| 365 GenerateLoadStart(1); |
| 366 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 367 Tick(); // 4ms. |
| 368 GenerateRenderWidgetHostDidUpdateBackingStore(1); |
| 369 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 370 Tick(); // 5ms. |
| 371 GenerateLoadStop(1); |
| 372 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 373 |
| 374 // Second background tab starts loading, finishes loading, but never paints. |
| 375 Tick(); // 6ms. |
| 376 GenerateLoadStart(2); |
| 377 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 378 |
| 379 Tick(); // 7ms. |
| 380 GenerateLoadStop(2); |
| 381 mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(3, 3, 2, 1, 7, 1); |
| 382 mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); |
| 383 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 384 } |
| 385 |
| 386 TEST_F(SessionRestoreStatsCollectorTest, MultipleTabsLoadSimultaneously) { |
| 387 MockStatsReportingDelegate mock_reporting_delegate; |
| 388 passthrough_reporting_delegate_->set_reporting_delegate( |
| 389 &mock_reporting_delegate); |
| 390 |
| 391 CreateRestoredTab(true); |
| 392 CreateRestoredTab(false); |
| 393 CreateRestoredTab(false); |
| 394 stats_collector_->TrackTabs(restored_tabs_); |
| 395 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 396 |
| 397 // Foreground tab paints then finishes loading. |
| 398 Tick(); // 1ms. |
| 399 GenerateRenderWidgetHostDidUpdateBackingStore(0); |
| 400 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 401 Tick(); // 2ms. |
| 402 GenerateLoadStop(0); |
| 403 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 404 |
| 405 // Both background tabs start loading at the same time. The first one paints |
| 406 // before finishing loading, the second one paints after finishing loading |
| 407 // (the stats collector never sees the paint event). |
| 408 Tick(); // 3ms. |
| 409 GenerateLoadStart(1); |
| 410 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 411 GenerateLoadStart(2); |
| 412 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 413 Tick(); // 4ms. |
| 414 GenerateRenderWidgetHostDidUpdateBackingStore(1); |
| 415 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 416 Tick(); // 5ms. |
| 417 GenerateLoadStop(1); |
| 418 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 419 Tick(); // 6ms. |
| 420 GenerateLoadStop(2); |
| 421 mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(3, 3, 2, 1, 6, 2); |
| 422 mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); |
| 423 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 424 } |
| 425 |
| 426 TEST_F(SessionRestoreStatsCollectorTest, DeferredTabs) { |
| 427 MockStatsReportingDelegate mock_reporting_delegate; |
| 428 passthrough_reporting_delegate_->set_reporting_delegate( |
| 429 &mock_reporting_delegate); |
| 430 |
| 431 CreateRestoredTab(true); |
| 432 CreateRestoredTab(false); |
| 433 stats_collector_->TrackTabs(restored_tabs_); |
| 434 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 435 |
| 436 // Foreground tab paints, then the background tab is deferred. |
| 437 Tick(); // 1ms. |
| 438 GenerateRenderWidgetHostDidUpdateBackingStore(0); |
| 439 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 440 DeferTab(1); |
| 441 mock_reporting_delegate.ExpectReportTabDeferredCalled(); |
| 442 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 443 |
| 444 // Foreground tab finishes loading and stats get reported. |
| 445 Tick(); // 2ms. |
| 446 GenerateLoadStop(0); |
| 447 mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(2, 1, 2, 1, 2, 1); |
| 448 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 449 |
| 450 // Background tab starts loading, paints and stops loading. This fires off a |
| 451 // deferred tab loaded notification. |
| 452 Tick(); // 3ms. |
| 453 GenerateLoadStart(1); |
| 454 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 455 Tick(); // 4ms. |
| 456 GenerateRenderWidgetHostDidUpdateBackingStore(1); |
| 457 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 458 Tick(); // 5ms. |
| 459 GenerateLoadStop(1); |
| 460 mock_reporting_delegate.ExpectReportDeferredTabLoadedCalled(); |
| 461 mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); |
| 462 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 463 } |
| 464 |
| 465 TEST_F(SessionRestoreStatsCollectorTest, FocusSwitchNoForegroundPaintOrLoad) { |
| 466 MockStatsReportingDelegate mock_reporting_delegate; |
| 467 passthrough_reporting_delegate_->set_reporting_delegate( |
| 468 &mock_reporting_delegate); |
| 469 |
| 470 CreateRestoredTab(true); |
| 471 stats_collector_->TrackTabs(restored_tabs_); |
| 472 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 473 |
| 474 // Create another tab and make it the foreground tab. This tab is not actually |
| 475 // being tracked by the SessionRestoreStatsCollector, but its paint events |
| 476 // will be observed. |
| 477 CreateRestoredTab(false); |
| 478 Hide(0); |
| 479 Show(1); |
| 480 |
| 481 // Load and paint the restored tab (now the background tab). Don't expect |
| 482 // any calls to the mock as a visible tab paint has not yet been observed. |
| 483 Tick(); // 1ms. |
| 484 GenerateRenderWidgetHostDidUpdateBackingStore(0); |
| 485 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 486 Tick(); // 2ms. |
| 487 GenerateLoadStop(0); |
| 488 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 489 |
| 490 // Mark the new foreground tab as having painted. This should cause the |
| 491 // stats to be emitted, but with empty foreground paint and load values. |
| 492 Tick(); // 3ms. |
| 493 GenerateRenderWidgetHostDidUpdateBackingStore(1); |
| 494 mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 1, 0, 0, 2, 1); |
| 495 mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); |
| 496 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 497 } |
| 498 |
| 499 TEST_F(SessionRestoreStatsCollectorTest, FocusSwitchNoForegroundPaint) { |
| 500 MockStatsReportingDelegate mock_reporting_delegate; |
| 501 passthrough_reporting_delegate_->set_reporting_delegate( |
| 502 &mock_reporting_delegate); |
| 503 |
| 504 CreateRestoredTab(true); |
| 505 stats_collector_->TrackTabs(restored_tabs_); |
| 506 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 507 |
| 508 // Load the foreground tab. |
| 509 Tick(); // 1ms. |
| 510 GenerateLoadStop(0); |
| 511 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 512 |
| 513 // Create another tab and make it the foreground tab. This tab is not actually |
| 514 // being tracked by the SessionRestoreStatsCollector, but its paint events |
| 515 // will still be observed. |
| 516 CreateRestoredTab(false); |
| 517 Hide(0); |
| 518 Show(1); |
| 519 |
| 520 // Load and paint the restored tab (now the background tab). Don't expect |
| 521 // any calls to the mock as a visible tab paint has not yet been observed. |
| 522 Tick(); // 2ms. |
| 523 GenerateRenderWidgetHostDidUpdateBackingStore(0); |
| 524 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 525 |
| 526 // Mark the new foreground tab as having painted. This should cause the |
| 527 // stats to be emitted, but with an empty foreground paint value. |
| 528 Tick(); // 3ms. |
| 529 GenerateRenderWidgetHostDidUpdateBackingStore(1); |
| 530 mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 1, 1, 0, 1, 1); |
| 531 mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); |
| 532 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 533 } |
| 534 |
| 535 TEST_F(SessionRestoreStatsCollectorTest, LoadingTabDestroyedBeforePaint) { |
| 536 MockStatsReportingDelegate mock_reporting_delegate; |
| 537 passthrough_reporting_delegate_->set_reporting_delegate( |
| 538 &mock_reporting_delegate); |
| 539 |
| 540 CreateRestoredTab(true); |
| 541 stats_collector_->TrackTabs(restored_tabs_); |
| 542 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 543 |
| 544 // Destroy the tab. Expect all timings to be zero. |
| 545 GenerateWebContentsDestroyed(0); |
| 546 mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 0, 0, 0, 1); |
| 547 mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); |
| 548 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 549 } |
| 550 |
| 551 TEST_F(SessionRestoreStatsCollectorTest, LoadingTabDestroyedAfterPaint) { |
| 552 MockStatsReportingDelegate mock_reporting_delegate; |
| 553 passthrough_reporting_delegate_->set_reporting_delegate( |
| 554 &mock_reporting_delegate); |
| 555 |
| 556 CreateRestoredTab(true); |
| 557 stats_collector_->TrackTabs(restored_tabs_); |
| 558 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 559 |
| 560 Tick(); // 1 ms. |
| 561 GenerateRenderWidgetHostDidUpdateBackingStore(0); |
| 562 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 563 |
| 564 // Destroy the tab. Expect both load timings to be zero. |
| 565 GenerateWebContentsDestroyed(0); |
| 566 mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 0, 0, 1, 0, 1); |
| 567 mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); |
| 568 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 569 } |
| 570 |
| 571 TEST_F(SessionRestoreStatsCollectorTest, BrowseAwayBeforePaint) { |
| 572 MockStatsReportingDelegate mock_reporting_delegate; |
| 573 passthrough_reporting_delegate_->set_reporting_delegate( |
| 574 &mock_reporting_delegate); |
| 575 |
| 576 CreateRestoredTab(true); |
| 577 stats_collector_->TrackTabs(restored_tabs_); |
| 578 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 579 |
| 580 // Load the tab. |
| 581 Tick(); // 1 ms. |
| 582 GenerateLoadStop(0); |
| 583 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 584 |
| 585 // Reload the tab. Expect the paint timing to be zero. |
| 586 Tick(); // 2 ms. |
| 587 GenerateLoadStart(0); |
| 588 mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(1, 1, 1, 0, 1, 1); |
| 589 mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); |
| 590 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 591 } |
| 592 |
| 593 TEST_F(SessionRestoreStatsCollectorTest, DiscardDeferredTabs) { |
| 594 MockStatsReportingDelegate mock_reporting_delegate; |
| 595 passthrough_reporting_delegate_->set_reporting_delegate( |
| 596 &mock_reporting_delegate); |
| 597 |
| 598 CreateRestoredTab(true); |
| 599 CreateRestoredTab(false); |
| 600 stats_collector_->TrackTabs(restored_tabs_); |
| 601 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 602 |
| 603 // Defer the background tab. |
| 604 Tick(); // 1 ms. |
| 605 DeferTab(1); |
| 606 mock_reporting_delegate.ExpectReportTabDeferredCalled(); |
| 607 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 608 |
| 609 // Discard the foreground tab. The stats tab loader stats should be reported |
| 610 // with all zero timings. |
| 611 Tick(); // 2 ms. |
| 612 GenerateWebContentsDestroyed(0); |
| 613 mock_reporting_delegate.ExpectReportTabLoaderStatsCalled(2, 0, 0, 0, 0, 1); |
| 614 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 615 |
| 616 // Destroy the background tab. The collector should release itself. |
| 617 Tick(); // 3 ms. |
| 618 GenerateWebContentsDestroyed(1); |
| 619 mock_reporting_delegate.ExpectReportStatsCollectorDeathCalled(); |
| 620 mock_reporting_delegate.EnsureNoUnexpectedCalls(); |
| 621 } |
OLD | NEW |