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 3// found in the LICENSE file. 4 5#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_QUERY_H_ 6#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_QUERY_H_ 7 8#include <map> 9#include <string> 10#include <vector> 11 12#include "base/callback_forward.h" 13#include "content/public/browser/download_item.h" 14 15namespace base { 16class Value; 17} 18 19// Filter and sort a vector of DownloadItem*s. 20// 21// The following example copies from |all_items| to |results| those 22// DownloadItem*s whose start time is 0 and whose id is odd, sorts primarily by 23// bytes received ascending and secondarily by url descending, and limits the 24// results to 20 items. Any number of filters or sorters is allowed. If all 25// sorters compare two DownloadItems equivalently, then they are sorted by their 26// id ascending. 27// 28// DownloadQuery query; 29// scoped_ptr<base::Value> start_time(base::Balue::CreateIntegerValue(0)); 30// CHECK(query.AddFilter(FILTER_START_TIME, *start_time.get())); 31// bool FilterOutOddDownloads(const DownloadItem& item) { 32// return 0 == (item.GetId() % 2); 33// } 34// CHECK(query.AddFilter(base::Bind(&FilterOutOddDownloads))); 35// query.AddSorter(SORT_BYTES_RECEIVED, ASCENDING); 36// query.AddSorter(SORT_URL, DESCENDING); 37// query.Limit(20); 38// DownloadVector all_items, results; 39// query.Search(all_items.begin(), all_items.end(), &results); 40class DownloadQuery { 41 public: 42 typedef std::vector<content::DownloadItem*> DownloadVector; 43 44 // FilterCallback is a Callback that takes a DownloadItem and returns true if 45 // the item matches the filter and false otherwise. 46 // query.AddFilter(base::Bind(&YourFilterFunction)); 47 typedef base::Callback<bool(const content::DownloadItem&)> FilterCallback; 48 49 // All times are ISO 8601 strings. 50 enum FilterType { 51 FILTER_BYTES_RECEIVED, // int 52 FILTER_DANGER_ACCEPTED, // bool 53 FILTER_ENDED_AFTER, // string 54 FILTER_ENDED_BEFORE, // string 55 FILTER_END_TIME, // string 56 FILTER_EXISTS, // bool 57 FILTER_FILENAME, // string 58 FILTER_FILENAME_REGEX, // string 59 FILTER_MIME, // string 60 FILTER_PAUSED, // bool 61 FILTER_QUERY, // vector<base::string16> 62 FILTER_STARTED_AFTER, // string 63 FILTER_STARTED_BEFORE, // string 64 FILTER_START_TIME, // string 65 FILTER_TOTAL_BYTES, // int 66 FILTER_TOTAL_BYTES_GREATER, // int 67 FILTER_TOTAL_BYTES_LESS, // int 68 FILTER_URL, // string 69 FILTER_URL_REGEX, // string 70 }; 71 72 enum SortType { 73 SORT_BYTES_RECEIVED, 74 SORT_DANGER, 75 SORT_DANGER_ACCEPTED, 76 SORT_END_TIME, 77 SORT_EXISTS, 78 SORT_FILENAME, 79 SORT_MIME, 80 SORT_PAUSED, 81 SORT_START_TIME, 82 SORT_STATE, 83 SORT_TOTAL_BYTES, 84 SORT_URL, 85 }; 86 87 enum SortDirection { 88 ASCENDING, 89 DESCENDING, 90 }; 91 92 DownloadQuery(); 93 ~DownloadQuery(); 94 95 // Adds a new filter of type |type| with value |value| and returns true if 96 // |type| is valid and |value| is the correct Value-type and well-formed. 97 // Returns false if |type| is invalid or |value| is the incorrect Value-type 98 // or malformed. Search() will filter out all DownloadItem*s that do not 99 // match all filters. Multiple instances of the same FilterType are allowed, 100 // so you can pass two regexes to AddFilter(URL_REGEX,...) in order to 101 // Search() for items whose url matches both regexes. You can also pass two 102 // different DownloadStates to AddFilter(), which will cause Search() to 103 // filter out all items. 104 bool AddFilter(const FilterCallback& filter); 105 bool AddFilter(FilterType type, const base::Value& value); 106 void AddFilter(content::DownloadDangerType danger); 107 void AddFilter(content::DownloadItem::DownloadState state); 108 109 // Adds a new sorter of type |type| with direction |direction|. After 110 // filtering DownloadItem*s, Search() will sort the results primarily by the 111 // sorter from the first call to Sort(), secondarily by the sorter from the 112 // second call to Sort(), and so on. For example, if the InputIterator passed 113 // to Search() yields four DownloadItems {id:0, error:0, start_time:0}, {id:1, 114 // error:0, start_time:1}, {id:2, error:1, start_time:0}, {id:3, error:1, 115 // start_time:1}, and Sort is called twice, once with (SORT_ERROR, ASCENDING) 116 // then with (SORT_START_TIME, DESCENDING), then Search() will return items 117 // ordered 1,0,3,2. 118 void AddSorter(SortType type, SortDirection direction); 119 120 // Limit the size of search results to |limit|. 121 void Limit(size_t limit) { limit_ = limit; } 122 123 // Filters DownloadItem*s from |iter| to |last| into |results|, sorts 124 // |results|, and limits the size of |results|. |results| must be non-NULL. 125 template <typename InputIterator> 126 void Search(InputIterator iter, const InputIterator last, 127 DownloadVector* results) const { 128 results->clear(); 129 for (; iter != last; ++iter) { 130 if (Matches(**iter)) results->push_back(*iter); 131 } 132 FinishSearch(results); 133 } 134 135 private: 136 struct Sorter; 137 class DownloadComparator; 138 typedef std::vector<FilterCallback> FilterCallbackVector; 139 typedef std::vector<Sorter> SorterVector; 140 141 bool FilterRegex(const std::string& regex_str, 142 const base::Callback<std::string( 143 const content::DownloadItem&)>& accessor); 144 bool Matches(const content::DownloadItem& item) const; 145 void FinishSearch(DownloadVector* results) const; 146 147 FilterCallbackVector filters_; 148 SorterVector sorters_; 149 size_t limit_; 150 151 DISALLOW_COPY_AND_ASSIGN(DownloadQuery); 152}; 153 154#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_QUERY_H_ 155