OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/download/download_query.h" | 5 #include "chrome/browser/download/download_query.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <limits> | 10 #include <limits> |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 return false; | 63 return false; |
64 } | 64 } |
65 out->push_back(element); | 65 out->push_back(element); |
66 } | 66 } |
67 return true; | 67 return true; |
68 } | 68 } |
69 | 69 |
70 // The next several functions are helpers for making Callbacks that access | 70 // The next several functions are helpers for making Callbacks that access |
71 // DownloadItem fields. | 71 // DownloadItem fields. |
72 | 72 |
73 static int64_t GetStartTimeMsEpoch(const DownloadItem& item) { | 73 int64_t GetStartTimeMsEpoch(const DownloadItem& item) { |
74 return (item.GetStartTime() - base::Time::UnixEpoch()).InMilliseconds(); | 74 return (item.GetStartTime() - base::Time::UnixEpoch()).InMilliseconds(); |
75 } | 75 } |
76 | 76 |
77 static int64_t GetEndTimeMsEpoch(const DownloadItem& item) { | 77 int64_t GetEndTimeMsEpoch(const DownloadItem& item) { |
78 return (item.GetEndTime() - base::Time::UnixEpoch()).InMilliseconds(); | 78 return (item.GetEndTime() - base::Time::UnixEpoch()).InMilliseconds(); |
79 } | 79 } |
80 | 80 |
81 std::string TimeToISO8601(const base::Time& t) { | 81 std::string TimeToISO8601(const base::Time& t) { |
82 base::Time::Exploded exploded; | 82 base::Time::Exploded exploded; |
83 t.UTCExplode(&exploded); | 83 t.UTCExplode(&exploded); |
84 return base::StringPrintf( | 84 return base::StringPrintf( |
85 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month, | 85 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month, |
86 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, | 86 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, |
87 exploded.millisecond); | 87 exploded.millisecond); |
88 } | 88 } |
89 | 89 |
90 static std::string GetStartTime(const DownloadItem& item) { | 90 std::string GetStartTime(const DownloadItem& item) { |
91 return TimeToISO8601(item.GetStartTime()); | 91 return TimeToISO8601(item.GetStartTime()); |
92 } | 92 } |
93 | 93 |
94 static std::string GetEndTime(const DownloadItem& item) { | 94 std::string GetEndTime(const DownloadItem& item) { |
95 return TimeToISO8601(item.GetEndTime()); | 95 return TimeToISO8601(item.GetEndTime()); |
96 } | 96 } |
97 | 97 |
98 static bool GetDangerAccepted(const DownloadItem& item) { | 98 bool GetDangerAccepted(const DownloadItem& item) { |
99 return (item.GetDangerType() == | 99 return (item.GetDangerType() == |
100 content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED); | 100 content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED); |
101 } | 101 } |
102 | 102 |
103 static bool GetExists(const DownloadItem& item) { | 103 bool GetExists(const DownloadItem& item) { |
104 return !item.GetFileExternallyRemoved(); | 104 return !item.GetFileExternallyRemoved(); |
105 } | 105 } |
106 | 106 |
107 static base::string16 GetFilename(const DownloadItem& item) { | 107 base::string16 GetFilename(const DownloadItem& item) { |
108 // This filename will be compared with strings that could be passed in by the | 108 // This filename will be compared with strings that could be passed in by the |
109 // user, who only sees LossyDisplayNames. | 109 // user, who only sees LossyDisplayNames. |
110 return item.GetTargetFilePath().LossyDisplayName(); | 110 return item.GetTargetFilePath().LossyDisplayName(); |
111 } | 111 } |
112 | 112 |
113 static std::string GetFilenameUTF8(const DownloadItem& item) { | 113 std::string GetFilenameUTF8(const DownloadItem& item) { |
114 return base::UTF16ToUTF8(GetFilename(item)); | 114 return base::UTF16ToUTF8(GetFilename(item)); |
115 } | 115 } |
116 | 116 |
117 static std::string GetUrl(const DownloadItem& item) { | 117 std::string GetOriginalUrl(const DownloadItem& item) { |
118 return item.GetOriginalUrl().spec(); | 118 return item.GetOriginalUrl().spec(); |
119 } | 119 } |
120 | 120 |
121 static DownloadItem::DownloadState GetState(const DownloadItem& item) { | 121 std::string GetUrl(const DownloadItem& item) { |
| 122 return item.GetURL().spec(); |
| 123 } |
| 124 |
| 125 DownloadItem::DownloadState GetState(const DownloadItem& item) { |
122 return item.GetState(); | 126 return item.GetState(); |
123 } | 127 } |
124 | 128 |
125 static DownloadDangerType GetDangerType(const DownloadItem& item) { | 129 DownloadDangerType GetDangerType(const DownloadItem& item) { |
126 return item.GetDangerType(); | 130 return item.GetDangerType(); |
127 } | 131 } |
128 | 132 |
129 static double GetReceivedBytes(const DownloadItem& item) { | 133 double GetReceivedBytes(const DownloadItem& item) { |
130 return item.GetReceivedBytes(); | 134 return item.GetReceivedBytes(); |
131 } | 135 } |
132 | 136 |
133 static double GetTotalBytes(const DownloadItem& item) { | 137 double GetTotalBytes(const DownloadItem& item) { |
134 return item.GetTotalBytes(); | 138 return item.GetTotalBytes(); |
135 } | 139 } |
136 | 140 |
137 static std::string GetMimeType(const DownloadItem& item) { | 141 std::string GetMimeType(const DownloadItem& item) { |
138 return item.GetMimeType(); | 142 return item.GetMimeType(); |
139 } | 143 } |
140 | 144 |
141 static bool IsPaused(const DownloadItem& item) { | 145 bool IsPaused(const DownloadItem& item) { |
142 return item.IsPaused(); | 146 return item.IsPaused(); |
143 } | 147 } |
144 | 148 |
145 enum ComparisonType {LT, EQ, GT}; | 149 enum ComparisonType {LT, EQ, GT}; |
146 | 150 |
147 // Returns true if |item| matches the filter specified by |value|, |cmptype|, | 151 // Returns true if |item| matches the filter specified by |value|, |cmptype|, |
148 // and |accessor|. |accessor| is conceptually a function that takes a | 152 // and |accessor|. |accessor| is conceptually a function that takes a |
149 // DownloadItem and returns one of its fields, which is then compared to | 153 // DownloadItem and returns one of its fields, which is then compared to |
150 // |value|. | 154 // |value|. |
151 template<typename ValueType> | 155 template<typename ValueType> |
152 static bool FieldMatches( | 156 bool FieldMatches( |
153 const ValueType& value, | 157 const ValueType& value, |
154 ComparisonType cmptype, | 158 ComparisonType cmptype, |
155 const base::Callback<ValueType(const DownloadItem&)>& accessor, | 159 const base::Callback<ValueType(const DownloadItem&)>& accessor, |
156 const DownloadItem& item) { | 160 const DownloadItem& item) { |
157 switch (cmptype) { | 161 switch (cmptype) { |
158 case LT: return accessor.Run(item) < value; | 162 case LT: return accessor.Run(item) < value; |
159 case EQ: return accessor.Run(item) == value; | 163 case EQ: return accessor.Run(item) == value; |
160 case GT: return accessor.Run(item) > value; | 164 case GT: return accessor.Run(item) > value; |
161 } | 165 } |
162 NOTREACHED(); | 166 NOTREACHED(); |
163 return false; | 167 return false; |
164 } | 168 } |
165 | 169 |
166 // Helper for building a Callback to FieldMatches<>(). | 170 // Helper for building a Callback to FieldMatches<>(). |
167 template <typename ValueType> DownloadQuery::FilterCallback BuildFilter( | 171 template <typename ValueType> DownloadQuery::FilterCallback BuildFilter( |
168 const base::Value& value, ComparisonType cmptype, | 172 const base::Value& value, ComparisonType cmptype, |
169 ValueType (*accessor)(const DownloadItem&)) { | 173 ValueType (*accessor)(const DownloadItem&)) { |
170 ValueType cpp_value; | 174 ValueType cpp_value; |
171 if (!GetAs(value, &cpp_value)) return DownloadQuery::FilterCallback(); | 175 if (!GetAs(value, &cpp_value)) return DownloadQuery::FilterCallback(); |
172 return base::Bind(&FieldMatches<ValueType>, cpp_value, cmptype, | 176 return base::Bind(&FieldMatches<ValueType>, cpp_value, cmptype, |
173 base::Bind(accessor)); | 177 base::Bind(accessor)); |
174 } | 178 } |
175 | 179 |
176 // Returns true if |accessor.Run(item)| matches |pattern|. | 180 // Returns true if |accessor.Run(item)| matches |pattern|. |
177 static bool FindRegex( | 181 bool FindRegex( |
178 RE2* pattern, | 182 RE2* pattern, |
179 const base::Callback<std::string(const DownloadItem&)>& accessor, | 183 const base::Callback<std::string(const DownloadItem&)>& accessor, |
180 const DownloadItem& item) { | 184 const DownloadItem& item) { |
181 return RE2::PartialMatch(accessor.Run(item), *pattern); | 185 return RE2::PartialMatch(accessor.Run(item), *pattern); |
182 } | 186 } |
183 | 187 |
184 // Helper for building a Callback to FindRegex(). | 188 // Helper for building a Callback to FindRegex(). |
185 DownloadQuery::FilterCallback BuildRegexFilter( | 189 DownloadQuery::FilterCallback BuildRegexFilter( |
186 const base::Value& regex_value, | 190 const base::Value& regex_value, |
187 std::string (*accessor)(const DownloadItem&)) { | 191 std::string (*accessor)(const DownloadItem&)) { |
188 std::string regex_str; | 192 std::string regex_str; |
189 if (!GetAs(regex_value, ®ex_str)) return DownloadQuery::FilterCallback(); | 193 if (!GetAs(regex_value, ®ex_str)) return DownloadQuery::FilterCallback(); |
190 std::unique_ptr<RE2> pattern(new RE2(regex_str)); | 194 std::unique_ptr<RE2> pattern(new RE2(regex_str)); |
191 if (!pattern->ok()) return DownloadQuery::FilterCallback(); | 195 if (!pattern->ok()) return DownloadQuery::FilterCallback(); |
192 return base::Bind(&FindRegex, base::Owned(pattern.release()), | 196 return base::Bind(&FindRegex, base::Owned(pattern.release()), |
193 base::Bind(accessor)); | 197 base::Bind(accessor)); |
194 } | 198 } |
195 | 199 |
196 // Returns a ComparisonType to indicate whether a field in |left| is less than, | 200 // Returns a ComparisonType to indicate whether a field in |left| is less than, |
197 // greater than or equal to the same field in |right|. | 201 // greater than or equal to the same field in |right|. |
198 template<typename ValueType> | 202 template<typename ValueType> |
199 static ComparisonType Compare( | 203 ComparisonType Compare( |
200 const base::Callback<ValueType(const DownloadItem&)>& accessor, | 204 const base::Callback<ValueType(const DownloadItem&)>& accessor, |
201 const DownloadItem& left, const DownloadItem& right) { | 205 const DownloadItem& left, const DownloadItem& right) { |
202 ValueType left_value = accessor.Run(left); | 206 ValueType left_value = accessor.Run(left); |
203 ValueType right_value = accessor.Run(right); | 207 ValueType right_value = accessor.Run(right); |
204 if (left_value > right_value) return GT; | 208 if (left_value > right_value) return GT; |
205 if (left_value < right_value) return LT; | 209 if (left_value < right_value) return LT; |
206 DCHECK_EQ(left_value, right_value); | 210 DCHECK_EQ(left_value, right_value); |
207 return EQ; | 211 return EQ; |
208 } | 212 } |
209 | 213 |
210 } // anonymous namespace | 214 } // anonymous namespace |
211 | 215 |
212 // static | 216 // static |
213 bool DownloadQuery::MatchesQuery(const std::vector<base::string16>& query_terms, | 217 bool DownloadQuery::MatchesQuery(const std::vector<base::string16>& query_terms, |
214 const DownloadItem& item) { | 218 const DownloadItem& item) { |
215 if (query_terms.empty()) | 219 if (query_terms.empty()) |
216 return true; | 220 return true; |
217 | 221 |
218 base::string16 url_raw(base::UTF8ToUTF16(item.GetOriginalUrl().spec())); | 222 base::string16 original_url_raw( |
219 base::string16 url_formatted = url_raw; | 223 base::UTF8ToUTF16(item.GetOriginalUrl().spec())); |
220 if (item.GetBrowserContext()) | 224 base::string16 url_raw(base::UTF8ToUTF16(item.GetURL().spec())); |
221 url_formatted = url_formatter::FormatUrl(item.GetOriginalUrl()); | 225 // Try to also match query with above URLs formatted in user display friendly |
| 226 // way. This will unescape characters (including spaces) and trim all extra |
| 227 // data (like username and password) from raw url so that for example raw url |
| 228 // "http://some.server.org/example%20download/file.zip" will be matched with |
| 229 // search term "example download". |
| 230 base::string16 original_url_formatted( |
| 231 url_formatter::FormatUrl(item.GetOriginalUrl())); |
| 232 base::string16 url_formatted(url_formatter::FormatUrl(item.GetURL())); |
222 base::string16 path(item.GetTargetFilePath().LossyDisplayName()); | 233 base::string16 path(item.GetTargetFilePath().LossyDisplayName()); |
223 | 234 |
224 for (std::vector<base::string16>::const_iterator it = query_terms.begin(); | 235 for (std::vector<base::string16>::const_iterator it = query_terms.begin(); |
225 it != query_terms.end(); ++it) { | 236 it != query_terms.end(); ++it) { |
226 base::string16 term = base::i18n::ToLower(*it); | 237 base::string16 term = base::i18n::ToLower(*it); |
227 if (!base::i18n::StringSearchIgnoringCaseAndAccents( | 238 if (!base::i18n::StringSearchIgnoringCaseAndAccents( |
| 239 term, original_url_raw, NULL, NULL) && |
| 240 !base::i18n::StringSearchIgnoringCaseAndAccents( |
| 241 term, original_url_formatted, NULL, NULL) && |
| 242 !base::i18n::StringSearchIgnoringCaseAndAccents( |
228 term, url_raw, NULL, NULL) && | 243 term, url_raw, NULL, NULL) && |
229 !base::i18n::StringSearchIgnoringCaseAndAccents( | 244 !base::i18n::StringSearchIgnoringCaseAndAccents( |
230 term, url_formatted, NULL, NULL) && | 245 term, url_formatted, NULL, NULL) && |
231 !base::i18n::StringSearchIgnoringCaseAndAccents( | 246 !base::i18n::StringSearchIgnoringCaseAndAccents( |
232 term, path, NULL, NULL)) { | 247 term, path, NULL, NULL)) { |
233 return false; | 248 return false; |
234 } | 249 } |
235 } | 250 } |
236 return true; | 251 return true; |
237 } | 252 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 case FILTER_STARTED_BEFORE: | 309 case FILTER_STARTED_BEFORE: |
295 return AddFilter(BuildFilter<std::string>(value, LT, &GetStartTime)); | 310 return AddFilter(BuildFilter<std::string>(value, LT, &GetStartTime)); |
296 case FILTER_START_TIME: | 311 case FILTER_START_TIME: |
297 return AddFilter(BuildFilter<std::string>(value, EQ, &GetStartTime)); | 312 return AddFilter(BuildFilter<std::string>(value, EQ, &GetStartTime)); |
298 case FILTER_TOTAL_BYTES: | 313 case FILTER_TOTAL_BYTES: |
299 return AddFilter(BuildFilter<double>(value, EQ, &GetTotalBytes)); | 314 return AddFilter(BuildFilter<double>(value, EQ, &GetTotalBytes)); |
300 case FILTER_TOTAL_BYTES_GREATER: | 315 case FILTER_TOTAL_BYTES_GREATER: |
301 return AddFilter(BuildFilter<double>(value, GT, &GetTotalBytes)); | 316 return AddFilter(BuildFilter<double>(value, GT, &GetTotalBytes)); |
302 case FILTER_TOTAL_BYTES_LESS: | 317 case FILTER_TOTAL_BYTES_LESS: |
303 return AddFilter(BuildFilter<double>(value, LT, &GetTotalBytes)); | 318 return AddFilter(BuildFilter<double>(value, LT, &GetTotalBytes)); |
| 319 case FILTER_ORIGINAL_URL: |
| 320 return AddFilter(BuildFilter<std::string>(value, EQ, &GetOriginalUrl)); |
| 321 case FILTER_ORIGINAL_URL_REGEX: |
| 322 return AddFilter(BuildRegexFilter(value, &GetOriginalUrl)); |
304 case FILTER_URL: | 323 case FILTER_URL: |
305 return AddFilter(BuildFilter<std::string>(value, EQ, &GetUrl)); | 324 return AddFilter(BuildFilter<std::string>(value, EQ, &GetUrl)); |
306 case FILTER_URL_REGEX: | 325 case FILTER_URL_REGEX: |
307 return AddFilter(BuildRegexFilter(value, &GetUrl)); | 326 return AddFilter(BuildRegexFilter(value, &GetUrl)); |
308 } | 327 } |
309 return false; | 328 return false; |
310 } | 329 } |
311 | 330 |
312 bool DownloadQuery::Matches(const DownloadItem& item) const { | 331 bool DownloadQuery::Matches(const DownloadItem& item) const { |
313 for (FilterCallbackVector::const_iterator filter = filters_.begin(); | 332 for (FilterCallbackVector::const_iterator filter = filters_.begin(); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 void DownloadQuery::AddSorter(DownloadQuery::SortType type, | 403 void DownloadQuery::AddSorter(DownloadQuery::SortType type, |
385 DownloadQuery::SortDirection direction) { | 404 DownloadQuery::SortDirection direction) { |
386 switch (type) { | 405 switch (type) { |
387 case SORT_END_TIME: | 406 case SORT_END_TIME: |
388 sorters_.push_back(Sorter::Build<int64_t>(direction, &GetEndTimeMsEpoch)); | 407 sorters_.push_back(Sorter::Build<int64_t>(direction, &GetEndTimeMsEpoch)); |
389 break; | 408 break; |
390 case SORT_START_TIME: | 409 case SORT_START_TIME: |
391 sorters_.push_back( | 410 sorters_.push_back( |
392 Sorter::Build<int64_t>(direction, &GetStartTimeMsEpoch)); | 411 Sorter::Build<int64_t>(direction, &GetStartTimeMsEpoch)); |
393 break; | 412 break; |
| 413 case SORT_ORIGINAL_URL: |
| 414 sorters_.push_back( |
| 415 Sorter::Build<std::string>(direction, &GetOriginalUrl)); |
| 416 break; |
394 case SORT_URL: | 417 case SORT_URL: |
395 sorters_.push_back(Sorter::Build<std::string>(direction, &GetUrl)); | 418 sorters_.push_back(Sorter::Build<std::string>(direction, &GetUrl)); |
396 break; | 419 break; |
397 case SORT_FILENAME: | 420 case SORT_FILENAME: |
398 sorters_.push_back( | 421 sorters_.push_back( |
399 Sorter::Build<base::string16>(direction, &GetFilename)); | 422 Sorter::Build<base::string16>(direction, &GetFilename)); |
400 break; | 423 break; |
401 case SORT_DANGER: | 424 case SORT_DANGER: |
402 sorters_.push_back(Sorter::Build<DownloadDangerType>( | 425 sorters_.push_back(Sorter::Build<DownloadDangerType>( |
403 direction, &GetDangerType)); | 426 direction, &GetDangerType)); |
(...skipping 27 matching lines...) Expand all Loading... |
431 if (!sorters_.empty()) { | 454 if (!sorters_.empty()) { |
432 std::partial_sort(results->begin(), | 455 std::partial_sort(results->begin(), |
433 results->begin() + std::min(limit_, results->size()), | 456 results->begin() + std::min(limit_, results->size()), |
434 results->end(), | 457 results->end(), |
435 DownloadComparator(sorters_)); | 458 DownloadComparator(sorters_)); |
436 } | 459 } |
437 | 460 |
438 if (results->size() > limit_) | 461 if (results->size() > limit_) |
439 results->resize(limit_); | 462 results->resize(limit_); |
440 } | 463 } |
OLD | NEW |