| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 "components/sessions/core/persistent_tab_restore_service.h" | 5 #include "components/sessions/core/persistent_tab_restore_service.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 TEST_F(PersistentTabRestoreServiceTest, Basic) { | 219 TEST_F(PersistentTabRestoreServiceTest, Basic) { |
| 220 AddThreeNavigations(); | 220 AddThreeNavigations(); |
| 221 | 221 |
| 222 // Have the service record the tab. | 222 // Have the service record the tab. |
| 223 service_->CreateHistoricalTab(live_tab(), -1); | 223 service_->CreateHistoricalTab(live_tab(), -1); |
| 224 | 224 |
| 225 // Make sure an entry was created. | 225 // Make sure an entry was created. |
| 226 ASSERT_EQ(1U, service_->entries().size()); | 226 ASSERT_EQ(1U, service_->entries().size()); |
| 227 | 227 |
| 228 // Make sure the entry matches. | 228 // Make sure the entry matches. |
| 229 sessions::TabRestoreService::Entry* entry = service_->entries().front(); | 229 sessions::TabRestoreService::Entry* entry = service_->entries().front().get(); |
| 230 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); | 230 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); |
| 231 Tab* tab = static_cast<Tab*>(entry); | 231 Tab* tab = static_cast<Tab*>(entry); |
| 232 EXPECT_FALSE(tab->pinned); | 232 EXPECT_FALSE(tab->pinned); |
| 233 EXPECT_TRUE(tab->extension_app_id.empty()); | 233 EXPECT_TRUE(tab->extension_app_id.empty()); |
| 234 ASSERT_EQ(3U, tab->navigations.size()); | 234 ASSERT_EQ(3U, tab->navigations.size()); |
| 235 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url()); | 235 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url()); |
| 236 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url()); | 236 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url()); |
| 237 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url()); | 237 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url()); |
| 238 EXPECT_EQ("", tab->user_agent_override); | 238 EXPECT_EQ("", tab->user_agent_override); |
| 239 EXPECT_EQ(2, tab->current_navigation_index); | 239 EXPECT_EQ(2, tab->current_navigation_index); |
| 240 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(), | 240 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(), |
| 241 tab->timestamp.ToInternalValue()); | 241 tab->timestamp.ToInternalValue()); |
| 242 | 242 |
| 243 NavigateToIndex(1); | 243 NavigateToIndex(1); |
| 244 | 244 |
| 245 // And check again, but set the user agent override this time. | 245 // And check again, but set the user agent override this time. |
| 246 web_contents()->SetUserAgentOverride(user_agent_override_); | 246 web_contents()->SetUserAgentOverride(user_agent_override_); |
| 247 service_->CreateHistoricalTab(live_tab(), -1); | 247 service_->CreateHistoricalTab(live_tab(), -1); |
| 248 | 248 |
| 249 // There should be two entries now. | 249 // There should be two entries now. |
| 250 ASSERT_EQ(2U, service_->entries().size()); | 250 ASSERT_EQ(2U, service_->entries().size()); |
| 251 | 251 |
| 252 // Make sure the entry matches. | 252 // Make sure the entry matches. |
| 253 entry = service_->entries().front(); | 253 entry = service_->entries().front().get(); |
| 254 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); | 254 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); |
| 255 tab = static_cast<Tab*>(entry); | 255 tab = static_cast<Tab*>(entry); |
| 256 EXPECT_FALSE(tab->pinned); | 256 EXPECT_FALSE(tab->pinned); |
| 257 ASSERT_EQ(3U, tab->navigations.size()); | 257 ASSERT_EQ(3U, tab->navigations.size()); |
| 258 EXPECT_EQ(url1_, tab->navigations[0].virtual_url()); | 258 EXPECT_EQ(url1_, tab->navigations[0].virtual_url()); |
| 259 EXPECT_EQ(url2_, tab->navigations[1].virtual_url()); | 259 EXPECT_EQ(url2_, tab->navigations[1].virtual_url()); |
| 260 EXPECT_EQ(url3_, tab->navigations[2].virtual_url()); | 260 EXPECT_EQ(url3_, tab->navigations[2].virtual_url()); |
| 261 EXPECT_EQ(user_agent_override_, tab->user_agent_override); | 261 EXPECT_EQ(user_agent_override_, tab->user_agent_override); |
| 262 EXPECT_EQ(1, tab->current_navigation_index); | 262 EXPECT_EQ(1, tab->current_navigation_index); |
| 263 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(), | 263 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(), |
| (...skipping 15 matching lines...) Expand all Loading... |
| 279 service_->CreateHistoricalTab(live_tab(), -1); | 279 service_->CreateHistoricalTab(live_tab(), -1); |
| 280 | 280 |
| 281 // Recreate the service and have it load the tabs. | 281 // Recreate the service and have it load the tabs. |
| 282 RecreateService(); | 282 RecreateService(); |
| 283 | 283 |
| 284 // One entry should be created. | 284 // One entry should be created. |
| 285 ASSERT_EQ(1U, service_->entries().size()); | 285 ASSERT_EQ(1U, service_->entries().size()); |
| 286 | 286 |
| 287 // And verify the entry. | 287 // And verify the entry. |
| 288 sessions::PersistentTabRestoreService::Entry* entry = | 288 sessions::PersistentTabRestoreService::Entry* entry = |
| 289 service_->entries().front(); | 289 service_->entries().front().get(); |
| 290 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); | 290 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); |
| 291 Tab* tab = static_cast<Tab*>(entry); | 291 Tab* tab = static_cast<Tab*>(entry); |
| 292 EXPECT_FALSE(tab->pinned); | 292 EXPECT_FALSE(tab->pinned); |
| 293 ASSERT_EQ(3U, tab->navigations.size()); | 293 ASSERT_EQ(3U, tab->navigations.size()); |
| 294 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url()); | 294 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url()); |
| 295 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url()); | 295 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url()); |
| 296 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url()); | 296 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url()); |
| 297 EXPECT_EQ(2, tab->current_navigation_index); | 297 EXPECT_EQ(2, tab->current_navigation_index); |
| 298 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(), | 298 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(), |
| 299 tab->timestamp.ToInternalValue()); | 299 tab->timestamp.ToInternalValue()); |
| 300 } | 300 } |
| 301 | 301 |
| 302 // Tests restoring a single pinned tab. | 302 // Tests restoring a single pinned tab. |
| 303 TEST_F(PersistentTabRestoreServiceTest, RestorePinnedAndApp) { | 303 TEST_F(PersistentTabRestoreServiceTest, RestorePinnedAndApp) { |
| 304 AddThreeNavigations(); | 304 AddThreeNavigations(); |
| 305 | 305 |
| 306 // Have the service record the tab. | 306 // Have the service record the tab. |
| 307 service_->CreateHistoricalTab(live_tab(), -1); | 307 service_->CreateHistoricalTab(live_tab(), -1); |
| 308 | 308 |
| 309 // One entry should be created. | 309 // One entry should be created. |
| 310 ASSERT_EQ(1U, service_->entries().size()); | 310 ASSERT_EQ(1U, service_->entries().size()); |
| 311 | 311 |
| 312 // We have to explicitly mark the tab as pinned as there is no browser for | 312 // We have to explicitly mark the tab as pinned as there is no browser for |
| 313 // these tests. | 313 // these tests. |
| 314 sessions::TabRestoreService::Entry* entry = service_->entries().front(); | 314 sessions::TabRestoreService::Entry* entry = service_->entries().front().get(); |
| 315 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); | 315 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); |
| 316 Tab* tab = static_cast<Tab*>(entry); | 316 Tab* tab = static_cast<Tab*>(entry); |
| 317 tab->pinned = true; | 317 tab->pinned = true; |
| 318 const std::string extension_app_id("test"); | 318 const std::string extension_app_id("test"); |
| 319 tab->extension_app_id = extension_app_id; | 319 tab->extension_app_id = extension_app_id; |
| 320 | 320 |
| 321 // Recreate the service and have it load the tabs. | 321 // Recreate the service and have it load the tabs. |
| 322 RecreateService(); | 322 RecreateService(); |
| 323 | 323 |
| 324 // One entry should be created. | 324 // One entry should be created. |
| 325 ASSERT_EQ(1U, service_->entries().size()); | 325 ASSERT_EQ(1U, service_->entries().size()); |
| 326 | 326 |
| 327 // And verify the entry. | 327 // And verify the entry. |
| 328 entry = service_->entries().front(); | 328 entry = service_->entries().front().get(); |
| 329 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); | 329 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); |
| 330 tab = static_cast<Tab*>(entry); | 330 tab = static_cast<Tab*>(entry); |
| 331 EXPECT_TRUE(tab->pinned); | 331 EXPECT_TRUE(tab->pinned); |
| 332 ASSERT_EQ(3U, tab->navigations.size()); | 332 ASSERT_EQ(3U, tab->navigations.size()); |
| 333 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url()); | 333 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url()); |
| 334 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url()); | 334 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url()); |
| 335 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url()); | 335 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url()); |
| 336 EXPECT_EQ(2, tab->current_navigation_index); | 336 EXPECT_EQ(2, tab->current_navigation_index); |
| 337 EXPECT_TRUE(extension_app_id == tab->extension_app_id); | 337 EXPECT_TRUE(extension_app_id == tab->extension_app_id); |
| 338 } | 338 } |
| 339 | 339 |
| 340 // Make sure we persist entries to disk that have post data. | 340 // Make sure we persist entries to disk that have post data. |
| 341 TEST_F(PersistentTabRestoreServiceTest, DontPersistPostData) { | 341 TEST_F(PersistentTabRestoreServiceTest, DontPersistPostData) { |
| 342 AddThreeNavigations(); | 342 AddThreeNavigations(); |
| 343 controller().GetEntryAtIndex(0)->SetHasPostData(true); | 343 controller().GetEntryAtIndex(0)->SetHasPostData(true); |
| 344 controller().GetEntryAtIndex(1)->SetHasPostData(true); | 344 controller().GetEntryAtIndex(1)->SetHasPostData(true); |
| 345 controller().GetEntryAtIndex(2)->SetHasPostData(true); | 345 controller().GetEntryAtIndex(2)->SetHasPostData(true); |
| 346 | 346 |
| 347 // Have the service record the tab. | 347 // Have the service record the tab. |
| 348 service_->CreateHistoricalTab(live_tab(), -1); | 348 service_->CreateHistoricalTab(live_tab(), -1); |
| 349 ASSERT_EQ(1U, service_->entries().size()); | 349 ASSERT_EQ(1U, service_->entries().size()); |
| 350 | 350 |
| 351 // Recreate the service and have it load the tabs. | 351 // Recreate the service and have it load the tabs. |
| 352 RecreateService(); | 352 RecreateService(); |
| 353 | 353 |
| 354 // One entry should be created. | 354 // One entry should be created. |
| 355 ASSERT_EQ(1U, service_->entries().size()); | 355 ASSERT_EQ(1U, service_->entries().size()); |
| 356 | 356 |
| 357 const sessions::TabRestoreService::Entry* restored_entry = | 357 const sessions::TabRestoreService::Entry* restored_entry = |
| 358 service_->entries().front(); | 358 service_->entries().front().get(); |
| 359 ASSERT_EQ(sessions::TabRestoreService::TAB, restored_entry->type); | 359 ASSERT_EQ(sessions::TabRestoreService::TAB, restored_entry->type); |
| 360 | 360 |
| 361 const Tab* restored_tab = | 361 const Tab* restored_tab = |
| 362 static_cast<const Tab*>(restored_entry); | 362 static_cast<const Tab*>(restored_entry); |
| 363 // There should be 3 navs. | 363 // There should be 3 navs. |
| 364 ASSERT_EQ(3U, restored_tab->navigations.size()); | 364 ASSERT_EQ(3U, restored_tab->navigations.size()); |
| 365 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(), | 365 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(), |
| 366 restored_tab->timestamp.ToInternalValue()); | 366 restored_tab->timestamp.ToInternalValue()); |
| 367 } | 367 } |
| 368 | 368 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 395 EXPECT_FALSE(service_->IsLoaded()); | 395 EXPECT_FALSE(service_->IsLoaded()); |
| 396 | 396 |
| 397 TestTabRestoreServiceObserver observer; | 397 TestTabRestoreServiceObserver observer; |
| 398 service_->AddObserver(&observer); | 398 service_->AddObserver(&observer); |
| 399 SynchronousLoadTabsFromLastSession(); | 399 SynchronousLoadTabsFromLastSession(); |
| 400 EXPECT_TRUE(observer.got_loaded()); | 400 EXPECT_TRUE(observer.got_loaded()); |
| 401 service_->RemoveObserver(&observer); | 401 service_->RemoveObserver(&observer); |
| 402 | 402 |
| 403 // Make sure we get back one entry with one tab whose url is url1. | 403 // Make sure we get back one entry with one tab whose url is url1. |
| 404 ASSERT_EQ(1U, service_->entries().size()); | 404 ASSERT_EQ(1U, service_->entries().size()); |
| 405 sessions::TabRestoreService::Entry* entry2 = service_->entries().front(); | 405 sessions::TabRestoreService::Entry* entry2 = |
| 406 service_->entries().front().get(); |
| 406 ASSERT_EQ(sessions::TabRestoreService::WINDOW, entry2->type); | 407 ASSERT_EQ(sessions::TabRestoreService::WINDOW, entry2->type); |
| 407 sessions::TabRestoreService::Window* window = | 408 sessions::TabRestoreService::Window* window = |
| 408 static_cast<sessions::TabRestoreService::Window*>(entry2); | 409 static_cast<sessions::TabRestoreService::Window*>(entry2); |
| 409 ASSERT_EQ(1U, window->tabs.size()); | 410 ASSERT_EQ(1U, window->tabs.size()); |
| 410 EXPECT_EQ(0, window->timestamp.ToInternalValue()); | 411 EXPECT_EQ(0, window->timestamp.ToInternalValue()); |
| 411 EXPECT_EQ(0, window->selected_tab_index); | 412 EXPECT_EQ(0, window->selected_tab_index); |
| 412 ASSERT_EQ(1U, window->tabs[0].navigations.size()); | 413 ASSERT_EQ(1U, window->tabs[0]->navigations.size()); |
| 413 EXPECT_EQ(0, window->tabs[0].current_navigation_index); | 414 EXPECT_EQ(0, window->tabs[0]->current_navigation_index); |
| 414 EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue()); | 415 EXPECT_EQ(0, window->tabs[0]->timestamp.ToInternalValue()); |
| 415 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url()); | 416 EXPECT_TRUE(url1_ == window->tabs[0]->navigations[0].virtual_url()); |
| 416 } | 417 } |
| 417 | 418 |
| 418 // Makes sure we don't attempt to load previous sessions after a restore. | 419 // Makes sure we don't attempt to load previous sessions after a restore. |
| 419 TEST_F(PersistentTabRestoreServiceTest, DontLoadAfterRestore) { | 420 TEST_F(PersistentTabRestoreServiceTest, DontLoadAfterRestore) { |
| 420 CreateSessionServiceWithOneWindow(false); | 421 CreateSessionServiceWithOneWindow(false); |
| 421 | 422 |
| 422 SessionServiceFactory::GetForProfile(profile())-> | 423 SessionServiceFactory::GetForProfile(profile())-> |
| 423 MoveCurrentSessionToLastSession(); | 424 MoveCurrentSessionToLastSession(); |
| 424 | 425 |
| 425 profile()->set_restored_last_session(true); | 426 profile()->set_restored_last_session(true); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 454 AddThreeNavigations(); | 455 AddThreeNavigations(); |
| 455 | 456 |
| 456 service_->CreateHistoricalTab(live_tab(), -1); | 457 service_->CreateHistoricalTab(live_tab(), -1); |
| 457 | 458 |
| 458 RecreateService(); | 459 RecreateService(); |
| 459 | 460 |
| 460 // We should get back two entries, one from the previous session and one from | 461 // We should get back two entries, one from the previous session and one from |
| 461 // the tab restore service. The previous session entry should be first. | 462 // the tab restore service. The previous session entry should be first. |
| 462 ASSERT_EQ(2U, service_->entries().size()); | 463 ASSERT_EQ(2U, service_->entries().size()); |
| 463 // The first entry should come from the session service. | 464 // The first entry should come from the session service. |
| 464 sessions::TabRestoreService::Entry* entry = service_->entries().front(); | 465 sessions::TabRestoreService::Entry* entry = service_->entries().front().get(); |
| 465 ASSERT_EQ(sessions::TabRestoreService::WINDOW, entry->type); | 466 ASSERT_EQ(sessions::TabRestoreService::WINDOW, entry->type); |
| 466 sessions::TabRestoreService::Window* window = | 467 sessions::TabRestoreService::Window* window = |
| 467 static_cast<sessions::TabRestoreService::Window*>(entry); | 468 static_cast<sessions::TabRestoreService::Window*>(entry); |
| 468 ASSERT_EQ(1U, window->tabs.size()); | 469 ASSERT_EQ(1U, window->tabs.size()); |
| 469 EXPECT_EQ(0, window->selected_tab_index); | 470 EXPECT_EQ(0, window->selected_tab_index); |
| 470 EXPECT_EQ(0, window->timestamp.ToInternalValue()); | 471 EXPECT_EQ(0, window->timestamp.ToInternalValue()); |
| 471 ASSERT_EQ(1U, window->tabs[0].navigations.size()); | 472 ASSERT_EQ(1U, window->tabs[0]->navigations.size()); |
| 472 EXPECT_EQ(0, window->tabs[0].current_navigation_index); | 473 EXPECT_EQ(0, window->tabs[0]->current_navigation_index); |
| 473 EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue()); | 474 EXPECT_EQ(0, window->tabs[0]->timestamp.ToInternalValue()); |
| 474 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url()); | 475 EXPECT_TRUE(url1_ == window->tabs[0]->navigations[0].virtual_url()); |
| 475 | 476 |
| 476 // Then the closed tab. | 477 // Then the closed tab. |
| 477 entry = *(++service_->entries().begin()); | 478 entry = (++service_->entries().begin())->get(); |
| 478 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); | 479 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); |
| 479 Tab* tab = static_cast<Tab*>(entry); | 480 Tab* tab = static_cast<Tab*>(entry); |
| 480 ASSERT_FALSE(tab->pinned); | 481 ASSERT_FALSE(tab->pinned); |
| 481 ASSERT_EQ(3U, tab->navigations.size()); | 482 ASSERT_EQ(3U, tab->navigations.size()); |
| 482 EXPECT_EQ(2, tab->current_navigation_index); | 483 EXPECT_EQ(2, tab->current_navigation_index); |
| 483 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(), | 484 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(), |
| 484 tab->timestamp.ToInternalValue()); | 485 tab->timestamp.ToInternalValue()); |
| 485 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url()); | 486 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url()); |
| 486 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url()); | 487 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url()); |
| 487 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url()); | 488 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url()); |
| 488 } | 489 } |
| 489 | 490 |
| 490 // Make sure pinned state is correctly loaded from session service. | 491 // Make sure pinned state is correctly loaded from session service. |
| 491 TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSessionAndTabsPinned) { | 492 TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSessionAndTabsPinned) { |
| 492 CreateSessionServiceWithOneWindow(true); | 493 CreateSessionServiceWithOneWindow(true); |
| 493 | 494 |
| 494 SessionServiceFactory::GetForProfile(profile())-> | 495 SessionServiceFactory::GetForProfile(profile())-> |
| 495 MoveCurrentSessionToLastSession(); | 496 MoveCurrentSessionToLastSession(); |
| 496 | 497 |
| 497 AddThreeNavigations(); | 498 AddThreeNavigations(); |
| 498 | 499 |
| 499 service_->CreateHistoricalTab(live_tab(), -1); | 500 service_->CreateHistoricalTab(live_tab(), -1); |
| 500 | 501 |
| 501 RecreateService(); | 502 RecreateService(); |
| 502 | 503 |
| 503 // We should get back two entries, one from the previous session and one from | 504 // We should get back two entries, one from the previous session and one from |
| 504 // the tab restore service. The previous session entry should be first. | 505 // the tab restore service. The previous session entry should be first. |
| 505 ASSERT_EQ(2U, service_->entries().size()); | 506 ASSERT_EQ(2U, service_->entries().size()); |
| 506 // The first entry should come from the session service. | 507 // The first entry should come from the session service. |
| 507 sessions::TabRestoreService::Entry* entry = service_->entries().front(); | 508 sessions::TabRestoreService::Entry* entry = service_->entries().front().get(); |
| 508 ASSERT_EQ(sessions::TabRestoreService::WINDOW, entry->type); | 509 ASSERT_EQ(sessions::TabRestoreService::WINDOW, entry->type); |
| 509 sessions::TabRestoreService::Window* window = | 510 sessions::TabRestoreService::Window* window = |
| 510 static_cast<sessions::TabRestoreService::Window*>(entry); | 511 static_cast<sessions::TabRestoreService::Window*>(entry); |
| 511 ASSERT_EQ(1U, window->tabs.size()); | 512 ASSERT_EQ(1U, window->tabs.size()); |
| 512 EXPECT_EQ(0, window->selected_tab_index); | 513 EXPECT_EQ(0, window->selected_tab_index); |
| 513 EXPECT_TRUE(window->tabs[0].pinned); | 514 EXPECT_TRUE(window->tabs[0]->pinned); |
| 514 ASSERT_EQ(1U, window->tabs[0].navigations.size()); | 515 ASSERT_EQ(1U, window->tabs[0]->navigations.size()); |
| 515 EXPECT_EQ(0, window->tabs[0].current_navigation_index); | 516 EXPECT_EQ(0, window->tabs[0]->current_navigation_index); |
| 516 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url()); | 517 EXPECT_TRUE(url1_ == window->tabs[0]->navigations[0].virtual_url()); |
| 517 | 518 |
| 518 // Then the closed tab. | 519 // Then the closed tab. |
| 519 entry = *(++service_->entries().begin()); | 520 entry = (++service_->entries().begin())->get(); |
| 520 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); | 521 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); |
| 521 Tab* tab = static_cast<Tab*>(entry); | 522 Tab* tab = static_cast<Tab*>(entry); |
| 522 ASSERT_FALSE(tab->pinned); | 523 ASSERT_FALSE(tab->pinned); |
| 523 ASSERT_EQ(3U, tab->navigations.size()); | 524 ASSERT_EQ(3U, tab->navigations.size()); |
| 524 EXPECT_EQ(2, tab->current_navigation_index); | 525 EXPECT_EQ(2, tab->current_navigation_index); |
| 525 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url()); | 526 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url()); |
| 526 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url()); | 527 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url()); |
| 527 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url()); | 528 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url()); |
| 528 } | 529 } |
| 529 | 530 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 542 | 543 |
| 543 service_->CreateHistoricalTab(live_tab(), -1); | 544 service_->CreateHistoricalTab(live_tab(), -1); |
| 544 | 545 |
| 545 RecreateService(); | 546 RecreateService(); |
| 546 | 547 |
| 547 // We should get back kMaxEntries entries. We added more, but | 548 // We should get back kMaxEntries entries. We added more, but |
| 548 // TabRestoreService only allows up to kMaxEntries. | 549 // TabRestoreService only allows up to kMaxEntries. |
| 549 ASSERT_EQ(kMaxEntries, service_->entries().size()); | 550 ASSERT_EQ(kMaxEntries, service_->entries().size()); |
| 550 | 551 |
| 551 // The first entry should come from the session service. | 552 // The first entry should come from the session service. |
| 552 sessions::TabRestoreService::Entry* entry = service_->entries().front(); | 553 sessions::TabRestoreService::Entry* entry = service_->entries().front().get(); |
| 553 ASSERT_EQ(sessions::TabRestoreService::WINDOW, entry->type); | 554 ASSERT_EQ(sessions::TabRestoreService::WINDOW, entry->type); |
| 554 sessions::TabRestoreService::Window* window = | 555 sessions::TabRestoreService::Window* window = |
| 555 static_cast<sessions::TabRestoreService::Window*>(entry); | 556 static_cast<sessions::TabRestoreService::Window*>(entry); |
| 556 ASSERT_EQ(1U, window->tabs.size()); | 557 ASSERT_EQ(1U, window->tabs.size()); |
| 557 EXPECT_EQ(0, window->selected_tab_index); | 558 EXPECT_EQ(0, window->selected_tab_index); |
| 558 EXPECT_EQ(0, window->timestamp.ToInternalValue()); | 559 EXPECT_EQ(0, window->timestamp.ToInternalValue()); |
| 559 ASSERT_EQ(1U, window->tabs[0].navigations.size()); | 560 ASSERT_EQ(1U, window->tabs[0]->navigations.size()); |
| 560 EXPECT_EQ(0, window->tabs[0].current_navigation_index); | 561 EXPECT_EQ(0, window->tabs[0]->current_navigation_index); |
| 561 EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue()); | 562 EXPECT_EQ(0, window->tabs[0]->timestamp.ToInternalValue()); |
| 562 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url()); | 563 EXPECT_TRUE(url1_ == window->tabs[0]->navigations[0].virtual_url()); |
| 563 } | 564 } |
| 564 | 565 |
| 565 // Makes sure we restore timestamps correctly. | 566 // Makes sure we restore timestamps correctly. |
| 566 TEST_F(PersistentTabRestoreServiceTest, TimestampSurvivesRestore) { | 567 TEST_F(PersistentTabRestoreServiceTest, TimestampSurvivesRestore) { |
| 567 base::Time tab_timestamp(base::Time::FromInternalValue(123456789)); | 568 base::Time tab_timestamp(base::Time::FromInternalValue(123456789)); |
| 568 | 569 |
| 569 AddThreeNavigations(); | 570 AddThreeNavigations(); |
| 570 | 571 |
| 571 // Have the service record the tab. | 572 // Have the service record the tab. |
| 572 service_->CreateHistoricalTab(live_tab(), -1); | 573 service_->CreateHistoricalTab(live_tab(), -1); |
| 573 | 574 |
| 574 // Make sure an entry was created. | 575 // Make sure an entry was created. |
| 575 ASSERT_EQ(1U, service_->entries().size()); | 576 ASSERT_EQ(1U, service_->entries().size()); |
| 576 | 577 |
| 577 // Make sure the entry matches. | 578 // Make sure the entry matches. |
| 578 std::vector<SerializedNavigationEntry> old_navigations; | 579 std::vector<SerializedNavigationEntry> old_navigations; |
| 579 { | 580 { |
| 580 // |entry|/|tab| doesn't survive after RecreateService(). | 581 // |entry|/|tab| doesn't survive after RecreateService(). |
| 581 sessions::TabRestoreService::Entry* entry = service_->entries().front(); | 582 sessions::TabRestoreService::Entry* entry = |
| 583 service_->entries().front().get(); |
| 582 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); | 584 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); |
| 583 Tab* tab = static_cast<Tab*>(entry); | 585 Tab* tab = static_cast<Tab*>(entry); |
| 584 tab->timestamp = tab_timestamp; | 586 tab->timestamp = tab_timestamp; |
| 585 old_navigations = tab->navigations; | 587 old_navigations = tab->navigations; |
| 586 } | 588 } |
| 587 | 589 |
| 588 EXPECT_EQ(3U, old_navigations.size()); | 590 EXPECT_EQ(3U, old_navigations.size()); |
| 589 for (size_t i = 0; i < old_navigations.size(); ++i) { | 591 for (size_t i = 0; i < old_navigations.size(); ++i) { |
| 590 EXPECT_FALSE(old_navigations[i].timestamp().is_null()); | 592 EXPECT_FALSE(old_navigations[i].timestamp().is_null()); |
| 591 } | 593 } |
| 592 | 594 |
| 593 // Set this, otherwise previous session won't be loaded. | 595 // Set this, otherwise previous session won't be loaded. |
| 594 profile()->set_last_session_exited_cleanly(false); | 596 profile()->set_last_session_exited_cleanly(false); |
| 595 | 597 |
| 596 RecreateService(); | 598 RecreateService(); |
| 597 | 599 |
| 598 // One entry should be created. | 600 // One entry should be created. |
| 599 ASSERT_EQ(1U, service_->entries().size()); | 601 ASSERT_EQ(1U, service_->entries().size()); |
| 600 | 602 |
| 601 // And verify the entry. | 603 // And verify the entry. |
| 602 sessions::TabRestoreService::Entry* restored_entry = | 604 sessions::TabRestoreService::Entry* restored_entry = |
| 603 service_->entries().front(); | 605 service_->entries().front().get(); |
| 604 ASSERT_EQ(sessions::TabRestoreService::TAB, restored_entry->type); | 606 ASSERT_EQ(sessions::TabRestoreService::TAB, restored_entry->type); |
| 605 Tab* restored_tab = | 607 Tab* restored_tab = |
| 606 static_cast<Tab*>(restored_entry); | 608 static_cast<Tab*>(restored_entry); |
| 607 EXPECT_EQ(tab_timestamp.ToInternalValue(), | 609 EXPECT_EQ(tab_timestamp.ToInternalValue(), |
| 608 restored_tab->timestamp.ToInternalValue()); | 610 restored_tab->timestamp.ToInternalValue()); |
| 609 ASSERT_EQ(old_navigations.size(), restored_tab->navigations.size()); | 611 ASSERT_EQ(old_navigations.size(), restored_tab->navigations.size()); |
| 610 for (size_t i = 0; i < restored_tab->navigations.size(); ++i) { | 612 for (size_t i = 0; i < restored_tab->navigations.size(); ++i) { |
| 611 EXPECT_EQ(old_navigations[i].timestamp(), | 613 EXPECT_EQ(old_navigations[i].timestamp(), |
| 612 restored_tab->navigations[i].timestamp()); | 614 restored_tab->navigations[i].timestamp()); |
| 613 } | 615 } |
| 614 } | 616 } |
| 615 | 617 |
| 616 // Makes sure we restore status codes correctly. | 618 // Makes sure we restore status codes correctly. |
| 617 TEST_F(PersistentTabRestoreServiceTest, StatusCodesSurviveRestore) { | 619 TEST_F(PersistentTabRestoreServiceTest, StatusCodesSurviveRestore) { |
| 618 AddThreeNavigations(); | 620 AddThreeNavigations(); |
| 619 | 621 |
| 620 // Have the service record the tab. | 622 // Have the service record the tab. |
| 621 service_->CreateHistoricalTab(live_tab(), -1); | 623 service_->CreateHistoricalTab(live_tab(), -1); |
| 622 | 624 |
| 623 // Make sure an entry was created. | 625 // Make sure an entry was created. |
| 624 ASSERT_EQ(1U, service_->entries().size()); | 626 ASSERT_EQ(1U, service_->entries().size()); |
| 625 | 627 |
| 626 // Make sure the entry matches. | 628 // Make sure the entry matches. |
| 627 std::vector<sessions::SerializedNavigationEntry> old_navigations; | 629 std::vector<sessions::SerializedNavigationEntry> old_navigations; |
| 628 { | 630 { |
| 629 // |entry|/|tab| doesn't survive after RecreateService(). | 631 // |entry|/|tab| doesn't survive after RecreateService(). |
| 630 sessions::TabRestoreService::Entry* entry = service_->entries().front(); | 632 sessions::TabRestoreService::Entry* entry = |
| 633 service_->entries().front().get(); |
| 631 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); | 634 ASSERT_EQ(sessions::TabRestoreService::TAB, entry->type); |
| 632 Tab* tab = static_cast<Tab*>(entry); | 635 Tab* tab = static_cast<Tab*>(entry); |
| 633 old_navigations = tab->navigations; | 636 old_navigations = tab->navigations; |
| 634 } | 637 } |
| 635 | 638 |
| 636 EXPECT_EQ(3U, old_navigations.size()); | 639 EXPECT_EQ(3U, old_navigations.size()); |
| 637 for (size_t i = 0; i < old_navigations.size(); ++i) { | 640 for (size_t i = 0; i < old_navigations.size(); ++i) { |
| 638 EXPECT_EQ(200, old_navigations[i].http_status_code()); | 641 EXPECT_EQ(200, old_navigations[i].http_status_code()); |
| 639 } | 642 } |
| 640 | 643 |
| 641 // Set this, otherwise previous session won't be loaded. | 644 // Set this, otherwise previous session won't be loaded. |
| 642 profile()->set_last_session_exited_cleanly(false); | 645 profile()->set_last_session_exited_cleanly(false); |
| 643 | 646 |
| 644 RecreateService(); | 647 RecreateService(); |
| 645 | 648 |
| 646 // One entry should be created. | 649 // One entry should be created. |
| 647 ASSERT_EQ(1U, service_->entries().size()); | 650 ASSERT_EQ(1U, service_->entries().size()); |
| 648 | 651 |
| 649 // And verify the entry. | 652 // And verify the entry. |
| 650 sessions::TabRestoreService::Entry* restored_entry = | 653 sessions::TabRestoreService::Entry* restored_entry = |
| 651 service_->entries().front(); | 654 service_->entries().front().get(); |
| 652 ASSERT_EQ(sessions::TabRestoreService::TAB, restored_entry->type); | 655 ASSERT_EQ(sessions::TabRestoreService::TAB, restored_entry->type); |
| 653 Tab* restored_tab = | 656 Tab* restored_tab = |
| 654 static_cast<Tab*>(restored_entry); | 657 static_cast<Tab*>(restored_entry); |
| 655 ASSERT_EQ(old_navigations.size(), restored_tab->navigations.size()); | 658 ASSERT_EQ(old_navigations.size(), restored_tab->navigations.size()); |
| 656 for (size_t i = 0; i < restored_tab->navigations.size(); ++i) { | 659 for (size_t i = 0; i < restored_tab->navigations.size(); ++i) { |
| 657 EXPECT_EQ(200, restored_tab->navigations[i].http_status_code()); | 660 EXPECT_EQ(200, restored_tab->navigations[i].http_status_code()); |
| 658 } | 661 } |
| 659 } | 662 } |
| 660 | 663 |
| 661 TEST_F(PersistentTabRestoreServiceTest, PruneEntries) { | 664 TEST_F(PersistentTabRestoreServiceTest, PruneEntries) { |
| 662 service_->ClearEntries(); | 665 service_->ClearEntries(); |
| 663 ASSERT_TRUE(service_->entries().empty()); | 666 ASSERT_TRUE(service_->entries().empty()); |
| 664 | 667 |
| 665 const size_t max_entries = kMaxEntries; | 668 const size_t max_entries = kMaxEntries; |
| 666 for (size_t i = 0; i < max_entries + 5; i++) { | 669 for (size_t i = 0; i < max_entries + 5; i++) { |
| 667 SerializedNavigationEntry navigation = | 670 SerializedNavigationEntry navigation = |
| 668 SerializedNavigationEntryTestHelper::CreateNavigation( | 671 SerializedNavigationEntryTestHelper::CreateNavigation( |
| 669 base::StringPrintf("http://%d", static_cast<int>(i)), | 672 base::StringPrintf("http://%d", static_cast<int>(i)), |
| 670 base::SizeTToString(i)); | 673 base::SizeTToString(i)); |
| 671 | 674 |
| 672 Tab* tab = new Tab(); | 675 auto tab = base::MakeUnique<Tab>(); |
| 673 tab->navigations.push_back(navigation); | 676 tab->navigations.push_back(navigation); |
| 674 tab->current_navigation_index = 0; | 677 tab->current_navigation_index = 0; |
| 675 | 678 |
| 676 mutable_entries()->push_back(tab); | 679 mutable_entries()->push_back(std::move(tab)); |
| 677 } | 680 } |
| 678 | 681 |
| 679 // Only keep kMaxEntries around. | 682 // Only keep kMaxEntries around. |
| 680 EXPECT_EQ(max_entries + 5, service_->entries().size()); | 683 EXPECT_EQ(max_entries + 5, service_->entries().size()); |
| 681 PruneEntries(); | 684 PruneEntries(); |
| 682 EXPECT_EQ(max_entries, service_->entries().size()); | 685 EXPECT_EQ(max_entries, service_->entries().size()); |
| 683 // Pruning again does nothing. | 686 // Pruning again does nothing. |
| 684 PruneEntries(); | 687 PruneEntries(); |
| 685 EXPECT_EQ(max_entries, service_->entries().size()); | 688 EXPECT_EQ(max_entries, service_->entries().size()); |
| 686 | 689 |
| 687 // Prune older first. | 690 // Prune older first. |
| 688 const char kRecentUrl[] = "http://recent"; | 691 const char kRecentUrl[] = "http://recent"; |
| 689 SerializedNavigationEntry navigation = | 692 SerializedNavigationEntry navigation = |
| 690 SerializedNavigationEntryTestHelper::CreateNavigation(kRecentUrl, | 693 SerializedNavigationEntryTestHelper::CreateNavigation(kRecentUrl, |
| 691 "Most recent"); | 694 "Most recent"); |
| 692 Tab* tab = new Tab(); | 695 auto tab = base::MakeUnique<Tab>(); |
| 693 tab->navigations.push_back(navigation); | 696 tab->navigations.push_back(navigation); |
| 694 tab->current_navigation_index = 0; | 697 tab->current_navigation_index = 0; |
| 695 mutable_entries()->push_front(tab); | 698 mutable_entries()->push_front(std::move(tab)); |
| 696 EXPECT_EQ(max_entries + 1, service_->entries().size()); | 699 EXPECT_EQ(max_entries + 1, service_->entries().size()); |
| 697 PruneEntries(); | 700 PruneEntries(); |
| 698 EXPECT_EQ(max_entries, service_->entries().size()); | 701 EXPECT_EQ(max_entries, service_->entries().size()); |
| 699 EXPECT_EQ(GURL(kRecentUrl), | 702 EXPECT_EQ(GURL(kRecentUrl), static_cast<Tab&>(*service_->entries().front()) |
| 700 static_cast<Tab*>(service_->entries().front())-> | 703 .navigations[0] |
| 701 navigations[0].virtual_url()); | 704 .virtual_url()); |
| 702 | 705 |
| 703 // Ignore NTPs. | 706 // Ignore NTPs. |
| 704 navigation = SerializedNavigationEntryTestHelper::CreateNavigation( | 707 navigation = SerializedNavigationEntryTestHelper::CreateNavigation( |
| 705 chrome::kChromeUINewTabURL, "New tab"); | 708 chrome::kChromeUINewTabURL, "New tab"); |
| 706 | 709 |
| 707 tab = new Tab(); | 710 tab = base::MakeUnique<Tab>(); |
| 708 tab->navigations.push_back(navigation); | 711 tab->navigations.push_back(navigation); |
| 709 tab->current_navigation_index = 0; | 712 tab->current_navigation_index = 0; |
| 710 mutable_entries()->push_front(tab); | 713 mutable_entries()->push_front(std::move(tab)); |
| 711 | 714 |
| 712 EXPECT_EQ(max_entries + 1, service_->entries().size()); | 715 EXPECT_EQ(max_entries + 1, service_->entries().size()); |
| 713 PruneEntries(); | 716 PruneEntries(); |
| 714 EXPECT_EQ(max_entries, service_->entries().size()); | 717 EXPECT_EQ(max_entries, service_->entries().size()); |
| 715 EXPECT_EQ(GURL(kRecentUrl), | 718 EXPECT_EQ(GURL(kRecentUrl), static_cast<Tab&>(*service_->entries().front()) |
| 716 static_cast<Tab*>(service_->entries().front())-> | 719 .navigations[0] |
| 717 navigations[0].virtual_url()); | 720 .virtual_url()); |
| 718 | 721 |
| 719 // Don't prune pinned NTPs. | 722 // Don't prune pinned NTPs. |
| 720 tab = new Tab(); | 723 tab = base::MakeUnique<Tab>(); |
| 721 tab->pinned = true; | 724 tab->pinned = true; |
| 722 tab->current_navigation_index = 0; | 725 tab->current_navigation_index = 0; |
| 723 tab->navigations.push_back(navigation); | 726 tab->navigations.push_back(navigation); |
| 724 mutable_entries()->push_front(tab); | 727 mutable_entries()->push_front(std::move(tab)); |
| 725 EXPECT_EQ(max_entries + 1, service_->entries().size()); | 728 EXPECT_EQ(max_entries + 1, service_->entries().size()); |
| 726 PruneEntries(); | 729 PruneEntries(); |
| 727 EXPECT_EQ(max_entries, service_->entries().size()); | 730 EXPECT_EQ(max_entries, service_->entries().size()); |
| 728 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), | 731 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), |
| 729 static_cast<Tab*>(service_->entries().front())-> | 732 static_cast<Tab*>(service_->entries().front().get()) |
| 730 navigations[0].virtual_url()); | 733 ->navigations[0] |
| 734 .virtual_url()); |
| 731 | 735 |
| 732 // Don't prune NTPs that have multiple navigations. | 736 // Don't prune NTPs that have multiple navigations. |
| 733 // (Erase the last NTP first.) | 737 // (Erase the last NTP first.) |
| 734 delete service_->entries().front(); | |
| 735 mutable_entries()->erase(mutable_entries()->begin()); | 738 mutable_entries()->erase(mutable_entries()->begin()); |
| 736 tab = new Tab(); | 739 tab = base::MakeUnique<Tab>(); |
| 737 tab->current_navigation_index = 1; | 740 tab->current_navigation_index = 1; |
| 738 tab->navigations.push_back(navigation); | 741 tab->navigations.push_back(navigation); |
| 739 tab->navigations.push_back(navigation); | 742 tab->navigations.push_back(navigation); |
| 740 mutable_entries()->push_front(tab); | 743 mutable_entries()->push_front(std::move(tab)); |
| 741 EXPECT_EQ(max_entries, service_->entries().size()); | 744 EXPECT_EQ(max_entries, service_->entries().size()); |
| 742 PruneEntries(); | 745 PruneEntries(); |
| 743 EXPECT_EQ(max_entries, service_->entries().size()); | 746 EXPECT_EQ(max_entries, service_->entries().size()); |
| 744 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), | 747 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), |
| 745 static_cast<Tab*>(service_->entries().front())-> | 748 static_cast<Tab*>(service_->entries().front().get()) |
| 746 navigations[1].virtual_url()); | 749 ->navigations[1] |
| 750 .virtual_url()); |
| 747 } | 751 } |
| 748 | 752 |
| 749 // Regression test for crbug.com/106082 | 753 // Regression test for crbug.com/106082 |
| 750 TEST_F(PersistentTabRestoreServiceTest, PruneIsCalled) { | 754 TEST_F(PersistentTabRestoreServiceTest, PruneIsCalled) { |
| 751 CreateSessionServiceWithOneWindow(false); | 755 CreateSessionServiceWithOneWindow(false); |
| 752 | 756 |
| 753 SessionServiceFactory::GetForProfile(profile())-> | 757 SessionServiceFactory::GetForProfile(profile())-> |
| 754 MoveCurrentSessionToLastSession(); | 758 MoveCurrentSessionToLastSession(); |
| 755 | 759 |
| 756 profile()->set_restored_last_session(true); | 760 profile()->set_restored_last_session(true); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 780 | 784 |
| 781 EXPECT_FALSE(service_->IsLoaded()); | 785 EXPECT_FALSE(service_->IsLoaded()); |
| 782 TestTabRestoreServiceObserver observer; | 786 TestTabRestoreServiceObserver observer; |
| 783 service_->AddObserver(&observer); | 787 service_->AddObserver(&observer); |
| 784 EXPECT_EQ(max_entries, service_->entries().size()); | 788 EXPECT_EQ(max_entries, service_->entries().size()); |
| 785 SynchronousLoadTabsFromLastSession(); | 789 SynchronousLoadTabsFromLastSession(); |
| 786 EXPECT_TRUE(observer.got_loaded()); | 790 EXPECT_TRUE(observer.got_loaded()); |
| 787 EXPECT_TRUE(service_->IsLoaded()); | 791 EXPECT_TRUE(service_->IsLoaded()); |
| 788 service_->RemoveObserver(&observer); | 792 service_->RemoveObserver(&observer); |
| 789 } | 793 } |
| OLD | NEW |