Add abhijeet.k@samsung.com to AUTHORS list.
[chromium-blink-merge.git] / components / dom_distiller / core / dom_distiller_service.cc
blob98be75416dace32e414996c78d006cd512655cf4
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/dom_distiller_service.h"
7 #include "base/guid.h"
8 #include "base/message_loop/message_loop.h"
9 #include "components/dom_distiller/core/distilled_content_store.h"
10 #include "components/dom_distiller/core/dom_distiller_store.h"
11 #include "components/dom_distiller/core/proto/distilled_article.pb.h"
12 #include "components/dom_distiller/core/task_tracker.h"
13 #include "url/gurl.h"
15 namespace dom_distiller {
17 namespace {
19 ArticleEntry CreateSkeletonEntryForUrl(const GURL& url) {
20 ArticleEntry skeleton;
21 skeleton.set_entry_id(base::GenerateGUID());
22 ArticleEntryPage* page = skeleton.add_pages();
23 page->set_url(url.spec());
25 DCHECK(IsEntryValid(skeleton));
26 return skeleton;
29 void RunArticleAvailableCallback(
30 const DomDistillerService::ArticleAvailableCallback& article_cb,
31 const ArticleEntry& entry,
32 const DistilledArticleProto* article_proto,
33 bool distillation_succeeded) {
34 article_cb.Run(distillation_succeeded);
37 } // namespace
39 DomDistillerService::DomDistillerService(
40 scoped_ptr<DomDistillerStoreInterface> store,
41 scoped_ptr<DistillerFactory> distiller_factory,
42 scoped_ptr<DistillerPageFactory> distiller_page_factory,
43 scoped_ptr<DistilledPagePrefs> distilled_page_prefs)
44 : store_(store.Pass()),
45 content_store_(new InMemoryContentStore(kDefaultMaxNumCachedEntries)),
46 distiller_factory_(distiller_factory.Pass()),
47 distiller_page_factory_(distiller_page_factory.Pass()),
48 distilled_page_prefs_(distilled_page_prefs.Pass()) {
51 DomDistillerService::~DomDistillerService() {
54 syncer::SyncableService* DomDistillerService::GetSyncableService() const {
55 return store_->GetSyncableService();
58 scoped_ptr<DistillerPage> DomDistillerService::CreateDefaultDistillerPage(
59 const gfx::Size& render_view_size) {
60 return distiller_page_factory_->CreateDistillerPage(render_view_size).Pass();
63 scoped_ptr<DistillerPage>
64 DomDistillerService::CreateDefaultDistillerPageWithHandle(
65 scoped_ptr<SourcePageHandle> handle) {
66 return distiller_page_factory_->CreateDistillerPageWithHandle(handle.Pass())
67 .Pass();
70 const std::string DomDistillerService::AddToList(
71 const GURL& url,
72 scoped_ptr<DistillerPage> distiller_page,
73 const ArticleAvailableCallback& article_cb) {
74 ArticleEntry entry;
75 const bool is_already_added = store_->GetEntryByUrl(url, &entry);
77 TaskTracker* task_tracker;
78 if (is_already_added) {
79 task_tracker = GetTaskTrackerForEntry(entry);
80 if (task_tracker == NULL) {
81 // Entry is in the store but there is no task tracker. This could
82 // happen when distillation has already completed. For now just return
83 // true.
84 // TODO(shashishekhar): Change this to check if article is available,
85 // An article may not be available for a variety of reasons, e.g.
86 // distillation failure or blobs not available locally.
87 base::MessageLoop::current()->PostTask(FROM_HERE,
88 base::Bind(article_cb, true));
89 return entry.entry_id();
91 } else {
92 task_tracker = GetOrCreateTaskTrackerForUrl(url);
95 if (!article_cb.is_null()) {
96 task_tracker->AddSaveCallback(
97 base::Bind(&RunArticleAvailableCallback, article_cb));
100 if (!is_already_added) {
101 task_tracker->AddSaveCallback(base::Bind(
102 &DomDistillerService::AddDistilledPageToList, base::Unretained(this)));
103 task_tracker->StartDistiller(distiller_factory_.get(),
104 distiller_page.Pass());
105 task_tracker->StartBlobFetcher();
108 return task_tracker->GetEntryId();
111 bool DomDistillerService::HasEntry(const std::string& entry_id) {
112 return store_->GetEntryById(entry_id, NULL);
115 std::string DomDistillerService::GetUrlForEntry(const std::string& entry_id) {
116 ArticleEntry entry;
117 if (store_->GetEntryById(entry_id, &entry)) {
118 return entry.pages().Get(0).url();
120 return "";
123 std::vector<ArticleEntry> DomDistillerService::GetEntries() const {
124 return store_->GetEntries();
127 scoped_ptr<ArticleEntry> DomDistillerService::RemoveEntry(
128 const std::string& entry_id) {
129 scoped_ptr<ArticleEntry> entry(new ArticleEntry);
130 entry->set_entry_id(entry_id);
131 TaskTracker* task_tracker = GetTaskTrackerForEntry(*entry);
132 if (task_tracker != NULL) {
133 task_tracker->CancelSaveCallbacks();
136 if (!store_->GetEntryById(entry_id, entry.get())) {
137 return scoped_ptr<ArticleEntry>();
140 if (store_->RemoveEntry(*entry)) {
141 return entry.Pass();
143 return scoped_ptr<ArticleEntry>();
146 scoped_ptr<ViewerHandle> DomDistillerService::ViewEntry(
147 ViewRequestDelegate* delegate,
148 scoped_ptr<DistillerPage> distiller_page,
149 const std::string& entry_id) {
150 ArticleEntry entry;
151 if (!store_->GetEntryById(entry_id, &entry)) {
152 return scoped_ptr<ViewerHandle>();
155 TaskTracker* task_tracker = GetOrCreateTaskTrackerForEntry(entry);
156 scoped_ptr<ViewerHandle> viewer_handle = task_tracker->AddViewer(delegate);
157 task_tracker->StartDistiller(distiller_factory_.get(), distiller_page.Pass());
158 task_tracker->StartBlobFetcher();
160 return viewer_handle.Pass();
163 scoped_ptr<ViewerHandle> DomDistillerService::ViewUrl(
164 ViewRequestDelegate* delegate,
165 scoped_ptr<DistillerPage> distiller_page,
166 const GURL& url) {
167 if (!url.is_valid()) {
168 return scoped_ptr<ViewerHandle>();
171 TaskTracker* task_tracker = GetOrCreateTaskTrackerForUrl(url);
172 scoped_ptr<ViewerHandle> viewer_handle = task_tracker->AddViewer(delegate);
173 task_tracker->StartDistiller(distiller_factory_.get(), distiller_page.Pass());
174 task_tracker->StartBlobFetcher();
176 return viewer_handle.Pass();
179 TaskTracker* DomDistillerService::GetOrCreateTaskTrackerForUrl(
180 const GURL& url) {
181 ArticleEntry entry;
182 if (store_->GetEntryByUrl(url, &entry)) {
183 return GetOrCreateTaskTrackerForEntry(entry);
186 for (TaskList::iterator it = tasks_.begin(); it != tasks_.end(); ++it) {
187 if ((*it)->HasUrl(url)) {
188 return *it;
192 ArticleEntry skeleton_entry = CreateSkeletonEntryForUrl(url);
193 TaskTracker* task_tracker = CreateTaskTracker(skeleton_entry);
194 return task_tracker;
197 TaskTracker* DomDistillerService::GetTaskTrackerForEntry(
198 const ArticleEntry& entry) const {
199 const std::string& entry_id = entry.entry_id();
200 for (TaskList::const_iterator it = tasks_.begin(); it != tasks_.end(); ++it) {
201 if ((*it)->HasEntryId(entry_id)) {
202 return *it;
205 return NULL;
208 TaskTracker* DomDistillerService::GetOrCreateTaskTrackerForEntry(
209 const ArticleEntry& entry) {
210 TaskTracker* task_tracker = GetTaskTrackerForEntry(entry);
211 if (task_tracker == NULL) {
212 task_tracker = CreateTaskTracker(entry);
214 return task_tracker;
217 TaskTracker* DomDistillerService::CreateTaskTracker(const ArticleEntry& entry) {
218 TaskTracker::CancelCallback cancel_callback =
219 base::Bind(&DomDistillerService::CancelTask, base::Unretained(this));
220 TaskTracker* tracker =
221 new TaskTracker(entry, cancel_callback, content_store_.get());
222 tasks_.push_back(tracker);
223 return tracker;
226 void DomDistillerService::CancelTask(TaskTracker* task) {
227 TaskList::iterator it = std::find(tasks_.begin(), tasks_.end(), task);
228 if (it != tasks_.end()) {
229 tasks_.weak_erase(it);
230 base::MessageLoop::current()->DeleteSoon(FROM_HERE, task);
234 void DomDistillerService::AddDistilledPageToList(
235 const ArticleEntry& entry,
236 const DistilledArticleProto* article_proto,
237 bool distillation_succeeded) {
238 DCHECK(IsEntryValid(entry));
239 if (distillation_succeeded) {
240 DCHECK(article_proto);
241 DCHECK_GT(article_proto->pages_size(), 0);
242 store_->AddEntry(entry);
243 DCHECK_EQ(article_proto->pages_size(), entry.pages_size());
247 void DomDistillerService::AddObserver(DomDistillerObserver* observer) {
248 DCHECK(observer);
249 store_->AddObserver(observer);
252 void DomDistillerService::RemoveObserver(DomDistillerObserver* observer) {
253 DCHECK(observer);
254 store_->RemoveObserver(observer);
257 DistilledPagePrefs* DomDistillerService::GetDistilledPagePrefs() {
258 return distilled_page_prefs_.get();
261 } // namespace dom_distiller