Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "chrome/browser/android/offline_pages/prerendering_offliner.h" | 5 #include "chrome/browser/android/offline_pages/prerendering_offliner.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 } | 250 } |
| 251 | 251 |
| 252 void PrerenderingOfflinerTest::OnProgress(const SavePageRequest& request, | 252 void PrerenderingOfflinerTest::OnProgress(const SavePageRequest& request, |
| 253 int64_t bytes) {} | 253 int64_t bytes) {} |
| 254 | 254 |
| 255 void PrerenderingOfflinerTest::OnCancel(const SavePageRequest& request) { | 255 void PrerenderingOfflinerTest::OnCancel(const SavePageRequest& request) { |
| 256 DCHECK(!cancel_callback_called_); | 256 DCHECK(!cancel_callback_called_); |
| 257 cancel_callback_called_ = true; | 257 cancel_callback_called_ = true; |
| 258 } | 258 } |
| 259 | 259 |
| 260 TEST_F(PrerenderingOfflinerTest, DISABLED_LoadAndSaveBadUrl) { | 260 TEST_F(PrerenderingOfflinerTest, LoadAndSaveBadUrl) { |
| 261 base::Time creation_time = base::Time::Now(); | 261 base::Time creation_time = base::Time::Now(); |
| 262 SavePageRequest request( | 262 SavePageRequest request( |
| 263 kRequestId, kFileUrl, kClientId, creation_time, kUserRequested); | 263 kRequestId, kFileUrl, kClientId, creation_time, kUserRequested); |
| 264 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), | 264 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), |
| 265 progress_callback())); | 265 progress_callback())); |
| 266 EXPECT_TRUE(loader()->IsIdle()); | 266 EXPECT_TRUE(loader()->IsIdle()); |
| 267 } | 267 } |
| 268 | 268 |
| 269 TEST_F(PrerenderingOfflinerTest, DISABLED_LoadAndSavePrerenderingDisabled) { | 269 TEST_F(PrerenderingOfflinerTest, LoadAndSavePrerenderingDisabled) { |
| 270 base::Time creation_time = base::Time::Now(); | 270 base::Time creation_time = base::Time::Now(); |
| 271 SavePageRequest request( | 271 SavePageRequest request( |
| 272 kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); | 272 kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); |
| 273 loader()->DisablePrerendering(); | 273 loader()->DisablePrerendering(); |
| 274 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), | 274 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), |
| 275 progress_callback())); | 275 progress_callback())); |
| 276 EXPECT_TRUE(loader()->IsIdle()); | 276 EXPECT_TRUE(loader()->IsIdle()); |
| 277 } | 277 } |
| 278 | 278 |
| 279 TEST_F(PrerenderingOfflinerTest, | 279 TEST_F(PrerenderingOfflinerTest, |
| 280 DISABLED_LoadAndSaveBlockThirdPartyCookiesForCustomTabs) { | 280 LoadAndSaveBlockThirdPartyCookiesForCustomTabs) { |
| 281 base::Time creation_time = base::Time::Now(); | 281 base::Time creation_time = base::Time::Now(); |
| 282 ClientId custom_tabs_client_id("custom_tabs", "88"); | 282 ClientId custom_tabs_client_id("custom_tabs", "88"); |
| 283 SavePageRequest request(kRequestId, kHttpUrl, custom_tabs_client_id, | 283 SavePageRequest request(kRequestId, kHttpUrl, custom_tabs_client_id, |
| 284 creation_time, kUserRequested); | 284 creation_time, kUserRequested); |
| 285 profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, true); | 285 profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, true); |
| 286 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), | 286 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), |
| 287 progress_callback())); | 287 progress_callback())); |
| 288 EXPECT_TRUE(loader()->IsIdle()); | 288 EXPECT_TRUE(loader()->IsIdle()); |
| 289 } | 289 } |
| 290 | 290 |
| 291 TEST_F(PrerenderingOfflinerTest, | 291 TEST_F(PrerenderingOfflinerTest, |
| 292 DISABLED_LoadAndSaveBlockOnDisabledPrerendererForCustomTabs) { | 292 LoadAndSaveBlockOnDisabledPrerendererForCustomTabs) { |
| 293 base::Time creation_time = base::Time::Now(); | 293 base::Time creation_time = base::Time::Now(); |
| 294 ClientId custom_tabs_client_id("custom_tabs", "88"); | 294 ClientId custom_tabs_client_id("custom_tabs", "88"); |
| 295 SavePageRequest request(kRequestId, kHttpUrl, custom_tabs_client_id, | 295 SavePageRequest request(kRequestId, kHttpUrl, custom_tabs_client_id, |
| 296 creation_time, kUserRequested); | 296 creation_time, kUserRequested); |
| 297 profile()->GetPrefs()->SetInteger( | 297 profile()->GetPrefs()->SetInteger( |
| 298 prefs::kNetworkPredictionOptions, | 298 prefs::kNetworkPredictionOptions, |
| 299 chrome_browser_net::NETWORK_PREDICTION_NEVER); | 299 chrome_browser_net::NETWORK_PREDICTION_NEVER); |
| 300 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), | 300 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), |
| 301 progress_callback())); | 301 progress_callback())); |
| 302 EXPECT_TRUE(loader()->IsIdle()); | 302 EXPECT_TRUE(loader()->IsIdle()); |
| 303 } | 303 } |
| 304 | 304 |
| 305 TEST_F(PrerenderingOfflinerTest, DISABLED_LoadAndSaveLoadStartedButFails) { | 305 TEST_F(PrerenderingOfflinerTest, LoadAndSaveLoadStartedButFails) { |
| 306 base::Time creation_time = base::Time::Now(); | 306 base::Time creation_time = base::Time::Now(); |
| 307 SavePageRequest request( | 307 SavePageRequest request( |
| 308 kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); | 308 kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); |
| 309 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | 309 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), |
| 310 progress_callback())); | 310 progress_callback())); |
| 311 EXPECT_FALSE(loader()->IsIdle()); | 311 EXPECT_FALSE(loader()->IsIdle()); |
| 312 EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status()); | 312 EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status()); |
| 313 | 313 |
| 314 loader()->CompleteLoadingAsFailed(); | 314 loader()->CompleteLoadingAsFailed(); |
| 315 PumpLoop(); | 315 PumpLoop(); |
| 316 EXPECT_TRUE(completion_callback_called()); | 316 EXPECT_TRUE(completion_callback_called()); |
| 317 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED, request_status()); | 317 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED, request_status()); |
| 318 EXPECT_TRUE(loader()->IsIdle()); | 318 EXPECT_TRUE(loader()->IsIdle()); |
| 319 EXPECT_FALSE(SaveInProgress()); | 319 EXPECT_FALSE(SaveInProgress()); |
| 320 } | 320 } |
| 321 | 321 |
| 322 TEST_F(PrerenderingOfflinerTest, DISABLED_CancelWhenLoading) { | 322 TEST_F(PrerenderingOfflinerTest, CancelWhenLoading) { |
| 323 base::Time creation_time = base::Time::Now(); | 323 base::Time creation_time = base::Time::Now(); |
| 324 SavePageRequest request( | 324 SavePageRequest request( |
| 325 kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); | 325 kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); |
| 326 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | 326 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), |
| 327 progress_callback())); | 327 progress_callback())); |
| 328 EXPECT_FALSE(loader()->IsIdle()); | 328 EXPECT_FALSE(loader()->IsIdle()); |
| 329 | 329 |
| 330 offliner()->Cancel(cancel_callback()); | 330 offliner()->Cancel(cancel_callback()); |
| 331 PumpLoop(); | 331 PumpLoop(); |
| 332 EXPECT_TRUE(cancel_callback_called()); | 332 EXPECT_TRUE(cancel_callback_called()); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 427 | 427 |
| 428 loader()->CompleteLoadingAsCanceled(); | 428 loader()->CompleteLoadingAsCanceled(); |
| 429 PumpLoop(); | 429 PumpLoop(); |
| 430 EXPECT_TRUE(completion_callback_called()); | 430 EXPECT_TRUE(completion_callback_called()); |
| 431 EXPECT_EQ(Offliner::RequestStatus::LOADING_CANCELED, request_status()); | 431 EXPECT_EQ(Offliner::RequestStatus::LOADING_CANCELED, request_status()); |
| 432 EXPECT_FALSE(loader()->IsLoaded()); | 432 EXPECT_FALSE(loader()->IsLoaded()); |
| 433 // Note: save still in progress since it does not support canceling. | 433 // Note: save still in progress since it does not support canceling. |
| 434 EXPECT_TRUE(SaveInProgress()); | 434 EXPECT_TRUE(SaveInProgress()); |
| 435 } | 435 } |
| 436 | 436 |
| 437 TEST_F(PrerenderingOfflinerTest, | 437 TEST_F(PrerenderingOfflinerTest, ForegroundTransitionCancelsOnLowEndDevice) { |
| 438 DISABLED_ForegroundTransitionCancelsOnLowEndDevice) { | |
| 439 offliner()->SetLowEndDeviceForTesting(true); | 438 offliner()->SetLowEndDeviceForTesting(true); |
| 440 | 439 |
| 441 base::Time creation_time = base::Time::Now(); | 440 base::Time creation_time = base::Time::Now(); |
| 442 SavePageRequest request( | 441 SavePageRequest request( |
| 443 kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); | 442 kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); |
| 444 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | 443 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), |
| 445 progress_callback())); | 444 progress_callback())); |
| 446 EXPECT_FALSE(loader()->IsIdle()); | 445 EXPECT_FALSE(loader()->IsIdle()); |
| 447 | 446 |
| 448 offliner()->SetApplicationStateForTesting( | 447 offliner()->SetApplicationStateForTesting( |
| 449 base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES); | 448 base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES); |
| 450 | 449 |
| 450 // Wait until callback arrives before checking postconditions. | |
|
dewittj
2017/04/27 17:30:52
Which callback?
Pete Williamson
2017/04/27 18:09:19
Done.
| |
| 451 PumpLoop(); | |
| 452 | |
| 451 // Loading canceled on low-end device. | 453 // Loading canceled on low-end device. |
| 452 EXPECT_TRUE(loader()->IsIdle()); | 454 EXPECT_TRUE(loader()->IsIdle()); |
| 453 EXPECT_EQ(Offliner::RequestStatus::FOREGROUND_CANCELED, request_status()); | 455 EXPECT_EQ(Offliner::RequestStatus::FOREGROUND_CANCELED, request_status()); |
| 454 } | 456 } |
| 455 | 457 |
| 456 // TODO(crbug.com/712941): Flaky test. | 458 TEST_F(PrerenderingOfflinerTest, ForegroundTransitionIgnoredOnHighEndDevice) { |
| 457 TEST_F(PrerenderingOfflinerTest, | |
| 458 DISABLED_ForegroundTransitionIgnoredOnHighEndDevice) { | |
| 459 offliner()->SetLowEndDeviceForTesting(false); | 459 offliner()->SetLowEndDeviceForTesting(false); |
| 460 | 460 |
| 461 base::Time creation_time = base::Time::Now(); | 461 base::Time creation_time = base::Time::Now(); |
| 462 SavePageRequest request( | 462 SavePageRequest request( |
| 463 kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); | 463 kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); |
| 464 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | 464 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), |
| 465 progress_callback())); | 465 progress_callback())); |
| 466 EXPECT_FALSE(loader()->IsIdle()); | 466 EXPECT_FALSE(loader()->IsIdle()); |
| 467 | 467 |
| 468 offliner()->SetApplicationStateForTesting( | 468 offliner()->SetApplicationStateForTesting( |
| 469 base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES); | 469 base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES); |
| 470 | 470 |
| 471 // Wait until callback arrives before checking postconditions. | |
|
dewittj
2017/04/27 17:30:52
same
Pete Williamson
2017/04/27 18:09:19
Done.
| |
| 472 PumpLoop(); | |
| 473 | |
| 471 // Loader still loading since not low-end device. | 474 // Loader still loading since not low-end device. |
| 472 EXPECT_FALSE(loader()->IsIdle()); | 475 EXPECT_FALSE(loader()->IsIdle()); |
| 473 } | 476 } |
| 474 | 477 |
| 475 TEST_F(PrerenderingOfflinerTest, HandleTimeoutWithLowbarAndCompletedTriesMet) { | 478 TEST_F(PrerenderingOfflinerTest, HandleTimeoutWithLowbarAndCompletedTriesMet) { |
| 476 offliner()->SetLowEndDeviceForTesting(false); | 479 offliner()->SetLowEndDeviceForTesting(false); |
| 477 | 480 |
| 478 base::Time creation_time = base::Time::Now(); | 481 base::Time creation_time = base::Time::Now(); |
| 479 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | 482 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, |
| 480 kUserRequested); | 483 kUserRequested); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 501 kUserRequested); | 504 kUserRequested); |
| 502 request.set_completed_attempt_count(policy()->GetMaxCompletedTries() - 1); | 505 request.set_completed_attempt_count(policy()->GetMaxCompletedTries() - 1); |
| 503 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | 506 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), |
| 504 progress_callback())); | 507 progress_callback())); |
| 505 loader()->set_is_lowbar_met(true); | 508 loader()->set_is_lowbar_met(true); |
| 506 EXPECT_TRUE(offliner()->HandleTimeout(kRequestId)); | 509 EXPECT_TRUE(offliner()->HandleTimeout(kRequestId)); |
| 507 EXPECT_TRUE(loader()->start_snapshot_called()); | 510 EXPECT_TRUE(loader()->start_snapshot_called()); |
| 508 } | 511 } |
| 509 | 512 |
| 510 TEST_F(PrerenderingOfflinerTest, | 513 TEST_F(PrerenderingOfflinerTest, |
| 511 DISABLED_HandleTimeoutCompletedTriesMetWithoutLowbarMet) { | 514 HandleTimeoutCompletedTriesMetWithoutLowbarMet) { |
| 512 offliner()->SetLowEndDeviceForTesting(false); | 515 offliner()->SetLowEndDeviceForTesting(false); |
| 513 | 516 |
| 514 base::Time creation_time = base::Time::Now(); | 517 base::Time creation_time = base::Time::Now(); |
| 515 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | 518 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, |
| 516 kUserRequested); | 519 kUserRequested); |
| 517 request.set_completed_attempt_count(policy()->GetMaxCompletedTries() - 1); | 520 request.set_completed_attempt_count(policy()->GetMaxCompletedTries() - 1); |
| 518 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | 521 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), |
| 519 progress_callback())); | 522 progress_callback())); |
| 520 loader()->set_is_lowbar_met(false); | 523 loader()->set_is_lowbar_met(false); |
| 521 EXPECT_FALSE(offliner()->HandleTimeout(kRequestId)); | 524 EXPECT_FALSE(offliner()->HandleTimeout(kRequestId)); |
| 522 EXPECT_FALSE(loader()->start_snapshot_called()); | 525 EXPECT_FALSE(loader()->start_snapshot_called()); |
| 523 } | 526 } |
| 524 | 527 |
| 525 TEST_F(PrerenderingOfflinerTest, | 528 TEST_F(PrerenderingOfflinerTest, HandleTimeoutStartedTriesMetWithoutLowbarMet) { |
| 526 DISABLED_HandleTimeoutStartedTriesMetWithoutLowbarMet) { | |
| 527 offliner()->SetLowEndDeviceForTesting(false); | 529 offliner()->SetLowEndDeviceForTesting(false); |
| 528 | 530 |
| 529 base::Time creation_time = base::Time::Now(); | 531 base::Time creation_time = base::Time::Now(); |
| 530 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | 532 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, |
| 531 kUserRequested); | 533 kUserRequested); |
| 532 request.set_started_attempt_count(policy()->GetMaxStartedTries() - 1); | 534 request.set_started_attempt_count(policy()->GetMaxStartedTries() - 1); |
| 533 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | 535 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), |
| 534 progress_callback())); | 536 progress_callback())); |
| 535 loader()->set_is_lowbar_met(false); | 537 loader()->set_is_lowbar_met(false); |
| 536 EXPECT_FALSE(offliner()->HandleTimeout(kRequestId)); | 538 EXPECT_FALSE(offliner()->HandleTimeout(kRequestId)); |
| 537 EXPECT_FALSE(loader()->start_snapshot_called()); | 539 EXPECT_FALSE(loader()->start_snapshot_called()); |
| 538 } | 540 } |
| 539 | 541 |
| 540 TEST_F(PrerenderingOfflinerTest, HandleTimeoutWithLowbarAndStartedTriesMet) { | 542 TEST_F(PrerenderingOfflinerTest, HandleTimeoutWithLowbarAndStartedTriesMet) { |
| 541 offliner()->SetLowEndDeviceForTesting(false); | 543 offliner()->SetLowEndDeviceForTesting(false); |
| 542 | 544 |
| 543 base::Time creation_time = base::Time::Now(); | 545 base::Time creation_time = base::Time::Now(); |
| 544 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | 546 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, |
| 545 kUserRequested); | 547 kUserRequested); |
| 546 request.set_started_attempt_count(policy()->GetMaxStartedTries() - 1); | 548 request.set_started_attempt_count(policy()->GetMaxStartedTries() - 1); |
| 547 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | 549 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), |
| 548 progress_callback())); | 550 progress_callback())); |
| 549 loader()->set_is_lowbar_met(true); | 551 loader()->set_is_lowbar_met(true); |
| 550 EXPECT_TRUE(offliner()->HandleTimeout(kRequestId)); | 552 EXPECT_TRUE(offliner()->HandleTimeout(kRequestId)); |
| 551 EXPECT_TRUE(loader()->start_snapshot_called()); | 553 EXPECT_TRUE(loader()->start_snapshot_called()); |
| 552 } | 554 } |
| 553 | 555 |
| 554 TEST_F(PrerenderingOfflinerTest, DISABLED_HandleTimeoutWithOnlyLowbarMet) { | 556 TEST_F(PrerenderingOfflinerTest, HandleTimeoutWithOnlyLowbarMet) { |
| 555 offliner()->SetLowEndDeviceForTesting(false); | 557 offliner()->SetLowEndDeviceForTesting(false); |
| 556 | 558 |
| 557 base::Time creation_time = base::Time::Now(); | 559 base::Time creation_time = base::Time::Now(); |
| 558 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | 560 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, |
| 559 kUserRequested); | 561 kUserRequested); |
| 560 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | 562 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), |
| 561 progress_callback())); | 563 progress_callback())); |
| 562 loader()->set_is_lowbar_met(true); | 564 loader()->set_is_lowbar_met(true); |
| 563 EXPECT_FALSE(offliner()->HandleTimeout(kRequestId)); | 565 EXPECT_FALSE(offliner()->HandleTimeout(kRequestId)); |
| 564 EXPECT_FALSE(loader()->start_snapshot_called()); | 566 EXPECT_FALSE(loader()->start_snapshot_called()); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 611 PumpLoop(); | 613 PumpLoop(); |
| 612 EXPECT_EQ(Offliner::RequestStatus::SAVED, request_status()); | 614 EXPECT_EQ(Offliner::RequestStatus::SAVED, request_status()); |
| 613 | 615 |
| 614 // One extra part should be added if the flag is on. | 616 // One extra part should be added if the flag is on. |
| 615 content::MHTMLExtraParts* extra_parts = | 617 content::MHTMLExtraParts* extra_parts = |
| 616 content::MHTMLExtraParts::FromWebContents(loader()->web_contents()); | 618 content::MHTMLExtraParts::FromWebContents(loader()->web_contents()); |
| 617 EXPECT_EQ(extra_parts->size(), 1); | 619 EXPECT_EQ(extra_parts->size(), 1); |
| 618 } | 620 } |
| 619 | 621 |
| 620 } // namespace offline_pages | 622 } // namespace offline_pages |
| OLD | NEW |