1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/offline_pages/core/prefetch/tasks/mark_operation_done_task.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "components/offline_pages/core/offline_clock.h"
13 #include "components/offline_pages/core/offline_store_utils.h"
14 #include "components/offline_pages/core/prefetch/prefetch_dispatcher.h"
15 #include "components/offline_pages/core/prefetch/prefetch_network_request_factory.h"
16 #include "components/offline_pages/core/prefetch/store/prefetch_store.h"
17 #include "sql/database.h"
18 #include "sql/statement.h"
19 #include "sql/transaction.h"
20 
21 namespace offline_pages {
22 
23 namespace {
24 
UpdatePrefetchItemsSync(sql::Database * db,const std::string & operation_name)25 bool UpdatePrefetchItemsSync(sql::Database* db,
26                              const std::string& operation_name) {
27   static const char kSql[] =
28       "UPDATE prefetch_items SET state = ?, freshness_time = ?"
29       " WHERE state = ? AND operation_name = ?";
30 
31   sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
32   statement.BindInt(0, static_cast<int>(PrefetchItemState::RECEIVED_GCM));
33   statement.BindInt64(1, store_utils::ToDatabaseTime(OfflineTimeNow()));
34   statement.BindInt(2, static_cast<int>(PrefetchItemState::AWAITING_GCM));
35   statement.BindString(3, operation_name);
36 
37   return statement.Run();
38 }
39 
MakeStoreError()40 MarkOperationDoneTask::TaskResult MakeStoreError() {
41   return std::make_pair(MarkOperationDoneTask::StoreResult::STORE_ERROR, -1);
42 }
43 
44 // Will hold the actual SQL implementation for marking a MarkOperationDone
45 // attempt in the database.
MarkOperationCompletedOnServerSync(const std::string & operation_name,sql::Database * db)46 MarkOperationDoneTask::TaskResult MarkOperationCompletedOnServerSync(
47     const std::string& operation_name,
48     sql::Database* db) {
49   sql::Transaction transaction(db);
50   if (transaction.Begin() && UpdatePrefetchItemsSync(db, operation_name) &&
51       transaction.Commit()) {
52     return std::make_pair(MarkOperationDoneTask::StoreResult::UPDATED,
53                           db->GetLastChangeCount());
54   }
55   return MakeStoreError();
56 }
57 
58 }  // namespace
59 
MarkOperationDoneTask(PrefetchDispatcher * prefetch_dispatcher,PrefetchStore * prefetch_store,const std::string & operation_name)60 MarkOperationDoneTask::MarkOperationDoneTask(
61     PrefetchDispatcher* prefetch_dispatcher,
62     PrefetchStore* prefetch_store,
63     const std::string& operation_name)
64     : prefetch_dispatcher_(prefetch_dispatcher),
65       prefetch_store_(prefetch_store),
66       operation_name_(operation_name) {}
67 
~MarkOperationDoneTask()68 MarkOperationDoneTask::~MarkOperationDoneTask() {}
69 
Run()70 void MarkOperationDoneTask::Run() {
71   prefetch_store_->Execute(
72       base::BindOnce(&MarkOperationCompletedOnServerSync, operation_name_),
73       base::BindOnce(&MarkOperationDoneTask::Done, weak_factory_.GetWeakPtr()),
74       MakeStoreError());
75 }
76 
Done(TaskResult result)77 void MarkOperationDoneTask::Done(TaskResult result) {
78   result_ = result;
79 
80   // We need to make sure we can process any work that was created by this event
81   // so we will ensure the task is scheudled.
82   if (change_count() > 0)
83     prefetch_dispatcher_->EnsureTaskScheduled();
84 
85   TaskComplete();
86 }
87 
88 }  // namespace offline_pages
89