Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: components/offline_pages/background/request_coordinator_unittest.cc

Issue 2431193003: [Offline Pages] Defines longer processing budget for immediate bg loads. (Closed)
Patch Set: Fixes tests wrt setting processing state Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "components/offline_pages/background/request_coordinator.h" 5 #include "components/offline_pages/background/request_coordinator.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 void GetRequestsDone(RequestQueue::GetRequestsResult result, 255 void GetRequestsDone(RequestQueue::GetRequestsResult result,
256 std::vector<std::unique_ptr<SavePageRequest>> requests); 256 std::vector<std::unique_ptr<SavePageRequest>> requests);
257 257
258 // Callback for removing requests. 258 // Callback for removing requests.
259 void RemoveRequestsDone(const MultipleItemStatuses& results); 259 void RemoveRequestsDone(const MultipleItemStatuses& results);
260 260
261 // Callback for getting request statuses. 261 // Callback for getting request statuses.
262 void GetQueuedRequestsDone( 262 void GetQueuedRequestsDone(
263 std::vector<std::unique_ptr<SavePageRequest>> requests); 263 std::vector<std::unique_ptr<SavePageRequest>> requests);
264 264
265 void StartProcessingImmediately() {
266 // Be sure conditions will allow the immediate start.
267 SetIsLowEndDeviceForTest(false);
Pete Williamson 2016/10/19 23:18:18 I think I'd prefer to see this set-up in the test,
dougarnett 2016/10/19 23:29:12 Had this all repeated in many tests. I can go back
dougarnett 2016/10/21 20:01:19 Dropped the immediate start and reworked common se
268 SetEffectiveConnectionTypeForTest(
269 net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G);
270 coordinator()->StartImmediatelyForTest();
271 }
272
265 void SendOfflinerDoneCallback(const SavePageRequest& request, 273 void SendOfflinerDoneCallback(const SavePageRequest& request,
266 Offliner::RequestStatus status); 274 Offliner::RequestStatus status);
267 275
268 RequestQueue::GetRequestsResult last_get_requests_result() const { 276 RequestQueue::GetRequestsResult last_get_requests_result() const {
269 return last_get_requests_result_; 277 return last_get_requests_result_;
270 } 278 }
271 279
272 const std::vector<std::unique_ptr<SavePageRequest>>& last_requests() const { 280 const std::vector<std::unique_ptr<SavePageRequest>>& last_requests() const {
273 return last_requests_; 281 return last_requests_;
274 } 282 }
275 283
276 const MultipleItemStatuses& last_remove_results() const { 284 const MultipleItemStatuses& last_remove_results() const {
277 return last_remove_results_; 285 return last_remove_results_;
278 } 286 }
279 287
280 void DisableLoading() { 288 void DisableLoading() {
281 offliner_->disable_loading(); 289 offliner_->disable_loading();
282 } 290 }
283 291
284 void EnableOfflinerCallback(bool enable) { 292 void EnableOfflinerCallback(bool enable) {
285 offliner_->enable_callback(enable); 293 offliner_->enable_callback(enable);
286 } 294 }
287 295
288 void SetNetworkConditionsForTest( 296 void SetNetworkConditionsForTest(
289 net::NetworkChangeNotifier::ConnectionType connection) { 297 net::NetworkChangeNotifier::ConnectionType connection) {
290 coordinator()->SetNetworkConditionsForTest(connection); 298 coordinator()->SetNetworkConditionsForTest(connection);
291 } 299 }
292 300
301 void SetIsLowEndDeviceForTest(bool is_low_end_device) {
302 coordinator()->is_low_end_device_ = is_low_end_device;
303 }
304
293 void SetEffectiveConnectionTypeForTest(net::EffectiveConnectionType type) { 305 void SetEffectiveConnectionTypeForTest(net::EffectiveConnectionType type) {
294 network_quality_estimator_->SetEffectiveConnectionTypeForTest(type); 306 network_quality_estimator_->SetEffectiveConnectionTypeForTest(type);
295 } 307 }
296 308
297 void ScheduleForTest() { coordinator_->ScheduleAsNeeded(); } 309 void ScheduleForTest() { coordinator_->ScheduleAsNeeded(); }
298 310
299 void CallRequestNotPicked(bool non_user_requested_tasks_remaining, 311 void CallRequestNotPicked(bool non_user_requested_tasks_remaining,
300 bool disabled_tasks_remaining) { 312 bool disabled_tasks_remaining) {
301 if (disabled_tasks_remaining) 313 if (disabled_tasks_remaining)
302 coordinator_->disabled_requests_.insert(kRequestId1); 314 coordinator_->disabled_requests_.insert(kRequestId1);
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 // Add a request to the queue, wait for callbacks to finish. 559 // Add a request to the queue, wait for callbacks to finish.
548 offline_pages::SavePageRequest request( 560 offline_pages::SavePageRequest request(
549 kRequestId1, kUrl1, kClientId1, base::Time::Now(), kUserRequested); 561 kRequestId1, kUrl1, kClientId1, base::Time::Now(), kUserRequested);
550 request.MarkAttemptStarted(base::Time::Now()); 562 request.MarkAttemptStarted(base::Time::Now());
551 coordinator()->queue()->AddRequest( 563 coordinator()->queue()->AddRequest(
552 request, 564 request,
553 base::Bind(&RequestCoordinatorTest::AddRequestDone, 565 base::Bind(&RequestCoordinatorTest::AddRequestDone,
554 base::Unretained(this))); 566 base::Unretained(this)));
555 PumpLoop(); 567 PumpLoop();
556 568
557 // We need to give a callback to the request. 569 // Trigger immediate processing of queued request without automatic callback.
570 EnableOfflinerCallback(false);
571 StartProcessingImmediately();
Pete Williamson 2016/10/19 23:18:18 Why add this? The more of the chain that we bring
dougarnett 2016/10/19 23:29:12 The motivation was that we now have a processing_s
572 PumpLoop();
573
574 // Override the processing callback for test visiblity.
558 base::Callback<void(bool)> callback = 575 base::Callback<void(bool)> callback =
559 base::Bind(&RequestCoordinatorTest::ImmediateScheduleCallbackFunction, 576 base::Bind(&RequestCoordinatorTest::ImmediateScheduleCallbackFunction,
560 base::Unretained(this)); 577 base::Unretained(this));
561 coordinator()->SetProcessingCallbackForTest(callback); 578 coordinator()->SetProcessingCallbackForTest(callback);
562 579
563 // Set up device conditions for the test.
564 DeviceConditions device_conditions(
565 false, 75, net::NetworkChangeNotifier::CONNECTION_3G);
566 SetDeviceConditionsForTest(device_conditions);
567
568 // Call the OfflinerDoneCallback to simulate the page being completed, wait 580 // Call the OfflinerDoneCallback to simulate the page being completed, wait
569 // for callbacks. 581 // for callbacks.
570 SendOfflinerDoneCallback(request, Offliner::RequestStatus::SAVED); 582 SendOfflinerDoneCallback(request, Offliner::RequestStatus::SAVED);
571 PumpLoop(); 583 PumpLoop();
572 EXPECT_TRUE(immediate_schedule_callback_called()); 584 EXPECT_TRUE(immediate_schedule_callback_called());
573 585
574 // Verify the request gets removed from the queue, and wait for callbacks. 586 // Verify the request gets removed from the queue, and wait for callbacks.
575 coordinator()->queue()->GetRequests( 587 coordinator()->queue()->GetRequests(
576 base::Bind(&RequestCoordinatorTest::GetRequestsDone, 588 base::Bind(&RequestCoordinatorTest::GetRequestsDone,
577 base::Unretained(this))); 589 base::Unretained(this)));
(...skipping 23 matching lines...) Expand all
601 613
602 // Add second request to the queue to check handling when first fails. 614 // Add second request to the queue to check handling when first fails.
603 offline_pages::SavePageRequest request2( 615 offline_pages::SavePageRequest request2(
604 kRequestId2, kUrl2, kClientId2, base::Time::Now(), kUserRequested); 616 kRequestId2, kUrl2, kClientId2, base::Time::Now(), kUserRequested);
605 coordinator()->queue()->AddRequest( 617 coordinator()->queue()->AddRequest(
606 request2, 618 request2,
607 base::Bind(&RequestCoordinatorTest::AddRequestDone, 619 base::Bind(&RequestCoordinatorTest::AddRequestDone,
608 base::Unretained(this))); 620 base::Unretained(this)));
609 PumpLoop(); 621 PumpLoop();
610 622
611 // We need to give a callback to the request. 623 // Trigger immediate processing of queued request without automatic callback.
624 EnableOfflinerCallback(false);
625 StartProcessingImmediately();
Pete Williamson 2016/10/19 23:18:18 Same question here, and the other instances below.
dougarnett 2016/10/21 20:01:19 Done.
626 PumpLoop();
627
628 // Override the processing callback for test visiblity.
612 base::Callback<void(bool)> callback = 629 base::Callback<void(bool)> callback =
613 base::Bind(&RequestCoordinatorTest::ImmediateScheduleCallbackFunction, 630 base::Bind(&RequestCoordinatorTest::ImmediateScheduleCallbackFunction,
614 base::Unretained(this)); 631 base::Unretained(this));
615 coordinator()->SetProcessingCallbackForTest(callback); 632 coordinator()->SetProcessingCallbackForTest(callback);
616 633
617 // Set up device conditions for the test.
618 DeviceConditions device_conditions(
619 false, 75, net::NetworkChangeNotifier::CONNECTION_3G);
620 SetDeviceConditionsForTest(device_conditions);
621
622 // Call the OfflinerDoneCallback to simulate the request failed, wait 634 // Call the OfflinerDoneCallback to simulate the request failed, wait
623 // for callbacks. 635 // for callbacks.
624 SendOfflinerDoneCallback(request, 636 SendOfflinerDoneCallback(request,
625 Offliner::RequestStatus::PRERENDERING_FAILED); 637 Offliner::RequestStatus::PRERENDERING_FAILED);
626 PumpLoop(); 638 PumpLoop();
627 EXPECT_TRUE(immediate_schedule_callback_called()); 639 EXPECT_TRUE(immediate_schedule_callback_called());
628 640
629 // TODO(dougarnett): Consider injecting mock RequestPicker for this test 641 // TODO(dougarnett): Consider injecting mock RequestPicker for this test
630 // and verifying that there is no attempt to pick another request following 642 // and verifying that there is no attempt to pick another request following
631 // this failure code. 643 // this failure code.
(...skipping 24 matching lines...) Expand all
656 PumpLoop(); 668 PumpLoop();
657 669
658 // Add second request to the queue to check handling when first fails. 670 // Add second request to the queue to check handling when first fails.
659 offline_pages::SavePageRequest request2(kRequestId2, kUrl2, kClientId2, 671 offline_pages::SavePageRequest request2(kRequestId2, kUrl2, kClientId2,
660 base::Time::Now(), kUserRequested); 672 base::Time::Now(), kUserRequested);
661 coordinator()->queue()->AddRequest( 673 coordinator()->queue()->AddRequest(
662 request2, base::Bind(&RequestCoordinatorTest::AddRequestDone, 674 request2, base::Bind(&RequestCoordinatorTest::AddRequestDone,
663 base::Unretained(this))); 675 base::Unretained(this)));
664 PumpLoop(); 676 PumpLoop();
665 677
666 // We need to give a callback to the request. 678 // Trigger immediate processing of queued request without automatic callback.
679 EnableOfflinerCallback(false);
680 StartProcessingImmediately();
681 PumpLoop();
682
683 // Override the processing callback for test visiblity.
667 base::Callback<void(bool)> callback = 684 base::Callback<void(bool)> callback =
668 base::Bind(&RequestCoordinatorTest::ImmediateScheduleCallbackFunction, 685 base::Bind(&RequestCoordinatorTest::ImmediateScheduleCallbackFunction,
669 base::Unretained(this)); 686 base::Unretained(this));
670 coordinator()->SetProcessingCallbackForTest(callback); 687 coordinator()->SetProcessingCallbackForTest(callback);
671 688
672 // Set up device conditions for the test.
673 DeviceConditions device_conditions(false, 75,
674 net::NetworkChangeNotifier::CONNECTION_3G);
675 SetDeviceConditionsForTest(device_conditions);
676
677 // Call the OfflinerDoneCallback to simulate the request failed, wait 689 // Call the OfflinerDoneCallback to simulate the request failed, wait
678 // for callbacks. 690 // for callbacks.
679 SendOfflinerDoneCallback( 691 SendOfflinerDoneCallback(
680 request, Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY); 692 request, Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY);
681 PumpLoop(); 693 PumpLoop();
682 EXPECT_TRUE(immediate_schedule_callback_called()); 694 EXPECT_FALSE(immediate_schedule_callback_called());
683 695
684 // TODO(dougarnett): Consider injecting mock RequestPicker for this test 696 // TODO(dougarnett): Consider injecting mock RequestPicker for this test
685 // and verifying that there is as attempt to pick another request following 697 // and verifying that there is as attempt to pick another request following
686 // this non-retryable failure code. 698 // this non-retryable failure code.
687 699
688 coordinator()->queue()->GetRequests(base::Bind( 700 coordinator()->queue()->GetRequests(base::Bind(
689 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); 701 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this)));
690 PumpLoop(); 702 PumpLoop();
691 703
692 // Now just one request in the queue since non-retryable failure. 704 // Now just one request in the queue since non-retryable failure.
693 EXPECT_EQ(1UL, last_requests().size()); 705 EXPECT_EQ(1UL, last_requests().size());
694 // Check that the observer got the notification that we failed (and the 706 // Check that the observer got the notification that we failed (and the
695 // subsequent notification that the request was removed). 707 // subsequent notification that the request was removed).
696 EXPECT_TRUE(observer().completed_called()); 708 EXPECT_TRUE(observer().completed_called());
697 EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::PRERENDER_FAILURE, 709 EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::PRERENDER_FAILURE,
698 observer().last_status()); 710 observer().last_status());
699 } 711 }
700 712
701 TEST_F(RequestCoordinatorTest, OfflinerDoneForegroundCancel) { 713 TEST_F(RequestCoordinatorTest, OfflinerDoneForegroundCancel) {
702 // Add a request to the queue, wait for callbacks to finish. 714 // Add a request to the queue, wait for callbacks to finish.
703 offline_pages::SavePageRequest request( 715 offline_pages::SavePageRequest request(
704 kRequestId1, kUrl1, kClientId1, base::Time::Now(), kUserRequested); 716 kRequestId1, kUrl1, kClientId1, base::Time::Now(), kUserRequested);
705 request.MarkAttemptStarted(base::Time::Now()); 717 request.MarkAttemptStarted(base::Time::Now());
706 coordinator()->queue()->AddRequest( 718 coordinator()->queue()->AddRequest(
707 request, base::Bind(&RequestCoordinatorTest::AddRequestDone, 719 request, base::Bind(&RequestCoordinatorTest::AddRequestDone,
708 base::Unretained(this))); 720 base::Unretained(this)));
709 PumpLoop(); 721 PumpLoop();
710 722
711 // We need to give a callback to the request. 723 // Trigger immediate processing of queued request without automatic callback.
724 EnableOfflinerCallback(false);
725 StartProcessingImmediately();
726 PumpLoop();
727
728 // Override the processing callback for test visiblity.
712 base::Callback<void(bool)> callback = 729 base::Callback<void(bool)> callback =
713 base::Bind(&RequestCoordinatorTest::ImmediateScheduleCallbackFunction, 730 base::Bind(&RequestCoordinatorTest::ImmediateScheduleCallbackFunction,
714 base::Unretained(this)); 731 base::Unretained(this));
715 coordinator()->SetProcessingCallbackForTest(callback); 732 coordinator()->SetProcessingCallbackForTest(callback);
716 733
717 // Set up device conditions for the test.
718 DeviceConditions device_conditions(false, 75,
719 net::NetworkChangeNotifier::CONNECTION_3G);
720 SetDeviceConditionsForTest(device_conditions);
721
722 // Call the OfflinerDoneCallback to simulate the request failed, wait 734 // Call the OfflinerDoneCallback to simulate the request failed, wait
723 // for callbacks. 735 // for callbacks.
724 SendOfflinerDoneCallback(request, 736 SendOfflinerDoneCallback(request,
725 Offliner::RequestStatus::FOREGROUND_CANCELED); 737 Offliner::RequestStatus::FOREGROUND_CANCELED);
726 PumpLoop(); 738 PumpLoop();
727 EXPECT_TRUE(immediate_schedule_callback_called()); 739 EXPECT_TRUE(immediate_schedule_callback_called());
728 740
729 // Verify the request is not removed from the queue, and wait for callbacks. 741 // Verify the request is not removed from the queue, and wait for callbacks.
730 coordinator()->queue()->GetRequests(base::Bind( 742 coordinator()->queue()->GetRequests(base::Bind(
731 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); 743 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this)));
732 PumpLoop(); 744 PumpLoop();
733 745
734 // Request no longer in the queue (for single attempt policy). 746 // Request no longer in the queue (for single attempt policy).
735 EXPECT_EQ(1UL, last_requests().size()); 747 EXPECT_EQ(1UL, last_requests().size());
736 // Verify foreground cancel not counted as an attempt after all. 748 // Verify foreground cancel not counted as an attempt after all.
737 EXPECT_EQ(0L, last_requests().at(0)->completed_attempt_count()); 749 EXPECT_EQ(0L, last_requests().at(0)->completed_attempt_count());
738 } 750 }
739 751
740 TEST_F(RequestCoordinatorTest, OfflinerDonePrerenderingCancel) { 752 TEST_F(RequestCoordinatorTest, OfflinerDonePrerenderingCancel) {
741 // Add a request to the queue, wait for callbacks to finish. 753 // Add a request to the queue, wait for callbacks to finish.
742 offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, 754 offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1,
743 base::Time::Now(), kUserRequested); 755 base::Time::Now(), kUserRequested);
744 request.MarkAttemptStarted(base::Time::Now()); 756 request.MarkAttemptStarted(base::Time::Now());
745 coordinator()->queue()->AddRequest( 757 coordinator()->queue()->AddRequest(
746 request, base::Bind(&RequestCoordinatorTest::AddRequestDone, 758 request, base::Bind(&RequestCoordinatorTest::AddRequestDone,
747 base::Unretained(this))); 759 base::Unretained(this)));
748 PumpLoop(); 760 PumpLoop();
749 761
750 // We need to give a callback to the request. 762 // Trigger immediate processing of queued request without automatic callback.
763 EnableOfflinerCallback(false);
764 StartProcessingImmediately();
765 PumpLoop();
766
767 // Override the processing callback for test visiblity.
751 base::Callback<void(bool)> callback = 768 base::Callback<void(bool)> callback =
752 base::Bind(&RequestCoordinatorTest::ImmediateScheduleCallbackFunction, 769 base::Bind(&RequestCoordinatorTest::ImmediateScheduleCallbackFunction,
753 base::Unretained(this)); 770 base::Unretained(this));
754 coordinator()->SetProcessingCallbackForTest(callback); 771 coordinator()->SetProcessingCallbackForTest(callback);
755 772
756 // Set up device conditions for the test.
757 DeviceConditions device_conditions(false, 75,
758 net::NetworkChangeNotifier::CONNECTION_3G);
759 SetDeviceConditionsForTest(device_conditions);
760
761 // Call the OfflinerDoneCallback to simulate the request failed, wait 773 // Call the OfflinerDoneCallback to simulate the request failed, wait
762 // for callbacks. 774 // for callbacks.
763 SendOfflinerDoneCallback(request, 775 SendOfflinerDoneCallback(request,
764 Offliner::RequestStatus::PRERENDERING_CANCELED); 776 Offliner::RequestStatus::PRERENDERING_CANCELED);
765 PumpLoop(); 777 PumpLoop();
766 EXPECT_TRUE(immediate_schedule_callback_called()); 778 EXPECT_TRUE(immediate_schedule_callback_called());
767 779
768 // Verify the request is not removed from the queue, and wait for callbacks. 780 // Verify the request is not removed from the queue, and wait for callbacks.
769 coordinator()->queue()->GetRequests(base::Bind( 781 coordinator()->queue()->GetRequests(base::Bind(
770 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); 782 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this)));
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 WaitForCallback(); 1106 WaitForCallback();
1095 PumpLoop(); 1107 PumpLoop();
1096 1108
1097 EXPECT_FALSE(is_starting()); 1109 EXPECT_FALSE(is_starting());
1098 EXPECT_TRUE(OfflinerWasCanceled()); 1110 EXPECT_TRUE(OfflinerWasCanceled());
1099 EXPECT_EQ(Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT, 1111 EXPECT_EQ(Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT,
1100 last_offlining_status()); 1112 last_offlining_status());
1101 } 1113 }
1102 1114
1103 TEST_F(RequestCoordinatorTest, WatchdogTimeoutForImmediateProcessing) { 1115 TEST_F(RequestCoordinatorTest, WatchdogTimeoutForImmediateProcessing) {
1104 // Test only applies on non-svelte device. 1116 // If low end device, pretend it is not so that immediate start happens.
1105 if (base::SysInfo::IsLowEndDevice()) 1117 SetIsLowEndDeviceForTest(false);
1106 return;
1107 1118
1108 // Set good network connection so that adding request will trigger 1119 // Set good network connection so that adding request will trigger
1109 // immediate processing. 1120 // immediate processing.
1110 SetEffectiveConnectionTypeForTest( 1121 SetEffectiveConnectionTypeForTest(
1111 net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G); 1122 net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G);
1112 1123
1113 // Ensure that the new request does not finish - we simulate it being 1124 // Ensure that the new request does not finish - we simulate it being
1114 // in progress by asking it to skip making the completion callback. 1125 // in progress by asking it to skip making the completion callback.
1115 EnableOfflinerCallback(false); 1126 EnableOfflinerCallback(false);
1116 1127
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
1354 // Now whether processing triggered immediately depends on whether test 1365 // Now whether processing triggered immediately depends on whether test
1355 // is run on svelte device or not. 1366 // is run on svelte device or not.
1356 if (base::SysInfo::IsLowEndDevice()) { 1367 if (base::SysInfo::IsLowEndDevice()) {
1357 EXPECT_FALSE(is_busy()); 1368 EXPECT_FALSE(is_busy());
1358 } else { 1369 } else {
1359 EXPECT_TRUE(is_busy()); 1370 EXPECT_TRUE(is_busy());
1360 } 1371 }
1361 } 1372 }
1362 1373
1363 } // namespace offline_pages 1374 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698