1 // Copyright 2015 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.
5 #include "components/offline_pages/offline_page_model.h"
10 #include "base/files/file_util.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/sequenced_task_runner.h"
14 #include "components/offline_pages/offline_page_item.h"
15 #include "components/offline_pages/offline_page_metadata_store.h"
18 using ArchiverResult
= offline_pages::OfflinePageArchiver::ArchiverResult
;
19 using SavePageResult
= offline_pages::OfflinePageModel::SavePageResult
;
21 namespace offline_pages
{
25 SavePageResult
ToSavePageResult(ArchiverResult archiver_result
) {
26 SavePageResult result
;
27 switch (archiver_result
) {
28 case ArchiverResult::SUCCESSFULLY_CREATED
:
29 result
= SavePageResult::SUCCESS
;
31 case ArchiverResult::ERROR_DEVICE_FULL
:
32 result
= SavePageResult::DEVICE_FULL
;
34 case ArchiverResult::ERROR_CONTENT_UNAVAILABLE
:
35 result
= SavePageResult::CONTENT_UNAVAILABLE
;
37 case ArchiverResult::ERROR_ARCHIVE_CREATION_FAILED
:
38 result
= SavePageResult::ARCHIVE_CREATION_FAILED
;
40 case ArchiverResult::ERROR_CANCELED
:
41 result
= SavePageResult::CANCELLED
;
45 result
= SavePageResult::CONTENT_UNAVAILABLE
;
52 OfflinePageModel::OfflinePageModel(
53 scoped_ptr
<OfflinePageMetadataStore
> store
,
54 const scoped_refptr
<base::SequencedTaskRunner
>& task_runner
)
55 : store_(store
.Pass()),
56 task_runner_(task_runner
),
57 weak_ptr_factory_(this) {
60 OfflinePageModel::~OfflinePageModel() {
63 void OfflinePageModel::Shutdown() {
66 void OfflinePageModel::SavePage(
68 scoped_ptr
<OfflinePageArchiver
> archiver
,
69 const SavePageCallback
& callback
) {
70 DCHECK(archiver
.get());
71 archiver
->CreateArchive(base::Bind(&OfflinePageModel::OnCreateArchiveDone
,
72 weak_ptr_factory_
.GetWeakPtr(), url
,
74 pending_archivers_
.push_back(archiver
.Pass());
77 void OfflinePageModel::DeletePage(const GURL
& url
,
78 const DeletePageCallback
& callback
) {
79 // First we have to load all entries in order to find out the file path
80 // for the page to be deleted.
81 store_
->Load(base::Bind(&OfflinePageModel::OnLoadDoneForDeletion
,
82 weak_ptr_factory_
.GetWeakPtr(), url
, callback
));
85 void OfflinePageModel::LoadAllPages(const LoadAllPagesCallback
& callback
) {
86 store_
->Load(base::Bind(&OfflinePageModel::OnLoadDone
,
87 weak_ptr_factory_
.GetWeakPtr(), callback
));
90 OfflinePageMetadataStore
* OfflinePageModel::GetStoreForTesting() {
94 void OfflinePageModel::OnCreateArchiveDone(
95 const GURL
& requested_url
,
96 const SavePageCallback
& callback
,
97 OfflinePageArchiver
* archiver
,
98 ArchiverResult archiver_result
,
100 const base::string16
& title
,
101 const base::FilePath
& file_path
,
103 if (requested_url
!= url
) {
104 DVLOG(1) << "Saved URL does not match requested URL.";
105 // TODO(fgorski): We have created an archive for a wrong URL. It should be
106 // deleted from here, once archiver has the right functionality.
107 InformSavePageDone(callback
, SavePageResult::ARCHIVE_CREATION_FAILED
);
108 DeletePendingArchiver(archiver
);
112 if (archiver_result
!= ArchiverResult::SUCCESSFULLY_CREATED
) {
113 SavePageResult result
= ToSavePageResult(archiver_result
);
114 InformSavePageDone(callback
, result
);
115 DeletePendingArchiver(archiver
);
119 OfflinePageItem
offline_page_item(url
, title
, file_path
, file_size
,
121 store_
->AddOfflinePage(
123 base::Bind(&OfflinePageModel::OnAddOfflinePageDone
,
124 weak_ptr_factory_
.GetWeakPtr(), archiver
, callback
));
127 void OfflinePageModel::OnAddOfflinePageDone(OfflinePageArchiver
* archiver
,
128 const SavePageCallback
& callback
,
130 SavePageResult result
=
131 success
? SavePageResult::SUCCESS
: SavePageResult::STORE_FAILURE
;
132 InformSavePageDone(callback
, result
);
133 DeletePendingArchiver(archiver
);
136 void OfflinePageModel::OnLoadDone(
137 const LoadAllPagesCallback
& callback
,
139 const std::vector
<OfflinePageItem
>& offline_pages
) {
140 // TODO(fgorski): Cache the values here, if we are comfortable with that
141 // model. This will require extra handling of parallel loads.
143 success
? LoadResult::SUCCESS
: LoadResult::STORE_FAILURE
;
144 callback
.Run(result
, offline_pages
);
147 void OfflinePageModel::InformSavePageDone(const SavePageCallback
& callback
,
148 SavePageResult result
) {
149 callback
.Run(result
);
152 void OfflinePageModel::DeletePendingArchiver(OfflinePageArchiver
* archiver
) {
153 pending_archivers_
.erase(std::find(
154 pending_archivers_
.begin(), pending_archivers_
.end(), archiver
));
157 void OfflinePageModel::OnLoadDoneForDeletion(
159 const DeletePageCallback
& callback
,
161 const std::vector
<OfflinePageItem
>& offline_pages
) {
163 callback
.Run(DeletePageResult::STORE_FAILURE
);
167 for (const auto& page
: offline_pages
) {
168 if (page
.url
== url
) {
169 bool* success
= new bool(false);
170 task_runner_
->PostTaskAndReply(
172 base::Bind(&OfflinePageModel::DeleteArchiverFile
,
173 weak_ptr_factory_
.GetWeakPtr(),
176 base::Bind(&OfflinePageModel::OnDeleteArchiverFileDone
,
177 weak_ptr_factory_
.GetWeakPtr(),
180 base::Owned(success
)));
185 callback
.Run(DeletePageResult::NOT_FOUND
);
188 void OfflinePageModel::DeleteArchiverFile(const base::FilePath
& file_path
,
191 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
193 *success
= base::DeleteFile(file_path
, false);
196 void OfflinePageModel::OnDeleteArchiverFileDone(
198 const DeletePageCallback
& callback
,
199 const bool* success
) {
203 callback
.Run(DeletePageResult::DEVICE_FAILURE
);
207 store_
->RemoveOfflinePage(
209 base::Bind(&OfflinePageModel::OnRemoveOfflinePageDone
,
210 weak_ptr_factory_
.GetWeakPtr(), callback
));
213 void OfflinePageModel::OnRemoveOfflinePageDone(
214 const DeletePageCallback
& callback
, bool success
) {
216 success
? DeletePageResult::SUCCESS
: DeletePageResult::STORE_FAILURE
);
219 } // namespace offline_pages