summaryrefslogtreecommitdiff
path: root/chromium/components/offline_pages
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-07-12 14:07:37 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-07-17 10:29:26 +0000
commitec02ee4181c49b61fce1c8fb99292dbb8139cc90 (patch)
tree25cde714b2b71eb639d1cd53f5a22e9ba76e14ef /chromium/components/offline_pages
parentbb09965444b5bb20b096a291445170876225268d (diff)
downloadqtwebengine-chromium-ec02ee4181c49b61fce1c8fb99292dbb8139cc90.tar.gz
BASELINE: Update Chromium to 59.0.3071.134
Change-Id: Id02ef6fb2204c5fd21668a1c3e6911c83b17585a Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/components/offline_pages')
-rw-r--r--chromium/components/offline_pages/OWNERS2
-rw-r--r--chromium/components/offline_pages/core/background/cleanup_task.cc4
-rw-r--r--chromium/components/offline_pages/core/background/network_quality_provider_stub.cc8
-rw-r--r--chromium/components/offline_pages/core/background/network_quality_provider_stub.h8
-rw-r--r--chromium/components/offline_pages/core/background/offliner_policy.h2
-rw-r--r--chromium/components/offline_pages/core/background/pick_request_task.cc72
-rw-r--r--chromium/components/offline_pages/core/background/pick_request_task.h5
-rw-r--r--chromium/components/offline_pages/core/background/pick_request_task_unittest.cc74
-rw-r--r--chromium/components/offline_pages/core/background/reconcile_task.cc2
-rw-r--r--chromium/components/offline_pages/core/background/request_coordinator.cc76
-rw-r--r--chromium/components/offline_pages/core/background/request_coordinator.h31
-rw-r--r--chromium/components/offline_pages/core/background/request_coordinator_unittest.cc85
-rw-r--r--chromium/components/offline_pages/core/background/request_queue.cc16
-rw-r--r--chromium/components/offline_pages/core/background/request_queue.h4
-rw-r--r--chromium/components/offline_pages/core/background/request_queue_store_sql.cc16
-rw-r--r--chromium/components/offline_pages/core/background/request_queue_store_sql.h11
-rw-r--r--chromium/components/offline_pages/core/background/request_queue_store_unittest.cc7
-rw-r--r--chromium/components/offline_pages/core/background/request_queue_unittest.cc1
-rw-r--r--chromium/components/offline_pages/core/background/save_page_request.cc23
-rw-r--r--chromium/components/offline_pages/core/background/save_page_request.h11
-rw-r--r--chromium/components/offline_pages/core/background/save_page_request_unittest.cc8
-rw-r--r--chromium/components/offline_pages/core/offline_page_archiver.h8
-rw-r--r--chromium/components/offline_pages/core/offline_page_feature.cc14
-rw-r--r--chromium/components/offline_pages/core/offline_page_feature.h8
-rw-r--r--chromium/components/offline_pages/core/offline_page_metadata_store_impl_unittest.cc8
-rw-r--r--chromium/components/offline_pages/core/offline_page_metadata_store_sql.cc4
-rw-r--r--chromium/components/offline_pages/core/offline_page_model_impl.cc37
-rw-r--r--chromium/components/offline_pages/core/offline_page_model_impl.h2
-rw-r--r--chromium/components/offline_pages/core/offline_page_model_impl_unittest.cc11
-rw-r--r--chromium/components/offline_pages/core/offline_page_storage_manager.cc1
-rw-r--r--chromium/components/offline_pages/core/offline_page_test_archiver.h2
-rw-r--r--chromium/components/offline_pages/core/offline_page_test_store.cc3
-rw-r--r--chromium/components/offline_pages/core/offline_page_types.h4
-rw-r--r--chromium/components/offline_pages/core/offline_store_types.h1
-rw-r--r--chromium/components/offline_pages/core/snapshot_controller.cc53
-rw-r--r--chromium/components/offline_pages/core/snapshot_controller.h14
-rw-r--r--chromium/components/offline_pages/core/snapshot_controller_unittest.cc3
37 files changed, 386 insertions, 253 deletions
diff --git a/chromium/components/offline_pages/OWNERS b/chromium/components/offline_pages/OWNERS
index 394e90ea958..4b3428eacec 100644
--- a/chromium/components/offline_pages/OWNERS
+++ b/chromium/components/offline_pages/OWNERS
@@ -3,3 +3,5 @@ dimich@chromium.org
fgorski@chromium.org
jianli@chromium.org
petewil@chromium.org
+
+# COMPONENT: UI>Browser>Offline
diff --git a/chromium/components/offline_pages/core/background/cleanup_task.cc b/chromium/components/offline_pages/core/background/cleanup_task.cc
index 84e2a7864d4..d66d48b610e 100644
--- a/chromium/components/offline_pages/core/background/cleanup_task.cc
+++ b/chromium/components/offline_pages/core/background/cleanup_task.cc
@@ -56,8 +56,8 @@ void CleanupTask::Prune(
return;
}
- // TODO(petewil): Add UMA saying why we remove them
- // TODO(petewil): Round trip the reason for deleting through the RQ
+ // TODO(petewil): Add UMA saying why we remove them. Round trip the reason
+ // for deleting through the RQ callbacks. crbug.com/705115.
store_->RemoveRequests(expired_request_ids,
base::Bind(&CleanupTask::OnRequestsExpired,
weak_ptr_factory_.GetWeakPtr()));
diff --git a/chromium/components/offline_pages/core/background/network_quality_provider_stub.cc b/chromium/components/offline_pages/core/background/network_quality_provider_stub.cc
index aaca69530b1..f4243af9ade 100644
--- a/chromium/components/offline_pages/core/background/network_quality_provider_stub.cc
+++ b/chromium/components/offline_pages/core/background/network_quality_provider_stub.cc
@@ -36,6 +36,14 @@ void NetworkQualityProviderStub::AddEffectiveConnectionTypeObserver(
void NetworkQualityProviderStub::RemoveEffectiveConnectionTypeObserver(
net::NetworkQualityEstimator::EffectiveConnectionTypeObserver* observer) {}
+void NetworkQualityProviderStub::AddRTTAndThroughputEstimatesObserver(
+ net::NetworkQualityEstimator::RTTAndThroughputEstimatesObserver* observer) {
+}
+
+void NetworkQualityProviderStub::RemoveRTTAndThroughputEstimatesObserver(
+ net::NetworkQualityEstimator::RTTAndThroughputEstimatesObserver* observer) {
+}
+
net::EffectiveConnectionType
NetworkQualityProviderStub::GetEffectiveConnectionType() const {
return connection_type_;
diff --git a/chromium/components/offline_pages/core/background/network_quality_provider_stub.h b/chromium/components/offline_pages/core/background/network_quality_provider_stub.h
index 1c13a17b3ea..525e1141f39 100644
--- a/chromium/components/offline_pages/core/background/network_quality_provider_stub.h
+++ b/chromium/components/offline_pages/core/background/network_quality_provider_stub.h
@@ -35,6 +35,14 @@ class NetworkQualityProviderStub
net::NetworkQualityEstimator::EffectiveConnectionTypeObserver* observer)
override;
+ void AddRTTAndThroughputEstimatesObserver(
+ net::NetworkQualityEstimator::RTTAndThroughputEstimatesObserver* observer)
+ override;
+
+ void RemoveRTTAndThroughputEstimatesObserver(
+ net::NetworkQualityEstimator::RTTAndThroughputEstimatesObserver* observer)
+ override;
+
void SetEffectiveConnectionTypeForTest(net::EffectiveConnectionType type) {
connection_type_ = type;
}
diff --git a/chromium/components/offline_pages/core/background/offliner_policy.h b/chromium/components/offline_pages/core/background/offliner_policy.h
index d828d4c6ea6..f61085b4b51 100644
--- a/chromium/components/offline_pages/core/background/offliner_policy.h
+++ b/chromium/components/offline_pages/core/background/offliner_policy.h
@@ -66,7 +66,7 @@ class OfflinerPolicy {
// TODO(petewil): Numbers here are chosen arbitrarily, do the proper studies
// to get good policy numbers. Eventually this should get data from a finch
- // experiment.
+ // experiment. crbug.com/705112.
// Returns true if we should prefer retrying lesser tried requests.
bool ShouldPreferUntriedRequests() const { return prefer_untried_requests_; }
diff --git a/chromium/components/offline_pages/core/background/pick_request_task.cc b/chromium/components/offline_pages/core/background/pick_request_task.cc
index 006d08b47af..d2faeac9cb1 100644
--- a/chromium/components/offline_pages/core/background/pick_request_task.cc
+++ b/chromium/components/offline_pages/core/background/pick_request_task.cc
@@ -4,6 +4,8 @@
#include "components/offline_pages/core/background/pick_request_task.h"
+#include <unordered_set>
+
#include "base/bind.h"
#include "base/logging.h"
#include "base/time/time.h"
@@ -35,13 +37,15 @@ PickRequestTask::PickRequestTask(RequestQueueStore* store,
RequestNotPickedCallback not_picked_callback,
RequestCountCallback request_count_callback,
DeviceConditions& device_conditions,
- const std::set<int64_t>& disabled_requests)
+ const std::set<int64_t>& disabled_requests,
+ std::deque<int64_t>& prioritized_requests)
: store_(store),
policy_(policy),
picked_callback_(picked_callback),
not_picked_callback_(not_picked_callback),
request_count_callback_(request_count_callback),
disabled_requests_(disabled_requests),
+ prioritized_requests_(prioritized_requests),
weak_ptr_factory_(this) {
device_conditions_.reset(new DeviceConditions(device_conditions));
}
@@ -80,24 +84,26 @@ void PickRequestTask::Choose(
else
comparator = &PickRequestTask::RecencyFirstCompareFunction;
- // TODO(petewil): Consider replacing this bool with a better named enum.
bool non_user_requested_tasks_remaining = false;
bool cleanup_needed = false;
size_t available_request_count = 0;
+ // Request ids which are available for picking.
+ std::unordered_set<int64_t> available_request_ids;
- // Iterate once through the requests, keeping track of best candidate.
- for (unsigned i = 0; i < requests.size(); ++i) {
+ // Iterate through the requests, filter out unavailable requests and get other
+ // information (if cleanup is needed and number of non-user-requested
+ // requests).
+ for (const auto& request : requests) {
// If the request is expired or has exceeded the retry count, skip it.
- if (OfflinerPolicyUtils::CheckRequestExpirationStatus(requests[i].get(),
+ if (OfflinerPolicyUtils::CheckRequestExpirationStatus(request.get(),
policy_) !=
OfflinerPolicyUtils::RequestExpirationStatus::VALID) {
cleanup_needed = true;
continue;
}
-
- // If the request is on the disabled list, skip it.
- auto search = disabled_requests_.find(requests[i]->request_id());
+ // If the request is on the disabled list, skip it.
+ auto search = disabled_requests_.find(request->request_id());
if (search != disabled_requests_.end())
continue;
@@ -106,21 +112,50 @@ void PickRequestTask::Choose(
// detect if any exist. If we don't find any user-requested tasks, we will
// inform the "not_picked_callback_" that it needs to schedule a task for
// non-user-requested items, which have different network and power needs.
- if (!requests[i]->user_requested())
+ if (!request->user_requested())
non_user_requested_tasks_remaining = true;
- if (requests[i]->request_state() ==
- SavePageRequest::RequestState::AVAILABLE) {
+ if (request->request_state() == SavePageRequest::RequestState::AVAILABLE) {
available_request_count++;
}
- if (!RequestConditionsSatisfied(requests[i].get()))
+ if (!RequestConditionsSatisfied(request.get()))
continue;
- if (IsNewRequestBetter(picked_request, requests[i].get(), comparator))
- picked_request = requests[i].get();
+ available_request_ids.insert(request->request_id());
}
-
// Report the request queue counts.
request_count_callback_.Run(requests.size(), available_request_count);
+ // Search for and pick the prioritized request which is available for picking
+ // from |available_request_ids|, the closer to the end means higher priority.
+ // Also if a request in |prioritized_requests_| doesn't exist in |requests|
+ // we're going to remove it.
+ // For every ID in |available_request_ids|, there exists a corresponding
+ // request in |requests|, so this won't be an infinite loop: either we pick a
+ // request, or there's a request being poped from |prioritized_requests_|.
+ while (!picked_request && !prioritized_requests_.empty()) {
+ if (available_request_ids.count(prioritized_requests_.back()) > 0) {
+ for (const auto& request : requests) {
+ if (request->request_id() == prioritized_requests_.back()) {
+ picked_request = request.get();
+ break;
+ }
+ }
+ DCHECK(picked_request);
+ } else {
+ prioritized_requests_.pop_back();
+ }
+ }
+
+ // If no request was found from the priority list, find the best request
+ // according to current policies.
+ if (!picked_request) {
+ for (const auto& request : requests) {
+ if ((available_request_ids.count(request->request_id()) > 0) &&
+ (IsNewRequestBetter(picked_request, request.get(), comparator))) {
+ picked_request = request.get();
+ }
+ }
+ }
+
// If we have a best request to try next, get the request coodinator to
// start it. Otherwise return that we have no candidates.
if (picked_request != nullptr) {
@@ -161,13 +196,6 @@ bool PickRequestTask::RequestConditionsSatisfied(
if (request->request_state() == SavePageRequest::RequestState::PAUSED)
return false;
- // If this request is not active yet, return false.
- // TODO(petewil): If the only reason we return nothing to do is that we have
- // inactive requests, we still want to try again later after their activation
- // time elapses, we shouldn't take ourselves completely off the scheduler.
- if (request->activation_time() > base::Time::Now())
- return false;
-
return true;
}
diff --git a/chromium/components/offline_pages/core/background/pick_request_task.h b/chromium/components/offline_pages/core/background/pick_request_task.h
index ef046124b1e..b6cad2cce18 100644
--- a/chromium/components/offline_pages/core/background/pick_request_task.h
+++ b/chromium/components/offline_pages/core/background/pick_request_task.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_PICK_REQUEST_TASK_H_
#define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_PICK_REQUEST_TASK_H_
+#include <deque>
#include <set>
#include "base/memory/weak_ptr.h"
@@ -43,7 +44,8 @@ class PickRequestTask : public Task {
RequestNotPickedCallback not_picked_callback,
RequestCountCallback request_count_callback,
DeviceConditions& device_conditions,
- const std::set<int64_t>& disabled_requests);
+ const std::set<int64_t>& disabled_requests,
+ std::deque<int64_t>& prioritized_requests);
~PickRequestTask() override;
@@ -94,6 +96,7 @@ class PickRequestTask : public Task {
RequestCountCallback request_count_callback_;
std::unique_ptr<DeviceConditions> device_conditions_;
const std::set<int64_t>& disabled_requests_;
+ std::deque<int64_t>& prioritized_requests_;
// Allows us to pass a weak pointer to callbacks.
base::WeakPtrFactory<PickRequestTask> weak_ptr_factory_;
};
diff --git a/chromium/components/offline_pages/core/background/pick_request_task_unittest.cc b/chromium/components/offline_pages/core/background/pick_request_task_unittest.cc
index 1b3ca4642f0..7f686246551 100644
--- a/chromium/components/offline_pages/core/background/pick_request_task_unittest.cc
+++ b/chromium/components/offline_pages/core/background/pick_request_task_unittest.cc
@@ -4,6 +4,7 @@
#include "components/offline_pages/core/background/pick_request_task.h"
+#include <deque>
#include <memory>
#include <set>
@@ -127,6 +128,7 @@ class PickRequestTaskTest : public testing::Test {
std::unique_ptr<OfflinerPolicy> policy_;
RequestCoordinatorEventLogger event_logger_;
std::set<int64_t> disabled_requests_;
+ std::deque<int64_t> prioritized_requests_;
std::unique_ptr<PickRequestTask> task_;
bool request_queue_not_picked_called_;
bool cleanup_needed_;
@@ -215,7 +217,7 @@ void PickRequestTaskTest::MakePickRequestTask() {
base::Unretained(this)),
base::Bind(&PickRequestTaskTest::RequestCountCallback,
base::Unretained(this)),
- conditions, disabled_requests_));
+ conditions, disabled_requests_, prioritized_requests_));
task_->SetTaskCompletionCallbackForTesting(
task_runner_.get(),
base::Bind(&PickRequestTaskTest::TaskCompletionCallback,
@@ -493,4 +495,74 @@ TEST_F(PickRequestTaskTest, ChooseRequestThatIsNotDisabled) {
EXPECT_TRUE(task_complete_called_);
}
+TEST_F(PickRequestTaskTest, ChoosePrioritizedRequests) {
+ prioritized_requests_.push_back(kRequestId2);
+ MakePickRequestTask();
+
+ base::Time creation_time = base::Time::Now();
+ SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time,
+ kUserRequested);
+ SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time,
+ kUserRequested);
+ // Since default policy prefer untried requests, make request1 the favorable
+ // pick if no prioritized requests. But request2 is prioritized so it should
+ // be picked.
+ request2.set_completed_attempt_count(kAttemptCount);
+
+ // Add test requests on the Queue.
+ QueueRequests(request1, request2);
+
+ task()->Run();
+ PumpLoop();
+
+ // Pump the loop again to give the async queue the opportunity to return
+ // results from the Get operation, and for the picker to call the "picked"
+ // callback.
+ PumpLoop();
+
+ EXPECT_EQ(kRequestId2, last_picked_->request_id());
+ EXPECT_FALSE(request_queue_not_picked_called_);
+ EXPECT_EQ(2UL, total_request_count_);
+ EXPECT_EQ(2UL, available_request_count_);
+ EXPECT_TRUE(task_complete_called_);
+ EXPECT_EQ(1UL, prioritized_requests_.size());
+}
+
+TEST_F(PickRequestTaskTest, ChooseFromTwoPrioritizedRequests) {
+ // Make two prioritized requests, the second one should be picked because
+ // higher priority requests are later on the list.
+ prioritized_requests_.push_back(kRequestId1);
+ prioritized_requests_.push_back(kRequestId2);
+ MakePickRequestTask();
+
+ // Making request 1 more attractive to be picked not considering the
+ // prioritizing issues with older creation time, fewer attempt count and it's
+ // earlier in the request queue.
+ base::Time creation_time = base::Time::Now();
+ base::Time older_creation_time =
+ creation_time - base::TimeDelta::FromMinutes(10);
+ SavePageRequest request1(kRequestId1, kUrl1, kClientId1, older_creation_time,
+ kUserRequested);
+ SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time,
+ kUserRequested);
+ request2.set_completed_attempt_count(kAttemptCount);
+
+ // Add test requests on the Queue.
+ QueueRequests(request1, request2);
+
+ task()->Run();
+ PumpLoop();
+
+ // Pump the loop again to give the async queue the opportunity to return
+ // results from the Get operation, and for the picker to call the "picked"
+ // callback.
+ PumpLoop();
+
+ EXPECT_EQ(kRequestId2, last_picked_->request_id());
+ EXPECT_FALSE(request_queue_not_picked_called_);
+ EXPECT_EQ(2UL, total_request_count_);
+ EXPECT_EQ(2UL, available_request_count_);
+ EXPECT_TRUE(task_complete_called_);
+ EXPECT_EQ(2UL, prioritized_requests_.size());
+}
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/background/reconcile_task.cc b/chromium/components/offline_pages/core/background/reconcile_task.cc
index 9b8427530b5..66833e859e4 100644
--- a/chromium/components/offline_pages/core/background/reconcile_task.cc
+++ b/chromium/components/offline_pages/core/background/reconcile_task.cc
@@ -48,8 +48,6 @@ void ReconcileTask::Reconcile(
if (request->request_state() == SavePageRequest::RequestState::OFFLINING) {
request->set_request_state(SavePageRequest::RequestState::AVAILABLE);
items_to_update.push_back(*request.get());
- // TODO(petewil): Consider adding UMA to see how often chrome gets killed
- // while processing a request.
}
}
diff --git a/chromium/components/offline_pages/core/background/request_coordinator.cc b/chromium/components/offline_pages/core/background/request_coordinator.cc
index 1a859fbcf11..167ffa78c7f 100644
--- a/chromium/components/offline_pages/core/background/request_coordinator.cc
+++ b/chromium/components/offline_pages/core/background/request_coordinator.cc
@@ -197,8 +197,7 @@ RequestCoordinator::RequestCoordinator(
net::NetworkQualityEstimator::NetworkQualityProvider*
network_quality_estimator)
: is_low_end_device_(base::SysInfo::IsLowEndDevice()),
- is_busy_(false),
- is_starting_(false),
+ state_(RequestCoordinatorState::IDLE),
processing_state_(ProcessingWindowState::STOPPED),
use_test_device_conditions_(false),
offliner_(std::move(offliner)),
@@ -287,7 +286,7 @@ void RequestCoordinator::GetQueuedRequestsCallback(
void RequestCoordinator::StopPrerendering(
const Offliner::CancelCallback& final_callback,
Offliner::RequestStatus stop_status) {
- if (offliner_ && is_busy_) {
+ if (offliner_ && state_ == RequestCoordinatorState::OFFLINING) {
DCHECK(active_request_.get());
offliner_->Cancel(base::Bind(
&RequestCoordinator::HandleCancelUpdateStatusCallback,
@@ -415,6 +414,15 @@ void RequestCoordinator::RemoveRequests(
void RequestCoordinator::PauseRequests(
const std::vector<int64_t>& request_ids) {
bool canceled = CancelActiveRequestIfItMatches(request_ids);
+
+ // Remove the paused requests from prioritized list.
+ for (int64_t id : request_ids) {
+ auto it = std::find(prioritized_requests_.begin(),
+ prioritized_requests_.end(), id);
+ if (it != prioritized_requests_.end())
+ prioritized_requests_.erase(it);
+ }
+
queue_->ChangeRequestsState(
request_ids, SavePageRequest::RequestState::PAUSED,
base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback,
@@ -434,6 +442,8 @@ void RequestCoordinator::PauseRequests(
void RequestCoordinator::ResumeRequests(
const std::vector<int64_t>& request_ids) {
+ prioritized_requests_.insert(prioritized_requests_.end(), request_ids.begin(),
+ request_ids.end());
queue_->ChangeRequestsState(
request_ids, SavePageRequest::RequestState::AVAILABLE,
base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback,
@@ -544,9 +554,9 @@ void RequestCoordinator::UpdateStatusForCancel(
RecordOfflinerResultUMA(active_request_->client_id(),
active_request_->creation_time(),
last_offlining_status_);
- is_busy_ = false;
active_request_.reset();
}
+ state_ = RequestCoordinatorState::IDLE;
}
void RequestCoordinator::ResetActiveRequestCallback(int64_t offline_id) {
@@ -613,7 +623,7 @@ bool RequestCoordinator::StartImmediateProcessing(
bool RequestCoordinator::StartProcessingInternal(
const ProcessingWindowState processing_state,
const base::Callback<void(bool)>& callback) {
- if (is_starting_ || is_busy_)
+ if (state_ != RequestCoordinatorState::IDLE)
return false;
processing_state_ = processing_state;
scheduler_callback_ = callback;
@@ -636,7 +646,7 @@ RequestCoordinator::TryImmediateStart(
const base::Callback<void(bool)>& callback) {
DVLOG(2) << "Immediate " << __func__;
// Make sure not already busy processing.
- if (is_busy_)
+ if (state_ == RequestCoordinatorState::OFFLINING)
return OfflinerImmediateStartStatus::BUSY;
// Make sure we are not on svelte device to start immediately.
@@ -691,13 +701,10 @@ void RequestCoordinator::UpdateCurrentConditionsFromAndroid() {
}
void RequestCoordinator::TryNextRequest(bool is_start_of_processing) {
- is_starting_ = true;
+ state_ = RequestCoordinatorState::PICKING;
// If this is the first call, the device conditions are current, no need to
// update them.
- // TODO(petewil): Now that we can get conditions any time, consider getting
- // them now instead of passing them in earlier when we start scheduled
- // processing.
if (!is_start_of_processing) {
// Get current device conditions from the Java side across the bridge.
// NetworkChangeNotifier will not have the right conditions if chromium is
@@ -726,7 +733,7 @@ void RequestCoordinator::TryNextRequest(bool is_start_of_processing) {
if (connection_type ==
net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE ||
(base::Time::Now() - operation_start_time_) > processing_time_budget) {
- is_starting_ = false;
+ state_ = RequestCoordinatorState::IDLE;
// If we were doing immediate processing, try to start it again
// when we get connected.
@@ -734,37 +741,34 @@ void RequestCoordinator::TryNextRequest(bool is_start_of_processing) {
RequestConnectedEventForStarting();
// Let the scheduler know we are done processing.
- // TODO: Make sure the scheduler callback is valid before running it.
scheduler_callback_.Run(true);
DVLOG(2) << " out of time, giving up. " << __func__;
return;
}
- // Ask request queue to make a new PickRequestTask object, then put it on the
- // task queue.
+ // Ask request queue to make a new PickRequestTask object, then put it on
+ // the task queue.
queue_->PickNextRequest(
- policy_.get(), base::Bind(&RequestCoordinator::RequestPicked,
- weak_ptr_factory_.GetWeakPtr()),
+ policy_.get(),
+ base::Bind(&RequestCoordinator::RequestPicked,
+ weak_ptr_factory_.GetWeakPtr()),
base::Bind(&RequestCoordinator::RequestNotPicked,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&RequestCoordinator::RequestCounts,
weak_ptr_factory_.GetWeakPtr(), is_start_of_processing),
- *current_conditions_.get(), disabled_requests_);
- // TODO(petewil): Verify current_conditions has a good value on all calling
- // paths. It is really more of a "last known conditions" than "current
- // conditions". Consider having a call to Java to check the current
- // conditions.
+ *current_conditions_.get(), disabled_requests_, prioritized_requests_);
}
// Called by the request picker when a request has been picked.
void RequestCoordinator::RequestPicked(const SavePageRequest& request,
bool cleanup_needed) {
DVLOG(2) << request.url() << " " << __func__;
- is_starting_ = false;
- // Make sure we were not stopped while picking.
- if (processing_state_ != ProcessingWindowState::STOPPED) {
+ // Make sure we were not stopped while picking, since any kind of cancel/stop
+ // will reset the state back to IDLE.
+ if (state_ == RequestCoordinatorState::PICKING) {
+ state_ = RequestCoordinatorState::OFFLINING;
// Send the request on to the offliner.
SendRequestToOffliner(request);
}
@@ -778,7 +782,7 @@ void RequestCoordinator::RequestNotPicked(
bool non_user_requested_tasks_remaining,
bool cleanup_needed) {
DVLOG(2) << __func__;
- is_starting_ = false;
+ state_ = RequestCoordinatorState::IDLE;
// Clear the outstanding "safety" task in the scheduler.
scheduler_->Unschedule();
@@ -848,21 +852,7 @@ void RequestCoordinator::RequestCounts(bool is_start_of_processing,
}
void RequestCoordinator::SendRequestToOffliner(const SavePageRequest& request) {
- // Check that offlining didn't get cancelled while performing some async
- // steps.
- if (processing_state_ == ProcessingWindowState::STOPPED)
- return;
-
- if (!offliner_) {
- // TODO(chili,petewil): We should have UMA here to track frequency of this,
- // if it happens at all.
- DVLOG(0) << "Offliner crashed. Cannot background offline page.";
- return;
- }
-
- DCHECK(!is_busy_);
- is_busy_ = true;
-
+ DCHECK(state_ == RequestCoordinatorState::OFFLINING);
// Record start time if this is first attempt.
if (request.started_attempt_count() == 0) {
RecordStartTimeUMA(request);
@@ -884,7 +874,7 @@ void RequestCoordinator::StartOffliner(
update_result->item_statuses.size() != 1 ||
update_result->item_statuses.at(0).first != request_id ||
update_result->item_statuses.at(0).second != ItemActionStatus::SUCCESS) {
- is_busy_ = false;
+ state_ = RequestCoordinatorState::IDLE;
StopProcessing(Offliner::QUEUE_UPDATE_FAILED);
DVLOG(1) << "Failed to mark attempt started: " << request_id;
UpdateRequestResult request_result =
@@ -924,7 +914,7 @@ void RequestCoordinator::StartOffliner(
watchdog_timer_.Start(FROM_HERE, timeout, this,
&RequestCoordinator::HandleWatchdogTimeout);
} else {
- is_busy_ = false;
+ state_ = RequestCoordinatorState::IDLE;
DVLOG(0) << "Unable to start LoadAndSave";
StopProcessing(Offliner::LOADING_NOT_ACCEPTED);
@@ -947,7 +937,7 @@ void RequestCoordinator::OfflinerDoneCallback(const SavePageRequest& request,
RecordOfflinerResultUMA(request.client_id(), request.creation_time(),
last_offlining_status_);
watchdog_timer_.Stop();
- is_busy_ = false;
+ state_ = RequestCoordinatorState::IDLE;
active_request_.reset(nullptr);
UpdateRequestForCompletedAttempt(request, status);
diff --git a/chromium/components/offline_pages/core/background/request_coordinator.h b/chromium/components/offline_pages/core/background/request_coordinator.h
index d4b91009ebd..412808c9da6 100644
--- a/chromium/components/offline_pages/core/background/request_coordinator.h
+++ b/chromium/components/offline_pages/core/background/request_coordinator.h
@@ -62,6 +62,12 @@ class RequestCoordinator : public KeyedService,
DISABLED_FOR_OFFLINER,
};
+ enum class RequestCoordinatorState {
+ IDLE,
+ PICKING,
+ OFFLINING,
+ };
+
// Describes the parameters to control how to save a page when system
// conditions allow.
struct SavePageLaterParams {
@@ -204,11 +210,8 @@ class RequestCoordinator : public KeyedService,
return last_offlining_status_;
}
- bool is_busy() { return is_busy_; }
-
- // Returns whether processing is starting (before it is decided to actually
- // process a request (is_busy()) at this time or not.
- bool is_starting() { return is_starting_; }
+ // Return the state of the request coordinator.
+ RequestCoordinatorState state() { return state_; }
// Tracks whether the last offlining attempt got canceled. This is reset by
// the next call to start processing.
@@ -406,13 +409,8 @@ class RequestCoordinator : public KeyedService,
// Cached value of whether low end device. Overwritable for testing.
bool is_low_end_device_;
- // The offliner can only handle one request at a time - if the offliner is
- // busy, prevent other requests. This flag marks whether the offliner is in
- // use.
- bool is_busy_;
- // There is more than one path to start processing so this flag is used
- // to avoid race conditions before is_busy_ is established.
- bool is_starting_;
+ // Current state of the request coordinator.
+ RequestCoordinatorState state_;
// Identifies the type of current processing window or if processing stopped.
ProcessingWindowState processing_state_;
// True if we should use the test device conditions instead of actual
@@ -461,6 +459,15 @@ class RequestCoordinator : public KeyedService,
base::OneShotTimer watchdog_timer_;
// Used for potential immediate processing when we get network connection.
std::unique_ptr<ConnectionNotifier> connection_notifier_;
+ // Used to track prioritized requests.
+ // The requests can only be added by RC when they are resumed and there are
+ // two places where deletion from the |prioritized_requests_| would happen:
+ // 1. When request is paused RC will remove it.
+ // 2. When a task is not available to be picked by PickRequestTask (because
+ // it was completed or cancelled), the task will remove it.
+ // Currently it's used as LIFO.
+ // TODO(romax): see if LIFO is a good idea or change to FIFO. crbug.com/705106
+ std::deque<int64_t> prioritized_requests_;
// Allows us to pass a weak pointer to callbacks.
base::WeakPtrFactory<RequestCoordinator> weak_ptr_factory_;
diff --git a/chromium/components/offline_pages/core/background/request_coordinator_unittest.cc b/chromium/components/offline_pages/core/background/request_coordinator_unittest.cc
index b732165b4e4..b45cf5547f3 100644
--- a/chromium/components/offline_pages/core/background/request_coordinator_unittest.cc
+++ b/chromium/components/offline_pages/core/background/request_coordinator_unittest.cc
@@ -119,6 +119,8 @@ class ObserverStub : public RequestCoordinator::Observer {
class RequestCoordinatorTest : public testing::Test {
public:
+ using RequestCoordinatorState = RequestCoordinator::RequestCoordinatorState;
+
RequestCoordinatorTest();
~RequestCoordinatorTest() override;
@@ -130,9 +132,7 @@ class RequestCoordinatorTest : public testing::Test {
return coordinator_taco_->request_coordinator();
}
- bool is_busy() { return coordinator()->is_busy(); }
-
- bool is_starting() { return coordinator()->is_starting(); }
+ RequestCoordinatorState state() { return coordinator()->state(); }
// Test processing callback function.
void ProcessingCallbackFunction(bool result) {
@@ -310,6 +310,10 @@ class RequestCoordinatorTest : public testing::Test {
return coordinator()->disabled_requests_;
}
+ const std::deque<int64_t>& prioritized_requests() {
+ return coordinator()->prioritized_requests_;
+ }
+
private:
GetRequestsResult last_get_requests_result_;
MultipleItemStatuses last_remove_results_;
@@ -489,7 +493,7 @@ TEST_F(RequestCoordinatorTest, StartScheduledProcessingWithRequestInProgress) {
processing_callback()));
PumpLoop();
- EXPECT_TRUE(is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
// Since the offliner is disabled, this callback should not be called.
EXPECT_FALSE(processing_callback_called());
@@ -538,7 +542,7 @@ TEST_F(RequestCoordinatorTest, StartImmediateProcessingWithRequestInProgress) {
EXPECT_TRUE(coordinator()->StartImmediateProcessing(processing_callback()));
PumpLoop();
- EXPECT_TRUE(is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
// Since the offliner is disabled, this callback should not be called.
EXPECT_FALSE(processing_callback_called());
@@ -693,13 +697,13 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceededButLostNetwork) {
EXPECT_TRUE(processing_callback_called());
// Verify not busy with 2nd request (since no connection).
- EXPECT_FALSE(is_busy());
+ EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
// Now connect network and verify processing starts.
SetNetworkConnected(true);
CallConnectionTypeObserver();
PumpLoop();
- EXPECT_TRUE(is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}
TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailed) {
@@ -725,7 +729,7 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailed) {
EXPECT_FALSE(processing_callback_called());
// Busy processing 2nd request.
- EXPECT_TRUE(is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
coordinator()->queue()->GetRequests(base::Bind(
&RequestCoordinatorTest::GetRequestsDone, base::Unretained(this)));
@@ -767,7 +771,7 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoRetryFailure) {
EXPECT_FALSE(processing_callback_called());
// Busy processing 2nd request.
- EXPECT_TRUE(is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
coordinator()->queue()->GetRequests(base::Bind(
&RequestCoordinatorTest::GetRequestsDone, base::Unretained(this)));
@@ -804,7 +808,7 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoNextFailure) {
EXPECT_TRUE(processing_callback_called());
// Not busy for NO_NEXT failure.
- EXPECT_FALSE(is_busy());
+ EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
coordinator()->queue()->GetRequests(base::Bind(
&RequestCoordinatorTest::GetRequestsDone, base::Unretained(this)));
@@ -868,13 +872,13 @@ TEST_F(RequestCoordinatorTest, OfflinerDonePrerenderingCancel) {
TEST_F(RequestCoordinatorTest, RequestNotPickedDisabledItemsRemain) {
coordinator()->StartScheduledProcessing(device_conditions(),
processing_callback());
- EXPECT_TRUE(is_starting());
+ EXPECT_TRUE(state() == RequestCoordinatorState::PICKING);
// Call RequestNotPicked, simulating a request on the disabled list.
CallRequestNotPicked(false, true);
PumpLoop();
- EXPECT_FALSE(is_starting());
+ EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);
// The scheduler should have been called to schedule the disabled task for
// 5 minutes from now.
@@ -889,14 +893,14 @@ TEST_F(RequestCoordinatorTest, RequestNotPickedDisabledItemsRemain) {
TEST_F(RequestCoordinatorTest, RequestNotPickedNonUserRequestedItemsRemain) {
coordinator()->StartScheduledProcessing(device_conditions(),
processing_callback());
- EXPECT_TRUE(is_starting());
+ EXPECT_TRUE(state() == RequestCoordinatorState::PICKING);
// Call RequestNotPicked, and make sure we pick schedule a task for non user
// requested conditions, with no tasks on the disabled list.
CallRequestNotPicked(true, false);
PumpLoop();
- EXPECT_FALSE(is_starting());
+ EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);
EXPECT_TRUE(processing_callback_called());
// The scheduler should have been called to schedule the non-user requested
@@ -959,7 +963,7 @@ TEST_F(RequestCoordinatorTest, StartScheduledProcessingWithLoadingDisabled) {
PumpLoop();
EXPECT_TRUE(processing_callback_called());
- EXPECT_FALSE(is_starting());
+ EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);
EXPECT_EQ(Offliner::LOADING_NOT_ACCEPTED, last_offlining_status());
}
@@ -975,7 +979,7 @@ TEST_F(RequestCoordinatorTest,
EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
processing_callback()));
- EXPECT_TRUE(is_starting());
+ EXPECT_TRUE(state() == RequestCoordinatorState::PICKING);
// Now, quick, before it can do much (we haven't called PumpLoop), cancel it.
coordinator()->StopProcessing(Offliner::REQUEST_COORDINATOR_CANCELED);
@@ -984,7 +988,7 @@ TEST_F(RequestCoordinatorTest,
PumpLoop();
EXPECT_TRUE(processing_callback_called());
- EXPECT_FALSE(is_starting());
+ EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);
// OfflinerDoneCallback will not end up getting called with status SAVED,
// since we cancelled the event before it called offliner_->LoadAndSave().
@@ -1007,7 +1011,7 @@ TEST_F(RequestCoordinatorTest,
EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
processing_callback()));
- EXPECT_TRUE(is_starting());
+ EXPECT_TRUE(state() == RequestCoordinatorState::PICKING);
// Let all the async parts of the start processing pipeline run to completion.
PumpLoop();
@@ -1021,8 +1025,8 @@ TEST_F(RequestCoordinatorTest,
EXPECT_FALSE(processing_callback_called());
// Coordinator should now be busy.
- EXPECT_TRUE(is_busy());
- EXPECT_FALSE(is_starting());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
+ EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);
// Now we cancel it while the prerenderer is busy.
coordinator()->StopProcessing(Offliner::REQUEST_COORDINATOR_CANCELED);
@@ -1035,7 +1039,7 @@ TEST_F(RequestCoordinatorTest,
EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state());
observer().Clear();
- EXPECT_FALSE(is_busy());
+ EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
// OfflinerDoneCallback will not end up getting called with status SAVED,
// since we cancelled the event before the LoadAndSave completed.
@@ -1167,8 +1171,8 @@ TEST_F(RequestCoordinatorTest,
WaitForCallback();
PumpLoop();
- EXPECT_FALSE(is_starting());
- EXPECT_FALSE(coordinator()->is_busy());
+ EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);
+ EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
EXPECT_TRUE(OfflinerWasCanceled());
}
@@ -1182,7 +1186,7 @@ TEST_F(RequestCoordinatorTest,
PumpLoop();
// Verify that immediate start from adding the request did happen.
- EXPECT_TRUE(coordinator()->is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
// Advance the mock clock 1 second before the watchdog timeout.
AdvanceClockBy(base::TimeDelta::FromSeconds(
@@ -1193,7 +1197,7 @@ TEST_F(RequestCoordinatorTest,
PumpLoop();
// Verify still busy.
- EXPECT_TRUE(coordinator()->is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
EXPECT_FALSE(OfflinerWasCanceled());
// Advance the mock clock past the watchdog timeout now.
@@ -1253,7 +1257,7 @@ TEST_F(RequestCoordinatorTest, TryNextRequestWithNoNetwork) {
EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
waiting_callback()));
PumpLoop();
- EXPECT_TRUE(coordinator()->is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
// Now lose the network connection.
SetNetworkConnected(false);
@@ -1264,8 +1268,8 @@ TEST_F(RequestCoordinatorTest, TryNextRequestWithNoNetwork) {
PumpLoop();
// Not starting nor busy with next request.
- EXPECT_FALSE(coordinator()->is_starting());
- EXPECT_FALSE(coordinator()->is_busy());
+ EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);
+ EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
// Get queued requests.
coordinator()->queue()->GetRequests(base::Bind(
@@ -1369,7 +1373,7 @@ TEST_F(RequestCoordinatorTest,
EXPECT_NE(0, SavePageLater());
PumpLoop();
- EXPECT_TRUE(is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}
TEST_F(RequestCoordinatorTest,
@@ -1383,7 +1387,7 @@ TEST_F(RequestCoordinatorTest,
PumpLoop();
// Verify not immediately busy (since low-end device).
- EXPECT_FALSE(is_busy());
+ EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
// Set feature flag to allow concurrent loads.
base::test::ScopedFeatureList scoped_feature_list;
@@ -1404,7 +1408,7 @@ TEST_F(RequestCoordinatorTest,
PumpLoop();
// Verify immediate processing did start this time.
- EXPECT_TRUE(is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}
TEST_F(RequestCoordinatorTest, SavePageDoesntStartProcessingWhenDisconnected) {
@@ -1412,13 +1416,13 @@ TEST_F(RequestCoordinatorTest, SavePageDoesntStartProcessingWhenDisconnected) {
EnableOfflinerCallback(false);
EXPECT_NE(0, SavePageLater());
PumpLoop();
- EXPECT_FALSE(is_busy());
+ EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
// Now connect network and verify processing starts.
SetNetworkConnected(true);
CallConnectionTypeObserver();
PumpLoop();
- EXPECT_TRUE(is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}
TEST_F(RequestCoordinatorTest,
@@ -1436,7 +1440,7 @@ TEST_F(RequestCoordinatorTest,
EXPECT_NE(0, SavePageLater());
PumpLoop();
- EXPECT_TRUE(is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}
TEST_F(RequestCoordinatorTest,
@@ -1451,7 +1455,7 @@ TEST_F(RequestCoordinatorTest,
// Add a request to the queue.
AddRequest1();
PumpLoop();
- EXPECT_FALSE(is_busy());
+ EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
// Pause the request.
std::vector<int64_t> request_ids;
@@ -1462,21 +1466,24 @@ TEST_F(RequestCoordinatorTest,
// Resume the request while disconnected.
coordinator()->ResumeRequests(request_ids);
PumpLoop();
- EXPECT_FALSE(is_busy());
+ EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
+ EXPECT_EQ(1UL, prioritized_requests().size());
// Pause the request again.
coordinator()->PauseRequests(request_ids);
PumpLoop();
+ EXPECT_EQ(0UL, prioritized_requests().size());
// Now simulate reasonable connection.
SetNetworkConnected(true);
// Resume the request while connected.
coordinator()->ResumeRequests(request_ids);
- EXPECT_FALSE(is_busy());
+ EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
PumpLoop();
+ EXPECT_EQ(1UL, prioritized_requests().size());
- EXPECT_TRUE(is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}
TEST_F(RequestCoordinatorTest, SnapshotOnLastTryForScheduledProcessing) {
@@ -1542,7 +1549,7 @@ TEST_F(RequestCoordinatorTest, SnapshotOnLastTryForImmediateProcessing) {
observer().Clear();
// Verify that the request is being processed.
- EXPECT_TRUE(coordinator()->is_busy());
+ EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
// Advance the mock clock 1 second more than the watchdog timeout.
AdvanceClockBy(base::TimeDelta::FromSeconds(
diff --git a/chromium/components/offline_pages/core/background/request_queue.cc b/chromium/components/offline_pages/core/background/request_queue.cc
index 406f0ae0ce4..bac52ae5abb 100644
--- a/chromium/components/offline_pages/core/background/request_queue.cc
+++ b/chromium/components/offline_pages/core/background/request_queue.cc
@@ -31,10 +31,6 @@ void GetRequestsDone(const RequestQueue::GetRequestsCallback& callback,
std::vector<std::unique_ptr<SavePageRequest>> requests) {
GetRequestsResult result =
success ? GetRequestsResult::SUCCESS : GetRequestsResult::STORE_FAILURE;
- // TODO(fgorski): Filter out expired requests based on policy.
- // This may trigger the purging if necessary.
- // Also this may be turned into a method on the request queue or add a policy
- // parameter in the process.
callback.Run(result, std::move(requests));
}
@@ -78,8 +74,6 @@ void RequestQueue::GetRequests(const GetRequestsCallback& callback) {
void RequestQueue::AddRequest(const SavePageRequest& request,
const AddRequestCallback& callback) {
- // TODO(fgorski): check that request makes sense.
- // TODO(fgorski): check that request does not violate policy.
std::unique_ptr<AddRequestTask> task(new AddRequestTask(
store_.get(), request, base::Bind(&AddRequestDone, callback, request)));
task_queue_.AddTask(std::move(task));
@@ -128,11 +122,13 @@ void RequestQueue::PickNextRequest(
PickRequestTask::RequestNotPickedCallback not_picked_callback,
PickRequestTask::RequestCountCallback request_count_callback,
DeviceConditions& conditions,
- std::set<int64_t>& disabled_requests) {
+ std::set<int64_t>& disabled_requests,
+ std::deque<int64_t>& prioritized_requests) {
// Using the PickerContext, create a picker task.
- std::unique_ptr<Task> task(new PickRequestTask(
- store_.get(), policy, picked_callback, not_picked_callback,
- request_count_callback, conditions, disabled_requests));
+ std::unique_ptr<Task> task(
+ new PickRequestTask(store_.get(), policy, picked_callback,
+ not_picked_callback, request_count_callback,
+ conditions, disabled_requests, prioritized_requests));
// Queue up the picking task, it will call one of the callbacks when it
// completes.
diff --git a/chromium/components/offline_pages/core/background/request_queue.h b/chromium/components/offline_pages/core/background/request_queue.h
index 8325dd07173..d0c66a7ad48 100644
--- a/chromium/components/offline_pages/core/background/request_queue.h
+++ b/chromium/components/offline_pages/core/background/request_queue.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <deque>
#include <memory>
#include <set>
#include <string>
@@ -95,7 +96,8 @@ class RequestQueue {
PickRequestTask::RequestNotPickedCallback not_picked_callback,
PickRequestTask::RequestCountCallback request_count_callback,
DeviceConditions& conditions,
- std::set<int64_t>& disabled_requests);
+ std::set<int64_t>& disabled_requests,
+ std::deque<int64_t>& prioritized_requests);
// Reconcile any requests that were active the last time chrome exited.
void ReconcileRequests(const UpdateCallback& callback);
diff --git a/chromium/components/offline_pages/core/background/request_queue_store_sql.cc b/chromium/components/offline_pages/core/background/request_queue_store_sql.cc
index 099f774180f..16a13e49c6b 100644
--- a/chromium/components/offline_pages/core/background/request_queue_store_sql.cc
+++ b/chromium/components/offline_pages/core/background/request_queue_store_sql.cc
@@ -97,7 +97,7 @@ bool CreateSchema(sql::Connection* db) {
return false;
}
- // TODO(fgorski): Add indices here.
+ // This would be a great place to add indices when we need them.
return transaction.Commit();
}
@@ -109,8 +109,6 @@ std::unique_ptr<SavePageRequest> MakeSavePageRequest(
const int64_t id = statement.ColumnInt64(0);
const base::Time creation_time =
base::Time::FromInternalValue(statement.ColumnInt64(1));
- const base::Time activation_time =
- base::Time::FromInternalValue(statement.ColumnInt64(2));
const base::Time last_attempt_time =
base::Time::FromInternalValue(statement.ColumnInt64(3));
const int64_t started_attempt_count = statement.ColumnInt64(4);
@@ -127,8 +125,8 @@ std::unique_ptr<SavePageRequest> MakeSavePageRequest(
<< " creation time " << creation_time << " user requested "
<< kUserRequested << " original_url " << original_url;
- std::unique_ptr<SavePageRequest> request(new SavePageRequest(
- id, url, client_id, creation_time, activation_time, kUserRequested));
+ std::unique_ptr<SavePageRequest> request(
+ new SavePageRequest(id, url, client_id, creation_time, kUserRequested));
request->set_last_attempt_time(last_attempt_time);
request->set_started_attempt_count(started_attempt_count);
request->set_completed_attempt_count(completed_attempt_count);
@@ -178,7 +176,7 @@ ItemActionStatus Insert(sql::Connection* db, const SavePageRequest& request) {
sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindInt64(0, request.request_id());
statement.BindInt64(1, request.creation_time().ToInternalValue());
- statement.BindInt64(2, request.activation_time().ToInternalValue());
+ statement.BindInt64(2, 0);
statement.BindInt64(3, request.last_attempt_time().ToInternalValue());
statement.BindInt64(4, request.started_attempt_count());
statement.BindInt64(5, request.completed_attempt_count());
@@ -205,7 +203,7 @@ ItemActionStatus Update(sql::Connection* db, const SavePageRequest& request) {
sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindInt64(0, request.creation_time().ToInternalValue());
- statement.BindInt64(1, request.activation_time().ToInternalValue());
+ statement.BindInt64(1, 0);
statement.BindInt64(2, request.last_attempt_time().ToInternalValue());
statement.BindInt64(3, request.started_attempt_count());
statement.BindInt64(4, request.completed_attempt_count());
@@ -294,7 +292,6 @@ void GetRequestsByIdsSync(sql::Connection* db,
scoped_refptr<base::SingleThreadTaskRunner> runner,
const std::vector<int64_t>& request_ids,
const RequestQueueStore::UpdateCallback& callback) {
- // TODO(fgorski): Perhaps add metrics here.
std::unique_ptr<UpdateRequestsResult> result(
new UpdateRequestsResult(StoreState::LOADED));
@@ -332,7 +329,6 @@ void AddRequestSync(sql::Connection* db,
scoped_refptr<base::SingleThreadTaskRunner> runner,
const SavePageRequest& request,
const RequestQueueStore::AddCallback& callback) {
- // TODO(fgorski): add UMA metrics here.
ItemActionStatus status = Insert(db, request);
runner->PostTask(FROM_HERE, base::Bind(callback, status));
}
@@ -341,7 +337,6 @@ void UpdateRequestsSync(sql::Connection* db,
scoped_refptr<base::SingleThreadTaskRunner> runner,
const std::vector<SavePageRequest>& requests,
const RequestQueueStore::UpdateCallback& callback) {
- // TODO(fgorski): add UMA metrics here.
std::unique_ptr<UpdateRequestsResult> result(
new UpdateRequestsResult(StoreState::LOADED));
@@ -371,7 +366,6 @@ void RemoveRequestsSync(sql::Connection* db,
scoped_refptr<base::SingleThreadTaskRunner> runner,
const std::vector<int64_t>& request_ids,
const RequestQueueStore::UpdateCallback& callback) {
- // TODO(fgorski): Perhaps add metrics here.
std::unique_ptr<UpdateRequestsResult> result(
new UpdateRequestsResult(StoreState::LOADED));
diff --git a/chromium/components/offline_pages/core/background/request_queue_store_sql.h b/chromium/components/offline_pages/core/background/request_queue_store_sql.h
index 6bd9b9a4ccd..7c694f39db7 100644
--- a/chromium/components/offline_pages/core/background/request_queue_store_sql.h
+++ b/chromium/components/offline_pages/core/background/request_queue_store_sql.h
@@ -24,6 +24,17 @@ class Connection;
namespace offline_pages {
// SQLite implementation of RequestQueueStore.
+//
+// This store has a history of schema updates.
+// Original schema was delivered in M57. Since then the following changes
+// happened:
+// * In M58 original_url was added.
+//
+// TODO(romax): remove all activation_time related code the next we change the
+// schema.
+//
+// Looking for procesure to update the schema, please refer to
+// offline_page_metadata_store_sql.h
class RequestQueueStoreSQL : public RequestQueueStore {
public:
RequestQueueStoreSQL(
diff --git a/chromium/components/offline_pages/core/background/request_queue_store_unittest.cc b/chromium/components/offline_pages/core/background/request_queue_store_unittest.cc
index bf78969fc92..9b0009fde61 100644
--- a/chromium/components/offline_pages/core/background/request_queue_store_unittest.cc
+++ b/chromium/components/offline_pages/core/background/request_queue_store_unittest.cc
@@ -428,16 +428,13 @@ TYPED_TEST(RequestQueueStoreTest, UpdateRequest) {
base::Time new_creation_time =
creation_time + base::TimeDelta::FromMinutes(1);
- base::Time activation_time = creation_time + base::TimeDelta::FromHours(6);
// Try updating an existing request.
SavePageRequest updated_request(kRequestId, kUrl, kClientId,
- new_creation_time, activation_time,
- kUserRequested);
+ new_creation_time, kUserRequested);
updated_request.set_original_url(kUrl2);
// Try to update a non-existing request.
SavePageRequest updated_request2(kRequestId2, kUrl, kClientId,
- new_creation_time, activation_time,
- kUserRequested);
+ new_creation_time, kUserRequested);
std::vector<SavePageRequest> requests_to_update{updated_request,
updated_request2};
store->UpdateRequests(
diff --git a/chromium/components/offline_pages/core/background/request_queue_unittest.cc b/chromium/components/offline_pages/core/background/request_queue_unittest.cc
index ed9054bc6c0..24903504eaf 100644
--- a/chromium/components/offline_pages/core/background/request_queue_unittest.cc
+++ b/chromium/components/offline_pages/core/background/request_queue_unittest.cc
@@ -85,7 +85,6 @@ class RequestNotifierStub : public RequestNotifier {
int32_t total_expired_requests_;
};
-// TODO(fgorski): Add tests for store failures in add/remove/get.
class RequestQueueTest : public testing::Test {
public:
RequestQueueTest();
diff --git a/chromium/components/offline_pages/core/background/save_page_request.cc b/chromium/components/offline_pages/core/background/save_page_request.cc
index 9b19dc4d429..d95df18069e 100644
--- a/chromium/components/offline_pages/core/background/save_page_request.cc
+++ b/chromium/components/offline_pages/core/background/save_page_request.cc
@@ -15,23 +15,6 @@ SavePageRequest::SavePageRequest(int64_t request_id,
url_(url),
client_id_(client_id),
creation_time_(creation_time),
- activation_time_(creation_time),
- started_attempt_count_(0),
- completed_attempt_count_(0),
- user_requested_(user_requested),
- state_(RequestState::AVAILABLE) {}
-
-SavePageRequest::SavePageRequest(int64_t request_id,
- const GURL& url,
- const ClientId& client_id,
- const base::Time& creation_time,
- const base::Time& activation_time,
- const bool user_requested)
- : request_id_(request_id),
- url_(url),
- client_id_(client_id),
- creation_time_(creation_time),
- activation_time_(activation_time),
started_attempt_count_(0),
completed_attempt_count_(0),
user_requested_(user_requested),
@@ -42,7 +25,6 @@ SavePageRequest::SavePageRequest(const SavePageRequest& other)
url_(other.url_),
client_id_(other.client_id_),
creation_time_(other.creation_time_),
- activation_time_(other.activation_time_),
started_attempt_count_(other.started_attempt_count_),
completed_attempt_count_(other.completed_attempt_count_),
last_attempt_time_(other.last_attempt_time_),
@@ -56,7 +38,6 @@ bool SavePageRequest::operator==(const SavePageRequest& other) const {
return request_id_ == other.request_id_ && url_ == other.url_ &&
client_id_ == other.client_id_ &&
creation_time_ == other.creation_time_ &&
- activation_time_ == other.activation_time_ &&
started_attempt_count_ == other.started_attempt_count_ &&
completed_attempt_count_ == other.completed_attempt_count_ &&
last_attempt_time_ == other.last_attempt_time_ &&
@@ -64,10 +45,6 @@ bool SavePageRequest::operator==(const SavePageRequest& other) const {
}
void SavePageRequest::MarkAttemptStarted(const base::Time& start_time) {
- DCHECK_LE(activation_time_, start_time);
- // TODO(fgorski): As part of introducing policy in GetStatus, we can make a
- // check here to ensure we only start tasks in status pending, and bail out in
- // other cases.
last_attempt_time_ = start_time;
++started_attempt_count_;
state_ = RequestState::OFFLINING;
diff --git a/chromium/components/offline_pages/core/background/save_page_request.h b/chromium/components/offline_pages/core/background/save_page_request.h
index b1bd54e806b..52dee9556a1 100644
--- a/chromium/components/offline_pages/core/background/save_page_request.h
+++ b/chromium/components/offline_pages/core/background/save_page_request.h
@@ -28,12 +28,6 @@ class SavePageRequest {
const ClientId& client_id,
const base::Time& creation_time,
const bool user_requested);
- SavePageRequest(int64_t request_id,
- const GURL& url,
- const ClientId& client_id,
- const base::Time& creation_time,
- const base::Time& activation_time,
- const bool user_requested);
SavePageRequest(const SavePageRequest& other);
~SavePageRequest();
@@ -64,8 +58,6 @@ class SavePageRequest {
const base::Time& creation_time() const { return creation_time_; }
- const base::Time& activation_time() const { return activation_time_; }
-
int64_t started_attempt_count() const { return started_attempt_count_; }
void set_started_attempt_count(int64_t started_attempt_count) {
started_attempt_count_ = started_attempt_count;
@@ -106,9 +98,6 @@ class SavePageRequest {
// Time when this request was created. (Alternative 2).
base::Time creation_time_;
- // Time when this request will become active.
- base::Time activation_time_;
-
// Number of attempts started to get the page. This may be different than the
// number of attempts completed because we could crash.
int started_attempt_count_;
diff --git a/chromium/components/offline_pages/core/background/save_page_request_unittest.cc b/chromium/components/offline_pages/core/background/save_page_request_unittest.cc
index ddfc2b990b7..df073bd61e3 100644
--- a/chromium/components/offline_pages/core/background/save_page_request_unittest.cc
+++ b/chromium/components/offline_pages/core/background/save_page_request_unittest.cc
@@ -32,7 +32,6 @@ TEST_F(SavePageRequestTest, CreatePendingReqeust) {
EXPECT_EQ(kUrl, request.url());
EXPECT_EQ(kClientId, request.client_id());
EXPECT_EQ(creation_time, request.creation_time());
- EXPECT_EQ(creation_time, request.activation_time());
EXPECT_EQ(base::Time(), request.last_attempt_time());
EXPECT_EQ(0, request.completed_attempt_count());
EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, request.request_state());
@@ -43,11 +42,10 @@ TEST_F(SavePageRequestTest, CreatePendingReqeust) {
TEST_F(SavePageRequestTest, StartAndCompleteRequest) {
base::Time creation_time = base::Time::Now();
- base::Time activation_time = creation_time + base::TimeDelta::FromHours(6);
SavePageRequest request(kRequestId, kUrl, kClientId, creation_time,
- activation_time, kUserRequested);
+ kUserRequested);
- base::Time start_time = activation_time + base::TimeDelta::FromHours(3);
+ base::Time start_time = creation_time + base::TimeDelta::FromHours(3);
request.MarkAttemptStarted(start_time);
// Most things don't change about the request.
@@ -55,7 +53,6 @@ TEST_F(SavePageRequestTest, StartAndCompleteRequest) {
EXPECT_EQ(kUrl, request.url());
EXPECT_EQ(kClientId, request.client_id());
EXPECT_EQ(creation_time, request.creation_time());
- EXPECT_EQ(activation_time, request.activation_time());
// Attempt time, attempt count and status will though.
EXPECT_EQ(start_time, request.last_attempt_time());
@@ -69,7 +66,6 @@ TEST_F(SavePageRequestTest, StartAndCompleteRequest) {
EXPECT_EQ(kUrl, request.url());
EXPECT_EQ(kClientId, request.client_id());
EXPECT_EQ(creation_time, request.creation_time());
- EXPECT_EQ(activation_time, request.activation_time());
// Last attempt time and status are updated.
EXPECT_EQ(1, request.completed_attempt_count());
diff --git a/chromium/components/offline_pages/core/offline_page_archiver.h b/chromium/components/offline_pages/core/offline_page_archiver.h
index 17631406db3..cfada7b4dea 100644
--- a/chromium/components/offline_pages/core/offline_page_archiver.h
+++ b/chromium/components/offline_pages/core/offline_page_archiver.h
@@ -39,12 +39,6 @@ namespace offline_pages {
// archiver whether to respond with ERROR_CONTENT_UNAVAILBLE, wait longer to
// actually snapshot a complete page, or snapshot whatever is available at that
// point in time (what the user sees).
-//
-// TODO(fgorski): Add ability to delete archive.
-// TODO(fgorski): Add ability to check that archive exists.
-// TODO(fgorski): Add ability to refresh an existing archive in one step.
-// TODO(fgorski): Add ability to identify all of the archives in the directory,
-// to enable to model to reconcile the archives.
class OfflinePageArchiver {
public:
// Results of the archive creation.
@@ -56,6 +50,8 @@ class OfflinePageArchiver {
ERROR_ARCHIVE_CREATION_FAILED, // Creation of archive failed.
ERROR_SECURITY_CERTIFICATE, // Page was loaded on secure connection, but
// there was a security error.
+ ERROR_ERROR_PAGE, // We detected an error page.
+ ERROR_INTERSTITIAL_PAGE, // We detected an interstitial page.
};
// Describes the parameters to control how to create an archive.
diff --git a/chromium/components/offline_pages/core/offline_page_feature.cc b/chromium/components/offline_pages/core/offline_page_feature.cc
index 9f283129f19..9dfab58bfca 100644
--- a/chromium/components/offline_pages/core/offline_page_feature.cc
+++ b/chromium/components/offline_pages/core/offline_page_feature.cc
@@ -36,12 +36,18 @@ const base::Feature kOfflinePagesSharingFeature{
const base::Feature kOfflinePagesSvelteConcurrentLoadingFeature{
"OfflinePagesSvelteConcurrentLoading", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kOfflinePagesLoadSignalCollectingFeature{
+ "OfflinePagesLoadSignalCollecting", base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kBackgroundLoaderForDownloadsFeature{
"BackgroundLoadingForDownloads", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kOfflinePagesAsyncDownloadFeature{
"OfflinePagesAsyncDownload", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kPrefetchingOfflinePagesFeature{
+ "OfflinePagesPrefetching", base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kNewBackgroundLoaderFeature {
"BackgroundLoader", base::FEATURE_DISABLED_BY_DEFAULT
};
@@ -75,6 +81,14 @@ bool IsOfflinePagesAsyncDownloadEnabled() {
return base::FeatureList::IsEnabled(kOfflinePagesAsyncDownloadFeature);
}
+bool IsPrefetchingOfflinePagesEnabled() {
+ return base::FeatureList::IsEnabled(kPrefetchingOfflinePagesFeature);
+}
+
+bool IsOfflinePagesLoadSignalCollectingEnabled() {
+ return base::FeatureList::IsEnabled(kOfflinePagesLoadSignalCollectingFeature);
+}
+
bool ShouldUseNewBackgroundLoader() {
return base::FeatureList::IsEnabled(kNewBackgroundLoaderFeature);
}
diff --git a/chromium/components/offline_pages/core/offline_page_feature.h b/chromium/components/offline_pages/core/offline_page_feature.h
index fdd42e6ed8c..11a5b68cf83 100644
--- a/chromium/components/offline_pages/core/offline_page_feature.h
+++ b/chromium/components/offline_pages/core/offline_page_feature.h
@@ -17,7 +17,9 @@ extern const base::Feature kOfflinePagesCTFeature;
extern const base::Feature kOfflinePagesSharingFeature;
extern const base::Feature kBackgroundLoaderForDownloadsFeature;
extern const base::Feature kOfflinePagesAsyncDownloadFeature;
+extern const base::Feature kPrefetchingOfflinePagesFeature;
extern const base::Feature kNewBackgroundLoaderFeature;
+extern const base::Feature kOfflinePagesLoadSignalCollectingFeature;
// Returns true if saving bookmarked pages for offline viewing is enabled.
bool IsOfflineBookmarksEnabled();
@@ -41,6 +43,12 @@ bool IsOfflinePagesSvelteConcurrentLoadingEnabled();
// Returns true if downloading a page asynchonously is enabled.
bool IsOfflinePagesAsyncDownloadEnabled();
+// Returns true if prefetching offline pages is enabled.
+bool IsPrefetchingOfflinePagesEnabled();
+
+// Returns true if we enable load timing signals to be collected.
+bool IsOfflinePagesLoadSignalCollectingEnabled();
+
// Returns true if we should use background loader rather than prerenderer
// to offline pages.
bool ShouldUseNewBackgroundLoader();
diff --git a/chromium/components/offline_pages/core/offline_page_metadata_store_impl_unittest.cc b/chromium/components/offline_pages/core/offline_page_metadata_store_impl_unittest.cc
index 36abbcc98f9..7dcb7898685 100644
--- a/chromium/components/offline_pages/core/offline_page_metadata_store_impl_unittest.cc
+++ b/chromium/components/offline_pages/core/offline_page_metadata_store_impl_unittest.cc
@@ -39,7 +39,6 @@ int64_t kFileSize = 234567LL;
int64_t kOfflineId = 12345LL;
// Build a store with outdated schema to simulate the upgrading process.
-// TODO(romax): move it to sql_unittests.
void BuildTestStoreWithSchemaFromM52(const base::FilePath& file) {
sql::Connection connection;
ASSERT_TRUE(
@@ -392,8 +391,6 @@ void OfflinePageMetadataStoreTest::GetOfflinePagesCallback(
void OfflinePageMetadataStoreTest::AddCallback(ItemActionStatus status) {
last_called_callback_ = ADD;
- // TODO(fgorski): Add specific add status.
- // last_item_status_ = status;
last_status_ =
status == ItemActionStatus::SUCCESS ? STATUS_TRUE : STATUS_FALSE;
}
@@ -636,7 +633,6 @@ TEST_F(OfflinePageMetadataStoreTest, GetOfflinePagesFromInvalidStore) {
// Loads a store which has an outdated schema.
// This test case would crash if it's not handling correctly when we're loading
// old version stores.
-// TODO(romax): Move this to sql_unittest.
TEST_F(OfflinePageMetadataStoreTest, LoadVersion52Store) {
std::unique_ptr<OfflinePageMetadataStore> store(
BuildStoreWithSchemaFromM52());
@@ -648,7 +644,6 @@ TEST_F(OfflinePageMetadataStoreTest, LoadVersion52Store) {
// Loads a store which has an outdated schema.
// This test case would crash if it's not handling correctly when we're loading
// old version stores.
-// TODO(romax): Move this to sql_unittest.
TEST_F(OfflinePageMetadataStoreTest, LoadVersion53Store) {
std::unique_ptr<OfflinePageMetadataStore> store(
BuildStoreWithSchemaFromM53());
@@ -660,7 +655,6 @@ TEST_F(OfflinePageMetadataStoreTest, LoadVersion53Store) {
// Loads a string with schema from M54.
// This test case would crash if it's not handling correctly when we're loading
// old version stores.
-// TODO(romax): Move this to sql_unittest.
TEST_F(OfflinePageMetadataStoreTest, LoadVersion54Store) {
std::unique_ptr<OfflinePageMetadataStore> store(
BuildStoreWithSchemaFromM54());
@@ -672,7 +666,6 @@ TEST_F(OfflinePageMetadataStoreTest, LoadVersion54Store) {
// Loads a string with schema from M55.
// This test case would crash if it's not handling correctly when we're loading
// old version stores.
-// TODO(romax): Move this to sql_unittest.
TEST_F(OfflinePageMetadataStoreTest, LoadVersion55Store) {
std::unique_ptr<OfflinePageMetadataStore> store(
BuildStoreWithSchemaFromM55());
@@ -684,7 +677,6 @@ TEST_F(OfflinePageMetadataStoreTest, LoadVersion55Store) {
// Loads a string with schema from M56.
// This test case would crash if it's not handling correctly when we're loading
// old version stores.
-// TODO(romax): Move this to sql_unittest.
TEST_F(OfflinePageMetadataStoreTest, LoadVersion56Store) {
std::unique_ptr<OfflinePageMetadataStore> store(
BuildStoreWithSchemaFromM56());
diff --git a/chromium/components/offline_pages/core/offline_page_metadata_store_sql.cc b/chromium/components/offline_pages/core/offline_page_metadata_store_sql.cc
index c8e3ee0e953..a4a8ea080b2 100644
--- a/chromium/components/offline_pages/core/offline_page_metadata_store_sql.cc
+++ b/chromium/components/offline_pages/core/offline_page_metadata_store_sql.cc
@@ -158,7 +158,7 @@ bool CreateSchema(sql::Connection* db) {
return false;
}
- // TODO(fgorski): Add indices here.
+ // This would be a great place to add indices when we need them.
return transaction.Commit();
}
@@ -292,7 +292,6 @@ void NotifyLoadResult(scoped_refptr<base::SingleThreadTaskRunner> runner,
const OfflinePageMetadataStore::LoadCallback& callback,
OfflinePageMetadataStore::LoadStatus status,
const std::vector<OfflinePageItem>& result) {
- // TODO(fgorski): Switch to SQL specific UMA metrics.
UMA_HISTOGRAM_ENUMERATION("OfflinePages.LoadStatus", status,
OfflinePageMetadataStore::LOAD_STATUS_COUNT);
if (status == OfflinePageMetadataStore::LOAD_SUCCEEDED) {
@@ -427,7 +426,6 @@ void RemoveOfflinePagesSync(
sql::Connection* db,
scoped_refptr<base::SingleThreadTaskRunner> runner,
const OfflinePageMetadataStore::UpdateCallback& callback) {
- // TODO(fgorski): Perhaps add metrics here.
std::unique_ptr<OfflinePagesUpdateResult> result(
new OfflinePagesUpdateResult(StoreState::LOADED));
diff --git a/chromium/components/offline_pages/core/offline_page_model_impl.cc b/chromium/components/offline_pages/core/offline_page_model_impl.cc
index 2e87035d1f6..596892d6171 100644
--- a/chromium/components/offline_pages/core/offline_page_model_impl.cc
+++ b/chromium/components/offline_pages/core/offline_page_model_impl.cc
@@ -72,6 +72,11 @@ SavePageResult ToSavePageResult(ArchiverResult archiver_result) {
case ArchiverResult::ERROR_SECURITY_CERTIFICATE:
result = SavePageResult::SECURITY_CERTIFICATE_ERROR;
break;
+ case ArchiverResult::ERROR_ERROR_PAGE:
+ result = SavePageResult::ERROR_PAGE;
+ break;
+ case ArchiverResult::ERROR_INTERSTITIAL_PAGE:
+ result = SavePageResult::INTERSTITIAL_PAGE;
default:
NOTREACHED();
result = SavePageResult::CONTENT_UNAVAILABLE;
@@ -572,7 +577,6 @@ const std::vector<int64_t> OfflinePageModelImpl::MaybeGetOfflineIdsForClientId(
std::vector<int64_t> results;
// We want only all pages, including those marked for deletion.
- // TODO(fgorski): actually use an index rather than linear scan.
for (const auto& id_page_pair : offline_pages_) {
if (id_page_pair.second.client_id == client_id)
results.push_back(id_page_pair.second.offline_id);
@@ -684,20 +688,10 @@ void OfflinePageModelImpl::OnCreateArchiveDone(
const SavePageCallback& callback,
OfflinePageArchiver* archiver,
ArchiverResult archiver_result,
- const GURL& url,
+ const GURL& saved_url,
const base::FilePath& file_path,
const base::string16& title,
int64_t file_size) {
- if (save_page_params.url != url) {
- DVLOG(1) << "Saved URL does not match requested URL.";
- // TODO(fgorski): We have created an archive for a wrong URL. It should be
- // deleted from here, once archiver has the right functionality.
- InformSavePageDone(callback, SavePageResult::ARCHIVE_CREATION_FAILED,
- save_page_params.client_id, offline_id);
- DeletePendingArchiver(archiver);
- return;
- }
-
if (archiver_result != ArchiverResult::SUCCESSFULLY_CREATED) {
SavePageResult result = ToSavePageResult(archiver_result);
InformSavePageDone(
@@ -705,8 +699,18 @@ void OfflinePageModelImpl::OnCreateArchiveDone(
DeletePendingArchiver(archiver);
return;
}
- OfflinePageItem offline_page_item(url, offline_id, save_page_params.client_id,
- file_path, file_size, start_time);
+
+ if (save_page_params.url != saved_url) {
+ DVLOG(1) << "Saved URL does not match requested URL.";
+ InformSavePageDone(callback, SavePageResult::ARCHIVE_CREATION_FAILED,
+ save_page_params.client_id, offline_id);
+ DeletePendingArchiver(archiver);
+ return;
+ }
+
+ OfflinePageItem offline_page_item(saved_url, offline_id,
+ save_page_params.client_id, file_path,
+ file_size, start_time);
offline_page_item.title = title;
offline_page_item.original_url = save_page_params.original_url;
store_->AddOfflinePage(offline_page_item,
@@ -907,7 +911,6 @@ void OfflinePageModelImpl::OnPagesFoundWithSameURL(
void OfflinePageModelImpl::OnDeleteOldPagesWithSameURL(
DeletePageResult result) {
- // TODO(romax) Add UMAs for failure cases.
PostClearStorageIfNeededTask(false /* delayed */);
}
@@ -956,10 +959,6 @@ void OfflinePageModelImpl::OnRemoveOfflinePagesDone(
observer.OfflinePageDeleted(page.offline_id, page.client_id);
}
- // TODO(fgorski): React the FAILED_INITIALIZATION, FAILED_RESET here.
- // TODO(fgorski): We need a better callback interface for the Remove action on
- // the this class. Currently removing an item that does not exist is
- // considered a success, but not called out as such to the caller.
DeletePageResult delete_result;
if (result->store_state == StoreState::LOADED)
delete_result = DeletePageResult::SUCCESS;
diff --git a/chromium/components/offline_pages/core/offline_page_model_impl.h b/chromium/components/offline_pages/core/offline_page_model_impl.h
index 5221644d7f3..64e2e3cfdfd 100644
--- a/chromium/components/offline_pages/core/offline_page_model_impl.h
+++ b/chromium/components/offline_pages/core/offline_page_model_impl.h
@@ -163,7 +163,7 @@ class OfflinePageModelImpl : public OfflinePageModel, public KeyedService {
const SavePageCallback& callback,
OfflinePageArchiver* archiver,
OfflinePageArchiver::ArchiverResult result,
- const GURL& url,
+ const GURL& saved_url,
const base::FilePath& file_path,
const base::string16& title,
int64_t file_size);
diff --git a/chromium/components/offline_pages/core/offline_page_model_impl_unittest.cc b/chromium/components/offline_pages/core/offline_page_model_impl_unittest.cc
index b5806b222b7..8d20e475263 100644
--- a/chromium/components/offline_pages/core/offline_page_model_impl_unittest.cc
+++ b/chromium/components/offline_pages/core/offline_page_model_impl_unittest.cc
@@ -1347,4 +1347,15 @@ TEST(CommandLineFlagsTest, OfflinePagesSvelteConcurrentLoading) {
EXPECT_TRUE(offline_pages::IsOfflinePagesSvelteConcurrentLoadingEnabled());
}
+TEST(CommandLineFlagsTest, OfflinePagesLoadSignalCollecting) {
+ // This feature is disabled by default.
+ EXPECT_FALSE(offline_pages::IsOfflinePagesLoadSignalCollectingEnabled());
+
+ // Check if feature is correctly enabled by command-line flag.
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ kOfflinePagesLoadSignalCollectingFeature);
+ EXPECT_TRUE(offline_pages::IsOfflinePagesLoadSignalCollectingEnabled());
+}
+
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/offline_page_storage_manager.cc b/chromium/components/offline_pages/core/offline_page_storage_manager.cc
index efe9ec2f856..1c17729f768 100644
--- a/chromium/components/offline_pages/core/offline_page_storage_manager.cc
+++ b/chromium/components/offline_pages/core/offline_page_storage_manager.cc
@@ -93,7 +93,6 @@ void OfflinePageStorageManager::GetPageIdsToClear(
const MultipleOfflinePageItemResult& pages,
const ArchiveManager::StorageStats& stats,
std::vector<int64_t>* page_ids_to_clear) {
- // TODO(romax): See how persistent should be considered here.
// Creating a map from namespace to a vector of page items.
// Sort each vector based on last accessed time and all pages after index
// min{size(), page_limit} should be deleted.
diff --git a/chromium/components/offline_pages/core/offline_page_test_archiver.h b/chromium/components/offline_pages/core/offline_page_test_archiver.h
index 6d7c04e8753..1ece7c811eb 100644
--- a/chromium/components/offline_pages/core/offline_page_test_archiver.h
+++ b/chromium/components/offline_pages/core/offline_page_test_archiver.h
@@ -26,8 +26,6 @@ namespace offline_pages {
// for an actual web contents.
class OfflinePageTestArchiver : public OfflinePageArchiver {
public:
- // TODO(fgorski): Try refactoring the observer out and replace it with a
- // callback, or completely remove the call to |SetLastPathCreatedByArchiver|.
class Observer {
public:
virtual ~Observer() {}
diff --git a/chromium/components/offline_pages/core/offline_page_test_store.cc b/chromium/components/offline_pages/core/offline_page_test_store.cc
index 556c12a2356..225d777694d 100644
--- a/chromium/components/offline_pages/core/offline_page_test_store.cc
+++ b/chromium/components/offline_pages/core/offline_page_test_store.cc
@@ -44,7 +44,6 @@ void OfflinePageTestStore::GetOfflinePages(const LoadCallback& callback) {
void OfflinePageTestStore::AddOfflinePage(const OfflinePageItem& offline_page,
const AddCallback& callback) {
- // TODO(fgorski): Add and cover scenario with existing item.
ItemActionStatus result;
if (store_state_ == StoreState::LOADED &&
scenario_ != TestScenario::WRITE_FAILED) {
@@ -61,8 +60,6 @@ void OfflinePageTestStore::AddOfflinePage(const OfflinePageItem& offline_page,
void OfflinePageTestStore::UpdateOfflinePages(
const std::vector<OfflinePageItem>& pages,
const UpdateCallback& callback) {
- // TODO(fgorski): Cover scenario where new items are being created while they
- // shouldn't.
std::unique_ptr<OfflinePagesUpdateResult> result(
new OfflinePagesUpdateResult(StoreState::LOADED));
if (scenario_ == TestScenario::WRITE_FAILED) {
diff --git a/chromium/components/offline_pages/core/offline_page_types.h b/chromium/components/offline_pages/core/offline_page_types.h
index ae9e298af8e..4bb3342e1d1 100644
--- a/chromium/components/offline_pages/core/offline_page_types.h
+++ b/chromium/components/offline_pages/core/offline_page_types.h
@@ -34,6 +34,10 @@ enum class SavePageResult {
// are already locally accessible.
SKIPPED,
SECURITY_CERTIFICATE_ERROR,
+ // Returned when we detect trying to save a chrome error page.
+ ERROR_PAGE,
+ // Returned when we detect trying to save a chrome interstitial page.
+ INTERSTITIAL_PAGE,
// NOTE: always keep this entry at the end. Add new result types only
// immediately above this line. Make sure to update the corresponding
// histogram enum accordingly.
diff --git a/chromium/components/offline_pages/core/offline_store_types.h b/chromium/components/offline_pages/core/offline_store_types.h
index 77d6a6a9bdf..aa95914e8ea 100644
--- a/chromium/components/offline_pages/core/offline_store_types.h
+++ b/chromium/components/offline_pages/core/offline_store_types.h
@@ -14,7 +14,6 @@
// offline page related components.
namespace offline_pages {
-// TODO(fgorski): This enum is meant to replace |LoadStatus|.
// Current store state. When LOADED, the store is operational. When
// loading or reset fails, it is reflected appropriately.
enum class StoreState {
diff --git a/chromium/components/offline_pages/core/snapshot_controller.cc b/chromium/components/offline_pages/core/snapshot_controller.cc
index c683a1a9b10..9d62297fb7b 100644
--- a/chromium/components/offline_pages/core/snapshot_controller.cc
+++ b/chromium/components/offline_pages/core/snapshot_controller.cc
@@ -11,6 +11,8 @@
#include "components/offline_pages/core/offline_page_feature.h"
namespace {
+const bool kDocumentAvailableTriggersSnapshot = true;
+
// Default delay, in milliseconds, between the main document parsed event and
// snapshot. Note: this snapshot might not occur if the OnLoad event and
// OnLoad delay elapses first to trigger a final snapshot.
@@ -18,7 +20,8 @@ const int64_t kDefaultDelayAfterDocumentAvailableMs = 7000;
// Default delay, in milliseconds, between the main document OnLoad event and
// snapshot.
-const int64_t kDelayAfterDocumentOnLoadCompletedMs = 1000;
+const int64_t kDelayAfterDocumentOnLoadCompletedMsForeground = 1000;
+const int64_t kDelayAfterDocumentOnLoadCompletedMsBackground = 2000;
// Delay for testing to keep polling times reasonable.
const int64_t kDelayForTests = 0;
@@ -27,25 +30,42 @@ const int64_t kDelayForTests = 0;
namespace offline_pages {
-SnapshotController::SnapshotController(
+// static
+std::unique_ptr<SnapshotController>
+SnapshotController::CreateForForegroundOfflining(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ SnapshotController::Client* client) {
+ return std::unique_ptr<SnapshotController>(new SnapshotController(
+ task_runner, client, kDefaultDelayAfterDocumentAvailableMs,
+ kDelayAfterDocumentOnLoadCompletedMsForeground,
+ kDocumentAvailableTriggersSnapshot));
+}
+
+// static
+std::unique_ptr<SnapshotController>
+SnapshotController::CreateForBackgroundOfflining(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- SnapshotController::Client* client)
- : SnapshotController(task_runner,
- client,
- kDefaultDelayAfterDocumentAvailableMs,
- kDelayAfterDocumentOnLoadCompletedMs) {}
+ SnapshotController::Client* client) {
+ return std::unique_ptr<SnapshotController>(new SnapshotController(
+ task_runner, client, kDefaultDelayAfterDocumentAvailableMs,
+ kDelayAfterDocumentOnLoadCompletedMsBackground,
+ !kDocumentAvailableTriggersSnapshot));
+}
SnapshotController::SnapshotController(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
SnapshotController::Client* client,
int64_t delay_after_document_available_ms,
- int64_t delay_after_document_on_load_completed_ms)
+ int64_t delay_after_document_on_load_completed_ms,
+ bool document_available_triggers_snapshot)
: task_runner_(task_runner),
client_(client),
state_(State::READY),
delay_after_document_available_ms_(delay_after_document_available_ms),
delay_after_document_on_load_completed_ms_(
delay_after_document_on_load_completed_ms),
+ document_available_triggers_snapshot_(
+ document_available_triggers_snapshot),
weak_ptr_factory_(this) {
if (offline_pages::ShouldUseTestingSnapshotDelay()) {
delay_after_document_available_ms_ = kDelayForTests;
@@ -75,13 +95,16 @@ void SnapshotController::PendingSnapshotCompleted() {
}
void SnapshotController::DocumentAvailableInMainFrame() {
- DCHECK_EQ(PageQuality::POOR, current_page_quality_);
- // Post a delayed task to snapshot.
- task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(&SnapshotController::MaybeStartSnapshot,
- weak_ptr_factory_.GetWeakPtr(),
- PageQuality::FAIR_AND_IMPROVING),
- base::TimeDelta::FromMilliseconds(delay_after_document_available_ms_));
+ if (document_available_triggers_snapshot_) {
+ DCHECK_EQ(PageQuality::POOR, current_page_quality_);
+ // Post a delayed task to snapshot.
+ task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&SnapshotController::MaybeStartSnapshot,
+ weak_ptr_factory_.GetWeakPtr(),
+ PageQuality::FAIR_AND_IMPROVING),
+ base::TimeDelta::FromMilliseconds(delay_after_document_available_ms_));
+ }
}
void SnapshotController::DocumentOnLoadCompletedInMainFrame() {
diff --git a/chromium/components/offline_pages/core/snapshot_controller.h b/chromium/components/offline_pages/core/snapshot_controller.h
index 36e1680a6f0..bcd5ee00b1b 100644
--- a/chromium/components/offline_pages/core/snapshot_controller.h
+++ b/chromium/components/offline_pages/core/snapshot_controller.h
@@ -60,14 +60,23 @@ class SnapshotController {
virtual ~Client() {}
};
- SnapshotController(
+ // Creates a SnapshotController with document available delay = 7s,
+ // document on load delay = 1s and triggers snapshot on document available.
+ static std::unique_ptr<SnapshotController> CreateForForegroundOfflining(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ SnapshotController::Client* client);
+ // Creates a SnapshotController with document on load delay = 2s
+ // and ignores document available signal.
+ static std::unique_ptr<SnapshotController> CreateForBackgroundOfflining(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
SnapshotController::Client* client);
+
SnapshotController(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
SnapshotController::Client* client,
int64_t delay_after_document_available_ms,
- int64_t delay_after_document_on_load_completed_ms);
+ int64_t delay_after_document_on_load_completed_ms,
+ bool document_available_triggers_snapshot);
virtual ~SnapshotController();
// Resets the 'session', returning controller to initial state.
@@ -103,6 +112,7 @@ class SnapshotController {
SnapshotController::State state_;
int64_t delay_after_document_available_ms_;
int64_t delay_after_document_on_load_completed_ms_;
+ bool document_available_triggers_snapshot_;
// The expected quality of a snapshot taken at the moment this value is
// queried.
diff --git a/chromium/components/offline_pages/core/snapshot_controller_unittest.cc b/chromium/components/offline_pages/core/snapshot_controller_unittest.cc
index a57c2da897b..123437b4e48 100644
--- a/chromium/components/offline_pages/core/snapshot_controller_unittest.cc
+++ b/chromium/components/offline_pages/core/snapshot_controller_unittest.cc
@@ -53,7 +53,8 @@ SnapshotControllerTest::SnapshotControllerTest()
SnapshotControllerTest::~SnapshotControllerTest() {}
void SnapshotControllerTest::SetUp() {
- controller_.reset(new SnapshotController(task_runner_, this));
+ controller_ =
+ SnapshotController::CreateForForegroundOfflining(task_runner_, this);
snapshot_started_ = true;
}