Revert 254567 "don't create SkDevice directly, use SkBitmap or (..."
[chromium-blink-merge.git] / components / dom_distiller / core / task_tracker.cc
blob1afd4825ac75dc96777a41aafa80f4f2e9cc39da
1 // Copyright 2013 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/dom_distiller/core/task_tracker.h"
7 #include "base/message_loop/message_loop.h"
8 #include "components/dom_distiller/core/proto/distilled_article.pb.h"
9 #include "components/dom_distiller/core/proto/distilled_page.pb.h"
11 namespace dom_distiller {
13 ViewerHandle::ViewerHandle(CancelCallback callback)
14 : cancel_callback_(callback) {}
16 ViewerHandle::~ViewerHandle() {
17 if (!cancel_callback_.is_null()) {
18 cancel_callback_.Run();
22 TaskTracker::TaskTracker(const ArticleEntry& entry, CancelCallback callback)
23 : cancel_callback_(callback),
24 entry_(entry),
25 distilled_article_(),
26 distillation_complete_(false),
27 weak_ptr_factory_(this) {}
29 TaskTracker::~TaskTracker() { DCHECK(viewers_.empty()); }
31 void TaskTracker::StartDistiller(DistillerFactory* factory) {
32 if (distiller_) {
33 return;
35 if (entry_.pages_size() == 0) {
36 return;
39 GURL url(entry_.pages(0).url());
40 DCHECK(url.is_valid());
42 distiller_ = factory->CreateDistiller();
43 distiller_->DistillPage(url,
44 base::Bind(&TaskTracker::OnDistilledDataReady,
45 weak_ptr_factory_.GetWeakPtr()));
48 void TaskTracker::StartBlobFetcher() {
49 // TODO(cjhopman): There needs to be some local storage for the distilled
50 // blob. When that happens, this should start some task to fetch the blob for
51 // |entry_| and asynchronously notify |this| when it is done.
54 void TaskTracker::AddSaveCallback(const SaveCallback& callback) {
55 DCHECK(!callback.is_null());
56 save_callbacks_.push_back(callback);
57 if (distillation_complete_) {
58 // Distillation for this task has already completed, and so it can be
59 // immediately saved.
60 ScheduleSaveCallbacks(true);
64 scoped_ptr<ViewerHandle> TaskTracker::AddViewer(ViewRequestDelegate* delegate) {
65 viewers_.push_back(delegate);
66 if (distillation_complete_) {
67 // Distillation for this task has already completed, and so the delegate can
68 // be immediately told of the result.
69 base::MessageLoop::current()->PostTask(
70 FROM_HERE,
71 base::Bind(&TaskTracker::NotifyViewer,
72 weak_ptr_factory_.GetWeakPtr(),
73 delegate));
75 return scoped_ptr<ViewerHandle>(new ViewerHandle(base::Bind(
76 &TaskTracker::RemoveViewer, weak_ptr_factory_.GetWeakPtr(), delegate)));
79 const std::string& TaskTracker::GetEntryId() const { return entry_.entry_id(); }
81 bool TaskTracker::HasEntryId(const std::string& entry_id) const {
82 return entry_.entry_id() == entry_id;
85 bool TaskTracker::HasUrl(const GURL& url) const {
86 for (int i = 0; i < entry_.pages_size(); ++i) {
87 if (entry_.pages(i).url() == url.spec()) {
88 return true;
91 return false;
94 void TaskTracker::RemoveViewer(ViewRequestDelegate* delegate) {
95 viewers_.erase(std::remove(viewers_.begin(), viewers_.end(), delegate));
96 if (viewers_.empty()) {
97 MaybeCancel();
101 void TaskTracker::MaybeCancel() {
102 if (!save_callbacks_.empty() || !viewers_.empty()) {
103 // There's still work to be done.
104 return;
107 // The cancel callback should not delete this. To ensure that it doesn't, grab
108 // a weak pointer and check that it has not been invalidated.
109 base::WeakPtr<TaskTracker> self(weak_ptr_factory_.GetWeakPtr());
110 cancel_callback_.Run(this);
111 DCHECK(self);
114 void TaskTracker::CancelSaveCallbacks() { ScheduleSaveCallbacks(false); }
116 void TaskTracker::ScheduleSaveCallbacks(bool distillation_succeeded) {
117 base::MessageLoop::current()->PostTask(
118 FROM_HERE,
119 base::Bind(&TaskTracker::DoSaveCallbacks,
120 weak_ptr_factory_.GetWeakPtr(),
121 distillation_succeeded));
124 void TaskTracker::DoSaveCallbacks(bool distillation_succeeded) {
125 if (!save_callbacks_.empty()) {
126 for (size_t i = 0; i < save_callbacks_.size(); ++i) {
127 DCHECK(!save_callbacks_[i].is_null());
128 save_callbacks_[i].Run(
129 entry_, distilled_article_.get(), distillation_succeeded);
132 save_callbacks_.clear();
133 MaybeCancel();
137 void TaskTracker::NotifyViewer(ViewRequestDelegate* delegate) {
138 DCHECK(distillation_complete_);
139 delegate->OnArticleReady(distilled_article_.get());
142 void TaskTracker::OnDistilledDataReady(
143 scoped_ptr<DistilledArticleProto> distilled_article) {
144 distilled_article_ = distilled_article.Pass();
145 bool distillation_successful = false;
146 if (distilled_article_->pages_size() > 0) {
147 distillation_successful = true;
148 entry_.set_title(distilled_article_->title());
149 // Reset the pages.
150 entry_.clear_pages();
151 for (int i = 0; i < distilled_article_->pages_size(); ++i) {
152 sync_pb::ArticlePage* page = entry_.add_pages();
153 page->set_url(distilled_article_->pages(i).url());
157 distillation_complete_ = true;
159 for (size_t i = 0; i < viewers_.size(); ++i) {
160 NotifyViewer(viewers_[i]);
163 // Already inside a callback run SaveCallbacks directly.
164 DoSaveCallbacks(distillation_successful);
167 } // namespace dom_distiller