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

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

Issue 7192016: chrome.experimental.downloads (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: merged db_handle, id; onCreated, onErased Created 9 years, 5 months 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 "chrome/browser/download/download_query.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/memory/scoped_ptr.h"
11 #include "base/stl_util-inl.h"
12 #include "base/string16.h"
13 #include "base/string_split.h"
14 #include "base/values.h"
15 #include "unicode/regex.h"
16 #include "chrome/browser/download/download_item.h"
17
18 namespace {
19 typedef std::vector<std::string> Strings;
20 typedef std::vector<DownloadItem*> DownloadItems;
21
22 struct SimpleDownloadItem {
23 static const char STATE_IN_PROGRESS[];
24 static const char STATE_COMPLETE[];
25 static const char STATE_INTERRUPTED[];
26 static const char DANGER_SAFE[];
27 static const char DANGER_FILE[];
28 static const char DANGER_URL[];
29
30 explicit SimpleDownloadItem(DownloadItem* download)
31 : item(download) {
32 CHECK(item);
33 }
34
35 int id() const { return item->id(); }
36 std::string url() const { return item->original_url().spec(); }
37 std::string filename() const {
38 return item->GetFileNameToReportUser().value();
39 }
40 std::string danger() const { return DangerString(item->GetDangerType()); }
41 bool dangerAccepted() const {
42 return item->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED;
43 }
44 std::string state() const { return StateString(item->state()); }
45 bool paused() const { return item->is_paused(); }
46 std::string mime() const { return item->mime_type(); }
47 int startTime() const {
48 return (item->start_time() - base::Time::UnixEpoch()).InMilliseconds();
49 }
50 int endTime() const { return -1; }
51 int bytesReceived() const { return item->received_bytes(); }
52 int totalBytes() const { return item->total_bytes(); }
53 int fileSize() const { return -1; }
54 int error() const { return 0; }
55
56 DictionaryValue* ToJSON() const;
57
58 static std::string DangerString(DownloadItem::DangerType danger) {
59 switch (danger) {
60 case DownloadItem::NOT_DANGEROUS: return DANGER_SAFE;
61 case DownloadItem::DANGEROUS_FILE: return DANGER_FILE;
62 case DownloadItem::DANGEROUS_URL: return DANGER_URL;
63 case DownloadItem::DANGEROUS_TYPE_MAX:
64 default:
65 NOTREACHED();
66 return "";
67 }
68 }
69
70 static std::string StateString(DownloadItem::DownloadState state) {
71 switch (state) {
72 case DownloadItem::IN_PROGRESS: return STATE_IN_PROGRESS;
73 case DownloadItem::COMPLETE: return STATE_COMPLETE;
74 case DownloadItem::INTERRUPTED: // fall through
75 case DownloadItem::CANCELLED: return STATE_INTERRUPTED;
76 case DownloadItem::REMOVING:
77 case DownloadItem::MAX_DOWNLOAD_STATE:
78 default:
79 NOTREACHED();
80 return "";
81 }
82 }
83
84 DownloadItem* item;
85 // Allow copy and assign.
86 };
87
88 typedef std::vector<SimpleDownloadItem*> SimpleItems;
89
90 // Functor passed to std::sort to sort SimpleDownloadItems.
91 class DownloadComparator {
92 public:
93 DownloadComparator(std::string* error_msg, Strings* order_terms)
94 : error_msg_(error_msg),
95 order_terms_(order_terms) {
96 }
97
98 bool operator() (const SimpleDownloadItem* left,
99 const SimpleDownloadItem* right);
100 private:
101 static const char kDash = '-';
102
103 template <typename FieldType> bool CompareField(
104 std::string term,
105 std::string field,
106 FieldType left,
107 FieldType right,
108 bool* matched_term,
109 bool* cmp) const;
110
111 std::string* error_msg_;
112 Strings* order_terms_;
113 // std::sort requires this class to be copyable.
114 };
115
116 using download_util::DownloadQuery;
117
118 class DownloadSearch : DownloadQuery {
119 public:
120 DownloadSearch(const DownloadQuery& query, DownloadItems* items);
121 ~DownloadSearch() {}
122
123 bool IsWellFormed(std::string* error_msg);
124 bool Matches(const SimpleDownloadItem& item);
125
126 SimpleItems::const_iterator begin() const { return simple_items_.begin(); }
127 SimpleItems::const_iterator end() const { return simple_items_.end(); }
128
129 bool ReachedLimit(int num_results) {
130 return has_limit_ && (num_results >= limit_);
131 }
132
133 private:
134 std::string error_msg_;
135 Strings order_terms_;
136 SimpleItems simple_items_;
137 STLElementDeleter<SimpleItems> delete_simple_items_;
138 Strings query_terms_;
139 scoped_ptr<icu::RegexPattern> filename_pattern_;
140 scoped_ptr<icu::RegexPattern> url_pattern_;
141 DownloadComparator comparator_;
142
143 DISALLOW_COPY_AND_ASSIGN(DownloadSearch);
144 };
145
146 DictionaryValue* SimpleDownloadItem::ToJSON() const {
147 DictionaryValue* json = new DictionaryValue();
148 #define FIELD(name, type) \
149 json->Set ## type(#name, name());
150 #include "chrome/browser/download/simple_download_item_fields.h"
151 #undef FIELD
152 return json;
153 }
154
155 bool DownloadComparator::operator() (
156 const SimpleDownloadItem* left,
157 const SimpleDownloadItem* right) {
158 CHECK(left);
159 CHECK(right);
160 Strings::iterator order_term,
161 last_order_term = order_terms_->end();
162 for (order_term = order_terms_->begin();
163 order_term != last_order_term; ++order_term) {
164 bool matched_term = false;
165 bool cmp = false;
166 #define Integer int
167 #define Boolean bool
168 #define String std::string
169 #define FIELD(name, type) \
170 if (CompareField<type>(*order_term, #name, left->name(), right->name(), \
171 &matched_term, &cmp)) return cmp; \
172 if (matched_term) continue;
173 #include "chrome/browser/download/simple_download_item_fields.h"
174 #undef FIELD
175 #undef String
176 #undef Boolean
177 #undef Integer
178 *error_msg_ += " " + *order_term;
179 order_terms_->erase(order_term);
180 }
181 CHECK_NE(left->id(), right->id());
182 return left->id() < right->id();
183 }
184
185 // Return true and set cmp if matched_term and left != right.
186 template <typename FieldType>
187 bool DownloadComparator::CompareField(
188 std::string term,
189 std::string field,
190 FieldType left,
191 FieldType right,
192 bool* matched_term,
193 bool* cmp) const {
194 bool diff = (left != right);
195 if (term == field) {
196 *matched_term = true;
197 if (diff) *cmp = (left < right);
198 }
199 if (term == kDash + field) {
200 *matched_term = true;
201 if (diff) *cmp = (left > right);
202 }
203 return diff && *matched_term;
204 }
205
206 // NOTE These string constants must match those in
207 // chrome/common/extensions/api/extension_api.json
208 const char SimpleDownloadItem::STATE_IN_PROGRESS[] = "in progress";
209 const char SimpleDownloadItem::STATE_COMPLETE[] = "complete";
210 const char SimpleDownloadItem::STATE_INTERRUPTED[] = "interrupted";
211 const char SimpleDownloadItem::DANGER_SAFE[] = "safe";
212 const char SimpleDownloadItem::DANGER_FILE[] = "file";
213 const char SimpleDownloadItem::DANGER_URL[] = "url";
214
215 DownloadSearch::DownloadSearch(
216 const DownloadQuery& query, DownloadItems* items)
217 : DownloadQuery(query),
218 delete_simple_items_(&simple_items_),
219 comparator_(&error_msg_, &order_terms_) {
220 if (has_query_) {
221 base::SplitString(query_, ' ', &query_terms_); // TODO handle quopri
222 }
223 if (has_filenameRegex_) {
224 UParseError regex_error; // TODO do these need to outlive the pattern?
225 UErrorCode regex_status = U_ZERO_ERROR;
226 filename_pattern_.reset(icu::RegexPattern::compile(
227 icu::UnicodeString::fromUTF8(filenameRegex_),
228 regex_error, regex_status));
229 if (!U_SUCCESS(regex_status)) {
230 error_msg_ = "bad filenameRegex";
231 return;
232 }
233 }
234 if (has_urlRegex_) {
235 UParseError regex_error;
236 UErrorCode regex_status = U_ZERO_ERROR;
237 url_pattern_.reset(icu::RegexPattern::compile(
238 icu::UnicodeString::fromUTF8(urlRegex_),
239 regex_error, regex_status));
240 if (!U_SUCCESS(regex_status)) {
241 error_msg_ = "bad urlRegex";
242 return;
243 }
244 }
245 for (DownloadItems::const_iterator iter = items->begin();
246 iter != items->end(); ++iter) {
247 if (*iter != NULL) {
248 if (!filter_func_.is_null() && !filter_func_.Run(**iter)) continue;
249 simple_items_.push_back(new SimpleDownloadItem(*iter));
250 }
251 }
252 if (has_orderBy_ && (1 < simple_items_.size())) {
253 base::SplitString(orderBy_, ' ', &order_terms_);
254 std::sort(simple_items_.begin(), simple_items_.end(), comparator_);
255 }
256 }
257
258 bool DownloadSearch::IsWellFormed(std::string* error_msg) {
259 if (error_msg != NULL) *error_msg = error_msg_;
260 return error_msg_.empty();
261 }
262
263 bool DownloadSearch::Matches(const SimpleDownloadItem& item) {
264 #define FIELD(name, unused_type) \
265 if (has_ ## name ## _ && (item.name() != name ## _)) return false;
266 #include "chrome/browser/download/simple_download_item_fields.h"
267 #undef FIELD
268 if (has_state_enum_ && (item.item->state() != state_enum_)) return false;
269 if (has_danger_enum_ && (item.item->GetDangerType() != danger_enum_))
270 return false;
271 if (has_startedBefore_ && (item.startTime() > startedBefore_)) return false;
272 if (has_startedAfter_ && (item.startTime() < startedAfter_)) return false;
273 if (has_endedBefore_ && (item.endTime() > endedBefore_)) return false;
274 if (has_endedAfter_ && (item.endTime() < endedAfter_)) return false;
275 if (has_totalBytesGreater_ && (item.totalBytes() < totalBytesGreater_))
276 return false;
277 if (has_totalBytesLess_ && (item.totalBytes() > totalBytesLess_))
278 return false;
279 Strings::const_iterator query_term_iter,
280 query_term_end = query_terms_.end();
281 for (query_term_iter = query_terms_.begin();
282 query_term_iter != query_term_end; ++query_term_iter) {
283 std::string query_term = *query_term_iter;
284 if ((std::string::npos == item.filename().find(query_term)) &&
285 (std::string::npos == item.url().find(query_term))) {
286 return false;
287 }
288 }
289 if (filename_pattern_.get() != NULL) {
290 UErrorCode status = U_ZERO_ERROR;
291 scoped_ptr<icu::RegexMatcher> filename_matcher(filename_pattern_->matcher(
292 icu::UnicodeString::fromUTF8(item.filename()), status));
293 if (U_FAILURE(status)) {
294 return false;
295 }
296 if (!filename_matcher->find(0, status)) return false;
297 }
298 if (url_pattern_.get() != NULL) {
299 UErrorCode status = U_ZERO_ERROR;
300 scoped_ptr<icu::RegexMatcher> url_matcher(url_pattern_->matcher(
301 icu::UnicodeString::fromUTF8(item.url()), status));
302 if (U_FAILURE(status)) {
303 return false;
304 }
305 if (!url_matcher->find(0, status)) return false;
306 }
307 return true;
308 }
309 } // anonymous namespace
310
311 namespace download_util {
312
313 DownloadQuery::DownloadQuery() {
314 has_state_enum_ = false;
315 has_danger_enum_ = false;
316 #define FIELD(name, type) \
317 has_ ## name ## _ = false;
318 #include "chrome/browser/download/download_query_fields.h"
319 #undef FIELD
320 }
321
322 DownloadQuery::DownloadQuery(const DictionaryValue& json) {
323 has_state_enum_ = false;
324 has_danger_enum_ = false;
325 #define FIELD(name, type) \
326 has_ ## name ## _ = json.Get ## type(#name, &name ## _);
327 #include "chrome/browser/download/download_query_fields.h"
328 #undef FIELD
329 }
330
331 DownloadQuery& DownloadQuery::filter_func(DownloadQuery::FilterType func) {
332 filter_func_ = func;
333 return *this;
334 }
335
336 DownloadQuery& DownloadQuery::state_enum(
337 DownloadItem::DownloadState stateenum) {
338 has_state_enum_ = true;
339 state_enum_ = stateenum;
340 return *this;
341 }
342
343 DownloadQuery& DownloadQuery::danger_enum(DownloadItem::DangerType dangerenum) {
344 has_danger_enum_ = true;
345 danger_enum_ = dangerenum;
346 return *this;
347 }
348
349 bool DownloadQuery::Search(
350 std::vector<DownloadItem*>* items,
351 std::string* error_msg,
352 ListValue* results) const {
353 DownloadSearch search(*this, items);
354 items->clear();
355 if (!search.IsWellFormed(error_msg)) return false;
356 for (SimpleItems::const_iterator iter = search.begin();
357 iter != search.end(); ++iter) {
358 if (!search.Matches(**iter)) continue;
359 items->push_back((*iter)->item);
360 if (results != NULL) results->Append((*iter)->ToJSON());
361 if (search.ReachedLimit(items->size())) break;
362 }
363 return true;
364 }
365 } // namespace download_util
366
OLDNEW
« no previous file with comments | « chrome/browser/download/download_query.h ('k') | chrome/browser/download/download_query_fields.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698