blob: ace7380f7a79d7e8bebf4fbb112d4649171db813 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_READING_LIST_URL_DOWNLOADER_H_
#define IOS_CHROME_BROWSER_READING_LIST_URL_DOWNLOADER_H_
#include <queue>
#include "base/callback.h"
#include "base/task/cancelable_task_tracker.h"
#include "ios/chrome/browser/dom_distiller/distiller_viewer.h"
class PrefService;
class GURL;
namespace base {
class FilePath;
}
namespace dom_distiller {
class DomDistillerService;
}
// This class downloads and deletes offline versions of URLs using DOM distiller
// to fetch the page and simplify it. Only one item is downloaded or deleted at
// a time using a queue of tasks that are handled sequentially. Items (page +
// images) are saved to individual folders within an offline folder, using md5
// hashing to create unique file names. When a deletion is requested, all
// previous downloads for that URL are cancelled as they would be deleted.
class URLDownloader {
friend class MockURLDownloader;
public:
// And enum indicating different download outcomes.
enum SuccessState {
DOWNLOAD_SUCCESS,
DOWNLOAD_EXISTS,
ERROR_RETRY,
ERROR_PERMANENT
};
// A completion callback that takes a GURL and a bool indicating the
// outcome and returns void.
using SuccessCompletion = base::Callback<void(const GURL&, bool)>;
// A download completion callback that takes, in order, the GURL that was
// downloaded, a SuccessState indicating the outcome of the download, the
// path to the downloaded page (relative to |OfflineRootDirectoryPath()|, and
// the title of the url, and returns void.
// The path to downloaded file and title should not be used in case of
// failure.
using DownloadCompletion = base::Callback<void(const GURL&,
SuccessState,
const base::FilePath&,
const std::string&)>;
// Create a URL downloader with completion callbacks for downloads and
// deletions. The completion callbacks will be called with the original url
// and a boolean indicating success. For downloads, if distillation was
// successful, it will also include the distilled url and extracted title.
URLDownloader(dom_distiller::DomDistillerService* distiller_service,
PrefService* prefs,
base::FilePath chrome_profile_path,
const DownloadCompletion& download_completion,
const SuccessCompletion& delete_completion);
virtual ~URLDownloader();
// Asynchronously download an offline version of the URL.
void DownloadOfflineURL(const GURL& url);
// Asynchronously remove the offline version of the URL if it exists.
void RemoveOfflineURL(const GURL& url);
private:
enum TaskType { DELETE, DOWNLOAD };
using Task = std::pair<TaskType, GURL>;
// Calls callback with true if an offline file exists for this URL.
void OfflineURLExists(const GURL& url, base::Callback<void(bool)> callback);
// Handles the next task in the queue, if no task is currently being handled.
void HandleNextTask();
// Callback for completed (or failed) download, handles calling
// downloadCompletion and starting the next task.
void DownloadCompletionHandler(const GURL& url,
const std::string& title,
SuccessState success);
// Callback for completed (or failed) deletion, handles calling
// deleteCompletion and starting the next task.
void DeleteCompletionHandler(const GURL& url, bool success);
// Creates the offline directory for |url|. Returns true if successful or if
// the directory already exists.
bool CreateOfflineURLDirectory(const GURL& url);
// Saves the |data| for image at |imageURL| to disk, for main URL |url|;
// puts path of saved file in |path| and returns whether save was successful.
bool SaveImage(const GURL& url,
const GURL& imageURL,
const std::string& data,
std::string* image_name);
// Saves images in |images| array to disk and replaces references in |html| to
// local path. Returns updated html.
std::string SaveAndReplaceImagesInHTML(
const GURL& url,
const std::string& html,
const std::vector<dom_distiller::DistillerViewerInterface::ImageInfo>&
images);
// Saves |html| to disk in the correct location for |url|; returns success.
bool SaveHTMLForURL(std::string html, const GURL& url);
// Downloads |url|, depending on |offlineURLExists| state.
virtual void DownloadURL(GURL url, bool offlineURLExists);
// Saves distilled html to disk, including saving images and main file.
SuccessState SaveDistilledHTML(
const GURL& url,
const std::vector<dom_distiller::DistillerViewerInterface::ImageInfo>&
images,
const std::string& html);
// Callback for distillation completion.
void DistillerCallback(
const GURL& pageURL,
const std::string& html,
const std::vector<dom_distiller::DistillerViewerInterface::ImageInfo>&
images,
const std::string& title);
dom_distiller::DomDistillerService* distiller_service_;
PrefService* pref_service_;
const DownloadCompletion download_completion_;
const SuccessCompletion delete_completion_;
std::deque<Task> tasks_;
bool working_;
base::FilePath base_directory_;
std::unique_ptr<dom_distiller::DistillerViewerInterface> distiller_;
base::CancelableTaskTracker task_tracker_;
DISALLOW_COPY_AND_ASSIGN(URLDownloader);
};
#endif // IOS_CHROME_BROWSER_READING_LIST_URL_DOWNLOADER_H_