download_query.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/download/download_query.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_path.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/case_conversion.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/string_search.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string16.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_split.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/content_browser_client.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_item.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "unicode/regex.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadDangerType; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadItem; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Templatized base::Value::GetAs*(). 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> bool GetAs(const base::Value& in, T* out); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<> bool GetAs(const base::Value& in, bool* out) { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return in.GetAsBoolean(out); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<> bool GetAs(const base::Value& in, int* out) { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return in.GetAsInteger(out); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<> bool GetAs(const base::Value& in, std::string* out) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return in.GetAsString(out); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<> bool GetAs(const base::Value& in, string16* out) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return in.GetAsString(out); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The next several functions are helpers for making Callbacks that access 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DownloadItem fields. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool MatchesQuery(const string16& query, const DownloadItem& item) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (query.empty()) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(query, base::i18n::ToLower(query)); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 url_raw(UTF8ToUTF16(item.GetOriginalUrl().spec())); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::i18n::StringSearchIgnoringCaseAndAccents( 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query, url_raw, NULL, NULL)) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 url_formatted = url_raw; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item.GetBrowserContext()) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_formatted = net::FormatUrl( 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.GetOriginalUrl(), 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::GetContentClient()->browser()->GetAcceptLangs( 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.GetBrowserContext())); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::i18n::StringSearchIgnoringCaseAndAccents( 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query, url_formatted, NULL, NULL)) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 path(item.GetTargetFilePath().LossyDisplayName()); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::i18n::StringSearchIgnoringCaseAndAccents( 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query, path, NULL, NULL); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int64 GetStartTimeMsEpoch(const DownloadItem& item) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (item.GetStartTime() - base::Time::UnixEpoch()).InMilliseconds(); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(benjhayden) These timestamps don't fit in int32, and base::Value doesn't 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// support int64. Use ISO 8601 date-time strings instead. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int GetStartTime(const DownloadItem& item) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (item.GetStartTime() - base::Time::UnixEpoch()).InMilliseconds(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool GetDangerAccepted(const DownloadItem& item) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (item.GetSafetyState() == DownloadItem::DANGEROUS_BUT_VALIDATED); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static string16 GetFilename(const DownloadItem& item) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This filename will be compared with strings that could be passed in by the 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // user, who only sees LossyDisplayNames. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item.GetTargetFilePath().LossyDisplayName(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static std::string GetFilenameUTF8(const DownloadItem& item) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return UTF16ToUTF8(GetFilename(item)); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static std::string GetUrl(const DownloadItem& item) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item.GetOriginalUrl().spec(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static DownloadItem::DownloadState GetState(const DownloadItem& item) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item.GetState(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static DownloadDangerType GetDangerType(const DownloadItem& item) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item.GetDangerType(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int GetReceivedBytes(const DownloadItem& item) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item.GetReceivedBytes(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int GetTotalBytes(const DownloadItem& item) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item.GetTotalBytes(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static std::string GetMimeType(const DownloadItem& item) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item.GetMimeType(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsPaused(const DownloadItem& item) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item.IsPaused(); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ComparisonType {LT, EQ, GT}; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |item| matches the filter specified by |value|, |cmptype|, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and |accessor|. |accessor| is conceptually a function that takes a 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DownloadItem and returns one of its fields, which is then compared to 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |value|. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename ValueType> 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool FieldMatches( 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ValueType& value, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ComparisonType cmptype, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Callback<ValueType(const DownloadItem&)>& accessor, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DownloadItem& item) { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (cmptype) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LT: return accessor.Run(item) < value; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EQ: return accessor.Run(item) == value; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GT: return accessor.Run(item) > value; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper for building a Callback to FieldMatches<>(). 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename ValueType> DownloadQuery::FilterCallback BuildFilter( 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Value& value, ComparisonType cmptype, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ValueType (*accessor)(const DownloadItem&)) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ValueType cpp_value; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetAs(value, &cpp_value)) return DownloadQuery::FilterCallback(); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::Bind(&FieldMatches<ValueType>, cpp_value, cmptype, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(accessor)); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |accessor.Run(item)| matches |pattern|. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool FindRegex( 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icu::RegexPattern* pattern, 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Callback<std::string(const DownloadItem&)>& accessor, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DownloadItem& item) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icu::UnicodeString input(accessor.Run(item).c_str()); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UErrorCode status = U_ZERO_ERROR; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<icu::RegexMatcher> matcher(pattern->matcher(input, status)); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return matcher->find() == TRUE; // Ugh, VS complains bool != UBool. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper for building a Callback to FindRegex(). 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadQuery::FilterCallback BuildRegexFilter( 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Value& regex_value, 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string (*accessor)(const DownloadItem&)) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string regex_str; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetAs(regex_value, ®ex_str)) return DownloadQuery::FilterCallback(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UParseError re_err; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UErrorCode re_status = U_ZERO_ERROR; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<icu::RegexPattern> pattern(icu::RegexPattern::compile( 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icu::UnicodeString::fromUTF8(regex_str.c_str()), re_err, re_status)); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!U_SUCCESS(re_status)) return DownloadQuery::FilterCallback(); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::Bind(&FindRegex, base::Owned(pattern.release()), 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(accessor)); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a ComparisonType to indicate whether a field in |left| is less than, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// greater than or equal to the same field in |right|. 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename ValueType> 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static ComparisonType Compare( 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Callback<ValueType(const DownloadItem&)>& accessor, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DownloadItem& left, const DownloadItem& right) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ValueType left_value = accessor.Run(left); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ValueType right_value = accessor.Run(right); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (left_value > right_value) return GT; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (left_value < right_value) return LT; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(left_value, right_value); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EQ; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // anonymous namespace 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadQuery::DownloadQuery() 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : limit_(kuint32max) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadQuery::~DownloadQuery() { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AddFilter() pushes a new FilterCallback to filters_. Most FilterCallbacks are 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callbacks to FieldMatches<>(). Search() iterates over given DownloadItems, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// discarding items for which any filter returns false. A DownloadQuery may have 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// zero or more FilterCallbacks. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DownloadQuery::AddFilter(const DownloadQuery::FilterCallback& value) { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value.is_null()) return false; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filters_.push_back(value); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadQuery::AddFilter(DownloadItem::DownloadState state) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddFilter(base::Bind(&FieldMatches<DownloadItem::DownloadState>, state, EQ, 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&GetState))); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadQuery::AddFilter(DownloadDangerType danger) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddFilter(base::Bind(&FieldMatches<DownloadDangerType>, danger, EQ, 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&GetDangerType))); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DownloadQuery::AddFilter(DownloadQuery::FilterType type, 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Value& value) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_BYTES_RECEIVED: 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildFilter<int>(value, EQ, &GetReceivedBytes)); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_DANGER_ACCEPTED: 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildFilter<bool>(value, EQ, &GetDangerAccepted)); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_FILENAME: 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildFilter<string16>(value, EQ, &GetFilename)); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_FILENAME_REGEX: 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildRegexFilter(value, &GetFilenameUTF8)); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_MIME: 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildFilter<std::string>(value, EQ, &GetMimeType)); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_PAUSED: 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildFilter<bool>(value, EQ, &IsPaused)); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_QUERY: { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 query; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetAs(value, &query) && 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddFilter(base::Bind(&MatchesQuery, query)); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_STARTED_AFTER: 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildFilter<int>(value, GT, &GetStartTime)); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_STARTED_BEFORE: 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildFilter<int>(value, LT, &GetStartTime)); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_START_TIME: 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildFilter<int>(value, EQ, &GetStartTime)); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_TOTAL_BYTES: 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildFilter<int>(value, EQ, &GetTotalBytes)); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_TOTAL_BYTES_GREATER: 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildFilter<int>(value, GT, &GetTotalBytes)); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_TOTAL_BYTES_LESS: 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildFilter<int>(value, LT, &GetTotalBytes)); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_URL: 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildFilter<std::string>(value, EQ, &GetUrl)); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_URL_REGEX: 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFilter(BuildRegexFilter(value, &GetUrl)); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DownloadQuery::Matches(const DownloadItem& item) const { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (FilterCallbackVector::const_iterator filter = filters_.begin(); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter != filters_.end(); ++filter) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!filter->Run(item)) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AddSorter() creates a Sorter and pushes it onto sorters_. A Sorter is a 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// direction and a Callback to Compare<>(). After filtering, Search() makes a 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DownloadComparator functor from the sorters_ and passes the 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DownloadComparator to std::partial_sort. std::partial_sort calls the 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DownloadComparator with different pairs of DownloadItems. DownloadComparator 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// iterates over the sorters until a callback returns ComparisonType LT or GT. 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DownloadComparator returns true or false depending on that ComparisonType and 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the sorter's direction in order to indicate to std::partial_sort whether the 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// left item is after or before the right item. If all sorters return EQ, then 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DownloadComparator compares GetId. A DownloadQuery may have zero or more 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sorters, but there is one DownloadComparator per call to Search(). 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DownloadQuery::Sorter { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef base::Callback<ComparisonType( 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DownloadItem&, const DownloadItem&)> SortType; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template<typename ValueType> 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static Sorter Build(DownloadQuery::SortDirection adirection, 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ValueType (*accessor)(const DownloadItem&)) { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Sorter(adirection, base::Bind(&Compare<ValueType>, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(accessor))); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sorter(DownloadQuery::SortDirection adirection, 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SortType& asorter) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : direction(adirection), 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorter(asorter) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~Sorter() {} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadQuery::SortDirection direction; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SortType sorter; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DownloadQuery::DownloadComparator { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit DownloadComparator(const DownloadQuery::SorterVector& terms) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : terms_(terms) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if |left| sorts before |right|. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operator() (const DownloadItem* left, const DownloadItem* right); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DownloadQuery::SorterVector& terms_; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // std::sort requires this class to be copyable. 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DownloadQuery::DownloadComparator::operator() ( 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DownloadItem* left, const DownloadItem* right) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (DownloadQuery::SorterVector::const_iterator term = terms_.begin(); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) term != terms_.end(); ++term) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (term->sorter.Run(*left, *right)) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LT: return term->direction == DownloadQuery::ASCENDING; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GT: return term->direction == DownloadQuery::DESCENDING; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EQ: break; // break the switch but not the loop 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_NE(left->GetId(), right->GetId()); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return left->GetId() < right->GetId(); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadQuery::AddSorter(DownloadQuery::SortType type, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadQuery::SortDirection direction) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SORT_START_TIME: 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorters_.push_back(Sorter::Build<int64>(direction, &GetStartTimeMsEpoch)); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SORT_URL: 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorters_.push_back(Sorter::Build<std::string>(direction, &GetUrl)); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SORT_FILENAME: 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorters_.push_back(Sorter::Build<string16>(direction, &GetFilename)); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SORT_DANGER: 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorters_.push_back(Sorter::Build<DownloadDangerType>( 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) direction, &GetDangerType)); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SORT_DANGER_ACCEPTED: 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorters_.push_back(Sorter::Build<bool>(direction, &GetDangerAccepted)); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SORT_STATE: 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorters_.push_back(Sorter::Build<DownloadItem::DownloadState>( 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) direction, &GetState)); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SORT_PAUSED: 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorters_.push_back(Sorter::Build<bool>(direction, &IsPaused)); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SORT_MIME: 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorters_.push_back(Sorter::Build<std::string>(direction, &GetMimeType)); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SORT_BYTES_RECEIVED: 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorters_.push_back(Sorter::Build<int>(direction, &GetReceivedBytes)); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SORT_TOTAL_BYTES: 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorters_.push_back(Sorter::Build<int>(direction, &GetTotalBytes)); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadQuery::FinishSearch(DownloadQuery::DownloadVector* results) const { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!sorters_.empty()) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::partial_sort(results->begin(), 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results->begin() + std::min(limit_, results->size()), 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results->end(), 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadComparator(sorters_)); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (results->size() > limit_) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results->resize(limit_); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 394