• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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.
4 
5 #include "components/dom_distiller/core/distilled_content_store.h"
6 
7 #include "base/message_loop/message_loop.h"
8 
9 namespace dom_distiller {
10 
InMemoryContentStore(const int max_num_entries)11 InMemoryContentStore::InMemoryContentStore(const int max_num_entries)
12     : cache_(max_num_entries, CacheDeletor(this)) {
13 }
14 
~InMemoryContentStore()15 InMemoryContentStore::~InMemoryContentStore() {
16   // Clear the cache before destruction to ensure the CacheDeletor is not called
17   // after InMemoryContentStore has been destroyed.
18   cache_.Clear();
19 }
20 
SaveContent(const ArticleEntry & entry,const DistilledArticleProto & proto,InMemoryContentStore::SaveCallback callback)21 void InMemoryContentStore::SaveContent(
22     const ArticleEntry& entry,
23     const DistilledArticleProto& proto,
24     InMemoryContentStore::SaveCallback callback) {
25   InjectContent(entry, proto);
26   if (!callback.is_null()) {
27     base::MessageLoop::current()->PostTask(FROM_HERE,
28                                            base::Bind(callback, true));
29   }
30 }
31 
LoadContent(const ArticleEntry & entry,InMemoryContentStore::LoadCallback callback)32 void InMemoryContentStore::LoadContent(
33     const ArticleEntry& entry,
34     InMemoryContentStore::LoadCallback callback) {
35   if (callback.is_null())
36     return;
37 
38   ContentMap::const_iterator it = cache_.Get(entry.entry_id());
39   bool success = it != cache_.end();
40   if (!success) {
41     // Could not find article by entry ID, so try looking it up by URL.
42     for (int i = 0; i < entry.pages_size(); ++i) {
43       UrlMap::const_iterator url_it = url_to_id_.find(entry.pages(i).url());
44       if (url_it != url_to_id_.end()) {
45         it = cache_.Get(url_it->second);
46         success = it != cache_.end();
47         if (success) {
48           break;
49         }
50       }
51     }
52   }
53   scoped_ptr<DistilledArticleProto> distilled_article;
54   if (success) {
55     distilled_article.reset(new DistilledArticleProto(it->second));
56   } else {
57     distilled_article.reset(new DistilledArticleProto());
58   }
59   base::MessageLoop::current()->PostTask(
60       FROM_HERE,
61       base::Bind(callback, success, base::Passed(&distilled_article)));
62 }
63 
InjectContent(const ArticleEntry & entry,const DistilledArticleProto & proto)64 void InMemoryContentStore::InjectContent(const ArticleEntry& entry,
65                                          const DistilledArticleProto& proto) {
66   cache_.Put(entry.entry_id(), proto);
67   AddUrlToIdMapping(entry, proto);
68 }
69 
AddUrlToIdMapping(const ArticleEntry & entry,const DistilledArticleProto & proto)70 void InMemoryContentStore::AddUrlToIdMapping(
71     const ArticleEntry& entry,
72     const DistilledArticleProto& proto) {
73   for (int i = 0; i < proto.pages_size(); i++) {
74     const DistilledPageProto& page = proto.pages(i);
75     if (page.has_url()) {
76       url_to_id_[page.url()] = entry.entry_id();
77     }
78   }
79 }
80 
EraseUrlToIdMapping(const DistilledArticleProto & proto)81 void InMemoryContentStore::EraseUrlToIdMapping(
82     const DistilledArticleProto& proto) {
83   for (int i = 0; i < proto.pages_size(); i++) {
84     const DistilledPageProto& page = proto.pages(i);
85     if (page.has_url()) {
86       url_to_id_.erase(page.url());
87     }
88   }
89 }
90 
CacheDeletor(InMemoryContentStore * store)91 InMemoryContentStore::CacheDeletor::CacheDeletor(InMemoryContentStore* store)
92     : store_(store) {
93 }
94 
~CacheDeletor()95 InMemoryContentStore::CacheDeletor::~CacheDeletor() {
96 }
97 
operator ()(const DistilledArticleProto & proto)98 void InMemoryContentStore::CacheDeletor::operator()(
99     const DistilledArticleProto& proto) {
100   // When InMemoryContentStore is deleted, the |store_| pointer becomes invalid,
101   // but since the ContentMap is cleared in the InMemoryContentStore destructor,
102   // this should never be called after the destructor.
103   store_->EraseUrlToIdMapping(proto);
104 }
105 
106 }  // namespace dom_distiller
107