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

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