blob: 14ebd11def6585c0d9e0a58cae77d40638d0e2f6 [file] [log] [blame]
// Copyright 2013 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 COMPONENTS_DOM_DISTILLER_CORE_TASK_TRACKER_H_
#define COMPONENTS_DOM_DISTILLER_CORE_TASK_TRACKER_H_
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/dom_distiller/core/article_distillation_update.h"
#include "components/dom_distiller/core/article_entry.h"
#include "components/dom_distiller/core/distiller.h"
#include "components/dom_distiller/core/proto/distilled_page.pb.h"
class GURL;
namespace dom_distiller {
class DistilledArticleProto;
class DistilledContentStore;
// A handle to a request to view a DOM distiller entry or URL. The request will
// be cancelled when the handle is destroyed.
class ViewerHandle {
public:
typedef base::Callback<void()> CancelCallback;
explicit ViewerHandle(CancelCallback callback);
~ViewerHandle();
private:
CancelCallback cancel_callback_;
DISALLOW_COPY_AND_ASSIGN(ViewerHandle);
};
// Interface for a DOM distiller entry viewer. Implement this to make a view
// request and receive the data for an entry when it becomes available.
class ViewRequestDelegate {
public:
virtual ~ViewRequestDelegate() {}
// Called when the distilled article contents are available. The
// DistilledArticleProto is owned by a TaskTracker instance and is invalidated
// when the corresponding ViewerHandle is destroyed (or when the
// DomDistillerService is destroyed).
virtual void OnArticleReady(const DistilledArticleProto* article_proto) = 0;
// Called when an article that is currently under distillation is updated.
virtual void OnArticleUpdated(ArticleDistillationUpdate article_update) = 0;
};
// A TaskTracker manages the various tasks related to viewing, saving,
// distilling, and fetching an article's distilled content.
//
// There are two sources of distilled content, a Distiller and the BlobFetcher.
// At any time, at most one of each of these will be in-progress (if one
// finishes, the other will be cancelled).
//
// There are also two consumers of that content, a view request and a save
// request. There is at most one save request (i.e. we are either adding this to
// the reading list or we aren't), and may be multiple view requests. When
// the distilled content is ready, each of these requests will be notified.
//
// A view request is cancelled by deleting the corresponding ViewerHandle. Once
// all view requests are cancelled (and the save callback has been called if
// appropriate) the cancel callback will be called.
//
// After creating a TaskTracker, a consumer of distilled content should be added
// and at least one of the sources should be started.
class TaskTracker {
public:
typedef base::Callback<void(TaskTracker*)> CancelCallback;
typedef base::Callback<
void(const ArticleEntry&, const DistilledArticleProto*, bool)>
SaveCallback;
TaskTracker(const ArticleEntry& entry,
CancelCallback callback,
DistilledContentStore* content_store);
~TaskTracker();
// |factory| will not be stored after this call.
void StartDistiller(DistillerFactory* factory,
std::unique_ptr<DistillerPage> distiller_page);
void StartBlobFetcher();
void AddSaveCallback(const SaveCallback& callback);
void CancelSaveCallbacks();
// The ViewerHandle should be destroyed before the ViewRequestDelegate.
std::unique_ptr<ViewerHandle> AddViewer(ViewRequestDelegate* delegate);
const std::string& GetEntryId() const;
bool HasEntryId(const std::string& entry_id) const;
bool HasUrl(const GURL& url) const;
private:
void OnArticleDistillationUpdated(
const ArticleDistillationUpdate& article_update);
void OnDistillerFinished(
std::unique_ptr<DistilledArticleProto> distilled_article);
void OnBlobFetched(bool success,
std::unique_ptr<DistilledArticleProto> distilled_article);
void RemoveViewer(ViewRequestDelegate* delegate);
void DistilledArticleReady(
std::unique_ptr<DistilledArticleProto> distilled_article);
// Posts a task to run DoSaveCallbacks with |distillation_succeeded|.
void ScheduleSaveCallbacks(bool distillation_succeeded);
// Runs all callbacks passing |distillation_succeeded| and clears them.
void DoSaveCallbacks(bool distillation_succeeded);
void AddDistilledContentToStore(const DistilledArticleProto& content);
void NotifyViewersAndCallbacks();
void NotifyViewer(ViewRequestDelegate* delegate);
bool IsAnySourceRunning() const;
void ContentSourceFinished();
void CancelPendingSources();
void MaybeCancel();
CancelCallback cancel_callback_;
DistilledContentStore* content_store_;
std::vector<SaveCallback> save_callbacks_;
// A ViewRequestDelegate will be added to this list when a view request is
// made and removed when the corresponding ViewerHandle is destroyed.
std::vector<ViewRequestDelegate*> viewers_;
std::unique_ptr<Distiller> distiller_;
bool blob_fetcher_running_;
ArticleEntry entry_;
std::unique_ptr<DistilledArticleProto> distilled_article_;
bool content_ready_;
bool destruction_allowed_;
// Note: This should remain the last member so it'll be destroyed and
// invalidate its weak pointers before any other members are destroyed.
base::WeakPtrFactory<TaskTracker> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(TaskTracker);
};
} // namespace dom_distiller
#endif // COMPONENTS_DOM_DISTILLER_CORE_TASK_TRACKER_H_