Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(303)

Side by Side Diff: content/browser/download/download_query.cc

Issue 7825035: Implement chrome.experimental.downloads.search() (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: rewrite Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "content/browser/download/download_query.h"
6
7 #include <algorithm>
8 #include <set>
9 #include <string>
10 #include <vector>
11
12 #include "base/memory/scoped_ptr.h"
13 #include "base/stl_util.h"
14 #include "base/string16.h"
15 #include "base/string_split.h"
16 #include "base/utf_string_conversions.h"
17 #include "unicode/regex.h"
18 #include "content/browser/download/download_item.h"
19
20 namespace download_util {
21
22 // The FieldInterfaces allow us to keep the templateyness out of the header.
23
24 // Filter fields can be used to filter DownloadVector out of the result set.
25 class DownloadQuery::FilterFieldInterface {
26 public:
27 virtual ~FilterFieldInterface() {}
28 virtual bool Valid() = 0;
29 virtual bool Matches(const DownloadItem& item) const = 0;
30 };
31
32 // Sort fields are used by DownloadComparator to sort DownloadVector.
33 class SortFieldInterface {
34 public:
35 virtual ~SortFieldInterface() {}
36
37 virtual DownloadQuery::SortFieldDirection direction() const = 0;
38
39 // Return 0 when left's field is equivalent to right's field, -1 when left <
40 // right, or 1 when left > right.
41 virtual int Compare(const DownloadItem& left,
42 const DownloadItem& right) const = 0;
43 };
44
45 namespace {
46
47 typedef std::vector<SortFieldInterface*> SortFieldVector;
48
49 // Functor passed to std::sort to sort DownloadVector.
50 class DownloadComparator {
51 public:
52 DownloadComparator(const SortFieldVector& terms)
53 : terms_(terms) {
54 }
55
56 // Returns true if |left| sorts before |right|.
57 bool operator() (const DownloadItem* left, const DownloadItem* right);
58
59 private:
60 const SortFieldVector& terms_;
61
62 // std::sort requires this class to be copyable.
63 };
64
65 bool DownloadComparator::operator() (const DownloadItem* left,
66 const DownloadItem* right) {
67 for (SortFieldVector::const_iterator term = terms_.begin();
68 term != terms_.end(); ++term) {
69 int comparison = (*term)->Compare(*left, *right);
70 if (comparison != 0)
71 return ((*term)->direction() == DownloadQuery::ASCENDING) == (comparison < 0);
72 }
73 if (left->id() != right->id())
74 return left->id() < right->id();
75 CHECK_NE(left->db_handle(), right->db_handle());
76 return left->db_handle() < right->db_handle();
77 }
78
79 static int get_start_time(const DownloadItem& item) {
80 return (item.start_time() - base::Time::UnixEpoch()).InMilliseconds();
81 }
82
83 static int get_end_time(const DownloadItem& item) {
84 return 0; // TODO(benjhayden): endTime
85 }
86
87 static bool get_danger_accepted(const DownloadItem& item) {
88 return (item.safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED);
89 }
90
91 static string16 get_filename(const DownloadItem& item) {
92 return item.full_path().LossyDisplayName();
93 }
94
95 template <typename ValueType_>
96 class FilterField : public DownloadQuery::FilterFieldInterface {
97 public:
98 typedef ValueType_ ValueType;
99 explicit FilterField(const ValueType& value) : value_(value) {}
100 virtual ~FilterField() {}
101 virtual bool Valid() OVERRIDE { return true; }
102
103 protected:
104 const ValueType& value() const { return value_; }
105
106 private:
107 ValueType value_;
108 };
109
110 template <typename StringType>
111 std::string ToUTF8(const StringType& s);
112
113 template<> std::string ToUTF8(const std::string& s) {
114 return s;
115 }
116
117 template<> std::string ToUTF8(const string16& s) {
118 return UTF16ToUTF8(s);
119 }
120
121 template <typename StringType>
122 class FilterFieldRegex : public FilterField<StringType> {
123 public:
124 explicit FilterFieldRegex(const StringType& value)
125 : FilterField<StringType>(value) {
126 }
127 virtual ~FilterFieldRegex() {}
128 using FilterField<StringType>::value;
129 virtual bool Valid() OVERRIDE {
130 UParseError re_err;
131 UErrorCode re_status = U_ZERO_ERROR;
132 pattern_.reset(icu::RegexPattern::compile(
133 icu::UnicodeString::fromUTF8(ToUTF8(value())),
134 re_err, re_status));
135 return U_SUCCESS(re_status);
136 }
137
138 protected:
139 bool RegexMatches(const StringType& text) const {
140 UErrorCode status = U_ZERO_ERROR;
141 scoped_ptr<icu::RegexMatcher> matcher(pattern_->matcher(
142 icu::UnicodeString::fromUTF8(ToUTF8(text)), status));
143 return U_SUCCESS(status) &&
144 matcher->find(0, status);
145 }
146
147 private:
148 scoped_ptr<icu::RegexPattern> pattern_;
149 };
150
151 template <typename ValueType>
152 class SortField : public SortFieldInterface {
153 public:
154 explicit SortField(DownloadQuery::SortFieldDirection direction)
155 : direction_(direction) {
156 }
157 virtual ~SortField() {}
158
159 virtual DownloadQuery::SortFieldDirection direction() const {
160 return direction_;
161 }
162
163 virtual ValueType GetField(const DownloadItem& item) const = 0;
164
165 virtual int Compare(const DownloadItem& left,
166 const DownloadItem& right) const OVERRIDE {
167 ValueType left_value = GetField(left), right_value = GetField(right);
168 if (left_value > right_value) return 1;
169 if (left_value < right_value) return -1;
170 if (left_value == right_value) return 0;
171 NOTREACHED();
172 return 0;
173 }
174
175 private:
176 DownloadQuery::SortFieldDirection direction_;
177 };
178
179 #define LAMBDA(__name, __base, __method, __expr, __ctor_arg_type, __ctor_arg) ({ \
180 class __name : public __base { \
181 public: \
182 explicit __name(__ctor_arg_type x) : __base(x) {} \
183 virtual __method(const DownloadItem& item) const OVERRIDE { \
184 return __expr; \
185 } \
186 }; \
187 new __name(__ctor_arg); \
188 })
189
190 SortFieldInterface* GetSortField(DownloadQuery::SortFieldName name,
191 DownloadQuery::SortFieldDirection direction) {
192 switch (name) {
193 #define SORT_FIELD(__name, __type, __expr) \
194 case DownloadQuery::SORT_FIELD_ ## __name: return LAMBDA( \
195 SortField ## __name, SortField<__type>, __type GetField, __expr, \
196 DownloadQuery::SortFieldDirection, direction)
197 SORT_FIELD(START_TIME, int, get_start_time(item));
198 SORT_FIELD(URL, std::string, item.original_url().spec());
199 SORT_FIELD(FILENAME, string16, get_filename(item));
200 SORT_FIELD(DANGER, DownloadItem::DangerType, item.GetDangerType());
201 SORT_FIELD(DANGER_ACCEPTED, bool, get_danger_accepted(item));
202 SORT_FIELD(STATE, DownloadItem::DownloadState, item.state());
203 SORT_FIELD(PAUSED, bool, item.is_paused());
204 SORT_FIELD(MIME, std::string, item.mime_type());
205 SORT_FIELD(END_TIME, int, get_end_time(item));
206 SORT_FIELD(BYTES_RECEIVED, int, item.received_bytes());
207 SORT_FIELD(TOTAL_BYTES, int, item.total_bytes());
208 SORT_FIELD(FILE_SIZE, int, 0); // TODO
209 SORT_FIELD(ERROR, int, 0); // TODO
210 #undef SORT_FIELD
211 default: return NULL;
212 }
213 }
214
215 } // anonymous namespace
216
217 DownloadQuery::DownloadQuery()
218 : limit_(kuint32max) {
219 }
220
221 DownloadQuery::~DownloadQuery() {
222 STLDeleteElements(&filter_fields_);
223 }
224
225 bool DownloadQuery::AddFilter(FilterFieldInterface* field) {
226 if (!field->Valid()) {
227 delete field;
228 return false;
229 }
230 filter_fields_.push_back(field);
231 return true;
232 }
233
234 #define START_FILTER_FIELDS(__type) \
235 template<> bool DownloadQuery::Filter(DownloadQuery::FilterFieldName name, \
236 const __type& _value) { \
237 typedef __type ValueType; \
238 switch (static_cast<int>(name)) {
239 #define FILTER_FIELD(__name, __expr) \
240 case FILTER_FIELD_ ## __name: return AddFilter( \
241 LAMBDA(FilterField ## __name, FilterField<ValueType>, bool Matches, \
242 __expr, const ValueType&, _value));
243 #define FILTER_FIELD_REGEX(__name, __expr) \
244 case FILTER_FIELD_ ## __name ## _REGEX: return AddFilter(LAMBDA( \
245 FilterField ## __name ## _REGEX, FilterFieldRegex<ValueType>, \
246 bool Matches, RegexMatches(__expr), const ValueType&, _value));
247 #define END_FILTER_FIELDS \
248 } \
249 return false; \
250 }
251
252 START_FILTER_FIELDS(int)
253 FILTER_FIELD(START_TIME, get_start_time(item))
254 FILTER_FIELD(END_TIME, get_end_time(item))
255 FILTER_FIELD(BYTES_RECEIVED, item.received_bytes())
256 FILTER_FIELD(TOTAL_BYTES, item.total_bytes())
257 FILTER_FIELD(STARTED_BEFORE, get_start_time(item) < value())
258 FILTER_FIELD(STARTED_AFTER, get_start_time(item) > value())
259 FILTER_FIELD(ENDED_BEFORE, get_end_time(item) < value())
260 FILTER_FIELD(ENDED_AFTER, get_end_time(item) > value())
261 FILTER_FIELD(TOTAL_BYTES_GREATER, item.total_bytes() > value())
262 FILTER_FIELD(TOTAL_BYTES_LESS, item.total_bytes() < value())
263 FILTER_FIELD(FILE_SIZE_GREATER, false) // TODO
264 FILTER_FIELD(FILE_SIZE_LESS, false) // TODO
265 FILTER_FIELD(FILE_SIZE, 0) // TODO
266 FILTER_FIELD(ERROR, 0) // TODO
267 END_FILTER_FIELDS
268
269 START_FILTER_FIELDS(bool)
270 FILTER_FIELD(DANGER_ACCEPTED, get_danger_accepted(item))
271 FILTER_FIELD(PAUSED, item.is_paused())
272 END_FILTER_FIELDS
273
274 START_FILTER_FIELDS(std::string)
275 FILTER_FIELD(URL, item.original_url().spec() == value())
276 FILTER_FIELD_REGEX(URL, item.original_url().spec())
277 FILTER_FIELD(MIME, item.mime_type() == value())
278 END_FILTER_FIELDS
279
280 START_FILTER_FIELDS(string16)
281 FILTER_FIELD(QUERY, item.MatchesQuery(value()))
282 FILTER_FIELD(FILENAME, get_filename(item) == value())
283 FILTER_FIELD_REGEX(FILENAME, get_filename(item))
284 END_FILTER_FIELDS
285
286 START_FILTER_FIELDS(base::Callback<bool(const DownloadItem& item)>)
287 FILTER_FIELD(FILTER, value().Run(item))
288 END_FILTER_FIELDS
289
290 START_FILTER_FIELDS(DownloadItem::DangerType)
291 FILTER_FIELD(DANGER, item.GetDangerType() == value())
292 END_FILTER_FIELDS
293
294 START_FILTER_FIELDS(DownloadItem::DownloadState)
295 FILTER_FIELD(STATE, item.state() == value())
296 END_FILTER_FIELDS
297
298 #undef START_FILTER_FIELDS
299 #undef FILTER_FIELD
300 #undef END_FILTER_FIELDS
301
302 void DownloadQuery::Sort(DownloadQuery::SortFieldName name, DownloadQuery::SortF ieldDirection direction) {
303 order_by_fields_.push_back(OrderTerm(name, direction));
304 }
305
306 bool DownloadQuery::Matches(const DownloadItem& item) const {
307 for (FilterFieldVector::const_iterator filter_field = filter_fields_.begin();
308 filter_field != filter_fields_.end(); ++filter_field) {
309 if (!(*filter_field)->Matches(item))
310 return false;
311 }
312 return true;
313 }
314
315 template <typename InputIterator>
316 void DownloadQuery::Search(InputIterator iter, const InputIterator last,
317 DownloadQuery::DownloadVector* results) const {
318 results->clear();
319 for (; iter != last; ++iter) {
320 if (Matches(**iter))
321 results->push_back(*iter);
322 }
323 if (!order_by_fields_.empty()) {
324 SortFieldVector order_terms;
325 for (OrderTermVector::const_iterator iter = order_by_fields_.begin();
326 iter != order_by_fields_.end(); ++iter) {
327 SortFieldInterface* sort_field = GetSortField(iter->name, iter->direction) ;
328 if (sort_field)
329 order_terms.push_back(sort_field);
330 }
331 std::partial_sort(results->begin(),
332 results->begin() + std::min(limit_, results->size()),
333 results->end(),
334 DownloadComparator(order_terms));
335 STLDeleteElements(&order_terms);
336 }
337 if (results->size() > limit_)
338 results->resize(limit_);
339 }
340
341 template void DownloadQuery::Search(
342 std::set<DownloadItem*>::const_iterator iter,
343 const std::set<DownloadItem*>::const_iterator last,
344 DownloadQuery::DownloadVector* results) const;
345 template void DownloadQuery::Search(
346 std::vector<DownloadItem*>::const_iterator iter,
347 const std::vector<DownloadItem*>::const_iterator last,
348 DownloadQuery::DownloadVector* results) const;
349 template void DownloadQuery::Search(
350 std::vector<DownloadItem*>::iterator iter,
351 const std::vector<DownloadItem*>::iterator last,
352 DownloadQuery::DownloadVector* results) const;
353
354 } // namespace download_util
355
OLDNEW
« no previous file with comments | « content/browser/download/download_query.h ('k') | content/browser/download/download_query_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698