Make sure webrtc::VideoSource is released when WebRtcVideoTrackAdapter is destroyed.
[chromium-blink-merge.git] / components / dom_distiller / core / dom_distiller_service.cc
bloba3cbbda2474734f5f67a91be7d247d35cb565143
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 : store_(store.Pass()),
44 content_store_(new InMemoryContentStore()),
45 distiller_factory_(distiller_factory.Pass()),
46 distiller_page_factory_(distiller_page_factory.Pass()) {
49 DomDistillerService::~DomDistillerService() {
52 syncer::SyncableService* DomDistillerService::GetSyncableService() const {
53 return store_->GetSyncableService();
56 scoped_ptr<DistillerPage> DomDistillerService::CreateDefaultDistillerPage() {
57 return distiller_page_factory_->CreateDistillerPage().Pass();
60 scoped_ptr<DistillerPage>
61 DomDistillerService::CreateDefaultDistillerPageWithHandle(
62 scoped_ptr<SourcePageHandle> handle) {
63 return distiller_page_factory_->CreateDistillerPageWithHandle(handle.Pass())
64 .Pass();
67 const std::string DomDistillerService::AddToList(
68 const GURL& url,
69 scoped_ptr<DistillerPage> distiller_page,
70 const ArticleAvailableCallback& article_cb) {
71 ArticleEntry entry;
72 const bool is_already_added = store_->GetEntryByUrl(url, &entry);
74 TaskTracker* task_tracker;
75 if (is_already_added) {
76 task_tracker = GetTaskTrackerForEntry(entry);
77 if (task_tracker == NULL) {
78 // Entry is in the store but there is no task tracker. This could
79 // happen when distillation has already completed. For now just return
80 // true.
81 // TODO(shashishekhar): Change this to check if article is available,
82 // An article may not be available for a variety of reasons, e.g.
83 // distillation failure or blobs not available locally.
84 base::MessageLoop::current()->PostTask(FROM_HERE,
85 base::Bind(article_cb, true));
86 return entry.entry_id();
88 } else {
89 task_tracker = GetOrCreateTaskTrackerForUrl(url);
92 if (!article_cb.is_null()) {
93 task_tracker->AddSaveCallback(
94 base::Bind(&RunArticleAvailableCallback, article_cb));
97 if (!is_already_added) {
98 task_tracker->AddSaveCallback(base::Bind(
99 &DomDistillerService::AddDistilledPageToList, base::Unretained(this)));
100 task_tracker->StartDistiller(distiller_factory_.get(),
101 distiller_page.Pass());
102 task_tracker->StartBlobFetcher();
105 return task_tracker->GetEntryId();
108 std::vector<ArticleEntry> DomDistillerService::GetEntries() const {
109 return store_->GetEntries();
112 scoped_ptr<ArticleEntry> DomDistillerService::RemoveEntry(
113 const std::string& entry_id) {
114 scoped_ptr<ArticleEntry> entry(new ArticleEntry);
115 entry->set_entry_id(entry_id);
116 TaskTracker* task_tracker = GetTaskTrackerForEntry(*entry);
117 if (task_tracker != NULL) {
118 task_tracker->CancelSaveCallbacks();
121 if (!store_->GetEntryById(entry_id, entry.get())) {
122 return scoped_ptr<ArticleEntry>();
125 if (store_->RemoveEntry(*entry)) {
126 return entry.Pass();
128 return scoped_ptr<ArticleEntry>();
131 scoped_ptr<ViewerHandle> DomDistillerService::ViewEntry(
132 ViewRequestDelegate* delegate,
133 scoped_ptr<DistillerPage> distiller_page,
134 const std::string& entry_id) {
135 ArticleEntry entry;
136 if (!store_->GetEntryById(entry_id, &entry)) {
137 return scoped_ptr<ViewerHandle>();
140 TaskTracker* task_tracker = GetOrCreateTaskTrackerForEntry(entry);
141 scoped_ptr<ViewerHandle> viewer_handle = task_tracker->AddViewer(delegate);
142 task_tracker->StartDistiller(distiller_factory_.get(), distiller_page.Pass());
143 task_tracker->StartBlobFetcher();
145 return viewer_handle.Pass();
148 scoped_ptr<ViewerHandle> DomDistillerService::ViewUrl(
149 ViewRequestDelegate* delegate,
150 scoped_ptr<DistillerPage> distiller_page,
151 const GURL& url) {
152 if (!url.is_valid()) {
153 return scoped_ptr<ViewerHandle>();
156 TaskTracker* task_tracker = GetOrCreateTaskTrackerForUrl(url);
157 scoped_ptr<ViewerHandle> viewer_handle = task_tracker->AddViewer(delegate);
158 task_tracker->StartDistiller(distiller_factory_.get(), distiller_page.Pass());
159 task_tracker->StartBlobFetcher();
161 return viewer_handle.Pass();
164 TaskTracker* DomDistillerService::GetOrCreateTaskTrackerForUrl(
165 const GURL& url) {
166 ArticleEntry entry;
167 if (store_->GetEntryByUrl(url, &entry)) {
168 return GetOrCreateTaskTrackerForEntry(entry);
171 for (TaskList::iterator it = tasks_.begin(); it != tasks_.end(); ++it) {
172 if ((*it)->HasUrl(url)) {
173 return *it;
177 ArticleEntry skeleton_entry = CreateSkeletonEntryForUrl(url);
178 TaskTracker* task_tracker = CreateTaskTracker(skeleton_entry);
179 return task_tracker;
182 TaskTracker* DomDistillerService::GetTaskTrackerForEntry(
183 const ArticleEntry& entry) const {
184 const std::string& entry_id = entry.entry_id();
185 for (TaskList::const_iterator it = tasks_.begin(); it != tasks_.end(); ++it) {
186 if ((*it)->HasEntryId(entry_id)) {
187 return *it;
190 return NULL;
193 TaskTracker* DomDistillerService::GetOrCreateTaskTrackerForEntry(
194 const ArticleEntry& entry) {
195 TaskTracker* task_tracker = GetTaskTrackerForEntry(entry);
196 if (task_tracker == NULL) {
197 task_tracker = CreateTaskTracker(entry);
199 return task_tracker;
202 TaskTracker* DomDistillerService::CreateTaskTracker(const ArticleEntry& entry) {
203 TaskTracker::CancelCallback cancel_callback =
204 base::Bind(&DomDistillerService::CancelTask, base::Unretained(this));
205 TaskTracker* tracker =
206 new TaskTracker(entry, cancel_callback, content_store_.get());
207 tasks_.push_back(tracker);
208 return tracker;
211 void DomDistillerService::CancelTask(TaskTracker* task) {
212 TaskList::iterator it = std::find(tasks_.begin(), tasks_.end(), task);
213 if (it != tasks_.end()) {
214 tasks_.weak_erase(it);
215 base::MessageLoop::current()->DeleteSoon(FROM_HERE, task);
219 void DomDistillerService::AddDistilledPageToList(
220 const ArticleEntry& entry,
221 const DistilledArticleProto* article_proto,
222 bool distillation_succeeded) {
223 DCHECK(IsEntryValid(entry));
224 if (distillation_succeeded) {
225 DCHECK(article_proto);
226 DCHECK_GT(article_proto->pages_size(), 0);
227 store_->AddEntry(entry);
228 DCHECK_EQ(article_proto->pages_size(), entry.pages_size());
232 void DomDistillerService::AddObserver(DomDistillerObserver* observer) {
233 DCHECK(observer);
234 store_->AddObserver(observer);
237 void DomDistillerService::RemoveObserver(DomDistillerObserver* observer) {
238 DCHECK(observer);
239 store_->RemoveObserver(observer);
242 } // namespace dom_distiller